minimal-agent 0.12.0 → 0.14.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 (472) hide show
  1. package/README.md +6 -5
  2. package/package.json +62 -5
  3. package/plugins/computer_use/.claude-plugin/plugin.json +1 -1
  4. package/plugins/cron-runner/src/commands.js +4 -4
  5. package/plugins/cron-runner/src/commands.ts +4 -4
  6. package/plugins/workflow-runner/.claude-plugin/plugin.json +2 -2
  7. package/plugins/workflow-runner/commands/workflow.md +57 -90
  8. package/plugins/workflow-runner/commands/workflows.md +4 -4
  9. package/plugins/workflow-runner/plugin.js +24 -13
  10. package/plugins/workflow-runner/plugin.ts +28 -13
  11. package/plugins/workflow-runner/src/discovery.js +160 -0
  12. package/plugins/workflow-runner/src/discovery.ts +194 -0
  13. package/plugins/workflow-runner/src/goalAnchor.js +53 -0
  14. package/plugins/workflow-runner/src/goalAnchor.ts +59 -0
  15. package/plugins/workflow-runner/src/index.js +204 -185
  16. package/plugins/workflow-runner/src/index.ts +249 -224
  17. package/plugins/workflow-runner/src/inputCoercion.js +40 -0
  18. package/plugins/workflow-runner/src/inputCoercion.ts +43 -0
  19. package/plugins/workflow-runner/src/journal.js +224 -0
  20. package/plugins/workflow-runner/src/journal.ts +274 -0
  21. package/plugins/workflow-runner/src/jsonSchema.js +132 -0
  22. package/plugins/workflow-runner/src/jsonSchema.ts +162 -0
  23. package/plugins/workflow-runner/src/moduleResolution.js +64 -0
  24. package/plugins/workflow-runner/src/moduleResolution.ts +71 -0
  25. package/plugins/workflow-runner/src/resourceInputs.js +220 -0
  26. package/plugins/workflow-runner/src/resourceInputs.ts +300 -0
  27. package/plugins/workflow-runner/src/runner.js +404 -467
  28. package/plugins/workflow-runner/src/runner.ts +491 -535
  29. package/plugins/workflow-runner/src/runtime/config.js +46 -0
  30. package/plugins/workflow-runner/src/runtime/config.ts +69 -0
  31. package/plugins/workflow-runner/src/runtime/context.js +1304 -0
  32. package/plugins/workflow-runner/src/runtime/context.ts +1786 -0
  33. package/plugins/workflow-runner/src/runtime/exec.js +34 -0
  34. package/plugins/workflow-runner/src/runtime/exec.ts +53 -0
  35. package/plugins/workflow-runner/src/runtime/flow.js +8 -0
  36. package/plugins/workflow-runner/src/runtime/flow.ts +12 -0
  37. package/plugins/workflow-runner/src/runtime/fs.js +27 -0
  38. package/plugins/workflow-runner/src/runtime/fs.ts +41 -0
  39. package/plugins/workflow-runner/src/runtime/model.js +6 -0
  40. package/plugins/workflow-runner/src/runtime/model.ts +8 -0
  41. package/plugins/workflow-runner/src/runtime/output.js +7 -0
  42. package/plugins/workflow-runner/src/runtime/output.ts +21 -0
  43. package/plugins/workflow-runner/src/runtime/scheduler.js +141 -0
  44. package/plugins/workflow-runner/src/runtime/scheduler.ts +166 -0
  45. package/plugins/workflow-runner/src/runtime/state.js +16 -0
  46. package/plugins/workflow-runner/src/runtime/state.ts +19 -0
  47. package/plugins/workflow-runner/src/runtime/tools.js +3 -0
  48. package/plugins/workflow-runner/src/runtime/tools.ts +6 -0
  49. package/plugins/workflow-runner/src/sandbox.js +141 -0
  50. package/plugins/workflow-runner/src/sandbox.ts +182 -0
  51. package/plugins/workflow-runner/src/scriptGuard.d.mts +38 -0
  52. package/plugins/workflow-runner/src/scriptGuard.mjs +449 -0
  53. package/plugins/workflow-runner/src/taskIdentity.js +172 -152
  54. package/plugins/workflow-runner/src/taskIdentity.ts +233 -200
  55. package/plugins/workflow-runner/src/toolRuntime.js +29 -8
  56. package/plugins/workflow-runner/src/toolRuntime.ts +36 -11
  57. package/plugins/workflow-runner/src/types.js +7 -105
  58. package/plugins/workflow-runner/src/types.ts +155 -520
  59. package/plugins/workflow-runner/src/util.js +47 -0
  60. package/plugins/workflow-runner/src/util.ts +51 -0
  61. package/plugins/workflow-runner/src/workflowContext.js +20 -0
  62. package/plugins/workflow-runner/src/workflowContext.ts +58 -0
  63. package/plugins/workflow-runner/src/workflowDependencies.js +36 -0
  64. package/plugins/workflow-runner/src/workflowDependencies.ts +59 -0
  65. package/plugins/workflow-runner/src/workflowFingerprint.js +118 -0
  66. package/plugins/workflow-runner/src/workflowFingerprint.ts +122 -0
  67. package/plugins/workflow-runner/src/workflowState.js +542 -469
  68. package/plugins/workflow-runner/src/workflowState.ts +639 -589
  69. package/plugins/workflow-runner/test/api.test.ts +223 -0
  70. package/plugins/workflow-runner/test/apiCapabilities.test.ts +614 -0
  71. package/plugins/workflow-runner/test/apiConcurrencyGate.test.ts +104 -0
  72. package/plugins/workflow-runner/test/apiEcho.test.ts +210 -0
  73. package/plugins/workflow-runner/test/apiReadText.test.ts +178 -0
  74. package/plugins/workflow-runner/test/apiResourceLedger.test.ts +184 -0
  75. package/plugins/workflow-runner/test/childWorkflow.test.ts +304 -0
  76. package/plugins/workflow-runner/test/discovery.test.ts +234 -0
  77. package/plugins/workflow-runner/test/goalAnchor.test.ts +106 -0
  78. package/plugins/workflow-runner/test/goalController.test.ts +317 -0
  79. package/plugins/workflow-runner/test/journalLanes.test.ts +198 -0
  80. package/plugins/workflow-runner/test/listResources.test.ts +106 -0
  81. package/plugins/workflow-runner/test/resourceInputs.test.ts +294 -0
  82. package/plugins/workflow-runner/test/sandbox.test.ts +126 -0
  83. package/plugins/workflow-runner/test/scheduler.test.ts +70 -0
  84. package/plugins/workflow-runner/test/scriptGuard.test.ts +276 -0
  85. package/plugins/workflow-runner/test/skillDocSync.test.ts +78 -0
  86. package/plugins/workflow-runner/test/taskIdentity.test.ts +288 -179
  87. package/plugins/workflow-runner/test/workflowFingerprint.test.ts +106 -0
  88. package/plugins/workflow-runner/test/workflowState.test.ts +429 -0
  89. package/skills/pptx/examples/assets/cover-bg.svg +23 -0
  90. package/skills/pptx/examples/assets/icon-spark.svg +5 -0
  91. package/skills/skill-creator/scripts/run_eval.py +3 -2
  92. package/skills/ui-design/SKILL.md +5 -2
  93. package/skills/ui-design/references/layout-composition.md +1 -1
  94. package/skills/workflow-creator/SKILL.md +344 -0
  95. package/skills/workflow-creator/assets/template/workflow.mjs +48 -0
  96. package/skills/workflow-creator/references/api.md +216 -0
  97. package/skills/workflow-creator/references/migration.md +103 -0
  98. package/skills/workflow-creator/references/patterns.md +779 -0
  99. package/skills/workflow-creator/scripts/list-resources.mjs +205 -0
  100. package/skills/workflow-creator/scripts/scaffold.mjs +148 -0
  101. package/skills/workflow-creator/scripts/validate.mjs +275 -0
  102. package/skills/workflow-creator/scripts/workflow-creator.test.mjs +82 -0
  103. package/src/advisor/advisorCoordinator.js +503 -0
  104. package/src/advisor/advisorCoordinator.ts +657 -0
  105. package/src/cli/configMenu.tsx +0 -1
  106. package/src/cli/print.js +44 -6
  107. package/src/cli/print.ts +73 -4
  108. package/src/cli/streamJson.js +5 -6
  109. package/src/cli/streamJson.ts +8 -4
  110. package/src/cli/wizards/advisorWizard.js +4 -2
  111. package/src/cli/wizards/advisorWizard.tsx +8 -2
  112. package/src/cli/wizards/contextAdvisorWizard.js +5 -4
  113. package/src/cli/wizards/contextAdvisorWizard.tsx +7 -6
  114. package/src/collaboration/taskFlow.js +115 -0
  115. package/src/collaboration/taskFlow.ts +169 -0
  116. package/src/config/configDefaults.js +41 -1
  117. package/src/config/configDefaults.ts +43 -1
  118. package/src/config/configDiagnostics.ts +2 -2
  119. package/src/config/configFile.js +40 -9
  120. package/src/config/configFile.ts +60 -11
  121. package/src/config/configService.js +443 -74
  122. package/src/config/configService.ts +723 -142
  123. package/src/config/numericLimits.js +22 -0
  124. package/src/config/numericLimits.ts +24 -0
  125. package/src/config.js +1 -0
  126. package/src/config.ts +3 -2
  127. package/src/context/budgetPlan.js +1 -1
  128. package/src/context/budgetPlan.ts +1 -1
  129. package/src/context/compact.js +7 -2
  130. package/src/context/compact.ts +9 -2
  131. package/src/context/microCompactLite.js +212 -13
  132. package/src/context/microCompactLite.ts +261 -12
  133. package/src/context/sessionRegistry.js +8 -1
  134. package/src/context/sessionRegistry.ts +18 -5
  135. package/src/context/toolResultArchive.js +72 -0
  136. package/src/context/toolResultArchive.ts +95 -0
  137. package/src/goal/errors.js +8 -0
  138. package/src/goal/errors.ts +18 -0
  139. package/src/goal/goalRuntime.js +344 -0
  140. package/src/goal/goalRuntime.ts +466 -0
  141. package/src/goal/goalStore.js +200 -0
  142. package/src/goal/goalStore.ts +219 -0
  143. package/src/goal/index.js +4 -0
  144. package/src/goal/index.ts +4 -0
  145. package/src/goal/statusMapping.js +71 -0
  146. package/src/goal/statusMapping.ts +95 -0
  147. package/src/goal/types.js +7 -0
  148. package/src/goal/types.ts +179 -0
  149. package/src/goal/workflowController.js +306 -0
  150. package/src/goal/workflowController.ts +360 -0
  151. package/src/harness/evidenceLedger.js +2 -0
  152. package/src/harness/evidenceLedger.ts +1 -0
  153. package/src/harness/stallGuard.js +9 -3
  154. package/src/harness/stallGuard.ts +7 -3
  155. package/src/images/imageResolver.js +161 -0
  156. package/src/images/imageResolver.ts +189 -0
  157. package/src/infra/verification.js +56 -20
  158. package/src/infra/verification.ts +87 -20
  159. package/src/llm/client.js +79 -21
  160. package/src/llm/client.ts +182 -35
  161. package/src/llm/gatewayClient.js +201 -0
  162. package/src/llm/gatewayClient.ts +299 -0
  163. package/src/llm/messageProvenance.js +46 -0
  164. package/src/llm/messageProvenance.ts +58 -0
  165. package/src/llm/modelProvider.js +1 -0
  166. package/src/llm/modelProvider.ts +22 -0
  167. package/src/llm/providers/anthropicFormat.js +108 -1
  168. package/src/llm/providers/anthropicFormat.ts +115 -4
  169. package/src/llm/providers/openaiFormat.js +9 -0
  170. package/src/llm/providers/openaiFormat.ts +12 -3
  171. package/src/loop.js +319 -54
  172. package/src/loop.ts +373 -57
  173. package/src/main.js +4 -1
  174. package/src/main.tsx +4 -1
  175. package/src/managedExecution/index.js +2 -0
  176. package/src/managedExecution/index.ts +2 -0
  177. package/src/managedExecution/registry.js +15 -0
  178. package/src/managedExecution/registry.ts +20 -0
  179. package/src/managedExecution/types.js +1 -0
  180. package/src/managedExecution/types.ts +86 -0
  181. package/src/modelRef.js +9 -0
  182. package/src/modelRef.ts +31 -0
  183. package/src/multimodal.js +14 -28
  184. package/src/multimodal.ts +17 -33
  185. package/src/net/lanDiscovery.js +65 -0
  186. package/src/net/lanDiscovery.ts +82 -0
  187. package/src/plugin-sdk.js +28 -3
  188. package/src/plugin-sdk.ts +39 -6
  189. package/src/plugins/pluginApi.ts +16 -1
  190. package/src/plugins/pluginLoader.js +4 -0
  191. package/src/plugins/pluginLoader.ts +6 -0
  192. package/src/plugins/pluginRunner.js +152 -9
  193. package/src/plugins/pluginRunner.ts +186 -8
  194. package/src/plugins/slashFallback.js +113 -0
  195. package/src/plugins/slashFallback.ts +137 -0
  196. package/src/prompts/policyRegistry.js +15 -8
  197. package/src/prompts/policyRegistry.ts +18 -8
  198. package/src/prompts/promptAssembly.js +103 -12
  199. package/src/prompts/promptAssembly.ts +114 -12
  200. package/src/prompts/skillList.js +21 -3
  201. package/src/prompts/skillList.ts +27 -2
  202. package/src/prompts/stableSystemPrompt.js +18 -0
  203. package/src/prompts/stableSystemPrompt.ts +33 -0
  204. package/src/runtime/agentRuntimeContext.js +8 -2
  205. package/src/runtime/agentRuntimeContext.ts +17 -4
  206. package/src/session/runAgentTurn.js +78 -12
  207. package/src/session/runAgentTurn.ts +105 -23
  208. package/src/session/runTurn.js +10 -9
  209. package/src/session/runTurn.ts +17 -8
  210. package/src/session/sessionState.ts +2 -0
  211. package/src/team/auth.js +186 -0
  212. package/src/team/auth.ts +298 -0
  213. package/src/team/cli.js +105 -0
  214. package/src/team/cli.ts +122 -0
  215. package/src/team/onlineToolContract.js +64 -0
  216. package/src/team/onlineToolContract.ts +109 -0
  217. package/src/team/toolPolicy.js +36 -0
  218. package/src/team/toolPolicy.ts +75 -0
  219. package/src/tools/advisor/advisor.js +148 -37
  220. package/src/tools/advisor/advisor.ts +161 -38
  221. package/src/tools/advisor/advisorDecision.js +71 -0
  222. package/src/tools/advisor/advisorDecision.ts +85 -0
  223. package/src/tools/agent/agent.js +18 -5
  224. package/src/tools/agent/agent.ts +21 -7
  225. package/src/tools/agent/agentControl.js +246 -0
  226. package/src/tools/agent/agentControl.ts +284 -0
  227. package/src/tools/agent/agentTaskService.js +40 -1
  228. package/src/tools/agent/agentTaskService.ts +44 -1
  229. package/src/tools/agent/agentTypes.js +14 -2
  230. package/src/tools/agent/agentTypes.ts +15 -2
  231. package/src/tools/applypatch/applyPatch.js +362 -0
  232. package/src/tools/applypatch/applyPatch.ts +428 -0
  233. package/src/tools/bash/bash.js +70 -18
  234. package/src/tools/bash/bash.ts +75 -20
  235. package/src/tools/capabilities.js +10 -5
  236. package/src/tools/capabilities.ts +10 -5
  237. package/src/tools/computeruse/computerIntent.js +32 -0
  238. package/src/tools/computeruse/computerIntent.ts +46 -0
  239. package/src/tools/computeruse/telemetryLog.js +12 -0
  240. package/src/tools/computeruse/telemetryLog.ts +16 -0
  241. package/src/tools/computeruse/vision/telemetry.js +1 -0
  242. package/src/tools/computeruse/vision/telemetry.ts +1 -0
  243. package/src/tools/effectiveToolSet.js +4 -0
  244. package/src/tools/effectiveToolSet.ts +4 -0
  245. package/src/tools/index.js +21 -2
  246. package/src/tools/index.ts +33 -2
  247. package/src/tools/powershell/powershell.js +18 -1
  248. package/src/tools/powershell/powershell.ts +18 -2
  249. package/src/tools/presentresult/presentresult.js +6 -15
  250. package/src/tools/presentresult/presentresult.ts +6 -15
  251. package/src/tools/read/read.js +69 -11
  252. package/src/tools/read/read.ts +70 -11
  253. package/src/tools/shared/fileUtils.js +1 -2
  254. package/src/tools/shared/fileUtils.ts +1 -2
  255. package/src/tools/shared/permanentDeleteGuard.js +34 -3
  256. package/src/tools/shared/permanentDeleteGuard.ts +43 -6
  257. package/src/tools/shared/toolOutputStore.js +23 -1
  258. package/src/tools/shared/toolOutputStore.ts +22 -1
  259. package/src/tools/skill/skill.js +9 -3
  260. package/src/tools/skill/skill.ts +8 -4
  261. package/src/tools/toolPromptGuides.js +117 -0
  262. package/src/tools/toolPromptGuides.ts +137 -0
  263. package/src/tools/webbrowser/agentBrowserPath.js +19 -9
  264. package/src/tools/webbrowser/agentBrowserPath.ts +70 -28
  265. package/src/tools/webbrowser/browser.js +27 -11
  266. package/src/tools/webbrowser/browser.ts +68 -24
  267. package/src/tools/webbrowser/browserAutomation.js +329 -0
  268. package/src/tools/webbrowser/browserAutomation.ts +467 -0
  269. package/src/tools/webbrowser/browserAxState.js +97 -0
  270. package/src/tools/webbrowser/browserAxState.ts +142 -0
  271. package/src/tools/webbrowser/browserBatch.js +1578 -0
  272. package/src/tools/webbrowser/browserBatch.ts +2382 -0
  273. package/src/tools/webbrowser/browserCdp.js +208 -0
  274. package/src/tools/webbrowser/browserCdp.ts +255 -0
  275. package/src/tools/webbrowser/browserConditions.js +24 -0
  276. package/src/tools/webbrowser/browserConditions.ts +45 -0
  277. package/src/tools/webbrowser/browserContent.js +281 -0
  278. package/src/tools/webbrowser/browserContent.ts +438 -0
  279. package/src/tools/webbrowser/browserControl.js +131 -30
  280. package/src/tools/webbrowser/browserControl.ts +210 -50
  281. package/src/tools/webbrowser/browserDaemon.js +22 -14
  282. package/src/tools/webbrowser/browserDaemon.ts +54 -21
  283. package/src/tools/webbrowser/browserFrames.js +47 -0
  284. package/src/tools/webbrowser/browserFrames.ts +54 -0
  285. package/src/tools/webbrowser/browserInteractionResolver.js +17 -0
  286. package/src/tools/webbrowser/browserInteractionResolver.ts +40 -0
  287. package/src/tools/webbrowser/browserLocator.js +140 -0
  288. package/src/tools/webbrowser/browserLocator.ts +194 -0
  289. package/src/tools/webbrowser/browserOutcome.js +10 -17
  290. package/src/tools/webbrowser/browserOutcome.ts +48 -31
  291. package/src/tools/webbrowser/browserRecovery.js +58 -0
  292. package/src/tools/webbrowser/browserRecovery.ts +83 -0
  293. package/src/tools/webbrowser/browserRunRegistry.js +35 -3
  294. package/src/tools/webbrowser/browserRunRegistry.ts +91 -15
  295. package/src/tools/webbrowser/browserService.js +28 -2
  296. package/src/tools/webbrowser/browserService.ts +49 -9
  297. package/src/tools/webbrowser/browserStream.js +132 -33
  298. package/src/tools/webbrowser/browserStream.ts +224 -50
  299. package/src/tools/webbrowser/browserTabs.js +48 -15
  300. package/src/tools/webbrowser/browserTabs.ts +178 -96
  301. package/src/tools/webbrowser/webbrowser.js +683 -144
  302. package/src/tools/webbrowser/webbrowser.ts +979 -236
  303. package/src/tools/webfetch/preapproved.js +0 -2
  304. package/src/tools/webfetch/preapproved.ts +0 -2
  305. package/src/tools/websearch/websearch.js +129 -8
  306. package/src/tools/websearch/websearch.ts +138 -6
  307. package/src/types.ts +450 -42
  308. package/src/ui/App.js +377 -58
  309. package/src/ui/App.tsx +576 -111
  310. package/src/ui/LiveArea.js +14 -8
  311. package/src/ui/LiveArea.tsx +14 -10
  312. package/src/ui/MessageList.js +63 -20
  313. package/src/ui/MessageList.tsx +101 -16
  314. package/src/ui/ModelPicker.js +7 -4
  315. package/src/ui/ModelPicker.tsx +55 -8
  316. package/src/ui/hooks/useChat.js +152 -163
  317. package/src/ui/hooks/useChat.ts +396 -334
  318. package/src/ui/loginCommand.js +56 -0
  319. package/src/ui/loginCommand.ts +63 -0
  320. package/src/ui/toolProgress.js +41 -0
  321. package/src/ui/toolProgress.ts +44 -0
  322. package/src/web/browserBridge.js +20 -2
  323. package/src/web/browserBridge.ts +20 -2
  324. package/src/web/protocol.ts +1897 -194
  325. package/workflows/adaptive-research/workflow.mjs +86 -0
  326. package/workflows/e2e-capabilities/workflow.mjs +102 -0
  327. package/workflows/e2e-llm/workflow.mjs +52 -0
  328. package/workflows/e2e-smoke/workflow.mjs +59 -0
  329. package/workflows/e2e-vision-schema/README.md +48 -0
  330. package/workflows/e2e-vision-schema/workflow.mjs +149 -0
  331. package/workflows/e2e-write-greet/workflow.mjs +37 -0
  332. package/workflows/file-census/README.md +14 -0
  333. package/workflows/file-census/scripts/.gitkeep +2 -0
  334. package/workflows/file-census/workflow.mjs +110 -0
  335. package/workflows/goal/README.md +166 -0
  336. package/workflows/goal/prompts/audit.md +57 -0
  337. package/workflows/goal/prompts/contract.md +56 -0
  338. package/workflows/goal/prompts/iterate.md +37 -0
  339. package/workflows/goal/workflow.mjs +501 -0
  340. package/workflows/illustrate/README.md +90 -0
  341. package/workflows/illustrate/assets/engines.json +20 -0
  342. package/workflows/illustrate/assets/extract-baidu.js +21 -0
  343. package/workflows/illustrate/assets/extract-bing.js +33 -0
  344. package/workflows/illustrate/assets/extract-google.js +31 -0
  345. package/workflows/illustrate/workflow.mjs +301 -0
  346. package/workflows/plan/workflow.mjs +389 -0
  347. package/workflows/question-crops/README.md +35 -0
  348. package/workflows/question-crops/prompts/inventory.md +23 -0
  349. package/workflows/question-crops/scripts/image-ops.mjs +305 -0
  350. package/workflows/question-crops/scripts/image-ops.test.mjs +95 -0
  351. package/workflows/question-crops/workflow.mjs +172 -0
  352. package/workflows/ralph-loop/workflow.mjs +162 -0
  353. package/workflows/research/DESIGN.md +449 -0
  354. package/workflows/research/README.md +74 -0
  355. package/workflows/research/prompts/s0-goal.md +43 -0
  356. package/workflows/research/prompts/s1-early-exit.md +22 -0
  357. package/workflows/research/prompts/s1-map.md +58 -0
  358. package/workflows/research/prompts/s2-options.md +53 -0
  359. package/workflows/research/prompts/s3-deep-dive.md +56 -0
  360. package/workflows/research/prompts/s4-verify.md +74 -0
  361. package/workflows/research/prompts/s5-synthesis.md +81 -0
  362. package/workflows/research/prompts/s5b-fill-gaps.md +32 -0
  363. package/workflows/research/prompts/s6-package.md +32 -0
  364. package/workflows/research/scripts/build-report.mjs +98 -0
  365. package/workflows/research/workflow.mjs +288 -0
  366. package/workflows/wechat-reading-shots/prompts/collect-params.md +16 -0
  367. package/workflows/wechat-reading-shots/prompts/evaluate.md +20 -0
  368. package/workflows/wechat-reading-shots/prompts/open-book.md +28 -0
  369. package/workflows/wechat-reading-shots/prompts/read-page.md +13 -0
  370. package/workflows/wechat-reading-shots/prompts/turn-batch.md +24 -0
  371. package/workflows/wechat-reading-shots/test/control-flow.test.ts +329 -0
  372. package/workflows/wechat-reading-shots/workflow.mjs +266 -0
  373. package/workflows/wrong-question-docx/README.md +55 -0
  374. package/workflows/wrong-question-docx/prompts/figure-qa.md +8 -0
  375. package/workflows/wrong-question-docx/prompts/transcribe.md +25 -0
  376. package/workflows/wrong-question-docx/scripts/workbook.mjs +857 -0
  377. package/workflows/wrong-question-docx/test/control-flow.test.ts +165 -0
  378. package/workflows/wrong-question-docx/test/workbook.test.mjs +303 -0
  379. package/workflows/wrong-question-docx/workflow.mjs +485 -0
  380. package/plugins/workflow-runner/src/agentCommon.js +0 -354
  381. package/plugins/workflow-runner/src/agentCommon.ts +0 -435
  382. package/plugins/workflow-runner/src/controlFlow/branch.js +0 -40
  383. package/plugins/workflow-runner/src/controlFlow/branch.ts +0 -46
  384. package/plugins/workflow-runner/src/controlFlow/loop.js +0 -211
  385. package/plugins/workflow-runner/src/controlFlow/loop.ts +0 -248
  386. package/plugins/workflow-runner/src/controlFlow/pause.js +0 -129
  387. package/plugins/workflow-runner/src/controlFlow/pause.ts +0 -141
  388. package/plugins/workflow-runner/src/controlFlow/signal.js +0 -21
  389. package/plugins/workflow-runner/src/controlFlow/signal.ts +0 -29
  390. package/plugins/workflow-runner/src/controlFlow/types.js +0 -18
  391. package/plugins/workflow-runner/src/controlFlow/types.ts +0 -63
  392. package/plugins/workflow-runner/src/dslManifest.js +0 -72
  393. package/plugins/workflow-runner/src/dslManifest.ts +0 -127
  394. package/plugins/workflow-runner/src/expressions.js +0 -618
  395. package/plugins/workflow-runner/src/expressions.ts +0 -622
  396. package/plugins/workflow-runner/src/loader.js +0 -573
  397. package/plugins/workflow-runner/src/loader.ts +0 -721
  398. package/plugins/workflow-runner/src/multimodal.js +0 -38
  399. package/plugins/workflow-runner/src/multimodal.ts +0 -64
  400. package/plugins/workflow-runner/src/recovery.js +0 -119
  401. package/plugins/workflow-runner/src/recovery.ts +0 -149
  402. package/plugins/workflow-runner/src/stepExecutors/agent.js +0 -173
  403. package/plugins/workflow-runner/src/stepExecutors/agent.ts +0 -234
  404. package/plugins/workflow-runner/src/stepExecutors/assert.js +0 -41
  405. package/plugins/workflow-runner/src/stepExecutors/assert.ts +0 -50
  406. package/plugins/workflow-runner/src/stepExecutors/echo.js +0 -31
  407. package/plugins/workflow-runner/src/stepExecutors/echo.ts +0 -38
  408. package/plugins/workflow-runner/src/stepExecutors/llm.js +0 -99
  409. package/plugins/workflow-runner/src/stepExecutors/llm.ts +0 -133
  410. package/plugins/workflow-runner/src/stepExecutors/set.js +0 -49
  411. package/plugins/workflow-runner/src/stepExecutors/set.ts +0 -56
  412. package/plugins/workflow-runner/src/stepExecutors/skill.js +0 -111
  413. package/plugins/workflow-runner/src/stepExecutors/skill.ts +0 -140
  414. package/plugins/workflow-runner/src/stepExecutors/tool.js +0 -208
  415. package/plugins/workflow-runner/src/stepExecutors/tool.ts +0 -256
  416. package/plugins/workflow-runner/src/stepExecutors/verify.js +0 -58
  417. package/plugins/workflow-runner/src/stepExecutors/verify.ts +0 -68
  418. package/plugins/workflow-runner/src/stepPipeline.js +0 -277
  419. package/plugins/workflow-runner/src/stepPipeline.ts +0 -366
  420. package/plugins/workflow-runner/test/agent.test.ts +0 -587
  421. package/plugins/workflow-runner/test/agentLlmError.test.ts +0 -373
  422. package/plugins/workflow-runner/test/bashBlacklist.sweep.test.ts +0 -65
  423. package/plugins/workflow-runner/test/captureMisbind.test.ts +0 -99
  424. package/plugins/workflow-runner/test/cli.e2e.test.ts +0 -147
  425. package/plugins/workflow-runner/test/context-files.test.ts +0 -320
  426. package/plugins/workflow-runner/test/e2e.test.ts +0 -370
  427. package/plugins/workflow-runner/test/engineRobustness.test.ts +0 -226
  428. package/plugins/workflow-runner/test/expressions.test.ts +0 -397
  429. package/plugins/workflow-runner/test/foundation.test.ts +0 -126
  430. package/plugins/workflow-runner/test/graceful.test.ts +0 -139
  431. package/plugins/workflow-runner/test/greedyInputs.load.test.ts +0 -47
  432. package/plugins/workflow-runner/test/hostCapability.test.ts +0 -108
  433. package/plugins/workflow-runner/test/illustrate.load.test.ts +0 -183
  434. package/plugins/workflow-runner/test/jsonPayload.test.ts +0 -83
  435. package/plugins/workflow-runner/test/loader.test.ts +0 -617
  436. package/plugins/workflow-runner/test/maxTurnsRetryDelay.test.ts +0 -33
  437. package/plugins/workflow-runner/test/multimodal.test.ts +0 -342
  438. package/plugins/workflow-runner/test/output-schema.test.ts +0 -213
  439. package/plugins/workflow-runner/test/parseWorkflowArgs.test.ts +0 -87
  440. package/plugins/workflow-runner/test/pluginRunner.isolation.test.ts +0 -269
  441. package/plugins/workflow-runner/test/ppt.load.test.ts +0 -1220
  442. package/plugins/workflow-runner/test/ralphLoop.e2e.test.ts +0 -220
  443. package/plugins/workflow-runner/test/recovery.test.ts +0 -265
  444. package/plugins/workflow-runner/test/runner.test.ts +0 -911
  445. package/plugins/workflow-runner/test/runnerPreflight.test.ts +0 -379
  446. package/plugins/workflow-runner/test/skillTurnDone.test.ts +0 -71
  447. package/plugins/workflow-runner/test/stateLifecycle.test.ts +0 -150
  448. package/plugins/workflow-runner/test/stepPipeline.test.ts +0 -114
  449. package/plugins/workflow-runner/test/taskArbitration.test.ts +0 -338
  450. package/plugins/workflow-runner/test/taskLifecycle.test.ts +0 -270
  451. package/plugins/workflow-runner/test/toolArtifactOverwrite.test.ts +0 -221
  452. package/plugins/workflow-runner/test/toolCapabilityBoundary.test.ts +0 -29
  453. package/plugins/workflow-runner/test/toolRuntimeIntegration.test.ts +0 -168
  454. package/plugins/workflow-runner/test/webppt.load.test.ts +0 -250
  455. package/plugins/workflow-runner/test/word.load.test.ts +0 -208
  456. package/plugins/workflow-runner/test/workflows.smoke.test.ts +0 -76
  457. package/plugins/workflow-runner/test/yamlGuardConditions.test.ts +0 -207
  458. package/src/advisorState.js +0 -22
  459. package/src/cli/configWizard.js +0 -293
  460. package/src/tools/toolProgressBridge.js +0 -48
  461. package/workflows/adaptive-research.yaml +0 -50
  462. package/workflows/book-review-short.yaml +0 -125
  463. package/workflows/e2e-write-greet.yaml +0 -31
  464. package/workflows/illustrate.yaml +0 -227
  465. package/workflows/plan.yaml +0 -470
  466. package/workflows/ppt.yaml +0 -1670
  467. package/workflows/ralph-loop.yaml +0 -199
  468. package/workflows/schema.json +0 -176
  469. package/workflows/webppt.yaml +0 -496
  470. package/workflows/wechat-reading-shots.yaml +0 -315
  471. package/workflows/word.yaml +0 -720
  472. package/workflows/youtube-shorts.yaml +0 -202
@@ -0,0 +1,467 @@
1
+ /**
2
+ * Persistent CDP transport used by BrowserBatch and BrowserCDP.
3
+ *
4
+ * The browser daemon is deliberately still owned by agent-browser; this module
5
+ * only replaces the short lived command clients used for each automation step.
6
+ */
7
+ import { mkdir, stat } from 'node:fs/promises';
8
+ import os from 'node:os';
9
+ import path from 'node:path';
10
+
11
+ import type { AgentBrowserRunner } from './browser.js';
12
+ import { sessionArgs } from './browser.js';
13
+ import { ensureDaemon } from './browserDaemon.js';
14
+
15
+ export type CdpEvent = {
16
+ sequence: number;
17
+ method: string;
18
+ params: Record<string, unknown>;
19
+ sessionId?: string;
20
+ at: number;
21
+ };
22
+ export type BrowserDownload = {
23
+ id: string;
24
+ url: string;
25
+ filename: string;
26
+ path: string;
27
+ state: 'start' | 'progress' | 'complete' | 'failed' | 'canceled';
28
+ receivedBytes?: number;
29
+ totalBytes?: number;
30
+ mime?: string;
31
+ error?: string;
32
+ };
33
+
34
+ export const BROWSER_TAB_MARKER_KEY = '__minimalAgentTabMarker';
35
+
36
+ type Pending = {
37
+ resolve: (value: unknown) => void;
38
+ reject: (reason: Error) => void;
39
+ timer: ReturnType<typeof setTimeout>;
40
+ onAbort?: () => void;
41
+ signal?: AbortSignal;
42
+ };
43
+
44
+ class CdpConnection {
45
+ private socket: WebSocket | null = null;
46
+ private opening: Promise<void> | null = null;
47
+ private pageTargetId: string | undefined;
48
+ private pageSessionId: string | undefined;
49
+ private id = 0;
50
+ private pending = new Map<number, Pending>();
51
+ private events: CdpEvent[] = [];
52
+ private sequence = 0;
53
+ private listeners = new Set<(event: CdpEvent) => void>();
54
+
55
+ constructor(private readonly url: string) {}
56
+
57
+ /**
58
+ * A connection is page-scoped. It must not be put back in a process-wide
59
+ * pool and rebound by another conversation while this caller still holds it.
60
+ */
61
+ close(): void {
62
+ const socket = this.socket;
63
+ this.socket = null;
64
+ this.pageTargetId = undefined;
65
+ this.pageSessionId = undefined;
66
+ socket?.close();
67
+ }
68
+
69
+ get attachedPageSessionId(): string | undefined {
70
+ return this.pageSessionId;
71
+ }
72
+
73
+ get attachedPageTargetId(): string | undefined {
74
+ return this.pageTargetId;
75
+ }
76
+
77
+ async evaluateInFrame(
78
+ frameId: string,
79
+ expression: string,
80
+ signal?: AbortSignal,
81
+ ): Promise<unknown> {
82
+ const isolated = (await this.send(
83
+ 'Page.createIsolatedWorld',
84
+ {
85
+ frameId,
86
+ worldName: 'minimal-agent-browser',
87
+ grantUniveralAccess: false,
88
+ },
89
+ undefined,
90
+ 30_000,
91
+ signal,
92
+ )) as { executionContextId?: unknown };
93
+ if (typeof isolated.executionContextId !== 'number')
94
+ throw new Error(`无法创建 frame execution context:${frameId}`);
95
+ return this.send(
96
+ 'Runtime.evaluate',
97
+ {
98
+ expression,
99
+ contextId: isolated.executionContextId,
100
+ returnByValue: true,
101
+ awaitPromise: true,
102
+ },
103
+ undefined,
104
+ 30_000,
105
+ signal,
106
+ );
107
+ }
108
+
109
+ async frameOwnerOffset(
110
+ frameId: string,
111
+ signal?: AbortSignal,
112
+ ): Promise<{ x: number; y: number }> {
113
+ // CDP returns the owner quad in top-level viewport coordinates, including
114
+ // nested cross-origin frames. Do not add ancestor offsets a second time.
115
+ const owner = (await this.send(
116
+ 'DOM.getFrameOwner',
117
+ { frameId },
118
+ undefined,
119
+ 30_000,
120
+ signal,
121
+ )) as { backendNodeId?: unknown };
122
+ if (typeof owner.backendNodeId !== 'number')
123
+ throw new Error(`无法取得 frame owner:${frameId}`);
124
+ const box = (await this.send(
125
+ 'DOM.getBoxModel',
126
+ { backendNodeId: owner.backendNodeId },
127
+ undefined,
128
+ 30_000,
129
+ signal,
130
+ )) as { model?: { border?: unknown } };
131
+ const border = box.model?.border;
132
+ if (!Array.isArray(border) || border.length < 2)
133
+ throw new Error(`无法取得 frame owner 坐标:${frameId}`);
134
+ const numbers = border.filter(
135
+ (value): value is number => typeof value === 'number',
136
+ );
137
+ if (numbers.length < 2) throw new Error(`frame owner 坐标无效:${frameId}`);
138
+ return { x: numbers[0]!, y: numbers[1]! };
139
+ }
140
+
141
+ async open(): Promise<void> {
142
+ if (this.socket?.readyState === WebSocket.OPEN) return;
143
+ if (this.opening) return this.opening;
144
+ this.opening = new Promise<void>((resolve, reject) => {
145
+ const socket = new WebSocket(this.url);
146
+ const timer = setTimeout(() => {
147
+ socket.close();
148
+ reject(new Error('CDP connection timed out'));
149
+ }, 10_000);
150
+ socket.onopen = () => {
151
+ clearTimeout(timer);
152
+ this.socket = socket;
153
+ resolve();
154
+ };
155
+ socket.onerror = () => {
156
+ clearTimeout(timer);
157
+ reject(new Error('Unable to connect to browser CDP'));
158
+ };
159
+ socket.onclose = () => {
160
+ if (this.socket === socket) this.socket = null;
161
+ this.pageTargetId = undefined;
162
+ this.pageSessionId = undefined;
163
+ for (const [id, request] of this.pending) {
164
+ clearTimeout(request.timer);
165
+ if (request.signal && request.onAbort)
166
+ request.signal.removeEventListener('abort', request.onAbort);
167
+ request.reject(new Error('CDP connection closed'));
168
+ this.pending.delete(id);
169
+ }
170
+ };
171
+ socket.onmessage = (message) => this.onMessage(String(message.data));
172
+ }).finally(() => {
173
+ this.opening = null;
174
+ });
175
+ return this.opening;
176
+ }
177
+
178
+ private onMessage(raw: string): void {
179
+ let data: Record<string, unknown>;
180
+ try {
181
+ data = JSON.parse(raw) as Record<string, unknown>;
182
+ } catch {
183
+ return;
184
+ }
185
+ if (typeof data.id === 'number') {
186
+ const request = this.pending.get(data.id);
187
+ if (!request) return;
188
+ this.pending.delete(data.id);
189
+ clearTimeout(request.timer);
190
+ if (request.signal && request.onAbort)
191
+ request.signal.removeEventListener('abort', request.onAbort);
192
+ if (data.error) request.reject(new Error(JSON.stringify(data.error)));
193
+ else request.resolve(data.result ?? {});
194
+ return;
195
+ }
196
+ if (typeof data.method !== 'string') return;
197
+ const event: CdpEvent = {
198
+ sequence: ++this.sequence,
199
+ method: data.method,
200
+ params: (data.params ?? {}) as Record<string, unknown>,
201
+ sessionId:
202
+ typeof data.sessionId === 'string' ? data.sessionId : undefined,
203
+ at: Date.now(),
204
+ };
205
+ if (
206
+ event.method === 'Target.detachedFromTarget' &&
207
+ String(event.params.sessionId ?? '') === this.pageSessionId
208
+ ) {
209
+ this.pageTargetId = undefined;
210
+ this.pageSessionId = undefined;
211
+ }
212
+ if (
213
+ (event.method === 'Target.targetDestroyed' ||
214
+ event.method === 'Target.targetCrashed') &&
215
+ String(event.params.targetId ?? '') === this.pageTargetId
216
+ ) {
217
+ this.pageTargetId = undefined;
218
+ this.pageSessionId = undefined;
219
+ }
220
+ this.events.push(event);
221
+ if (this.events.length > 500)
222
+ this.events.splice(0, this.events.length - 500);
223
+ for (const listener of this.listeners) {
224
+ try {
225
+ listener(event);
226
+ } catch {
227
+ // One observer must not break delivery to the remaining CDP consumers.
228
+ }
229
+ }
230
+ }
231
+
232
+ async send(
233
+ method: string,
234
+ params: Record<string, unknown> = {},
235
+ target?: string,
236
+ timeoutMs = 30_000,
237
+ signal?: AbortSignal,
238
+ ): Promise<unknown> {
239
+ await this.open();
240
+ const socket = this.socket;
241
+ if (!socket || socket.readyState !== WebSocket.OPEN)
242
+ throw new Error('CDP connection is unavailable');
243
+ const id = ++this.id;
244
+ const pageDomain =
245
+ /^(Accessibility|DOM|Input|Log|Network|Page|Performance|Runtime|Security)\./.test(
246
+ method,
247
+ );
248
+ const effectiveTarget =
249
+ target ?? (pageDomain ? this.pageSessionId : undefined);
250
+ return new Promise((resolve, reject) => {
251
+ const abortError = () =>
252
+ signal?.reason instanceof Error
253
+ ? signal.reason
254
+ : new Error(`CDP ${method} aborted`);
255
+ const cleanup = () => {
256
+ const request = this.pending.get(id);
257
+ if (!request) return false;
258
+ this.pending.delete(id);
259
+ clearTimeout(request.timer);
260
+ if (request.signal && request.onAbort)
261
+ request.signal.removeEventListener('abort', request.onAbort);
262
+ return true;
263
+ };
264
+ const onAbort = () => {
265
+ if (cleanup()) reject(abortError());
266
+ };
267
+ const timer = setTimeout(() => {
268
+ if (cleanup()) reject(new Error(`CDP ${method} timed out`));
269
+ }, timeoutMs);
270
+ this.pending.set(id, { resolve, reject, timer, onAbort, signal });
271
+ if (signal?.aborted) {
272
+ onAbort();
273
+ return;
274
+ }
275
+ signal?.addEventListener('abort', onAbort, { once: true });
276
+ try {
277
+ socket.send(
278
+ JSON.stringify({
279
+ id,
280
+ method,
281
+ params,
282
+ ...(effectiveTarget ? { sessionId: effectiveTarget } : {}),
283
+ }),
284
+ );
285
+ } catch (error) {
286
+ if (cleanup())
287
+ reject(error instanceof Error ? error : new Error(String(error)));
288
+ }
289
+ });
290
+ }
291
+
292
+ async attachToPage(
293
+ preferredUrl?: string,
294
+ force = false,
295
+ preferredMarker?: string,
296
+ ): Promise<void> {
297
+ if (this.pageSessionId && !force) return;
298
+ if (force && this.pageSessionId) {
299
+ const previousSession = this.pageSessionId;
300
+ this.pageSessionId = undefined;
301
+ this.pageTargetId = undefined;
302
+ await this.send('Target.detachFromTarget', {
303
+ sessionId: previousSession,
304
+ }).catch(() => undefined);
305
+ }
306
+ const targets = (await this.send('Target.getTargets')) as {
307
+ targetInfos?: Array<{
308
+ targetId?: unknown;
309
+ type?: unknown;
310
+ url?: unknown;
311
+ }>;
312
+ };
313
+ const pages = (targets.targetInfos ?? []).filter(
314
+ (target) => target.type === 'page' && typeof target.targetId === 'string',
315
+ );
316
+ if (!pages.length) throw new Error('浏览器没有可绑定的页面标签');
317
+ let selected = preferredMarker
318
+ ? undefined
319
+ : preferredUrl
320
+ ? pages.find((target) => target.url === preferredUrl)
321
+ : undefined;
322
+ if (preferredMarker) {
323
+ const marker = JSON.stringify(preferredMarker);
324
+ for (const candidate of pages) {
325
+ const attached = (await this.send('Target.attachToTarget', {
326
+ targetId: candidate.targetId,
327
+ flatten: true,
328
+ })) as { sessionId?: unknown };
329
+ const sessionId = attached.sessionId;
330
+ if (typeof sessionId !== 'string') continue;
331
+ const probe = await this.send(
332
+ 'Runtime.evaluate',
333
+ {
334
+ expression: `globalThis[${JSON.stringify(BROWSER_TAB_MARKER_KEY)}] === ${marker}`,
335
+ returnByValue: true,
336
+ },
337
+ sessionId,
338
+ ).catch(() => undefined);
339
+ if (
340
+ (probe as { result?: { value?: unknown } } | undefined)?.result
341
+ ?.value === true
342
+ ) {
343
+ selected = candidate;
344
+ this.pageTargetId = String(candidate.targetId);
345
+ this.pageSessionId = sessionId;
346
+ break;
347
+ }
348
+ await this.send('Target.detachFromTarget', { sessionId }).catch(
349
+ () => undefined,
350
+ );
351
+ }
352
+ }
353
+ if (preferredMarker) {
354
+ if (!selected) throw new Error('无法通过会话标记绑定到当前浏览器标签');
355
+ return;
356
+ }
357
+ selected ??= pages[pages.length - 1]!;
358
+ const attached = (await this.send('Target.attachToTarget', {
359
+ targetId: selected.targetId,
360
+ flatten: true,
361
+ })) as { sessionId?: unknown };
362
+ if (typeof attached.sessionId !== 'string')
363
+ throw new Error('浏览器未返回页面 target session');
364
+ this.pageTargetId = selected.targetId as string;
365
+ this.pageSessionId = attached.sessionId;
366
+ }
367
+
368
+ read(after = 0, methods?: string[], limit = 100): CdpEvent[] {
369
+ return this.events
370
+ .filter(
371
+ (event) =>
372
+ event.sequence > after &&
373
+ (!methods?.length || methods.includes(event.method)),
374
+ )
375
+ .slice(-Math.max(1, Math.min(limit, 500)));
376
+ }
377
+ subscribe(listener: (event: CdpEvent) => void): () => void {
378
+ this.listeners.add(listener);
379
+ return () => this.listeners.delete(listener);
380
+ }
381
+ }
382
+
383
+ async function cdpUrl(
384
+ sessionName: string,
385
+ bin: string,
386
+ run: AgentBrowserRunner,
387
+ signal?: AbortSignal,
388
+ ): Promise<string> {
389
+ await ensureDaemon(sessionName, { signal });
390
+ const output = await run(
391
+ bin,
392
+ [...sessionArgs(sessionName), 'get', 'cdp-url'],
393
+ signal,
394
+ );
395
+ const url = `${output.stdout}\n${output.stderr}`.match(
396
+ /ws:\/\/[^\s"']+/,
397
+ )?.[0];
398
+ if (output.code !== 0 || !url) throw new Error('无法取得浏览器 CDP 地址');
399
+ return url;
400
+ }
401
+
402
+ export async function getBrowserAutomation(
403
+ sessionName: string,
404
+ bin: string,
405
+ run: AgentBrowserRunner,
406
+ signal?: AbortSignal,
407
+ preferredUrl?: string,
408
+ preferredMarker?: string,
409
+ ): Promise<CdpConnection> {
410
+ const url = await cdpUrl(sessionName, bin, run, signal);
411
+ // The browser endpoint is shared, but the attached page is not. Returning
412
+ // a fresh connection prevents a later conversation from changing the
413
+ // mutable page session underneath an in-flight batch.
414
+ const conn = new CdpConnection(url);
415
+ await conn.open();
416
+ await conn.attachToPage(preferredUrl, true, preferredMarker);
417
+ return conn;
418
+ }
419
+
420
+ export function browserDownloadDir(
421
+ conversationKey = 'local',
422
+ runId = 'default',
423
+ ): string {
424
+ const safe = (value: string) =>
425
+ value.replace(/[^a-zA-Z0-9._-]/g, '_').slice(0, 100) || 'default';
426
+ const root =
427
+ process.env.MINIMAL_AGENT_HOME ?? path.join(os.homedir(), '.minimal-agent');
428
+ return path.join(
429
+ root,
430
+ 'browser',
431
+ 'downloads',
432
+ safe(conversationKey),
433
+ safe(runId),
434
+ );
435
+ }
436
+
437
+ export async function configureDownloads(
438
+ cdp: CdpConnection,
439
+ conversationKey?: string,
440
+ runId?: string,
441
+ ): Promise<string> {
442
+ const dir = browserDownloadDir(conversationKey, runId);
443
+ await mkdir(dir, { recursive: true, mode: 0o700 });
444
+ // Browser domain is current Chrome; Page fallback keeps older Chromium usable.
445
+ await cdp
446
+ .send('Browser.setDownloadBehavior', {
447
+ behavior: 'allow',
448
+ downloadPath: dir,
449
+ eventsEnabled: true,
450
+ })
451
+ .catch(() =>
452
+ cdp.send('Page.setDownloadBehavior', {
453
+ behavior: 'allow',
454
+ downloadPath: dir,
455
+ }),
456
+ );
457
+ return dir;
458
+ }
459
+
460
+ export async function finalDownload(
461
+ pathname: string,
462
+ ): Promise<Pick<BrowserDownload, 'path' | 'receivedBytes' | 'mime'>> {
463
+ const info = await stat(pathname);
464
+ return { path: pathname, receivedBytes: info.size };
465
+ }
466
+
467
+ export type { CdpConnection };
@@ -0,0 +1,97 @@
1
+ /** Compact AX state and generation-aware diffs for BrowserBatch observations. */
2
+ function axValue(input) {
3
+ if (input && typeof input === 'object' && 'value' in input)
4
+ return input.value;
5
+ return input;
6
+ }
7
+ function propertyValue(node, key) {
8
+ const value = node.properties?.find((item) => item.name === key)?.value
9
+ ?.value;
10
+ return value === undefined || value === null ? undefined : String(value);
11
+ }
12
+ export function normalizeAxTree(raw) {
13
+ const root = raw && typeof raw === 'object' ? raw : {};
14
+ const nodes = Array.isArray(raw)
15
+ ? raw
16
+ : Array.isArray(root.nodes)
17
+ ? root.nodes
18
+ : [];
19
+ return nodes
20
+ .map((value) => {
21
+ const node = value && typeof value === 'object' ? value : {};
22
+ const bounds = node?.bounds;
23
+ return {
24
+ id: String(node.nodeId ?? node.id ?? ''),
25
+ ...(node.parentId !== undefined
26
+ ? { parentId: String(node.parentId) }
27
+ : {}),
28
+ ...(axValue(node.role) || node.role
29
+ ? { role: String(axValue(node.role) ?? node.role) }
30
+ : {}),
31
+ ...(axValue(node.name) || node.name
32
+ ? { name: String(axValue(node.name) ?? node.name) }
33
+ : {}),
34
+ ...(propertyValue(node, 'value')
35
+ ? { value: propertyValue(node, 'value') }
36
+ : {}),
37
+ ...(node.ignored !== undefined
38
+ ? { ignored: Boolean(node.ignored) }
39
+ : {}),
40
+ ...(node.backendDOMNodeId !== undefined
41
+ ? { backendDOMNodeId: Number(node.backendDOMNodeId) }
42
+ : {}),
43
+ ...(bounds &&
44
+ typeof bounds.x === 'number' &&
45
+ typeof bounds.y === 'number' &&
46
+ typeof bounds.width === 'number' &&
47
+ typeof bounds.height === 'number'
48
+ ? {
49
+ bounds: {
50
+ x: bounds.x,
51
+ y: bounds.y,
52
+ width: bounds.width,
53
+ height: bounds.height,
54
+ },
55
+ }
56
+ : {}),
57
+ };
58
+ })
59
+ .filter((node) => node.id.length > 0);
60
+ }
61
+ function nodeKey(node) {
62
+ return JSON.stringify(node);
63
+ }
64
+ export function diffAxTree(previous, current, generation, pageRevision, forceFull = false) {
65
+ const next = new Map(current.map((node) => [node.id, node]));
66
+ if (!previous || forceFull) {
67
+ return {
68
+ generation,
69
+ pageRevision,
70
+ full: true,
71
+ added: current,
72
+ changed: [],
73
+ removed: [],
74
+ };
75
+ }
76
+ const added = [];
77
+ const changed = [];
78
+ for (const node of current) {
79
+ const old = previous.get(node.id);
80
+ if (!old)
81
+ added.push(node);
82
+ else if (nodeKey(old) !== nodeKey(node))
83
+ changed.push(node);
84
+ }
85
+ const removed = [...previous.keys()].filter((id) => !next.has(id));
86
+ return { generation, pageRevision, full: false, added, changed, removed };
87
+ }
88
+ export function conciseAxTree(nodes) {
89
+ return nodes
90
+ .map((node, index) => {
91
+ const details = [node.role, node.name, node.value]
92
+ .filter(Boolean)
93
+ .join(' ');
94
+ return `[ax=${node.id}]${details ? ` ${details}` : ''} index=${index}${node.ignored ? ' (ignored)' : ''}`;
95
+ })
96
+ .join('\n');
97
+ }
@@ -0,0 +1,142 @@
1
+ /** Compact AX state and generation-aware diffs for BrowserBatch observations. */
2
+
3
+ export interface BrowserAxNode {
4
+ id: string;
5
+ parentId?: string;
6
+ role?: string;
7
+ name?: string;
8
+ value?: string;
9
+ ignored?: boolean;
10
+ backendDOMNodeId?: number;
11
+ bounds?: { x: number; y: number; width: number; height: number };
12
+ }
13
+
14
+ export interface BrowserAxDiff {
15
+ generation: number;
16
+ pageRevision: number;
17
+ full: boolean;
18
+ added: BrowserAxNode[];
19
+ changed: BrowserAxNode[];
20
+ removed: string[];
21
+ }
22
+
23
+ type RawAxProperty = { name?: unknown; value?: { value?: unknown } };
24
+ type RawAxNode = {
25
+ nodeId?: unknown;
26
+ id?: unknown;
27
+ parentId?: unknown;
28
+ role?: unknown;
29
+ name?: unknown;
30
+ ignored?: unknown;
31
+ backendDOMNodeId?: unknown;
32
+ bounds?: { x?: unknown; y?: unknown; width?: unknown; height?: unknown };
33
+ properties?: RawAxProperty[];
34
+ };
35
+
36
+ function axValue(input: unknown): unknown {
37
+ if (input && typeof input === 'object' && 'value' in input)
38
+ return (input as { value?: unknown }).value;
39
+ return input;
40
+ }
41
+
42
+ function propertyValue(node: RawAxNode, key: string): string | undefined {
43
+ const value = node.properties?.find((item) => item.name === key)?.value
44
+ ?.value;
45
+ return value === undefined || value === null ? undefined : String(value);
46
+ }
47
+
48
+ export function normalizeAxTree(raw: unknown): BrowserAxNode[] {
49
+ const root =
50
+ raw && typeof raw === 'object' ? (raw as { nodes?: unknown }) : {};
51
+ const nodes = Array.isArray(raw)
52
+ ? raw
53
+ : Array.isArray(root.nodes)
54
+ ? root.nodes
55
+ : [];
56
+ return nodes
57
+ .map((value: unknown) => {
58
+ const node =
59
+ value && typeof value === 'object' ? (value as RawAxNode) : {};
60
+ const bounds = node?.bounds;
61
+ return {
62
+ id: String(node.nodeId ?? node.id ?? ''),
63
+ ...(node.parentId !== undefined
64
+ ? { parentId: String(node.parentId) }
65
+ : {}),
66
+ ...(axValue(node.role) || node.role
67
+ ? { role: String(axValue(node.role) ?? node.role) }
68
+ : {}),
69
+ ...(axValue(node.name) || node.name
70
+ ? { name: String(axValue(node.name) ?? node.name) }
71
+ : {}),
72
+ ...(propertyValue(node, 'value')
73
+ ? { value: propertyValue(node, 'value') }
74
+ : {}),
75
+ ...(node.ignored !== undefined
76
+ ? { ignored: Boolean(node.ignored) }
77
+ : {}),
78
+ ...(node.backendDOMNodeId !== undefined
79
+ ? { backendDOMNodeId: Number(node.backendDOMNodeId) }
80
+ : {}),
81
+ ...(bounds &&
82
+ typeof bounds.x === 'number' &&
83
+ typeof bounds.y === 'number' &&
84
+ typeof bounds.width === 'number' &&
85
+ typeof bounds.height === 'number'
86
+ ? {
87
+ bounds: {
88
+ x: bounds.x,
89
+ y: bounds.y,
90
+ width: bounds.width,
91
+ height: bounds.height,
92
+ },
93
+ }
94
+ : {}),
95
+ } satisfies BrowserAxNode;
96
+ })
97
+ .filter((node: BrowserAxNode) => node.id.length > 0);
98
+ }
99
+
100
+ function nodeKey(node: BrowserAxNode): string {
101
+ return JSON.stringify(node);
102
+ }
103
+
104
+ export function diffAxTree(
105
+ previous: Map<string, BrowserAxNode> | undefined,
106
+ current: BrowserAxNode[],
107
+ generation: number,
108
+ pageRevision: number,
109
+ forceFull = false,
110
+ ): BrowserAxDiff {
111
+ const next = new Map(current.map((node) => [node.id, node]));
112
+ if (!previous || forceFull) {
113
+ return {
114
+ generation,
115
+ pageRevision,
116
+ full: true,
117
+ added: current,
118
+ changed: [],
119
+ removed: [],
120
+ };
121
+ }
122
+ const added: BrowserAxNode[] = [];
123
+ const changed: BrowserAxNode[] = [];
124
+ for (const node of current) {
125
+ const old = previous.get(node.id);
126
+ if (!old) added.push(node);
127
+ else if (nodeKey(old) !== nodeKey(node)) changed.push(node);
128
+ }
129
+ const removed = [...previous.keys()].filter((id) => !next.has(id));
130
+ return { generation, pageRevision, full: false, added, changed, removed };
131
+ }
132
+
133
+ export function conciseAxTree(nodes: BrowserAxNode[]): string {
134
+ return nodes
135
+ .map((node, index) => {
136
+ const details = [node.role, node.name, node.value]
137
+ .filter(Boolean)
138
+ .join(' ');
139
+ return `[ax=${node.id}]${details ? ` ${details}` : ''} index=${index}${node.ignored ? ' (ignored)' : ''}`;
140
+ })
141
+ .join('\n');
142
+ }