feat(agent-toolkit): support asset_id for image blocks in update_doc#280
feat(agent-toolkit): support asset_id for image blocks in update_doc#280RoniLandau merged 11 commits intomasterfrom
Conversation
Allow image blocks in create_block/replace_block operations to use asset_id instead of public_url. The create_doc_blocks API handles asset-based images internally. Updated tool description to guide agents on splitting mixed content (text + asset images) into alternating add_markdown_content and create_block operations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Avoids internal server error when creating asset-based image blocks, since ImageContent.public_url is non-nullable but unavailable for asset-based images. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PR Review:
|
| Case | Priority |
|---|---|
asset_id: 0 — should fail clearly, not silently fall back to public_url path |
High |
Neither public_url nor asset_id provided — should fail with a clear message |
High |
Both public_url and asset_id provided — document which wins, assert it in the payload |
Medium |
Invalid string asset_id (e.g. "abc") — assert schema validation error |
Medium |
replace_block GraphQL payload assertions (see #5 above) |
Medium |
What's Good ✓
- String coercion via
z.union([z.number().int(), z.string().regex(/^\d+$/).transform(Number)])is exactly right for agents sending IDs as either type. - The first
asset_idtest correctly asserts both presence ofasset_idAND absence ofpublic_url— the right mutual-exclusion pattern. - Removing
public_urlfrom the GraphQL response fragment is safe — it's the response selection set only, not the mutation input. - Tool description update in
getDescription()and the schema operation guide are clear and actionable for agents. - Version bump follows CLAUDE.md conventions.
- Tests are behaviorally focused (asserting GraphQL inputs, not internal method calls).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds guard in buildCreateBlockInput to throw a clear error when an image block is missing both asset_id and public_url, instead of sending an invalid request to the API. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use `block.asset_id != null` instead of falsy check (handles edge case where asset_id is 0) - Replace Record<string, unknown> spread with typed conditional to preserve TypeScript safety Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verify blocksInput contains asset_id and no public_url, matching the assertion pattern used by the public_url replace_block test. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The generated ImageBlockInput requires public_url (non-nullable) and doesn't include asset_id yet. Use separate branches with a type assertion for the asset_id path to satisfy TypeScript while keeping the public_url path fully typed. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Run codegen to pick up asset_id and optional public_url from the schema. ImageBlockInput now has asset_id natively, so the `as unknown as CreateBlockInput` cast is no longer needed. Also revert accidental rename of getDocByObjectId query. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
asset_idas an alternative topublic_urlfor image blocks increate_blockandreplace_blockoperationsasset_idaccepts both number and string (coerced to number) since agents may send it as either typebuildCreateBlockInputhelper to passasset_idto theimage_blockGraphQL input when providedadd_markdown_contentandcreate_blockoperations, sinceadd_markdown_contentdoes not support asset-based imagesTest plan
asset_id(number) creates block withasset_idin GraphQL input, nopublic_urlasset_id(string) coerces to number correctlyreplace_blockwithasset_idimage works (delete + create)public_urlimage block tests still pass🤖 Generated with Claude Code