diff --git a/crates/tui/assets/skills/delegate/SKILL.md b/crates/tui/assets/skills/delegate/SKILL.md index 8d7ff4675f..74f90878b3 100644 --- a/crates/tui/assets/skills/delegate/SKILL.md +++ b/crates/tui/assets/skills/delegate/SKILL.md @@ -32,7 +32,7 @@ Do not delegate tiny one-step tasks, ambiguous product decisions, destructive op Use `agent` for a focused child run. Launch independent children together so they can run in parallel. -Prefer provider-neutral `model_strength` over hardcoded model ids — `type: "explore"` already defaults to `model_strength: "faster"` (the cheaper same-family sibling), so for read-only exploration you can usually omit it entirely: +Prefer provider-neutral `model_strength` over hardcoded model ids. Children inherit the active model by default (`model_strength: "same"`), so pass `model_strength: "faster"` explicitly for read-only exploration that can use the cheaper same-family sibling: ```json { diff --git a/crates/tui/assets/skills/feishu/SKILL.md b/crates/tui/assets/skills/feishu/SKILL.md index 93b696037f..8930bc8a17 100644 --- a/crates/tui/assets/skills/feishu/SKILL.md +++ b/crates/tui/assets/skills/feishu/SKILL.md @@ -35,8 +35,8 @@ Use this skill when the user asks for Feishu, Lark, or "飞书" integration work configured. 4. For MCP, build or configure a server that exposes narrow tools such as `send_message`, `read_doc`, `append_sheet_row`, or `query_bitable`. -5. Register the MCP server with `deepseek mcp add`, then run - `deepseek mcp validate` and `deepseek mcp tools`. +5. Register the MCP server with `codewhale mcp add`, then run + `codewhale mcp validate` and `codewhale mcp tools`. 6. Verify with a dry run, sandbox document, or read-back call before sending externally visible messages. diff --git a/crates/tui/assets/skills/fleet-manager/SKILL.md b/crates/tui/assets/skills/fleet-manager/SKILL.md index 8947d3ba2a..0a9680fc1e 100644 --- a/crates/tui/assets/skills/fleet-manager/SKILL.md +++ b/crates/tui/assets/skills/fleet-manager/SKILL.md @@ -14,8 +14,8 @@ and leave a ledgered receipt or a safe escalation draft. ## Authority Boundary - Prefer typed fleet surfaces over shell spelunking: `codewhale fleet status`, - `inspect`, `logs`, `artifacts`, `interrupt`, `restart`, `stop`, and the - Runtime API fleet endpoints. + `inspect`, `logs`, `artifacts`, `interrupt`, `restart`, `resume`, `stop`, + and the Runtime API fleet endpoints. - Do not read `.codewhale/fleet.jsonl`, host logs, or remote files directly unless the typed command or API is missing required evidence. - Do not send Slack, webhook, PagerDuty, email, or chat messages unless the @@ -44,6 +44,8 @@ and leave a ledgered receipt or a safe escalation draft. conflict between artifacts and verifier. 5. Choose one typed action: - transient and retry budget remains: `codewhale fleet restart `. + - stale or orphaned run with no live manager: `codewhale fleet resume + `. - transient but unsafe to retry: draft escalation and mark needs-human. - task failure: preserve artifacts, summarize the failure, and avoid restart unless the task spec says retrying can produce new evidence. diff --git a/crates/tui/assets/skills/mcp-builder/SKILL.md b/crates/tui/assets/skills/mcp-builder/SKILL.md index 1408b4d17f..ed29e70162 100644 --- a/crates/tui/assets/skills/mcp-builder/SKILL.md +++ b/crates/tui/assets/skills/mcp-builder/SKILL.md @@ -18,20 +18,20 @@ or tool integration. default unless the server explicitly requires something else. - Add timeouts and clear error messages around external APIs. -## DeepSeek Setup +## Codewhale Setup Common commands: ```bash -deepseek mcp init -deepseek mcp add my-server --command node --arg server.js -deepseek mcp add remote-server --url http://127.0.0.1:3000/mcp -deepseek mcp list -deepseek mcp validate -deepseek mcp tools +codewhale mcp init +codewhale mcp add my-server --command node --arg server.js +codewhale mcp add remote-server --url http://127.0.0.1:3000/mcp +codewhale mcp list +codewhale mcp validate +codewhale mcp tools ``` -HTTP/SSE entries can include per-server headers in `~/.deepseek/mcp.json` when +HTTP/SSE entries can include per-server headers in `~/.codewhale/mcp.json` when credentials or custom routing headers are required. ## Workflow @@ -39,6 +39,6 @@ credentials or custom routing headers are required. 1. Define the service boundary and the minimum useful tools. 2. Choose transport and credential handling. 3. Implement the server using a maintained MCP SDK when available. -4. Add the server with `deepseek mcp add` or edit `~/.deepseek/mcp.json`. -5. Run `deepseek mcp validate`, then `deepseek mcp tools`. +4. Add the server with `codewhale mcp add` or edit `~/.codewhale/mcp.json`. +5. Run `codewhale mcp validate`, then `codewhale mcp tools`. 6. Test one happy path and one failure path before calling it done. diff --git a/crates/tui/assets/skills/pdf/SKILL.md b/crates/tui/assets/skills/pdf/SKILL.md index 098cdf88ff..e9a69a240e 100644 --- a/crates/tui/assets/skills/pdf/SKILL.md +++ b/crates/tui/assets/skills/pdf/SKILL.md @@ -13,7 +13,7 @@ Use this skill for any task where a PDF is the primary input or output. watermark, redact, fill forms, encrypt/decrypt, or create. 2. Preserve originals. Write outputs with explicit names. 3. Use the most reliable available tool: - - DeepSeek's file reader for basic text extraction from PDFs + - the built-in `read_file` tool for basic text extraction from PDFs - `pdftotext`, `pdfinfo`, `qpdf`, or `mutool` when installed - Python libraries such as `pypdf`, `pdfplumber`, `PyMuPDF`, or `reportlab` when available diff --git a/crates/tui/assets/skills/plugin-creator/SKILL.md b/crates/tui/assets/skills/plugin-creator/SKILL.md index d3e4a1501a..a641138183 100644 --- a/crates/tui/assets/skills/plugin-creator/SKILL.md +++ b/crates/tui/assets/skills/plugin-creator/SKILL.md @@ -5,18 +5,22 @@ description: Scaffold codewhale local plugin directories and activation notes. U # Plugin Creator -Use this skill when a user wants a DeepSeek plugin scaffold or a plan for a +Use this skill when a user wants a codewhale plugin scaffold or a plan for a plugin-style extension. -DeepSeek plugins are currently a documented packaging convention, not an -auto-loaded runtime. Be explicit about that. A plugin becomes active only when -it is referenced from a skill, hook, MCP server, or future plugin loader. +Codewhale recognizes two plugin shapes under `~/.codewhale/plugins/`. A +`plugin.toml` manifest is auto-discovered (gated by its `[when]` rules) and its +`[mcp_servers]` entries merge into MCP config while the plugin is enabled. The +`PLUGIN.md` layout scaffolded by `codewhale setup --plugins` is a packaging +convention only — it becomes active when referenced from a skill, hook, or MCP +server. Be explicit about which shape you are creating. ## Workflow 1. Pick the location: - - Global user plugin: `~/.deepseek/plugins//` - - Workspace plugin: `/plugins//` + - User plugin (auto-discovered): `~/.codewhale/plugins//` + - Workspace folder (packaging only, not auto-discovered): + `/plugins//` 2. Normalize names to lower-case hyphen-case. 3. Create `PLUGIN.md` with frontmatter: @@ -32,16 +36,33 @@ status: draft What it does, how to enable it, and any scripts or MCP servers it expects. ``` + For the auto-discovered shape, create `plugin.toml` instead: + +```toml +[plugin] +name = "my-plugin" +description = "What this plugin packages or enables." +version = "0.1.0" + +[when] +os = ["linux", "macos", "windows"] +``` + + Add `[skills] path = "skills"` to bundle skills and `[mcp_servers]` entries + for MCP servers the plugin provides. + 4. Add companion folders only when useful: - `skills/` for model instructions - `scripts/` for helpers invoked by a skill or hook - `mcp/` for an MCP server package or config notes - `assets/` for templates, examples, or fixtures -5. Include an activation section in `PLUGIN.md` that says exactly how the user - should turn it on today. -6. Validate by listing the created files and checking that `PLUGIN.md` has - `name` and `description` frontmatter. - -Do not claim that dropping a folder into `plugins/` changes runtime behavior by -itself. If the user asks for a live plugin system, propose a loader design -separately and keep the scaffold honest. +5. Include an activation section that says exactly how the user should turn it + on today (in the `PLUGIN.md` body, or as `plugin.toml` comments). +6. Validate by listing the created files and checking that the manifest + (`PLUGIN.md` frontmatter or `plugin.toml` `[plugin]` table) has `name` and + `description`. + +Dropping a `plugin.toml` folder into `~/.codewhale/plugins/` does register the +plugin and merge its enabled MCP servers; a `PLUGIN.md` folder alone changes +nothing until it is wired through a skill, hook, or MCP server. Keep the +scaffold honest about which behavior applies. diff --git a/crates/tui/assets/skills/skill-creator/SKILL.md b/crates/tui/assets/skills/skill-creator/SKILL.md index f83b4ec678..47029ed549 100644 --- a/crates/tui/assets/skills/skill-creator/SKILL.md +++ b/crates/tui/assets/skills/skill-creator/SKILL.md @@ -23,14 +23,16 @@ Discovery paths, in precedence order: - `/.opencode/skills` - `/.claude/skills` - `/.cursor/skills` +- `/.codewhale/skills` - `~/.agents/skills` - `~/.claude/skills` -- `~/.deepseek/skills` +- `~/.codewhale/skills` +- `~/.deepseek/skills` (legacy fallback) Use skills for model instructions, workflows, and lightweight conventions. Use MCP for live external APIs or durable tools. Use hooks for automatic local -events. Use plugin folders only as packaging/scaffolding until a real plugin -loader exists. +events. Use plugin folders to package related skills, scripts, and MCP servers +behind one `plugin.toml` manifest. ## Minimum Shape @@ -85,7 +87,7 @@ plain single-line values. Use lower-case hyphen-case names. - validation checks - safety notes 6. Add companion files only when they reduce real complexity. -7. Validate by loading the skill through `/skills` or by running the relevant +7. Validate by loading the skill through `/skill ` or by running the relevant skill discovery tests if editing this repository. ## Updating Existing Skills diff --git a/crates/tui/assets/skills/skill-installer/SKILL.md b/crates/tui/assets/skills/skill-installer/SKILL.md index 1d34c043a9..2969cace39 100644 --- a/crates/tui/assets/skills/skill-installer/SKILL.md +++ b/crates/tui/assets/skills/skill-installer/SKILL.md @@ -1,12 +1,12 @@ --- name: skill-installer -description: Install, update, trust, or inspect DeepSeek skills from GitHub or local skill folders. Use when the user asks for available skills or wants a community skill installed. +description: Install, update, trust, or inspect codewhale skills from GitHub or local skill folders. Use when the user asks for available skills or wants a community skill installed. --- # Skill Installer Use this skill when the user wants to find, install, update, trust, or remove a -DeepSeek skill. +codewhale skill. ## Commands @@ -14,7 +14,7 @@ DeepSeek skill. - Activate a skill: `/skill ` - Scaffold a new skill: `/skill new` - Install from GitHub: `/skill install github:/` -- Update installed skills: `/skill update` +- Update an installed skill: `/skill update ` - Remove a skill: `/skill uninstall ` - Trust a skill for script/tool use: `/skill trust ` @@ -24,13 +24,13 @@ DeepSeek skill. - Existing local folder with `SKILL.md` - GitHub repo or registry entry - User request for a new skill scaffold -2. Prefer DeepSeek's native `/skill` commands over ad hoc copying. +2. Prefer the built-in `/skill` commands over ad hoc copying. 3. For GitHub/community skills, inspect the `SKILL.md` before recommending trust. Treat scripts and companion files as untrusted until reviewed. 4. After installing, tell the user to restart the session if the skill does not appear immediately in the available-skills list. 5. If a skill conflicts by name with a workspace skill, explain that workspace - skill directories take precedence over global `~/.deepseek/skills`. + skill directories take precedence over global `~/.codewhale/skills`. Do not execute community skill scripts unless the user explicitly asks and the skill has been reviewed or trusted. diff --git a/crates/tui/src/core/engine/tool_catalog.rs b/crates/tui/src/core/engine/tool_catalog.rs index d4abe6448d..841784146b 100644 --- a/crates/tui/src/core/engine/tool_catalog.rs +++ b/crates/tui/src/core/engine/tool_catalog.rs @@ -328,7 +328,7 @@ pub(super) fn ensure_advanced_tooling( catalog.push(Tool { tool_type: Some(CODE_EXECUTION_TOOL_TYPE.to_string()), name: CODE_EXECUTION_TOOL_NAME.to_string(), - description: "Execute Python code in a local sandboxed runtime and return stdout/stderr/return_code as JSON.".to_string(), + description: "Execute Python code with the local Python interpreter in the workspace and return stdout/stderr/return_code as JSON.".to_string(), input_schema: json!({ "type": "object", "properties": { diff --git a/crates/tui/src/prompts.rs b/crates/tui/src/prompts.rs index 632fef1e66..444030dd1e 100644 --- a/crates/tui/src/prompts.rs +++ b/crates/tui/src/prompts.rs @@ -908,7 +908,7 @@ pub const NEVER_APPROVAL: &str = include_str!("prompts/approvals/never.md"); /// static system-prompt prefix (preserves DeepSeek prefix cache across /// shell-access toggles). pub const SHELL_POLICY_DISABLED: &str = "Shell tools unavailable. For mandatory-use items referencing \ -`exec_shell`, use `code_execution` (Python sandbox). For GitHub triage, use \ +`exec_shell`, use `code_execution` (local Python interpreter). For GitHub triage, use \ `github_issue_context` / `github_pr_context` as primary route."; /// Compaction relay template — written into the system prompt so the @@ -2023,7 +2023,9 @@ mod tests { let edit = EditFileTool.description(); assert!(edit.contains("read_file")); - assert!(edit.contains("apply_patch") && edit.contains("write_file")); + // apply_patch is hidden from the pinvou3 tool surface, so edit_file + // points to write_file / repeated edits instead of referencing it. + assert!(edit.contains("write_file")); let patch = ApplyPatchTool.description(); assert!(patch.contains("unified-diff") && patch.contains("transactional")); diff --git a/crates/tui/src/prompts/agent.txt b/crates/tui/src/prompts/agent.txt index 3f806304f1..71c37b5744 100644 --- a/crates/tui/src/prompts/agent.txt +++ b/crates/tui/src/prompts/agent.txt @@ -1,7 +1,7 @@ ## Mode: agent Read-only tools (reads, searches, persistent RLM session tools, git inspection) run silently. -Any write, patch, shell execution, sub-agent start, or CSV batch operation will ask for approval first. +Any write, patch, shell execution, or sub-agent start will ask for approval first. Before requesting approval for multi-step writes, lay out your work with `work_update` so the user can see what you intend to do and approve with context. Complex changes should also get diff --git a/crates/tui/src/prompts/approvals/suggest.md b/crates/tui/src/prompts/approvals/suggest.md index 11d02bb2f7..d974e6ebdd 100644 --- a/crates/tui/src/prompts/approvals/suggest.md +++ b/crates/tui/src/prompts/approvals/suggest.md @@ -1,6 +1,6 @@ ##### Approval Policy: Suggest — Tier 2 (Statute) -Read-only operations run silently. Write operations (file edits, patches, shell execution, sub-agent spawns, CSV batches) require user approval before executing. +Read-only operations run silently. Write operations (file edits, patches, shell execution, sub-agent spawns) require user approval before executing. When you need approval: 1. For multi-step changes, lay out your approach with `work_update`. diff --git a/crates/tui/src/prompts/modes/agent.md b/crates/tui/src/prompts/modes/agent.md index bc99d88349..d2f8382110 100644 --- a/crates/tui/src/prompts/modes/agent.md +++ b/crates/tui/src/prompts/modes/agent.md @@ -3,7 +3,7 @@ You are running in Agent mode — autonomous task execution with tool access. Read-only tools (reads, searches, RLM session tools, agent status, git inspection) run silently. -Any write, patch, shell, sub-agent open, or CSV batch asks for approval first. +Any write, patch, shell, or sub-agent open asks for approval first. Before multi-step write approvals, lay out work with `work_update`. Use `update_plan` only for Strategy metadata, not a second checklist. Simple writes: state the edit and use normal approval. diff --git a/crates/tui/src/skills/mod.rs b/crates/tui/src/skills/mod.rs index 9491cb50ec..744554eab4 100644 --- a/crates/tui/src/skills/mod.rs +++ b/crates/tui/src/skills/mod.rs @@ -957,7 +957,7 @@ instructions when using a specific skill.\n\n", out.push_str( "\n### How to use skills\n\ -- Skill bodies live on disk at the listed paths. When a skill is relevant, open only that skill's `SKILL.md` and the specific companion files it references.\n\ +- Skill bodies live on disk at the listed paths. When a skill is relevant, load it with the `load_skill` tool, or open only that skill's `SKILL.md` and the specific companion files it references.\n\ - Trigger rules: use a skill when the user names it (`$SkillName`, `/skill `, or plain text) or the task clearly matches its description. Do not carry skills across turns unless re-mentioned.\n\ - Missing/blocked: if a named skill is missing or cannot be read, say so briefly and continue with the best fallback.\n\ - Safety: do not execute scripts from a community skill unless the user explicitly asks or the skill has been trusted for script use.\n", diff --git a/crates/tui/src/tools/apply_patch.rs b/crates/tui/src/tools/apply_patch.rs index 76f9d6a6bb..33ea87cfae 100644 --- a/crates/tui/src/tools/apply_patch.rs +++ b/crates/tui/src/tools/apply_patch.rs @@ -211,7 +211,7 @@ impl ToolSpec for ApplyPatchTool { } fn description(&self) -> &'static str { - "Apply a unified-diff patch (multi-hunk, multi-file). Use this instead of `git apply`, `patch`, or repeated `edit_file` calls in `exec_shell` — single transactional change with fuzzy matching and a rendered diff." + "Apply a unified-diff patch (multi-hunk, multi-file). Use this instead of `git apply` or `patch` in `exec_shell`, or repeated `edit_file` calls — single transactional change with fuzzy matching and a rendered diff." } fn input_schema(&self) -> Value { @@ -220,7 +220,7 @@ impl ToolSpec for ApplyPatchTool { "properties": { "path": { "type": "string", - "description": "Path to the file to patch (relative to workspace)" + "description": "Path to the file to patch (relative to workspace). Required when the patch has no `---`/`+++` file headers; otherwise overrides the header path." }, "patch": { "type": "string", diff --git a/crates/tui/src/tools/automation.rs b/crates/tui/src/tools/automation.rs index 752a276134..18629a41a0 100644 --- a/crates/tui/src/tools/automation.rs +++ b/crates/tui/src/tools/automation.rs @@ -29,7 +29,7 @@ impl ToolSpec for AutomationCreateTool { } fn description(&self) -> &'static str { - "Create a durable scheduled automation. Creation requires approval and recurrence is constrained to supported HOURLY/WEEKLY RRULE forms. Runs enqueue normal durable tasks." + "Create a durable scheduled automation. Creation requires approval and recurrence is constrained to supported HOURLY/WEEKLY RRULE forms. Runs enqueue normal durable tasks; runs missed while the app is not running are skipped (no backfill), and a run still queued/running blocks the next slot (no overlap)." } fn input_schema(&self) -> Value { @@ -40,7 +40,7 @@ impl ToolSpec for AutomationCreateTool { "prompt": { "type": "string" }, "rrule": { "type": "string", - "description": "Supported: FREQ=HOURLY;INTERVAL=N[;BYDAY=MO,TU] or FREQ=WEEKLY;BYDAY=MO;BYHOUR=9;BYMINUTE=30" + "description": "Supported forms: FREQ=HOURLY[;INTERVAL=N][;BYDAY=MO,TU][;BYHOUR=H][;BYMINUTE=M] or FREQ=WEEKLY;BYDAY=MO[,TU,...];BYHOUR=9;BYMINUTE=30 (WEEKLY requires BYDAY, BYHOUR, and BYMINUTE). Times are evaluated in the machine's local timezone." }, "cwds": { "type": "array", "items": { "type": "string" } }, "model": { "type": "string", "description": "Model name for scheduled runs. Uses the task manager default when omitted." }, @@ -148,7 +148,7 @@ impl ToolSpec for AutomationReadTool { } fn description(&self) -> &'static str { - "Read one durable automation plus recent run records." + "Read one durable automation plus up to 20 recent run records." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/diagnostics.rs b/crates/tui/src/tools/diagnostics.rs index f4097d5d45..1dfc3a04f1 100644 --- a/crates/tui/src/tools/diagnostics.rs +++ b/crates/tui/src/tools/diagnostics.rs @@ -53,7 +53,7 @@ impl ToolSpec for DiagnosticsTool { } fn description(&self) -> &'static str { - "Report workspace info, git detection, sandbox availability, and Rust toolchain versions." + "Report workspace info, git detection, sandbox and bubblewrap availability, cgroup version, Rust toolchain versions, and trusted external paths." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/fetch_url.rs b/crates/tui/src/tools/fetch_url.rs index e27ee68251..30b7452e9b 100644 --- a/crates/tui/src/tools/fetch_url.rs +++ b/crates/tui/src/tools/fetch_url.rs @@ -92,7 +92,7 @@ impl ToolSpec for FetchUrlTool { } fn description(&self) -> &'static str { - "Fetch a known URL directly (HTTP GET) and return its content. Use this instead of `curl` in `exec_shell` — sandboxed, network-policy aware, and properly decoded. Plain-text endpoints (`.md`, `.txt`, `.json`, `.yaml`, `raw.githubusercontent.com`, public APIs) prefer this over the browser/automation stack. For unknown queries, use `web_search` first." + "Fetch a known URL directly (HTTP GET) and return its content. Use this instead of `curl` in `exec_shell` (whose sandbox policy may deny outbound network) — network-policy aware and properly decoded. Plain-text endpoints (`.md`, `.txt`, `.json`, `.yaml`, `raw.githubusercontent.com`, public APIs) prefer this over the browser/automation stack. For unknown queries, use `web_search` first. Follows up to 5 redirects; non-2xx responses still return the body marked as a failure. Requests to localhost, private/loopback/link-local IPs, and cloud metadata addresses are rejected (SSRF protection)." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/file.rs b/crates/tui/src/tools/file.rs index ba60e19425..d5c19967f3 100644 --- a/crates/tui/src/tools/file.rs +++ b/crates/tui/src/tools/file.rs @@ -128,7 +128,7 @@ impl ToolSpec for ReadFileTool { } fn description(&self) -> &'static str { - "Read a UTF-8 file from the workspace. Use this instead of `cat`, `head`, `tail`, or `sed -n '..p'` in `exec_shell` — it's faster, sandbox-aware, and skips the approval prompt. Plain text is returned as-is and records the file snapshot required before `edit_file` will make a narrow in-place edit. CodeWhale config files and file-backed credential stores cannot be read with this tool; use `codewhale config list` or `codewhale auth status` for safe inspection. PDFs are auto-extracted via the bundled pure-Rust extractor (no Poppler install required). Image screenshots are OCR-extracted when local OCR is available. Cannot read other non-PDF binaries.\n\nFor large files, use `start_line` and `max_lines` to read in chunks. By default, returns at most 200 lines (~16KB). If `truncated=\"true\"` in the response, use `next_start_line` to continue reading. For PDFs, use `pages` instead — `start_line`/`max_lines` only apply to text files." + "Read a UTF-8 file from the workspace. Use this instead of `cat`, `head`, `tail`, or `sed -n '..p'` in `exec_shell` — it's faster, sandbox-aware, and skips the approval prompt. Plain text is returned as-is and records the file snapshot required before `edit_file` will make a narrow in-place edit. CodeWhale config files and file-backed credential stores cannot be read with this tool; use `codewhale config list` or `codewhale auth status` for safe inspection. PDFs are auto-extracted via the bundled pure-Rust extractor (no Poppler install required). Image screenshots are OCR-extracted when local OCR is available. Cannot read other non-PDF binaries.\n\nFor large files, use `start_line` and `max_lines` to read in chunks. By default, returns at most 200 lines (~16KB). Large or ranged reads are wrapped in a `` envelope with each line prefixed by its line number and `│` — never include these prefixes in `edit_file` search strings. If `truncated=\"true\"`, continue from the `next_start_line` attribute when present; when the selected range exceeded 16KB there is no `next_start_line` — retry with a smaller `max_lines`. For PDFs, use `pages` instead — `start_line`/`max_lines` only apply to text files." } fn input_schema(&self) -> Value { @@ -1022,7 +1022,7 @@ impl ToolSpec for EditFileTool { } fn description(&self) -> &'static str { - "Replace text in a single file via exact search/replace after the file has been read with `read_file` in this session. Use this instead of `sed -i` in `exec_shell` for one unambiguous in-place edit. `search` must match exactly one location by default; when no exact match is found the tool retries with leading-whitespace-tolerant fuzzy matching automatically. The optional `fuzz` parameter is accepted for backward compatibility and is no longer needed. Returns a compact unified diff, not the full file. For structural, multi-block, or cross-file changes, use `apply_patch` or `write_file` instead." + "Replace text in a single file via exact search/replace after the file has been read with `read_file` (or written with `write_file`) in this session and has not changed on disk since. Use this instead of `sed -i` in `exec_shell` for one unambiguous in-place edit. `search` must match exactly one location; when no exact match is found the tool automatically retries fuzzy matching that tolerates leading-whitespace and typographic-punctuation (smart quotes, em-dashes, NBSP) drift. `read_file` strips `\\r` from CRLF line endings, so a multi-line `search` copied from its output will not match a CRLF file — restore the carriage returns or use `write_file`. The optional `fuzz` parameter is accepted for backward compatibility and ignored. Returns a compact unified diff, not the full file. For structural, multi-block, or cross-file changes, use `write_file` or repeated `edit_file` calls instead." } fn input_schema(&self) -> Value { @@ -1323,7 +1323,7 @@ impl ToolSpec for ListDirTool { } fn description(&self) -> &'static str { - "List entries in a directory relative to the workspace. Use this instead of `ls`, `ls -la`, or `find . -maxdepth 1` in `exec_shell` for directory listings." + "List entries in a directory relative to the workspace. Use this instead of `ls`, `ls -la`, or `find . -maxdepth 1` in `exec_shell` for directory listings. Returns each entry as `{name, is_dir}` (no sizes or permissions); at most 500 entries per call — larger directories return the first 500 with `truncated: true` and `total_entries` in the response." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/git.rs b/crates/tui/src/tools/git.rs index 178d9ae1f4..e669f78bc5 100644 --- a/crates/tui/src/tools/git.rs +++ b/crates/tui/src/tools/git.rs @@ -32,7 +32,7 @@ impl ToolSpec for GitStatusTool { } fn description(&self) -> &'static str { - "Run `git status --porcelain=v1 -b` in the workspace (optionally scoped to a path)." + "Run `git status --porcelain=v1 -b` in the workspace (optionally scoped to a path). Read-only; prefer this over running `git status` in `exec_shell`." } fn input_schema(&self) -> Value { @@ -113,7 +113,7 @@ impl ToolSpec for GitDiffTool { } fn description(&self) -> &'static str { - "Run `git diff` in the workspace with sensible defaults and safe truncation." + "Run `git diff` in the workspace with sensible defaults and safe truncation. Read-only; prefer this over running `git diff` in `exec_shell`." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/git_history.rs b/crates/tui/src/tools/git_history.rs index a9210ec138..da9e0a61aa 100644 --- a/crates/tui/src/tools/git_history.rs +++ b/crates/tui/src/tools/git_history.rs @@ -35,7 +35,7 @@ impl ToolSpec for GitLogTool { } fn description(&self) -> &'static str { - "Run `git log` in the workspace with optional path and author/date filters." + "Run `git log` in the workspace with optional path and author/date filters. Read-only; prefer this over running `git log` in `exec_shell`." } fn input_schema(&self) -> Value { @@ -152,7 +152,7 @@ impl ToolSpec for GitShowTool { } fn description(&self) -> &'static str { - "Run `git show` for a specific revision with optional patch and stats." + "Run `git show` for a specific revision with optional patch and stats. Read-only; prefer this over running `git show` in `exec_shell`." } fn input_schema(&self) -> Value { @@ -270,7 +270,7 @@ impl ToolSpec for GitBlameTool { } fn description(&self) -> &'static str { - "Run `git blame` on a file with optional revision and line-range controls." + "Run `git blame` on a file with optional revision and line-range controls. Read-only; prefer this over running `git blame` in `exec_shell`." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/github.rs b/crates/tui/src/tools/github.rs index b2a0ad5078..a1a4457472 100644 --- a/crates/tui/src/tools/github.rs +++ b/crates/tui/src/tools/github.rs @@ -38,7 +38,7 @@ impl ToolSpec for GithubIssueContextTool { } fn description(&self) -> &'static str { - "Read GitHub issue context using gh. Read-only: body/comments/labels/state are summarized and large bodies become task artifacts when a durable task is active." + "Read GitHub issue context using gh (requires the gh CLI installed and authenticated, and a git-repository workspace). Read-only: body/comments/labels/state are summarized and large bodies become task artifacts when a durable task is active." } fn input_schema(&self) -> Value { @@ -93,7 +93,7 @@ impl ToolSpec for GithubPrContextTool { } fn description(&self) -> &'static str { - "Read GitHub PR context using gh: body/comments/reviews/check status/files and optional diff artifact. Read-only; no push/merge/close." + "Read GitHub PR context using gh (requires the gh CLI installed and authenticated, and a git-repository workspace): body/comments/reviews/check status/files and optional diff artifact. Read-only; no push/merge/close." } fn input_schema(&self) -> Value { @@ -162,7 +162,7 @@ impl ToolSpec for GithubCommentTool { } fn description(&self) -> &'static str { - "Post an evidence-backed GitHub issue/PR comment with gh. Requires approval. Use blocker comments for partial work; do not claim closure without evidence." + "Post an evidence-backed GitHub issue/PR comment with gh (requires the gh CLI installed and authenticated). Requires approval. Use blocker comments for partial work; do not claim closure without evidence." } fn input_schema(&self) -> Value { @@ -223,7 +223,7 @@ impl ToolSpec for GithubCloseIssueTool { } fn description(&self) -> &'static str { - "Close a GitHub issue only when structured acceptance evidence is present and approved. For pull requests use github_close_pr; do not call PRs issues in user-facing output. Never close merely because the agent is stopping." + "Close a GitHub issue only when structured acceptance evidence is present and approved. Requires the gh CLI installed and authenticated; refuses to close while the worktree is dirty unless allow_dirty is true. For pull requests use github_close_pr; do not call PRs issues in user-facing output. Never close merely because the agent is stopping." } fn input_schema(&self) -> Value { @@ -250,7 +250,7 @@ impl ToolSpec for GithubClosePrTool { } fn description(&self) -> &'static str { - "Close a GitHub pull request only when structured acceptance evidence is present and approved. Use this for PRs instead of github_close_issue so the UI, audit trail, and comments keep PR wording clear." + "Close a GitHub pull request only when structured acceptance evidence is present and approved. Requires the gh CLI installed and authenticated; refuses to close while the worktree is dirty unless allow_dirty is true. Use this for PRs instead of github_close_issue so the UI, audit trail, and comments keep PR wording clear." } fn input_schema(&self) -> Value { @@ -323,7 +323,7 @@ fn close_input_schema() -> Value { "required": ["files_changed", "tests_run", "final_status"] }, "comment": { "type": "string" }, - "allow_dirty": { "type": "boolean", "default": false }, + "allow_dirty": { "type": "boolean", "default": false, "description": "Set true to allow closing with uncommitted changes; by default the close is refused while the worktree is dirty." }, "dry_run": { "type": "boolean", "default": false } }, "required": ["number", "acceptance_criteria", "evidence"], diff --git a/crates/tui/src/tools/goal.rs b/crates/tui/src/tools/goal.rs index c4c8a35bf9..b7d5ae2921 100644 --- a/crates/tui/src/tools/goal.rs +++ b/crates/tui/src/tools/goal.rs @@ -379,7 +379,7 @@ impl ToolSpec for CreateGoalTool { } fn description(&self) -> &'static str { - "Create the current runtime goal. Use this only when the user explicitly asks to pursue a persistent objective." + "Create the current runtime goal, replacing any existing goal and resetting its usage accounting. Use this only when the user explicitly asks to pursue a persistent objective." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/handle.rs b/crates/tui/src/tools/handle.rs index 8fceb7c38f..329e171f5b 100644 --- a/crates/tui/src/tools/handle.rs +++ b/crates/tui/src/tools/handle.rs @@ -184,8 +184,10 @@ impl ToolSpec for HandleReadTool { retrieve_tool_result for spilled tool results/artifacts and \ read_file for workspace files. Provide \ exactly one projection: `slice` for char/line slices, `range` for \ - one-based line ranges, `count` for metadata counts, or `jsonpath` \ - for a small JSON-path projection. This retrieves from the handle's \ + one-based line ranges, `count` for metadata counts, `jsonpath` \ + for a small JSON-path projection, or `introspect` for the supported \ + projections and ready-to-copy examples of this handle. This retrieves \ + from the handle's \ backing environment instead of asking the parent transcript to hold \ the full payload." } diff --git a/crates/tui/src/tools/js_execution.rs b/crates/tui/src/tools/js_execution.rs index 063678b72d..c427a780ba 100644 --- a/crates/tui/src/tools/js_execution.rs +++ b/crates/tui/src/tools/js_execution.rs @@ -94,7 +94,7 @@ pub fn js_execution_tool_definition() -> Tool { tool_type: Some(JS_EXECUTION_TOOL_TYPE.to_string()), name: JS_EXECUTION_TOOL_NAME.to_string(), description: - "Execute JavaScript code in a local sandboxed Node.js runtime and return stdout/stderr/return_code as JSON." + "Execute JavaScript code with the local Node.js runtime in the workspace and return stdout/stderr/return_code as JSON." .to_string(), input_schema: json!({ "type": "object", diff --git a/crates/tui/src/tools/review.rs b/crates/tui/src/tools/review.rs index dd917cbe72..f4451658de 100644 --- a/crates/tui/src/tools/review.rs +++ b/crates/tui/src/tools/review.rs @@ -428,7 +428,7 @@ impl ToolSpec for ReviewTool { } fn description(&self) -> &'static str { - "Run a structured code review for a file, git diff, or GitHub pull request." + "Run a structured code review for a file, git diff, or GitHub pull request. Pull request targets are fetched with the `gh` CLI and require it to be installed." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/rlm.rs b/crates/tui/src/tools/rlm.rs index 3e7ceeb940..c2929bb7d8 100644 --- a/crates/tui/src/tools/rlm.rs +++ b/crates/tui/src/tools/rlm.rs @@ -257,7 +257,7 @@ impl ToolSpec for RlmEvalTool { "required": ["name", "code"], "properties": { "name": { "type": "string", "description": "RLM context name returned by rlm_open." }, - "code": { "type": "string", "description": "Raw Python executed against the context (no markdown fences). The loaded source is in scope; call FINAL(value)/finalize(...) to return a result handle. Example: print(len(SOURCE))." } + "code": { "type": "string", "description": "Raw Python executed against the context (no markdown fences). The loaded source is in scope as `content`; call FINAL(value)/finalize(...) to return a result handle. Example: print(len(content))." } } }) } @@ -279,7 +279,7 @@ impl ToolSpec for RlmEvalTool { let code = required_non_empty_str(&input, "code").map_err(|_| { ToolError::invalid_input( "rlm_eval: `code` is required and runs raw Python against the RLM context (no markdown fences). \ - Example: {\"name\": \"\", \"code\": \"print(len(SOURCE))\"}; call FINAL(value) to return a result handle.", + Example: {\"name\": \"\", \"code\": \"print(len(content))\"}; call FINAL(value) to return a result handle.", ) })?; let session = get_session(context, name).await?; @@ -859,7 +859,7 @@ mod tests { let msg = err.to_string(); assert!(msg.contains("raw Python"), "explains it runs Python: {msg}"); assert!( - msg.contains("print(len(SOURCE))") || msg.contains("FINAL"), + msg.contains("print(len(content))") || msg.contains("FINAL"), "includes an example: {msg}" ); } diff --git a/crates/tui/src/tools/runtime_mcp.rs b/crates/tui/src/tools/runtime_mcp.rs index 8ae6da7ac0..41b16d832f 100644 --- a/crates/tui/src/tools/runtime_mcp.rs +++ b/crates/tui/src/tools/runtime_mcp.rs @@ -216,6 +216,10 @@ impl ToolSpec for StartRuntimeMcpServer { (like 'https://...'), call this tool immediately to start the server \ and register its tools. Do NOT suggest editing config files. \ Accepts a local command (stdio) or a remote URL (HTTP/SSE). \ + Local commands must invoke an allowed runtime directly (npx, npm, pnpm, \ + yarn, bunx, bun, node, python, python3, uvx, uv, deno, ruby, cargo); \ + shell wrappers (bash, sh, cmd, powershell) and shell metacharacters \ + in arguments are rejected. \ After the server starts, the response lists each tool's callable name. \ You MUST copy those exact names when calling the tools. \ Do NOT construct or guess tool names yourself." diff --git a/crates/tui/src/tools/search.rs b/crates/tui/src/tools/search.rs index 8f114f1f77..266a6616a1 100644 --- a/crates/tui/src/tools/search.rs +++ b/crates/tui/src/tools/search.rs @@ -49,7 +49,7 @@ impl ToolSpec for GrepFilesTool { } fn description(&self) -> &'static str { - "Search for a regex pattern in workspace files. Use this instead of `grep -r`, `rg`, or `find ... -exec grep` in `exec_shell` — pure-Rust, faster, and respects `.gitignore`. Returns matching lines with context (default: 2 lines before/after each match)." + "Search for a regex pattern in workspace files. Use this instead of `grep -r`, `rg`, or `find ... -exec grep` in `exec_shell` — pure-Rust, faster, and skips common non-code directories (node_modules, .git, target, ...) by default. Returns matching lines with context (default: 2 lines before/after each match)." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/shell.rs b/crates/tui/src/tools/shell.rs index 6c31b9c765..85fa81496f 100644 --- a/crates/tui/src/tools/shell.rs +++ b/crates/tui/src/tools/shell.rs @@ -2293,7 +2293,7 @@ impl ToolSpec for ExecShellTool { }, "interactive": { "type": "boolean", - "description": "Run interactively with terminal IO (default: false)" + "description": "Run interactively with terminal IO (default: false). Cannot be combined with background, tty, combined_output, or stdin." }, "stdin": { "type": "string", @@ -3223,7 +3223,7 @@ impl ToolSpec for ShellInteractTool { }, "input": { "type": "string", - "description": "Input to send to the task's stdin" + "description": "Input to send to the task's stdin (sent as-is; include a trailing newline to submit a line)" }, "stdin": { "type": "string", diff --git a/crates/tui/src/tools/speech.rs b/crates/tui/src/tools/speech.rs index 9c690512a6..140854e80e 100644 --- a/crates/tui/src/tools/speech.rs +++ b/crates/tui/src/tools/speech.rs @@ -105,7 +105,7 @@ impl ToolSpec for SpeechTool { }, "clone_voice": { "type": "string", - "description": "Path to a .mp3 or .wav voice sample for cloning. When model is omitted this uses mimo-v2.5-tts-voiceclone." + "description": "Path to a .mp3 or .wav voice sample for cloning. Mutually exclusive with voice. When model is omitted this uses mimo-v2.5-tts-voiceclone." }, "format": { "type": "string", diff --git a/crates/tui/src/tools/subagent/coord.rs b/crates/tui/src/tools/subagent/coord.rs index 771fd74a45..094fac90ee 100644 --- a/crates/tui/src/tools/subagent/coord.rs +++ b/crates/tui/src/tools/subagent/coord.rs @@ -136,7 +136,7 @@ impl ToolSpec for AgentsMessageTool { } fn description(&self) -> &'static str { - "Queue a parent message onto a child agent without waking it. The child receives the message on the next followup or natural resume. Use agents/followup when you also need to resume an idle or interrupted child." + "Queue a parent message onto a child agent without waking it. The message stays queued until a later agents/followup delivers it to the running child. Use agents/followup directly when you want that immediate delivery." } fn input_schema(&self) -> Value { @@ -224,7 +224,7 @@ impl ToolSpec for AgentsFollowupTool { } fn description(&self) -> &'static str { - "Queue a message and attempt to resume an idle or interrupted child. Running children receive the message on their next step; interrupted_continuable children keep a checkpoint and return the continuation_handle — live in-place resume is not automated yet (re-dispatch via agent)." + "Queue a message and deliver it live to a still-running child on its next step. Interrupted children are not resumed: the message stays queued and interrupted_continuable children return their continuation_handle — live in-place resume is not automated yet (re-dispatch via agent)." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/subagent/mod.rs b/crates/tui/src/tools/subagent/mod.rs index 9db13f0544..13ecb0c3a0 100644 --- a/crates/tui/src/tools/subagent/mod.rs +++ b/crates/tui/src/tools/subagent/mod.rs @@ -4878,7 +4878,7 @@ impl ToolSpec for AgentTool { }, "deliberate": { "type": "boolean", - "description": "When true, require type (or profile), workspace_policy, expected_artifact, and write_authority." + "description": "When true, require type (or profile), workspace_policy (or worktree=true), expected_artifact, and write_authority." } }, "required": [] diff --git a/crates/tui/src/tools/tasks.rs b/crates/tui/src/tools/tasks.rs index 8252e3e623..c524e74c9f 100644 --- a/crates/tui/src/tools/tasks.rs +++ b/crates/tui/src/tools/tasks.rs @@ -69,12 +69,12 @@ impl ToolSpec for TaskCreateTool { "type": "object", "properties": { "prompt": { "type": "string", "description": "Work prompt for the durable task." }, - "model": { "type": "string" }, + "model": { "type": "string", "description": "Model override; defaults to the configured task model." }, "workspace": { "type": "string", "description": "Workspace path; defaults to current workspace." }, - "mode": { "type": "string", "enum": ["agent", "plan", "yolo"] }, - "allow_shell": { "type": "boolean" }, - "trust_mode": { "type": "boolean" }, - "auto_approve": { "type": "boolean" } + "mode": { "type": "string", "enum": ["agent", "plan", "yolo"], "description": "Execution mode; defaults to the configured default." }, + "allow_shell": { "type": "boolean", "description": "Allow shell commands in the task; defaults to host configuration." }, + "trust_mode": { "type": "boolean", "description": "Override trust mode for the task; defaults to host configuration." }, + "auto_approve": { "type": "boolean", "description": "Auto-approve the task's tool calls; defaults to false and must be opted into explicitly." } }, "required": ["prompt"], "additionalProperties": false @@ -252,7 +252,7 @@ impl ToolSpec for TaskGateRunTool { } fn description(&self) -> &'static str { - "Run an approved verification gate command and return structured evidence. When inside a durable task, the gate result and log artifact are attached to that task." + "Run an approved verification gate command (executed via `/bin/sh -lc`) and return structured evidence. When inside a durable task, the gate result and log artifact are attached to that task. Default timeout is 120 s (max 600 s); commands classified dangerous are blocked unless the session auto-approves." } fn input_schema(&self) -> Value { @@ -409,9 +409,9 @@ impl ToolSpec for TaskShellStartTool { "properties": { "command": { "type": "string" }, "cwd": { "type": "string", "description": "Optional working directory within the workspace." }, - "timeout_ms": { "type": "integer", "minimum": 1000, "maximum": 600000 }, - "stdin": { "type": "string" }, - "tty": { "type": "boolean" } + "timeout_ms": { "type": "integer", "minimum": 1000, "maximum": 600000, "description": "Milliseconds; defaults to 120000." }, + "stdin": { "type": "string", "description": "Optional standard input for the command." }, + "tty": { "type": "boolean", "description": "Allocate a pseudo-TTY for the command." } }, "required": ["command"], "additionalProperties": false @@ -466,7 +466,7 @@ impl ToolSpec for TaskShellWaitTool { } fn description(&self) -> &'static str { - "Poll a background shell task without blocking the agent indefinitely. If `gate` is supplied and the shell task has completed, records structured gate evidence on the active durable task." + "Poll a background shell task; with `wait: true`, block until it completes or `timeout_ms` elapses instead of returning immediately. If `gate` is supplied and the shell task has completed, records structured gate evidence on the active durable task." } fn input_schema(&self) -> Value { @@ -474,7 +474,7 @@ impl ToolSpec for TaskShellWaitTool { "type": "object", "properties": { "task_id": { "type": "string", "description": "Background shell task id returned by task_shell_start or exec_shell." }, - "wait": { "type": "boolean", "default": false }, + "wait": { "type": "boolean", "default": false, "description": "Wait for completion (up to timeout_ms) instead of a non-blocking poll." }, "timeout_ms": { "type": "integer", "minimum": 1000, "maximum": 600000 }, "gate": { "type": "string", "enum": ["fmt", "check", "clippy", "test", "custom"] }, "command": { "type": "string", "description": "Original command, used when recording gate evidence." } @@ -565,7 +565,7 @@ impl ToolSpec for PrAttemptRecordTool { } fn description(&self) -> &'static str { - "Capture current git diff as a durable PR work attempt with patch artifact, changed files, and verification notes." + "Capture the current git working-tree diff as a durable PR work attempt with patch artifact, changed files, and verification notes. Fails when there is no working-tree diff to record." } fn input_schema(&self) -> Value { diff --git a/crates/tui/src/tools/terminal_session.rs b/crates/tui/src/tools/terminal_session.rs index 40663ea2af..35db8e1831 100644 --- a/crates/tui/src/tools/terminal_session.rs +++ b/crates/tui/src/tools/terminal_session.rs @@ -585,7 +585,7 @@ pub struct TerminalRunTool; impl ToolSpec for TerminalRunTool { terminal_tool_common!( "terminal/run", - "Run a command in a persistent PTY shell session. cd, exports, shell functions, and activated environments persist across calls in this process. Identity and a non-secret last-known summary persist across restarts; prior shells are surfaced as stale/lost and are never reattached." + "Run a command in a persistent PTY shell session. cd, exports, shell functions, and activated environments persist across calls in this process. Identity and a non-secret last-known summary persist across restarts; prior shells are surfaced as stale/lost and are never reattached. If the command is still running when timeout_secs elapses, it keeps running and the result reports timed_out; use terminal/wait to collect further output or terminal/send to interact." ); fn input_schema(&self) -> serde_json::Value { json!({"type":"object","properties":{"command":{"type":"string"},"session":{"type":"string","default":"term-1"},"timeout_secs":{"type":"integer","default":120}},"required":["command"]}) @@ -632,7 +632,7 @@ pub struct TerminalSendTool; impl ToolSpec for TerminalSendTool { terminal_tool_common!( "terminal/send", - "Send raw input to a live persistent terminal session. Use a literal ETX control byte to interrupt an interactive process. A prior-process shell is reported as stale/lost rather than reattached." + "Send raw input to a live persistent terminal session. To interrupt the running foreground command, use terminal/cancel instead of sending a raw ETX byte. A prior-process shell is reported as stale/lost rather than reattached." ); fn input_schema(&self) -> serde_json::Value { json!({"type":"object","properties":{"session":{"type":"string"},"text":{"type":"string"},"wait_ms":{"type":"integer","default":250}},"required":["session","text"]}) diff --git a/crates/tui/src/tools/todo.rs b/crates/tui/src/tools/todo.rs index deada37323..5532ffab81 100644 --- a/crates/tui/src/tools/todo.rs +++ b/crates/tui/src/tools/todo.rs @@ -569,7 +569,7 @@ impl ToolSpec for TodoWriteTool { "status": { "type": "string", "enum": ["pending", "in_progress", "completed"], - "description": "Task status" + "description": "Task status. At most one item may be in_progress; if several are, the last one stays in_progress." } }, "required": ["content", "status"] diff --git a/crates/tui/src/tools/validate_data.rs b/crates/tui/src/tools/validate_data.rs index 6e1a69350b..a8382048bb 100644 --- a/crates/tui/src/tools/validate_data.rs +++ b/crates/tui/src/tools/validate_data.rs @@ -60,11 +60,11 @@ impl ToolSpec for ValidateDataTool { "properties": { "path": { "type": "string", - "description": "Optional path to a file within the workspace." + "description": "Path to a file within the workspace. Exactly one of 'path' or 'content' is required; providing both is an error." }, "content": { "type": "string", - "description": "Optional inline content to validate." + "description": "Inline content to validate. Exactly one of 'path' or 'content' is required; providing both is an error." }, "format": { "type": "string", diff --git a/crates/tui/src/tools/verifier.rs b/crates/tui/src/tools/verifier.rs index 484132255b..ad028651ca 100644 --- a/crates/tui/src/tools/verifier.rs +++ b/crates/tui/src/tools/verifier.rs @@ -271,7 +271,7 @@ impl ToolSpec for RunVerifiersTool { }, "commands": { "type": "array", - "description": "Optional explicit verifier gates. Commands run directly as program+args, not through a shell. Use program='bash', args=['-lc', '...'] only when Bash is intentionally part of the verifier.", + "description": "Optional explicit verifier gates (at most 12). Commands run directly as program+args, not through a shell. Use program='bash', args=['-lc', '...'] only when Bash is intentionally part of the verifier.", "items": { "type": "object", "properties": { diff --git a/crates/tui/src/tools/web_run.rs b/crates/tui/src/tools/web_run.rs index 80b9d2c364..8ce640c96b 100644 --- a/crates/tui/src/tools/web_run.rs +++ b/crates/tui/src/tools/web_run.rs @@ -343,7 +343,7 @@ impl ToolSpec for WebRunTool { } fn description(&self) -> &'static str { - "Browse the web (search/open/click/find/screenshot/image_query) and return structured results with ref_ids for citations." + "Browse the web (search/open/click/find/screenshot/image_query) and return structured results with ref_ids for citations. `open` accepts a ref_id from earlier output or a direct http(s) URL; `click`/`find`/`screenshot` require a previously returned ref_id. `screenshot` returns the text of a single PDF page and only works for opened PDF documents." } fn input_schema(&self) -> Value { @@ -356,7 +356,7 @@ impl ToolSpec for WebRunTool { "type": "object", "properties": { "q": { "type": "string" }, - "recency": { "type": "integer" }, + "recency": { "type": "integer", "description": "Accepted for compatibility; not currently enforced." }, "max_results": { "type": "integer" }, "timeout_ms": { "type": "integer" }, "domains": { "type": "array", "items": { "type": "string" } } @@ -370,7 +370,7 @@ impl ToolSpec for WebRunTool { "type": "object", "properties": { "q": { "type": "string" }, - "recency": { "type": "integer" }, + "recency": { "type": "integer", "description": "Accepted for compatibility; not currently enforced." }, "max_results": { "type": "integer" }, "timeout_ms": { "type": "integer" }, "domains": { "type": "array", "items": { "type": "string" } } @@ -425,7 +425,7 @@ impl ToolSpec for WebRunTool { "response_length": { "type": "string", "enum": ["short", "medium", "long"], - "description": "Controls result verbosity" + "description": "Controls result verbosity (default: medium)" } } }) diff --git a/crates/tui/src/tools/workflow.rs b/crates/tui/src/tools/workflow.rs index 2046415bd4..a1cc3082a2 100644 --- a/crates/tui/src/tools/workflow.rs +++ b/crates/tui/src/tools/workflow.rs @@ -461,7 +461,7 @@ impl ToolSpec for WorkflowTool { }, "script": { "type": "string", - "description": "Workflow JS source. The runtime provides args, task(...), parallel(thunks), pipeline(thunks), log(...), phase(...), and budget. Fan-out syntax: await parallel([() => task({...}), () => task({...})]). parallel() requires one array of zero-argument thunks, not variadic task promises." + "description": "Workflow JS source. The runtime provides args, task(...), parallel(thunks), pipeline(thunks), log(...), phase(...), and budget. Fan-out syntax: await parallel([() => task({...}), () => task({...})])." }, "source_path": { "type": "string", diff --git a/crates/tui/src/vision/tools.rs b/crates/tui/src/vision/tools.rs index de06240c21..df82b4d8bc 100644 --- a/crates/tui/src/vision/tools.rs +++ b/crates/tui/src/vision/tools.rs @@ -169,7 +169,7 @@ impl ToolSpec for ImageAnalyzeTool { "properties": { "image_path": { "type": "string", - "description": "Path to the image file to analyze" + "description": "Path to the image file to analyze. Must be a relative path within the workspace." }, "prompt": { "type": "string",