Skip to main content

cosh_tools/
lib.rs

1// Known transitive dependency version duplicates intentionally kept:
2// bitflags 1.x/2.x, thiserror 1.x/2.x, phf 0.11/0.13, rand 0.8/0.9, etc.
3// These cannot be unified without breaking upstream crates.
4#![allow(clippy::multiple_crate_versions)]
5// The tool-description schemas are single `serde_json::json!` macros with
6// deep `allOf`/`anyOf` nesting (computer_control carries the deepest) —
7// the default 128 recursion limit overflows while expanding them.
8#![recursion_limit = "512"]
9
10// TOOL DESCRIPTION CONVENTION (applies to every tool in this crate)
11//
12// A tool description tells the model HOW to use the tool and WHEN to reach
13// for it. It never explains the tool's internals. Do not document
14// implementation details in descriptions — no dispatch modes, engine names,
15// internal batching or fallback behavior, error-handling strategy, or
16// "one file per call" style rules that the input schema already expresses
17// structurally (a flat {path, content} schema says it plainly). The model
18// gets the advertised schema and the description; anything the schema can
19// communicate on its own belongs to the schema, not to prose.
20//
21// What belongs in a description:
22//   - what the tool does, in direct language ("Write content to one file")
23//   - required usage the schema cannot enforce by itself (e.g. "you MUST
24//     include the `file_hash` from a previous read before overwriting")
25//   - useful cases and disambiguation vs. sibling tools
26//
27// What does NOT belong:
28//   - how the tool works internally (engines, modes, dispatch, fallbacks)
29//   - rules that restate the schema's structure in words
30//   - history or rationale ("we changed this from X because Y") — that lives
31//     in code comments and commit messages, where maintainers will find it
32//
33// When a model misuses a tool, correct it at the rejection site with a
34// targeted, actionable message; do not pre-pollute every session's context
35// with instructions guarding against a mistake most sessions never make.
36
37pub mod bash;
38pub mod computer;
39pub mod find;
40pub mod fs;
41pub mod lsp;
42pub mod plan;
43pub mod question;
44#[cfg(feature = "embed")]
45pub mod recall;
46pub mod skills;
47pub mod subagent;
48pub mod util;
49pub mod web;
50
51/// MCP Tool description: name, description, and inputSchema as a JSON value.
52/// Follows the [MCP Tool schema](https://modelcontextprotocol.io/specification/2025-11-25/server/tools)
53/// so it can be passed directly to an rmcp server in the future.
54/// Structure: `{ "name": string, "description": string, "inputSchema": { ... } }`
55pub type ToolDescription = serde_json::Value;
56
57pub const TOOL_FORMAT: &str = concat!(
58    "## Tool format\n",
59    "To call a tool, respond with a JSON object:\n",
60    "{\"name\": \"tool_name\", \"arguments\": { ... }}\n\n",
61    "Warning: Do not wrap tool calls in a code block or any markdown formatting. Emit the tool call as raw, unformatted JSON only — no backticks, no language tags, no surrounding text.\n\n",
62    "INCORRECT (do not do this):\n",
63    "```json\n",
64    "    {\"name\": \"tool_name\", \"arguments\": {...}}\n",
65    "```\n\n",
66    "CORRECT:",
67    "{\"name\": \"tool_name\", \"arguments\": {...}}\n"
68);
69
70/// Native function-calling instruction for providers that MUST use their
71/// structured tool mechanism instead of inline JSON text.
72///
73/// Gemini 3.x models obey the legacy inline-JSON `TOOL_FORMAT` literally:
74/// with it in the prompt they emit tool calls as raw TEXT frames (`{"name":
75/// "fs_read", ...}`) even when the request also carries `toolConfig AUTO` —
76/// the API then rejects the turn with `MALFORMED_FUNCTION_CALL` and stray
77/// fragments (`}`) plus reasoning text leak to the user. The harness selects
78/// this variant when the active provider is Gemini (OpenAI/Claude ignore the
79/// inline instruction and use their native mechanism regardless).
80pub const TOOL_FORMAT_NATIVE: &str = concat!(
81    "## Tool format\n",
82    "You call tools using the NATIVE function calling mechanism: the platform \n",
83    "exposes each tool as a structured functionCall and delivers the result \n",
84    "after you invoke it. NEVER write a tool call as JSON inside your text \n",
85    "response — no {\"name\": ..., \"arguments\": ...} objects in prose, code \n",
86    "blocks or anywhere else. Text output is reserved for answering the user. \n",
87    "When you need a tool, invoke it as a native function call; the platform \n",
88    "handles the rest.\n"
89);