thincoder 0.12.61 → 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.
Files changed (230) hide show
  1. package/CHANGELOG.md +34 -1
  2. package/README.md +13 -12
  3. package/bin/thincoder.mjs +63 -28
  4. package/package.json +6 -5
  5. package/src/acp/bridge.mjs +35 -15
  6. package/src/acp/client-caps.mjs +86 -0
  7. package/src/acp/ext.mjs +86 -0
  8. package/src/acp/handlers-session.mjs +240 -0
  9. package/src/acp/handlers-slots.mjs +196 -0
  10. package/src/acp/login.mjs +48 -0
  11. package/src/acp/session.mjs +6 -4
  12. package/src/acp.mjs +67 -371
  13. package/src/cli/distill-command.mjs +3 -3
  14. package/src/cli/make-agent.mjs +59 -17
  15. package/src/cli/memory-command.mjs +3 -3
  16. package/src/cli/permission.mjs +4 -48
  17. package/src/cli/setup-wizard.mjs +1 -1
  18. package/src/completions.mjs +3 -1
  19. package/src/crash-reports.mjs +32 -10
  20. package/src/distill.mjs +4 -4
  21. package/src/heap-watch.mjs +88 -0
  22. package/src/prompt-injections.mjs +20 -0
  23. package/src/tui/agent-turn.mjs +40 -9
  24. package/src/tui/cmd-advisor.mjs +5 -5
  25. package/src/tui/cmd-clear.mjs +2 -0
  26. package/src/tui/cmd-config.mjs +8 -8
  27. package/src/tui/cmd-eng.mjs +25 -9
  28. package/src/tui/cmd-mcp.mjs +9 -8
  29. package/src/tui/cmd-model.mjs +1 -1
  30. package/src/tui/cmd-new.mjs +10 -5
  31. package/src/tui/cmd-reindex.mjs +1 -1
  32. package/src/tui/cmd-restore.mjs +2 -2
  33. package/src/tui/cmd-session.mjs +31 -4
  34. package/src/tui/cmd-skills.mjs +1 -1
  35. package/src/tui/cmd-think.mjs +22 -9
  36. package/src/tui/config-helpers.mjs +1 -1
  37. package/src/tui/display-budget.mjs +206 -0
  38. package/src/tui/index.mjs +40 -12
  39. package/src/tui/interaction.mjs +16 -7
  40. package/src/tui/key-handler-search.mjs +9 -1
  41. package/src/tui/key-modes.mjs +9 -4
  42. package/src/tui/ledger-surface.mjs +85 -0
  43. package/src/tui/model-catalog.mjs +4 -4
  44. package/src/tui/model-picker.mjs +8 -7
  45. package/src/tui/mouse.mjs +11 -6
  46. package/src/tui/pickers.mjs +15 -2
  47. package/src/tui/render-conversation.mjs +1 -1
  48. package/src/tui/render-frame.mjs +17 -6
  49. package/src/tui/render-loop.mjs +1 -1
  50. package/src/tui/render-segments.mjs +3 -1
  51. package/src/tui/slash-commands.mjs +1 -1
  52. package/src/tui/startup.mjs +49 -17
  53. package/src/tui/subagent-blocks.mjs +21 -3
  54. package/src/tui/subagent-children.mjs +86 -14
  55. package/src/tui/subagent-freeze.mjs +80 -3
  56. package/src/tui/suspension-drive.mjs +48 -22
  57. package/src/tui/tool-args.mjs +5 -2
  58. package/src/tui/tool-display.mjs +16 -2
  59. package/src/tui/tool-events.mjs +64 -22
  60. package/src/tui/tui-lifecycle.mjs +9 -2
  61. package/src/tui/wizard.mjs +3 -3
  62. package/src/tui/wrapped-spawn.mjs +21 -5
  63. package/src/abort-provenance.mjs +0 -116
  64. package/src/advisor/citations.mjs +0 -139
  65. package/src/advisor/compaction.mjs +0 -174
  66. package/src/advisor/convergence.mjs +0 -80
  67. package/src/advisor/history.mjs +0 -77
  68. package/src/advisor/loop.mjs +0 -293
  69. package/src/advisor/messages.mjs +0 -299
  70. package/src/advisor/project-context.mjs +0 -194
  71. package/src/advisor/repos.mjs +0 -150
  72. package/src/advisor/run.mjs +0 -293
  73. package/src/advisor/truncate.mjs +0 -57
  74. package/src/advisor.mjs +0 -290
  75. package/src/agent/completion.mjs +0 -146
  76. package/src/agent/dispatch.mjs +0 -489
  77. package/src/agent/helpers.mjs +0 -384
  78. package/src/agent/post-turn.mjs +0 -70
  79. package/src/agent/record-results.mjs +0 -174
  80. package/src/agent/relay-prefix.mjs +0 -39
  81. package/src/agent/run-stages.mjs +0 -242
  82. package/src/agent/setup-reminders.mjs +0 -69
  83. package/src/agent/setup.mjs +0 -354
  84. package/src/agent/spawn-child.mjs +0 -228
  85. package/src/agent-tools/advisor-async.mjs +0 -346
  86. package/src/agent-tools/advisor-settle.mjs +0 -231
  87. package/src/agent-tools/advisor.mjs +0 -260
  88. package/src/agent-tools/async-settle.mjs +0 -191
  89. package/src/agent-tools/batch-segment.mjs +0 -195
  90. package/src/agent-tools/consult.mjs +0 -468
  91. package/src/agent-tools/design-token.mjs +0 -117
  92. package/src/agent-tools/digest-budget.mjs +0 -76
  93. package/src/agent-tools/eng.mjs +0 -67
  94. package/src/agent-tools/escalate-async.mjs +0 -289
  95. package/src/agent-tools/goal.mjs +0 -119
  96. package/src/agent-tools/plan.mjs +0 -81
  97. package/src/agent-tools/read-history.mjs +0 -294
  98. package/src/agent-tools/recent-changes.mjs +0 -24
  99. package/src/agent-tools/review-streak.mjs +0 -93
  100. package/src/agent-tools/settings.mjs +0 -265
  101. package/src/agent-tools/skill.mjs +0 -47
  102. package/src/agent-tools/subagent-actions.mjs +0 -479
  103. package/src/agent-tools/subagent-async.mjs +0 -434
  104. package/src/agent-tools/subagent-panel.mjs +0 -160
  105. package/src/agent-tools/subagent-run.mjs +0 -205
  106. package/src/agent-tools/subagent-scheduler.mjs +0 -392
  107. package/src/agent-tools/subagent-spawn.mjs +0 -453
  108. package/src/agent-tools/subagent.mjs +0 -404
  109. package/src/agent-tools/task.mjs +0 -87
  110. package/src/agent-tools/timer.mjs +0 -46
  111. package/src/agent-tools/verify.mjs +0 -271
  112. package/src/agent-tools.mjs +0 -17
  113. package/src/agent.mjs +0 -413
  114. package/src/auto-think.mjs +0 -115
  115. package/src/config-migrate.mjs +0 -70
  116. package/src/config.mjs +0 -496
  117. package/src/context.mjs +0 -381
  118. package/src/conventions.mjs +0 -223
  119. package/src/embedding.mjs +0 -120
  120. package/src/escape.mjs +0 -152
  121. package/src/expand-home.mjs +0 -16
  122. package/src/explore-distill.mjs +0 -155
  123. package/src/generate-title.mjs +0 -83
  124. package/src/git/checkpoint.mjs +0 -448
  125. package/src/git/gitmem.mjs +0 -100
  126. package/src/hooks.mjs +0 -97
  127. package/src/log.mjs +0 -195
  128. package/src/markdown.mjs +0 -106
  129. package/src/mcp/helpers.mjs +0 -51
  130. package/src/mcp/transport-http.mjs +0 -248
  131. package/src/mcp/transport-stdio.mjs +0 -140
  132. package/src/mcp/transport-ws.mjs +0 -122
  133. package/src/mcp.mjs +0 -295
  134. package/src/memory/code-index.mjs +0 -219
  135. package/src/memory/code-sync.mjs +0 -413
  136. package/src/memory/core.mjs +0 -300
  137. package/src/memory/delete.mjs +0 -236
  138. package/src/memory/docs.mjs +0 -417
  139. package/src/memory/file-walk.mjs +0 -109
  140. package/src/memory/schema.mjs +0 -452
  141. package/src/memory.mjs +0 -21
  142. package/src/model-ref.mjs +0 -66
  143. package/src/model-specs.mjs +0 -179
  144. package/src/peer-domains.mjs +0 -265
  145. package/src/peer-instances.mjs +0 -231
  146. package/src/prompt-overlays.mjs +0 -82
  147. package/src/prompts/advisor-design.md +0 -41
  148. package/src/prompts/advisor-round1.md +0 -41
  149. package/src/prompts/advisor-round2.md +0 -46
  150. package/src/prompts/advisor-round3.md +0 -42
  151. package/src/prompts/common.md +0 -115
  152. package/src/prompts/consult-base.md +0 -19
  153. package/src/prompts/discipline-engineering.md +0 -217
  154. package/src/prompts/discipline-normal.md +0 -179
  155. package/src/prompts/persona-coder.md +0 -21
  156. package/src/prompts/persona-eng-coder.md +0 -37
  157. package/src/prompts/persona-eng-designer.md +0 -55
  158. package/src/prompts/persona-engineering.md +0 -54
  159. package/src/prompts/persona-explore.md +0 -15
  160. package/src/prompts/persona-normal.md +0 -27
  161. package/src/prompts/persona-plan.md +0 -26
  162. package/src/provider/anthropic.mjs +0 -225
  163. package/src/provider/core.mjs +0 -476
  164. package/src/provider/errors.mjs +0 -101
  165. package/src/provider/google.mjs +0 -257
  166. package/src/provider/index.mjs +0 -7
  167. package/src/provider/list-models.mjs +0 -93
  168. package/src/provider/normalize.mjs +0 -81
  169. package/src/provider/rate.mjs +0 -108
  170. package/src/provider/responses.mjs +0 -495
  171. package/src/provider/retry.mjs +0 -88
  172. package/src/provider/sse.mjs +0 -264
  173. package/src/proxy.mjs +0 -261
  174. package/src/rules.mjs +0 -53
  175. package/src/session-gc.mjs +0 -214
  176. package/src/session-guard.mjs +0 -47
  177. package/src/session-migrate.mjs +0 -48
  178. package/src/session-rename.mjs +0 -38
  179. package/src/session-slots.mjs +0 -489
  180. package/src/session.mjs +0 -475
  181. package/src/skills.mjs +0 -153
  182. package/src/token-ttl.mjs +0 -274
  183. package/src/tools/apply_patch.md +0 -15
  184. package/src/tools/bash.md +0 -37
  185. package/src/tools/bash.mjs +0 -268
  186. package/src/tools/checklist-sync.mjs +0 -181
  187. package/src/tools/checklist.md +0 -13
  188. package/src/tools/checklist.mjs +0 -299
  189. package/src/tools/delete.md +0 -13
  190. package/src/tools/edit-batch.mjs +0 -191
  191. package/src/tools/edit-diff.mjs +0 -348
  192. package/src/tools/edit.md +0 -30
  193. package/src/tools/execute.md +0 -21
  194. package/src/tools/execute.mjs +0 -228
  195. package/src/tools/fetch.md +0 -12
  196. package/src/tools/file.mjs +0 -469
  197. package/src/tools/file_ops.md +0 -17
  198. package/src/tools/get_current_time.md +0 -8
  199. package/src/tools/git-checkpoint.mjs +0 -143
  200. package/src/tools/git-ext.mjs +0 -173
  201. package/src/tools/git.md +0 -54
  202. package/src/tools/git.mjs +0 -356
  203. package/src/tools/glob-dialect.mjs +0 -130
  204. package/src/tools/glob.md +0 -11
  205. package/src/tools/grep.md +0 -19
  206. package/src/tools/hashline_edit.md +0 -14
  207. package/src/tools/index.mjs +0 -36
  208. package/src/tools/insert_after.md +0 -15
  209. package/src/tools/lint.md +0 -10
  210. package/src/tools/linter.mjs +0 -128
  211. package/src/tools/ls.md +0 -12
  212. package/src/tools/lsp.md +0 -10
  213. package/src/tools/lsp.mjs +0 -316
  214. package/src/tools/ops.mjs +0 -299
  215. package/src/tools/patch.mjs +0 -282
  216. package/src/tools/process.md +0 -10
  217. package/src/tools/question.md +0 -16
  218. package/src/tools/question.mjs +0 -26
  219. package/src/tools/read.md +0 -20
  220. package/src/tools/read_image.md +0 -8
  221. package/src/tools/repomap.mjs +0 -314
  222. package/src/tools/search.mjs +0 -236
  223. package/src/tools/shared.mjs +0 -446
  224. package/src/tools/tree.md +0 -14
  225. package/src/tools/tree.mjs +0 -66
  226. package/src/tools/wait_for.md +0 -22
  227. package/src/tools/web.mjs +0 -224
  228. package/src/tools/websearch.md +0 -16
  229. package/src/tools/write.md +0 -11
  230. package/src/traces/trace-store.mjs +0 -224
