Skip to content

feat: V2 parse & extract SDK support (client.v2) - #72

Merged
tian-lan-landing merged 13 commits into
mainfrom
feat/v2-parse-extract
Jul 9, 2026
Merged

feat: V2 parse & extract SDK support (client.v2)#72
tian-lan-landing merged 13 commits into
mainfrom
feat/v2-parse-extract

Conversation

@tian-lan-landing

@tian-lan-landing tian-lan-landing commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Ports ade-python's V2 work (ade-python#105, plan #95) to the TS SDK, synced to the updated AIDE Gateway openapi.json, and validated end-to-end against a live staging gateway. Additive client.v2 sub-client; V1 untouched, package stays 2.x.

Surface

  • client.v2.parse / extract — sync (206 partial success, saveTo, 504 → V2SyncTimeoutError)
  • client.v2.parseJobs / extractJobs / workflowJobs{create, get, list, wait} → one normalized Job
  • client.v2.workflow — sync parse-extract pipeline; inputs accept a file (multipart), a files.upload document_ref, or a document_url
  • client.v2.files.upload({ file }) -> file_ref
  • V2 routes to api.ade.[env].landing.ai; V1 stays on api.va.[env].landing.ai. environment / LANDINGAI_ADE_ENVIRONMENT + v2BaseURL / LANDINGAI_ADE_V2_BASE_URL overrides
  • Fully typed parse result (structure/grounding trees, metadata); unified Job across the divergent envelopes (Job.raw keeps the original)

Live validation (staging) ✅

Ran examples/v2_smoke_test.ts against api.ade.staging.landing.ai with a real PDF — all 7 surfaces pass (files, extract, extract-jobs, parse, parse-jobs, workflow, workflow-jobs). Full table in this comment. Confirms auth, host routing, multipart upload, schema coercion, the three job normalizers, and the wait() poller against the real gateway. (Manual/QA tool; not wired into CI — same as ade-python's examples/v2_smoke_test.py.)

Tracks the updated spec

Jobs-create param is service_tier (not priority); V2ExtractMetadata.billing (+ V2Billing); the /v2/workflow surface; password → 422 doc note.

Conventions (settled)

  • Host api.ade.* — matches the python SDK and verified live. (aide.* only publishes the spec and is behind staff SSO.)
  • Casing: unified Job/JobList use snake_case, matching V1 + the rest of the SDK + the python SDK.
  • wait() timeout: milliseconds (this SDK's convention).
  • schema: a JSON-Schema object or JSON string (no zod dep; z.toJSONSchema(...) documented).
  • Sync retries: parse/extract/workflow cap at maxRetries: 1 — a 504 (cancelled work) costs ≤ 2 attempts, while a transient connection blip on a long sync call recovers once.

Review fixes (max-effort review)

Env-resolution precedence (explicit args beat env vars; an explicit baseURL governs both hosts), wait(raiseOnFailure) keys off terminal failed/cancelled status (not error != null), and the full V2 type-export surface across the barrels + LandingAIADE namespace. Plus the 4 inline review comments (host alignment, environment-option comment, README parse/extract split).

Tests

V2 unit + routing tests (env matrix, normalizers incl. workflow, waiter, schema, host routing, service_tier, workflow multipart, sync retry cap) + the live smoke test. tsc + eslint clean; full suite green (280 passed).

Cross-repo note

ade-python #105 predates the spec's priorityservice_tier rename and still sends priority — worth the matching fix there.

🤖 Generated with Claude Code

tian-lan-landing and others added 6 commits July 9, 2026 10:17
Additive `client.v2` sub-client for the V2 (ADE gateway) surface, ported from
ade-python #105. V1 surface untouched; package stays 2.x.

- `client.v2.parse`/`extract` (sync) + `parseJobs`/`extractJobs` (create/get/list/wait)
  returning one unified, normalized `Job` across the divergent parse/extract envelopes.
- `client.v2.files.upload` staging (`file_ref` for `markdown_ref`).
- Environment matrix (production/eu/staging/dev) pairing V1 `api.va.*` with V2 `api.ade.*`;
  `environment`/`LANDINGAI_ADE_ENVIRONMENT` + `v2BaseURL`/`LANDINGAI_ADE_V2_BASE_URL` overrides.
- `wait()` backoff poller, schema coercion (JSON-Schema object or JSON string),
  504 -> `V2SyncTimeoutError`, `saveTo` parity.
- 34 tests (env, normalize, waiter, schema, routing/errors); typecheck + lint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…se, workflow)

Sync client.v2 to the updated AIDE Gateway spec:

- BREAKING (vs prior commit): jobs-create renamed priority -> service_tier on
  parseJobs/extractJobs/workflowJobs (values unchanged).
- Type V2ParseResponse fully (structure/grounding trees, ParseMetadata/ParseBilling).
- Add V2Billing + V2ExtractMetadata.billing.
- Add the /v2/workflow surface: client.v2.workflow (sync) + workflowJobs
  {create,get,list,wait}, reusing the Job normalizer/waiter.
- Update password doc (encrypted PDFs unsupported -> 422).

40 V2 tests; tsc + eslint clean; full suite 274 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…puts

- V2 host corrected to aide.[env].landing.ai per ade-python#105 (api.ade.* is a
  separate VTRA host, not V2); updated env map, tests, README, api.md.
- Workflow inputs now accept a file via inputs.<name>.document — staged as a
  multipart part with inputs/steps/output JSON-encoded; document_ref/document_url
  stay on the JSON path.

