feat(sdk,cli,mcp): agent-DX blob CDN diagnostics (v1.45)#117
Merged
Conversation
Coordinated public-repo half of the v1.33 agent-DX blob CDN release. All additive — no existing API surface broken.
SDK (sdk/src/namespaces/blobs.{ts,types.ts}):
- Widen blobs.put return into AssetRef: keeps the snake_case fields for back-compat AND adds size, contentSha256, contentType, immutableUrl, etag, sri, contentDigest, cacheKind, cdn:{version,invalidationId,invalidationStatus,ready,hint}.
- buildAssetRef derives etag/sri/contentDigest locally from the SHA so the SDK surface is stable across gateway versions.
- New helpers: client.blobs.diagnoseUrl(projectId, url) and client.blobs.waitFresh(projectId, {url, sha256, timeoutMs?}). Signed slightly differently from the spec scenarios (added projectId first arg) for consistency with put/get/ls.
- 8 new tests in blobs.test.ts (22 total).
CLI (cli/lib/blob.mjs, cli/lib/cdn.mjs, cli/cli.mjs, openclaw/scripts/cdn.mjs):
- run402 blob diagnose <url> — exit 0 on SHA match, 1 otherwise (shell-loop friendly).
- run402 cdn wait-fresh <url> --sha <hex> [--timeout <secs>] — polls until fresh.
- Both --help docs include exit-code semantics and the vantage caveat.
MCP tools (src/tools/blob-{diagnose,wait-fresh}.ts, src/index.ts):
- diagnose_public_url + wait_for_cdn_freshness with explicit agent guidance ('mutable URLs only').
- wait_for_cdn_freshness returns isError=true on timeout so agents branch into the immutableUrl fallback.
Docs (SKILL.md, cli/llms-cli.txt):
- 'Prefer immutableUrl in generated HTML/CSS/JS' guidance with reasoning (read-after-write correctness, integrity via SRI).
- New tool sections for diagnose_public_url + wait_for_cdn_freshness.
Notes:
- sync.test.ts updated for the new SURFACE rows + cdn namespace; the llms.txt-alignment assertion fails locally until the private-repo PR merges (it reads ~/Developer/run402-private/site/llms.txt). CI in the public repo skips the suite when the path is absent.
- Version is already 1.45.0 (chore: bump in 143f408). After this PR merges, run npm publish in coordination with the v1.33 backend cutover.
Co-Authored-By: Claude Opus 4.7 (1M context) <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
Coordinated public-repo half of the v1.33 agent-DX blob CDN release. All additive — no existing API surface broken.
Pairs with the private-repo PR that ships the gateway + infra + schema changes. Merge that one first so the canonical
site/llms.txtcarries the/storage/v1/blobs/diagnoseendpoint row; thesync.test.tsllms.txt alignmentassertion in this PR then auto-passes when re-run locally.After both PRs land, run
npm publishfrom this branch in the coordinated release window with the v1.33 backend cutover. Version is already bumped to1.45.0(commit143f408).What's in this PR
SDK (sdk/src/namespaces/blobs.ts, blobs.types.ts)
client.blobs.putreturn intoAssetRef: keeps the snake_case fields (size_bytes,sha256,immutable_url) for back-compat AND addssize,contentSha256,contentType,immutableUrl,etag,sri,contentDigest,cacheKind,cdn: { version, invalidationId, invalidationStatus, ready, hint }.buildAssetRefderivesetag/sri/contentDigestlocally from the SHA so the SDK surface is stable across gateway versions (older gateways without thecdnenvelope still work —buildAssetReffills safe defaults).client.blobs.diagnoseUrl(projectId, url)→ diagnose envelopeclient.blobs.waitFresh(projectId, { url, sha256, timeoutMs? })→ polls with exponential backoff, returns{ fresh, observedSha256, attempts, elapsedMs, vantage }— never throws on timeout.CLI
cli/lib/blob.mjs: newrun402 blob diagnose <url>subcommand. Exit code 0 ifobservedSha256 === expectedSha256, 1 otherwise — agents canuntil run402 blob diagnose <url>; do sleep 1; done. Vantage caveat printed to stderr so it doesn't pollute pipes.cli/lib/cdn.mjs: newrun402 cdn wait-fresh <url> --sha <hex> [--timeout <secs>]namespace + subcommand. Exit 0 when fresh, 1 on timeout.--helpdocumenting input/output/exit-code semantics + the "mutable URLs only" caveat.openclaw/scripts/cdn.mjsre-exportscdn.mjsto keep CLI ↔ OpenClaw parity.MCP tools (src/tools/blob-diagnose.ts, blob-wait-fresh.ts)
diagnose_public_url— returns the diagnose envelope, formatted with summary + JSON.wait_for_cdn_freshness— polls; returnsisError=trueon timeout so an agent can branch into theimmutableUrlfallback. Tool descriptions explicitly tag mutability ("mutable URLs only").Docs
SKILL.md:blob_putsection now describes the AssetRef return shape; new## Prefer immutableUrl in generated HTML/CSS/JSguidance with reasoning (read-after-write correctness, integrity via SRI). New tool sections fordiagnose_public_url+wait_for_cdn_freshness.cli/llms-cli.txt: blob section rewritten with the agent-DX guidance + AssetRef field table.Out of scope (deferred to followups)
client.blobs.stats(...),run402 cdn tail,get_cdn_metrics,explain_blob_cache_state— need CloudFront log ingestionAssetRefon every per-file/deploy/v1/commitresponse (only onblobs.putfor v1)Test plan
npx tsc --noEmitcleanSKILL.test.ts: 21/21 passsync.test.ts: 17/20 pass, 1 fail, 2 skipped — the single failure is the cross-repollms.txt alignmentassertion (reads~/Developer/run402-private/site/llms.txtfrommain). Auto-passes after the paired private PR merges. CI in this repo skips the suite when the path is absent.node cli/cli.mjs cdn --helpandnode cli/cli.mjs blob diagnose --helpprint structured helpnpm run buildpasses (verified locally; CI re-checks)npm publishafter the private cutover lands (operator step in coordinated release window)🤖 Generated with Claude Code