agents: contract 0.2.0 — generate the tool surface from vendored descriptors#70
Open
ShawnChen-Sirius wants to merge 2 commits into
Open
agents: contract 0.2.0 — generate the tool surface from vendored descriptors#70ShawnChen-Sirius wants to merge 2 commits into
ShawnChen-Sirius wants to merge 2 commits into
Conversation
…riptors descriptors.json (vendored byte-identical from the Python reference in chdb-io/chdb) becomes the single source of the model-visible tool surface: - new descriptors.mjs: CONTRACT_VERSION, loadDescriptors(), toolSpecs(dialect='anthropic'|'openai'|'mcp'), capabilities(); ChDBTool#toolSpecs(dialect) delegates to it. - framework.mjs AGENT_TOOL_DESCRIPTORS (the zod schemas the Vercel AI SDK / Mastra adapters consume) is now generated mechanically from the same file; the hand-written descriptor list is gone. Drift fixes against the Python reference, now conformance-tested: - a non-numeric maxRows/limit throws ChDBError(INVALID_ARGUMENT); previously Number(...) produced NaN, every NaN comparison is false, and the row cap was silently disabled. - maxBytes counts UTF-8 bytes of each row's compact JSON (Buffer.byteLength); String.length counted UTF-16 units, putting the truncation point up to ~3x later than the reference on non-ASCII rows. - an explicit empty-string database is rejected like the reference; the falsy check treated '' as "no database" and silently dropped the qualifier. conformance fixture re-synced (header record with contract_version, capability gating, new cases); CONTRACT.md mirror re-synced. Co-Authored-By: Claude Fable 5 <[email protected]>
Contributor
Author
|
@chibugai, review it |
There was a problem hiding this comment.
Pull request overview
Aligns the TypeScript agents binding with agents contract 0.2.0 by making the vendored descriptors.json the single source of truth for the model-visible tool surface, and updating the framework adapters + conformance fixtures/tests to be generated/validated from it.
Changes:
- Added
integrations/agents/descriptors.mjs(+ typings + vendoreddescriptors.json) to generate tool specs for multiple dialects and exposecapabilities()/CONTRACT_VERSION. - Updated
ChDBTooland the framework adapter surface to consume generated tool specs and to match Python-reference drift fixes (typed INVALID_ARGUMENT for non-numeric caps, UTF-8 byte counting formaxBytes, reject empty-string database qualifier). - Re-synced and strengthened the conformance fixture/test runner to assert contract version headers and capability-gate optional cases.
Reviewed changes
Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| test/v3/integrations/agents-tool.test.ts | Adds unit coverage for descriptor-generated tool surfaces, capabilities, and argument validation. |
| test/v3/integrations/agents-conformance.test.ts | Updates conformance runner to handle fixture header records and capability-gated cases. |
| integrations/agents/tool.mjs | Implements contract 0.2.0 drift fixes; delegates tool spec generation to descriptors module. |
| integrations/agents/tool.d.mts | Updates TS declarations for the new toolSpecs(dialect) signature. |
| integrations/agents/index.mjs | Re-exports descriptors/capabilities APIs from the agents entrypoint. |
| integrations/agents/index.d.mts | Re-exports new descriptors types and functions in typings. |
| integrations/agents/framework.mjs | Generates AGENT_TOOL_DESCRIPTORS mechanically from descriptors.json via loadDescriptors(). |
| integrations/agents/descriptors.mjs | New generator for dialect tool specs + capabilities surface + contract version constant. |
| integrations/agents/descriptors.json | Vendored, contract-governed tool descriptor source of truth (contract 0.2.0). |
| integrations/agents/descriptors.d.mts | Adds typings for descriptors module public API. |
| integrations/agents/CONTRACT.md | Updates contract mirror with descriptors.json + capabilities/versioning details and new normative notes. |
| integrations/agents/conformance/README.md | Updates fixture documentation to include header record + capability gating. |
| integrations/agents/conformance/cases.jsonl | Adds header record, new drift-fix cases, and capability-gated optional case(s). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
chibugai
reviewed
Jul 7, 2026
Review follow-ups on the contract-0.2.0 change, mirroring the Python
reference:
- loadDescriptors() returns a structuredClone of the cached parse, so a caller
mutating the result can no longer corrupt what toolSpecs()/capabilities()/
AGENT_TOOL_DESCRIPTORS generate for everyone else in-process; a
missing/broken descriptors.json now throws a diagnosable ChDBError instead
of a raw fs error or SyntaxError.
- An unknown param type in descriptors.json fails loudly in both renderings
(jsonSchema and the zod codegen) instead of falling through to a permissive
z.record — a typo in the shared asset must not silently degrade the
model-visible argument schema.
- call() validates the arguments payload before dispatch: a non-object
(string/number/array) returns the {ok: false, INVALID_ARGUMENT} envelope.
Previously a string would spread into {0: 'S', 1: 'E', ...} garbage and run
anyway, while the Python reference raised — both bindings now return the
same envelope (new conformance case p4_malformed_arguments).
- The conformance runner enforces the fixture shape: the first record must be
the header, every later record must carry an "id" — a case that lost its id
fails the run instead of being silently reclassified as a second header.
Tests: 66 passed (was 63).
Co-Authored-By: Claude Fable 5 <[email protected]>
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.
What
TypeScript half of chdb-io/chdb#602 (agents contract 0.2.0).
descriptors.json— vendored byte-identical from the Python reference (chdb/agents/descriptors.json) — becomes the single source of the model-visible tool surface:integrations/agents/descriptors.mjs:CONTRACT_VERSION,loadDescriptors(),toolSpecs(dialect = 'anthropic' | 'openai' | 'mcp'),capabilities();ChDBTool#toolSpecs(dialect)delegates to it.framework.mjs'sAGENT_TOOL_DESCRIPTORS(the zod schema list the Vercel AI SDK and Mastra adapters consume) is now generated mechanically from the same file; the hand-written descriptor list is gone. The adapters themselves are untouched — the descriptor shape ({name, id, description, schema}) is unchanged.capabilities()returns{contract_version, tools, features}for downstream feature-probing (features.dataframe_queryisfalsehere — that capability is Python-only).Drift fixes against the Python reference (behavior changes)
maxRows/limit(per-call or constructor) throws a typedChDBErrorwithtype: 'INVALID_ARGUMENT'. PreviouslyNumber('lots')producedNaN, everyNaNcomparison is false, and the row cap was silently disabled — the Python reference raises.maxBytescounts UTF-8 bytes of each row's compact JSON (Buffer.byteLength).String.lengthcounted UTF-16 code units, putting the truncation point up to ~3× later than the reference on non-ASCII rows — a model-visible split between bindings.databaseis rejected like the reference. The previous falsy check treated''as "no database" and silently dropped the qualifier.call()envelope path, a JSONnulloptional argument means "omitted" (matches the reference).Conformance fixture
integrations/agents/conformance/re-synced with upstream: the fixture now starts with a header record whosecontract_versionthe runner asserts against this binding'sCONTRACT_VERSION(a stale vendored fixture fails loudly), and cases may carry"requires": "<feature>"— the runner skips them whencapabilities()lacks the feature (this is how the Python-onlydataframe_querycase is handled here). New cases cover every behavior above.CONTRACT.mdmirror re-synced.Tests
npx vitest run test/v3/integrations/— 63 passed (21 conformance cases, 12 agents unit tests incl. dialect rendering, descriptors/zod parity, capabilities, argument validation; ai-sdk/mastra/hypequery suites unaffected).🤖 Generated with Claude Code
Note
Generate agents tool surface from vendored descriptors in contract 0.2.0
loadDescriptors(),toolSpecs(dialect), andcapabilities()functions in descriptors.mjs, supporting'anthropic','openai', and'mcp'dialects; unknown dialects throw a typedINVALID_ARGUMENTerror.intArg()validation toChDBToolconstructor and call-site caps (maxRows,maxBytes,maxExecutionTime); non-numeric values now throw typedINVALID_ARGUMENTerrors instead of silently coercing toNaN.ChDBTool.call()now returns an error envelope for non-object arguments (including arrays and JSON null) rather than proceeding or throwing.contract_versionand feature-gated cases driven bycapabilities().features.query()now measures UTF-8 bytes viaBuffer.byteLength(JSON.stringify(row), 'utf8')instead of string length, which changes truncation boundaries for non-ASCII data.Macroscope summarized 8e5d77d.