Repository navigation
feat!: release DeckOps 4.0.0 — probe, render, extract and convert - #2
Merged
Merged
Conversation
…yped task errors The transport now covers every task the 4.0 route table submits: - GET /tools/capabilities, cached per API root at module level for the server's five-minute max-age; a 404 means a pre-4.0 server with no document tasks. - Signed result URLs are fetched without credentials, with gateway retries and error messages that never include the signature. - Waits fail with TaskFailedError / TaskTimeoutError carrying the task id; translateError turns them into backend_error with details.reason failed or timeout. DeckOpsError gains details and isDeckOpsError(). - insufficientPackage and 402 map to quota_error with the server body kept in details; a 402 no longer drops its body. documentSourceInvalid is input_error. - tasks.start(), and URL-input document tasks are created without fileIds. The 3.0 parse client moves to client/legacy*.ts over cloud/legacy-transport.ts so the Node CLI and browser entry keep working until they move to the ops client. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ops/ turns (verb, input family, target) into a cloud task chain:
- routes.ts: the 4.0 rows only, as data: render image/video over convertor.*,
convert markdown over document.convert, extract json/assets over
document.extract; requires gates document routes (and URL render) on the
server capabilities; webp appends image.convertWebp per frame.
- params.ts is the single option → task-params mapping; plan.ts validates every
option against the route and the input format and names the nearest
supported combinations when one is missing.
- chain.ts runs multi-step chains by downloading and re-uploading the
intermediate result, applies page selection before per-frame steps, and can
continue a submitted task by id; results.ts normalizes file tuples and the
document delivery shape into RemoteFile and rewrites Markdown image links.
client/ exposes createClientWith() → { render, convert, extract, tasks, files }:
one timeout budget per call, aborts rejecting with signal.reason, progress
phases upload / task / download, in-memory fileId reuse by object and SHA-256,
and one re-upload when the server has forgotten a reused file id.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
fake-cloud now serves /tools/capabilities (404 for legacy-server cases), document.convert / document.extract in the RFC §5.6 delivery shape with summary-only detail results, convertor.* and image.convertWebp file tuples, signed result files, insufficientPackage, and forgotten file ids. tests/ops: one case per route row over real HTTP, the old-server gate, capability caching, quota_error details, failed and timed-out tasks, abort reasons, progress order, upload reuse, stale file ids, resume and the low-level tasks/files API; plus table, planning-error and parameter-mapping unit tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
DeckOps 4 drops the parse verb and the artifact directory; the server owns the parse and reuses it by file hash. - node/: the 3.0 artifact model (manifest v3, read/parse/convert ops, localization) is gone. cache.ts keeps ~/.cache/deckops/index.json with sha256 → fileId and the submission journal (written before dispatch and on creation, dropped only after the outputs are written; a rerun continues the task instead of paying again; password and multi-task runs are not journaled). ops.ts runs every verb under one --timeout budget and writes results: Markdown with images under assets/ beside it (never overwriting another document's asset, md5-verified), JSON with its assets, frames named by page. source.ts reads and freezes the source within 256 MiB. - probe: ops/probe.ts loads the optional @deckflow/deckprobe@2.7.0 (probeFile with backend auto, deadline, input limit, signal); stdin goes through a temp file; it never resolves credentials or reaches the network; without the package it is unsupported with an install hint. The schema-2 report is printed unchanged. - cli/: probe / render / extract / convert, a bare source = convert -o -, --json envelopes with tasks[], formats from the route table; parse, --format, --mode fail as usage errors that name the replacement. Error and exit codes are unchanged. - Uploads are verified with PUT /files/:id/status/uploaded on servers with capabilities v1 before an id is cached or used; fileUploadInvalid is input_error. The runtime can keep fileIds across processes (Node does, without passwords). - The 3.0 parse client, parse facade and legacy transport are deleted; the browser entry now exposes the ops client. Browser gzip budget rebased to 42,856 (measured 38,960 with render/extract and the route table). - check-boundaries: DeckProbe only as an optional dependency and only in ops/probe.ts, which may not import cloud/, auth/, config/; ops/routes.ts must be declarative; no node: imports in ops/ either; no probe engine in the browser. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The strict profile (--omit=dev --omit=optional) keeps the 3.0 budget — 12 MiB, no native binaries, no install scripts, cold start — and requires `deckops probe` to fail as unsupported. The default profile records the size with the probe engine and requires `deckops probe` to produce a schema-2 report from the installed package. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PDF assets are named p1_i0000.png in every document, so a shared assets/ beside the output made the second document in a directory fail. Markdown and extracted JSON now place their images in <stem>.assets/ (staged in a temporary sibling that replaces the directory only when every download verified), links and JSON references point there, and --split-pages pages share it. A rerun replaces only its own directory; the conflict error is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- createClient takes authUuid (a UUID v4, sent as X-Auth-UUID; otherwise localStorage df_uuid) and rejects anything else as usage_error. - Tests over real HTTP for the remaining contract items: concurrent 401s share one refresh, an explicit and a stored device id, abort rejecting with the caller's reason (an AbortError DOMException without one), and an import with no side effects that works without window or localStorage. - tests/browser/smoke.js runs the same contract in a real browser against the ops API (17 checks, cross-origin CORS, verified and multipart uploads, rendered frame blobs). - Browser gzip budget: measured 39,025 bytes at 4.0.0, plus 10 %. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- README is organized by the four verbs, the files they write, the --json envelopes, the Node SDK and the browser SDK contract. - The Agent Skill teaches the probe → extract → convert → render workflow, asks before uploading for the cloud verbs only, and replaces references/artifact.md with probe.md. - CHANGELOG 4.0.0 lists the 3.x → 4.0 command and SDK migration table. - src/README.md states the layering rules for ops/ and the local, free probe. - Version 4.0.0. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`deckops doc.pdf | head -c 10` closed stdout before DeckOps wrote, and the unhandled EPIPE printed a Node stack and exited 1. A closed stdout now ends every verb and the default entry with exit 0 and no output. A closed stderr loses only diagnostics: the run continues, so stdout stays complete and a failure keeps its exit code (a login keeps waiting instead of ending as a silent success). check:read spawns the built CLI with each pipe closed before it writes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tasks.get() now passes through the server's credits, consumedMS, createdAt and completedAt, so callers can reconcile usage per task. The wire fixture serves them like the task detail does: credits and createdAt from creation, completedAt and consumedMS once the task ends. Browser gzip budget: measured 39,079 bytes, plus 10 %. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The probe tests and the package check read tests/test-data/test.pdf, a local sample that .gitignore keeps out of the repository, so every CI job failed with input_error. They now probe tests/generated/test.pdf from scripts/generate-fixtures.mjs (one page, no metadata), and check:package generates it first. The package check asks for page_count and expects 1: the default targets include the title and author this fixture lacks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DeckOps 4.0.0 replaces parse/IR artifacts with four atomic capabilities:
@deckflow/deckprobe@2.7.0engine; no credentials, no request, the schema-2 report printed unchanged.--to json) or its images (--to assets).The IR never leaves the server: the SDK and CLI receive Markdown, JSON and signed result files, and the cloud reuses one parse per file for 7 days without another charge. One declarative route table (
src/ops/routes.ts) maps verb × input × target to cloud tasks. Convert and extract need the server'sdocument.*tasks, gated byGET /tools/capabilities; against an older server they fail withunsupportedwhile render keeps working. There is no fallback to the 3.0 protocol.Breaking. The 3.x → 4.0 command and SDK migration table is in CHANGELOG.md.
Verification
pnpm check: 13 files / 213 tests, typecheck (Node + browser + standalone consumer), build, browser export (39,079 bytes gzip, budget 42,987), boundaries, and the built CLI contract over real HTTP against the wire fixture.pnpm check:package: tarball 359 KiB;--omit=optionalinstall 4.42 MiB (probe reportsunsupported); default install 8.98 MiB with probe working; cold start P95 64 ms.tests/local-case):--to jsonon the same file —reusedParse: true, 0 credits.--to assetsand a rerun of convert —reusedParse: true, 0 credits.--split-pages— 99 slides, 5 s.--pages 1-2— 27 s; the server renders all 99 slides and bills 100 (expected).sha256 → fileIdentries and the submission journal empties after completion.tests/browser/client.test.ts;tests/browser/smoke.jsruns the same flow in a real browser.🤖 Generated with Claude Code