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,159 @@
1
+ import { axGivesControlDetail } from './vision/focus.js';
2
+ const HUMAN_TEXT = {
3
+ password: /password|passcode|密码|口令/i,
4
+ otp: /one[- ]time|verification code|\botp\b|短信验证码|邮件验证码|动态口令/i,
5
+ captcha: /captcha|verify.{0,12}human|安全验证|人机验证|验证码|滑块|拼图/i,
6
+ qr_login: /scan.{0,12}(?:code|qr)|扫码登录|二维码登录/i,
7
+ permission: /permission|allow access|授权|访问权限/i,
8
+ security_warning: /security warning|安全警告|风险提示|系统保护/i,
9
+ login: /sign in|log in|登录/i,
10
+ };
11
+ function flatten(node) {
12
+ if (!node)
13
+ return [];
14
+ return [node, ...(node.children ?? []).flatMap(flatten)];
15
+ }
16
+ /**
17
+ * Detects only host-observable boundaries. Protected values and screenshot
18
+ * pixels are never returned or included in the model-visible summary.
19
+ *
20
+ * ⚠️ The accessibility tree is not always there. Measured on this repo: an
21
+ * Electron app (Claude desktop) exposes its window and three window buttons
22
+ * and nothing else — no fields, no buttons, no text. Self-drawn and Electron
23
+ * apps are exactly the target scenario, so a `null` here means "found no
24
+ * evidence", never "there is no password box". Callers that need to act on
25
+ * the difference should read `state.accessibility.truncated` as well.
26
+ */
27
+ export function detectComputerHumanBoundary(state, manual) {
28
+ const nodes = flatten(state.accessibility?.root);
29
+ const target = {
30
+ ...(state.activeApp?.id || state.accessibility?.appId
31
+ ? { appId: state.activeApp?.id ?? state.accessibility?.appId }
32
+ : {}),
33
+ ...(state.accessibility?.windowId ? { windowId: state.accessibility.windowId } : {}),
34
+ };
35
+ const ax = (reason, summary) => ({ reason, summary, target, confidence: 'ax' });
36
+ if (nodes.some((node) => node.protected === true || /secure|password/i.test(node.role))) {
37
+ return ax('password', '需要你在目标应用中输入密码或安全凭据');
38
+ }
39
+ const text = nodes
40
+ .map((node) => `${node.role} ${node.name ?? ''}`)
41
+ .join('\n')
42
+ .slice(0, 100_000);
43
+ // ★ 应用自己声明的信号先于通用正则。
44
+ //
45
+ // 内核只认识**跨应用成立**的东西(密码框、验证码、二维码登录…)。有些应用的
46
+ // 边界只有它自己知道,那属于说明书的知识,不属于内核 —— 此前这里写死过一段
47
+ // `/com\.tencent\.xinWeChat/` 的判断(微信登录小窗不暴露「扫码登录」四个字,
48
+ // 只能靠「二维码」+「仅传输文件」同时出现来判),那等于「多支持一个应用就要
49
+ // 改一次内核」,与「drop 一份说明书即扩展能力」的架构正好相反。现在它住在
50
+ // `plugins/computer_use/app/wechat.md` 的 `humanBoundary:` 段里。
51
+ //
52
+ // 放在通用正则**之前**:应用专属判据更精确,通用的更钝,钝的先命中会把
53
+ // 精确的那条永远盖住。
54
+ for (const declared of manual?.humanBoundary ?? []) {
55
+ // 空条件 `every` 恒真 —— 会把**任何**界面报成需要人工介入。加载期已经报 error,
56
+ // 这里再挡一次:一份坏说明书最多是「这条不生效」,绝不能变成「整个应用卡死」。
57
+ if (declared.allOf.length === 0 || !declared.reason)
58
+ continue;
59
+ const hit = declared.allOf.every((pattern) => {
60
+ try {
61
+ return new RegExp(pattern, 'i').test(text);
62
+ }
63
+ catch {
64
+ // 说明书里的正则写坏了 —— 当作不成立,别让一份坏说明书拖垮整个判定。
65
+ // (validateManual 会把它报成 issue,作者看得见。)
66
+ return false;
67
+ }
68
+ });
69
+ if (hit)
70
+ return ax(declared.reason, declared.summary);
71
+ }
72
+ if (HUMAN_TEXT.otp.test(text))
73
+ return ax('otp', '需要你在目标应用中输入一次性验证码');
74
+ if (HUMAN_TEXT.captcha.test(text))
75
+ return ax('captcha', '需要你在目标应用中完成人工验证');
76
+ if (HUMAN_TEXT.qr_login.test(text))
77
+ return ax('qr_login', '需要你扫码完成登录');
78
+ if (HUMAN_TEXT.permission.test(text))
79
+ return ax('permission', '需要你确认系统或应用权限');
80
+ if (HUMAN_TEXT.security_warning.test(text))
81
+ return ax('security_warning', '需要你处理系统安全提示');
82
+ if (HUMAN_TEXT.login.test(text) && nodes.some((node) => /text.?field|input/i.test(node.role))) {
83
+ return ax('login', '需要你完成登录');
84
+ }
85
+ return null;
86
+ }
87
+ /** 拿不到焦点控件时的整屏阈值。比有 ROI 时高,因为判据更钝。 */
88
+ const BLIND_FULLSCREEN_LIMIT = 0.15;
89
+ /** 变化面积超过焦点控件面积的多少倍才算「控件解释不了」。 */
90
+ const AREA_SLACK = 1.5;
91
+ /** 有 ROI 时的整屏下限:再小的动静都不值得打断人。 */
92
+ const MIN_FULLSCREEN_LIMIT = 0.02;
93
+ /**
94
+ * 不依赖无障碍树的兜底判据。
95
+ *
96
+ * 存在的理由:`detectComputerHumanBoundary` 的全部判据来自 AX,而 AX 在
97
+ * Electron/自绘应用上常常是空的 —— 本仓库实测确认过。把安全关键判定单押在
98
+ * 一个已知会失效的通道上,正是 R1 重构纠正过的那个错误,不能再犯第二次。
99
+ *
100
+ * ★ **判据是面积归一化的,不是一个固定的整屏百分比。**
101
+ *
102
+ * 在输入框里打字,界面**必然**变化 —— 变的就是那个输入框。老判据是
103
+ * 「整屏变化 > 2%」,于是每一次正常输入都可能命中,而真正该命中的
104
+ * 「输入框外面冒出了个联想框」反而和它混在一起分不出来。
105
+ *
106
+ * 现在问的是:**这次变化超出了焦点控件本身能解释的范围吗**。控件面积占屏
107
+ * 3%,那么 3% 以内的变化完全可以是「字打进去了」;显著超出,才说明控件
108
+ * 之外多了东西。ROI 面积比 TS 自己就知道(AX 给了控件矩形),不用原生再算。
109
+ *
110
+ * 这**不能**告诉我们弹的是什么(所以 reason 是笼统的 `blocked`),但足以
111
+ * 停下来交给人 —— 而停下来正是这里唯一需要做对的决定。
112
+ */
113
+ export function detectPixelHumanBoundary(state, observation) {
114
+ if (classifyPixelChange(state, observation) !== 'suspicious')
115
+ return null;
116
+ return {
117
+ reason: 'blocked',
118
+ summary: '输入过程中,焦点控件之外的界面发生了明显变化'
119
+ + '(可能弹出了联想、补全或对话框),需要你确认当前状态',
120
+ target: {
121
+ ...(state.activeApp?.id ? { appId: state.activeApp.id } : {}),
122
+ },
123
+ confidence: 'pixel-only',
124
+ };
125
+ }
126
+ /**
127
+ * 像素证据的三分类。分出 `no-effect` 是因为它回答的是另一个问题:
128
+ * ROI 和整屏**都没动** = 这次按键根本没落地(焦点丢了、应用没响应)。
129
+ * 那不是安全问题,但把它当成「一切正常」会让模型接着往下打字,越走越偏。
130
+ */
131
+ export function classifyPixelChange(state, observation) {
132
+ if (!observation.typing)
133
+ return 'normal';
134
+ // 树**真的给得出控件级信息**时,以 AX 判据为准,不用这条更钝的信号去添乱。
135
+ //
136
+ // ⚠️ 这里曾经写成 `state.accessibility && !truncated` —— 那测的是「树存在」,
137
+ // 不是「树有用」。微信的 AX 树有 5 个节点(纯窗口壳)、未截断,于是这条直接
138
+ // 返回 normal,下面整段像素判据(含 no-effect 回执与像素级人工接管)从未运行过。
139
+ // 判据统一收敛到 `axGivesControlDetail`,与 shouldProbeChange 共用同一份。
140
+ if (axGivesControlDetail(state))
141
+ return 'normal';
142
+ // 没测就是没测。把「没看」当成「没变」是这套判据里最容易犯的错。
143
+ if (observation.changeRatio === undefined)
144
+ return 'normal';
145
+ const full = observation.changeRatio;
146
+ const region = observation.regionChangeRatio;
147
+ const area = observation.focusAreaRatio;
148
+ // 完全没有动静:输入没落地。需要 ROI 那一路也确认,否则「整屏没变」可能
149
+ // 只是变化都发生在一个小控件里而被平均掉了。
150
+ if (full <= 0.0005 && (region === undefined || region <= 0.0005))
151
+ return 'no-effect';
152
+ if (area === undefined) {
153
+ // 拿不到焦点控件(AX 全空)。只能看整屏,且门槛抬高 —— 判据钝了,
154
+ // 就不该用和精确判据一样的灵敏度去打断人。
155
+ return full > BLIND_FULLSCREEN_LIMIT ? 'suspicious' : 'normal';
156
+ }
157
+ const limit = Math.max(MIN_FULLSCREEN_LIMIT, area * AREA_SLACK);
158
+ return full > limit ? 'suspicious' : 'normal';
159
+ }
@@ -0,0 +1,199 @@
1
+ import type { HumanInterventionReason } from '../../humanIntervention.js';
2
+ import type { AccessibilityNode, ComputerState } from './protocol.js';
3
+ import { axGivesControlDetail } from './vision/focus.js';
4
+
5
+ const HUMAN_TEXT = {
6
+ password: /password|passcode|密码|口令/i,
7
+ otp: /one[- ]time|verification code|\botp\b|短信验证码|邮件验证码|动态口令/i,
8
+ captcha: /captcha|verify.{0,12}human|安全验证|人机验证|验证码|滑块|拼图/i,
9
+ qr_login: /scan.{0,12}(?:code|qr)|扫码登录|二维码登录/i,
10
+ permission: /permission|allow access|授权|访问权限/i,
11
+ security_warning: /security warning|安全警告|风险提示|系统保护/i,
12
+ login: /sign in|log in|登录/i,
13
+ } as const;
14
+
15
+ function flatten(node: AccessibilityNode | undefined): AccessibilityNode[] {
16
+ if (!node) return [];
17
+ return [node, ...(node.children ?? []).flatMap(flatten)];
18
+ }
19
+
20
+ export interface ComputerHumanBoundary {
21
+ reason: HumanInterventionReason;
22
+ summary: string;
23
+ target?: { appId?: string; windowId?: string };
24
+ /**
25
+ * How this was established.
26
+ *
27
+ * `ax` — read out of the accessibility tree; specific and reliable.
28
+ * `pixel-only` — inferred without a usable tree. Weaker, and the host must
29
+ * be able to tell the difference rather than treating both as equal.
30
+ */
31
+ confidence?: 'ax' | 'pixel-only';
32
+ }
33
+
34
+ /**
35
+ * Detects only host-observable boundaries. Protected values and screenshot
36
+ * pixels are never returned or included in the model-visible summary.
37
+ *
38
+ * ⚠️ The accessibility tree is not always there. Measured on this repo: an
39
+ * Electron app (Claude desktop) exposes its window and three window buttons
40
+ * and nothing else — no fields, no buttons, no text. Self-drawn and Electron
41
+ * apps are exactly the target scenario, so a `null` here means "found no
42
+ * evidence", never "there is no password box". Callers that need to act on
43
+ * the difference should read `state.accessibility.truncated` as well.
44
+ */
45
+ export function detectComputerHumanBoundary(
46
+ state: ComputerState,
47
+ manual?: { humanBoundary?: { reason: string; summary: string; allOf: string[] }[] },
48
+ ): ComputerHumanBoundary | null {
49
+ const nodes = flatten(state.accessibility?.root);
50
+ const target = {
51
+ ...(state.activeApp?.id || state.accessibility?.appId
52
+ ? { appId: state.activeApp?.id ?? state.accessibility?.appId }
53
+ : {}),
54
+ ...(state.accessibility?.windowId ? { windowId: state.accessibility.windowId } : {}),
55
+ };
56
+ const ax = (reason: HumanInterventionReason, summary: string): ComputerHumanBoundary =>
57
+ ({ reason, summary, target, confidence: 'ax' });
58
+
59
+ if (nodes.some((node) => node.protected === true || /secure|password/i.test(node.role))) {
60
+ return ax('password', '需要你在目标应用中输入密码或安全凭据');
61
+ }
62
+ const text = nodes
63
+ .map((node) => `${node.role} ${node.name ?? ''}`)
64
+ .join('\n')
65
+ .slice(0, 100_000);
66
+
67
+ // ★ 应用自己声明的信号先于通用正则。
68
+ //
69
+ // 内核只认识**跨应用成立**的东西(密码框、验证码、二维码登录…)。有些应用的
70
+ // 边界只有它自己知道,那属于说明书的知识,不属于内核 —— 此前这里写死过一段
71
+ // `/com\.tencent\.xinWeChat/` 的判断(微信登录小窗不暴露「扫码登录」四个字,
72
+ // 只能靠「二维码」+「仅传输文件」同时出现来判),那等于「多支持一个应用就要
73
+ // 改一次内核」,与「drop 一份说明书即扩展能力」的架构正好相反。现在它住在
74
+ // `plugins/computer_use/app/wechat.md` 的 `humanBoundary:` 段里。
75
+ //
76
+ // 放在通用正则**之前**:应用专属判据更精确,通用的更钝,钝的先命中会把
77
+ // 精确的那条永远盖住。
78
+ for (const declared of manual?.humanBoundary ?? []) {
79
+ // 空条件 `every` 恒真 —— 会把**任何**界面报成需要人工介入。加载期已经报 error,
80
+ // 这里再挡一次:一份坏说明书最多是「这条不生效」,绝不能变成「整个应用卡死」。
81
+ if (declared.allOf.length === 0 || !declared.reason) continue;
82
+ const hit = declared.allOf.every((pattern) => {
83
+ try {
84
+ return new RegExp(pattern, 'i').test(text);
85
+ } catch {
86
+ // 说明书里的正则写坏了 —— 当作不成立,别让一份坏说明书拖垮整个判定。
87
+ // (validateManual 会把它报成 issue,作者看得见。)
88
+ return false;
89
+ }
90
+ });
91
+ if (hit) return ax(declared.reason as HumanInterventionReason, declared.summary);
92
+ }
93
+
94
+ if (HUMAN_TEXT.otp.test(text)) return ax('otp', '需要你在目标应用中输入一次性验证码');
95
+ if (HUMAN_TEXT.captcha.test(text)) return ax('captcha', '需要你在目标应用中完成人工验证');
96
+ if (HUMAN_TEXT.qr_login.test(text)) return ax('qr_login', '需要你扫码完成登录');
97
+ if (HUMAN_TEXT.permission.test(text)) return ax('permission', '需要你确认系统或应用权限');
98
+ if (HUMAN_TEXT.security_warning.test(text)) return ax('security_warning', '需要你处理系统安全提示');
99
+ if (HUMAN_TEXT.login.test(text) && nodes.some((node) => /text.?field|input/i.test(node.role))) {
100
+ return ax('login', '需要你完成登录');
101
+ }
102
+ return null;
103
+ }
104
+
105
+ /** 输入过程中的观察,供不依赖无障碍树的兜底判据使用。 */
106
+ export interface TypingObservation {
107
+ /** 模型正在(或即将)输入文本 */
108
+ typing: boolean;
109
+ /** 全屏像素变化占比(0–1)。undefined = 没测,与「测了是 0」不同。 */
110
+ changeRatio?: number;
111
+ /** 焦点控件区域内的变化占比(0–1)。给了 ROI 才有。 */
112
+ regionChangeRatio?: number;
113
+ /** 焦点控件占全屏的面积比例(0–1)。TS 自己就知道,不必让原生再算一遍。 */
114
+ focusAreaRatio?: number;
115
+ }
116
+
117
+ /** 拿不到焦点控件时的整屏阈值。比有 ROI 时高,因为判据更钝。 */
118
+ const BLIND_FULLSCREEN_LIMIT = 0.15;
119
+ /** 变化面积超过焦点控件面积的多少倍才算「控件解释不了」。 */
120
+ const AREA_SLACK = 1.5;
121
+ /** 有 ROI 时的整屏下限:再小的动静都不值得打断人。 */
122
+ const MIN_FULLSCREEN_LIMIT = 0.02;
123
+
124
+ /** 判定的三种结局。`no-effect` 不是安全问题,但同样值得如实报给模型。 */
125
+ export type PixelVerdict = 'suspicious' | 'no-effect' | 'normal';
126
+
127
+ /**
128
+ * 不依赖无障碍树的兜底判据。
129
+ *
130
+ * 存在的理由:`detectComputerHumanBoundary` 的全部判据来自 AX,而 AX 在
131
+ * Electron/自绘应用上常常是空的 —— 本仓库实测确认过。把安全关键判定单押在
132
+ * 一个已知会失效的通道上,正是 R1 重构纠正过的那个错误,不能再犯第二次。
133
+ *
134
+ * ★ **判据是面积归一化的,不是一个固定的整屏百分比。**
135
+ *
136
+ * 在输入框里打字,界面**必然**变化 —— 变的就是那个输入框。老判据是
137
+ * 「整屏变化 > 2%」,于是每一次正常输入都可能命中,而真正该命中的
138
+ * 「输入框外面冒出了个联想框」反而和它混在一起分不出来。
139
+ *
140
+ * 现在问的是:**这次变化超出了焦点控件本身能解释的范围吗**。控件面积占屏
141
+ * 3%,那么 3% 以内的变化完全可以是「字打进去了」;显著超出,才说明控件
142
+ * 之外多了东西。ROI 面积比 TS 自己就知道(AX 给了控件矩形),不用原生再算。
143
+ *
144
+ * 这**不能**告诉我们弹的是什么(所以 reason 是笼统的 `blocked`),但足以
145
+ * 停下来交给人 —— 而停下来正是这里唯一需要做对的决定。
146
+ */
147
+ export function detectPixelHumanBoundary(
148
+ state: ComputerState,
149
+ observation: TypingObservation,
150
+ ): ComputerHumanBoundary | null {
151
+ if (classifyPixelChange(state, observation) !== 'suspicious') return null;
152
+ return {
153
+ reason: 'blocked',
154
+ summary: '输入过程中,焦点控件之外的界面发生了明显变化'
155
+ + '(可能弹出了联想、补全或对话框),需要你确认当前状态',
156
+ target: {
157
+ ...(state.activeApp?.id ? { appId: state.activeApp.id } : {}),
158
+ },
159
+ confidence: 'pixel-only',
160
+ };
161
+ }
162
+
163
+ /**
164
+ * 像素证据的三分类。分出 `no-effect` 是因为它回答的是另一个问题:
165
+ * ROI 和整屏**都没动** = 这次按键根本没落地(焦点丢了、应用没响应)。
166
+ * 那不是安全问题,但把它当成「一切正常」会让模型接着往下打字,越走越偏。
167
+ */
168
+ export function classifyPixelChange(
169
+ state: ComputerState,
170
+ observation: TypingObservation,
171
+ ): PixelVerdict {
172
+ if (!observation.typing) return 'normal';
173
+ // 树**真的给得出控件级信息**时,以 AX 判据为准,不用这条更钝的信号去添乱。
174
+ //
175
+ // ⚠️ 这里曾经写成 `state.accessibility && !truncated` —— 那测的是「树存在」,
176
+ // 不是「树有用」。微信的 AX 树有 5 个节点(纯窗口壳)、未截断,于是这条直接
177
+ // 返回 normal,下面整段像素判据(含 no-effect 回执与像素级人工接管)从未运行过。
178
+ // 判据统一收敛到 `axGivesControlDetail`,与 shouldProbeChange 共用同一份。
179
+ if (axGivesControlDetail(state)) return 'normal';
180
+ // 没测就是没测。把「没看」当成「没变」是这套判据里最容易犯的错。
181
+ if (observation.changeRatio === undefined) return 'normal';
182
+
183
+ const full = observation.changeRatio;
184
+ const region = observation.regionChangeRatio;
185
+ const area = observation.focusAreaRatio;
186
+
187
+ // 完全没有动静:输入没落地。需要 ROI 那一路也确认,否则「整屏没变」可能
188
+ // 只是变化都发生在一个小控件里而被平均掉了。
189
+ if (full <= 0.0005 && (region === undefined || region <= 0.0005)) return 'no-effect';
190
+
191
+ if (area === undefined) {
192
+ // 拿不到焦点控件(AX 全空)。只能看整屏,且门槛抬高 —— 判据钝了,
193
+ // 就不该用和精确判据一样的灵敏度去打断人。
194
+ return full > BLIND_FULLSCREEN_LIMIT ? 'suspicious' : 'normal';
195
+ }
196
+
197
+ const limit = Math.max(MIN_FULLSCREEN_LIMIT, area * AREA_SLACK);
198
+ return full > limit ? 'suspicious' : 'normal';
199
+ }
@@ -0,0 +1,77 @@
1
+ import { detectComputerHumanBoundary } from './humanBoundary.js';
2
+ export function createComputerInterventionAdapter(input) {
3
+ const detect = (state) => detectComputerHumanBoundary(state, input.manualFor?.(state));
4
+ const waitForOwner = async (pending, signal) => {
5
+ const resolution = await input.coordinator.wait(pending.id, signal);
6
+ if (resolution.status !== 'resumed')
7
+ return { resolution: 'cancelled' };
8
+ const refreshed = await input.observe(signal);
9
+ if (!refreshed)
10
+ return { resolution: 'cancelled' };
11
+ return { resolution: 'resumed', state: refreshed };
12
+ };
13
+ return {
14
+ async pause(reason, summary, signal) {
15
+ let pending = input.coordinator.get(input.context) ?? input.coordinator.request({
16
+ ownerId: input.context.ownerId,
17
+ conversationKey: input.context.conversationKey,
18
+ runId: input.context.runId,
19
+ surface: 'computer',
20
+ reason,
21
+ sanitizedSummary: summary,
22
+ });
23
+ while (true) {
24
+ const resolution = await waitForOwner(pending, signal);
25
+ if (resolution.resolution !== 'resumed' || !resolution.state)
26
+ return resolution;
27
+ const boundary = detect(resolution.state);
28
+ if (!boundary) {
29
+ input.onResumed?.(resolution.state);
30
+ return resolution;
31
+ }
32
+ pending = input.coordinator.request({
33
+ ownerId: input.context.ownerId,
34
+ conversationKey: input.context.conversationKey,
35
+ runId: input.context.runId,
36
+ surface: 'computer',
37
+ reason: boundary.reason,
38
+ sanitizedSummary: boundary.summary,
39
+ target: boundary.target,
40
+ });
41
+ }
42
+ },
43
+ async inspect(initialState, signal) {
44
+ let state = initialState;
45
+ let pending = input.coordinator.get(input.context);
46
+ let boundary = detect(state);
47
+ if (!pending && !boundary)
48
+ return { resolution: 'none' };
49
+ while (true) {
50
+ if (!pending) {
51
+ if (!boundary)
52
+ return { resolution: 'resumed', state };
53
+ pending = input.coordinator.request({
54
+ ownerId: input.context.ownerId,
55
+ conversationKey: input.context.conversationKey,
56
+ runId: input.context.runId,
57
+ surface: 'computer',
58
+ reason: boundary.reason,
59
+ sanitizedSummary: boundary.summary,
60
+ target: boundary.target,
61
+ });
62
+ }
63
+ const resolution = await waitForOwner(pending, signal);
64
+ if (resolution.resolution !== 'resumed' || !resolution.state) {
65
+ return { resolution: 'cancelled' };
66
+ }
67
+ state = resolution.state;
68
+ boundary = detect(state);
69
+ pending = undefined;
70
+ if (!boundary) {
71
+ input.onResumed?.(state);
72
+ return { resolution: 'resumed', state };
73
+ }
74
+ }
75
+ },
76
+ };
77
+ }
@@ -0,0 +1,110 @@
1
+ import type {
2
+ HumanInterventionCoordinator,
3
+ HumanInterventionReason,
4
+ PendingHumanIntervention,
5
+ } from '../../humanIntervention.js';
6
+ import { detectComputerHumanBoundary } from './humanBoundary.js';
7
+ import type { ManualHumanBoundary } from './manualSchema.js';
8
+ import type { ComputerState, ComputerUseRunContext } from './protocol.js';
9
+
10
+ export interface ComputerInterventionAdapter {
11
+ inspect(
12
+ state: ComputerState,
13
+ signal?: AbortSignal,
14
+ ): Promise<{ resolution: 'none' | 'resumed' | 'cancelled'; state?: ComputerState }>;
15
+ pause(
16
+ reason: HumanInterventionReason,
17
+ summary: string,
18
+ signal?: AbortSignal,
19
+ ): Promise<{ resolution: 'resumed' | 'cancelled'; state?: ComputerState }>;
20
+ }
21
+
22
+ export function createComputerInterventionAdapter(input: {
23
+ coordinator: HumanInterventionCoordinator;
24
+ context: ComputerUseRunContext;
25
+ observe(signal?: AbortSignal): Promise<ComputerState | undefined>;
26
+ onResumed?(state: ComputerState): void;
27
+ /**
28
+ * 按当前观测解析出该应用的说明书,供应用专属的人工介入信号使用。
29
+ *
30
+ * ⚠️ 以依赖注入的形式给进来,而不是让本模块自己去 import 说明书加载器 ——
31
+ * 那会让「通用的人机边界判定」反向依赖「具体应用的知识加载」,正是要避免的
32
+ * 方向。不注入时退化成只用内核的通用判据,行为与从前一致。
33
+ */
34
+ manualFor?(state: ComputerState): { humanBoundary?: ManualHumanBoundary[] } | undefined;
35
+ }): ComputerInterventionAdapter {
36
+ const detect = (state: ComputerState) =>
37
+ detectComputerHumanBoundary(state, input.manualFor?.(state));
38
+ const waitForOwner = async (
39
+ pending: PendingHumanIntervention,
40
+ signal?: AbortSignal,
41
+ ): Promise<{ resolution: 'resumed' | 'cancelled'; state?: ComputerState }> => {
42
+ const resolution = await input.coordinator.wait(pending.id, signal);
43
+ if (resolution.status !== 'resumed') return { resolution: 'cancelled' };
44
+ const refreshed = await input.observe(signal);
45
+ if (!refreshed) return { resolution: 'cancelled' };
46
+ return { resolution: 'resumed', state: refreshed };
47
+ };
48
+ return {
49
+ async pause(reason, summary, signal) {
50
+ let pending = input.coordinator.get(input.context) ?? input.coordinator.request({
51
+ ownerId: input.context.ownerId,
52
+ conversationKey: input.context.conversationKey,
53
+ runId: input.context.runId,
54
+ surface: 'computer',
55
+ reason,
56
+ sanitizedSummary: summary,
57
+ });
58
+ while (true) {
59
+ const resolution = await waitForOwner(pending, signal);
60
+ if (resolution.resolution !== 'resumed' || !resolution.state) return resolution;
61
+ const boundary = detect(resolution.state);
62
+ if (!boundary) {
63
+ input.onResumed?.(resolution.state);
64
+ return resolution;
65
+ }
66
+ pending = input.coordinator.request({
67
+ ownerId: input.context.ownerId,
68
+ conversationKey: input.context.conversationKey,
69
+ runId: input.context.runId,
70
+ surface: 'computer',
71
+ reason: boundary.reason,
72
+ sanitizedSummary: boundary.summary,
73
+ target: boundary.target,
74
+ });
75
+ }
76
+ },
77
+ async inspect(initialState, signal) {
78
+ let state = initialState;
79
+ let pending = input.coordinator.get(input.context);
80
+ let boundary = detect(state);
81
+ if (!pending && !boundary) return { resolution: 'none' };
82
+
83
+ while (true) {
84
+ if (!pending) {
85
+ if (!boundary) return { resolution: 'resumed', state };
86
+ pending = input.coordinator.request({
87
+ ownerId: input.context.ownerId,
88
+ conversationKey: input.context.conversationKey,
89
+ runId: input.context.runId,
90
+ surface: 'computer',
91
+ reason: boundary.reason,
92
+ sanitizedSummary: boundary.summary,
93
+ target: boundary.target,
94
+ });
95
+ }
96
+ const resolution = await waitForOwner(pending, signal);
97
+ if (resolution.resolution !== 'resumed' || !resolution.state) {
98
+ return { resolution: 'cancelled' };
99
+ }
100
+ state = resolution.state;
101
+ boundary = detect(state);
102
+ pending = undefined;
103
+ if (!boundary) {
104
+ input.onResumed?.(state);
105
+ return { resolution: 'resumed', state };
106
+ }
107
+ }
108
+ },
109
+ };
110
+ }