Repository navigation
feat(tools): add ToolSearch for on-demand loading of deferred tool schemas #3589
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from 2 commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
0a2e390
feat(tools): add ToolSearch for on-demand loading of deferred tool sc…
f22d164
feat(cli): add --json-schema for structured output in headless mode
a17a357
fix(tools): tighten ToolSearch schema + match invocation signature
wenshao 1fa1d75
fix(tools,cli): surface ToolSearch reveal failures + dedupe revealed …
wenshao e8712eb
fix(cli): honor process.exitCode in headless main exit
wenshao 88b10c2
test(cli): add integration tests for --json-schema and ToolSearch
wenshao 3872656
fix(cli,core): tighten --json-schema validation
wenshao 6153efb
fix(tools): roll back ToolSearch reveals when setTools() throws
wenshao dbc6714
test(cli): unit-cover --json-schema runtime branches
wenshao 210ec2b
fix(cli,core): support type-union arrays in --json-schema
wenshao 7f235c2
fix(tools): cap select: mode in ToolSearch by max_results
wenshao c24c1e5
fix(tools): treat null GeminiClient like setTools() failure in ToolSe…
wenshao 21c48e9
fix(cli): use boolean sentinel for structured_output submission
wenshao ea3ab0c
fix(cli): finish structured_output sentinel cleanup + reject stream-j…
wenshao b680acc
fix(prompt): harden deferred-tools section against MCP description in…
wenshao 9c031da
fix(core): scope --json-schema strictness so spec-valid schemas pass
wenshao 2213e6e
fix(cli): allow --json-schema with stdin-piped prompt
wenshao 093b5f8
fix(cli,tools): short-circuit after structured_output + tighten ToolS…
wenshao 5efc328
fix(prompt,tools): escape backticks in tool names + report select: tr…
wenshao e39948e
fix(prompt): JSON-quote tool names instead of incomplete backtick escape
wenshao 33a946a
fix(tools): escape `<` in ToolSearch schema blocks to prevent wrapper…
wenshao 9588231
fix: address #3589 wave 2 — Critical reveal/race + revealed-set hygiene
wenshao 11ccadd
fix(tools,cli): select: quote-strip + import order
wenshao 1ae9b4a
fix(tools,cli): isolate ensureTool failures + enrich --json-schema error
wenshao b8ff450
test(core): cover startChat deferred-tool branches
wenshao 883a332
test(tools): pin MCP `__` suffix already scores as exact (12), not su…
wenshao 1884c97
test(cli,core): cover --json-schema pre-scan + resetChat reveal cleanup
wenshao e1b75f6
docs(tools): clarify ToolSearch description — fetch decl, callable ne…
wenshao bb39976
docs(cli): correct pre-scan comment — siblings are skipped, not synth…
wenshao e7a0da9
Merge remote-tracking branch 'origin/main' into x3
wenshao 1d97d7a
fix(tools,cli): scope ToolSearch reveal/setTools to deferred + drop d…
wenshao ca4835c
test(cli): pin contextCommand passes includeDeferred to getFunctionDe…
wenshao b3027a5
fix(tools): surface ToolSearch ensureTool/setTools failures to stderr
wenshao File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| /** | ||
| * @license | ||
| * Copyright 2025 Qwen | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| import { describe, it, expect } from 'vitest'; | ||
| import * as fs from 'node:fs'; | ||
| import * as os from 'node:os'; | ||
| import * as path from 'node:path'; | ||
| import { resolveJsonSchemaArg } from './config.js'; | ||
|
|
||
| describe('resolveJsonSchemaArg', () => { | ||
| it('returns undefined when the arg is absent', () => { | ||
| expect(resolveJsonSchemaArg(undefined)).toBeUndefined(); | ||
| }); | ||
|
|
||
| it('parses an inline JSON literal into a schema object', () => { | ||
| const schema = resolveJsonSchemaArg( | ||
| '{"type":"object","properties":{"summary":{"type":"string"}}}', | ||
| ); | ||
| expect(schema).toEqual({ | ||
| type: 'object', | ||
| properties: { summary: { type: 'string' } }, | ||
| }); | ||
| }); | ||
|
|
||
| it('reads schema from disk via @path syntax', () => { | ||
| const tmp = fs.mkdtempSync(path.join(os.tmpdir(), 'qwen-schema-')); | ||
| const file = path.join(tmp, 'schema.json'); | ||
| fs.writeFileSync(file, '{"type":"object"}'); | ||
| try { | ||
| const schema = resolveJsonSchemaArg(`@${file}`); | ||
| expect(schema).toEqual({ type: 'object' }); | ||
| } finally { | ||
| fs.rmSync(tmp, { recursive: true, force: true }); | ||
| } | ||
| }); | ||
|
|
||
| it('throws on empty string', () => { | ||
| expect(() => resolveJsonSchemaArg(' ')).toThrow(/cannot be empty/); | ||
| }); | ||
|
|
||
| it('throws on invalid JSON', () => { | ||
| expect(() => resolveJsonSchemaArg('{not json}')).toThrow( | ||
| /not valid JSON/, | ||
| ); | ||
| }); | ||
|
|
||
| it('throws when the parsed value is not an object', () => { | ||
| expect(() => resolveJsonSchemaArg('[]')).toThrow(/must be a JSON object/); | ||
| expect(() => resolveJsonSchemaArg('"just a string"')).toThrow( | ||
| /must be a JSON object/, | ||
| ); | ||
| }); | ||
|
|
||
| it('throws when the referenced file does not exist', () => { | ||
| expect(() => | ||
| resolveJsonSchemaArg('@/this/path/does/not/exist.json'), | ||
| ).toThrow(/could not read/); | ||
| }); | ||
|
|
||
| it('throws when schema is syntactically JSON but invalid as a JSON Schema', () => { | ||
| // `type` must be a string or array, not a number. | ||
| expect(() => resolveJsonSchemaArg('{"type": 42}')).toThrow( | ||
| /not a valid JSON Schema/, | ||
| ); | ||
| }); | ||
|
|
||
| it('accepts a minimal empty-object schema', () => { | ||
| // `{}` is a valid schema that accepts anything. | ||
| expect(resolveJsonSchemaArg('{}')).toEqual({}); | ||
| }); | ||
|
|
||
| it('accepts a draft-2020-12 schema', () => { | ||
| const schema = resolveJsonSchemaArg( | ||
| '{"$schema":"https://json-schema.org/draft/2020-12/schema","type":"object"}', | ||
| ); | ||
| expect(schema).toBeDefined(); | ||
| }); | ||
| }); |
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
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
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
Oops, something went wrong.
Oops, something went wrong.
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.
Uh oh!
There was an error while loading. Please reload this page.