From e89b3cf7e8a5e42ccc097d251fab9d3d0a0bddfd Mon Sep 17 00:00:00 2001 From: can1357 Date: Sun, 26 Apr 2026 01:02:01 +0200 Subject: [PATCH] feat(coding-agent/tools): added examples to coding-agent tools - Added `examples` support to `StringEnum` schemas and propagated it to tool metadata. - Added concise descriptions and example values across coding-agent tool schemas for clearer guidance. - Documented the new StringEnum examples capability in `packages/ai/CHANGELOG.md`. - Cast `real` to `HASHLINE_BIGRAMS` elements in `staleBigramFor` test setup. --- packages/ai/CHANGELOG.md | 5 ++ packages/ai/src/utils/schema/strict-mode.ts | 3 +- packages/coding-agent/src/edit/modes/atom.ts | 28 ++++--- packages/coding-agent/src/tools/ask.ts | 14 ++-- packages/coding-agent/src/tools/ast-edit.ts | 26 +++++-- packages/coding-agent/src/tools/ast-grep.ts | 30 ++++++-- packages/coding-agent/src/tools/bash.ts | 17 ++--- packages/coding-agent/src/tools/browser.ts | 60 +++++++-------- packages/coding-agent/src/tools/calculator.ts | 8 +- packages/coding-agent/src/tools/cancel-job.ts | 2 +- packages/coding-agent/src/tools/checkpoint.ts | 4 +- packages/coding-agent/src/tools/debug.ts | 72 +++++++++--------- .../coding-agent/src/tools/exit-plan-mode.ts | 2 +- packages/coding-agent/src/tools/find.ts | 8 +- .../coding-agent/src/tools/gemini-image.ts | 45 ++++++------ packages/coding-agent/src/tools/gh.ts | 73 ++++++++----------- packages/coding-agent/src/tools/grep.ts | 22 +++--- .../coding-agent/src/tools/inspect-image.ts | 4 +- packages/coding-agent/src/tools/notebook.ts | 12 +-- packages/coding-agent/src/tools/poll-tool.ts | 3 +- packages/coding-agent/src/tools/python.ts | 12 +-- packages/coding-agent/src/tools/read.ts | 6 +- .../coding-agent/src/tools/render-mermaid.ts | 2 +- .../src/tools/report-tool-issue.ts | 4 +- packages/coding-agent/src/tools/resolve.ts | 2 +- packages/coding-agent/src/tools/review.ts | 16 ++-- .../src/tools/search-tool-bm25.ts | 4 +- packages/coding-agent/src/tools/ssh.ts | 8 +- packages/coding-agent/src/tools/todo-write.ts | 32 ++++---- packages/coding-agent/src/tools/vim.ts | 15 ++-- packages/coding-agent/src/tools/write.ts | 4 +- packages/coding-agent/src/tools/yield.ts | 6 +- .../coding-agent/test/core/hashline.test.ts | 2 +- 33 files changed, 294 insertions(+), 257 deletions(-) diff --git a/packages/ai/CHANGELOG.md b/packages/ai/CHANGELOG.md index bb722041a..2f5eece1d 100644 --- a/packages/ai/CHANGELOG.md +++ b/packages/ai/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog ## [Unreleased] + +### Added + +- Added an `examples` option to `StringEnum` to include example values in the generated schema + ### Fixed - Fixed parsing of JSON tool arguments containing raw control characters inside string values (such as embedded newlines) by escaping them before JSON parsing diff --git a/packages/ai/src/utils/schema/strict-mode.ts b/packages/ai/src/utils/schema/strict-mode.ts index 6445f7861..a6f4144bf 100644 --- a/packages/ai/src/utils/schema/strict-mode.ts +++ b/packages/ai/src/utils/schema/strict-mode.ts @@ -17,13 +17,14 @@ import { isJsonObject } from "./types"; */ export function StringEnum( values: T, - options?: { description?: string; default?: T[number] }, + options?: { description?: string; default?: T[number]; examples?: readonly T[number][] }, ): TUnsafe { return Type.Unsafe({ type: "string", enum: values as unknown as string[], ...(options?.description && { description: options.description }), ...(options?.default && { default: options.default }), + ...(options?.examples && { examples: options.examples }), }); } diff --git a/packages/coding-agent/src/edit/modes/atom.ts b/packages/coding-agent/src/edit/modes/atom.ts index 22a47642f..1f240129f 100644 --- a/packages/coding-agent/src/edit/modes/atom.ts +++ b/packages/coding-agent/src/edit/modes/atom.ts @@ -53,7 +53,9 @@ import { // Schema // ═══════════════════════════════════════════════════════════════════════════ -const linesSchema = Type.Union([Type.Array(Type.String()), Type.String()]); +const linesSchema = Type.Union([Type.Array(Type.String()), Type.String()], { + description: "replacement lines", +}); /** * Flat entry shape: every op key is optional, and the runtime validator @@ -65,7 +67,7 @@ const linesSchema = Type.Union([Type.Array(Type.String()), Type.String()]); */ export const atomEditSchema = Type.Object( { - path: Type.Optional(Type.String({ description: "file path override" })), + path: Type.Optional(Type.String({ description: "file path override", examples: ["src/foo.ts"] })), // Exactly one of the following op keys is required per entry: set: Type.Optional( Type.Union([ @@ -81,15 +83,23 @@ export const atomEditSchema = Type.Object( del: Type.Optional(Type.String({ description: "line anchor to delete", examples: ["5#aa"] })), sub: Type.Optional(Type.String({ description: "line anchor to rewrite", examples: ["5#aa"] })), ins: Type.Optional( - Type.String({ description: "line anchor to overwrite from a substring to end-of-line", examples: ["5#aa"] }), + Type.String({ description: "line anchor to overwrite", examples: ["5#aa"] }), + ), + append: Type.Optional( + Type.Union([Type.Array(Type.String()), Type.String()], { description: "lines to append at EOF" }), + ), + prepend: Type.Optional( + Type.Union([Type.Array(Type.String()), Type.String()], { description: "lines to prepend at BOF" }), ), - append: Type.Optional(linesSchema), - prepend: Type.Optional(linesSchema), // Payload (used by set/before/after/sub/ins/append/prepend): - lines: Type.Optional(linesSchema), + lines: Type.Optional( + Type.Union([Type.Array(Type.String()), Type.String()], { + description: "replacement payload", + }), + ), find: Type.Optional( Type.String({ - description: "shortest substring on the anchored line that must occur exactly once", + description: "unique substring on anchor line", examples: ["if("], }), ), @@ -99,8 +109,8 @@ export const atomEditSchema = Type.Object( export const atomEditParamsSchema = Type.Object( { - path: Type.Optional(Type.String({ description: "Default file path used when an edit omits its own `path`" })), - edits: Type.Array(atomEditSchema, { description: "edits" }), + path: Type.Optional(Type.String({ description: "default file path for edits" })), + edits: Type.Array(atomEditSchema, { description: "edit ops" }), }, { additionalProperties: false }, ); diff --git a/packages/coding-agent/src/tools/ask.ts b/packages/coding-agent/src/tools/ask.ts index 72239fdf7..6f81d985f 100644 --- a/packages/coding-agent/src/tools/ask.ts +++ b/packages/coding-agent/src/tools/ask.ts @@ -32,19 +32,19 @@ import { ToolAbortError } from "./tool-errors"; // ============================================================================= const OptionItem = Type.Object({ - label: Type.String({ description: "Display label" }), + label: Type.String({ description: "display label" }), }); const QuestionItem = Type.Object({ - id: Type.String({ description: "Question ID, e.g. 'auth', 'cache'" }), - question: Type.String({ description: "Question text" }), - options: Type.Array(OptionItem, { description: "Available options" }), - multi: Type.Optional(Type.Boolean({ description: "Allow multiple selections" })), - recommended: Type.Optional(Type.Number({ description: "Index of recommended option (0-indexed)" })), + id: Type.String({ description: "question id", examples: ["auth", "cache"] }), + question: Type.String({ description: "question text" }), + options: Type.Array(OptionItem, { description: "available options" }), + multi: Type.Optional(Type.Boolean({ description: "allow multiple selections" })), + recommended: Type.Optional(Type.Number({ description: "recommended option index" })), }); const askSchema = Type.Object({ - questions: Type.Array(QuestionItem, { description: "Questions to ask", minItems: 1 }), + questions: Type.Array(QuestionItem, { description: "questions to ask", minItems: 1 }), }); export type AskToolInput = Static; diff --git a/packages/coding-agent/src/tools/ast-edit.ts b/packages/coding-agent/src/tools/ast-edit.ts index 568637cbf..0967d41f7 100644 --- a/packages/coding-agent/src/tools/ast-edit.ts +++ b/packages/coding-agent/src/tools/ast-edit.ts @@ -36,20 +36,30 @@ import { ToolError } from "./tool-errors"; import { toolResult } from "./tool-result"; const astEditOpSchema = Type.Object({ - pat: Type.String({ description: "AST pattern to match" }), - out: Type.String({ description: "Replacement template" }), + pat: Type.String({ description: "ast pattern", examples: ["oldFn($$$ARGS)"] }), + out: Type.String({ description: "replacement template", examples: ["newFn($$$ARGS)"] }), }); const astEditSchema = Type.Object({ ops: Type.Array(astEditOpSchema, { minItems: 1, - description: "Rewrite ops as [{ pat, out }]", + description: "rewrite ops", }), - lang: Type.Optional(Type.String({ description: "Language override" })), - path: Type.Optional(Type.String({ description: "File, directory, or glob pattern to rewrite (default: cwd)" })), - glob: Type.Optional(Type.String({ description: "Optional glob filter relative to path" })), - sel: Type.Optional(Type.String({ description: "Optional selector for contextual pattern mode" })), - limit: Type.Optional(Type.Number({ description: "Max total replacements" })), + lang: Type.Optional(Type.String({ description: "language override", examples: ["typescript", "python"] })), + path: Type.Optional( + Type.String({ + description: "path or glob to rewrite", + examples: ["src/", "src/foo.ts"], + }), + ), + glob: Type.Optional(Type.String({ description: "glob filter", examples: ["**/*.ts"] })), + sel: Type.Optional( + Type.String({ + description: "contextual pattern selector", + examples: ["function_declaration", "call_expression", "identifier"], + }), + ), + limit: Type.Optional(Type.Number({ description: "max replacements" })), }); export interface AstEditToolDetails { diff --git a/packages/coding-agent/src/tools/ast-grep.ts b/packages/coding-agent/src/tools/ast-grep.ts index 80b79b3e4..e228de7c7 100644 --- a/packages/coding-agent/src/tools/ast-grep.ts +++ b/packages/coding-agent/src/tools/ast-grep.ts @@ -35,14 +35,28 @@ import { ToolError } from "./tool-errors"; import { toolResult } from "./tool-result"; const astGrepSchema = Type.Object({ - pat: Type.Array(Type.String(), { minItems: 1, description: "AST patterns to match" }), - lang: Type.Optional(Type.String({ description: "Language override" })), - path: Type.Optional(Type.String({ description: "File, directory, or glob pattern to search (default: cwd)" })), - glob: Type.Optional(Type.String({ description: "Optional glob filter relative to path" })), - sel: Type.Optional(Type.String({ description: "Optional selector for contextual pattern mode" })), - limit: Type.Optional(Type.Number({ description: "Max matches", default: 50 })), - offset: Type.Optional(Type.Number({ description: "Skip first N matches", default: 0 })), - context: Type.Optional(Type.Number({ description: "Context lines around each match" })), + pat: Type.Array(Type.String(), { + minItems: 1, + description: "ast patterns", + examples: [["console.log($$$)"]], + }), + lang: Type.Optional(Type.String({ description: "language override", examples: ["typescript", "python"] })), + path: Type.Optional( + Type.String({ + description: "path or glob to search", + examples: ["src/", "src/foo.ts"], + }), + ), + glob: Type.Optional(Type.String({ description: "glob filter", examples: ["**/*.ts"] })), + sel: Type.Optional( + Type.String({ + description: "contextual pattern selector", + examples: ["function_declaration", "call_expression", "identifier"], + }), + ), + limit: Type.Optional(Type.Number({ description: "max matches", default: 50 })), + offset: Type.Optional(Type.Number({ description: "skip first n matches", default: 0 })), + context: Type.Optional(Type.Number({ description: "context lines" })), }); export interface AstGrepToolDetails { diff --git a/packages/coding-agent/src/tools/bash.ts b/packages/coding-agent/src/tools/bash.ts index be507f38a..a46719975 100644 --- a/packages/coding-agent/src/tools/bash.ts +++ b/packages/coding-agent/src/tools/bash.ts @@ -42,20 +42,19 @@ async function saveBashOriginalArtifact(session: ToolSession, originalText: stri } const bashSchemaBase = Type.Object({ - command: Type.String({ description: "Command to execute" }), + command: Type.String({ description: "command to execute", examples: ["ls -la", "echo hi"] }), env: Type.Optional( Type.Record(Type.String({ pattern: BASH_ENV_NAME_PATTERN.source }), Type.String(), { - description: - "Additional environment variables passed to the command and rendered inline as shell assignments; prefer this for multiline or quote-heavy content", + description: "extra env vars", }), ), - timeout: Type.Optional(Type.Number({ description: "Timeout in seconds", default: 300 })), - cwd: Type.Optional(Type.String({ description: "Working directory (default: cwd)" })), - head: Type.Optional(Type.Number({ description: "Return only first N lines of output" })), - tail: Type.Optional(Type.Number({ description: "Return only last N lines of output" })), + timeout: Type.Optional(Type.Number({ description: "timeout in seconds", default: 300 })), + cwd: Type.Optional(Type.String({ description: "working directory", examples: ["src/", "/tmp"] })), + head: Type.Optional(Type.Number({ description: "first n lines of output" })), + tail: Type.Optional(Type.Number({ description: "last n lines of output" })), pty: Type.Optional( Type.Boolean({ - description: "Run in PTY mode when command needs a real terminal (e.g. sudo/ssh/top/less); default: false", + description: "run in pty mode", }), ), }); @@ -64,7 +63,7 @@ const bashSchemaWithAsync = Type.Object({ ...bashSchemaBase.properties, async: Type.Optional( Type.Boolean({ - description: "Run in background; returns immediately with a job ID. Result delivered as follow-up.", + description: "run in background", }), ), }); diff --git a/packages/coding-agent/src/tools/browser.ts b/packages/coding-agent/src/tools/browser.ts index 034363c8f..c12c2af0c 100644 --- a/packages/coding-agent/src/tools/browser.ts +++ b/packages/coding-agent/src/tools/browser.ts @@ -361,12 +361,12 @@ function resolvePageClient(page: Page): PuppeteerCdpClient | null { const puppeteerGetArgsSchema = Type.Array( Type.Object({ selector: Type.String({ - description: - "Selector for the target element (CSS, or puppeteer query handler like aria/, text/, xpath/, pierce/; also accepts legacy p- prefixes)", + description: "target element selector", + examples: ["aria/Sign in", "text/Continue", "xpath/...", "pierce/..."], }), - attribute: Type.Optional(Type.String({ description: "Attribute name (get_attribute)" })), + attribute: Type.Optional(Type.String({ description: "attribute name", examples: ["href", "data-id"] })), }), - { description: "Batch arguments for get_* actions", minItems: 1 }, + { description: "batch get_* args", minItems: 1 }, ); const browserSchema = Type.Object({ @@ -393,56 +393,56 @@ const browserSchema = Type.Object({ "screenshot", "close", ], - { description: "Action to perform" }, + { description: "action to perform" }, ), - url: Type.Optional(Type.String({ description: "URL to navigate to (goto)" })), + url: Type.Optional(Type.String({ description: "url to navigate to", examples: ["https://example.com"] })), selector: Type.Optional( Type.String({ - description: - "Selector for the target element (CSS, or puppeteer query handler like aria/, text/, xpath/, pierce/; also accepts legacy p- prefixes)", + description: "target element selector", + examples: ["aria/Sign in", "text/Continue", "xpath/...", "pierce/..."], }), ), - element_id: Type.Optional(Type.Number({ description: "Element ID from observe" })), - include_all: Type.Optional(Type.Boolean({ description: "Include non-interactive nodes in observe" })), - viewport_only: Type.Optional(Type.Boolean({ description: "Limit observe output to elements in the viewport" })), + element_id: Type.Optional(Type.Number({ description: "observed element id" })), + include_all: Type.Optional(Type.Boolean({ description: "include non-interactive nodes" })), + viewport_only: Type.Optional(Type.Boolean({ description: "limit to viewport" })), args: Type.Optional(puppeteerGetArgsSchema), - script: Type.Optional(Type.String({ description: "JavaScript to evaluate (evaluate)" })), - text: Type.Optional(Type.String({ description: "Text to type (type)" })), - value: Type.Optional(Type.String({ description: "Value to set (fill)" })), - attribute: Type.Optional(Type.String({ description: "Attribute name to read (get_attribute)" })), - key: Type.Optional(Type.String({ description: "Keyboard key to press (press)" })), - timeout: Type.Optional(Type.Number({ description: "Timeout in seconds", default: 30 })), + script: Type.Optional(Type.String({ description: "javascript expression", examples: ["document.title", "window.location.href"] })), + text: Type.Optional(Type.String({ description: "text to type", examples: ["hello world"] })), + value: Type.Optional(Type.String({ description: "value to set", examples: ["hello"] })), + attribute: Type.Optional(Type.String({ description: "attribute to read", examples: ["href", "data-id"] })), + key: Type.Optional(Type.String({ description: "keyboard key", examples: ["Enter", "Tab", "Escape"] })), + timeout: Type.Optional(Type.Number({ description: "timeout in seconds", default: 30 })), wait_until: Type.Optional( StringEnum(["load", "domcontentloaded", "networkidle0", "networkidle2"], { - description: "Navigation wait condition (goto)", + description: "navigation wait condition", }), ), - full_page: Type.Optional(Type.Boolean({ description: "Capture full page screenshot (screenshot)" })), + full_page: Type.Optional(Type.Boolean({ description: "full page screenshot" })), format: Type.Optional( StringEnum(["text", "markdown"], { - description: "Output format for extract_readable (text/markdown)", + description: "output format", }), ), - path: Type.Optional(Type.String({ description: "Optional path to save screenshot (relative to cwd)" })), + path: Type.Optional(Type.String({ description: "screenshot save path", examples: ["out.png"] })), viewport: Type.Optional( Type.Object({ - width: Type.Number({ description: "Viewport width in pixels" }), - height: Type.Number({ description: "Viewport height in pixels" }), - device_scale_factor: Type.Optional(Type.Number({ description: "Device scale factor" })), + width: Type.Number({ description: "viewport width" }), + height: Type.Number({ description: "viewport height" }), + device_scale_factor: Type.Optional(Type.Number({ description: "device scale factor" })), }), ), - delta_x: Type.Optional(Type.Number({ description: "Scroll delta X (scroll)" })), - delta_y: Type.Optional(Type.Number({ description: "Scroll delta Y (scroll)" })), + delta_x: Type.Optional(Type.Number({ description: "scroll delta x" })), + delta_y: Type.Optional(Type.Number({ description: "scroll delta y" })), from_selector: Type.Optional( Type.String({ - description: - "Drag start selector (CSS, or puppeteer query handler like aria/, text/, xpath/, pierce/; also accepts legacy p- prefixes)", + description: "drag start selector", + examples: ["aria/Drag handle"], }), ), to_selector: Type.Optional( Type.String({ - description: - "Drag end selector (CSS, or puppeteer query handler like aria/, text/, xpath/, pierce/; also accepts legacy p- prefixes)", + description: "drag end selector", + examples: ["text/Drop zone"], }), ), }); diff --git a/packages/coding-agent/src/tools/calculator.ts b/packages/coding-agent/src/tools/calculator.ts index b74e2723a..492e13296 100644 --- a/packages/coding-agent/src/tools/calculator.ts +++ b/packages/coding-agent/src/tools/calculator.ts @@ -31,11 +31,11 @@ type Token = const calculatorSchema = Type.Object({ calculations: Type.Array( Type.Object({ - expression: Type.String({ description: "Math expression to evaluate" }), - prefix: Type.String({ description: "Text to prepend to the result" }), - suffix: Type.String({ description: "Text to append to the result" }), + expression: Type.String({ description: "math expression", examples: ["2 + 2", "sqrt(16)"] }), + prefix: Type.String({ description: "prefix text" }), + suffix: Type.String({ description: "suffix text" }), }), - { description: "List of calculations to evaluate" }, + { description: "calculations to evaluate" }, ), }); diff --git a/packages/coding-agent/src/tools/cancel-job.ts b/packages/coding-agent/src/tools/cancel-job.ts index 224ec4c9a..bd670e39d 100644 --- a/packages/coding-agent/src/tools/cancel-job.ts +++ b/packages/coding-agent/src/tools/cancel-job.ts @@ -6,7 +6,7 @@ import cancelJobDescription from "../prompts/tools/cancel-job.md" with { type: " import type { ToolSession } from "./index"; const cancelJobSchema = Type.Object({ - job_id: Type.String({ description: "Background job ID" }), + job_id: Type.String({ description: "background job id", examples: ["job-1234"] }), }); type CancelJobParams = Static; diff --git a/packages/coding-agent/src/tools/checkpoint.ts b/packages/coding-agent/src/tools/checkpoint.ts index 145a50296..2d3618f42 100644 --- a/packages/coding-agent/src/tools/checkpoint.ts +++ b/packages/coding-agent/src/tools/checkpoint.ts @@ -18,13 +18,13 @@ export interface CheckpointState { } const checkpointSchema = Type.Object({ - goal: Type.String({ description: "What you are investigating and why" }), + goal: Type.String({ description: "investigation goal", examples: ["investigate retry logic"] }), }); type CheckpointParams = Static; const rewindSchema = Type.Object({ - report: Type.String({ description: "Concise investigation findings to retain after rewind" }), + report: Type.String({ description: "investigation findings" }), }); type RewindParams = Static; diff --git a/packages/coding-agent/src/tools/debug.ts b/packages/coding-agent/src/tools/debug.ts index 0e45c11f0..d943f107c 100644 --- a/packages/coding-agent/src/tools/debug.ts +++ b/packages/coding-agent/src/tools/debug.ts @@ -83,51 +83,51 @@ const debugSchema = Type.Object({ "terminate", "sessions", ], - { description: "DAP debugger action" }, + { description: "dap debugger action" }, ), - program: Type.Optional(Type.String({ description: "Program or script path for launch" })), - args: Type.Optional(Type.Array(Type.String(), { description: "Program arguments for launch" })), - adapter: Type.Optional(Type.String({ description: "Debugger adapter override (gdb, lldb-dap, debugpy, dlv)" })), - cwd: Type.Optional(Type.String({ description: "Working directory for launch or attach" })), - file: Type.Optional(Type.String({ description: "Source file for source breakpoints" })), - line: Type.Optional(Type.Number({ description: "1-indexed source line for source breakpoints" })), - function: Type.Optional(Type.String({ description: "Function name for function breakpoints" })), - name: Type.Optional(Type.String({ description: "Variable or data name for data breakpoint info" })), - condition: Type.Optional(Type.String({ description: "Breakpoint condition expression" })), - hit_condition: Type.Optional(Type.String({ description: "Breakpoint hit condition expression" })), - expression: Type.Optional(Type.String({ description: "Expression to evaluate in debugger context" })), - context: Type.Optional(Type.String({ description: "Evaluate context (watch, repl, hover, variables, clipboard)" })), - frame_id: Type.Optional(Type.Number({ description: "Stack frame ID for scopes/evaluate" })), - scope_id: Type.Optional(Type.Number({ description: "Scope variablesReference for variables requests" })), - variable_ref: Type.Optional(Type.Number({ description: "Variable reference for variables requests" })), - pid: Type.Optional(Type.Number({ description: "Process ID for attach" })), - port: Type.Optional(Type.Number({ description: "Port for remote attach when adapter supports it" })), - host: Type.Optional(Type.String({ description: "Host for remote attach when adapter supports it" })), - levels: Type.Optional(Type.Number({ description: "Maximum stack frames to fetch" })), - memory_reference: Type.Optional(Type.String({ description: "Memory reference or address" })), + program: Type.Optional(Type.String({ description: "program path", examples: ["./my_app", "src/main.py"] })), + args: Type.Optional(Type.Array(Type.String(), { description: "program arguments", examples: [["--verbose"]] })), + adapter: Type.Optional(Type.String({ description: "debugger adapter", examples: ["gdb", "lldb-dap", "debugpy", "dlv"] })), + cwd: Type.Optional(Type.String({ description: "working directory", examples: ["src/"] })), + file: Type.Optional(Type.String({ description: "source file", examples: ["src/main.c"] })), + line: Type.Optional(Type.Number({ description: "source line", examples: [42] })), + function: Type.Optional(Type.String({ description: "function name", examples: ["main", "handle_request"] })), + name: Type.Optional(Type.String({ description: "variable or data name", examples: ["counter", "buffer"] })), + condition: Type.Optional(Type.String({ description: "breakpoint condition", examples: ["i == 10", "x > 0"] })), + hit_condition: Type.Optional(Type.String({ description: "hit condition" })), + expression: Type.Optional(Type.String({ description: "expression to evaluate", examples: ["x + 1", "obj.field"] })), + context: Type.Optional(Type.String({ description: "evaluate context", examples: ["watch", "repl", "hover", "variables", "clipboard"] })), + frame_id: Type.Optional(Type.Number({ description: "stack frame id" })), + scope_id: Type.Optional(Type.Number({ description: "scope variables reference" })), + variable_ref: Type.Optional(Type.Number({ description: "variable reference" })), + pid: Type.Optional(Type.Number({ description: "process id for attach", examples: [12345] })), + port: Type.Optional(Type.Number({ description: "remote attach port", examples: [4711] })), + host: Type.Optional(Type.String({ description: "remote attach host", examples: ["127.0.0.1"] })), + levels: Type.Optional(Type.Number({ description: "max stack frames" })), + memory_reference: Type.Optional(Type.String({ description: "memory reference or address", examples: ["0x7ffd1234"] })), instruction_reference: Type.Optional( - Type.String({ description: "Instruction address/reference for instruction breakpoints" }), + Type.String({ description: "instruction address or reference" }), ), - instruction_count: Type.Optional(Type.Number({ description: "Number of instructions to disassemble" })), - instruction_offset: Type.Optional(Type.Number({ description: "Instruction offset for disassembly" })), - count: Type.Optional(Type.Number({ description: "Number of bytes to read from memory" })), - data: Type.Optional(Type.String({ description: "Base64-encoded memory payload for write_memory" })), - data_id: Type.Optional(Type.String({ description: "DAP data breakpoint identifier" })), + instruction_count: Type.Optional(Type.Number({ description: "instructions to disassemble" })), + instruction_offset: Type.Optional(Type.Number({ description: "instruction offset" })), + count: Type.Optional(Type.Number({ description: "bytes to read" })), + data: Type.Optional(Type.String({ description: "base64 memory payload" })), + data_id: Type.Optional(Type.String({ description: "data breakpoint id" })), access_type: Type.Optional( - StringEnum(["read", "write", "readWrite"], { description: "Data breakpoint access type" }), + StringEnum(["read", "write", "readWrite"], { description: "data breakpoint access type" }), ), - command: Type.Optional(Type.String({ description: "Custom DAP request command" })), + command: Type.Optional(Type.String({ description: "custom dap request command" })), arguments: Type.Optional( Type.Record(Type.String(), Type.Any(), { - description: "Arguments object for custom_request", + description: "custom request arguments", }), ), - offset: Type.Optional(Type.Number({ description: "Memory or instruction offset" })), - resolve_symbols: Type.Optional(Type.Boolean({ description: "Resolve symbols during disassembly" })), - allow_partial: Type.Optional(Type.Boolean({ description: "Allow partial writes for write_memory" })), - start_module: Type.Optional(Type.Number({ description: "Modules request start index" })), - module_count: Type.Optional(Type.Number({ description: "Maximum modules to fetch" })), - timeout: Type.Optional(Type.Number({ description: "Per-request timeout in seconds" })), + offset: Type.Optional(Type.Number({ description: "memory or instruction offset" })), + resolve_symbols: Type.Optional(Type.Boolean({ description: "resolve symbols during disassembly" })), + allow_partial: Type.Optional(Type.Boolean({ description: "allow partial writes" })), + start_module: Type.Optional(Type.Number({ description: "modules start index" })), + module_count: Type.Optional(Type.Number({ description: "max modules to fetch" })), + timeout: Type.Optional(Type.Number({ description: "per-request timeout seconds" })), }); export type DebugParams = Static; diff --git a/packages/coding-agent/src/tools/exit-plan-mode.ts b/packages/coding-agent/src/tools/exit-plan-mode.ts index 9ed0394ce..dd91a753a 100644 --- a/packages/coding-agent/src/tools/exit-plan-mode.ts +++ b/packages/coding-agent/src/tools/exit-plan-mode.ts @@ -8,7 +8,7 @@ import { resolvePlanPath } from "./plan-mode-guard"; import { ToolError } from "./tool-errors"; const exitPlanModeSchema = Type.Object({ - title: Type.String({ description: "Final plan title, e.g. WP_MIGRATION_PLAN" }), + title: Type.String({ description: "final plan title", examples: ["WP_MIGRATION_PLAN"] }), }); type ExitPlanModeParams = Static; diff --git a/packages/coding-agent/src/tools/find.ts b/packages/coding-agent/src/tools/find.ts index 5e13fc9e2..b9717596e 100644 --- a/packages/coding-agent/src/tools/find.ts +++ b/packages/coding-agent/src/tools/find.ts @@ -30,11 +30,11 @@ import { toolResult } from "./tool-result"; const findSchema = Type.Object({ pattern: Type.String({ - description: - "Glob pattern including the search path (no separate path param), e.g. 'src/**/*.ts', 'lib/*.json'. Supports comma-separated lists like 'apps/,packages/,phases/'. Simple patterns like '*.ts' recurse from cwd.", + description: "glob including search path", + examples: ["src/**/*.ts", "lib/*.json", "apps/,packages/", "*.ts"], }), - hidden: Type.Optional(Type.Boolean({ description: "Include hidden files and directories", default: true })), - limit: Type.Optional(Type.Number({ description: "Max results", default: 1000 })), + hidden: Type.Optional(Type.Boolean({ description: "include hidden files", default: true })), + limit: Type.Optional(Type.Number({ description: "max results", default: 1000 })), }); export type FindToolInput = Static; diff --git a/packages/coding-agent/src/tools/gemini-image.ts b/packages/coding-agent/src/tools/gemini-image.ts index 58aa76a61..6855fc016 100644 --- a/packages/coding-agent/src/tools/gemini-image.ts +++ b/packages/coding-agent/src/tools/gemini-image.ts @@ -36,17 +36,19 @@ interface ImageApiKey { const responseModalitySchema = StringEnum(["IMAGE", "TEXT"]); const aspectRatioSchema = StringEnum(["1:1", "3:4", "4:3", "9:16", "16:9"], { - description: "Aspect ratio (1:1, 3:4, 4:3, 9:16, 16:9).", + description: "aspect ratio", + examples: ["1:1", "3:4", "16:9"], }); const imageSizeSchema = StringEnum(["1024x1024", "1536x1024", "1024x1536"], { - description: "Image size, mainly for gemini-3-pro-image-preview.", + description: "image size", + examples: ["1024x1024", "1536x1024"], }); const inputImageSchema = Type.Object( { - path: Type.Optional(Type.String({ description: "Path to an input image file." })), - data: Type.Optional(Type.String({ description: "Base64 image data or a data: URL." })), - mime_type: Type.Optional(Type.String({ description: "Required for raw base64 data." })), + path: Type.Optional(Type.String({ description: "input image path" })), + data: Type.Optional(Type.String({ description: "base64 image data" })), + mime_type: Type.Optional(Type.String({ description: "mime type" })), }, { additionalProperties: false }, ); @@ -54,55 +56,56 @@ const inputImageSchema = Type.Object( const baseImageSchema = Type.Object( { subject: Type.String({ - description: - "Main subject with key descriptors (e.g., 'A stoic robot barista with glowing blue optics', 'A weathered lighthouse on a rocky cliff').", + description: "main subject", + examples: ["a stoic robot barista", "a weathered lighthouse"], }), action: Type.Optional( Type.String({ - description: "What the subject is doing (e.g., 'pouring latte art', 'standing against crashing waves').", + description: "what subject is doing", + examples: ["pouring latte art", "standing against waves"], }), ), scene: Type.Optional( Type.String({ - description: - "Location or environment (e.g., 'in a futuristic café on Mars', 'during a violent thunderstorm at dusk').", + description: "location or environment", + examples: ["futuristic café on mars", "thunderstorm at dusk"], }), ), composition: Type.Optional( Type.String({ - description: - "Camera angle, framing, depth of field (e.g., 'low-angle close-up, shallow depth of field', 'wide establishing shot').", + description: "camera angle and framing", + examples: ["low-angle close-up", "wide establishing shot"], }), ), lighting: Type.Optional( Type.String({ - description: - "Lighting setup and mood (e.g., 'warm rim lighting', 'golden hour backlight', 'hard noon shadows').", + description: "lighting setup", + examples: ["warm rim lighting", "golden hour backlight"], }), ), style: Type.Optional( Type.String({ - description: - "Artistic style, mood, color grading, camera (e.g., 'film noir mood, cinematic color grading', 'Studio Ghibli watercolor', 'photorealistic').", + description: "artistic style", + examples: ["film noir", "studio ghibli watercolor", "photorealistic"], }), ), text: Type.Optional( Type.String({ - description: - "Text to render in image with specs: exact wording in quotes, font style, color, placement (e.g., 'Headline \"URBAN EXPLORER\" in bold white sans-serif at top center').", + description: "text to render", + examples: ["headline 'urban explorer' top center"], }), ), changes: Type.Optional( Type.Array(Type.String(), { - description: - "For edits: specific changes to make, as well as, what to keep unchanged (e.g., ['Change the tie to green', 'Remove the car in background']). Use with input_images.", + description: "edits to make", + examples: [["change tie to green", "remove car"]], }), ), aspect_ratio: Type.Optional(aspectRatioSchema), image_size: Type.Optional(imageSizeSchema), input: Type.Optional( Type.Array(inputImageSchema, { - description: "Optional input images for edits or variations.", + description: "input images", }), ), }, diff --git a/packages/coding-agent/src/tools/gh.ts b/packages/coding-agent/src/tools/gh.ts index d9f0a17c2..3dd35b0a2 100644 --- a/packages/coding-agent/src/tools/gh.ts +++ b/packages/coding-agent/src/tools/gh.ts @@ -138,70 +138,62 @@ const JOB_FAILURE_CONCLUSIONS = new Set(["failure", "timed_out", "cancelled", "a const ghRepoViewSchema = Type.Object({ repo: Type.Optional( Type.String({ - description: "Repository in OWNER/REPO format. Defaults to the current GitHub repository context.", + description: "owner/repo", + examples: ["facebook/react"], }), ), - branch: Type.Optional(Type.String({ description: "Branch name to inspect instead of the default branch." })), + branch: Type.Optional(Type.String({ description: "branch to inspect", examples: ["main", "develop"] })), }); const ghIssueViewSchema = Type.Object({ - issue: Type.String({ description: "Issue number or full GitHub issue URL." }), + issue: Type.String({ description: "issue number or url", examples: ["123", "https://github.com/owner/repo/issues/123"] }), repo: Type.Optional( - Type.String({ description: "Repository in OWNER/REPO format. Omit when passing a full issue URL." }), + Type.String({ description: "owner/repo", examples: ["facebook/react"] }), ), - comments: Type.Optional(Type.Boolean({ description: "Include issue comments.", default: true })), + comments: Type.Optional(Type.Boolean({ description: "include issue comments", default: true })), }); const ghPrViewSchema = Type.Object({ pr: Type.Optional( - Type.String({ - description: - "Pull request number, full GitHub pull request URL, or branch name. Defaults to the current branch PR.", - }), + Type.String({ description: "pr number, url, or branch", examples: ["123", "feature-branch"] }), ), repo: Type.Optional( - Type.String({ description: "Repository in OWNER/REPO format. Omit when passing a full pull request URL." }), + Type.String({ description: "owner/repo", examples: ["facebook/react"] }), ), - comments: Type.Optional(Type.Boolean({ description: "Include pull request comments.", default: true })), + comments: Type.Optional(Type.Boolean({ description: "include pr comments", default: true })), }); const ghPrDiffSchema = Type.Object({ pr: Type.Optional( - Type.String({ - description: - "Pull request number, full GitHub pull request URL, or branch name. Defaults to the current branch PR.", - }), + Type.String({ description: "pr number, url, or branch", examples: ["123", "feature-branch"] }), ), repo: Type.Optional( - Type.String({ description: "Repository in OWNER/REPO format. Omit when passing a full pull request URL." }), + Type.String({ description: "owner/repo", examples: ["facebook/react"] }), ), nameOnly: Type.Optional( - Type.Boolean({ description: "Return only changed file names instead of unified diff output." }), + Type.Boolean({ description: "return file names only" }), ), exclude: Type.Optional( - Type.Array(Type.String({ description: "Glob pattern for files to exclude from the diff." }), { - description: "File globs to exclude from the diff output.", + Type.Array(Type.String({ description: "glob to exclude" }), { + description: "file globs to exclude", }), ), }); const ghPrCheckoutSchema = Type.Object({ pr: Type.Optional( - Type.String({ - description: - "Pull request number, full GitHub pull request URL, or branch name. Defaults to the current branch PR.", - }), + Type.String({ description: "pr number, url, or branch", examples: ["123", "feature-branch"] }), ), repo: Type.Optional( - Type.String({ description: "Repository in OWNER/REPO format. Omit when passing a full pull request URL." }), + Type.String({ description: "owner/repo", examples: ["facebook/react"] }), ), - branch: Type.Optional(Type.String({ description: "Local branch name to create or reuse (default: pr-)." })), + branch: Type.Optional(Type.String({ description: "local branch name", examples: ["main", "develop"] })), worktree: Type.Optional( - Type.String({ description: "Worktree path to create. Defaults to /.worktrees/." }), + Type.String({ description: "worktree path" }), ), force: Type.Optional( Type.Boolean({ - description: "Reset an existing local branch to the PR head when it is not already checked out elsewhere.", + description: "reset existing local branch", }), ), }); @@ -209,38 +201,37 @@ const ghPrCheckoutSchema = Type.Object({ const ghPrPushSchema = Type.Object({ branch: Type.Optional( Type.String({ - description: "Local branch name to push. Defaults to the current checked-out git branch.", + description: "local branch name", + examples: ["main", "develop"], }), ), - forceWithLease: Type.Optional(Type.Boolean({ description: "Use --force-with-lease when pushing the PR branch." })), + forceWithLease: Type.Optional(Type.Boolean({ description: "force-with-lease push" })), }); const ghSearchIssuesSchema = Type.Object({ - query: Type.String({ description: "GitHub issue search query. Supports GitHub search syntax." }), - repo: Type.Optional(Type.String({ description: "Repository in OWNER/REPO format to scope the search." })), - limit: Type.Optional(Type.Number({ description: "Maximum results to return (max: 50).", default: 10 })), + query: Type.String({ description: "issue search query", examples: ["is:open label:bug"] }), + repo: Type.Optional(Type.String({ description: "scope to owner/repo" })), + limit: Type.Optional(Type.Number({ description: "max results", default: 10 })), }); const ghSearchPrsSchema = Type.Object({ - query: Type.String({ description: "GitHub pull request search query. Supports GitHub search syntax." }), - repo: Type.Optional(Type.String({ description: "Repository in OWNER/REPO format to scope the search." })), - limit: Type.Optional(Type.Number({ description: "Maximum results to return (max: 50).", default: 10 })), + query: Type.String({ description: "pr search query", examples: ["is:open label:bug"] }), + repo: Type.Optional(Type.String({ description: "scope to owner/repo" })), + limit: Type.Optional(Type.Number({ description: "max results", default: 10 })), }); const ghRunWatchSchema = Type.Object({ run: Type.Optional( - Type.String({ - description: - "GitHub Actions run ID or full run URL. Omitting this watches the workflow runs for the current HEAD commit on the selected branch.", - }), + Type.String({ description: "actions run id or url", examples: ["123456"] }), ), branch: Type.Optional( Type.String({ - description: "Branch to inspect when omitting `run`. Defaults to the current checked-out git branch.", + description: "branch to inspect", + examples: ["main", "develop"], }), ), tail: Type.Optional( - Type.Number({ description: "Number of log lines to include per failed job (max: 200).", default: 15 }), + Type.Number({ description: "log lines per failed job", default: 15 }), ), }); diff --git a/packages/coding-agent/src/tools/grep.ts b/packages/coding-agent/src/tools/grep.ts index 55b00d06e..037393037 100644 --- a/packages/coding-agent/src/tools/grep.ts +++ b/packages/coding-agent/src/tools/grep.ts @@ -31,17 +31,17 @@ import { ToolError } from "./tool-errors"; import { toolResult } from "./tool-result"; const grepSchema = Type.Object({ - pattern: Type.String({ description: "Regex pattern to search for" }), - path: Type.Optional(Type.String({ description: "File or directory to search (default: cwd)" })), - glob: Type.Optional(Type.String({ description: "Filter files by glob pattern (e.g., '*.js')" })), - type: Type.Optional(Type.String({ description: "Filter by file type (e.g., js, py, rust)" })), - i: Type.Optional(Type.Boolean({ description: "Case-insensitive search", default: false })), - pre: Type.Optional(Type.Number({ description: "Lines of context before matches" })), - post: Type.Optional(Type.Number({ description: "Lines of context after matches" })), - multiline: Type.Optional(Type.Boolean({ description: "Enable multiline matching" })), - gitignore: Type.Optional(Type.Boolean({ description: "Respect .gitignore files during search", default: true })), - limit: Type.Optional(Type.Number({ description: "Limit output to first N matches", default: 20 })), - offset: Type.Optional(Type.Number({ description: "Skip first N entries before applying limit", default: 0 })), + pattern: Type.String({ description: "regex pattern", examples: ["function\\s+\\w+", "TODO"] }), + path: Type.Optional(Type.String({ description: "path to search", examples: ["src/", "src/foo.ts"] })), + glob: Type.Optional(Type.String({ description: "glob filter", examples: ["*.js"] })), + type: Type.Optional(Type.String({ description: "file type filter", examples: ["js", "py", "rust"] })), + i: Type.Optional(Type.Boolean({ description: "case-insensitive search", default: false })), + pre: Type.Optional(Type.Number({ description: "lines before matches" })), + post: Type.Optional(Type.Number({ description: "lines after matches" })), + multiline: Type.Optional(Type.Boolean({ description: "multiline matching" })), + gitignore: Type.Optional(Type.Boolean({ description: "respect gitignore", default: true })), + limit: Type.Optional(Type.Number({ description: "max matches", default: 20 })), + offset: Type.Optional(Type.Number({ description: "skip first n matches", default: 0 })), }); export type GrepToolInput = Static; diff --git a/packages/coding-agent/src/tools/inspect-image.ts b/packages/coding-agent/src/tools/inspect-image.ts index 2f246811c..bcb58fcc6 100644 --- a/packages/coding-agent/src/tools/inspect-image.ts +++ b/packages/coding-agent/src/tools/inspect-image.ts @@ -16,8 +16,8 @@ import { ToolError } from "./tool-errors"; const inspectImageSchema = Type.Object( { - path: Type.String({ description: "Filesystem path to an image" }), - question: Type.String({ description: "Question to ask about the image" }), + path: Type.String({ description: "image path", examples: ["image.png"] }), + question: Type.String({ description: "question about image", examples: ["What is in this image?"] }), }, { additionalProperties: false }, ); diff --git a/packages/coding-agent/src/tools/notebook.ts b/packages/coding-agent/src/tools/notebook.ts index 11ebd052f..ad0a21851 100644 --- a/packages/coding-agent/src/tools/notebook.ts +++ b/packages/coding-agent/src/tools/notebook.ts @@ -13,14 +13,16 @@ import { formatCount, formatErrorMessage, PREVIEW_LIMITS } from "./render-utils" const notebookSchema = Type.Object({ action: StringEnum(["edit", "insert", "delete"], { - description: "Action to perform on the notebook cell", + description: "cell action", + examples: ["edit", "insert", "delete"], }), - notebook_path: Type.String({ description: "Path to the .ipynb file" }), - cell_index: Type.Number({ description: "0-based index of the cell to operate on" }), - content: Type.Optional(Type.String({ description: "New cell content (required for edit/insert)" })), + notebook_path: Type.String({ description: "notebook path", examples: ["analysis.ipynb"] }), + cell_index: Type.Number({ description: "cell index", examples: [0, 1] }), + content: Type.Optional(Type.String({ description: "new cell content" })), cell_type: Type.Optional( StringEnum(["code", "markdown"], { - description: "Cell type for insert (default: code)", + description: "cell type", + examples: ["code", "markdown"], }), ), }); diff --git a/packages/coding-agent/src/tools/poll-tool.ts b/packages/coding-agent/src/tools/poll-tool.ts index 290b4a21b..14d02061c 100644 --- a/packages/coding-agent/src/tools/poll-tool.ts +++ b/packages/coding-agent/src/tools/poll-tool.ts @@ -8,7 +8,8 @@ import type { ToolSession } from "./index"; const pollSchema = Type.Object({ jobs: Type.Optional( Type.Array(Type.String(), { - description: "Specific job IDs to wait for. If omitted, waits for any running job.", + description: "job ids to wait for", + examples: [["job-1234"]], }), ), }); diff --git a/packages/coding-agent/src/tools/python.ts b/packages/coding-agent/src/tools/python.ts index 719ae9623..477b73c35 100644 --- a/packages/coding-agent/src/tools/python.ts +++ b/packages/coding-agent/src/tools/python.ts @@ -47,14 +47,14 @@ function groupPreludeHelpers(helpers: PreludeHelper[]): PreludeCategory[] { export const pythonSchema = Type.Object({ cells: Type.Array( Type.Object({ - code: Type.String({ description: "Python code to execute" }), - title: Type.Optional(Type.String({ description: "Cell label, e.g. 'imports', 'helper'" })), + code: Type.String({ description: "python code", examples: ["print('hello')", "import json"] }), + title: Type.Optional(Type.String({ description: "cell label", examples: ["imports", "helper"] })), }), - { description: "Cells to execute sequentially in persistent kernel" }, + { description: "cells to execute" }, ), - timeout: Type.Optional(Type.Number({ description: "Timeout in seconds", default: 30 })), - cwd: Type.Optional(Type.String({ description: "Working directory (default: cwd)" })), - reset: Type.Optional(Type.Boolean({ description: "Restart kernel before execution" })), + timeout: Type.Optional(Type.Number({ description: "timeout in seconds", default: 30 })), + cwd: Type.Optional(Type.String({ description: "working directory", examples: ["src/"] })), + reset: Type.Optional(Type.Boolean({ description: "restart kernel" })), }); export type PythonToolParams = Static; diff --git a/packages/coding-agent/src/tools/read.ts b/packages/coding-agent/src/tools/read.ts index cd6575207..5278eaf6c 100644 --- a/packages/coding-agent/src/tools/read.ts +++ b/packages/coding-agent/src/tools/read.ts @@ -369,9 +369,9 @@ function prependSuffixResolutionNotice(text: string, suffixResolution?: { from: } const readSchema = Type.Object({ - path: Type.String({ description: "Path or URL to read" }), - sel: Type.Optional(Type.String({ description: "Selector" })), - timeout: Type.Optional(Type.Number({ description: "Timeout in seconds", default: 20 })), + path: Type.String({ description: "path or url", examples: ["src/foo.ts", "https://example.com"] }), + sel: Type.Optional(Type.String({ description: "line range or mode", examples: ["L50", "L50-L120", "raw"] })), + timeout: Type.Optional(Type.Number({ description: "timeout in seconds", default: 20 })), }); export type ReadToolInput = Static; diff --git a/packages/coding-agent/src/tools/render-mermaid.ts b/packages/coding-agent/src/tools/render-mermaid.ts index 36a8195ba..ca029a493 100644 --- a/packages/coding-agent/src/tools/render-mermaid.ts +++ b/packages/coding-agent/src/tools/render-mermaid.ts @@ -5,7 +5,7 @@ import renderMermaidDescription from "../prompts/tools/render-mermaid.md" with { import type { ToolSession } from "./index"; const renderMermaidSchema = Type.Object({ - mermaid: Type.String({ description: "Mermaid graph source text" }), + mermaid: Type.String({ description: "mermaid source", examples: ["graph TD; A-->B"] }), config: Type.Optional( Type.Object({ useAscii: Type.Optional(Type.Boolean()), diff --git a/packages/coding-agent/src/tools/report-tool-issue.ts b/packages/coding-agent/src/tools/report-tool-issue.ts index c3e5b377f..4329b42c3 100644 --- a/packages/coding-agent/src/tools/report-tool-issue.ts +++ b/packages/coding-agent/src/tools/report-tool-issue.ts @@ -14,8 +14,8 @@ import type { Settings } from ".."; import type { ToolSession } from "./index"; const ReportToolIssueParams = Type.Object({ - tool: Type.String({ description: "Name of the tool that behaved unexpectedly" }), - report: Type.String({ description: "Description of what was unexpected about the tool's behavior" }), + tool: Type.String({ description: "tool name", examples: ["bash", "read"] }), + report: Type.String({ description: "unexpected behavior" }), }); export function isAutoQaEnabled(settings?: Settings): boolean { diff --git a/packages/coding-agent/src/tools/resolve.ts b/packages/coding-agent/src/tools/resolve.ts index 0c40c06fa..dbd6b9e5d 100644 --- a/packages/coding-agent/src/tools/resolve.ts +++ b/packages/coding-agent/src/tools/resolve.ts @@ -13,7 +13,7 @@ import { ToolError } from "./tool-errors"; const resolveSchema = Type.Object({ action: Type.Union([Type.Literal("apply"), Type.Literal("discard")]), - reason: Type.String({ description: "Why you're applying or discarding" }), + reason: Type.String({ description: "reason for action", examples: ["approved by user"] }), }); type ResolveParams = Static; diff --git a/packages/coding-agent/src/tools/review.ts b/packages/coding-agent/src/tools/review.ts index a15df2444..edbc4e915 100644 --- a/packages/coding-agent/src/tools/review.ts +++ b/packages/coding-agent/src/tools/review.ts @@ -55,22 +55,24 @@ function getPriorityDisplay( // report_finding schema const ReportFindingParams = Type.Object({ title: Type.String({ - description: "≤80 chars, imperative, prefixed with [P0-P3]. E.g., '[P1] Un-padding slices along wrong dimension'", + description: "prefixed imperative title", + examples: ["[P1] un-padding wrong dimension"], }), body: Type.String({ - description: "Markdown explaining why this is a problem. One paragraph max.", + description: "problem explanation", }), priority: StringEnum(["P0", "P1", "P2", "P3"], { - description: "0=P0 (critical), 1=P1 (urgent), 2=P2 (normal), 3=P3 (low)", + description: "priority 0-3", }), confidence: Type.Number({ minimum: 0, maximum: 1, - description: "Confidence score 0.0-1.0", + description: "confidence score", + examples: [0.0, 0.5, 1.0], }), - file_path: Type.String({ description: "Path to the file" }), - line_start: Type.Number({ description: "Start line of the issue" }), - line_end: Type.Number({ description: "End line of the issue" }), + file_path: Type.String({ description: "file path" }), + line_start: Type.Number({ description: "start line" }), + line_end: Type.Number({ description: "end line" }), }); interface ReportFindingDetails { diff --git a/packages/coding-agent/src/tools/search-tool-bm25.ts b/packages/coding-agent/src/tools/search-tool-bm25.ts index a3dceb2a9..c4c33e53c 100644 --- a/packages/coding-agent/src/tools/search-tool-bm25.ts +++ b/packages/coding-agent/src/tools/search-tool-bm25.ts @@ -25,9 +25,9 @@ const MATCH_LABEL_LEN = 72; const MATCH_DESCRIPTION_LEN = 96; const searchToolBm25Schema = Type.Object({ - query: Type.String({ description: "Search query for hidden MCP tool metadata" }), + query: Type.String({ description: "mcp search query", examples: ["kubernetes pod", "image processing"] }), limit: Type.Optional( - Type.Integer({ description: "Max matching tools to activate and return (default 8)", minimum: 1 }), + Type.Integer({ description: "max matches", minimum: 1 }), ), }); diff --git a/packages/coding-agent/src/tools/ssh.ts b/packages/coding-agent/src/tools/ssh.ts index 0b38912e7..1b88a2c00 100644 --- a/packages/coding-agent/src/tools/ssh.ts +++ b/packages/coding-agent/src/tools/ssh.ts @@ -22,10 +22,10 @@ import { toolResult } from "./tool-result"; import { clampTimeout } from "./tool-timeouts"; const sshSchema = Type.Object({ - host: Type.String({ description: "Host name from managed SSH config or discovered ssh.json files" }), - command: Type.String({ description: "Command to execute on the remote host" }), - cwd: Type.Optional(Type.String({ description: "Remote working directory (optional)" })), - timeout: Type.Optional(Type.Number({ description: "Timeout in seconds", default: 60 })), + host: Type.String({ description: "ssh host", examples: ["my-server", "prod-1"] }), + command: Type.String({ description: "remote command", examples: ["ls -la", "uptime"] }), + cwd: Type.Optional(Type.String({ description: "remote working directory", examples: ["/var/log"] })), + timeout: Type.Optional(Type.Number({ description: "timeout in seconds", default: 60 })), }); export interface SSHToolDetails { diff --git a/packages/coding-agent/src/tools/todo-write.ts b/packages/coding-agent/src/tools/todo-write.ts index 39798118b..9cafcc30b 100644 --- a/packages/coding-agent/src/tools/todo-write.ts +++ b/packages/coding-agent/src/tools/todo-write.ts @@ -43,41 +43,41 @@ export interface TodoWriteToolDetails { // ============================================================================= const InputTask = Type.Object({ - content: Type.String({ description: "Task description" }), + content: Type.String({ description: "task description", examples: ["Add unit tests"] }), status: Type.Optional( StringEnum(["pending", "in_progress", "completed", "abandoned"] as const, { - description: "Task status", + description: "task status", }), ), details: Type.Optional( - Type.String({ description: "Implementation details, file paths, and specifics (shown only when active)" }), + Type.String({ description: "implementation details" }), ), }); const InputPhase = Type.Object({ - name: Type.String({ description: "Phase name" }), + name: Type.String({ description: "phase name", examples: ["Investigation", "Implementation"] }), tasks: Type.Optional(Type.Array(InputTask)), }); const AddNoteEntry = Type.Object({ - id: Type.String({ description: "Task ID, e.g. task-3" }), - notes: Type.String({ description: "Notes to append" }), + id: Type.String({ description: "task id", examples: ["task-3"] }), + notes: Type.String({ description: "notes to append" }), }); const AddTaskEntry = Type.Object({ - phase: Type.String({ description: "Phase name or ID" }), - content: Type.String({ description: "Task description" }), - details: Type.Optional(Type.String({ description: "Implementation details, file paths, and specifics" })), + phase: Type.String({ description: "phase name or id", examples: ["Investigation", "phase-1"] }), + content: Type.String({ description: "task description", examples: ["Add unit tests"] }), + details: Type.Optional(Type.String({ description: "implementation details" })), }); const todoWriteSchema = Type.Object({ - phases: Type.Optional(Type.Array(InputPhase, { description: "Replace entire todo list with these phases" })), - start: Type.Optional(Type.String({ description: "Task ID to start, e.g. task-3" })), - complete: Type.Optional(Type.Array(Type.String(), { description: "Task IDs to mark completed" })), - abandon: Type.Optional(Type.Array(Type.String(), { description: "Task IDs to mark abandoned" })), - remove: Type.Optional(Type.Array(Type.String(), { description: "Task IDs to remove" })), - add_notes: Type.Optional(Type.Array(AddNoteEntry, { description: "Notes to append to tasks" })), - add_tasks: Type.Optional(Type.Array(AddTaskEntry, { description: "Tasks to add" })), + phases: Type.Optional(Type.Array(InputPhase, { description: "replace todo list" })), + start: Type.Optional(Type.String({ description: "task id to start", examples: ["task-3"] })), + complete: Type.Optional(Type.Array(Type.String(), { description: "task ids to complete" })), + abandon: Type.Optional(Type.Array(Type.String(), { description: "task ids to abandon" })), + remove: Type.Optional(Type.Array(Type.String(), { description: "task ids to remove" })), + add_notes: Type.Optional(Type.Array(AddNoteEntry, { description: "notes to append" })), + add_tasks: Type.Optional(Type.Array(AddTaskEntry, { description: "tasks to add" })), add_phase: Type.Optional(InputPhase), }); diff --git a/packages/coding-agent/src/tools/vim.ts b/packages/coding-agent/src/tools/vim.ts index f5502dd85..6d4cb6c71 100644 --- a/packages/coding-agent/src/tools/vim.ts +++ b/packages/coding-agent/src/tools/vim.ts @@ -38,28 +38,27 @@ const utf8Decoder = new TextDecoder("utf-8", { fatal: true }); const vimStepSchema = Type.Object({ kbd: Type.Array(Type.String(), { - description: "Vim key sequences ONLY (e.g. ggdGi, 3Go, dd). NEVER put file content here — use insert for text.", + description: "vim key sequences", + examples: [["ggdGi"], ["3Go"], ["dd"]], }), insert: Type.Optional( Type.String({ - description: - "Raw text to type into the buffer. kbd must leave INSERT mode active first (e.g. via o, O, i, cc).", + description: "raw text to insert", + examples: ["hello world"], }), ), }); const vimSchema = Type.Object({ - file: Type.String({ description: "File path to edit." }), + file: Type.String({ description: "file path", examples: ["src/foo.ts"] }), steps: Type.Optional( Type.Array(vimStepSchema, { - description: - "Ordered editing steps. Each step executes kbd sequences, then optionally inserts text. INSERT mode is auto-exited between steps.", + description: "editing steps", }), ), pause: Type.Optional( Type.Boolean({ - description: - "Advanced: skip auto-save after the last step. Rarely needed. Omit or set false for normal use — edits auto-save.", + description: "skip auto-save", }), ), }); diff --git a/packages/coding-agent/src/tools/write.ts b/packages/coding-agent/src/tools/write.ts index 7a789f517..33d60e1a5 100644 --- a/packages/coding-agent/src/tools/write.ts +++ b/packages/coding-agent/src/tools/write.ts @@ -44,8 +44,8 @@ import { ToolError } from "./tool-errors"; import { toolResult } from "./tool-result"; const writeSchema = Type.Object({ - path: Type.String({ description: "Path to the file to write" }), - content: Type.String({ description: "Content to write to the file" }), + path: Type.String({ description: "file path", examples: ["src/new.ts"] }), + content: Type.String({ description: "file content" }), }); export type WriteToolInput = Static; diff --git a/packages/coding-agent/src/tools/yield.ts b/packages/coding-agent/src/tools/yield.ts index b9b076d2d..877dbfde4 100644 --- a/packages/coding-agent/src/tools/yield.ts +++ b/packages/coding-agent/src/tools/yield.ts @@ -59,15 +59,15 @@ export class YieldTool implements AgentTool { Type.Object( { result: Type.Union([ - Type.Object({ data: dataSchema }, { description: "Successfully completed the task" }), + Type.Object({ data: dataSchema }, { description: "task succeeded" }), Type.Object({ - error: Type.String({ description: "Error message when the task cannot be completed" }), + error: Type.String({ description: "error message" }), }), ]), }, { additionalProperties: false, - description: "Submit either `data` for success or `error` for failure", + description: "submit data or error", }, ) as TSchema; diff --git a/packages/coding-agent/test/core/hashline.test.ts b/packages/coding-agent/test/core/hashline.test.ts index 76b9116b3..3319ff1c3 100644 --- a/packages/coding-agent/test/core/hashline.test.ts +++ b/packages/coding-agent/test/core/hashline.test.ts @@ -28,7 +28,7 @@ function makeTag(line: number, content: string): Anchor { /** Returns a valid bigram that's guaranteed NOT to equal the real hash of `(line, content)`. */ function staleBigramFor(line: number, content: string): string { const real = computeLineHash(line, content); - const idx = HASHLINE_BIGRAMS.indexOf(real); + const idx = HASHLINE_BIGRAMS.indexOf(real as (typeof HASHLINE_BIGRAMS)[number]); return HASHLINE_BIGRAMS[(idx + 1) % HASHLINE_BIGRAMS_COUNT]; }