thincoder 0.12.62 → 0.12.63
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 +9 -0
- package/README.md +13 -12
- package/bin/thincoder.mjs +53 -27
- package/package.json +6 -5
- package/src/acp/bridge.mjs +35 -15
- package/src/acp/client-caps.mjs +86 -0
- package/src/acp/ext.mjs +86 -0
- package/src/acp/handlers-session.mjs +240 -0
- package/src/acp/handlers-slots.mjs +196 -0
- package/src/acp/login.mjs +48 -0
- package/src/acp/session.mjs +6 -4
- package/src/acp.mjs +67 -379
- package/src/cli/distill-command.mjs +3 -3
- package/src/cli/make-agent.mjs +59 -17
- package/src/cli/memory-command.mjs +3 -3
- package/src/cli/permission.mjs +4 -48
- package/src/cli/setup-wizard.mjs +1 -1
- package/src/completions.mjs +3 -1
- package/src/crash-reports.mjs +1 -1
- package/src/distill.mjs +4 -4
- package/src/heap-watch.mjs +1 -1
- package/src/prompt-injections.mjs +20 -0
- package/src/tui/agent-turn.mjs +40 -9
- package/src/tui/cmd-advisor.mjs +5 -5
- package/src/tui/cmd-config.mjs +8 -8
- package/src/tui/cmd-eng.mjs +25 -9
- package/src/tui/cmd-mcp.mjs +9 -8
- package/src/tui/cmd-model.mjs +1 -1
- package/src/tui/cmd-new.mjs +6 -5
- package/src/tui/cmd-reindex.mjs +1 -1
- package/src/tui/cmd-restore.mjs +2 -2
- package/src/tui/cmd-session.mjs +24 -1
- package/src/tui/cmd-skills.mjs +1 -1
- package/src/tui/cmd-think.mjs +22 -9
- package/src/tui/config-helpers.mjs +1 -1
- package/src/tui/display-budget.mjs +33 -11
- package/src/tui/index.mjs +9 -9
- package/src/tui/interaction.mjs +16 -7
- package/src/tui/key-modes.mjs +9 -4
- package/src/tui/ledger-surface.mjs +26 -10
- package/src/tui/model-catalog.mjs +4 -4
- package/src/tui/model-picker.mjs +8 -7
- package/src/tui/mouse.mjs +11 -6
- package/src/tui/pickers.mjs +15 -2
- package/src/tui/render-conversation.mjs +1 -1
- package/src/tui/render-frame.mjs +10 -5
- package/src/tui/render-loop.mjs +1 -1
- package/src/tui/render-segments.mjs +3 -1
- package/src/tui/slash-commands.mjs +1 -1
- package/src/tui/startup.mjs +14 -14
- package/src/tui/subagent-blocks.mjs +20 -3
- package/src/tui/subagent-freeze.mjs +73 -2
- package/src/tui/suspension-drive.mjs +46 -22
- package/src/tui/tool-events.mjs +11 -8
- package/src/tui/wizard.mjs +3 -3
- package/src/abort-provenance.mjs +0 -116
- package/src/advisor/citations.mjs +0 -139
- package/src/advisor/compaction.mjs +0 -174
- package/src/advisor/convergence.mjs +0 -80
- package/src/advisor/history.mjs +0 -77
- package/src/advisor/loop.mjs +0 -293
- package/src/advisor/messages.mjs +0 -299
- package/src/advisor/project-context.mjs +0 -194
- package/src/advisor/repos.mjs +0 -150
- package/src/advisor/run.mjs +0 -293
- package/src/advisor/truncate.mjs +0 -57
- package/src/advisor.mjs +0 -290
- package/src/agent/completion.mjs +0 -146
- package/src/agent/dispatch.mjs +0 -489
- package/src/agent/helpers.mjs +0 -384
- package/src/agent/post-turn.mjs +0 -70
- package/src/agent/record-results.mjs +0 -174
- package/src/agent/relay-prefix.mjs +0 -39
- package/src/agent/run-stages.mjs +0 -244
- package/src/agent/setup-reminders.mjs +0 -69
- package/src/agent/setup.mjs +0 -354
- package/src/agent/spawn-child.mjs +0 -243
- package/src/agent-tools/advisor-async.mjs +0 -346
- package/src/agent-tools/advisor-settle.mjs +0 -231
- package/src/agent-tools/advisor.mjs +0 -260
- package/src/agent-tools/async-settle.mjs +0 -204
- package/src/agent-tools/batch-segment.mjs +0 -195
- package/src/agent-tools/consult.mjs +0 -473
- package/src/agent-tools/design-token.mjs +0 -117
- package/src/agent-tools/digest-budget.mjs +0 -76
- package/src/agent-tools/eng.mjs +0 -67
- package/src/agent-tools/escalate-async.mjs +0 -295
- package/src/agent-tools/goal.mjs +0 -119
- package/src/agent-tools/plan.mjs +0 -81
- package/src/agent-tools/read-history.mjs +0 -309
- package/src/agent-tools/recent-changes.mjs +0 -24
- package/src/agent-tools/review-streak.mjs +0 -93
- package/src/agent-tools/settings.mjs +0 -265
- package/src/agent-tools/skill.mjs +0 -47
- package/src/agent-tools/subagent-actions.mjs +0 -482
- package/src/agent-tools/subagent-async.mjs +0 -434
- package/src/agent-tools/subagent-panel.mjs +0 -160
- package/src/agent-tools/subagent-run.mjs +0 -205
- package/src/agent-tools/subagent-scheduler.mjs +0 -392
- package/src/agent-tools/subagent-spawn.mjs +0 -459
- package/src/agent-tools/subagent.mjs +0 -404
- package/src/agent-tools/task.mjs +0 -87
- package/src/agent-tools/timer.mjs +0 -46
- package/src/agent-tools/verify.mjs +0 -271
- package/src/agent-tools.mjs +0 -17
- package/src/agent.mjs +0 -417
- package/src/auto-think.mjs +0 -115
- package/src/config-migrate.mjs +0 -70
- package/src/config.mjs +0 -496
- package/src/context.mjs +0 -392
- package/src/conventions.mjs +0 -223
- package/src/embedding.mjs +0 -120
- package/src/escape.mjs +0 -152
- package/src/expand-home.mjs +0 -16
- package/src/explore-distill.mjs +0 -155
- package/src/generate-title.mjs +0 -88
- package/src/git/checkpoint.mjs +0 -448
- package/src/git/gitmem.mjs +0 -100
- package/src/hooks.mjs +0 -97
- package/src/ledger.mjs +0 -227
- package/src/log.mjs +0 -195
- package/src/markdown.mjs +0 -106
- package/src/mcp/helpers.mjs +0 -51
- package/src/mcp/transport-http.mjs +0 -248
- package/src/mcp/transport-stdio.mjs +0 -140
- package/src/mcp/transport-ws.mjs +0 -122
- package/src/mcp.mjs +0 -295
- package/src/memory/code-index.mjs +0 -219
- package/src/memory/code-sync.mjs +0 -415
- package/src/memory/core.mjs +0 -299
- package/src/memory/delete.mjs +0 -236
- package/src/memory/docs.mjs +0 -419
- package/src/memory/file-walk.mjs +0 -109
- package/src/memory/scan.mjs +0 -95
- package/src/memory/schema.mjs +0 -452
- package/src/memory.mjs +0 -21
- package/src/model-ref.mjs +0 -66
- package/src/model-specs.mjs +0 -179
- package/src/peer-domains.mjs +0 -265
- package/src/peer-instances.mjs +0 -231
- package/src/prompt-overlays.mjs +0 -82
- package/src/prompts/advisor-design.md +0 -41
- package/src/prompts/advisor-round1.md +0 -41
- package/src/prompts/advisor-round2.md +0 -46
- package/src/prompts/advisor-round3.md +0 -42
- package/src/prompts/common.md +0 -115
- package/src/prompts/consult-base.md +0 -19
- package/src/prompts/discipline-engineering.md +0 -258
- package/src/prompts/discipline-normal.md +0 -185
- package/src/prompts/persona-coder.md +0 -21
- package/src/prompts/persona-eng-coder.md +0 -37
- package/src/prompts/persona-eng-designer.md +0 -60
- package/src/prompts/persona-engineering.md +0 -55
- package/src/prompts/persona-explore.md +0 -15
- package/src/prompts/persona-normal.md +0 -27
- package/src/prompts/persona-plan.md +0 -26
- package/src/provider/anthropic.mjs +0 -225
- package/src/provider/core.mjs +0 -476
- package/src/provider/errors.mjs +0 -101
- package/src/provider/google.mjs +0 -257
- package/src/provider/index.mjs +0 -7
- package/src/provider/list-models.mjs +0 -93
- package/src/provider/normalize.mjs +0 -81
- package/src/provider/rate.mjs +0 -108
- package/src/provider/responses.mjs +0 -495
- package/src/provider/retry.mjs +0 -88
- package/src/provider/sse.mjs +0 -264
- package/src/proxy.mjs +0 -261
- package/src/rules.mjs +0 -53
- package/src/session-gc.mjs +0 -221
- package/src/session-guard.mjs +0 -59
- package/src/session-migrate.mjs +0 -48
- package/src/session-rename.mjs +0 -38
- package/src/session-segments.mjs +0 -100
- package/src/session-slots.mjs +0 -492
- package/src/session-store.mjs +0 -441
- package/src/session.mjs +0 -492
- package/src/skills.mjs +0 -153
- package/src/text-budget.mjs +0 -46
- package/src/token-ttl.mjs +0 -274
- package/src/tools/apply_patch.md +0 -15
- package/src/tools/bash.md +0 -37
- package/src/tools/bash.mjs +0 -268
- package/src/tools/checklist-sync.mjs +0 -181
- package/src/tools/checklist.md +0 -13
- package/src/tools/checklist.mjs +0 -299
- package/src/tools/delete.md +0 -13
- package/src/tools/edit-batch.mjs +0 -191
- package/src/tools/edit-diff.mjs +0 -348
- package/src/tools/edit.md +0 -30
- package/src/tools/execute.md +0 -21
- package/src/tools/execute.mjs +0 -228
- package/src/tools/fetch.md +0 -12
- package/src/tools/file.mjs +0 -469
- package/src/tools/file_ops.md +0 -17
- package/src/tools/get_current_time.md +0 -8
- package/src/tools/git-checkpoint.mjs +0 -143
- package/src/tools/git-ext.mjs +0 -173
- package/src/tools/git.md +0 -54
- package/src/tools/git.mjs +0 -356
- package/src/tools/glob-dialect.mjs +0 -130
- package/src/tools/glob.md +0 -11
- package/src/tools/grep.md +0 -19
- package/src/tools/hashline_edit.md +0 -14
- package/src/tools/index.mjs +0 -36
- package/src/tools/insert_after.md +0 -15
- package/src/tools/lint.md +0 -10
- package/src/tools/linter.mjs +0 -128
- package/src/tools/ls.md +0 -12
- package/src/tools/lsp.md +0 -10
- package/src/tools/lsp.mjs +0 -316
- package/src/tools/ops.mjs +0 -299
- package/src/tools/patch.mjs +0 -282
- package/src/tools/process.md +0 -10
- package/src/tools/question.md +0 -16
- package/src/tools/question.mjs +0 -26
- package/src/tools/read.md +0 -20
- package/src/tools/read_image.md +0 -8
- package/src/tools/repomap.mjs +0 -314
- package/src/tools/search.mjs +0 -236
- package/src/tools/shared.mjs +0 -446
- package/src/tools/tree.md +0 -14
- package/src/tools/tree.mjs +0 -66
- package/src/tools/wait_for.md +0 -22
- package/src/tools/web.mjs +0 -224
- package/src/tools/websearch.md +0 -16
- package/src/tools/write.md +0 -11
- package/src/traces/trace-store.mjs +0 -355
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* glob-dialect.mjs — glob 方言(TOOLS.md §17 — 2026-09-06)单一权威模块(CLI)。
|
|
3
|
-
*
|
|
4
|
-
* `{a,b}` brace expansion is handled BEFORE the sentinel/escape flow (braces must
|
|
5
|
-
* not be literal-escaped — a bare "star-star slash star .{js,txt}" pattern
|
|
6
|
-
* previously escaped to a literal that silently matched nothing). Unsupported
|
|
7
|
-
* extglob dialects (`?(x)`/`@(a|b)`/`+(x)`/`*(x)`/`!(x)`) and malformed braces
|
|
8
|
-
* (empty `{}`, unclosed `{`, nested `{a,{b,c}}`) are EXPLICIT errors — never a
|
|
9
|
-
* silent no-match. Exclude prefixes (`!pattern`) are the CALLER's job: the
|
|
10
|
-
* glob/grep tools whitespace-split the pattern expression (splitGlobPatterns —
|
|
11
|
-
* never inside a brace group) and pass the parts to compileGlobMatchers, which
|
|
12
|
-
* intersects includes and excludes.
|
|
13
|
-
*
|
|
14
|
-
* Extracted from shared.mjs (2026-09-06 advisor #5 — shared.mjs exceeded the
|
|
15
|
-
* 500-line cap after §17); shared.mjs re-exports these symbols so all existing
|
|
16
|
-
* importers (system.mjs / ls filter / tests) keep their import paths.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const BRACE_OPEN = "\u0003", BRACE_SEP = "\u0004", BRACE_CLOSE = "\u0005"
|
|
20
|
-
const EXT_GLOB_RE = /[@?+*!]\(/
|
|
21
|
-
|
|
22
|
-
export const GLOB_EXTGLOB_ERROR =
|
|
23
|
-
"glob syntax error: unsupported extglob syntax — ?(x)/@(a|b)/+(x)/*(x)/!(x) are not supported; use {a,b} brace expansion or multiple space-separated patterns instead"
|
|
24
|
-
export const GLOB_EMPTY_BRACE_ERROR =
|
|
25
|
-
'glob syntax error: empty brace group "{}" — put at least one alternative between the braces (e.g. {js,txt})'
|
|
26
|
-
export const GLOB_UNCLOSED_BRACE_ERROR =
|
|
27
|
-
'glob syntax error: unclosed brace group — add a matching "}" (e.g. {js,txt})'
|
|
28
|
-
export const GLOB_NESTED_BRACE_ERROR =
|
|
29
|
-
"glob syntax error: nested brace groups are not supported (e.g. {a,{b,c}}) — use a flat alternative list (e.g. {a,b,c})"
|
|
30
|
-
|
|
31
|
-
function assertNoExtglob(pattern) {
|
|
32
|
-
if (EXT_GLOB_RE.test(pattern)) throw new Error(GLOB_EXTGLOB_ERROR)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/** Replace every {a,b,c} group with placeholder alternation markers. Runs BEFORE
|
|
36
|
-
* the sentinel/escape flow so the inserted alternation survives literal escaping. */
|
|
37
|
-
function expandBraces(pattern) {
|
|
38
|
-
for (;;) {
|
|
39
|
-
const open = pattern.indexOf("{")
|
|
40
|
-
if (open === -1) return pattern
|
|
41
|
-
let close = -1
|
|
42
|
-
for (let j = open + 1; j < pattern.length; j++) {
|
|
43
|
-
if (pattern[j] === "{") throw new Error(GLOB_NESTED_BRACE_ERROR)
|
|
44
|
-
if (pattern[j] === "}") { close = j; break }
|
|
45
|
-
}
|
|
46
|
-
if (close === -1) throw new Error(GLOB_UNCLOSED_BRACE_ERROR)
|
|
47
|
-
const inner = pattern.slice(open + 1, close)
|
|
48
|
-
if (inner === "") throw new Error(GLOB_EMPTY_BRACE_ERROR)
|
|
49
|
-
const alts = inner.split(",").map((a) => a.trim())
|
|
50
|
-
pattern = pattern.slice(0, open) + BRACE_OPEN + alts.join(BRACE_SEP) + BRACE_CLOSE + pattern.slice(close + 1)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Convert a single glob pattern to a RegExp (anchored full match). Supports the
|
|
55
|
-
* recursive "star-star" forms, single-star, "?", "[..]" character classes and
|
|
56
|
-
* {a,b} brace expansion. Malformed braces and unsupported extglob syntax throw
|
|
57
|
-
* explicit errors (no silent mismatch). */
|
|
58
|
-
export function globToRegex(pattern) {
|
|
59
|
-
pattern = String(pattern)
|
|
60
|
-
assertNoExtglob(pattern)
|
|
61
|
-
pattern = expandBraces(pattern)
|
|
62
|
-
// Sentinel chars: \u0001/\u0002 never appear in real glob patterns (they
|
|
63
|
-
// come from model output or the filesystem) — safe as **/ and ** placeholders.
|
|
64
|
-
const DS = "\u0001", DP = "\u0002"
|
|
65
|
-
const escaped = pattern
|
|
66
|
-
.replace(/\*\*\//g, DS).replace(/\*\*/g, DP)
|
|
67
|
-
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
68
|
-
.replace(/\*/g, "[^/]*").replace(/\?/g, "[^/]")
|
|
69
|
-
.replace(new RegExp(DS, "g"), "(?:.+/)?")
|
|
70
|
-
.replace(new RegExp(DP, "g"), ".*")
|
|
71
|
-
.replace(new RegExp(BRACE_OPEN, "g"), "(?:")
|
|
72
|
-
.replace(new RegExp(BRACE_SEP, "g"), "|")
|
|
73
|
-
.replace(new RegExp(BRACE_CLOSE, "g"), ")")
|
|
74
|
-
return new RegExp(`^${escaped}$`)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/** Whitespace-split a glob expression into parts WITHOUT splitting inside {a,b}
|
|
78
|
-
* brace groups and WITHOUT splitting literal spaces inside a single pattern
|
|
79
|
-
* (2026-09-06 audit F1 / advisor #4): a whitespace run is a pattern separator
|
|
80
|
-
* ONLY when the next non-space token starts an exclusion ("!" — the §17
|
|
81
|
-
* "include !exclude" form). So a BARE pattern like "docs/my file/*.md" and an
|
|
82
|
-
* exclude like "!docs/my file/**" each stay ONE part; the standard
|
|
83
|
-
* "js-pattern 空格 !test-pattern" form still splits into its two parts. */
|
|
84
|
-
export function splitGlobPatterns(expr) {
|
|
85
|
-
const s = String(expr ?? "").trim()
|
|
86
|
-
if (!s) return []
|
|
87
|
-
const parts = []
|
|
88
|
-
let depth = 0
|
|
89
|
-
let cur = ""
|
|
90
|
-
for (let i = 0; i < s.length; i++) {
|
|
91
|
-
const ch = s[i]
|
|
92
|
-
if (ch === "{") depth++
|
|
93
|
-
else if (ch === "}") depth = Math.max(0, depth - 1)
|
|
94
|
-
if (/\s/.test(ch) && depth === 0) {
|
|
95
|
-
let j = i
|
|
96
|
-
while (j < s.length && /\s/.test(s[j])) j++
|
|
97
|
-
if (s[j] === "!") {
|
|
98
|
-
if (cur) { parts.push(cur); cur = "" }
|
|
99
|
-
i = j - 1 // next loop iteration continues at the "!"
|
|
100
|
-
continue
|
|
101
|
-
}
|
|
102
|
-
// literal space inside a pattern (or trailing) — keep it in the current part
|
|
103
|
-
cur += ch
|
|
104
|
-
continue
|
|
105
|
-
}
|
|
106
|
-
cur += ch
|
|
107
|
-
}
|
|
108
|
-
if (cur) parts.push(cur)
|
|
109
|
-
return parts
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/** Compile whitespace-split pattern parts (see splitGlobPatterns) into a matcher:
|
|
113
|
-
* non-"!" parts are includes, leading-"!" parts are excludes — a rel path matches
|
|
114
|
-
* when it matches ≥1 include (or there are no includes) and no exclude. Every
|
|
115
|
-
* part runs the full brace/error dialect through globToRegex (excludes too). */
|
|
116
|
-
export function compileGlobMatchers(parts) {
|
|
117
|
-
const includes = []
|
|
118
|
-
const excludes = []
|
|
119
|
-
for (const p of parts) {
|
|
120
|
-
const part = String(p)
|
|
121
|
-
if (part.startsWith("!")) excludes.push(part.slice(1))
|
|
122
|
-
else if (part !== "") includes.push(part)
|
|
123
|
-
}
|
|
124
|
-
const include = includes.map((p) => globToRegex(p))
|
|
125
|
-
const exclude = excludes.map((p) => globToRegex(p))
|
|
126
|
-
const test = (relPath) =>
|
|
127
|
-
(include.length === 0 || include.some((re) => re.test(relPath))) &&
|
|
128
|
-
!exclude.some((re) => re.test(relPath))
|
|
129
|
-
return { include, exclude, test }
|
|
130
|
-
}
|
package/src/tools/glob.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
Find files by glob pattern. Returns matching paths (relative to the search path), sorted, capped at 1000. Use this to discover file structure; use grep to search file contents.
|
|
2
|
-
|
|
3
|
-
Parameters:
|
|
4
|
-
- pattern (required): Glob pattern — supports `**` (recursive), `**/`, `*` (within a segment), `?` (single char), `[..]` character classes, and `{a,b}` brace expansion (e.g. `**/*.{js,txt}` matches .js and .txt files at any depth). Space-separated multiple patterns with a leading `!` are EXCLUSIONS — `**/*.js !test/**` matches .js files except those under test/. Pattern matching is relative to `path`. A pattern containing a literal space is fine on its own (spaces only separate patterns when a `!` exclusion is present). An expression splits ONLY before `!`-exclusion tokens — to match several extensions in one include, use a `{a,b}` group (e.g. `**/*.{js,md}`); adjacent space-separated includes are not a supported form.
|
|
5
|
-
- path: Directory to search in (default cwd)
|
|
6
|
-
|
|
7
|
-
Notes:
|
|
8
|
-
- Invalid glob syntax is an EXPLICIT error — never a silent no-match. Unsupported extglob dialects (`?(x)`/`@(a|b)`/`+(x)`) and malformed braces (empty `{}`, unclosed `{`, nested `{a,{b,c}}`) return `glob error: ...` — use `{a,b}` or a space-separated `!exclude` pattern instead.
|
|
9
|
-
- Skips node_modules, .git, dist, build, .turbo, coverage
|
|
10
|
-
- Results capped at 1000 matches
|
|
11
|
-
- Prefer patterns with a literal anchor (extension or subdirectory) over bare wildcards
|
package/src/tools/grep.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
Search file contents with a regex. Returns matching lines as path:line: content.
|
|
2
|
-
|
|
3
|
-
**Route to grep instead of bash:** `findstr /c:"pat" file` / `grep -rn pat .` → grep. Searching file contents is a read — never shell out for it.
|
|
4
|
-
|
|
5
|
-
Parameters:
|
|
6
|
-
- pattern (required): JavaScript regular expression, or a literal string when literal=true
|
|
7
|
-
- path: Directory or file to search (default cwd)
|
|
8
|
-
- glob: Only search files matching this glob — supports `**`, `*`, `?`, `[..]`, `{a,b}` braces and space-separated exclusion (`"**/*.js !test/**"` = .js files outside test/); e.g. '*.mjs'
|
|
9
|
-
- ignoreCase: Case-insensitive match (default false)
|
|
10
|
-
- literal: Literal string match — no regex interpretation (default false; use for strings with `. \` etc.)
|
|
11
|
-
- before: Lines of context to show before each match (grep -B). Default 0
|
|
12
|
-
- after: Lines of context to show after each match (grep -A). Default 0
|
|
13
|
-
|
|
14
|
-
Notes:
|
|
15
|
-
- Skips node_modules, .git, dist, build, .turbo, coverage
|
|
16
|
-
- Results capped at 200 matches
|
|
17
|
-
- Binary/unreadable files are silently skipped
|
|
18
|
-
- Use this to find usages, definitions, patterns; use glob to find files by name
|
|
19
|
-
- With before/after: matching lines use `:` separator, context lines use `-` (like ripgrep); overlapping context ranges in the same file are merged and de-duplicated
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
Edit a file using content-hash addressing instead of string matching. More reliable than edit when whitespace or encoding varies — hashes are computed from exact line bytes on disk.
|
|
2
|
-
|
|
3
|
-
Parameters:
|
|
4
|
-
- path (required): File path
|
|
5
|
-
- old_hashes (required): Array of SHA256 hashes (12-char hex) identifying lines to replace. Read the file with hashes=true first to obtain these hashes. For a single line, pass [hash]; for a contiguous block, pass [hash1, hash2, ...] in order.
|
|
6
|
-
- new_content (required): Replacement text (multi-line ok, \n separated)
|
|
7
|
-
|
|
8
|
-
Notes:
|
|
9
|
-
- The hash of each line is computed as SHA256(line_content).slice(0, 12) — the same algorithm used by read(hashes=true)
|
|
10
|
-
- Hashes are position-independent: they identify lines by content, not by line number (which changes after edits)
|
|
11
|
-
- If the hash sequence isn't found, the error will include the current file's hashes so you can retry with corrected values
|
|
12
|
-
- Prefer this over edit when: 1) the file may have mixed whitespace/encoding, 2) you want to edit a block of lines with a single call
|
|
13
|
-
- Replacement text replaces the lines identified by the hashes — content not present in new_content is deleted. For a new line after a known line, use insert_after. For a single simple string swap, use edit.
|
|
14
|
-
- use the most recent read of the file as the source of old_string / line numbers / hashes — re-read after the file changed
|
package/src/tools/index.mjs
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
// tools/index.mjs — backend-compatible re-export
|
|
2
|
-
export { toOpenAISchema } from "./shared.mjs";
|
|
3
|
-
|
|
4
|
-
import { readTool, writeTool, editTool, insertAfterTool, readImageTool, hashlineEditTool } from "./file.mjs";
|
|
5
|
-
import { applyPatchTool, deleteTool } from "./patch.mjs";
|
|
6
|
-
import { bashTool } from "./bash.mjs";
|
|
7
|
-
import { globTool, grepTool, lsTool } from "./search.mjs";
|
|
8
|
-
import { websearchTool, fetchTool } from "./web.mjs";
|
|
9
|
-
import { gitTool } from "./git.mjs";
|
|
10
|
-
import { questionTool } from "./question.mjs";
|
|
11
|
-
import { checklistTool } from "./checklist.mjs";
|
|
12
|
-
import { lintTool } from "./linter.mjs";
|
|
13
|
-
import { lspTool } from "./lsp.mjs";
|
|
14
|
-
import { executeTool } from "./execute.mjs";
|
|
15
|
-
import { fileOpsTool, processTool, getCurrentTimeTool, waitForTool } from "./ops.mjs";
|
|
16
|
-
import { treeTool } from "./tree.mjs";
|
|
17
|
-
|
|
18
|
-
export const builtinTools = [
|
|
19
|
-
readTool, writeTool, editTool, insertAfterTool, hashlineEditTool, applyPatchTool,
|
|
20
|
-
readImageTool, bashTool, globTool, grepTool,
|
|
21
|
-
websearchTool, lsTool, fetchTool, deleteTool,
|
|
22
|
-
gitTool, questionTool,
|
|
23
|
-
checklistTool, lintTool, lspTool, executeTool,
|
|
24
|
-
fileOpsTool, processTool, getCurrentTimeTool, waitForTool,
|
|
25
|
-
treeTool,
|
|
26
|
-
];
|
|
27
|
-
|
|
28
|
-
export {
|
|
29
|
-
readTool, writeTool, editTool, insertAfterTool, hashlineEditTool, applyPatchTool,
|
|
30
|
-
readImageTool, bashTool, globTool, grepTool,
|
|
31
|
-
websearchTool, lsTool, fetchTool, deleteTool,
|
|
32
|
-
gitTool, questionTool,
|
|
33
|
-
checklistTool, lintTool, lspTool, executeTool,
|
|
34
|
-
fileOpsTool, processTool, getCurrentTimeTool, waitForTool,
|
|
35
|
-
treeTool,
|
|
36
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
Insert a line of text after a specific line in a file. Safer than `edit` for adding new content — no need to copy surrounding context for exact string matching.
|
|
2
|
-
|
|
3
|
-
Parameters:
|
|
4
|
-
- path (required): File path
|
|
5
|
-
- content (required): Text to insert (will be placed as a new line after the target line)
|
|
6
|
-
- after_line: Line number to insert after (1-based). Preferred when you know the exact line number from `read`.
|
|
7
|
-
- after_regex: JavaScript regex to find the line to insert after. Must match exactly one line; if it matches multiple, the tool errors and shows the matching line numbers.
|
|
8
|
-
|
|
9
|
-
Notes:
|
|
10
|
-
- Either after_line or after_regex is required; if both are given, after_line wins.
|
|
11
|
-
- Use this instead of edit when you're adding a new line — a checklist item, a doc heading, a line of prose, a function, an import, or a block — no need to fabricate surrounding context for exact matching.
|
|
12
|
-
- The inserted content becomes its own line; it's equivalent to `lines.splice(targetLine, 0, content)`.
|
|
13
|
-
- Returns a diff of the change.
|
|
14
|
-
- **Read-before-insert guard**: if the file was modified by any write tool (write/edit/insert_after/hashline_edit/apply_patch/delete) since your last `read`, this tool REFUSES with an error — line numbers may be stale. Read the file again, then retry. This prevents after_line from silently landing at a drifted position.
|
|
15
|
-
- use the most recent read of the file as the source of old_string / line numbers / hashes — re-read after the file changed
|
package/src/tools/lint.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
Run the appropriate linter/checker for a file. Auto-detects based on file extension and project config.
|
|
2
|
-
Without 'full', runs a fast node --check (JS/TS syntax only, catches parse errors in milliseconds).
|
|
3
|
-
With 'full', runs the language-aware cascade: tsc –noEmit (TS); ruff (Python); cargo check (Rust); go vet (Go). JS/JSX files fall back to node --check; TS uses tsc --noEmit (requires tsconfig.json).
|
|
4
|
-
Use the fast default after every write/edit; use 'full' before declaring a task complete.
|
|
5
|
-
|
|
6
|
-
Returns the check result: `Syntax OK: <path>` / `Syntax error in <path>: <message>` (or the language checker's output — `✓ no issues` or the failure text).
|
|
7
|
-
|
|
8
|
-
Parameters:
|
|
9
|
-
- path: File to check (default: most recently modified file)
|
|
10
|
-
- full: Run the full language-aware cascade instead of just node --check (default false)
|
package/src/tools/linter.mjs
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
import { DESC, resolveInCwd } from "./shared.mjs"
|
|
2
|
-
import { execFileSync } from "node:child_process"
|
|
3
|
-
import { existsSync } from "node:fs"
|
|
4
|
-
import { join } from "node:path"
|
|
5
|
-
|
|
6
|
-
export const lintTool = {
|
|
7
|
-
name: "lint",
|
|
8
|
-
description: DESC("lint"),
|
|
9
|
-
parameters: {
|
|
10
|
-
type: "object",
|
|
11
|
-
properties: {
|
|
12
|
-
path: { type: "string", description: "File to check (default: most recently modified file)" },
|
|
13
|
-
full: { type: "boolean", description: "Run the full language-aware cascade instead of just node --check (default false)" },
|
|
14
|
-
},
|
|
15
|
-
required: [],
|
|
16
|
-
},
|
|
17
|
-
readonly: true,
|
|
18
|
-
async execute(args, ctx) {
|
|
19
|
-
const abs = args.path
|
|
20
|
-
? resolveInCwd(ctx, args.path)
|
|
21
|
-
: (ctx.agent?._touchedFiles?.at(-1) || null)
|
|
22
|
-
if (!abs) return "lint: no file specified and no recently modified file to check"
|
|
23
|
-
|
|
24
|
-
if (!args.full) {
|
|
25
|
-
// Fast path: node --check only
|
|
26
|
-
return nodeCheckResult(abs)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// Full cascade: language-aware (tsc → node --check, ruff, cargo, go vet —
|
|
30
|
-
// third-party linter cascade removed 2026-09-02, TOOLS.md §10.2: zero-dependency lint)
|
|
31
|
-
const ext = abs.split(".").pop()?.toLowerCase()
|
|
32
|
-
const checkers = LANG_CHECKERS[ext]
|
|
33
|
-
if (!checkers) return nodeCheckResult(abs) // fall back to node --check
|
|
34
|
-
|
|
35
|
-
for (const checker of checkers) {
|
|
36
|
-
const result = await checker(abs, { cwd: ctx.cwd, existsSync, execFileSync, join, relative })
|
|
37
|
-
if (result !== null) return result
|
|
38
|
-
}
|
|
39
|
-
return `lint: no linter available for ${abs}. Install one?`
|
|
40
|
-
},
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function nodeCheckResult(abs) {
|
|
44
|
-
if (!/\.(?:m?js|cjs|m?ts|cts|jsx|tsx)$/.test(abs)) {
|
|
45
|
-
return `lint (check): only JS/TS-family files supported for fast syntax check; use full=true for other languages. Path: ${abs}`
|
|
46
|
-
}
|
|
47
|
-
try {
|
|
48
|
-
execFileSync(process.execPath, ["--check", abs], {
|
|
49
|
-
encoding: "utf8", timeout: 10000, stdio: ["ignore", "pipe", "pipe"],
|
|
50
|
-
})
|
|
51
|
-
return `Syntax OK: ${abs}`
|
|
52
|
-
} catch (e) {
|
|
53
|
-
const msg = (e.stderr || e.stdout || e.message || "").trim()
|
|
54
|
-
return `Syntax error in ${abs}:\n${msg || "(unknown)"}`
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// ─── Full-check cascade checkers (third-party linter branch removed 2026-09-02, TOOLS.md §10.2) ──────
|
|
59
|
-
|
|
60
|
-
async function tscCheck(file, { cwd, existsSync, execFileSync, join }) {
|
|
61
|
-
if (!existsSync(join(cwd, "tsconfig.json"))) return null
|
|
62
|
-
if (!/\.(ts|tsx|mts|cts)$/.test(file)) return null
|
|
63
|
-
try {
|
|
64
|
-
execFileSync("npx", ["tsc", "--noEmit", "--pretty", "false"], {
|
|
65
|
-
cwd, encoding: "utf8", timeout: 60000, stdio: ["ignore", "pipe", "pipe"],
|
|
66
|
-
})
|
|
67
|
-
return "✓ tsc: no type errors"
|
|
68
|
-
} catch (e) {
|
|
69
|
-
const stdout = (e.stdout || "").trim()
|
|
70
|
-
if (stdout) return stdout
|
|
71
|
-
return `✗ tsc: ${(e.stderr || e.message).slice(0, 500)}`
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
async function ruffCheck(file, { cwd, execFileSync }) {
|
|
76
|
-
if (!/\.py$/.test(file)) return null
|
|
77
|
-
try {
|
|
78
|
-
execFileSync("ruff", ["check", "--output-format", "concise", file], {
|
|
79
|
-
cwd, encoding: "utf8", timeout: 30000, stdio: ["ignore", "pipe", "pipe"],
|
|
80
|
-
})
|
|
81
|
-
return "✓ ruff: no issues"
|
|
82
|
-
} catch (e) {
|
|
83
|
-
if (e.code === "ENOENT") return "lint: ruff not installed. Run: pip install ruff"
|
|
84
|
-
const stdout = (e.stdout || "").trim()
|
|
85
|
-
if (stdout) return stdout
|
|
86
|
-
return `✗ ruff: ${(e.stderr || e.message).slice(0, 500)}`
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function cargoCheck(file, { cwd, existsSync, execFileSync, join }) {
|
|
91
|
-
if (!/\.rs$/.test(file)) return null
|
|
92
|
-
if (!existsSync(join(cwd, "Cargo.toml"))) return null
|
|
93
|
-
const fname = file.split(/[\\/]/).pop()
|
|
94
|
-
try {
|
|
95
|
-
const out = execFileSync("cargo", ["check", "--message-format", "short"], {
|
|
96
|
-
cwd, encoding: "utf8", timeout: 120000, stdio: ["ignore", "pipe", "pipe"],
|
|
97
|
-
})
|
|
98
|
-
const errors = out.split("\n").filter(l => l.includes(fname))
|
|
99
|
-
return errors.length > 0 ? errors.join("\n") : "✓ cargo check: no errors"
|
|
100
|
-
} catch (e) {
|
|
101
|
-
const combined = ((e.stdout || "") + "\n" + (e.stderr || "")).trim()
|
|
102
|
-
const errors = combined.split("\n").filter(l => l.includes(fname) || l.startsWith("error"))
|
|
103
|
-
return errors.length > 0 ? errors.join("\n") : `✗ cargo check failed:\n${combined.slice(0, 1000)}`
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
async function goVet(file, { cwd, execFileSync }) {
|
|
108
|
-
if (!/\.go$/.test(file)) return null
|
|
109
|
-
try {
|
|
110
|
-
execFileSync("go", ["vet", file], {
|
|
111
|
-
cwd, encoding: "utf8", timeout: 60000, stdio: ["ignore", "pipe", "pipe"],
|
|
112
|
-
})
|
|
113
|
-
return "✓ go vet: no issues"
|
|
114
|
-
} catch (e) {
|
|
115
|
-
return `✗ go vet: ${(e.stderr || e.message).slice(0, 500)}`
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
const LANG_CHECKERS = {
|
|
120
|
-
// js/mjs/cjs/jsx fall back to node --check (no entry — third-party linter cascade removed 2026-09-02, TOOLS.md §10.2)
|
|
121
|
-
ts: [tscCheck],
|
|
122
|
-
tsx: [tscCheck],
|
|
123
|
-
mts: [tscCheck],
|
|
124
|
-
cts: [tscCheck],
|
|
125
|
-
py: [ruffCheck],
|
|
126
|
-
rs: [cargoCheck],
|
|
127
|
-
go: [goVet],
|
|
128
|
-
}
|
package/src/tools/ls.md
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
List directory contents with type, size, and modification time. Directories listed first. Use to see what a directory contains (glob only matches files).
|
|
2
|
-
|
|
3
|
-
**Route to ls instead of bash:** `dir /b` / `ls` / `dir` → ls. Listing a directory is a read — never shell out for it.
|
|
4
|
-
|
|
5
|
-
Parameters:
|
|
6
|
-
- path: Directory path (default cwd)
|
|
7
|
-
- filter: Only list entries matching this glob (e.g. '*.mjs', '*test*') — a wildcard filter, not a full listing
|
|
8
|
-
|
|
9
|
-
Notes:
|
|
10
|
-
- Shows first 500 entries
|
|
11
|
-
- Directories are suffixed with `/` and listed before files
|
|
12
|
-
- Use this for a quick overview; use glob when you have a specific file pattern in mind
|
package/src/tools/lsp.md
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
LSP code intelligence: go to definition, find references, hover info, document symbols, diagnostics. Use this to understand code structure without grep-guessing function locations or type shapes. Find files with glob / repo_outline — use lsp for definition / references / diagnostics
|
|
2
|
-
|
|
3
|
-
Parameters:
|
|
4
|
-
- subcommand (required): LSP operation — "definition" | "references" | "hover" | "symbols" | "diagnostics"
|
|
5
|
-
- uri (required): Target file path (relative to project root)
|
|
6
|
-
- line: 1-based line number (for definition/references/hover)
|
|
7
|
-
- character: 1-based character offset (for definition/references/hover)
|
|
8
|
-
|
|
9
|
-
Notes:
|
|
10
|
-
- Returns the requested LSP result: definition location, references, hover info, document symbols, or diagnostics — or an error message.
|