@theokit/sdk-tools 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/dist/index.cjs +12 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +12 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- bd10da3: SOTA default descriptions for the 9 built-in tools (`read_file`/`write_file`/`edit_file`/`glob_files`/`search_text`/`shell_exec`/`todolist`/`web_fetch`/`web_search`).
|
|
8
|
+
|
|
9
|
+
Each tool's default `description` is upgraded from terse mechanics-only copy to rich, behavior-accurate ACI copy (preconditions, when-to-prefer-which-tool, return shape) — the Agent-Computer Interface the model reads to choose tools, which measurably improves tool-selection. Every claim is verified against the tool's own handler (e.g. `search_text` is described as LITERAL + CASE-SENSITIVE because it matches via `line.includes`; `web_fetch` is described as SSRF-guarded because `screenedFetch` defaults `allowPrivateHosts: false`), so the description lives next to the implementation it describes and cannot drift. Descriptions are generalized (no app-specific cross-tool references). `edit_file` now also ENFORCES the documented `old_string !== new_string` precondition (a no-op edit returns `{ ok: false, error: "no_change" }` instead of a misleading `replacements: 1`), so the description matches behavior. Otherwise no API change: same factory signatures, same return shapes; only the default description string changed. Consumers no longer need to override these descriptions app-side — `withDescription` remains for genuine per-consumer customization. Added `tests/sota-descriptions.test.ts` asserting each description's load-bearing behavioral phrases.
|
|
10
|
+
|
|
3
11
|
## 0.3.0
|
|
4
12
|
|
|
5
13
|
### Minor Changes
|
package/dist/index.cjs
CHANGED
|
@@ -268,7 +268,7 @@ function createEditFileTool(opts) {
|
|
|
268
268
|
const { projectRoot } = opts;
|
|
269
269
|
return sdk.defineTool({
|
|
270
270
|
name: "edit_file",
|
|
271
|
-
description: "
|
|
271
|
+
description: "Make an exact string replacement in a project-relative file. Replaces the FIRST occurrence of old_string with new_string (a whitespace-normalized fallback is attempted if the exact match fails) and writes a .bak backup first. Read the file first so old_string matches the on-disk text exactly; include enough surrounding context to make it unique \u2014 only the first match is replaced, so a too-short old_string can edit the wrong location. old_string must be non-empty and differ from new_string; to change every occurrence, call edit_file repeatedly. Returns { ok, replacements } or { ok: false, error }.",
|
|
272
272
|
inputSchema: zod.z.object({
|
|
273
273
|
path: zod.z.string().min(1).describe("Project-relative file path."),
|
|
274
274
|
old_string: zod.z.string().min(1).describe("String to find in the file."),
|
|
@@ -276,6 +276,9 @@ function createEditFileTool(opts) {
|
|
|
276
276
|
}),
|
|
277
277
|
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: unified diff parsing is inherently complex
|
|
278
278
|
handler: async ({ path, old_string, new_string }) => {
|
|
279
|
+
if (old_string === new_string) {
|
|
280
|
+
return JSON.stringify({ ok: false, error: "no_change", path });
|
|
281
|
+
}
|
|
279
282
|
if (isForbiddenPath(path)) {
|
|
280
283
|
return JSON.stringify({ ok: false, error: "forbidden_path", path });
|
|
281
284
|
}
|
|
@@ -524,7 +527,7 @@ function createGlobTool(opts) {
|
|
|
524
527
|
const { projectRoot } = opts;
|
|
525
528
|
return sdk.defineTool({
|
|
526
529
|
name: "glob_files",
|
|
527
|
-
description: "
|
|
530
|
+
description: "Find files by glob pattern across the project \u2014 fast at any repo size. Use glob_files when you know the filename SHAPE; use search_text when you know the file CONTENT; use read_file when you know the exact path. The pattern supports * and ** wildcards (e.g. '**/*.ts', 'src/**/*.json'); node_modules/.git/dist/.theo are excluded and results are relative paths. Returns { ok, files } or { ok: false, error }.",
|
|
528
531
|
inputSchema: zod.z.object({
|
|
529
532
|
pattern: zod.z.string().min(1).describe("Glob pattern (e.g. '**/*.ts', 'src/**/*.json')."),
|
|
530
533
|
cwd: zod.z.string().optional().describe("Project-relative subdirectory to search from.")
|
|
@@ -1211,7 +1214,7 @@ function createReadFileTool(opts) {
|
|
|
1211
1214
|
const { projectRoot } = opts;
|
|
1212
1215
|
return sdk.defineTool({
|
|
1213
1216
|
name: "read_file",
|
|
1214
|
-
description: "Read a
|
|
1217
|
+
description: "Read a project-relative text file as UTF-8. ALWAYS read a file before you edit it (edit_file) or overwrite it (write_file), so your old_string / new content matches the real bytes exactly. Returns the WHOLE file (there is no offset or line-range parameter); to locate a symbol inside a large file, use search_text instead of re-reading. Refuses paths that escape the project root, sensitive files (.env, .git/, node_modules/, .theo/, lock files), and binary files (null byte in the first 8 KB); caps at 5 MB. Returns { ok, content, size } or { ok: false, error }.",
|
|
1215
1218
|
inputSchema: zod.z.object({
|
|
1216
1219
|
path: zod.z.string().min(1).describe("Project-relative file path.")
|
|
1217
1220
|
}),
|
|
@@ -1401,7 +1404,7 @@ function createSearchTextTool(opts) {
|
|
|
1401
1404
|
} = opts;
|
|
1402
1405
|
return sdk.defineTool({
|
|
1403
1406
|
name: "search_text",
|
|
1404
|
-
description: `Search the project tree
|
|
1407
|
+
description: `Search file CONTENTS for a LITERAL, CASE-SENSITIVE query across the project tree (the query is matched as a substring, not a regex). Use search_text when you know the content; use glob_files when you know the filename shape; use read_file when you know the exact path. Skips sensitive dirs (.env/.git/node_modules/.theo), binary files, and files over 1 MB; 'path' scopes the search to a subdirectory. Returns up to ${String(maxMatches)} matches as { file, line, preview } \u2014 cite locations to the user as file:line. Returns { ok, matches } or { ok: false, error }.`,
|
|
1405
1408
|
inputSchema: zod.z.object({
|
|
1406
1409
|
query: zod.z.string().min(1).describe("Literal text to search for. Case-sensitive."),
|
|
1407
1410
|
path: zod.z.string().optional().describe("Optional project-relative directory to scope the search.")
|
|
@@ -1512,7 +1515,7 @@ function createShellTool(opts) {
|
|
|
1512
1515
|
const { projectRoot, defaultTimeoutMs = DEFAULT_TIMEOUT_MS3, allowCatastrophic = false } = opts;
|
|
1513
1516
|
return sdk.defineTool({
|
|
1514
1517
|
name: "shell_exec",
|
|
1515
|
-
description: "Execute a shell command in the project directory.
|
|
1518
|
+
description: "Execute a shell command in the project directory. Use this for terminal operations \u2014 running tests, git, package managers, build tools. Do NOT use it for file operations (reading, writing, editing, finding files): prefer the specialized read_file/write_file/edit_file/glob_files/search_text tools, which are path-checked and safer. Only commit, push, or change git state when the user explicitly asks. timeout_ms defaults to 30000 (max 300000); stdout/stderr are capped (~5 MB). Returns { ok, stdout, stderr, exit_code } or { ok: false, error }.",
|
|
1516
1519
|
inputSchema: zod.z.object({
|
|
1517
1520
|
command: zod.z.string().min(1).describe("Shell command to execute."),
|
|
1518
1521
|
timeout_ms: zod.z.number().int().positive().optional().describe("Timeout in milliseconds (default 30000, max 300000).")
|
|
@@ -1690,7 +1693,7 @@ ${done}/${items.length} done | ${inProg} in progress | ${pending} pending`);
|
|
|
1690
1693
|
};
|
|
1691
1694
|
return {
|
|
1692
1695
|
name: "todolist",
|
|
1693
|
-
description: "
|
|
1696
|
+
description: "Create and maintain a structured task list for the current session \u2014 tracks progress and keeps a multi-step plan visible across turns. Use it proactively when the work has 3+ steps or the user gave multiple tasks; skip it for a single trivial step. Keep exactly ONE item 'in_progress' at a time, and mark 'complete' only after the work is actually done. Actions: 'add' (create with title), 'in_progress' (mark started by id), 'complete' (mark done by id), 'remove' (delete by id), 'list' (show all), 'clear_completed' (remove done items). Returns { ok, items, items_summary } (items = structured array; items_summary = formatted text).",
|
|
1694
1697
|
inputSchema: {
|
|
1695
1698
|
type: "object",
|
|
1696
1699
|
properties: {
|
|
@@ -1746,7 +1749,7 @@ function createWebFetchTool(opts) {
|
|
|
1746
1749
|
const allowPrivateHosts = opts?.allowPrivateHosts ?? false;
|
|
1747
1750
|
return sdk.defineTool({
|
|
1748
1751
|
name: "web_fetch",
|
|
1749
|
-
description: "Fetch
|
|
1752
|
+
description: "Fetch the contents of a URL via HTTP/HTTPS. Use only for URLs the user provided or that you are confident help with the task; never invent or guess URLs. Rejects non-http(s) URLs and is SSRF-guarded by default (private/loopback/link-local/cloud-metadata hosts are refused with an ssrf_blocked error). The response body is capped at 1 MB. Returns { ok, content, status_code, content_type } or { ok: false, error }.",
|
|
1750
1753
|
inputSchema: zod.z.object({
|
|
1751
1754
|
url: zod.z.string().min(1).describe("URL to fetch (http or https only)."),
|
|
1752
1755
|
timeout_ms: zod.z.number().int().positive().optional().describe("Timeout in milliseconds (default 30000).")
|
|
@@ -1827,7 +1830,7 @@ function createWebSearchTool(opts) {
|
|
|
1827
1830
|
const { search, defaultMaxResults = 5 } = opts;
|
|
1828
1831
|
return sdk.defineTool({
|
|
1829
1832
|
name: "web_search",
|
|
1830
|
-
description: "Search the web for a query. Returns a list of results with title, URL, and snippet. The search provider is injected by the consumer. Returns { ok, results } or { ok: false, error }.",
|
|
1833
|
+
description: "Search the web for a query \u2014 use when you need current information beyond the repo or your training cutoff (library docs, an error message, an API). Returns a list of results with title, URL, and snippet; follow up with web_fetch on a promising result to read it in full. The search provider is injected by the consumer. Returns { ok, results } or { ok: false, error }.",
|
|
1831
1834
|
inputSchema: zod.z.object({
|
|
1832
1835
|
query: zod.z.string().min(1).describe("Search query."),
|
|
1833
1836
|
max_results: zod.z.number().int().positive().max(20).optional().describe("Maximum results to return (default 5, max 20).")
|
|
@@ -1885,7 +1888,7 @@ function createWriteFileTool(opts) {
|
|
|
1885
1888
|
const { projectRoot } = opts;
|
|
1886
1889
|
return sdk.defineTool({
|
|
1887
1890
|
name: "write_file",
|
|
1888
|
-
description: "Write UTF-8 content to a project-relative file
|
|
1891
|
+
description: "Write UTF-8 content to a project-relative file, creating parent directories as needed. OVERWRITES any existing file at the path. Prefer editing an existing file with edit_file over rewriting it; use write_file to create a NEW file or fully replace a small one. If the file already exists, read_file it first so you do not discard content you have not seen. Refuses paths that escape the project root, sensitive files (.env, .git/, node_modules/, .theo/, lock files), and binary-file overwrites. Returns { ok, path, bytes } or { ok: false, error }.",
|
|
1889
1892
|
inputSchema: zod.z.object({
|
|
1890
1893
|
path: zod.z.string().min(1).describe("Project-relative file path."),
|
|
1891
1894
|
content: zod.z.string().describe("UTF-8 content to write.")
|