@@ -1,228 +0,0 @@
1
- /**
2
- * tools/execute.mjs — JavaScript execution tool
3
- *
4
- * Gives the model an `execute` tool that runs JS in a child `node
5
- * --input-type=module --eval` process — NOT the in-process vm sandbox it used
6
- * to be. The vm route could not support dynamic `import()` (needs the
7
- * --experimental-vm-modules flag) or await it, which pushed every real JS run
8
- * back to `bash node -e`. A child node process gives top-level await, dynamic
9
- * `import()` of the project's own .mjs modules, native `console`/`fetch`, AND a
10
- * killable timeout (an in-process infinite loop would freeze the CLI; a child
11
- * process is killed like bash).
12
- *
13
- * The child runs PURE node ESM — no helpers are injected (exec-prelude.mjs
14
- * retired 2026-09-03, TOOLS.md §12: preloaded readFile/writeFile/glob/grep/log
15
- * helpers made execute look like a file tool, bypassing the dedicated
16
- * read/ls/glob/grep/write/edit tools). Scripts that need fs/path import the
17
- * node: modules themselves — same boundary as bash, no fake sandbox.
18
- *
19
- * Parameters:
20
- * code — JS to run inline (top-level await and import() supported). Use this OR scriptFile.
21
- * scriptFile — run a .mjs/.js file with node (self-contained, imports what it needs). Use this OR code.
22
- * nodeArgs — (scriptFile) extra node flags before the script (e.g. --test, --check); eval-like flags rejected
23
- * workdir — run in this sub-directory (no directory restriction)
24
- * filter — return only output lines matching this regex (case-insensitive)
25
- * timeoutMs — timeout (default 30s, max 600000ms)
26
- */
27
- import { spawn, execFileSync } from "node:child_process"
28
- import { resolve } from "node:path"
29
- import { DESC } from "./shared.mjs"
30
-
31
- const MAX_SCRIPT = 50_000
32
- const MAX_OUTPUT = 50_000
33
- const DEFAULT_TIMEOUT = 30_000
34
-
35
- /**
36
- * 超时错误文本——带重试引导(TOOLS.md §14.1 D14.1.2——"下一跳"):数字 = 实际生效的
37
- * timeoutMs(Math.min(t, 600_000) 或默认 30s)——上限 600000 与 schema/头注/execute.md 一致。
38
- */
39
- const timeoutErrorText = (timeoutMs) =>
40
- `Error: script timed out after ${timeoutMs}ms — retry with a larger timeoutMs (up to 600000) for long scripts, or use bash (default 120s) for shell commands`
41
-
42
- /** Resolve workdir relative to cwd — no boundary assertion
43
- * (§10.1 2026-09-02: workspace confinement removed; the child node process is
44
- * not directory-limited — same boundary as bash). */
45
- function resolveBaseDir(cwd, workdir) {
46
- if (!workdir || typeof workdir !== "string") return cwd
47
- return resolve(cwd, workdir)
48
- }
49
-
50
- /** Keep only output lines matching a regex (execute filter, case-insensitive). */
51
- function applyFilter(output, filter) {
52
- try {
53
- const re = new RegExp(filter, "i")
54
- const lines = output.split("\n").filter((l) => re.test(l))
55
- return lines.length ? lines.join("\n") : `(no output lines matched filter "${filter}")`
56
- } catch (e) {
57
- return `Error: filter regex invalid: ${e.message}`
58
- }
59
- }
60
-
61
- /** Platform-aware process tree kill — mirror of system.mjs/verify.mjs killProcessTree.
62
- * Timeout/abort must reach grandchildren: a script that spawned children keeps the
63
- * pipes open otherwise — "close" never fires and the tool stalls until the 3s kick
64
- * while the orphan keeps running (2026-09-05 advisor 🟡#4). */
65
- function killProcessTree(child) {
66
- if (process.platform === "win32") {
67
- try { execFileSync("taskkill", ["/PID", String(child.pid), "/T", "/F"], { stdio: "ignore" }) } catch {}
68
- } else {
69
- try { process.kill(-child.pid, "SIGKILL") } catch {}
70
- try { child.kill("SIGKILL") } catch {}
71
- }
72
- }
73
-
74
- /** Spawn node with the given args, capture stdout/stderr, enforce timeout/abort.
75
- * Resolves { text, ok } — ok=false on non-zero exit / timeout / abort. */
76
- function runNode(childArgs, baseDir, timeoutMs, signal) {
77
- return new Promise((resolvePromise) => {
78
- const child = spawn(process.execPath, childArgs, {
79
- cwd: baseDir,
80
- stdio: ["ignore", "pipe", "pipe"],
81
- windowsHide: true,
82
- // POSIX detached → 子进程为组首——killProcessTree 的 -pid 组杀可达孙进程(win 用
83
- // taskkill /T 不需 detached)——2026-09-05 advisor 🟡#4
84
- detached: process.platform !== "win32",
85
- // 双保险(2026-09-05——裸 spawn 无 signal 教训——system.mjs 同款):abort 时
86
- // Node 自动杀直接子进程(第一道)——onAbort 手动 kill 兜底(SIGKILL 防信号陷阱
87
- // 脚本——见 kill 注释)——AbortError 在 error 分支让路(close 必随——走 mode 收尾)
88
- ...(signal ? { signal } : {}),
89
- })
90
-
91
- let outBuf = "", errBuf = "", truncated = false, settled = false, mode = null
92
- let timer = null, kickTimer = null
93
-
94
- const settle = (text, ok) => {
95
- if (settled) return
96
- settled = true
97
- clearTimeout(timer)
98
- clearTimeout(kickTimer)
99
- if (signal) signal.removeEventListener("abort", onAbort)
100
- resolvePromise({ text, ok })
101
- }
102
- // Tree kill(SIGKILL/taskkill /T——signal-trapping 脚本躲不开 watchdog;孙进程持管道
103
- // 时直接 kill 不达——close 不触发拖到 kick——2026-09-05 advisor 🟡#4 对齐 bash/verify)
104
- const kill = () => { killProcessTree(child) }
105
- // After kill, wait for "close" (child fully reaped) before settling — settling
106
- // early races the caller deleting the cwd dir while the child still holds it.
107
- const armKick = () => { kickTimer = setTimeout(() => settle(mode === "abort" ? "(stopped)" : timeoutErrorText(timeoutMs), false), 3000) }
108
- const onAbort = () => { if (mode) return; mode = "abort"; kill(); armKick() }
109
-
110
- timer = setTimeout(() => { if (!mode) { mode = "timeout"; kill(); armKick() } }, timeoutMs)
111
-
112
- if (signal) {
113
- if (signal.aborted) onAbort()
114
- else signal.addEventListener("abort", onAbort, { once: true })
115
- }
116
-
117
- const cap = (buf, d) => {
118
- if (buf.length < MAX_OUTPUT) return buf + d
119
- if (!truncated) { truncated = true; return buf + "\n...[output truncated]" }
120
- return buf
121
- }
122
- child.stdout.on("data", (d) => { outBuf = cap(outBuf, d.toString()) })
123
- child.stderr.on("data", (d) => { errBuf = cap(errBuf, d.toString()) })
124
- child.on("error", (e) => {
125
- // signal 双保险(2026-09-05):abort 时 Node signal option 杀子进程 → 本事件以
126
- // AbortError 先触发——让路(close 必随——close 分支 mode==="abort" →
127
- // settle("(stopped)"))——不把中止误报为启动失败
128
- if (e.name === "AbortError") return
129
- settle(`Error: failed to start node: ${e.message}`, false)
130
- })
131
- child.on("close", (code) => {
132
- if (mode === "abort") return settle("(stopped)", false)
133
- if (mode === "timeout") return settle(timeoutErrorText(timeoutMs), false)
134
- const out = outBuf.trimEnd()
135
- const err = errBuf.trim()
136
- if (code === 0) {
137
- settle(out || "(no output)", true)
138
- } else {
139
- settle(err ? (out ? `${out}\n\n[stderr]:\n${err}` : err) : `${out}\n(exit code ${code})`.trim(), false)
140
- }
141
- })
142
- })
143
- }
144
-
145
- /** Validate nodeArgs (extra node flags for scriptFile mode, e.g. --test / --check). Forbids
146
- * eval-like flags that would conflict with scriptFile mode or re-open inline injection. */
147
- function validateNodeArgs(nodeArgs) {
148
- if (!nodeArgs) return []
149
- const arr = Array.isArray(nodeArgs) ? nodeArgs : String(nodeArgs).split(/\s+/).filter(Boolean)
150
- const forbidden = /^(--eval|-e|--input-type|--print|-p|--inspect|--inspect-brk)(=|$)/i
151
- for (const a of arr) {
152
- if (forbidden.test(a)) throw new Error(`nodeArgs flag not allowed: ${a}`)
153
- }
154
- return arr
155
- }
156
-
157
- export const executeTool = {
158
- name: "execute",
159
- description: DESC("execute"),
160
- parameters: {
161
- type: "object",
162
- properties: {
163
- code: {
164
- type: "string",
165
- description: "JavaScript code to execute (top-level await and dynamic import() supported). Pure node ESM — no preloaded globals; import node: modules (fs/path) yourself when needed. File reads/writes go through the dedicated read/ls/glob/grep/write/edit tools. Use this OR scriptFile.",
166
- },
167
- scriptFile: {
168
- type: "string",
169
- description: "Run a .mjs/.js file with node (self-contained — the file imports what it needs). Path relative to workdir — no directory restriction. Use this OR code. For `node <script>` / `node --test <file>` / `node --check <file>`.",
170
- },
171
- nodeArgs: {
172
- type: "array",
173
- items: { type: "string" },
174
- description: "(scriptFile) Extra node flags before the script, e.g. [\"--test\"], [\"--check\"]. Eval-like flags (--eval/--input-type/--inspect) are rejected.",
175
- },
176
- workdir: {
177
- type: "string",
178
- description: "Run in this directory (relative to cwd — no directory restriction; default cwd)",
179
- },
180
- filter: {
181
- type: "string",
182
- description: "Optional: only return output lines matching this regex (case-insensitive)",
183
- },
184
- timeoutMs: {
185
- type: "integer",
186
- minimum: 1,
187
- maximum: 600000,
188
- description: `Timeout in milliseconds (default ${DEFAULT_TIMEOUT}, max 600000)`,
189
- },
190
- },
191
- required: [],
192
- },
193
- readonly: false,
194
-
195
- async execute(args, ctx) {
196
- let baseDir
197
- try { baseDir = resolveBaseDir(ctx.cwd, args.workdir) }
198
- catch (e) { return `Error: ${e.message}` }
199
-
200
- const t = Number(args.timeoutMs)
201
- const timeoutMs = Number.isFinite(t) && t > 0 ? Math.min(t, 600_000) : DEFAULT_TIMEOUT
202
-
203
- let childArgs
204
- if (args.scriptFile) {
205
- if (args.code?.trim()) return "Error: pass code OR scriptFile, not both"
206
- // scriptFile mode: run a .mjs/.js file with node [nodeArgs...]. Self-contained —
207
- // a real node process imports what it needs. No directory restriction.
208
- const scriptAbs = resolve(baseDir, args.scriptFile)
209
- let nodeArgs
210
- try { nodeArgs = validateNodeArgs(args.nodeArgs) }
211
- catch (e) { return `Error: ${e.message}` }
212
- childArgs = [...nodeArgs, scriptAbs]
213
- } else {
214
- const code = args.code ?? ""
215
- if (!code.trim()) return "Error: either code or scriptFile is required"
216
- if (code.length > MAX_SCRIPT) {
217
- return `Error: script too large (${code.length} > ${MAX_SCRIPT} bytes). Split into smaller scripts or use individual tools.`
218
- }
219
- // inline mode: pure node ESM — no prelude, nothing injected (TOOLS.md §12).
220
- childArgs = ["--input-type=module", "--eval", code]
221
- }
222
-
223
- const { text, ok } = await runNode(childArgs, baseDir, timeoutMs, ctx.signal)
224
- // Only filter successful output — never swallow an error report behind a filter.
225
- if (!ok) return text
226
- return args.filter ? applyFilter(text, args.filter) : text
227
- },
228
- }
@@ -1,12 +0,0 @@
1
- Fetch a URL and return its content as text. HTML pages are stripped to readable text. Use after websearch to read full documents.
2
-
3
- Parameters:
4
- - url (required): http/https URL
5
- - proxy: http://host:port explicit proxy (optional) — use ONLY when passed; no proxy = direct. config.json proxy is NOT auto-applied (2026-08-31 ruling); pick per target (github/foreign sites need a proxy, gitee/domestic don't)
6
-
7
- Notes:
8
- - Follows redirects automatically
9
- - Timeout: 15 seconds
10
- - HTML pages are converted to plain text (scripts, styles, navigation stripped)
11
- - Non-HTML responses are returned as-is (truncated at ~50000 chars)
12
- - Proxy support: set `"proxy": {"uri": "http://host:port", "web": true}` in config.json or `HTTPS_PROXY` env var