minimal-agent 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (573) hide show
  1. package/README.md +11 -3
  2. package/package.json +52 -5
  3. package/plugins/computer_use/.claude-plugin/plugin.json +6 -0
  4. package/plugins/computer_use/README.md +94 -0
  5. package/plugins/computer_use/app/_template.md +142 -0
  6. package/plugins/computer_use/app/chrome.md +165 -0
  7. package/plugins/computer_use/app/finder.md +76 -0
  8. package/plugins/computer_use/app/macos-system-settings.md +81 -0
  9. package/plugins/computer_use/app/microsoft-excel.md +80 -0
  10. package/plugins/computer_use/app/microsoft-powerpoint.md +80 -0
  11. package/plugins/computer_use/app/microsoft-word.md +79 -0
  12. package/plugins/computer_use/app/wechat.md +413 -0
  13. package/plugins/computer_use/app/weread.md +319 -0
  14. package/plugins/computer_use/commands/computeruse.md +25 -0
  15. package/plugins/computer_use/commands/cu.md +9 -0
  16. package/plugins/computer_use/plugin.js +26 -0
  17. package/plugins/computer_use/plugin.ts +30 -0
  18. package/plugins/computer_use/src/capture.js +90 -0
  19. package/plugins/computer_use/src/capture.ts +104 -0
  20. package/plugins/computer_use/src/commands.js +91 -0
  21. package/plugins/computer_use/src/commands.ts +103 -0
  22. package/plugins/computer_use/src/daemon.js +134 -0
  23. package/plugins/computer_use/src/daemon.ts +161 -0
  24. package/plugins/computer_use/src/manuals.js +135 -0
  25. package/plugins/computer_use/src/manuals.ts +159 -0
  26. package/plugins/computer_use/src/verify.js +168 -0
  27. package/plugins/computer_use/src/verify.ts +219 -0
  28. package/plugins/computer_use/test/commands.test.ts +73 -0
  29. package/plugins/cron-runner/plugin.ts +38 -0
  30. package/plugins/cron-runner/src/commands.ts +373 -0
  31. package/plugins/cron-runner/src/cronTime.ts +155 -0
  32. package/plugins/cron-runner/src/lock.ts +79 -0
  33. package/plugins/cron-runner/src/runs.ts +99 -0
  34. package/plugins/cron-runner/src/scheduleEngine.ts +76 -0
  35. package/plugins/cron-runner/src/scheduler.ts +376 -0
  36. package/plugins/cron-runner/src/schema.ts +139 -0
  37. package/plugins/cron-runner/src/service.ts +193 -0
  38. package/plugins/cron-runner/src/store.ts +333 -0
  39. package/plugins/cron-runner/src/types.ts +141 -0
  40. package/plugins/cron-runner/test/cronTime.test.ts +41 -0
  41. package/plugins/cron-runner/test/plugin-integration.test.ts +47 -0
  42. package/plugins/cron-runner/test/scheduleEngine.test.ts +41 -0
  43. package/plugins/cron-runner/test/service.test.ts +76 -0
  44. package/plugins/cron-runner/test/store-and-scheduler.test.ts +501 -0
  45. package/plugins/workflow-runner/plugin.js +56 -2
  46. package/plugins/workflow-runner/plugin.ts +113 -0
  47. package/plugins/workflow-runner/src/agentCommon.js +43 -4
  48. package/plugins/workflow-runner/src/agentCommon.ts +435 -0
  49. package/plugins/workflow-runner/src/controlFlow/branch.js +40 -0
  50. package/plugins/workflow-runner/src/controlFlow/branch.ts +46 -0
  51. package/plugins/workflow-runner/src/controlFlow/loop.js +211 -0
  52. package/plugins/workflow-runner/src/controlFlow/loop.ts +248 -0
  53. package/plugins/workflow-runner/src/controlFlow/pause.js +129 -0
  54. package/plugins/workflow-runner/src/controlFlow/pause.ts +141 -0
  55. package/plugins/workflow-runner/src/controlFlow/signal.js +21 -0
  56. package/plugins/workflow-runner/src/controlFlow/signal.ts +29 -0
  57. package/plugins/workflow-runner/src/controlFlow/types.js +18 -0
  58. package/plugins/workflow-runner/src/controlFlow/types.ts +63 -0
  59. package/plugins/workflow-runner/src/dslManifest.ts +127 -0
  60. package/plugins/workflow-runner/src/expressions.ts +622 -0
  61. package/plugins/workflow-runner/src/index.js +13 -4
  62. package/plugins/workflow-runner/src/index.ts +338 -0
  63. package/plugins/workflow-runner/src/jsonPayload.ts +84 -0
  64. package/plugins/workflow-runner/src/loader.js +23 -0
  65. package/plugins/workflow-runner/src/loader.ts +721 -0
  66. package/plugins/workflow-runner/src/multimodal.js +2 -1
  67. package/plugins/workflow-runner/src/multimodal.ts +64 -0
  68. package/plugins/workflow-runner/src/recovery.ts +149 -0
  69. package/plugins/workflow-runner/src/runner.js +75 -659
  70. package/plugins/workflow-runner/src/runner.ts +604 -0
  71. package/plugins/workflow-runner/src/stepExecutors/agent.ts +234 -0
  72. package/plugins/workflow-runner/src/stepExecutors/assert.ts +50 -0
  73. package/plugins/workflow-runner/src/stepExecutors/echo.js +31 -0
  74. package/plugins/workflow-runner/src/stepExecutors/echo.ts +38 -0
  75. package/plugins/workflow-runner/src/stepExecutors/llm.ts +133 -0
  76. package/plugins/workflow-runner/src/stepExecutors/set.js +49 -0
  77. package/plugins/workflow-runner/src/stepExecutors/set.ts +56 -0
  78. package/plugins/workflow-runner/src/stepExecutors/skill.js +5 -6
  79. package/plugins/workflow-runner/src/stepExecutors/skill.ts +140 -0
  80. package/plugins/workflow-runner/src/stepExecutors/tool.js +80 -8
  81. package/plugins/workflow-runner/src/stepExecutors/tool.ts +256 -0
  82. package/plugins/workflow-runner/src/stepExecutors/verify.ts +68 -0
  83. package/plugins/workflow-runner/src/stepPipeline.js +277 -0
  84. package/plugins/workflow-runner/src/stepPipeline.ts +366 -0
  85. package/plugins/workflow-runner/src/taskIdentity.ts +405 -0
  86. package/plugins/workflow-runner/src/toolRuntime.js +48 -0
  87. package/plugins/workflow-runner/src/toolRuntime.ts +64 -0
  88. package/plugins/workflow-runner/src/types.js +37 -1
  89. package/plugins/workflow-runner/src/types.ts +602 -0
  90. package/plugins/workflow-runner/src/workflowState.ts +733 -0
  91. package/plugins/workflow-runner/test/agent.test.ts +587 -0
  92. package/plugins/workflow-runner/test/agentLlmError.test.ts +373 -0
  93. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +65 -0
  94. package/plugins/workflow-runner/test/captureMisbind.test.ts +99 -0
  95. package/plugins/workflow-runner/test/cli.e2e.test.ts +147 -0
  96. package/plugins/workflow-runner/test/context-files.test.ts +320 -0
  97. package/plugins/workflow-runner/test/e2e.test.ts +370 -0
  98. package/plugins/workflow-runner/test/engineRobustness.test.ts +226 -0
  99. package/plugins/workflow-runner/test/expressions.test.ts +397 -0
  100. package/plugins/workflow-runner/test/foundation.test.ts +126 -0
  101. package/plugins/workflow-runner/test/graceful.test.ts +139 -0
  102. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +47 -0
  103. package/plugins/workflow-runner/test/hostCapability.test.ts +108 -0
  104. package/plugins/workflow-runner/test/illustrate.load.test.ts +183 -0
  105. package/plugins/workflow-runner/test/jsonPayload.test.ts +83 -0
  106. package/plugins/workflow-runner/test/loader.test.ts +617 -0
  107. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +33 -0
  108. package/plugins/workflow-runner/test/multimodal.test.ts +342 -0
  109. package/plugins/workflow-runner/test/output-schema.test.ts +213 -0
  110. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +87 -0
  111. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +269 -0
  112. package/plugins/workflow-runner/test/ppt.load.test.ts +1220 -0
  113. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +220 -0
  114. package/plugins/workflow-runner/test/recovery.test.ts +265 -0
  115. package/plugins/workflow-runner/test/runner.test.ts +911 -0
  116. package/plugins/workflow-runner/test/runnerPreflight.test.ts +379 -0
  117. package/plugins/workflow-runner/test/skillTurnDone.test.ts +71 -0
  118. package/plugins/workflow-runner/test/stateLifecycle.test.ts +150 -0
  119. package/plugins/workflow-runner/test/stepPipeline.test.ts +114 -0
  120. package/plugins/workflow-runner/test/taskArbitration.test.ts +338 -0
  121. package/plugins/workflow-runner/test/taskIdentity.test.ts +237 -0
  122. package/plugins/workflow-runner/test/taskLifecycle.test.ts +270 -0
  123. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +221 -0
  124. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +29 -0
  125. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +168 -0
  126. package/plugins/workflow-runner/test/webppt.load.test.ts +250 -0
  127. package/plugins/workflow-runner/test/word.load.test.ts +208 -0
  128. package/plugins/workflow-runner/test/workflows.smoke.test.ts +76 -0
  129. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +207 -0
  130. package/skills/browser-automation/SKILL.md +9 -19
  131. package/skills/web-crawler/SKILL.md +9 -11
  132. package/src/askBridge.ts +249 -0
  133. package/src/bootstrap/cwdArg.js +10 -3
  134. package/src/bootstrap/cwdArg.ts +31 -0
  135. package/src/bootstrap/workingDir.ts +48 -0
  136. package/src/cli/args.js +70 -7
  137. package/src/cli/args.ts +146 -0
  138. package/src/cli/computerUse.js +185 -0
  139. package/src/cli/computerUse.ts +221 -0
  140. package/src/cli/configMenu.js +274 -202
  141. package/src/cli/configMenu.tsx +521 -0
  142. package/src/cli/memoryAccess.js +45 -0
  143. package/src/cli/memoryAccess.ts +53 -0
  144. package/src/cli/print.js +119 -5
  145. package/src/cli/print.ts +597 -0
  146. package/src/cli/quickModelSetup.js +60 -0
  147. package/src/cli/quickModelSetup.tsx +96 -0
  148. package/src/cli/streamJson.js +80 -4
  149. package/src/cli/streamJson.ts +433 -0
  150. package/src/cli/wizards/advisorWizard.js +1 -0
  151. package/src/cli/wizards/advisorWizard.tsx +195 -0
  152. package/src/cli/wizards/agentRuntimeWizard.js +84 -0
  153. package/src/cli/wizards/agentRuntimeWizard.tsx +134 -0
  154. package/src/cli/wizards/browserWizard.js +55 -0
  155. package/src/cli/wizards/browserWizard.tsx +77 -0
  156. package/src/cli/wizards/contextAdvisorWizard.js +84 -0
  157. package/src/cli/wizards/contextAdvisorWizard.tsx +124 -0
  158. package/src/cli/wizards/fieldForm.js +7 -4
  159. package/src/cli/wizards/fieldForm.tsx +250 -0
  160. package/src/cli/wizards/imageWizard.js +4 -5
  161. package/src/cli/wizards/imageWizard.tsx +96 -0
  162. package/src/cli/wizards/openRouterWizard.tsx +48 -0
  163. package/src/cli/wizards/providerPresets.js +1 -8
  164. package/src/cli/wizards/providerPresets.ts +106 -0
  165. package/src/cli/wizards/providerWizard.js +152 -205
  166. package/src/cli/wizards/providerWizard.tsx +266 -0
  167. package/src/cli/wizards/searchWizard.tsx +47 -0
  168. package/src/cli/wizards/ttsWizard.js +4 -3
  169. package/src/cli/wizards/ttsWizard.tsx +61 -0
  170. package/src/config/configDefaults.js +25 -0
  171. package/src/config/configDefaults.ts +33 -0
  172. package/src/config/configDiagnostics.js +117 -0
  173. package/src/config/configDiagnostics.ts +166 -0
  174. package/src/config/configFile.js +52 -32
  175. package/src/config/configFile.ts +633 -0
  176. package/src/config/configManagement.js +126 -0
  177. package/src/config/configManagement.ts +159 -0
  178. package/src/config/configService.js +66 -11
  179. package/src/config/configService.ts +554 -0
  180. package/src/config/numericLimits.js +61 -0
  181. package/src/config/numericLimits.ts +80 -0
  182. package/src/config.ts +109 -0
  183. package/src/context/agentHome.ts +11 -0
  184. package/src/context/archive.ts +144 -0
  185. package/src/context/budgetPlan.js +54 -0
  186. package/src/context/budgetPlan.ts +88 -0
  187. package/src/context/compact.js +179 -106
  188. package/src/context/compact.ts +584 -0
  189. package/src/context/contextBundle.js +119 -0
  190. package/src/context/contextBundle.ts +176 -0
  191. package/src/context/contextLock.ts +84 -0
  192. package/src/context/microCompactLite.ts +218 -0
  193. package/src/context/persistContext.ts +177 -0
  194. package/src/context/reactiveCompact.js +19 -4
  195. package/src/context/reactiveCompact.ts +240 -0
  196. package/src/context/recentDirs.ts +42 -0
  197. package/src/context/sessionPath.ts +206 -0
  198. package/src/context/sessionRegistry.js +8 -2
  199. package/src/context/sessionRegistry.ts +414 -0
  200. package/src/context/snipCompact.ts +163 -0
  201. package/src/context/tokenCounter.ts +106 -0
  202. package/src/context/workspaceIndex.js +2 -2
  203. package/src/context/workspaceIndex.ts +751 -0
  204. package/src/entry.compiled.tsx +20 -0
  205. package/src/harness/claimValidation.js +9 -0
  206. package/src/harness/claimValidation.ts +22 -0
  207. package/src/harness/evidenceLedger.js +92 -0
  208. package/src/harness/evidenceLedger.ts +96 -0
  209. package/src/harness/stallGuard.js +60 -0
  210. package/src/harness/stallGuard.ts +81 -0
  211. package/src/humanIntervention.js +129 -0
  212. package/src/humanIntervention.ts +216 -0
  213. package/src/infra/verification.ts +295 -0
  214. package/src/irreversible/rules.js +216 -0
  215. package/src/irreversible/rules.ts +261 -0
  216. package/src/llm/client.js +40 -3
  217. package/src/llm/client.ts +621 -0
  218. package/src/llm/promptCache.js +27 -0
  219. package/src/llm/promptCache.ts +41 -0
  220. package/src/llm/providers/anthropicFormat.js +41 -5
  221. package/src/llm/providers/anthropicFormat.ts +290 -0
  222. package/src/llm/providers/openaiFormat.js +186 -8
  223. package/src/llm/providers/openaiFormat.ts +428 -0
  224. package/src/loop.js +614 -63
  225. package/src/loop.ts +1454 -0
  226. package/src/main.js +67 -10
  227. package/src/main.tsx +344 -0
  228. package/src/memory/codec.js +204 -0
  229. package/src/memory/codec.ts +249 -0
  230. package/src/memory/constants.js +34 -0
  231. package/src/memory/constants.ts +50 -0
  232. package/src/memory/episodicMemory.js +684 -0
  233. package/src/memory/episodicMemory.ts +815 -0
  234. package/src/memory/fileStore.js +148 -0
  235. package/src/memory/fileStore.ts +184 -0
  236. package/src/memory/memoryService.js +570 -0
  237. package/src/memory/memoryService.ts +859 -0
  238. package/src/memory/migration.js +128 -0
  239. package/src/memory/migration.ts +160 -0
  240. package/src/memory/repository.js +789 -0
  241. package/src/memory/repository.ts +893 -0
  242. package/src/memory/retrieval.js +108 -0
  243. package/src/memory/retrieval.ts +145 -0
  244. package/src/memory/searchIndex.js +107 -0
  245. package/src/memory/searchIndex.ts +153 -0
  246. package/src/memory/topicView.js +82 -0
  247. package/src/memory/topicView.ts +95 -0
  248. package/src/memory/turnJournal.js +95 -0
  249. package/src/memory/turnJournal.ts +120 -0
  250. package/src/memory/types.js +2 -0
  251. package/src/memory/types.ts +186 -0
  252. package/src/messageQueue.ts +123 -0
  253. package/src/multimodal.js +128 -46
  254. package/src/multimodal.ts +349 -0
  255. package/src/plugin-sdk.js +21 -1
  256. package/src/plugin-sdk.ts +134 -0
  257. package/src/plugins/builtinPluginIds.js +47 -0
  258. package/src/plugins/builtinPluginIds.ts +51 -0
  259. package/src/plugins/builtinRegistry.ts +43 -0
  260. package/src/plugins/commandRouter.js +40 -26
  261. package/src/plugins/commandRouter.ts +261 -0
  262. package/src/plugins/hookEngine.ts +341 -0
  263. package/src/plugins/pluginApi.ts +133 -0
  264. package/src/plugins/pluginLifecycle.ts +34 -0
  265. package/src/plugins/pluginLoader.ts +147 -0
  266. package/src/plugins/pluginManifest.js +127 -0
  267. package/src/plugins/pluginManifest.ts +152 -0
  268. package/src/plugins/pluginRunner.js +47 -2
  269. package/src/plugins/pluginRunner.ts +207 -0
  270. package/src/plugins/transcript.ts +208 -0
  271. package/src/prompts/lint.js +169 -0
  272. package/src/prompts/lint.ts +220 -0
  273. package/src/prompts/pluginList.js +32 -16
  274. package/src/prompts/pluginList.ts +86 -0
  275. package/src/prompts/policyRegistry.js +318 -0
  276. package/src/prompts/policyRegistry.ts +358 -0
  277. package/src/prompts/projectInstructions.js +24 -0
  278. package/src/prompts/projectInstructions.ts +81 -0
  279. package/src/prompts/promptAssembly.js +311 -202
  280. package/src/prompts/promptAssembly.ts +510 -0
  281. package/src/prompts/skillList.js +106 -45
  282. package/src/prompts/skillList.ts +198 -0
  283. package/src/prompts/system.js +31 -6
  284. package/src/prompts/system.ts +81 -0
  285. package/src/runtime/agentRuntimeContext.js +53 -0
  286. package/src/runtime/agentRuntimeContext.ts +112 -0
  287. package/src/session/runAgentTurn.js +71 -12
  288. package/src/session/runAgentTurn.ts +181 -0
  289. package/src/session/runTurn.js +29 -0
  290. package/src/session/runTurn.ts +160 -0
  291. package/src/session/runtimeStore.js +149 -0
  292. package/src/session/runtimeStore.ts +197 -0
  293. package/src/session/sessionState.js +79 -3
  294. package/src/session/sessionState.ts +134 -0
  295. package/src/toolGate.ts +50 -0
  296. package/src/tools/advisor/advisor.js +76 -15
  297. package/src/tools/advisor/advisor.ts +512 -0
  298. package/src/tools/agent/agent.js +245 -29
  299. package/src/tools/agent/agent.ts +837 -0
  300. package/src/tools/agent/agentTaskService.js +60 -0
  301. package/src/tools/agent/agentTaskService.ts +113 -0
  302. package/src/tools/agent/agentTypes.js +20 -8
  303. package/src/tools/agent/agentTypes.ts +94 -0
  304. package/src/tools/agent/coordinator.ts +111 -0
  305. package/src/tools/agent/worktree.ts +296 -0
  306. package/src/tools/ask/ask.js +17 -0
  307. package/src/tools/ask/ask.ts +122 -0
  308. package/src/tools/bash/attachImage.js +223 -0
  309. package/src/tools/bash/attachImage.ts +281 -0
  310. package/src/tools/bash/bash.js +132 -14
  311. package/src/tools/bash/bash.ts +642 -0
  312. package/src/tools/bash/semantics.ts +103 -0
  313. package/src/tools/bash/warnings.js +17 -11
  314. package/src/tools/bash/warnings.ts +117 -0
  315. package/src/tools/capabilities.js +42 -0
  316. package/src/tools/capabilities.ts +69 -0
  317. package/src/tools/computeruse/accessibilityPermission.js +261 -0
  318. package/src/tools/computeruse/accessibilityPermission.ts +294 -0
  319. package/src/tools/computeruse/axSearch.js +96 -0
  320. package/src/tools/computeruse/axSearch.ts +120 -0
  321. package/src/tools/computeruse/axSnap.js +272 -0
  322. package/src/tools/computeruse/axSnap.ts +349 -0
  323. package/src/tools/computeruse/capabilityLabels.js +95 -0
  324. package/src/tools/computeruse/capabilityLabels.ts +115 -0
  325. package/src/tools/computeruse/computerUseService.js +2235 -0
  326. package/src/tools/computeruse/computerUseService.ts +2686 -0
  327. package/src/tools/computeruse/computeruse.js +2742 -0
  328. package/src/tools/computeruse/computeruse.ts +3265 -0
  329. package/src/tools/computeruse/diagnosticTrace.js +154 -0
  330. package/src/tools/computeruse/diagnosticTrace.ts +195 -0
  331. package/src/tools/computeruse/diagnostics.js +369 -0
  332. package/src/tools/computeruse/diagnostics.ts +453 -0
  333. package/src/tools/computeruse/grants.js +53 -0
  334. package/src/tools/computeruse/grants.ts +70 -0
  335. package/src/tools/computeruse/humanBoundary.js +159 -0
  336. package/src/tools/computeruse/humanBoundary.ts +199 -0
  337. package/src/tools/computeruse/intervention.js +77 -0
  338. package/src/tools/computeruse/intervention.ts +110 -0
  339. package/src/tools/computeruse/manualSchema.js +709 -0
  340. package/src/tools/computeruse/manualSchema.ts +916 -0
  341. package/src/tools/computeruse/observationImages.js +705 -0
  342. package/src/tools/computeruse/observationImages.ts +889 -0
  343. package/src/tools/computeruse/protocol.js +60 -0
  344. package/src/tools/computeruse/protocol.ts +515 -0
  345. package/src/tools/computeruse/telemetryLog.js +57 -0
  346. package/src/tools/computeruse/telemetryLog.ts +67 -0
  347. package/src/tools/computeruse/vision/appGuide.js +325 -0
  348. package/src/tools/computeruse/vision/appGuide.ts +482 -0
  349. package/src/tools/computeruse/vision/focus.js +291 -0
  350. package/src/tools/computeruse/vision/focus.ts +382 -0
  351. package/src/tools/computeruse/vision/frames.js +248 -0
  352. package/src/tools/computeruse/vision/frames.ts +329 -0
  353. package/src/tools/computeruse/vision/geometry.js +131 -0
  354. package/src/tools/computeruse/vision/geometry.ts +163 -0
  355. package/src/tools/computeruse/vision/imaging.js +201 -0
  356. package/src/tools/computeruse/vision/imaging.ts +281 -0
  357. package/src/tools/computeruse/vision/png.js +274 -0
  358. package/src/tools/computeruse/vision/png.ts +317 -0
  359. package/src/tools/computeruse/vision/raster.js +320 -0
  360. package/src/tools/computeruse/vision/raster.ts +408 -0
  361. package/src/tools/computeruse/vision/settle.js +131 -0
  362. package/src/tools/computeruse/vision/settle.ts +220 -0
  363. package/src/tools/computeruse/vision/telemetry.js +196 -0
  364. package/src/tools/computeruse/vision/telemetry.ts +241 -0
  365. package/src/tools/computeruse/visionOcr.js +115 -0
  366. package/src/tools/computeruse/visionOcr.ts +128 -0
  367. package/src/tools/computeruse/waitFor.js +237 -0
  368. package/src/tools/computeruse/waitFor.ts +291 -0
  369. package/src/tools/download/download.js +10 -6
  370. package/src/tools/download/download.ts +187 -0
  371. package/src/tools/edit/edit.js +30 -18
  372. package/src/tools/edit/edit.ts +349 -0
  373. package/src/tools/edit/multi-edit.js +25 -14
  374. package/src/tools/edit/multi-edit.ts +223 -0
  375. package/src/tools/effectiveToolSet.js +73 -0
  376. package/src/tools/effectiveToolSet.ts +91 -0
  377. package/src/tools/genimage/genimage.ts +257 -0
  378. package/src/tools/genspeech/genspeech.ts +83 -0
  379. package/src/tools/glob/glob.js +176 -29
  380. package/src/tools/glob/glob.ts +283 -0
  381. package/src/tools/grep/grep.js +61 -19
  382. package/src/tools/grep/grep.ts +239 -0
  383. package/src/tools/grep/rgPath.ts +206 -0
  384. package/src/tools/index.js +99 -5
  385. package/src/tools/index.ts +293 -0
  386. package/src/tools/lsp/config.js +113 -0
  387. package/src/tools/lsp/config.ts +113 -0
  388. package/src/tools/lsp/lsp.js +256 -0
  389. package/src/tools/lsp/lsp.ts +274 -0
  390. package/src/tools/lsp/service.js +303 -0
  391. package/src/tools/lsp/service.ts +296 -0
  392. package/src/tools/memory/memory.js +520 -0
  393. package/src/tools/memory/memory.ts +625 -0
  394. package/src/tools/memory/policy.js +53 -0
  395. package/src/tools/memory/policy.ts +72 -0
  396. package/src/tools/notebook/notebookEdit.js +114 -0
  397. package/src/tools/notebook/notebookEdit.ts +126 -0
  398. package/src/tools/powershell/powershell.js +210 -0
  399. package/src/tools/powershell/powershell.ts +239 -0
  400. package/src/tools/presentresult/presentresult.js +145 -0
  401. package/src/tools/presentresult/presentresult.ts +156 -0
  402. package/src/tools/read/read.js +371 -163
  403. package/src/tools/read/read.ts +558 -0
  404. package/src/tools/shared/diffSummary.js +44 -0
  405. package/src/tools/shared/diffSummary.ts +63 -0
  406. package/src/tools/shared/fileActivity.js +51 -0
  407. package/src/tools/shared/fileActivity.ts +66 -0
  408. package/src/tools/shared/fileMutationBus.js +13 -0
  409. package/src/tools/shared/fileMutationBus.ts +14 -0
  410. package/src/tools/shared/fileState.js +73 -65
  411. package/src/tools/shared/fileState.ts +145 -0
  412. package/src/tools/shared/fileUtils.js +81 -4
  413. package/src/tools/shared/fileUtils.ts +504 -0
  414. package/src/tools/shared/killTree.ts +50 -0
  415. package/src/tools/shared/permanentDeleteGuard.js +26 -0
  416. package/src/tools/shared/permanentDeleteGuard.ts +34 -0
  417. package/src/tools/shared/schemas.ts +20 -0
  418. package/src/tools/shared/toolOutputStore.js +97 -0
  419. package/src/tools/shared/toolOutputStore.ts +110 -0
  420. package/src/tools/skill/skill.js +86 -0
  421. package/src/tools/skill/skill.ts +94 -0
  422. package/src/tools/snip/snip.js +67 -0
  423. package/src/tools/snip/snip.ts +80 -0
  424. package/src/tools/tasks/backgroundTaskService.js +275 -0
  425. package/src/tools/tasks/backgroundTaskService.ts +369 -0
  426. package/src/tools/tasks/processEvidence.js +24 -0
  427. package/src/tools/tasks/processEvidence.ts +34 -0
  428. package/src/tools/tasks/taskManagement.js +163 -0
  429. package/src/tools/tasks/taskManagement.ts +180 -0
  430. package/src/tools/tasks/taskOutput.js +113 -0
  431. package/src/tools/tasks/taskOutput.ts +145 -0
  432. package/src/tools/tasks/taskStop.js +74 -0
  433. package/src/tools/tasks/taskStop.ts +99 -0
  434. package/src/tools/tasks/taskStore.js +46 -0
  435. package/src/tools/tasks/taskStore.ts +77 -0
  436. package/src/tools/terminal/terminalCapture.js +167 -0
  437. package/src/tools/terminal/terminalCapture.ts +179 -0
  438. package/src/tools/trash/trash.js +233 -0
  439. package/src/tools/trash/trash.ts +283 -0
  440. package/src/tools/types.js +1 -1
  441. package/src/tools/types.ts +24 -0
  442. package/src/tools/webbrowser/agentBrowserPath.ts +286 -0
  443. package/src/tools/webbrowser/browser.js +214 -11
  444. package/src/tools/webbrowser/browser.ts +293 -0
  445. package/src/tools/webbrowser/browserControl.js +153 -48
  446. package/src/tools/webbrowser/browserControl.ts +262 -0
  447. package/src/tools/webbrowser/browserDaemon.js +147 -39
  448. package/src/tools/webbrowser/browserDaemon.ts +270 -0
  449. package/src/tools/webbrowser/browserOutcome.js +273 -0
  450. package/src/tools/webbrowser/browserOutcome.ts +306 -0
  451. package/src/tools/webbrowser/browserRunRegistry.js +150 -0
  452. package/src/tools/webbrowser/browserRunRegistry.ts +179 -0
  453. package/src/tools/webbrowser/browserService.js +20 -6
  454. package/src/tools/webbrowser/browserService.ts +56 -0
  455. package/src/tools/webbrowser/browserStream.js +30 -1
  456. package/src/tools/webbrowser/browserStream.ts +216 -0
  457. package/src/tools/webbrowser/browserTabs.js +143 -0
  458. package/src/tools/webbrowser/browserTabs.ts +210 -0
  459. package/src/tools/webbrowser/webbrowser.js +831 -150
  460. package/src/tools/webbrowser/webbrowser.ts +1537 -0
  461. package/src/tools/webfetch/preapproved.ts +274 -0
  462. package/src/tools/webfetch/webfetch.js +24 -23
  463. package/src/tools/webfetch/webfetch.ts +383 -0
  464. package/src/tools/websearch/websearch.js +12 -11
  465. package/src/tools/websearch/websearch.ts +292 -0
  466. package/src/tools/worktree/sessionWorktree.js +128 -0
  467. package/src/tools/worktree/sessionWorktree.ts +158 -0
  468. package/src/tools/write/write.js +27 -44
  469. package/src/tools/write/write.ts +136 -0
  470. package/src/types.ts +960 -0
  471. package/src/ui/App.js +216 -12
  472. package/src/ui/App.tsx +879 -0
  473. package/src/ui/AskQuestion.tsx +300 -0
  474. package/src/ui/InputBox.js +77 -1
  475. package/src/ui/InputBox.tsx +567 -0
  476. package/src/ui/LiveArea.tsx +344 -0
  477. package/src/ui/MessageList.js +27 -6
  478. package/src/ui/MessageList.tsx +559 -0
  479. package/src/ui/ModelPicker.tsx +107 -0
  480. package/src/ui/QueuedMessagesBanner.tsx +51 -0
  481. package/src/ui/Root.js +6 -8
  482. package/src/ui/Root.tsx +100 -0
  483. package/src/ui/SessionPicker.tsx +169 -0
  484. package/src/ui/StatusLine.js +22 -1
  485. package/src/ui/StatusLine.tsx +145 -0
  486. package/src/ui/WorkspacePicker.tsx +84 -0
  487. package/src/ui/advisorCommand.js +54 -0
  488. package/src/ui/advisorCommand.ts +63 -0
  489. package/src/ui/computerCommand.js +19 -0
  490. package/src/ui/computerCommand.ts +35 -0
  491. package/src/ui/figures.ts +45 -0
  492. package/src/ui/hooks/askSlot.ts +112 -0
  493. package/src/ui/hooks/useChat.js +271 -7
  494. package/src/ui/hooks/useChat.ts +1578 -0
  495. package/src/ui/hooks/useInputHistory.ts +235 -0
  496. package/src/ui/hooks/usePasteHandler.ts +220 -0
  497. package/src/ui/hooks/useTerminalSize.ts +41 -0
  498. package/src/ui/hooks/useTextBuffer.ts +108 -0
  499. package/src/ui/hooks/useTokenUsage.ts +44 -0
  500. package/src/ui/liveViewport.ts +189 -0
  501. package/src/ui/markdown.ts +230 -0
  502. package/src/ui/textBuffer.ts +239 -0
  503. package/src/ui/theme.ts +35 -0
  504. package/src/utils/clipboardImage.js +358 -0
  505. package/src/utils/clipboardImage.ts +420 -0
  506. package/src/utils/debugLog.ts +50 -0
  507. package/src/utils/greenRoot.ts +35 -0
  508. package/src/utils/packageRoot.ts +40 -0
  509. package/src/utils/pathContains.js +28 -0
  510. package/src/utils/pathContains.ts +31 -0
  511. package/src/utils/resourcePaths.ts +71 -0
  512. package/src/utils/stripThink.ts +49 -0
  513. package/src/utils/zodToJson.ts +73 -0
  514. package/src/web/browserBridge.js +365 -66
  515. package/src/web/browserBridge.ts +672 -0
  516. package/src/web/protocol.ts +1804 -0
  517. package/vendor/computer-use/arm64-darwin/cu-helperd +0 -0
  518. package/workflows/ppt.yaml +13 -2
  519. package/workflows/wechat-reading-shots.yaml +315 -0
  520. package/workflows/word.yaml +11 -1
  521. package/skills/docx/scripts/office/helpers/__pycache__/__init__.cpython-314.pyc +0 -0
  522. package/skills/docx/scripts/office/helpers/__pycache__/merge_runs.cpython-314.pyc +0 -0
  523. package/skills/docx/scripts/office/helpers/__pycache__/simplify_redlines.cpython-314.pyc +0 -0
  524. package/skills/docx/scripts/office/validators/__pycache__/__init__.cpython-314.pyc +0 -0
  525. package/skills/docx/scripts/office/validators/__pycache__/base.cpython-314.pyc +0 -0
  526. package/skills/docx/scripts/office/validators/__pycache__/docx.cpython-314.pyc +0 -0
  527. package/skills/docx/scripts/office/validators/__pycache__/pptx.cpython-314.pyc +0 -0
  528. package/skills/docx/scripts/office/validators/__pycache__/redlining.cpython-314.pyc +0 -0
  529. package/skills/image-stats/scripts/__pycache__/image_stats.cpython-314.pyc +0 -0
  530. package/skills/image-stats/scripts/__pycache__/image_stats_test.cpython-314.pyc +0 -0
  531. package/skills/ui-design/scripts/__pycache__/assemble_material.cpython-314.pyc +0 -0
  532. package/skills/ui-design/scripts/__pycache__/assemble_material_test.cpython-314.pyc +0 -0
  533. package/skills/ui-design/scripts/__pycache__/chart_sanity_check.cpython-314.pyc +0 -0
  534. package/skills/ui-design/scripts/__pycache__/check_language_policy.cpython-314.pyc +0 -0
  535. package/skills/ui-design/scripts/__pycache__/check_ui_artifact.cpython-314.pyc +0 -0
  536. package/skills/ui-design/scripts/__pycache__/check_ui_artifact_pptx_test.cpython-314.pyc +0 -0
  537. package/skills/ui-design/scripts/__pycache__/deck_pages_check.cpython-314.pyc +0 -0
  538. package/skills/ui-design/scripts/__pycache__/deck_pages_check_test.cpython-314.pyc +0 -0
  539. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check.cpython-314.pyc +0 -0
  540. package/skills/ui-design/scripts/__pycache__/deck_visual_style_check_test.cpython-314.pyc +0 -0
  541. package/skills/ui-design/scripts/__pycache__/design_budget_check.cpython-314.pyc +0 -0
  542. package/skills/ui-design/scripts/__pycache__/design_budget_check_test.cpython-314.pyc +0 -0
  543. package/skills/ui-design/scripts/__pycache__/design_repair_hints.cpython-314.pyc +0 -0
  544. package/skills/ui-design/scripts/__pycache__/design_repair_hints_test.cpython-314.pyc +0 -0
  545. package/skills/ui-design/scripts/__pycache__/design_style_check.cpython-314.pyc +0 -0
  546. package/skills/ui-design/scripts/__pycache__/design_style_check_test.cpython-314.pyc +0 -0
  547. package/skills/ui-design/scripts/__pycache__/draft_coverage_check.cpython-314.pyc +0 -0
  548. package/skills/ui-design/scripts/__pycache__/extract_source_assets.cpython-314.pyc +0 -0
  549. package/skills/ui-design/scripts/__pycache__/extract_source_assets_test.cpython-314.pyc +0 -0
  550. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect.cpython-314.pyc +0 -0
  551. package/skills/ui-design/scripts/__pycache__/generated_image_review_collect_test.cpython-314.pyc +0 -0
  552. package/skills/ui-design/scripts/__pycache__/image_plan_lint.cpython-314.pyc +0 -0
  553. package/skills/ui-design/scripts/__pycache__/image_plan_lint_test.cpython-314.pyc +0 -0
  554. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite.cpython-314.pyc +0 -0
  555. package/skills/ui-design/scripts/__pycache__/image_prompt_rewrite_test.cpython-314.pyc +0 -0
  556. package/skills/ui-design/scripts/__pycache__/layout_balance.cpython-314.pyc +0 -0
  557. package/skills/ui-design/scripts/__pycache__/layout_balance_test.cpython-314.pyc +0 -0
  558. package/skills/ui-design/scripts/__pycache__/normalize_design_json.cpython-314.pyc +0 -0
  559. package/skills/ui-design/scripts/__pycache__/normalize_design_json_test.cpython-314.pyc +0 -0
  560. package/skills/ui-design/scripts/__pycache__/plan_source_layout.cpython-314.pyc +0 -0
  561. package/skills/ui-design/scripts/__pycache__/plan_source_layout_test.cpython-314.pyc +0 -0
  562. package/skills/ui-design/scripts/__pycache__/resolve_source_hint.cpython-314.pyc +0 -0
  563. package/skills/ui-design/scripts/__pycache__/resolve_source_hint_test.cpython-314.pyc +0 -0
  564. package/skills/ui-design/scripts/__pycache__/resolve_source_input.cpython-314.pyc +0 -0
  565. package/skills/ui-design/scripts/__pycache__/resolve_source_input_test.cpython-314.pyc +0 -0
  566. package/skills/ui-design/scripts/__pycache__/scaffold_ui_artifact.cpython-314.pyc +0 -0
  567. package/skills/ui-design/scripts/__pycache__/source_usage_check.cpython-314.pyc +0 -0
  568. package/skills/ui-design/scripts/__pycache__/source_usage_check_test.cpython-314.pyc +0 -0
  569. package/skills/ui-design/scripts/__pycache__/text_readability_pixel.cpython-314.pyc +0 -0
  570. package/skills/ui-design/scripts/__pycache__/visual_quality_gate.cpython-314.pyc +0 -0
  571. package/skills/ui-design/scripts/__pycache__/visual_quality_gate_test.cpython-314.pyc +0 -0
  572. /package/skills/ai-image/scripts/{generate_test.mjs → generate.selftest.mjs} +0 -0
  573. /package/skills/ai-image/scripts/{generate_from_plan_test.mjs → generate_from_plan.selftest.mjs} +0 -0
@@ -0,0 +1,216 @@
1
+ /**
2
+ * ============================================================
3
+ * src/irreversible/rules.ts —— 不可逆动作分级(内核通用)
4
+ * ------------------------------------------------------------
5
+ * 这里只回答一个问题:**这一步做下去,还救得回来吗?**
6
+ *
7
+ * 判据是「**是否毁掉最后一份副本**」,不是「动词听着吓不吓人」。
8
+ * 这条判据很重要,因为选错方向会两头落空:
9
+ * · 拦得太宽(把 `git reset --hard` 也拦下来)→ 用户每天被问十几次,
10
+ * 很快学会闭眼点「同意」,闸门等于不存在;
11
+ * · 拦得太窄 → 真出事时没人拦。
12
+ * 所以 `git reset --hard` **不拦**(reflog 能捞回来),而 `git push --force`
13
+ * **要拦**(远端那段历史可能是唯一副本,别人本地未必有)。
14
+ *
15
+ * 为什么住在内核而不是某个工具里:这套语义天然**跨工具**。
16
+ * 「格式化硬盘 / 删库 / 汇款 / 毁 git 历史」主要发生在 Bash,
17
+ * 「点确认转账 / 永久删除」发生在 ComputerUse。两边共用同一套词汇表,
18
+ * 才不会各写一份、各自漂移。工具依赖内核,不是内核依赖工具。
19
+ *
20
+ * ⚠️ 两条路的可靠性**根本不同**,不要混为一谈:
21
+ * · `classifyCommand()` —— 读**真实命令文本**,确定性匹配。
22
+ * · `classifyIntent()` —— 读**模型自报的 intent**。模型不报就不命中。
23
+ * 这是 ComputerUse 侧的固有局限(GUI 上没有"命令文本"可读),
24
+ * 它先于本模块存在,搬过来时**不会**因此变可靠,别被"进了内核"迷惑。
25
+ *
26
+ * 与 Bash 现有两层的分工(三层各司其职,同一条模式只住一处):
27
+ * 1. `bash.ts::FORBIDDEN_PATTERNS` —— 灾难且无正当用途(`rm -rf /`、mkfs、
28
+ * fork bomb):**直接拒绝**,不问人。
29
+ * 2. 本模块 `classifyCommand()` —— 不可逆但**有正当用途**(force push、
30
+ * 删库、毁 reflog):**停下来问人**;无人可问 = 拒绝。
31
+ * 3. `bash/warnings.ts` —— 危险但可回滚(reset --hard、clean -f、stash drop):
32
+ * **只提示**,不阻塞。
33
+ * ============================================================
34
+ */
35
+ /**
36
+ * 「毁掉最后一份副本」的命令。命中 = 停下来问人。
37
+ *
38
+ * 收录标准(三条全中才进来):
39
+ * ① 结果不可逆 —— 没有 reflog / 回收站 / 事务能捞回来
40
+ * ② 有正当用途 —— 否则该进 `FORBIDDEN_PATTERNS` 直接拒,不该浪费一次提问
41
+ * ③ 不在其它两层里 —— 同一条模式只住一处,避免漂移
42
+ */
43
+ const COMMAND_RULES = [
44
+ // ---- git:毁掉远端/历史的最后一份副本 ----
45
+ // 注意只拦 --force / -f。`--force-with-lease` 在远端有未见提交时会**拒绝执行**,
46
+ // 正是为了防经典事故而设计的安全形式,拦它只会逼用户改用更危险的 --force。
47
+ // 它仍留在 warnings.ts 的提示层。
48
+ {
49
+ id: 'git-push-force',
50
+ pattern: /\bgit\b[^;&|\n]*\bpush\b(?![^;&|\n]*--force-with-lease)[^;&|\n]*(?:\s--force(?:=\S*)?\b|\s-[a-zA-Z]*f\b)/,
51
+ why: '强制推送会覆盖远端历史;被覆盖的提交可能只存在于远端,其他人本地也未必有',
52
+ },
53
+ {
54
+ // `git push origin +main` —— refspec 前缀 `+` 等价于强推,容易被漏看
55
+ id: 'git-push-plus-refspec',
56
+ pattern: /\bgit\b[^;&|\n]*\bpush\b[^;&|\n]*\s\+[\w./-]+:[\w./-]+/,
57
+ why: 'refspec 前的 `+` 等同强制推送,会覆盖远端历史',
58
+ },
59
+ {
60
+ id: 'git-push-delete-branch',
61
+ pattern: /\bgit\b[^;&|\n]*\bpush\b[^;&|\n]*(?:\s--delete\b|\s:[\w./-]+(?:\s|$))/,
62
+ why: '删除远端分支;若该分支未被其它引用包含,提交将无处可寻',
63
+ },
64
+ {
65
+ id: 'git-history-rewrite',
66
+ pattern: /\bgit\b[^;&|\n]*\b(?:filter-branch|filter-repo)\b/,
67
+ why: '重写整条提交历史,所有旧提交哈希失效且原历史不再可达',
68
+ },
69
+ {
70
+ // reflog 是本仓库大多数"手滑"的救命稻草;主动过期 + 立刻 gc 就是把它烧掉
71
+ id: 'git-destroy-reflog',
72
+ pattern: /\bgit\b[^;&|\n]*\b(?:reflog\s+expire\b[^;&|\n]*--expire(?:-unreachable)?=(?:now|all)|gc\b[^;&|\n]*--prune=(?:now|all))/,
73
+ why: '销毁 reflog / 立即清理不可达对象,等于拆掉本地误操作的最后一道保险',
74
+ },
75
+ // ---- 数据库:删库 ----
76
+ {
77
+ id: 'sql-drop-database',
78
+ pattern: /\bDROP\s+(?:DATABASE|SCHEMA)\b/i,
79
+ why: '删库;除非另有备份,库内全部数据不可恢复',
80
+ },
81
+ {
82
+ id: 'sql-drop-or-truncate-table',
83
+ pattern: /\b(?:DROP\s+TABLE|TRUNCATE\s+(?:TABLE\s+)?)\b/i,
84
+ why: '删表 / 清空表;TRUNCATE 通常不写 undo 日志,删掉即没了',
85
+ },
86
+ // ---- 绕过回收站的永久删除 ----
87
+ // 「一般删除进回收站、永久删除要拦」这条判据的落点。注意 shell 里的 `rm`
88
+ // **本来就不进回收站**,但逐个 `rm` 都拦会让 agent 没法干活;
89
+ // 灾难范围的 rm 已由 FORBIDDEN_PATTERNS 直接拒。这里只收「明确表达
90
+ // 要抹掉到不可恢复」的那几个。
91
+ {
92
+ id: 'shred-file',
93
+ pattern: /\bshred\b[^;&|\n]*-[a-zA-Z]*u|\bshred\s+--remove\b/,
94
+ why: '覆写并删除文件内容,磁盘取证也无法恢复',
95
+ },
96
+ {
97
+ id: 'empty-recycle-bin',
98
+ pattern: /\bClear-RecycleBin\b/i,
99
+ why: '清空回收站;里面原本还能还原的文件将彻底消失',
100
+ },
101
+ {
102
+ id: 'rm-no-preserve-root',
103
+ pattern: /--no-preserve-root\b/,
104
+ why: '显式解除根目录保护,是在主动拆掉系统自带的最后一道防线',
105
+ },
106
+ ];
107
+ /**
108
+ * 归一化命令后逐段匹配。
109
+ *
110
+ * 归一化做两件事:剥掉 `sudo` / 环境变量前缀,并按 `&& || ; | 换行` 切段 ——
111
+ * 否则 `cd /x && git push --force` 这类连写会漏判。
112
+ *
113
+ * ⚠️ **这是黑名单,不是沙盒,必然有绕过**:shell 是图灵完备的,
114
+ * `bash -c "$(echo Z2l0IHB1c2g... | base64 -d)"`、alias、变量拼接都能躲开。
115
+ * `test/irreversible.test.ts` 里有一组**明确列出、明确不修**的已知绕过用例,
116
+ * 那是诚实声明;把这层当成"拦住手滑与顺手误操作",不要当成对抗恶意输入。
117
+ */
118
+ export function classifyCommand(command) {
119
+ for (const segment of splitCommandSegments(command)) {
120
+ for (const rule of COMMAND_RULES) {
121
+ if (rule.pattern.test(segment)) {
122
+ return {
123
+ entry: rule.id,
124
+ riskLevel: 'critical',
125
+ checkable: true,
126
+ why: rule.why,
127
+ source: 'command',
128
+ };
129
+ }
130
+ }
131
+ }
132
+ return null;
133
+ }
134
+ /** 按 shell 的连接符切段,并剥掉 `sudo` / `VAR=x` 前缀。 */
135
+ function splitCommandSegments(command) {
136
+ return command
137
+ .split(/&&|\|\||[;|\n]/)
138
+ .map((part) => part.trim().replace(/^(?:sudo\s+|[A-Za-z_][A-Za-z0-9_]*=\S*\s+)+/, ''))
139
+ .filter((part) => part.length > 0);
140
+ }
141
+ /** 供文档/测试枚举当前规则(不暴露 RegExp,避免调用方自行匹配绕过本函数)。 */
142
+ export function commandRuleIds() {
143
+ return COMMAND_RULES.map((rule) => rule.id);
144
+ }
145
+ // ============================================================
146
+ // 二、意图路(ComputerUse)—— 依赖模型自报,可靠性天然弱一档
147
+ // ============================================================
148
+ /**
149
+ * 全局高危意图黑名单:任何应用命中都按 critical。
150
+ *
151
+ * ⚠️ 这些条目形如 `intent:payment`,来源是**模型在工具入参里自报的 intent**。
152
+ * 模型不报、或报成别的词,就不会命中 —— GUI 上没有"命令文本"可供确定性匹配,
153
+ * 这是该路径的固有上限。真正的兜底是宿主侧的人工监督,不是这张表。
154
+ */
155
+ const GLOBAL_CRITICAL_INTENTS = [
156
+ // 财产类
157
+ 'intent:payment',
158
+ 'intent:payment-or-transfer',
159
+ 'intent:transfer',
160
+ 'intent:pay',
161
+ 'intent:withdraw',
162
+ // 数据销毁类
163
+ 'intent:permanent-delete',
164
+ 'intent:format-disk',
165
+ 'intent:rm-rf',
166
+ 'intent:wipe-data',
167
+ 'intent:clear-chat-history',
168
+ // 账号/关系类(不可逆且有社交成本)
169
+ 'intent:remove-contact',
170
+ 'intent:block-user',
171
+ 'intent:leave-group-permanently',
172
+ 'intent:dissolve-group',
173
+ 'intent:delete-account',
174
+ // 关窗:按同一条判据(毁掉最后一份副本)——未保存的内容没有回收站也没有
175
+ // reflog,窗口一关就没了。它不是 `intent:` 形状,因为不靠模型自报:
176
+ // `action:'window' + windowOperation:'close'` 是引擎能自己看出来的确定事实。
177
+ // 触发频率也不高:agent 主动去关用户桌面上的窗口本就罕见且后果明确。
178
+ 'window:close',
179
+ ];
180
+ /**
181
+ * 判断一个不可逆条目是否在全局高危黑名单中。
182
+ *
183
+ * 匹配规则:完全相等,或 pattern 是 entry 的前缀且在分隔符处断开
184
+ * (`payment-or-transfer` 命中 `payment`;但 `send-message` 不会误命中 `send`)。
185
+ */
186
+ export function isGlobalCriticalIntent(entry) {
187
+ const normalized = entry.toLowerCase();
188
+ return GLOBAL_CRITICAL_INTENTS.some((pattern) => {
189
+ if (normalized === pattern)
190
+ return true;
191
+ return (normalized.startsWith(`${pattern}-`) ||
192
+ normalized.startsWith(`${pattern}_`) ||
193
+ normalized.startsWith(`${pattern}:`));
194
+ });
195
+ }
196
+ export function globalCriticalIntentEntries() {
197
+ return [...GLOBAL_CRITICAL_INTENTS];
198
+ }
199
+ /**
200
+ * 综合判定一个不可逆意图条目的风险级别。
201
+ *
202
+ * 优先级:全局黑名单 > 应用级 critical > 其余(normal)。
203
+ * **黑名单制**:只有明确列进 critical 的才拦,其余放行 —— 这是产品决定,
204
+ * 见本文件头注对「拦太宽等于没拦」的说明。全局黑名单不可被应用级降级。
205
+ */
206
+ export function classifyIntent(params) {
207
+ const { entry, guideCritical, why, checkable = false } = params;
208
+ if (isGlobalCriticalIntent(entry)) {
209
+ return { entry, riskLevel: 'critical', checkable, why, source: 'global' };
210
+ }
211
+ const normalized = entry.toLowerCase();
212
+ if (guideCritical.some((c) => c.toLowerCase() === normalized)) {
213
+ return { entry, riskLevel: 'critical', checkable, why, source: 'app-critical' };
214
+ }
215
+ return { entry, riskLevel: 'normal', checkable, why, source: 'app-normal' };
216
+ }
@@ -0,0 +1,261 @@
1
+ /**
2
+ * ============================================================
3
+ * src/irreversible/rules.ts —— 不可逆动作分级(内核通用)
4
+ * ------------------------------------------------------------
5
+ * 这里只回答一个问题:**这一步做下去,还救得回来吗?**
6
+ *
7
+ * 判据是「**是否毁掉最后一份副本**」,不是「动词听着吓不吓人」。
8
+ * 这条判据很重要,因为选错方向会两头落空:
9
+ * · 拦得太宽(把 `git reset --hard` 也拦下来)→ 用户每天被问十几次,
10
+ * 很快学会闭眼点「同意」,闸门等于不存在;
11
+ * · 拦得太窄 → 真出事时没人拦。
12
+ * 所以 `git reset --hard` **不拦**(reflog 能捞回来),而 `git push --force`
13
+ * **要拦**(远端那段历史可能是唯一副本,别人本地未必有)。
14
+ *
15
+ * 为什么住在内核而不是某个工具里:这套语义天然**跨工具**。
16
+ * 「格式化硬盘 / 删库 / 汇款 / 毁 git 历史」主要发生在 Bash,
17
+ * 「点确认转账 / 永久删除」发生在 ComputerUse。两边共用同一套词汇表,
18
+ * 才不会各写一份、各自漂移。工具依赖内核,不是内核依赖工具。
19
+ *
20
+ * ⚠️ 两条路的可靠性**根本不同**,不要混为一谈:
21
+ * · `classifyCommand()` —— 读**真实命令文本**,确定性匹配。
22
+ * · `classifyIntent()` —— 读**模型自报的 intent**。模型不报就不命中。
23
+ * 这是 ComputerUse 侧的固有局限(GUI 上没有"命令文本"可读),
24
+ * 它先于本模块存在,搬过来时**不会**因此变可靠,别被"进了内核"迷惑。
25
+ *
26
+ * 与 Bash 现有两层的分工(三层各司其职,同一条模式只住一处):
27
+ * 1. `bash.ts::FORBIDDEN_PATTERNS` —— 灾难且无正当用途(`rm -rf /`、mkfs、
28
+ * fork bomb):**直接拒绝**,不问人。
29
+ * 2. 本模块 `classifyCommand()` —— 不可逆但**有正当用途**(force push、
30
+ * 删库、毁 reflog):**停下来问人**;无人可问 = 拒绝。
31
+ * 3. `bash/warnings.ts` —— 危险但可回滚(reset --hard、clean -f、stash drop):
32
+ * **只提示**,不阻塞。
33
+ * ============================================================
34
+ */
35
+
36
+ /** 风险级别。保持两档:只有 critical 会改变执行路径,别加没人消费的第三档。 */
37
+ export type RiskLevel = 'critical' | 'normal';
38
+
39
+ export interface RiskHit {
40
+ /** 命中的条目(intent 路是 `intent:xxx`,命令路是规则 id) */
41
+ entry: string;
42
+ riskLevel: RiskLevel;
43
+ /** 引擎能独立验证(命令文本 / key / region),还是只能信模型自报(intent) */
44
+ checkable: boolean;
45
+ /** 人话后果,直接展示给用户,必须说清「丢什么、能不能找回」 */
46
+ why: string;
47
+ /** 命中来自哪一层,便于审计与排错 */
48
+ source: 'command' | 'global' | 'app-critical' | 'app-normal';
49
+ }
50
+
51
+ // ============================================================
52
+ // 一、命令文本路(Bash)—— 确定性,不依赖模型自报
53
+ // ============================================================
54
+
55
+ interface CommandRule {
56
+ id: string;
57
+ pattern: RegExp;
58
+ why: string;
59
+ }
60
+
61
+ /**
62
+ * 「毁掉最后一份副本」的命令。命中 = 停下来问人。
63
+ *
64
+ * 收录标准(三条全中才进来):
65
+ * ① 结果不可逆 —— 没有 reflog / 回收站 / 事务能捞回来
66
+ * ② 有正当用途 —— 否则该进 `FORBIDDEN_PATTERNS` 直接拒,不该浪费一次提问
67
+ * ③ 不在其它两层里 —— 同一条模式只住一处,避免漂移
68
+ */
69
+ const COMMAND_RULES: CommandRule[] = [
70
+ // ---- git:毁掉远端/历史的最后一份副本 ----
71
+ // 注意只拦 --force / -f。`--force-with-lease` 在远端有未见提交时会**拒绝执行**,
72
+ // 正是为了防经典事故而设计的安全形式,拦它只会逼用户改用更危险的 --force。
73
+ // 它仍留在 warnings.ts 的提示层。
74
+ {
75
+ id: 'git-push-force',
76
+ pattern: /\bgit\b[^;&|\n]*\bpush\b(?![^;&|\n]*--force-with-lease)[^;&|\n]*(?:\s--force(?:=\S*)?\b|\s-[a-zA-Z]*f\b)/,
77
+ why: '强制推送会覆盖远端历史;被覆盖的提交可能只存在于远端,其他人本地也未必有',
78
+ },
79
+ {
80
+ // `git push origin +main` —— refspec 前缀 `+` 等价于强推,容易被漏看
81
+ id: 'git-push-plus-refspec',
82
+ pattern: /\bgit\b[^;&|\n]*\bpush\b[^;&|\n]*\s\+[\w./-]+:[\w./-]+/,
83
+ why: 'refspec 前的 `+` 等同强制推送,会覆盖远端历史',
84
+ },
85
+ {
86
+ id: 'git-push-delete-branch',
87
+ pattern: /\bgit\b[^;&|\n]*\bpush\b[^;&|\n]*(?:\s--delete\b|\s:[\w./-]+(?:\s|$))/,
88
+ why: '删除远端分支;若该分支未被其它引用包含,提交将无处可寻',
89
+ },
90
+ {
91
+ id: 'git-history-rewrite',
92
+ pattern: /\bgit\b[^;&|\n]*\b(?:filter-branch|filter-repo)\b/,
93
+ why: '重写整条提交历史,所有旧提交哈希失效且原历史不再可达',
94
+ },
95
+ {
96
+ // reflog 是本仓库大多数"手滑"的救命稻草;主动过期 + 立刻 gc 就是把它烧掉
97
+ id: 'git-destroy-reflog',
98
+ pattern: /\bgit\b[^;&|\n]*\b(?:reflog\s+expire\b[^;&|\n]*--expire(?:-unreachable)?=(?:now|all)|gc\b[^;&|\n]*--prune=(?:now|all))/,
99
+ why: '销毁 reflog / 立即清理不可达对象,等于拆掉本地误操作的最后一道保险',
100
+ },
101
+
102
+ // ---- 数据库:删库 ----
103
+ {
104
+ id: 'sql-drop-database',
105
+ pattern: /\bDROP\s+(?:DATABASE|SCHEMA)\b/i,
106
+ why: '删库;除非另有备份,库内全部数据不可恢复',
107
+ },
108
+ {
109
+ id: 'sql-drop-or-truncate-table',
110
+ pattern: /\b(?:DROP\s+TABLE|TRUNCATE\s+(?:TABLE\s+)?)\b/i,
111
+ why: '删表 / 清空表;TRUNCATE 通常不写 undo 日志,删掉即没了',
112
+ },
113
+
114
+ // ---- 绕过回收站的永久删除 ----
115
+ // 「一般删除进回收站、永久删除要拦」这条判据的落点。注意 shell 里的 `rm`
116
+ // **本来就不进回收站**,但逐个 `rm` 都拦会让 agent 没法干活;
117
+ // 灾难范围的 rm 已由 FORBIDDEN_PATTERNS 直接拒。这里只收「明确表达
118
+ // 要抹掉到不可恢复」的那几个。
119
+ {
120
+ id: 'shred-file',
121
+ pattern: /\bshred\b[^;&|\n]*-[a-zA-Z]*u|\bshred\s+--remove\b/,
122
+ why: '覆写并删除文件内容,磁盘取证也无法恢复',
123
+ },
124
+ {
125
+ id: 'empty-recycle-bin',
126
+ pattern: /\bClear-RecycleBin\b/i,
127
+ why: '清空回收站;里面原本还能还原的文件将彻底消失',
128
+ },
129
+ {
130
+ id: 'rm-no-preserve-root',
131
+ pattern: /--no-preserve-root\b/,
132
+ why: '显式解除根目录保护,是在主动拆掉系统自带的最后一道防线',
133
+ },
134
+ ];
135
+
136
+ /**
137
+ * 归一化命令后逐段匹配。
138
+ *
139
+ * 归一化做两件事:剥掉 `sudo` / 环境变量前缀,并按 `&& || ; | 换行` 切段 ——
140
+ * 否则 `cd /x && git push --force` 这类连写会漏判。
141
+ *
142
+ * ⚠️ **这是黑名单,不是沙盒,必然有绕过**:shell 是图灵完备的,
143
+ * `bash -c "$(echo Z2l0IHB1c2g... | base64 -d)"`、alias、变量拼接都能躲开。
144
+ * `test/irreversible.test.ts` 里有一组**明确列出、明确不修**的已知绕过用例,
145
+ * 那是诚实声明;把这层当成"拦住手滑与顺手误操作",不要当成对抗恶意输入。
146
+ */
147
+ export function classifyCommand(command: string): RiskHit | null {
148
+ for (const segment of splitCommandSegments(command)) {
149
+ for (const rule of COMMAND_RULES) {
150
+ if (rule.pattern.test(segment)) {
151
+ return {
152
+ entry: rule.id,
153
+ riskLevel: 'critical',
154
+ checkable: true,
155
+ why: rule.why,
156
+ source: 'command',
157
+ };
158
+ }
159
+ }
160
+ }
161
+ return null;
162
+ }
163
+
164
+ /** 按 shell 的连接符切段,并剥掉 `sudo` / `VAR=x` 前缀。 */
165
+ function splitCommandSegments(command: string): string[] {
166
+ return command
167
+ .split(/&&|\|\||[;|\n]/)
168
+ .map((part) => part.trim().replace(/^(?:sudo\s+|[A-Za-z_][A-Za-z0-9_]*=\S*\s+)+/, ''))
169
+ .filter((part) => part.length > 0);
170
+ }
171
+
172
+ /** 供文档/测试枚举当前规则(不暴露 RegExp,避免调用方自行匹配绕过本函数)。 */
173
+ export function commandRuleIds(): string[] {
174
+ return COMMAND_RULES.map((rule) => rule.id);
175
+ }
176
+
177
+ // ============================================================
178
+ // 二、意图路(ComputerUse)—— 依赖模型自报,可靠性天然弱一档
179
+ // ============================================================
180
+
181
+ /**
182
+ * 全局高危意图黑名单:任何应用命中都按 critical。
183
+ *
184
+ * ⚠️ 这些条目形如 `intent:payment`,来源是**模型在工具入参里自报的 intent**。
185
+ * 模型不报、或报成别的词,就不会命中 —— GUI 上没有"命令文本"可供确定性匹配,
186
+ * 这是该路径的固有上限。真正的兜底是宿主侧的人工监督,不是这张表。
187
+ */
188
+ const GLOBAL_CRITICAL_INTENTS: readonly string[] = [
189
+ // 财产类
190
+ 'intent:payment',
191
+ 'intent:payment-or-transfer',
192
+ 'intent:transfer',
193
+ 'intent:pay',
194
+ 'intent:withdraw',
195
+ // 数据销毁类
196
+ 'intent:permanent-delete',
197
+ 'intent:format-disk',
198
+ 'intent:rm-rf',
199
+ 'intent:wipe-data',
200
+ 'intent:clear-chat-history',
201
+ // 账号/关系类(不可逆且有社交成本)
202
+ 'intent:remove-contact',
203
+ 'intent:block-user',
204
+ 'intent:leave-group-permanently',
205
+ 'intent:dissolve-group',
206
+ 'intent:delete-account',
207
+ // 关窗:按同一条判据(毁掉最后一份副本)——未保存的内容没有回收站也没有
208
+ // reflog,窗口一关就没了。它不是 `intent:` 形状,因为不靠模型自报:
209
+ // `action:'window' + windowOperation:'close'` 是引擎能自己看出来的确定事实。
210
+ // 触发频率也不高:agent 主动去关用户桌面上的窗口本就罕见且后果明确。
211
+ 'window:close',
212
+ ];
213
+
214
+ /**
215
+ * 判断一个不可逆条目是否在全局高危黑名单中。
216
+ *
217
+ * 匹配规则:完全相等,或 pattern 是 entry 的前缀且在分隔符处断开
218
+ * (`payment-or-transfer` 命中 `payment`;但 `send-message` 不会误命中 `send`)。
219
+ */
220
+ export function isGlobalCriticalIntent(entry: string): boolean {
221
+ const normalized = entry.toLowerCase();
222
+ return GLOBAL_CRITICAL_INTENTS.some((pattern) => {
223
+ if (normalized === pattern) return true;
224
+ return (
225
+ normalized.startsWith(`${pattern}-`) ||
226
+ normalized.startsWith(`${pattern}_`) ||
227
+ normalized.startsWith(`${pattern}:`)
228
+ );
229
+ });
230
+ }
231
+
232
+ export function globalCriticalIntentEntries(): string[] {
233
+ return [...GLOBAL_CRITICAL_INTENTS];
234
+ }
235
+
236
+ /**
237
+ * 综合判定一个不可逆意图条目的风险级别。
238
+ *
239
+ * 优先级:全局黑名单 > 应用级 critical > 其余(normal)。
240
+ * **黑名单制**:只有明确列进 critical 的才拦,其余放行 —— 这是产品决定,
241
+ * 见本文件头注对「拦太宽等于没拦」的说明。全局黑名单不可被应用级降级。
242
+ */
243
+ export function classifyIntent(params: {
244
+ entry: string;
245
+ guideCritical: readonly string[];
246
+ why: string;
247
+ checkable?: boolean;
248
+ }): RiskHit {
249
+ const { entry, guideCritical, why, checkable = false } = params;
250
+
251
+ if (isGlobalCriticalIntent(entry)) {
252
+ return { entry, riskLevel: 'critical', checkable, why, source: 'global' };
253
+ }
254
+
255
+ const normalized = entry.toLowerCase();
256
+ if (guideCritical.some((c) => c.toLowerCase() === normalized)) {
257
+ return { entry, riskLevel: 'critical', checkable, why, source: 'app-critical' };
258
+ }
259
+
260
+ return { entry, riskLevel: 'normal', checkable, why, source: 'app-normal' };
261
+ }
package/src/llm/client.js CHANGED
@@ -24,7 +24,8 @@
24
24
  * ============================================================
25
25
  */
26
26
  import { dlog } from '../utils/debugLog.js';
27
- import { buildOpenAIRequest, createOpenAISSEParser, isImageInputRejected, isMaxTokensRejected, isResponseFormatUnsupported, } from './providers/openaiFormat.js';
27
+ import { buildOpenAIRequest, createOpenAISSEParser, isImageInputRejected, isMaxTokensRejected, isPromptCacheKeyRejected, isResponseFormatUnsupported, } from './providers/openaiFormat.js';
28
+ import { promptMaterialHash, shortCacheScope } from './promptCache.js';
28
29
  import { buildAnthropicRequest, createAnthropicSSEParser } from './providers/anthropicFormat.js';
29
30
  /**
30
31
  * 记住"这个 baseURL::model 不支持 response_format.json_schema",避免每次都先撞 400。
@@ -38,6 +39,7 @@ const rfUnsupported = new Set();
38
39
  * ≥131072 仍正常),这只是给个别挑剔 provider 的兜底,命中后该进程不再发 max_tokens。
39
40
  */
40
41
  const maxTokensUnsupported = new Set();
42
+ const promptCacheKeyUnsupported = new Set();
41
43
  /** 调试日志用的请求自增号(vote 并发多 voter 时靠它在日志里区分是哪一路)。 */
42
44
  let reqCounter = 0;
43
45
  // ============================================================
@@ -239,7 +241,7 @@ export function createIdleWatchdog(userSignal, timeoutMs = IDLE_TIMEOUT_MS) {
239
241
  * ```
240
242
  */
241
243
  export async function* chat(args) {
242
- const { provider, messages, tools, signal, responseFormat } = args;
244
+ const { provider, messages, tools, signal, responseFormat, promptCache } = args;
243
245
  const format = provider.apiFormat === 'anthropic' ? 'anthropic' : 'openai';
244
246
  if (format === 'anthropic' && responseFormat) {
245
247
  throw new Error('output_schema 结构化输出目前不支持 Anthropic Messages 格式的 provider' +
@@ -252,7 +254,7 @@ export async function* chat(args) {
252
254
  let cleanedMessages = messages
253
255
  .filter((m) => !(m.role === 'system' && m._ephemeral === true))
254
256
  .map((m) => {
255
- const { id, timestamp, attachments, display_metadata, ...rest } = m;
257
+ const { id, timestamp, attachments, browserReferences, display_metadata, ...rest } = m;
256
258
  return rest;
257
259
  });
258
260
  const includeUsage = process.env.MINIMAL_AGENT_DISABLE_USAGE !== '1';
@@ -265,6 +267,10 @@ export async function* chat(args) {
265
267
  provider.maxTokens > 0 &&
266
268
  !maxTokensUnsupported.has(rfKey);
267
269
  let imagesStripped = false;
270
+ let wantPromptCacheKey = format === 'openai' &&
271
+ provider.promptCache?.mode === 'session-key' &&
272
+ !!promptCache?.scopeKey &&
273
+ !promptCacheKeyUnsupported.has(rfKey);
268
274
  const stripImagesFromMessages = (msgs) => msgs.map((m) => {
269
275
  const c = m.content;
270
276
  if (!Array.isArray(c))
@@ -288,6 +294,8 @@ export async function* chat(args) {
288
294
  withResponseFormat: wantResponseFormat,
289
295
  withMaxTokens: wantMaxTokens,
290
296
  includeUsage,
297
+ promptCache,
298
+ withPromptCacheKey: wantPromptCacheKey,
291
299
  responseFormat,
292
300
  });
293
301
  return fetch(req.url, { method: 'POST', headers: req.headers, body: req.body, signal: watchdog.signal });
@@ -300,6 +308,16 @@ export async function* chat(args) {
300
308
  maxTokens: wantMaxTokens ? provider.maxTokens : undefined,
301
309
  msgs: cleanedMessages.length,
302
310
  tools: tools.length,
311
+ promptCacheMode: provider.promptCache?.mode ?? 'auto',
312
+ promptCacheScope: shortCacheScope(promptCache?.scopeKey),
313
+ systemPromptHash: promptMaterialHash(cleanedMessages
314
+ .filter((message) => message.role === 'system')
315
+ .map((message) => message.content)),
316
+ toolSchemaHash: promptMaterialHash(tools.map((tool) => ({
317
+ name: tool.name,
318
+ description: typeof tool.description === 'function' ? tool.description() : tool.description,
319
+ parameters: tool.parameters,
320
+ }))),
303
321
  });
304
322
  // 重试循环:每个 attempt 内部可能触发"response_format 不支持 → 去掉"的本地退化
305
323
  // (本地退化不算重试,仍属同一 attempt 的"拿到 200"路径的一部分;只 openai 分支会真的
@@ -348,6 +366,25 @@ export async function* chat(args) {
348
366
  // resp !ok:本地退化路径(response_format / max_tokens 不被支持 → 去掉重发,不算重试;
349
367
  // 仅 openai 分支——wantResponseFormat/wantMaxTokens 在 anthropic 分支恒为 false)
350
368
  let errText = await resp.text().catch(() => '');
369
+ if (wantPromptCacheKey && isPromptCacheKeyRejected(resp.status, errText)) {
370
+ promptCacheKeyUnsupported.add(rfKey);
371
+ wantPromptCacheKey = false;
372
+ dlog('llm', `req#${reqId} prompt_cache_key unsupported; downgraded`, {
373
+ model: provider.model,
374
+ });
375
+ try {
376
+ resp = await postChat();
377
+ watchdog.kick();
378
+ }
379
+ catch (e) {
380
+ if ((await handleNetworkError(e, attempt, 'cache-key fallback fetch failed')) === 'break')
381
+ break;
382
+ continue;
383
+ }
384
+ if (resp.ok)
385
+ break;
386
+ errText = await resp.text().catch(() => '');
387
+ }
351
388
  // 退化①:response_format.json_schema 不支持
352
389
  if (wantResponseFormat && isResponseFormatUnsupported(resp.status, errText)) {
353
390
  // 记住该 model 不支持,单进程内后续结构化调用直接跳过 response_format(不再撞 400)。