Full suite 275 passed; tsc + eslint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Unified Job/JobList now use snake_case (job_id, created_at, completed_at,
  is_terminal, has_more, org_id, page, page_size), matching V1 + the rest of
  the SDK + the Python SDK. wait() timeout stays in milliseconds.
- README: point V2 extract at the existing 'Using Zod' section (z.toJSONSchema).

Full suite 275 passed; tsc + eslint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… sync 504 retries

Addresses the CONFIRMED findings from the code review:

- resolveV2BaseURL: explicit args now beat ambient env vars, and an explicit
  baseURL governs BOTH hosts. Fixes (a) LANDINGAI_ADE_ENVIRONMENT silently
  splitting V1→baseURL / V2→real gateway, and (b) LANDINGAI_ADE_V2_BASE_URL
  overriding an explicit environment arg.
- pollUntilTerminal(raiseOnFailure): key off terminal failed/cancelled status
  instead of job.error!=null — fixes a failed job with no error not throwing,
  and a completed job with a residual error object wrongly throwing.
- Sync v2.parse/extract/workflow disable retries (caller-overridable) so a
  server 504 (cancelled work) surfaces immediately instead of re-running 3x.

+5 regression tests; full suite 280 passed; tsc + eslint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The parse structure/grounding leaf types (V2ParseStructure, V2ParsePage,
V2ParseElement, V2GroundingDocument/Page/Element/Entry, V2ElementType, V2Span,
V2Box) plus isTerminalStatus/DEFAULT_WAIT_TIMEOUT_MS were exported from
resources/v2 but missing from resources/index.ts and the LandingAIADE
namespace, so they were unreachable from the package root / LandingAIADE.*.
Now all three export sites agree.

tsc + eslint clean; full suite 280 passed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread src/client.ts
…per review

Addresses PR review comments:
- V2 host reverted to api.ade.[env].landing.ai to match the python SDK's
  V2_ENVIRONMENTS (client.ts map, ClientOptions doc, README, api.md, tests).
- README V2 section: annotate the environment option (values + env var) like
  the python doc, and split sync parse & extract into their own subsections
  instead of one combined code block.

Full suite 280 passed; tsc + eslint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
tian-lan-landing and others added 2 commits July 9, 2026 16:00
Mirrors ade-python's examples/v2_smoke_test.py: drives files/extract/parse/
workflow (sync + jobs) against a live gateway with per-check PASS/FAIL and a
non-zero exit on failure. Manual/QA tool — not wired into CI (neither is the
python one). Auto-loads .env.local for VISION_AGENT_API_KEY; defaults to
staging. Run: yarn tsn examples/v2_smoke_test.ts

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tian-lan-landing
tian-lan-landing force-pushed the feat/v2-parse-extract branch from e38f264 to ff82e18 Compare July 9, 2026 08:03
Two same-named VISION_AGENT_API_KEY lines (dev then staging) previously took
the first (dev); now the last wins, so a staging-last .env.local targets
staging by default. Verified end-to-end against api.ade.staging: files.upload,
v2.extract, and v2.extractJobs (create+wait) all pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tian-lan-landing

Copy link
Copy Markdown
Collaborator Author

Live smoke test (staging) — all V2 surfaces pass ✅

Ran examples/v2_smoke_test.ts against the real gateway (api.ade.staging.landing.ai) with a staging API key and a real PDF (deel-testing.pdf). Every V2 surface works end-to-end:

surface result
client.v2.files.upload ✅ returns a file_ref
client.v2.extract (sync) ✅ extracted the schema fields; version=extract-20260630
client.v2.extractJobs (create + wait) ✅ completed
client.v2.parse (sync, real PDF)
client.v2.parseJobs (create + wait) ✅ ~31s
client.v2.workflow (sync) ✅ 3/3 retries, ~37–60s (output keys=["parse-extract"])
client.v2.workflowJobs (create + wait) ✅ ~46s (multipart file input)

This exercises, against the live gateway: Bearer-key auth, api.ade.* host routing, multipart upload, JSON bodies, schema coercion (JSON-Schema object), all response parsing, the parse/extract/workflow job normalizers, and the wait() poller. Host api.ade.* confirmed correct.

Notes

  • Sync workflow is a ~40–60s long-held connection and occasionally hits a transient socket close; it succeeded on 3/3 individual re-runs. Sync methods (parse/extract/workflow) cap retries at maxRetries: 1, so a transient blip recovers once while a server 504 (cancelled work) still costs ≤ 2 attempts. For large documents the async workflowJobs route is the robust path.
  • Two combined-run failures earlier were staging load + a too-short --timeout; each surface passes when run individually.
  • The smoke test is a manual/QA tool (not wired into CI, same as ade-python's examples/v2_smoke_test.py). Run: yarn tsn examples/v2_smoke_test.ts.

🤖 Generated with Claude Code

tian-lan-landing and others added 3 commits July 9, 2026 18:53
… bound 504)

maxRetries:0 meant a transient connection blip on a long sync parse/extract/
workflow surfaced immediately. Cap at 1 instead: a 504 (cancelled work) still
costs at most 2 attempts, while a one-off socket drop can recover once. Live
smoke test showed sync workflow is a ~40-60s call that occasionally drops the
socket but succeeds on retry (3/3 when re-run).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
parse/parse_jobs/workflow/workflow_jobs shared one fs.ReadStream, which is one-shot: the sync parse drained it, so later checks uploaded an empty body (422 "Empty file"). Pull a fresh source per check.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tian-lan-landing
tian-lan-landing force-pushed the feat/v2-parse-extract branch from 66d763d to 8d0bf63 Compare July 9, 2026 10:54
@tian-lan-landing
tian-lan-landing merged commit c3fe332 into main Jul 9, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants