@xopcai/xopc 0.0.112 → 0.0.114

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 (351) hide show
  1. package/dist/browser-ext/icons/icon-128.png +0 -0
  2. package/dist/browser-ext/icons/icon-16.png +0 -0
  3. package/dist/browser-ext/icons/icon-32.png +0 -0
  4. package/dist/browser-ext/icons/icon-48.png +0 -0
  5. package/dist/browser-ext/manifest.json +1 -1
  6. package/dist/extensions/telegram/xopc.extension.json +1 -1
  7. package/dist/extensions/weixin/src/delivery-to.d.ts +3 -3
  8. package/dist/extensions/weixin/src/delivery-to.js.map +1 -1
  9. package/dist/gateway/static/root/apple-touch-icon.png +0 -0
  10. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-EhRp-ZMa.js → agent-avatar-dicebear-Fp-p7bP1.js} +1 -1
  11. package/dist/gateway/static/root/assets/agent-browser-settings-page-CWh7trjd.js +6 -0
  12. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-kC8OuLoj.js +1 -0
  13. package/dist/gateway/static/root/assets/agents-DJWG26Si.js +71 -0
  14. package/dist/gateway/static/root/assets/{app-management-settings-panel-BIy7KEsM.js → app-management-settings-panel-v24i25Oj.js} +1 -1
  15. package/dist/gateway/static/root/assets/{appearance-settings-DGQG8NwA.js → appearance-settings-ycbdJRuZ.js} +1 -1
  16. package/dist/gateway/static/root/assets/apps-page-0V3DXZ7J.js +1 -0
  17. package/dist/gateway/static/root/assets/{archive-plugin-uuQPupqx.js → archive-plugin-CJzSADJo.js} +1 -1
  18. package/dist/gateway/static/root/assets/{attachment-load-DBkv0cAv.js → attachment-load-BTAB4zGS.js} +1 -1
  19. package/dist/gateway/static/root/assets/{binary-plugins-DxxN_VAR.js → binary-plugins-DXR1-mct.js} +1 -1
  20. package/dist/gateway/static/root/assets/{block-editor-CwnUlRmO.js → block-editor-CzQri9h2.js} +44 -44
  21. package/dist/gateway/static/root/assets/channels-settings-CIKOkYdO.js +1 -0
  22. package/dist/gateway/static/root/assets/{config-api-BD-NcD5d.js → config-api-DRqjEvAx.js} +1 -1
  23. package/dist/gateway/static/root/assets/connectors-settings-ClrDS5jH.js +2 -0
  24. package/dist/gateway/static/root/assets/{cron-api-C5DoipZA.js → cron-api-BXaZXv1o.js} +1 -1
  25. package/dist/gateway/static/root/assets/cron-page-Chi_4u4P.js +3 -0
  26. package/dist/gateway/static/root/assets/dreaming-settings-B0_rs2tj.js +1 -0
  27. package/dist/gateway/static/root/assets/{extension-debug-page-BDHA9o_e.js → extension-debug-page-DSkqMYo7.js} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-page-DmDLVSPE.js → extension-page-h2dGDbMN.js} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-settings-page-1124aHw_.js → extension-settings-page-hN99RhOi.js} +1 -1
  30. package/dist/gateway/static/root/assets/{fetch-DOe56Wmy.js → fetch-D9QqUtzZ.js} +1 -1
  31. package/dist/gateway/static/root/assets/{format-interval-label-tsMSvBSR.js → format-interval-label-D6E687rG.js} +1 -1
  32. package/dist/gateway/static/root/assets/{gateway-config-api-CsD4FC9D.js → gateway-config-api-CLt_SKTC.js} +1 -1
  33. package/dist/gateway/static/root/assets/{gateway-settings-HQ8FBhY2.js → gateway-settings-1PDi4lI0.js} +1 -1
  34. package/dist/gateway/static/root/assets/{gateway-startup-retry-C1zg7pH3.js → gateway-startup-retry-N7Z_sz7p.js} +1 -1
  35. package/dist/gateway/static/root/assets/goal-detail-page-D_wwXL-t.js +1 -0
  36. package/dist/gateway/static/root/assets/goals-page-DZ2toZ8y.js +2 -0
  37. package/dist/gateway/static/root/assets/{goals-settings-B5nI6lgz.js → goals-settings-LFlwtIKE.js} +1 -1
  38. package/dist/gateway/static/root/assets/{heartbeat-config-api-CIv42nJD.js → heartbeat-config-api-DGPadTw-.js} +1 -1
  39. package/dist/gateway/static/root/assets/{heartbeat-settings-DFcVuJ3M.js → heartbeat-settings-BHHAs8ZX.js} +1 -1
  40. package/dist/gateway/static/root/assets/index-DefIdW9q.js +122 -0
  41. package/dist/gateway/static/root/assets/index-DzmWBkq-.css +1 -0
  42. package/dist/gateway/static/root/assets/{interval-presets-DGP3S7OB.js → interval-presets-CEklPQ_r.js} +1 -1
  43. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-fETaDYQP.js → keyboard-shortcuts-settings-Ce_aQ8Iv.js} +1 -1
  44. package/dist/gateway/static/root/assets/logs-page-j_D2QTuQ.js +2 -0
  45. package/dist/gateway/static/root/assets/{markdown-split-CgeBJMOD.js → markdown-split-BMz3xPXO.js} +1 -1
  46. package/dist/gateway/static/root/assets/{media-plugins-C30GzlV2.js → media-plugins-BalOSoz9.js} +1 -1
  47. package/dist/gateway/static/root/assets/messages-BN_WiUg0.js +3 -0
  48. package/dist/gateway/static/root/assets/models-hub-panel-CMH_TmZz.js +2 -0
  49. package/dist/gateway/static/root/assets/note-detail-page-O18BrQPq.js +2 -0
  50. package/dist/gateway/static/root/assets/{note-image-lightbox-t1g0qZYh.js → note-image-lightbox-C5D1Q5mY.js} +1 -1
  51. package/dist/gateway/static/root/assets/notes-page-B_ZYCmY9.js +1 -0
  52. package/dist/gateway/static/root/assets/{preview-open-alternatives-DeWp9x5g.js → preview-open-alternatives-CYFR5U9l.js} +1 -1
  53. package/dist/gateway/static/root/assets/remote-access-hub-CwKgWixY.js +1 -0
  54. package/dist/gateway/static/root/assets/{save-bar-controls-BOaAOJI3.js → save-bar-controls-BQ79Z5IP.js} +1 -1
  55. package/dist/gateway/static/root/assets/{schedule-field-BLWLKqgw.js → schedule-field-Bgk6Emue.js} +1 -1
  56. package/dist/gateway/static/root/assets/{schema-form-plqRFYT8.js → schema-form-DzS36TMa.js} +1 -1
  57. package/dist/gateway/static/root/assets/sessions-page-C4fcD-7B.js +1 -0
  58. package/dist/gateway/static/root/assets/settings-advanced-gate-Ad2OJ86w.js +1 -0
  59. package/dist/gateway/static/root/assets/{settings-collapsible-section-BP5zRrDI.js → settings-collapsible-section-CdjFnSAy.js} +1 -1
  60. package/dist/gateway/static/root/assets/{settings-form-section-Bv8MZplG.js → settings-form-section-DZLy_exu.js} +1 -1
  61. package/dist/gateway/static/root/assets/settings-page-D2BMY5wo.js +1 -0
  62. package/dist/gateway/static/root/assets/setup-status-panel-aWwxl_E1.js +1 -0
  63. package/dist/gateway/static/root/assets/{share-preview-page-4OX1YCgp.js → share-preview-page-_qRDr4g_.js} +1 -1
  64. package/dist/gateway/static/root/assets/shares-settings-DUE83uIf.js +1 -0
  65. package/dist/gateway/static/root/assets/skill-reload-api-mWKJcrog.js +1 -0
  66. package/dist/gateway/static/root/assets/skills-page-0Sx1Q58n.js +2 -0
  67. package/dist/gateway/static/root/assets/{system-settings-panel-CGy4f_s2.js → system-settings-panel-hqaBF5aG.js} +1 -1
  68. package/dist/gateway/static/root/assets/use-agent-defaults-form-zbVIQLOA.js +1 -0
  69. package/dist/gateway/static/root/assets/{use-channel-catalog-CjGHnDvN.js → use-channel-catalog-CbXq97rT.js} +1 -1
  70. package/dist/gateway/static/root/assets/{use-settings-tab-guard-BMMFa0oA.js → use-settings-tab-guard-DwS3drWK.js} +1 -1
  71. package/dist/gateway/static/root/assets/voice-api-key-field-D6HR0hR2.js +1 -0
  72. package/dist/gateway/static/root/assets/{voice-player-store-D5vzWwls.js → voice-player-store-DSuOd9zy.js} +1 -1
  73. package/dist/gateway/static/root/assets/workflow-page.utils-C0Uq3xyq.js +1 -0
  74. package/dist/gateway/static/root/assets/workflows-page-DW0fmWhQ.js +18 -0
  75. package/dist/gateway/static/root/favicon-16x16.png +0 -0
  76. package/dist/gateway/static/root/favicon-32x32.png +0 -0
  77. package/dist/gateway/static/root/favicon-icon.svg +1 -0
  78. package/dist/gateway/static/root/favicon.ico +0 -0
  79. package/dist/gateway/static/root/favicon.png +0 -0
  80. package/dist/gateway/static/root/favicon.svg +24 -17
  81. package/dist/gateway/static/root/index.html +5 -5
  82. package/dist/gateway/static/root/logo-dark.svg +23 -15
  83. package/dist/gateway/static/root/logo.svg +23 -16
  84. package/dist/package.js +1 -1
  85. package/dist/src/agent/agent-manager.d.ts +8 -0
  86. package/dist/src/agent/agent-manager.js +57 -22
  87. package/dist/src/agent/agent-manager.js.map +1 -1
  88. package/dist/src/agent/bootstrap/project-agents-context.d.ts +2 -0
  89. package/dist/src/agent/bootstrap/project-agents-context.js +32 -0
  90. package/dist/src/agent/bootstrap/project-agents-context.js.map +1 -0
  91. package/dist/src/agent/goals/persistent-goal-service.js +2 -4
  92. package/dist/src/agent/goals/persistent-goal-service.js.map +1 -1
  93. package/dist/src/agent/inbound/inbound-loop.js +5 -1
  94. package/dist/src/agent/inbound/inbound-loop.js.map +1 -1
  95. package/dist/src/agent/inbound/turn-dispatcher.d.ts +2 -2
  96. package/dist/src/agent/inbound/turn-dispatcher.js +2 -2
  97. package/dist/src/agent/inbound/turn-dispatcher.js.map +1 -1
  98. package/dist/src/agent/mcp/bundle-mcp-materialize.d.ts +27 -0
  99. package/dist/src/agent/mcp/bundle-mcp-materialize.js +49 -1
  100. package/dist/src/agent/mcp/bundle-mcp-materialize.js.map +1 -1
  101. package/dist/src/agent/mcp/bundle-mcp-runtime.js +78 -3
  102. package/dist/src/agent/mcp/bundle-mcp-runtime.js.map +1 -1
  103. package/dist/src/agent/mcp/bundle-mcp-types.d.ts +19 -0
  104. package/dist/src/agent/service/btw-query.js +11 -3
  105. package/dist/src/agent/service/btw-query.js.map +1 -1
  106. package/dist/src/agent/service/parse-outbound-session-key.js +13 -8
  107. package/dist/src/agent/service/parse-outbound-session-key.js.map +1 -1
  108. package/dist/src/agent/service/process-direct-one-shot.d.ts +2 -2
  109. package/dist/src/agent/service/process-direct-one-shot.js +1 -1
  110. package/dist/src/agent/service/process-direct-one-shot.js.map +1 -1
  111. package/dist/src/agent/service/process-direct-streaming.d.ts +2 -2
  112. package/dist/src/agent/service/process-direct-streaming.js +10 -5
  113. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  114. package/dist/src/agent/service.d.ts +1 -1
  115. package/dist/src/agent/service.js +9 -5
  116. package/dist/src/agent/service.js.map +1 -1
  117. package/dist/src/agent/service.types.d.ts +5 -0
  118. package/dist/src/agent/skills/filesystem-watcher.js +4 -3
  119. package/dist/src/agent/skills/filesystem-watcher.js.map +1 -1
  120. package/dist/src/agent/skills/index.js +2 -1
  121. package/dist/src/agent/skills/index.js.map +1 -1
  122. package/dist/src/agent/skills/skill-manage-ops.js +2 -1
  123. package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
  124. package/dist/src/agent/skills/types.d.ts +1 -1
  125. package/dist/src/agent/skills/watcher.js +2 -5
  126. package/dist/src/agent/skills/watcher.js.map +1 -1
  127. package/dist/src/agent/skills/workspace-skills-dir.d.ts +1 -0
  128. package/dist/src/agent/skills/workspace-skills-dir.js +11 -0
  129. package/dist/src/agent/skills/workspace-skills-dir.js.map +1 -0
  130. package/dist/src/agent/tool-manuals/browser.d.ts +1 -1
  131. package/dist/src/agent/tool-manuals/browser.js +62 -3
  132. package/dist/src/agent/tool-manuals/browser.js.map +1 -1
  133. package/dist/src/agent/tools/browser/tool/browser-use-tool.d.ts +4 -1
  134. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +13 -4
  135. package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
  136. package/dist/src/agent/tools/browser/tool/schemas.d.ts +0 -2
  137. package/dist/src/agent/tools/browser/tool/schemas.js +1 -2
  138. package/dist/src/agent/tools/browser/tool/schemas.js.map +1 -1
  139. package/dist/src/agent/tools/factory.js +1 -10
  140. package/dist/src/agent/tools/factory.js.map +1 -1
  141. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  142. package/dist/src/agent/tools/skill-manage-tool.js.map +1 -1
  143. package/dist/src/agent/workflow/subagent-runner.js +18 -1
  144. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  145. package/dist/src/ai-assist/text-assist.d.ts +3 -0
  146. package/dist/src/ai-assist/text-assist.js +25 -7
  147. package/dist/src/ai-assist/text-assist.js.map +1 -1
  148. package/dist/src/browser/actions/extension-registry-bridge.js +91 -7
  149. package/dist/src/browser/actions/extension-registry-bridge.js.map +1 -1
  150. package/dist/src/browser/actions/registry.js +383 -7
  151. package/dist/src/browser/actions/registry.js.map +1 -1
  152. package/dist/src/browser/actions/types.d.ts +11 -3
  153. package/dist/src/browser/index.js +2 -2
  154. package/dist/src/browser/pipeline/output.d.ts +18 -16
  155. package/dist/src/browser/pipeline/output.js +28 -20
  156. package/dist/src/browser/pipeline/output.js.map +1 -1
  157. package/dist/src/browser/pipeline/runner.d.ts +7 -14
  158. package/dist/src/browser/pipeline/runner.js +349 -102
  159. package/dist/src/browser/pipeline/runner.js.map +1 -1
  160. package/dist/src/browser/pipeline/schema.d.ts +1 -0
  161. package/dist/src/browser/pipeline/schema.js +35 -58
  162. package/dist/src/browser/pipeline/schema.js.map +1 -1
  163. package/dist/src/browser/pipeline/source.d.ts +2 -0
  164. package/dist/src/browser/pipeline/source.js +10 -1
  165. package/dist/src/browser/pipeline/source.js.map +1 -1
  166. package/dist/src/browser/pipeline/template.d.ts +10 -2
  167. package/dist/src/browser/pipeline/template.js +50 -8
  168. package/dist/src/browser/pipeline/template.js.map +1 -1
  169. package/dist/src/channels/plugins/types.adapters.d.ts +2 -2
  170. package/dist/src/chat-commands/builtins/config.js +3 -5
  171. package/dist/src/chat-commands/builtins/config.js.map +1 -1
  172. package/dist/src/chat-commands/context.d.ts +5 -0
  173. package/dist/src/chat-commands/context.js +18 -9
  174. package/dist/src/chat-commands/context.js.map +1 -1
  175. package/dist/src/chat-commands/index.d.ts +1 -1
  176. package/dist/src/chat-commands/index.js +2 -2
  177. package/dist/src/chat-commands/index.js.map +1 -1
  178. package/dist/src/chat-commands/processor.js +22 -21
  179. package/dist/src/chat-commands/processor.js.map +1 -1
  180. package/dist/src/chat-commands/session-key.d.ts +3 -15
  181. package/dist/src/chat-commands/session-key.js +3 -49
  182. package/dist/src/chat-commands/session-key.js.map +1 -1
  183. package/dist/src/chat-commands/types.d.ts +4 -0
  184. package/dist/src/cli/commands/browser-cli-helpers.js +11 -5
  185. package/dist/src/cli/commands/browser-cli-helpers.js.map +1 -1
  186. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  187. package/dist/src/cli/commands/doctor/checks/session-integrity.js +8 -8
  188. package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
  189. package/dist/src/config/rules.js +5 -0
  190. package/dist/src/config/rules.js.map +1 -1
  191. package/dist/src/connectors/builtin-catalog.js +180 -1
  192. package/dist/src/connectors/builtin-catalog.js.map +1 -1
  193. package/dist/src/connectors/health.js +18 -9
  194. package/dist/src/connectors/health.js.map +1 -1
  195. package/dist/src/connectors/types.d.ts +19 -0
  196. package/dist/src/connectors/usage.js +12 -4
  197. package/dist/src/connectors/usage.js.map +1 -1
  198. package/dist/src/cron/executor.js.map +1 -1
  199. package/dist/src/cron/types.d.ts +2 -2
  200. package/dist/src/extensions/types/tui.d.ts +2 -0
  201. package/dist/src/gateway/heartbeat/service.js +13 -1
  202. package/dist/src/gateway/heartbeat/service.js.map +1 -1
  203. package/dist/src/gateway/hono/app.js +13 -4
  204. package/dist/src/gateway/hono/app.js.map +1 -1
  205. package/dist/src/gateway/hono/oauth-async.js +1 -1
  206. package/dist/src/gateway/hono/routes/agent-stream.js +6 -6
  207. package/dist/src/gateway/hono/routes/agent-stream.js.map +1 -1
  208. package/dist/src/gateway/hono/routes/config-patch/gateway.d.ts +1 -1
  209. package/dist/src/gateway/hono/routes/config-patch/gateway.js +6 -0
  210. package/dist/src/gateway/hono/routes/config-patch/gateway.js.map +1 -1
  211. package/dist/src/gateway/hono/routes/goals.js +16 -3
  212. package/dist/src/gateway/hono/routes/goals.js.map +1 -1
  213. package/dist/src/gateway/hono/routes/logs.js +1 -0
  214. package/dist/src/gateway/hono/routes/logs.js.map +1 -1
  215. package/dist/src/gateway/hono/routes/mcp.js +27 -8
  216. package/dist/src/gateway/hono/routes/mcp.js.map +1 -1
  217. package/dist/src/gateway/hono/routes/notes.js +14 -2
  218. package/dist/src/gateway/hono/routes/notes.js.map +1 -1
  219. package/dist/src/gateway/hono/routes/sessions.js +62 -4
  220. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  221. package/dist/src/gateway/hono/routes/workspace.js +3 -66
  222. package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
  223. package/dist/src/gateway/hono/sse.d.ts +2 -2
  224. package/dist/src/gateway/hono/sse.js +7 -15
  225. package/dist/src/gateway/hono/sse.js.map +1 -1
  226. package/dist/src/gateway/resolve-webchat-session-key.d.ts +2 -6
  227. package/dist/src/gateway/resolve-webchat-session-key.js +5 -31
  228. package/dist/src/gateway/resolve-webchat-session-key.js.map +1 -1
  229. package/dist/src/gateway/service/agent-runner.d.ts +2 -3
  230. package/dist/src/gateway/service/agent-runner.js +9 -22
  231. package/dist/src/gateway/service/agent-runner.js.map +1 -1
  232. package/dist/src/gateway/service/run-gateway-agent.js +9 -7
  233. package/dist/src/gateway/service/run-gateway-agent.js.map +1 -1
  234. package/dist/src/gateway/service/sessions-api.d.ts +9 -0
  235. package/dist/src/gateway/service/sessions-api.js +11 -0
  236. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  237. package/dist/src/gateway/service.d.ts +1 -1
  238. package/dist/src/gateway/service.js +19 -5
  239. package/dist/src/gateway/service.js.map +1 -1
  240. package/dist/src/gateway/workspace-file-search.d.ts +9 -0
  241. package/dist/src/gateway/workspace-file-search.js +76 -0
  242. package/dist/src/gateway/workspace-file-search.js.map +1 -0
  243. package/dist/src/goals/goal-notifications.d.ts +2 -0
  244. package/dist/src/goals/goal-notifications.js +16 -11
  245. package/dist/src/goals/goal-notifications.js.map +1 -1
  246. package/dist/src/goals/goal-service.js +1 -6
  247. package/dist/src/goals/goal-service.js.map +1 -1
  248. package/dist/src/project-trust/trust-store.js +2 -0
  249. package/dist/src/project-trust/trust-store.js.map +1 -1
  250. package/dist/src/session/index.d.ts +1 -1
  251. package/dist/src/session/index.js +2 -2
  252. package/dist/src/session/init-session-turn.js +6 -9
  253. package/dist/src/session/init-session-turn.js.map +1 -1
  254. package/dist/src/session/manager.d.ts +5 -1
  255. package/dist/src/session/manager.js +5 -2
  256. package/dist/src/session/manager.js.map +1 -1
  257. package/dist/src/session/reset-type.d.ts +0 -2
  258. package/dist/src/session/reset-type.js +3 -9
  259. package/dist/src/session/reset-type.js.map +1 -1
  260. package/dist/src/session/resolve-session.js +9 -20
  261. package/dist/src/session/resolve-session.js.map +1 -1
  262. package/dist/src/session/store-reader.d.ts +5 -0
  263. package/dist/src/session/store-reader.js +1 -0
  264. package/dist/src/session/store.d.ts +11 -3
  265. package/dist/src/session/store.js +29 -13
  266. package/dist/src/session/store.js.map +1 -1
  267. package/dist/src/session/types.d.ts +2 -4
  268. package/dist/src/session/types.js.map +1 -1
  269. package/dist/src/storage/sqlite/index.d.ts +2 -2
  270. package/dist/src/storage/sqlite/index.js +3 -3
  271. package/dist/src/storage/sqlite/migrations/010_session_id_identity.sql +30 -0
  272. package/dist/src/storage/sqlite/migrations/runner.d.ts +2 -2
  273. package/dist/src/storage/sqlite/migrations/runner.js +4 -4
  274. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  275. package/dist/src/storage/sqlite/migrations/runner.ts +2 -2
  276. package/dist/src/storage/sqlite/row-mappers.d.ts +4 -4
  277. package/dist/src/storage/sqlite/row-mappers.js +11 -14
  278. package/dist/src/storage/sqlite/row-mappers.js.map +1 -1
  279. package/dist/src/storage/sqlite/schema.js +3 -3
  280. package/dist/src/storage/sqlite/schema.js.map +1 -1
  281. package/dist/src/storage/sqlite/schema.sql +37 -10
  282. package/dist/src/storage/sqlite/session-metadata.d.ts +2 -7
  283. package/dist/src/storage/sqlite/session-metadata.js +18 -72
  284. package/dist/src/storage/sqlite/session-metadata.js.map +1 -1
  285. package/dist/src/storage/sqlite/session-repository.d.ts +6 -5
  286. package/dist/src/storage/sqlite/session-repository.js +34 -40
  287. package/dist/src/storage/sqlite/session-repository.js.map +1 -1
  288. package/dist/src/storage/sqlite/transcript-repository.d.ts +2 -2
  289. package/dist/src/storage/sqlite/transcript-repository.js +52 -52
  290. package/dist/src/storage/sqlite/transcript-repository.js.map +1 -1
  291. package/dist/src/tui/backends/embedded-backend.d.ts +11 -4
  292. package/dist/src/tui/backends/embedded-backend.js +27 -1
  293. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  294. package/dist/src/tui/backends/gateway-sse-backend.d.ts +4 -1
  295. package/dist/src/tui/backends/gateway-sse-backend.js +21 -2
  296. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  297. package/dist/src/tui/extension-host/autocomplete.js +13 -10
  298. package/dist/src/tui/extension-host/autocomplete.js.map +1 -1
  299. package/dist/src/tui/extension-host/runtime.d.ts +7 -0
  300. package/dist/src/tui/extension-host/runtime.js +6 -4
  301. package/dist/src/tui/extension-host/runtime.js.map +1 -1
  302. package/dist/src/tui/tui-backend.d.ts +9 -0
  303. package/dist/src/tui/tui-commands.js +85 -6
  304. package/dist/src/tui/tui-commands.js.map +1 -1
  305. package/dist/src/tui/tui-file-autocomplete.d.ts +5 -0
  306. package/dist/src/tui/tui-file-autocomplete.js +26 -0
  307. package/dist/src/tui/tui-file-autocomplete.js.map +1 -0
  308. package/dist/src/tui/tui-picker-overlay.js +1 -1
  309. package/dist/src/tui/tui.js +29 -11
  310. package/dist/src/tui/tui.js.map +1 -1
  311. package/dist/src/utils/logger/context.d.ts +2 -2
  312. package/dist/src/utils/logger/context.js +2 -1
  313. package/dist/src/utils/logger/context.js.map +1 -1
  314. package/dist/src/utils/logger/log-store.js +1 -0
  315. package/dist/src/utils/logger/log-store.js.map +1 -1
  316. package/dist/src/utils/logger/pino-record.js +3 -0
  317. package/dist/src/utils/logger/pino-record.js.map +1 -1
  318. package/dist/src/utils/logger/types.d.ts +5 -0
  319. package/dist/src/utils/logger/types.js.map +1 -1
  320. package/dist/src/workflows/service/workflow-session-bridge.js +13 -1
  321. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  322. package/package.json +1 -1
  323. package/dist/gateway/static/root/assets/agent-browser-settings-page-H4foVCiS.js +0 -6
  324. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-DDNw2oNU.js +0 -1
  325. package/dist/gateway/static/root/assets/agents-E_X2kzS1.js +0 -71
  326. package/dist/gateway/static/root/assets/apps-page-BZLvInLr.js +0 -1
  327. package/dist/gateway/static/root/assets/channels-settings-BHvUKlzw.js +0 -1
  328. package/dist/gateway/static/root/assets/connectors-settings-VBzXcEXL.js +0 -2
  329. package/dist/gateway/static/root/assets/cron-page-BLTpdm34.js +0 -3
  330. package/dist/gateway/static/root/assets/dreaming-settings-DSVhXTPq.js +0 -1
  331. package/dist/gateway/static/root/assets/goal-detail-page-BG3Onph0.js +0 -1
  332. package/dist/gateway/static/root/assets/goals-page-DgeKn8zL.js +0 -2
  333. package/dist/gateway/static/root/assets/index-5A_ZaABy.css +0 -1
  334. package/dist/gateway/static/root/assets/index-BTmbp2AU.js +0 -121
  335. package/dist/gateway/static/root/assets/logs-page-B1-b27lK.js +0 -2
  336. package/dist/gateway/static/root/assets/messages-BUUfPaZ9.js +0 -3
  337. package/dist/gateway/static/root/assets/models-hub-panel-DPcTS1-u.js +0 -2
  338. package/dist/gateway/static/root/assets/note-detail-page-xeGb4owe.js +0 -2
  339. package/dist/gateway/static/root/assets/notes-page-C_TdnKBe.js +0 -1
  340. package/dist/gateway/static/root/assets/remote-access-hub-BtkPmJIN.js +0 -1
  341. package/dist/gateway/static/root/assets/sessions-page-DOUjxzJm.js +0 -1
  342. package/dist/gateway/static/root/assets/settings-advanced-gate-qK_bnTrw.js +0 -1
  343. package/dist/gateway/static/root/assets/settings-page-DmDfE1ww.js +0 -1
  344. package/dist/gateway/static/root/assets/setup-status-panel-BEFwNcIZ.js +0 -1
  345. package/dist/gateway/static/root/assets/shares-settings-CbKmJZot.js +0 -1
  346. package/dist/gateway/static/root/assets/skill-reload-api-YdtnUHtK.js +0 -1
  347. package/dist/gateway/static/root/assets/skills-page-DwW1IzQ0.js +0 -2
  348. package/dist/gateway/static/root/assets/use-agent-defaults-form-BMuMvzl_.js +0 -1
  349. package/dist/gateway/static/root/assets/voice-api-key-field-DnRbhMNq.js +0 -1
  350. package/dist/gateway/static/root/assets/workflow-page.utils-tjGpRVnw.js +0 -1
  351. package/dist/gateway/static/root/assets/workflows-page-DqqHKGj2.js +0 -18
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { resolveWorkspaceSkillsDir } from "./workspace-skills-dir.js";
3
4
  import { watch } from "fs";
4
- import { join } from "path";
5
5
  //#region src/agent/skills/watcher.ts
6
6
  /**
7
7
  * Skill Watcher
@@ -102,10 +102,7 @@ function createSkillWatcher(loader, options) {
102
102
  */
103
103
  function createWatcherFromLoader(loader, options) {
104
104
  const watchDirs = [];
105
- if (options.workspaceDir) {
106
- const workspaceSkillsDir = join(options.workspaceDir, "skills");
107
- watchDirs.push(workspaceSkillsDir);
108
- }
105
+ if (options.workspaceDir) watchDirs.push(resolveWorkspaceSkillsDir(options.workspaceDir));
109
106
  if (options.builtinDir) watchDirs.push(options.builtinDir);
110
107
  if (options.globalDirs) watchDirs.push(...options.globalDirs);
111
108
  if (options.extraDirs) watchDirs.push(...options.extraDirs);
@@ -1 +1 @@
1
- {"version":3,"file":"watcher.js","names":[],"sources":["../../../../src/agent/skills/watcher.ts"],"sourcesContent":["/**\n * Skill Watcher\n * \n * Watches skill directories for changes and triggers reloads.\n *\n */\n\nimport { watch } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillLoader } from './index.js';\n\nconst log = createLogger('SkillWatcher');\n\nexport interface SkillWatcherOptions {\n /** Debounce time in milliseconds */\n debounceMs?: number;\n /** Watch these directories */\n watchDirs: string[];\n}\n\nexport interface SkillWatcher {\n /** Start watching */\n start: () => void;\n /** Stop watching */\n stop: () => void;\n /** Check if watching is active */\n isWatching: () => boolean;\n /** Get last refresh time */\n getLastRefreshTime: () => number;\n}\n\n/**\n * Create a debounced reload function\n */\nfunction createDebouncedReload(\n loader: SkillLoader,\n debounceMs: number\n): () => void {\n let timeout: NodeJS.Timeout | null = null;\n let pendingReload = false;\n\n return () => {\n if (timeout) {\n pendingReload = true;\n return;\n }\n\n timeout = setTimeout(() => {\n timeout = null;\n \n if (pendingReload) {\n pendingReload = false;\n loader.reload();\n log.info('Skills reloaded after directory changes');\n }\n }, debounceMs);\n };\n}\n\n/**\n * Create a skill watcher\n */\nexport function createSkillWatcher(\n loader: SkillLoader,\n options: SkillWatcherOptions\n): SkillWatcher {\n const { watchDirs, debounceMs = 1000 } = options;\n \n const watchers: Array<{ watcher: ReturnType<typeof watch>; dir: string }> = [];\n const debouncedReload = createDebouncedReload(loader, debounceMs);\n let isWatching = false;\n let lastRefreshTime = Date.now();\n\n function watchDirectory(dir: string): void {\n try {\n const watcher = watch(dir, { recursive: true }, (eventType, filename) => {\n if (!filename) return;\n\n // Only care about SKILL.md files\n if (filename.toLowerCase() === 'skill.md') {\n log.debug({ eventType, filename, dir }, 'Skill file changed');\n lastRefreshTime = Date.now();\n debouncedReload();\n }\n\n // Also watch for new directories (potential new skills)\n if (eventType === 'rename') {\n log.debug({ eventType, filename, dir }, 'Directory changed, may be new skill');\n lastRefreshTime = Date.now();\n debouncedReload();\n }\n });\n\n watchers.push({ watcher, dir });\n log.info({ dir }, 'Watching skill directory');\n } catch (err) {\n log.warn({ dir, error: err }, 'Failed to watch skill directory');\n }\n }\n\n return {\n start: () => {\n if (isWatching) {\n log.warn('Watcher already started');\n return;\n }\n\n for (const dir of watchDirs) {\n watchDirectory(dir);\n }\n\n isWatching = true;\n log.info({ dirs: watchDirs }, 'Skill watcher started');\n },\n\n stop: () => {\n if (!isWatching) {\n return;\n }\n\n for (const { watcher } of watchers) {\n watcher.close();\n }\n\n watchers.length = 0;\n isWatching = false;\n log.info('Skill watcher stopped');\n },\n\n isWatching: () => isWatching,\n\n getLastRefreshTime: () => lastRefreshTime,\n };\n}\n\n/**\n * Create a skill watcher from loader configuration\n */\nexport function createWatcherFromLoader(\n loader: SkillLoader,\n options: {\n workspaceDir?: string;\n builtinDir?: string;\n globalDirs?: string[];\n extraDirs?: string[];\n debounceMs?: number;\n }\n): SkillWatcher | null {\n const watchDirs: string[] = [];\n\n // Add workspace skills directory\n if (options.workspaceDir) {\n const workspaceSkillsDir = join(options.workspaceDir, 'skills');\n watchDirs.push(workspaceSkillsDir);\n }\n\n // Add builtin directory\n if (options.builtinDir) {\n watchDirs.push(options.builtinDir);\n }\n\n // Add global directories\n if (options.globalDirs) {\n watchDirs.push(...options.globalDirs);\n }\n\n // Add extra directories\n if (options.extraDirs) {\n watchDirs.push(...options.extraDirs);\n }\n\n if (watchDirs.length === 0) {\n log.warn('No directories to watch');\n return null;\n }\n\n return createSkillWatcher(loader, {\n watchDirs,\n debounceMs: options.debounceMs ?? 1000,\n });\n}\n"],"mappings":";;;;;;;;;;;aASqD;AAGrD,MAAM,MAAM,aAAa,eAAe;;;;AAuBxC,SAAS,sBACP,QACA,YACY;CACZ,IAAI,UAAiC;CACrC,IAAI,gBAAgB;AAEpB,cAAa;AACX,MAAI,SAAS;AACX,mBAAgB;AAChB;;AAGF,YAAU,iBAAiB;AACzB,aAAU;AAEV,OAAI,eAAe;AACjB,oBAAgB;AAChB,WAAO,QAAQ;AACf,QAAI,KAAK,0CAA0C;;KAEpD,WAAW;;;;;;AAOlB,SAAgB,mBACd,QACA,SACc;CACd,MAAM,EAAE,WAAW,aAAa,QAAS;CAEzC,MAAM,WAAsE,EAAE;CAC9E,MAAM,kBAAkB,sBAAsB,QAAQ,WAAW;CACjE,IAAI,aAAa;CACjB,IAAI,kBAAkB,KAAK,KAAK;CAEhC,SAAS,eAAe,KAAmB;AACzC,MAAI;GACF,MAAM,UAAU,MAAM,KAAK,EAAE,WAAW,MAAM,GAAG,WAAW,aAAa;AACvE,QAAI,CAAC,SAAU;AAGf,QAAI,SAAS,aAAa,KAAK,YAAY;AACzC,SAAI,MAAM;MAAE;MAAW;MAAU;MAAK,EAAE,qBAAqB;AAC7D,uBAAkB,KAAK,KAAK;AAC5B,sBAAiB;;AAInB,QAAI,cAAc,UAAU;AAC1B,SAAI,MAAM;MAAE;MAAW;MAAU;MAAK,EAAE,sCAAsC;AAC9E,uBAAkB,KAAK,KAAK;AAC5B,sBAAiB;;KAEnB;AAEF,YAAS,KAAK;IAAE;IAAS;IAAK,CAAC;AAC/B,OAAI,KAAK,EAAE,KAAK,EAAE,2BAA2B;WACtC,KAAK;AACZ,OAAI,KAAK;IAAE;IAAK,OAAO;IAAK,EAAE,kCAAkC;;;AAIpE,QAAO;EACL,aAAa;AACX,OAAI,YAAY;AACd,QAAI,KAAK,0BAA0B;AACnC;;AAGF,QAAK,MAAM,OAAO,UAChB,gBAAe,IAAI;AAGrB,gBAAa;AACb,OAAI,KAAK,EAAE,MAAM,WAAW,EAAE,wBAAwB;;EAGxD,YAAY;AACV,OAAI,CAAC,WACH;AAGF,QAAK,MAAM,EAAE,aAAa,SACxB,SAAQ,OAAO;AAGjB,YAAS,SAAS;AAClB,gBAAa;AACb,OAAI,KAAK,wBAAwB;;EAGnC,kBAAkB;EAElB,0BAA0B;EAC3B;;;;;AAMH,SAAgB,wBACd,QACA,SAOqB;CACrB,MAAM,YAAsB,EAAE;AAG9B,KAAI,QAAQ,cAAc;EACxB,MAAM,qBAAqB,KAAK,QAAQ,cAAc,SAAS;AAC/D,YAAU,KAAK,mBAAmB;;AAIpC,KAAI,QAAQ,WACV,WAAU,KAAK,QAAQ,WAAW;AAIpC,KAAI,QAAQ,WACV,WAAU,KAAK,GAAG,QAAQ,WAAW;AAIvC,KAAI,QAAQ,UACV,WAAU,KAAK,GAAG,QAAQ,UAAU;AAGtC,KAAI,UAAU,WAAW,GAAG;AAC1B,MAAI,KAAK,0BAA0B;AACnC,SAAO;;AAGT,QAAO,mBAAmB,QAAQ;EAChC;EACA,YAAY,QAAQ,cAAc;EACnC,CAAC"}
1
+ {"version":3,"file":"watcher.js","names":[],"sources":["../../../../src/agent/skills/watcher.ts"],"sourcesContent":["/**\n * Skill Watcher\n * \n * Watches skill directories for changes and triggers reloads.\n *\n */\n\nimport { watch } from 'fs';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillLoader } from './index.js';\nimport { resolveWorkspaceSkillsDir } from './workspace-skills-dir.js';\n\nconst log = createLogger('SkillWatcher');\n\nexport interface SkillWatcherOptions {\n /** Debounce time in milliseconds */\n debounceMs?: number;\n /** Watch these directories */\n watchDirs: string[];\n}\n\nexport interface SkillWatcher {\n /** Start watching */\n start: () => void;\n /** Stop watching */\n stop: () => void;\n /** Check if watching is active */\n isWatching: () => boolean;\n /** Get last refresh time */\n getLastRefreshTime: () => number;\n}\n\n/**\n * Create a debounced reload function\n */\nfunction createDebouncedReload(\n loader: SkillLoader,\n debounceMs: number\n): () => void {\n let timeout: NodeJS.Timeout | null = null;\n let pendingReload = false;\n\n return () => {\n if (timeout) {\n pendingReload = true;\n return;\n }\n\n timeout = setTimeout(() => {\n timeout = null;\n \n if (pendingReload) {\n pendingReload = false;\n loader.reload();\n log.info('Skills reloaded after directory changes');\n }\n }, debounceMs);\n };\n}\n\n/**\n * Create a skill watcher\n */\nexport function createSkillWatcher(\n loader: SkillLoader,\n options: SkillWatcherOptions\n): SkillWatcher {\n const { watchDirs, debounceMs = 1000 } = options;\n \n const watchers: Array<{ watcher: ReturnType<typeof watch>; dir: string }> = [];\n const debouncedReload = createDebouncedReload(loader, debounceMs);\n let isWatching = false;\n let lastRefreshTime = Date.now();\n\n function watchDirectory(dir: string): void {\n try {\n const watcher = watch(dir, { recursive: true }, (eventType, filename) => {\n if (!filename) return;\n\n // Only care about SKILL.md files\n if (filename.toLowerCase() === 'skill.md') {\n log.debug({ eventType, filename, dir }, 'Skill file changed');\n lastRefreshTime = Date.now();\n debouncedReload();\n }\n\n // Also watch for new directories (potential new skills)\n if (eventType === 'rename') {\n log.debug({ eventType, filename, dir }, 'Directory changed, may be new skill');\n lastRefreshTime = Date.now();\n debouncedReload();\n }\n });\n\n watchers.push({ watcher, dir });\n log.info({ dir }, 'Watching skill directory');\n } catch (err) {\n log.warn({ dir, error: err }, 'Failed to watch skill directory');\n }\n }\n\n return {\n start: () => {\n if (isWatching) {\n log.warn('Watcher already started');\n return;\n }\n\n for (const dir of watchDirs) {\n watchDirectory(dir);\n }\n\n isWatching = true;\n log.info({ dirs: watchDirs }, 'Skill watcher started');\n },\n\n stop: () => {\n if (!isWatching) {\n return;\n }\n\n for (const { watcher } of watchers) {\n watcher.close();\n }\n\n watchers.length = 0;\n isWatching = false;\n log.info('Skill watcher stopped');\n },\n\n isWatching: () => isWatching,\n\n getLastRefreshTime: () => lastRefreshTime,\n };\n}\n\n/**\n * Create a skill watcher from loader configuration\n */\nexport function createWatcherFromLoader(\n loader: SkillLoader,\n options: {\n workspaceDir?: string;\n builtinDir?: string;\n globalDirs?: string[];\n extraDirs?: string[];\n debounceMs?: number;\n }\n): SkillWatcher | null {\n const watchDirs: string[] = [];\n\n // Add project-local workspace skills directory\n if (options.workspaceDir) {\n watchDirs.push(resolveWorkspaceSkillsDir(options.workspaceDir));\n }\n\n // Add builtin directory\n if (options.builtinDir) {\n watchDirs.push(options.builtinDir);\n }\n\n // Add global directories\n if (options.globalDirs) {\n watchDirs.push(...options.globalDirs);\n }\n\n // Add extra directories\n if (options.extraDirs) {\n watchDirs.push(...options.extraDirs);\n }\n\n if (watchDirs.length === 0) {\n log.warn('No directories to watch');\n return null;\n }\n\n return createSkillWatcher(loader, {\n watchDirs,\n debounceMs: options.debounceMs ?? 1000,\n });\n}\n"],"mappings":";;;;;;;;;;;aAQqD;AAIrD,MAAM,MAAM,aAAa,eAAe;;;;AAuBxC,SAAS,sBACP,QACA,YACY;CACZ,IAAI,UAAiC;CACrC,IAAI,gBAAgB;AAEpB,cAAa;AACX,MAAI,SAAS;AACX,mBAAgB;AAChB;;AAGF,YAAU,iBAAiB;AACzB,aAAU;AAEV,OAAI,eAAe;AACjB,oBAAgB;AAChB,WAAO,QAAQ;AACf,QAAI,KAAK,0CAA0C;;KAEpD,WAAW;;;;;;AAOlB,SAAgB,mBACd,QACA,SACc;CACd,MAAM,EAAE,WAAW,aAAa,QAAS;CAEzC,MAAM,WAAsE,EAAE;CAC9E,MAAM,kBAAkB,sBAAsB,QAAQ,WAAW;CACjE,IAAI,aAAa;CACjB,IAAI,kBAAkB,KAAK,KAAK;CAEhC,SAAS,eAAe,KAAmB;AACzC,MAAI;GACF,MAAM,UAAU,MAAM,KAAK,EAAE,WAAW,MAAM,GAAG,WAAW,aAAa;AACvE,QAAI,CAAC,SAAU;AAGf,QAAI,SAAS,aAAa,KAAK,YAAY;AACzC,SAAI,MAAM;MAAE;MAAW;MAAU;MAAK,EAAE,qBAAqB;AAC7D,uBAAkB,KAAK,KAAK;AAC5B,sBAAiB;;AAInB,QAAI,cAAc,UAAU;AAC1B,SAAI,MAAM;MAAE;MAAW;MAAU;MAAK,EAAE,sCAAsC;AAC9E,uBAAkB,KAAK,KAAK;AAC5B,sBAAiB;;KAEnB;AAEF,YAAS,KAAK;IAAE;IAAS;IAAK,CAAC;AAC/B,OAAI,KAAK,EAAE,KAAK,EAAE,2BAA2B;WACtC,KAAK;AACZ,OAAI,KAAK;IAAE;IAAK,OAAO;IAAK,EAAE,kCAAkC;;;AAIpE,QAAO;EACL,aAAa;AACX,OAAI,YAAY;AACd,QAAI,KAAK,0BAA0B;AACnC;;AAGF,QAAK,MAAM,OAAO,UAChB,gBAAe,IAAI;AAGrB,gBAAa;AACb,OAAI,KAAK,EAAE,MAAM,WAAW,EAAE,wBAAwB;;EAGxD,YAAY;AACV,OAAI,CAAC,WACH;AAGF,QAAK,MAAM,EAAE,aAAa,SACxB,SAAQ,OAAO;AAGjB,YAAS,SAAS;AAClB,gBAAa;AACb,OAAI,KAAK,wBAAwB;;EAGnC,kBAAkB;EAElB,0BAA0B;EAC3B;;;;;AAMH,SAAgB,wBACd,QACA,SAOqB;CACrB,MAAM,YAAsB,EAAE;AAG9B,KAAI,QAAQ,aACV,WAAU,KAAK,0BAA0B,QAAQ,aAAa,CAAC;AAIjE,KAAI,QAAQ,WACV,WAAU,KAAK,QAAQ,WAAW;AAIpC,KAAI,QAAQ,WACV,WAAU,KAAK,GAAG,QAAQ,WAAW;AAIvC,KAAI,QAAQ,UACV,WAAU,KAAK,GAAG,QAAQ,UAAU;AAGtC,KAAI,UAAU,WAAW,GAAG;AAC1B,MAAI,KAAK,0BAA0B;AACnC,SAAO;;AAGT,QAAO,mBAAmB,QAAQ;EAChC;EACA,YAAY,QAAQ,cAAc;EACnC,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function resolveWorkspaceSkillsDir(workspaceDir: string): string;
@@ -0,0 +1,11 @@
1
+ import { join } from "node:path";
2
+ //#region src/agent/skills/workspace-skills-dir.ts
3
+ const PROJECT_XOPC_DIR = ".xopc";
4
+ const PROJECT_SKILLS_DIR = "skills";
5
+ function resolveWorkspaceSkillsDir(workspaceDir) {
6
+ return join(workspaceDir, PROJECT_XOPC_DIR, PROJECT_SKILLS_DIR);
7
+ }
8
+ //#endregion
9
+ export { resolveWorkspaceSkillsDir };
10
+
11
+ //# sourceMappingURL=workspace-skills-dir.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace-skills-dir.js","names":[],"sources":["../../../../src/agent/skills/workspace-skills-dir.ts"],"sourcesContent":["import { join } from 'node:path';\n\nconst PROJECT_XOPC_DIR = '.xopc';\nconst PROJECT_SKILLS_DIR = 'skills';\n\nexport function resolveWorkspaceSkillsDir(workspaceDir: string): string {\n return join(workspaceDir, PROJECT_XOPC_DIR, PROJECT_SKILLS_DIR);\n}\n"],"mappings":";;AAEA,MAAM,mBAAmB;AACzB,MAAM,qBAAqB;AAE3B,SAAgB,0BAA0B,cAA8B;AACtE,QAAO,KAAK,cAAc,kBAAkB,mBAAmB"}
@@ -1 +1 @@
1
- export declare const browserUseManual = "# Browser Tool Manual\n\n## Overview\n\n`browser_use` is XOPC's unified browser tool. It supports four modes:\n\n| Mode | Purpose |\n|------|---------|\n| `command` | Run a single browser action |\n| `pipeline` | Run a multi-step YAML flow |\n| `inspect` | Read current page state |\n| `close` | Close the browser session |\n\n## When to use\n\n- Open pages, click controls, fill forms\n- Capture screenshots or page content\n- Run multi-step automation flows\n- Extract data from pages\n\n## Command mode\n\n### Basic shape\n\n```json\n{\n \"mode\": \"command\",\n \"command\": \"<action>\",\n \"args\": { ... }\n}\n```\n\n### Available commands\n\n| Command | Description | Key arguments |\n|---------|-------------|---------------|\n| `open` / `navigate` | Open a URL | `url`, `wait_until` |\n| `state` / `snapshot` | ARIA snapshot of the page | `selector`, `maxLength` |\n| `click` | Click an element | `selector` / `text` / `role` |\n| `type` / `input` | Type text | `selector` / `label`, `text`, `pressEnter` |\n| `scroll` | Scroll the page | `direction`, `amount` |\n| `screenshot` | Screenshot | `selector`, `full_page`, `path` |\n| `back` | Go back | `waitFor` |\n| `keys` / `press` | Keyboard input | `key` |\n| `console` / `eval` | Run JavaScript | `javascript` |\n| `images` | Collect images on the page | `selector`, `maxImages` |\n| `wait` | Wait for element/time | `selector` / `text` / `ms`, `timeout_ms` |\n| `dialog` | Handle dialogs | `action` (accept/dismiss) |\n| `close` | Close the current page | \u2014 |\n\n### Element targeting\n\nPrefer, in order:\n\n1. **ARIA role**: most stable, e.g. `\"role\": \"button:Submit\"`\n2. **Visible text**, e.g. `\"text\": \"Sign In\"`\n3. **CSS selector**, e.g. `\"selector\": \"#login-btn\"`\n\nGuidelines:\n\n- Use `inspect` or `state` first to get a snapshot\n- Pick locators from ARIA info in the snapshot\n- Avoid dynamic class names when possible\n\n## Inspect mode\n\nBefore acting, understand the current page:\n\n```json\n{ \"mode\": \"inspect\" }\n```\n\nReturns: current URL, title, ARIA snapshot.\n\n**Best practice**: after each navigation, inspect, then choose the next step.\n\n## Pipeline mode\n\nFor multi-step, reusable flows. Uses a brocli-style YAML DSL.\n\n### Run from file\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"path\": \"./browser-flow.yaml\",\n \"args\": { \"url\": \"https://example.com\" }\n }\n}\n```\n\n### Run inline YAML\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"name: quick-check\\npipeline:\\n - navigate:\\n url: https://example.com\\n - screenshot:\\n full_page: true\",\n \"dryRun\": false\n }\n}\n```\n\n### YAML layout\n\n```yaml\nname: pipeline-name\ndescription: What this flow does\nargs:\n url:\n type: string\n required: true\n query:\n type: string\n default: \"hello\"\npipeline:\n - navigate:\n url: ${{ args.url }}\n wait_until: domcontentloaded\n - wait:\n selector: input[name=\"q\"]\n - type:\n selector: input[name=\"q\"]\n text: ${{ args.query }}\n - press:\n key: Enter\n - wait:\n selector: body\n timeout_ms: 10000\n - screenshot:\n path: ./artifacts/result.png\n full_page: true\n - output:\n value:\n screenshot: ./artifacts/result.png\non_error:\n - screenshot:\n path: ./artifacts/error.png\n full_page: true\n```\n\n### Authoring rules\n\n1. One action per step\n2. Use `${{ args.xxx }}` for parameters\n3. Use `${{ data }}` or `${{ data | json }}` for the previous step's result\n4. Use `on_error` to collect diagnostics after failure\n\n### Validate without running\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"...\",\n \"dryRun\": true\n }\n}\n```\n\n## Recovery when something fails\n\n1. `inspect` to see current state\n2. Confirm the URL (redirects may have changed it)\n3. Use the snapshot to see if the page finished loading\n4. `screenshot` for visual debugging\n5. `wait` for elements, then retry\n\n## Safety\n\n- Do not put API keys or tokens in URLs\n- Do not target private IPs / localhost unless configuration allows it\n- Cloud metadata endpoints are always blocked\n- For destructive actions (submit forms, delete data), confirm intent with the user first\n";
1
+ export declare const browserUseManual = "# Browser Tool Manual\n\n## Overview\n\n`browser_use` is XOPC's unified browser tool. It supports four modes:\n\n| Mode | Purpose |\n|------|---------|\n| `command` | Run a single browser action |\n| `pipeline` | Run a multi-step YAML flow |\n| `inspect` | Read current page state |\n| `close` | Close the browser session |\n\n## When to use\n\n- Open pages, click controls, fill forms\n- Capture screenshots or page content\n- Run multi-step automation flows\n- Extract data from pages\n\n## Command mode\n\n### Basic shape\n\n```json\n{\n \"mode\": \"command\",\n \"command\": \"<action>\",\n \"args\": { ... }\n}\n```\n\n### Available commands\n\n| Command | Description | Key arguments |\n|---------|-------------|---------------|\n| `open` / `navigate` | Open a URL | `url`, `wait_until` |\n| `state` / `snapshot` | ARIA snapshot of the page | `selector`, `maxLength` |\n| `click` | Click an element | `selector` / `text` / `role` |\n| `type` / `input` | Type text | `selector` / `label`, `text`, `pressEnter` |\n| `scroll` | Scroll the page | `direction`, `amount` |\n| `screenshot` | Screenshot | `selector`, `full_page`, `path` |\n| `back` | Go back | `waitFor` |\n| `keys` / `press` | Keyboard input | `key` |\n| `console` / `eval` | Run JavaScript | `javascript` |\n| `images` | Collect images on the page | `selector`, `maxImages` |\n| `wait` | Wait for element/text/function/time | `selector` / `text` / `function` / `ms`, `state`, `timeout_ms` |\n| `wait_for_navigation` | Wait for page load state | `wait_until`, `timeout_ms` |\n| `wait_for_network_idle` | Wait until network is idle | `timeout_ms` |\n| `element_text` | Read element text | `selector` |\n| `element_attribute` | Read element attribute | `selector`, `attribute` |\n| `bounding_box` | Read element box | `selector` |\n| `network_start` / `network_events` / `network_stop` | Capture network events | `url_pattern`, `include_body` |\n| `dialog` | Handle dialogs | `action` (accept/dismiss) |\n| `close` | Close the current page | \u2014 |\n\n### Element targeting\n\nPrefer, in order:\n\n1. **ARIA role**: most stable, e.g. `\"role\": \"button:Submit\"`\n2. **Visible text**, e.g. `\"text\": \"Sign In\"`\n3. **CSS selector**, e.g. `\"selector\": \"#login-btn\"`\n\nGuidelines:\n\n- Use `inspect` or `state` first to get a snapshot\n- Pick locators from ARIA info in the snapshot\n- Avoid dynamic class names when possible\n\n## Inspect mode\n\nBefore acting, understand the current page:\n\n```json\n{ \"mode\": \"inspect\" }\n```\n\nReturns: current URL, title, ARIA snapshot.\n\n**Best practice**: after each navigation, inspect, then choose the next step.\n\n## Pipeline mode\n\nFor multi-step, reusable flows. Uses a brocli-style YAML DSL.\n\n### Run from file\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"path\": \"./browser-flow.yaml\",\n \"args\": { \"url\": \"https://example.com\" }\n }\n}\n```\n\n### Run inline YAML\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"name: quick-check\\npipeline:\\n - navigate:\\n url: https://example.com\\n - screenshot:\\n full_page: true\",\n \"dryRun\": false\n }\n}\n```\n\n### YAML layout\n\n```yaml\nname: pipeline-name\ndescription: What this flow does\ntimeoutSeconds: 60\ninclude:\n - ./shared-login.yaml\nargs:\n url:\n type: string\n required: true\n query:\n type: string\n default: \"hello\"\npipeline:\n - navigate:\n url: ${{ args.url }}\n wait_until: domcontentloaded\n - wait:\n selector: input[name=\"q\"]\n - type:\n selector: input[name=\"q\"]\n text: ${{ args.query }}\n - press:\n key: Enter\n - wait:\n selector: body\n timeout_ms: 10000\n - element_text:\n selector: h1\n - assert:\n contains: Results\n - screenshot:\n path: ./artifacts/result.png\n full_page: true\n - output:\n value:\n screenshot: ./artifacts/result.png\non_error:\n - screenshot:\n path: ./artifacts/error.png\n full_page: true\n```\n\n### Authoring rules\n\n1. One action per step\n2. Use `${{ args.xxx }}` for parameters\n3. Use `${{ last }}` or `${{ last | json }}` for the previous step result\n4. Use `${{ outputs.0 }}` for prior `output` values and `${{ vars.name }}` for values from `set_var`\n5. Use `include` for shared YAML fragments; relative includes resolve from the current pipeline file\n6. Use `on_error` to collect diagnostics after failure\n\n### Stable pipeline actions\n\n```yaml\npipeline:\n - network_start:\n url_pattern: /api/search\n include_body: true\n - click:\n text: Search\n - wait_for_network_idle:\n timeout_ms: 10000\n - collect: {}\n - filter:\n path: type\n equals: response\n - limit:\n count: 3\n - output:\n value: ${{ last }}\n```\n\nControl flow:\n\n```yaml\npipeline:\n - retry:\n times: 3\n delay_ms: 500\n pipeline:\n - wait:\n selector: button.submit\n timeout_ms: 3000\n - click:\n selector: button.submit\n - if:\n condition: ${{ last }}\n then:\n - output:\n value: clicked\n else:\n - output:\n value: missing\n```\n\n### Validate without running\n\n```json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"...\",\n \"dryRun\": true\n }\n}\n```\n\n## Recovery when something fails\n\n1. `inspect` to see current state\n2. Confirm the URL (redirects may have changed it)\n3. Use the snapshot to see if the page finished loading\n4. `screenshot` for visual debugging\n5. `wait` for elements, then retry\n\n## Safety\n\n- Do not put API keys or tokens in URLs\n- Do not target private IPs / localhost unless configuration allows it\n- Cloud metadata endpoints are always blocked\n- For destructive actions (submit forms, delete data), confirm intent with the user first\n";
@@ -45,7 +45,13 @@ const browserUseManual = `# Browser Tool Manual
45
45
  | \`keys\` / \`press\` | Keyboard input | \`key\` |
46
46
  | \`console\` / \`eval\` | Run JavaScript | \`javascript\` |
47
47
  | \`images\` | Collect images on the page | \`selector\`, \`maxImages\` |
48
- | \`wait\` | Wait for element/time | \`selector\` / \`text\` / \`ms\`, \`timeout_ms\` |
48
+ | \`wait\` | Wait for element/text/function/time | \`selector\` / \`text\` / \`function\` / \`ms\`, \`state\`, \`timeout_ms\` |
49
+ | \`wait_for_navigation\` | Wait for page load state | \`wait_until\`, \`timeout_ms\` |
50
+ | \`wait_for_network_idle\` | Wait until network is idle | \`timeout_ms\` |
51
+ | \`element_text\` | Read element text | \`selector\` |
52
+ | \`element_attribute\` | Read element attribute | \`selector\`, \`attribute\` |
53
+ | \`bounding_box\` | Read element box | \`selector\` |
54
+ | \`network_start\` / \`network_events\` / \`network_stop\` | Capture network events | \`url_pattern\`, \`include_body\` |
49
55
  | \`dialog\` | Handle dialogs | \`action\` (accept/dismiss) |
50
56
  | \`close\` | Close the current page | — |
51
57
 
@@ -108,6 +114,9 @@ For multi-step, reusable flows. Uses a brocli-style YAML DSL.
108
114
  \`\`\`yaml
109
115
  name: pipeline-name
110
116
  description: What this flow does
117
+ timeoutSeconds: 60
118
+ include:
119
+ - ./shared-login.yaml
111
120
  args:
112
121
  url:
113
122
  type: string
@@ -129,6 +138,10 @@ pipeline:
129
138
  - wait:
130
139
  selector: body
131
140
  timeout_ms: 10000
141
+ - element_text:
142
+ selector: h1
143
+ - assert:
144
+ contains: Results
132
145
  - screenshot:
133
146
  path: ./artifacts/result.png
134
147
  full_page: true
@@ -145,8 +158,54 @@ on_error:
145
158
 
146
159
  1. One action per step
147
160
  2. Use \`\${{ args.xxx }}\` for parameters
148
- 3. Use \`\${{ data }}\` or \`\${{ data | json }}\` for the previous step's result
149
- 4. Use \`on_error\` to collect diagnostics after failure
161
+ 3. Use \`\${{ last }}\` or \`\${{ last | json }}\` for the previous step result
162
+ 4. Use \`\${{ outputs.0 }}\` for prior \`output\` values and \`\${{ vars.name }}\` for values from \`set_var\`
163
+ 5. Use \`include\` for shared YAML fragments; relative includes resolve from the current pipeline file
164
+ 6. Use \`on_error\` to collect diagnostics after failure
165
+
166
+ ### Stable pipeline actions
167
+
168
+ \`\`\`yaml
169
+ pipeline:
170
+ - network_start:
171
+ url_pattern: /api/search
172
+ include_body: true
173
+ - click:
174
+ text: Search
175
+ - wait_for_network_idle:
176
+ timeout_ms: 10000
177
+ - collect: {}
178
+ - filter:
179
+ path: type
180
+ equals: response
181
+ - limit:
182
+ count: 3
183
+ - output:
184
+ value: \${{ last }}
185
+ \`\`\`
186
+
187
+ Control flow:
188
+
189
+ \`\`\`yaml
190
+ pipeline:
191
+ - retry:
192
+ times: 3
193
+ delay_ms: 500
194
+ pipeline:
195
+ - wait:
196
+ selector: button.submit
197
+ timeout_ms: 3000
198
+ - click:
199
+ selector: button.submit
200
+ - if:
201
+ condition: \${{ last }}
202
+ then:
203
+ - output:
204
+ value: clicked
205
+ else:
206
+ - output:
207
+ value: missing
208
+ \`\`\`
150
209
 
151
210
  ### Validate without running
152
211
 
@@ -1 +1 @@
1
- {"version":3,"file":"browser.js","names":[],"sources":["../../../../src/agent/tool-manuals/browser.ts"],"sourcesContent":["export const browserUseManual = `# Browser Tool Manual\n\n## Overview\n\n\\`browser_use\\` is XOPC's unified browser tool. It supports four modes:\n\n| Mode | Purpose |\n|------|---------|\n| \\`command\\` | Run a single browser action |\n| \\`pipeline\\` | Run a multi-step YAML flow |\n| \\`inspect\\` | Read current page state |\n| \\`close\\` | Close the browser session |\n\n## When to use\n\n- Open pages, click controls, fill forms\n- Capture screenshots or page content\n- Run multi-step automation flows\n- Extract data from pages\n\n## Command mode\n\n### Basic shape\n\n\\`\\`\\`json\n{\n \"mode\": \"command\",\n \"command\": \"<action>\",\n \"args\": { ... }\n}\n\\`\\`\\`\n\n### Available commands\n\n| Command | Description | Key arguments |\n|---------|-------------|---------------|\n| \\`open\\` / \\`navigate\\` | Open a URL | \\`url\\`, \\`wait_until\\` |\n| \\`state\\` / \\`snapshot\\` | ARIA snapshot of the page | \\`selector\\`, \\`maxLength\\` |\n| \\`click\\` | Click an element | \\`selector\\` / \\`text\\` / \\`role\\` |\n| \\`type\\` / \\`input\\` | Type text | \\`selector\\` / \\`label\\`, \\`text\\`, \\`pressEnter\\` |\n| \\`scroll\\` | Scroll the page | \\`direction\\`, \\`amount\\` |\n| \\`screenshot\\` | Screenshot | \\`selector\\`, \\`full_page\\`, \\`path\\` |\n| \\`back\\` | Go back | \\`waitFor\\` |\n| \\`keys\\` / \\`press\\` | Keyboard input | \\`key\\` |\n| \\`console\\` / \\`eval\\` | Run JavaScript | \\`javascript\\` |\n| \\`images\\` | Collect images on the page | \\`selector\\`, \\`maxImages\\` |\n| \\`wait\\` | Wait for element/time | \\`selector\\` / \\`text\\` / \\`ms\\`, \\`timeout_ms\\` |\n| \\`dialog\\` | Handle dialogs | \\`action\\` (accept/dismiss) |\n| \\`close\\` | Close the current page | — |\n\n### Element targeting\n\nPrefer, in order:\n\n1. **ARIA role**: most stable, e.g. \\`\"role\": \"button:Submit\"\\`\n2. **Visible text**, e.g. \\`\"text\": \"Sign In\"\\`\n3. **CSS selector**, e.g. \\`\"selector\": \"#login-btn\"\\`\n\nGuidelines:\n\n- Use \\`inspect\\` or \\`state\\` first to get a snapshot\n- Pick locators from ARIA info in the snapshot\n- Avoid dynamic class names when possible\n\n## Inspect mode\n\nBefore acting, understand the current page:\n\n\\`\\`\\`json\n{ \"mode\": \"inspect\" }\n\\`\\`\\`\n\nReturns: current URL, title, ARIA snapshot.\n\n**Best practice**: after each navigation, inspect, then choose the next step.\n\n## Pipeline mode\n\nFor multi-step, reusable flows. Uses a brocli-style YAML DSL.\n\n### Run from file\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"path\": \"./browser-flow.yaml\",\n \"args\": { \"url\": \"https://example.com\" }\n }\n}\n\\`\\`\\`\n\n### Run inline YAML\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"name: quick-check\\\\npipeline:\\\\n - navigate:\\\\n url: https://example.com\\\\n - screenshot:\\\\n full_page: true\",\n \"dryRun\": false\n }\n}\n\\`\\`\\`\n\n### YAML layout\n\n\\`\\`\\`yaml\nname: pipeline-name\ndescription: What this flow does\nargs:\n url:\n type: string\n required: true\n query:\n type: string\n default: \"hello\"\npipeline:\n - navigate:\n url: \\${{ args.url }}\n wait_until: domcontentloaded\n - wait:\n selector: input[name=\"q\"]\n - type:\n selector: input[name=\"q\"]\n text: \\${{ args.query }}\n - press:\n key: Enter\n - wait:\n selector: body\n timeout_ms: 10000\n - screenshot:\n path: ./artifacts/result.png\n full_page: true\n - output:\n value:\n screenshot: ./artifacts/result.png\non_error:\n - screenshot:\n path: ./artifacts/error.png\n full_page: true\n\\`\\`\\`\n\n### Authoring rules\n\n1. One action per step\n2. Use \\`\\${{ args.xxx }}\\` for parameters\n3. Use \\`\\${{ data }}\\` or \\`\\${{ data | json }}\\` for the previous step's result\n4. Use \\`on_error\\` to collect diagnostics after failure\n\n### Validate without running\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"...\",\n \"dryRun\": true\n }\n}\n\\`\\`\\`\n\n## Recovery when something fails\n\n1. \\`inspect\\` to see current state\n2. Confirm the URL (redirects may have changed it)\n3. Use the snapshot to see if the page finished loading\n4. \\`screenshot\\` for visual debugging\n5. \\`wait\\` for elements, then retry\n\n## Safety\n\n- Do not put API keys or tokens in URLs\n- Do not target private IPs / localhost unless configuration allows it\n- Cloud metadata endpoints are always blocked\n- For destructive actions (submit forms, delete data), confirm intent with the user first\n`;\n"],"mappings":";AAAA,MAAa,mBAAmB"}
1
+ {"version":3,"file":"browser.js","names":[],"sources":["../../../../src/agent/tool-manuals/browser.ts"],"sourcesContent":["export const browserUseManual = `# Browser Tool Manual\n\n## Overview\n\n\\`browser_use\\` is XOPC's unified browser tool. It supports four modes:\n\n| Mode | Purpose |\n|------|---------|\n| \\`command\\` | Run a single browser action |\n| \\`pipeline\\` | Run a multi-step YAML flow |\n| \\`inspect\\` | Read current page state |\n| \\`close\\` | Close the browser session |\n\n## When to use\n\n- Open pages, click controls, fill forms\n- Capture screenshots or page content\n- Run multi-step automation flows\n- Extract data from pages\n\n## Command mode\n\n### Basic shape\n\n\\`\\`\\`json\n{\n \"mode\": \"command\",\n \"command\": \"<action>\",\n \"args\": { ... }\n}\n\\`\\`\\`\n\n### Available commands\n\n| Command | Description | Key arguments |\n|---------|-------------|---------------|\n| \\`open\\` / \\`navigate\\` | Open a URL | \\`url\\`, \\`wait_until\\` |\n| \\`state\\` / \\`snapshot\\` | ARIA snapshot of the page | \\`selector\\`, \\`maxLength\\` |\n| \\`click\\` | Click an element | \\`selector\\` / \\`text\\` / \\`role\\` |\n| \\`type\\` / \\`input\\` | Type text | \\`selector\\` / \\`label\\`, \\`text\\`, \\`pressEnter\\` |\n| \\`scroll\\` | Scroll the page | \\`direction\\`, \\`amount\\` |\n| \\`screenshot\\` | Screenshot | \\`selector\\`, \\`full_page\\`, \\`path\\` |\n| \\`back\\` | Go back | \\`waitFor\\` |\n| \\`keys\\` / \\`press\\` | Keyboard input | \\`key\\` |\n| \\`console\\` / \\`eval\\` | Run JavaScript | \\`javascript\\` |\n| \\`images\\` | Collect images on the page | \\`selector\\`, \\`maxImages\\` |\n| \\`wait\\` | Wait for element/text/function/time | \\`selector\\` / \\`text\\` / \\`function\\` / \\`ms\\`, \\`state\\`, \\`timeout_ms\\` |\n| \\`wait_for_navigation\\` | Wait for page load state | \\`wait_until\\`, \\`timeout_ms\\` |\n| \\`wait_for_network_idle\\` | Wait until network is idle | \\`timeout_ms\\` |\n| \\`element_text\\` | Read element text | \\`selector\\` |\n| \\`element_attribute\\` | Read element attribute | \\`selector\\`, \\`attribute\\` |\n| \\`bounding_box\\` | Read element box | \\`selector\\` |\n| \\`network_start\\` / \\`network_events\\` / \\`network_stop\\` | Capture network events | \\`url_pattern\\`, \\`include_body\\` |\n| \\`dialog\\` | Handle dialogs | \\`action\\` (accept/dismiss) |\n| \\`close\\` | Close the current page | — |\n\n### Element targeting\n\nPrefer, in order:\n\n1. **ARIA role**: most stable, e.g. \\`\"role\": \"button:Submit\"\\`\n2. **Visible text**, e.g. \\`\"text\": \"Sign In\"\\`\n3. **CSS selector**, e.g. \\`\"selector\": \"#login-btn\"\\`\n\nGuidelines:\n\n- Use \\`inspect\\` or \\`state\\` first to get a snapshot\n- Pick locators from ARIA info in the snapshot\n- Avoid dynamic class names when possible\n\n## Inspect mode\n\nBefore acting, understand the current page:\n\n\\`\\`\\`json\n{ \"mode\": \"inspect\" }\n\\`\\`\\`\n\nReturns: current URL, title, ARIA snapshot.\n\n**Best practice**: after each navigation, inspect, then choose the next step.\n\n## Pipeline mode\n\nFor multi-step, reusable flows. Uses a brocli-style YAML DSL.\n\n### Run from file\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"path\": \"./browser-flow.yaml\",\n \"args\": { \"url\": \"https://example.com\" }\n }\n}\n\\`\\`\\`\n\n### Run inline YAML\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"name: quick-check\\\\npipeline:\\\\n - navigate:\\\\n url: https://example.com\\\\n - screenshot:\\\\n full_page: true\",\n \"dryRun\": false\n }\n}\n\\`\\`\\`\n\n### YAML layout\n\n\\`\\`\\`yaml\nname: pipeline-name\ndescription: What this flow does\ntimeoutSeconds: 60\ninclude:\n - ./shared-login.yaml\nargs:\n url:\n type: string\n required: true\n query:\n type: string\n default: \"hello\"\npipeline:\n - navigate:\n url: \\${{ args.url }}\n wait_until: domcontentloaded\n - wait:\n selector: input[name=\"q\"]\n - type:\n selector: input[name=\"q\"]\n text: \\${{ args.query }}\n - press:\n key: Enter\n - wait:\n selector: body\n timeout_ms: 10000\n - element_text:\n selector: h1\n - assert:\n contains: Results\n - screenshot:\n path: ./artifacts/result.png\n full_page: true\n - output:\n value:\n screenshot: ./artifacts/result.png\non_error:\n - screenshot:\n path: ./artifacts/error.png\n full_page: true\n\\`\\`\\`\n\n### Authoring rules\n\n1. One action per step\n2. Use \\`\\${{ args.xxx }}\\` for parameters\n3. Use \\`\\${{ last }}\\` or \\`\\${{ last | json }}\\` for the previous step result\n4. Use \\`\\${{ outputs.0 }}\\` for prior \\`output\\` values and \\`\\${{ vars.name }}\\` for values from \\`set_var\\`\n5. Use \\`include\\` for shared YAML fragments; relative includes resolve from the current pipeline file\n6. Use \\`on_error\\` to collect diagnostics after failure\n\n### Stable pipeline actions\n\n\\`\\`\\`yaml\npipeline:\n - network_start:\n url_pattern: /api/search\n include_body: true\n - click:\n text: Search\n - wait_for_network_idle:\n timeout_ms: 10000\n - collect: {}\n - filter:\n path: type\n equals: response\n - limit:\n count: 3\n - output:\n value: \\${{ last }}\n\\`\\`\\`\n\nControl flow:\n\n\\`\\`\\`yaml\npipeline:\n - retry:\n times: 3\n delay_ms: 500\n pipeline:\n - wait:\n selector: button.submit\n timeout_ms: 3000\n - click:\n selector: button.submit\n - if:\n condition: \\${{ last }}\n then:\n - output:\n value: clicked\n else:\n - output:\n value: missing\n\\`\\`\\`\n\n### Validate without running\n\n\\`\\`\\`json\n{\n \"mode\": \"pipeline\",\n \"pipeline\": {\n \"yaml\": \"...\",\n \"dryRun\": true\n }\n}\n\\`\\`\\`\n\n## Recovery when something fails\n\n1. \\`inspect\\` to see current state\n2. Confirm the URL (redirects may have changed it)\n3. Use the snapshot to see if the page finished loading\n4. \\`screenshot\\` for visual debugging\n5. \\`wait\\` for elements, then retry\n\n## Safety\n\n- Do not put API keys or tokens in URLs\n- Do not target private IPs / localhost unless configuration allows it\n- Cloud metadata endpoints are always blocked\n- For destructive actions (submit forms, delete data), confirm intent with the user first\n`;\n"],"mappings":";AAAA,MAAa,mBAAmB"}
@@ -25,6 +25,9 @@ export interface CreateBrowserUseToolDeps {
25
25
  */
26
26
  getReadiness?: () => Promise<BrowserNotReadyError | null>;
27
27
  /** Pipeline runner (injected to avoid circular deps; lazy-loaded if not provided). */
28
- runPipeline?: (yaml: string, args: Record<string, unknown>, ctx: BrowserActionContext, dryRun: boolean) => Promise<BrowserActionResult>;
28
+ runPipeline?: (yaml: string, args: Record<string, unknown>, ctx: BrowserActionContext, options: {
29
+ dryRun?: boolean;
30
+ sourceLocation?: string;
31
+ }) => Promise<BrowserActionResult>;
29
32
  }
30
33
  export declare function createBrowserUseTool(deps: CreateBrowserUseToolDeps): AgentTool<any, any>;
@@ -185,9 +185,12 @@ function createBrowserUseTool(deps) {
185
185
  mode: "pipeline"
186
186
  }
187
187
  };
188
- let yamlSource = pipelineParams.yaml ?? pipelineParams.script ?? "";
188
+ let yamlSource = pipelineParams.yaml ?? "";
189
+ let sourceLocation;
189
190
  if (!yamlSource && pipelineParams.path) try {
190
- yamlSource = (await loadBrowserPipelineSource(pipelineParams.path)).source;
191
+ const loaded = await loadBrowserPipelineSource(pipelineParams.path);
192
+ yamlSource = loaded.source;
193
+ sourceLocation = loaded.location;
191
194
  } catch (e) {
192
195
  const msg = e instanceof Error ? e.message : String(e);
193
196
  return {
@@ -215,10 +218,16 @@ function createBrowserUseTool(deps) {
215
218
  const pipelineArgs = pipelineParams.args ?? {};
216
219
  const dryRun = pipelineParams.dryRun === true;
217
220
  const ctx = buildContext(await deps.getPageForTask(), signal);
218
- if (deps.runPipeline) return formatResult(await deps.runPipeline(yamlSource, pipelineArgs, ctx, dryRun));
221
+ if (deps.runPipeline) return formatResult(await deps.runPipeline(yamlSource, pipelineArgs, ctx, {
222
+ dryRun,
223
+ sourceLocation
224
+ }));
219
225
  try {
220
226
  const { runBrowserPipeline } = await import("../../../../browser/pipeline/runner.js");
221
- return formatResult(await runBrowserPipeline(yamlSource, pipelineArgs, ctx, registry, dryRun));
227
+ return formatResult(await runBrowserPipeline(yamlSource, pipelineArgs, ctx, registry, {
228
+ dryRun,
229
+ sourceLocation
230
+ }));
222
231
  } catch (e) {
223
232
  const msg = e instanceof Error ? e.message : String(e);
224
233
  log.error({ err: e }, `Pipeline execution failed: ${msg}`);
@@ -1 +1 @@
1
- {"version":3,"file":"browser-use-tool.js","names":[],"sources":["../../../../../../src/agent/tools/browser/tool/browser-use-tool.ts"],"sourcesContent":["/**\n * browser_use — unified browser AgentTool.\n *\n * Modes: command | pipeline | inspect | close.\n * Replaces the 14 fine-grained browser_* tools with a single entry point.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport { createLogger } from '../../../../utils/logger.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { BrowserManager } from '../../../../browser/manager.js';\nimport type { CdpSupervisor } from '../../../../browser/cdp-supervisor.js';\nimport type { Page } from 'playwright-core';\n\nimport { BrowserUseSchema } from './schemas.js';\nimport { createBrowserActionRegistry } from '../../../../browser/actions/registry.js';\nimport type { BrowserActionContext, BrowserActionResult } from '../../../../browser/actions/types.js';\nimport { loadBrowserPipelineSource } from '../../../../browser/pipeline/source.js';\nimport type { BrowserNotReadyError, BrowserSetupHint } from '../../../../browser/readiness.js';\n\nconst log = createLogger('Agent:BrowserUse');\n\nexport interface CreateBrowserUseToolDeps {\n getManager: () => BrowserManager;\n getPageForTask: () => Promise<Page>;\n getTaskId: () => string;\n getConfig: () => Config | undefined;\n getSupervisor?: () => CdpSupervisor | undefined;\n notifyBrowserPageClosed?: (taskId: string) => void;\n /**\n * Preflight readiness check. Returns `null` when the configured backend is\n * usable, otherwise a structured hint the chat surface renders as a setup\n * card. Cache the result upstream (~30s) so back-to-back calls don't reprobe.\n */\n getReadiness?: () => Promise<BrowserNotReadyError | null>;\n /** Pipeline runner (injected to avoid circular deps; lazy-loaded if not provided). */\n runPipeline?: (yaml: string, args: Record<string, unknown>, ctx: BrowserActionContext, dryRun: boolean) => Promise<BrowserActionResult>;\n}\n\nexport function createBrowserUseTool(deps: CreateBrowserUseToolDeps): AgentTool<any, any> {\n const registry = createBrowserActionRegistry();\n\n function buildContext(page: Page, signal?: AbortSignal): BrowserActionContext {\n return {\n page,\n manager: deps.getManager(),\n config: deps.getConfig(),\n taskId: deps.getTaskId(),\n supervisor: deps.getSupervisor?.(),\n signal,\n };\n }\n\n /**\n * Render a {@link BrowserSetupHint} as a tool result. The text body is a\n * JSON envelope (`kind: 'browser_setup_required'`) so the chat surface can\n * detect it and render a Setup card; the embedded `message` keeps the\n * payload human-readable for the LLM so it stops the browser attempt and\n * tells the user to finish setup.\n */\n function formatNotReady(hint: BrowserSetupHint): { content: { type: 'text'; text: string }[]; details: Record<string, unknown> } {\n const message =\n `⚠ Browser is not ready (backend=${hint.backend}, reason=${hint.reason}). ` +\n `Do NOT retry. Tell the user to open Settings → Browser to finish setup, ` +\n `then ask them to confirm before running any browser action again.`;\n const payload = {\n kind: 'browser_setup_required' as const,\n backend: hint.backend,\n reason: hint.reason,\n deepLink: hint.deepLink,\n detail: hint.detail,\n message,\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(payload) }],\n details: {\n ok: false,\n kind: 'browser_setup_required',\n backend: hint.backend,\n reason: hint.reason,\n deepLink: hint.deepLink,\n },\n };\n }\n\n function formatResult(result: BrowserActionResult): { content: { type: 'text'; text: string }[]; details: Record<string, unknown> } {\n if (result.ok) {\n const parts: string[] = [];\n if (result.text) parts.push(result.text);\n if (result.data && !result.text) parts.push(JSON.stringify(result.data, null, 2));\n return {\n content: [{ type: 'text', text: parts.join('\\n') || 'OK' }],\n details: { ok: true, action: result.action, ...(result.artifacts?.length ? { artifacts: result.artifacts.length } : {}) },\n };\n }\n const parts: string[] = [];\n if (result.error) parts.push(`[${result.error.code}] ${result.error.message}`);\n if (result.diagnostics?.url) parts.push(`URL: ${result.diagnostics.url}`);\n if (result.diagnostics?.snapshot) parts.push(`Snapshot: ${result.diagnostics.snapshot.slice(0, 2000)}`);\n return {\n content: [{ type: 'text', text: parts.join('\\n') || 'Failed' }],\n details: { ok: false, action: result.action, error: result.error },\n };\n }\n\n const tool: any = {\n name: 'browser_use',\n label: '🌐 Browser',\n description:\n 'Use a persistent browser for web navigation, page inspection, interaction, screenshots, network capture, and scripted browser pipelines. For non-trivial browser tasks, load the built-in manual first with tool_manual({ tool: \"browser_use\" }).',\n parameters: BrowserUseSchema,\n\n async execute(_toolCallId, params: any, signal, _onUpdate) {\n const { mode, command, args: cmdArgs, pipeline: pipelineParams, options: _options } = params as {\n mode: string;\n command?: string;\n args?: Record<string, unknown>;\n pipeline?: { yaml?: string; script?: string; path?: string; args?: Record<string, unknown>; dryRun?: boolean };\n options?: { timeout?: number; headless?: boolean };\n };\n\n // ─── readiness preflight ────────────────────────────────────────────\n // Probes the configured backend (doctor + WS bridge / CDP / cloud key)\n // before any launch attempt. On failure we short-circuit with a setup\n // hint the chat renders as a card — the agent should stop and ask the\n // user to finish setup instead of looping on launch errors.\n if (deps.getReadiness) {\n try {\n const notReady = await deps.getReadiness();\n if (notReady) {\n return formatNotReady(notReady.hint);\n }\n } catch (e) {\n log.warn({ err: e }, 'Readiness preflight threw; continuing with launch attempt');\n }\n }\n\n // ─── inspect ────────────────────────────────────────────────────────\n if (mode === 'inspect') {\n const mgr = deps.getManager();\n await mgr.ensureConnected();\n const ext = mgr.getExtensionProvider();\n if (ext) {\n const timeout = deps.getConfig?.()?.agents?.defaults?.browser?.commandTimeout;\n const timeoutMs =\n typeof timeout === 'number' && Number.isFinite(timeout) && timeout > 0\n ? Math.floor(timeout * 1000)\n : 30_000;\n const urlRes = await ext.sendCommand('get_url', {}, { timeout: timeoutMs });\n const titleRes = await ext.sendCommand('get_title', {}, { timeout: timeoutMs });\n const snapRes = await ext.sendCommand('snapshot', {}, { timeout: timeoutMs });\n const url = urlRes.ok && urlRes.data ? String((urlRes.data as { url?: string }).url ?? '') : '';\n const title =\n titleRes.ok && titleRes.data ? String((titleRes.data as { title?: string }).title ?? '') : '';\n let snapText = '';\n if (snapRes.ok && snapRes.data) {\n const nodes = (snapRes.data as { nodes?: Array<{ role?: string; name?: string }> }).nodes ?? [];\n snapText = nodes.map((n) => `${n.role ?? '?'}: ${n.name ?? ''}`).join('\\n');\n if (snapText.length > 8000) snapText = `${snapText.slice(0, 8000)}\\n... (truncated)`;\n }\n const text = `URL: ${url}\\nTitle: ${title}\\n${snapText ? `--- Page Snapshot ---\\n${snapText}` : ''}`;\n return {\n content: [{ type: 'text', text }],\n details: { ok: true, mode: 'inspect', url, title },\n };\n }\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n const result = await registry.execute('state', ctx, {});\n // Augment with URL / title\n const url = page.url();\n const title = await page.title().catch(() => '');\n const text = `URL: ${url}\\nTitle: ${title}\\n${result.text ?? ''}`;\n return {\n content: [{ type: 'text', text }],\n details: { ok: true, mode: 'inspect', url, title },\n };\n }\n\n // ─── close ──────────────────────────────────────────────────────────\n if (mode === 'close') {\n const taskId = deps.getTaskId();\n await deps.getManager().ensureConnected();\n await deps.getManager().closePage(taskId);\n deps.notifyBrowserPageClosed?.(taskId);\n return {\n content: [{ type: 'text', text: 'Browser page closed.' }],\n details: { ok: true, mode: 'close' },\n };\n }\n\n // ─── command ────────────────────────────────────────────────────────\n if (mode === 'command') {\n if (!command) {\n return {\n content: [{ type: 'text', text: 'Missing `command` parameter for command mode.' }],\n details: { ok: false, mode: 'command' },\n };\n }\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n const args = cmdArgs ?? {};\n const result = await registry.execute(command, ctx, args);\n return formatResult(result);\n }\n\n // ─── pipeline ──────────────────────────────────────────────────────\n if (mode === 'pipeline') {\n if (!pipelineParams) {\n return {\n content: [{ type: 'text', text: 'Missing `pipeline` parameter for pipeline mode.' }],\n details: { ok: false, mode: 'pipeline' },\n };\n }\n\n // Resolve YAML source\n let yamlSource = pipelineParams.yaml ?? pipelineParams.script ?? '';\n\n if (!yamlSource && pipelineParams.path) {\n try {\n yamlSource = (await loadBrowserPipelineSource(pipelineParams.path)).source;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n content: [{ type: 'text', text: `Failed to read pipeline source: ${msg}` }],\n details: { ok: false, mode: 'pipeline', error: msg },\n };\n }\n }\n\n if (!yamlSource) {\n return {\n content: [{ type: 'text', text: 'Pipeline mode requires `yaml`, `script`, or `path`.' }],\n details: { ok: false, mode: 'pipeline' },\n };\n }\n\n const pipelineArgs = (pipelineParams.args as Record<string, unknown>) ?? {};\n const dryRun = pipelineParams.dryRun === true;\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n\n // Use injected runner or lazy-load\n if (deps.runPipeline) {\n const result = await deps.runPipeline(yamlSource, pipelineArgs, ctx, dryRun);\n return formatResult(result);\n }\n\n // Lazy import pipeline runner\n try {\n const { runBrowserPipeline } = await import('../../../../browser/pipeline/runner.js');\n const result = await runBrowserPipeline(yamlSource, pipelineArgs, ctx, registry, dryRun);\n return formatResult(result);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n log.error({ err: e }, `Pipeline execution failed: ${msg}`);\n return {\n content: [{ type: 'text', text: `Pipeline failed: ${msg}` }],\n details: { ok: false, mode: 'pipeline', error: msg },\n };\n }\n }\n\n return {\n content: [{ type: 'text', text: `Unknown mode: ${mode}` }],\n details: { ok: false },\n };\n },\n };\n return tool;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"browser-use-tool.js","names":[],"sources":["../../../../../../src/agent/tools/browser/tool/browser-use-tool.ts"],"sourcesContent":["/**\n * browser_use — unified browser AgentTool.\n *\n * Modes: command | pipeline | inspect | close.\n * Replaces the 14 fine-grained browser_* tools with a single entry point.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport { createLogger } from '../../../../utils/logger.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { BrowserManager } from '../../../../browser/manager.js';\nimport type { CdpSupervisor } from '../../../../browser/cdp-supervisor.js';\nimport type { Page } from 'playwright-core';\n\nimport { BrowserUseSchema } from './schemas.js';\nimport { createBrowserActionRegistry } from '../../../../browser/actions/registry.js';\nimport type { BrowserActionContext, BrowserActionResult } from '../../../../browser/actions/types.js';\nimport { loadBrowserPipelineSource } from '../../../../browser/pipeline/source.js';\nimport type { BrowserNotReadyError, BrowserSetupHint } from '../../../../browser/readiness.js';\n\nconst log = createLogger('Agent:BrowserUse');\n\nexport interface CreateBrowserUseToolDeps {\n getManager: () => BrowserManager;\n getPageForTask: () => Promise<Page>;\n getTaskId: () => string;\n getConfig: () => Config | undefined;\n getSupervisor?: () => CdpSupervisor | undefined;\n notifyBrowserPageClosed?: (taskId: string) => void;\n /**\n * Preflight readiness check. Returns `null` when the configured backend is\n * usable, otherwise a structured hint the chat surface renders as a setup\n * card. Cache the result upstream (~30s) so back-to-back calls don't reprobe.\n */\n getReadiness?: () => Promise<BrowserNotReadyError | null>;\n /** Pipeline runner (injected to avoid circular deps; lazy-loaded if not provided). */\n runPipeline?: (\n yaml: string,\n args: Record<string, unknown>,\n ctx: BrowserActionContext,\n options: { dryRun?: boolean; sourceLocation?: string },\n ) => Promise<BrowserActionResult>;\n}\n\nexport function createBrowserUseTool(deps: CreateBrowserUseToolDeps): AgentTool<any, any> {\n const registry = createBrowserActionRegistry();\n\n function buildContext(page: Page, signal?: AbortSignal): BrowserActionContext {\n return {\n page,\n manager: deps.getManager(),\n config: deps.getConfig(),\n taskId: deps.getTaskId(),\n supervisor: deps.getSupervisor?.(),\n signal,\n };\n }\n\n /**\n * Render a {@link BrowserSetupHint} as a tool result. The text body is a\n * JSON envelope (`kind: 'browser_setup_required'`) so the chat surface can\n * detect it and render a Setup card; the embedded `message` keeps the\n * payload human-readable for the LLM so it stops the browser attempt and\n * tells the user to finish setup.\n */\n function formatNotReady(hint: BrowserSetupHint): { content: { type: 'text'; text: string }[]; details: Record<string, unknown> } {\n const message =\n `⚠ Browser is not ready (backend=${hint.backend}, reason=${hint.reason}). ` +\n `Do NOT retry. Tell the user to open Settings → Browser to finish setup, ` +\n `then ask them to confirm before running any browser action again.`;\n const payload = {\n kind: 'browser_setup_required' as const,\n backend: hint.backend,\n reason: hint.reason,\n deepLink: hint.deepLink,\n detail: hint.detail,\n message,\n };\n return {\n content: [{ type: 'text', text: JSON.stringify(payload) }],\n details: {\n ok: false,\n kind: 'browser_setup_required',\n backend: hint.backend,\n reason: hint.reason,\n deepLink: hint.deepLink,\n },\n };\n }\n\n function formatResult(result: BrowserActionResult): { content: { type: 'text'; text: string }[]; details: Record<string, unknown> } {\n if (result.ok) {\n const parts: string[] = [];\n if (result.text) parts.push(result.text);\n if (result.data && !result.text) parts.push(JSON.stringify(result.data, null, 2));\n return {\n content: [{ type: 'text', text: parts.join('\\n') || 'OK' }],\n details: { ok: true, action: result.action, ...(result.artifacts?.length ? { artifacts: result.artifacts.length } : {}) },\n };\n }\n const parts: string[] = [];\n if (result.error) parts.push(`[${result.error.code}] ${result.error.message}`);\n if (result.diagnostics?.url) parts.push(`URL: ${result.diagnostics.url}`);\n if (result.diagnostics?.snapshot) parts.push(`Snapshot: ${result.diagnostics.snapshot.slice(0, 2000)}`);\n return {\n content: [{ type: 'text', text: parts.join('\\n') || 'Failed' }],\n details: { ok: false, action: result.action, error: result.error },\n };\n }\n\n const tool: any = {\n name: 'browser_use',\n label: '🌐 Browser',\n description:\n 'Use a persistent browser for web navigation, page inspection, interaction, screenshots, network capture, and scripted browser pipelines. For non-trivial browser tasks, load the built-in manual first with tool_manual({ tool: \"browser_use\" }).',\n parameters: BrowserUseSchema,\n\n async execute(_toolCallId, params: any, signal, _onUpdate) {\n const { mode, command, args: cmdArgs, pipeline: pipelineParams, options: _options } = params as {\n mode: string;\n command?: string;\n args?: Record<string, unknown>;\n pipeline?: { yaml?: string; path?: string; args?: Record<string, unknown>; dryRun?: boolean };\n options?: { timeout?: number; headless?: boolean };\n };\n\n // ─── readiness preflight ────────────────────────────────────────────\n // Probes the configured backend (doctor + WS bridge / CDP / cloud key)\n // before any launch attempt. On failure we short-circuit with a setup\n // hint the chat renders as a card — the agent should stop and ask the\n // user to finish setup instead of looping on launch errors.\n if (deps.getReadiness) {\n try {\n const notReady = await deps.getReadiness();\n if (notReady) {\n return formatNotReady(notReady.hint);\n }\n } catch (e) {\n log.warn({ err: e }, 'Readiness preflight threw; continuing with launch attempt');\n }\n }\n\n // ─── inspect ────────────────────────────────────────────────────────\n if (mode === 'inspect') {\n const mgr = deps.getManager();\n await mgr.ensureConnected();\n const ext = mgr.getExtensionProvider();\n if (ext) {\n const timeout = deps.getConfig?.()?.agents?.defaults?.browser?.commandTimeout;\n const timeoutMs =\n typeof timeout === 'number' && Number.isFinite(timeout) && timeout > 0\n ? Math.floor(timeout * 1000)\n : 30_000;\n const urlRes = await ext.sendCommand('get_url', {}, { timeout: timeoutMs });\n const titleRes = await ext.sendCommand('get_title', {}, { timeout: timeoutMs });\n const snapRes = await ext.sendCommand('snapshot', {}, { timeout: timeoutMs });\n const url = urlRes.ok && urlRes.data ? String((urlRes.data as { url?: string }).url ?? '') : '';\n const title =\n titleRes.ok && titleRes.data ? String((titleRes.data as { title?: string }).title ?? '') : '';\n let snapText = '';\n if (snapRes.ok && snapRes.data) {\n const nodes = (snapRes.data as { nodes?: Array<{ role?: string; name?: string }> }).nodes ?? [];\n snapText = nodes.map((n) => `${n.role ?? '?'}: ${n.name ?? ''}`).join('\\n');\n if (snapText.length > 8000) snapText = `${snapText.slice(0, 8000)}\\n... (truncated)`;\n }\n const text = `URL: ${url}\\nTitle: ${title}\\n${snapText ? `--- Page Snapshot ---\\n${snapText}` : ''}`;\n return {\n content: [{ type: 'text', text }],\n details: { ok: true, mode: 'inspect', url, title },\n };\n }\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n const result = await registry.execute('state', ctx, {});\n // Augment with URL / title\n const url = page.url();\n const title = await page.title().catch(() => '');\n const text = `URL: ${url}\\nTitle: ${title}\\n${result.text ?? ''}`;\n return {\n content: [{ type: 'text', text }],\n details: { ok: true, mode: 'inspect', url, title },\n };\n }\n\n // ─── close ──────────────────────────────────────────────────────────\n if (mode === 'close') {\n const taskId = deps.getTaskId();\n await deps.getManager().ensureConnected();\n await deps.getManager().closePage(taskId);\n deps.notifyBrowserPageClosed?.(taskId);\n return {\n content: [{ type: 'text', text: 'Browser page closed.' }],\n details: { ok: true, mode: 'close' },\n };\n }\n\n // ─── command ────────────────────────────────────────────────────────\n if (mode === 'command') {\n if (!command) {\n return {\n content: [{ type: 'text', text: 'Missing `command` parameter for command mode.' }],\n details: { ok: false, mode: 'command' },\n };\n }\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n const args = cmdArgs ?? {};\n const result = await registry.execute(command, ctx, args);\n return formatResult(result);\n }\n\n // ─── pipeline ──────────────────────────────────────────────────────\n if (mode === 'pipeline') {\n if (!pipelineParams) {\n return {\n content: [{ type: 'text', text: 'Missing `pipeline` parameter for pipeline mode.' }],\n details: { ok: false, mode: 'pipeline' },\n };\n }\n\n let yamlSource = pipelineParams.yaml ?? '';\n let sourceLocation: string | undefined;\n\n if (!yamlSource && pipelineParams.path) {\n try {\n const loaded = await loadBrowserPipelineSource(pipelineParams.path);\n yamlSource = loaded.source;\n sourceLocation = loaded.location;\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n content: [{ type: 'text', text: `Failed to read pipeline source: ${msg}` }],\n details: { ok: false, mode: 'pipeline', error: msg },\n };\n }\n }\n\n if (!yamlSource) {\n return {\n content: [{ type: 'text', text: 'Pipeline mode requires `yaml`, `script`, or `path`.' }],\n details: { ok: false, mode: 'pipeline' },\n };\n }\n\n const pipelineArgs = (pipelineParams.args as Record<string, unknown>) ?? {};\n const dryRun = pipelineParams.dryRun === true;\n const page = await deps.getPageForTask();\n const ctx = buildContext(page, signal);\n\n // Use injected runner or lazy-load\n if (deps.runPipeline) {\n const result = await deps.runPipeline(yamlSource, pipelineArgs, ctx, { dryRun, sourceLocation });\n return formatResult(result);\n }\n\n // Lazy import pipeline runner\n try {\n const { runBrowserPipeline } = await import('../../../../browser/pipeline/runner.js');\n const result = await runBrowserPipeline(yamlSource, pipelineArgs, ctx, registry, { dryRun, sourceLocation });\n return formatResult(result);\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n log.error({ err: e }, `Pipeline execution failed: ${msg}`);\n return {\n content: [{ type: 'text', text: `Pipeline failed: ${msg}` }],\n details: { ok: false, mode: 'pipeline', error: msg },\n };\n }\n }\n\n return {\n content: [{ type: 'text', text: `Unknown mode: ${mode}` }],\n details: { ok: false },\n };\n },\n };\n return tool;\n}\n"],"mappings":"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"}
@@ -3,7 +3,6 @@
3
3
  */
4
4
  export declare const BrowserUsePipelineSchema: import("@sinclair/typebox/build/cjs").TObject<{
5
5
  yaml: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
6
- script: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
7
6
  path: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
8
7
  args: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TRecord<import("@sinclair/typebox/build/cjs").TString, import("@sinclair/typebox/build/cjs").TUnknown>>;
9
8
  dryRun: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TBoolean>;
@@ -18,7 +17,6 @@ export declare const BrowserUseSchema: import("@sinclair/typebox/build/cjs").TOb
18
17
  args: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TRecord<import("@sinclair/typebox/build/cjs").TString, import("@sinclair/typebox/build/cjs").TUnknown>>;
19
18
  pipeline: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TObject<{
20
19
  yaml: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
21
- script: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
22
20
  path: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TString>;
23
21
  args: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TRecord<import("@sinclair/typebox/build/cjs").TString, import("@sinclair/typebox/build/cjs").TUnknown>>;
24
22
  dryRun: import("@sinclair/typebox/build/cjs").TOptional<import("@sinclair/typebox/build/cjs").TBoolean>;
@@ -4,8 +4,7 @@ import { Type } from "@sinclair/typebox";
4
4
  * BrowserUseSchema — Typebox schema for the unified `browser_use` AgentTool.
5
5
  */
6
6
  const BrowserUsePipelineSchema = Type.Object({
7
- yaml: Type.Optional(Type.String({ description: "Inline YAML pipeline (brocli-style DSL)." })),
8
- script: Type.Optional(Type.String({ description: "Alias for `yaml` — inline brocli YAML script." })),
7
+ yaml: Type.Optional(Type.String({ description: "Inline YAML browser pipeline." })),
9
8
  path: Type.Optional(Type.String({ description: "Path or http(s) URL to a .yaml pipeline file." })),
10
9
  args: Type.Optional(Type.Record(Type.String(), Type.Unknown(), { description: "Override pipeline arg defaults." })),
11
10
  dryRun: Type.Optional(Type.Boolean({ description: "Only parse & validate, do not execute." }))
@@ -1 +1 @@
1
- {"version":3,"file":"schemas.js","names":[],"sources":["../../../../../../src/agent/tools/browser/tool/schemas.ts"],"sourcesContent":["/**\n * BrowserUseSchema — Typebox schema for the unified `browser_use` AgentTool.\n */\n\nimport { Type } from '@sinclair/typebox';\n\nexport const BrowserUsePipelineSchema = Type.Object({\n yaml: Type.Optional(Type.String({ description: 'Inline YAML pipeline (brocli-style DSL).' })),\n script: Type.Optional(Type.String({ description: 'Alias for `yaml` — inline brocli YAML script.' })),\n path: Type.Optional(Type.String({ description: 'Path or http(s) URL to a .yaml pipeline file.' })),\n args: Type.Optional(\n Type.Record(Type.String(), Type.Unknown(), { description: 'Override pipeline arg defaults.' }),\n ),\n dryRun: Type.Optional(Type.Boolean({ description: 'Only parse & validate, do not execute.' })),\n});\n\nexport const BrowserUseOptionsSchema = Type.Object({\n timeout: Type.Optional(Type.Number({ description: 'Action timeout override (ms).' })),\n headless: Type.Optional(Type.Boolean({ description: 'Override headless mode for this call.' })),\n});\n\nexport const BrowserUseSchema = Type.Object({\n mode: Type.Union(\n [\n Type.Literal('command'),\n Type.Literal('pipeline'),\n Type.Literal('inspect'),\n Type.Literal('close'),\n ],\n { description: 'Execution mode.' },\n ),\n command: Type.Optional(\n Type.String({ description: 'Browser action name (command mode). E.g. open, click, type, screenshot.' }),\n ),\n args: Type.Optional(\n Type.Record(Type.String(), Type.Unknown(), { description: 'Action arguments (command mode).' }),\n ),\n pipeline: Type.Optional(BrowserUsePipelineSchema),\n options: Type.Optional(BrowserUseOptionsSchema),\n});\n"],"mappings":";;;;;AAMA,MAAa,2BAA2B,KAAK,OAAO;CAClD,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,4CAA4C,CAAC,CAAC;CAC7F,QAAQ,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iDAAiD,CAAC,CAAC;CACpG,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iDAAiD,CAAC,CAAC;CAClG,MAAM,KAAK,SACT,KAAK,OAAO,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,EAAE,aAAa,mCAAmC,CAAC,CAC/F;CACD,QAAQ,KAAK,SAAS,KAAK,QAAQ,EAAE,aAAa,0CAA0C,CAAC,CAAC;CAC/F,CAAC;AAEF,MAAa,0BAA0B,KAAK,OAAO;CACjD,SAAS,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iCAAiC,CAAC,CAAC;CACrF,UAAU,KAAK,SAAS,KAAK,QAAQ,EAAE,aAAa,yCAAyC,CAAC,CAAC;CAChG,CAAC;AAEF,MAAa,mBAAmB,KAAK,OAAO;CAC1C,MAAM,KAAK,MACT;EACE,KAAK,QAAQ,UAAU;EACvB,KAAK,QAAQ,WAAW;EACxB,KAAK,QAAQ,UAAU;EACvB,KAAK,QAAQ,QAAQ;EACtB,EACD,EAAE,aAAa,mBAAmB,CACnC;CACD,SAAS,KAAK,SACZ,KAAK,OAAO,EAAE,aAAa,2EAA2E,CAAC,CACxG;CACD,MAAM,KAAK,SACT,KAAK,OAAO,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,EAAE,aAAa,oCAAoC,CAAC,CAChG;CACD,UAAU,KAAK,SAAS,yBAAyB;CACjD,SAAS,KAAK,SAAS,wBAAwB;CAChD,CAAC"}
1
+ {"version":3,"file":"schemas.js","names":[],"sources":["../../../../../../src/agent/tools/browser/tool/schemas.ts"],"sourcesContent":["/**\n * BrowserUseSchema — Typebox schema for the unified `browser_use` AgentTool.\n */\n\nimport { Type } from '@sinclair/typebox';\n\nexport const BrowserUsePipelineSchema = Type.Object({\n yaml: Type.Optional(Type.String({ description: 'Inline YAML browser pipeline.' })),\n path: Type.Optional(Type.String({ description: 'Path or http(s) URL to a .yaml pipeline file.' })),\n args: Type.Optional(\n Type.Record(Type.String(), Type.Unknown(), { description: 'Override pipeline arg defaults.' }),\n ),\n dryRun: Type.Optional(Type.Boolean({ description: 'Only parse & validate, do not execute.' })),\n});\n\nexport const BrowserUseOptionsSchema = Type.Object({\n timeout: Type.Optional(Type.Number({ description: 'Action timeout override (ms).' })),\n headless: Type.Optional(Type.Boolean({ description: 'Override headless mode for this call.' })),\n});\n\nexport const BrowserUseSchema = Type.Object({\n mode: Type.Union(\n [\n Type.Literal('command'),\n Type.Literal('pipeline'),\n Type.Literal('inspect'),\n Type.Literal('close'),\n ],\n { description: 'Execution mode.' },\n ),\n command: Type.Optional(\n Type.String({ description: 'Browser action name (command mode). E.g. open, click, type, screenshot.' }),\n ),\n args: Type.Optional(\n Type.Record(Type.String(), Type.Unknown(), { description: 'Action arguments (command mode).' }),\n ),\n pipeline: Type.Optional(BrowserUsePipelineSchema),\n options: Type.Optional(BrowserUseOptionsSchema),\n});\n"],"mappings":";;;;;AAMA,MAAa,2BAA2B,KAAK,OAAO;CAClD,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iCAAiC,CAAC,CAAC;CAClF,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iDAAiD,CAAC,CAAC;CAClG,MAAM,KAAK,SACT,KAAK,OAAO,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,EAAE,aAAa,mCAAmC,CAAC,CAC/F;CACD,QAAQ,KAAK,SAAS,KAAK,QAAQ,EAAE,aAAa,0CAA0C,CAAC,CAAC;CAC/F,CAAC;AAEF,MAAa,0BAA0B,KAAK,OAAO;CACjD,SAAS,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,iCAAiC,CAAC,CAAC;CACrF,UAAU,KAAK,SAAS,KAAK,QAAQ,EAAE,aAAa,yCAAyC,CAAC,CAAC;CAChG,CAAC;AAEF,MAAa,mBAAmB,KAAK,OAAO;CAC1C,MAAM,KAAK,MACT;EACE,KAAK,QAAQ,UAAU;EACvB,KAAK,QAAQ,WAAW;EACxB,KAAK,QAAQ,UAAU;EACvB,KAAK,QAAQ,QAAQ;EACtB,EACD,EAAE,aAAa,mBAAmB,CACnC;CACD,SAAS,KAAK,SACZ,KAAK,OAAO,EAAE,aAAa,2EAA2E,CAAC,CACxG;CACD,MAAM,KAAK,SACT,KAAK,OAAO,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,EAAE,aAAa,oCAAoC,CAAC,CAChG;CACD,UAAU,KAAK,SAAS,yBAAyB;CACjD,SAAS,KAAK,SAAS,wBAAwB;CAChD,CAAC"}
@@ -1,6 +1,5 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
4
3
  import { createReadFileTool } from "./read.js";
5
4
  import { createWriteFileTool } from "./write.js";
6
5
  import { createEditFileTool } from "./edit.js";
@@ -45,7 +44,6 @@ import { mergeTtsConfigFromAppConfig } from "../../voice/tts/merge-config.js";
45
44
  import { createTextToSpeechTool } from "./tts-tool.js";
46
45
  import { createGoalEvidenceRecorder } from "./goal-evidence-recorder.js";
47
46
  //#region src/agent/tools/factory.ts
48
- init_session_key();
49
47
  init_logger();
50
48
  const log = createLogger("AgentToolsFactory");
51
49
  /** Channels where `clarify` can block for a user answer (web UI, Telegram, CLI readline). */
@@ -54,12 +52,6 @@ const CLARIFY_SUPPORTED_CHANNELS = new Set([
54
52
  "telegram",
55
53
  "cli"
56
54
  ]);
57
- function clarifyTransportSource(sessionKey) {
58
- const parsed = parseSessionKey(sessionKey);
59
- if (parsed) return parsed.source;
60
- const first = sessionKey.split(":").filter(Boolean)[0] ?? "";
61
- if (first === "cli" || first === "webchat") return first;
62
- }
63
55
  var AgentToolsFactory = class AgentToolsFactory {
64
56
  browserManager = null;
65
57
  /** One dialog/console supervisor per chat session (browser tab). */
@@ -195,8 +187,7 @@ var AgentToolsFactory = class AgentToolsFactory {
195
187
  if (!req) return null;
196
188
  const ctx = this.deps.getCurrentContext();
197
189
  if (!ctx?.sessionKey) return null;
198
- const source = clarifyTransportSource(ctx.sessionKey);
199
- if (!source || !CLARIFY_SUPPORTED_CHANNELS.has(source)) return null;
190
+ if (!CLARIFY_SUPPORTED_CHANNELS.has(ctx.channel)) return null;
200
191
  return (r) => req(ctx.sessionKey, r);
201
192
  } }),
202
193
  createTodoTool({ getSessionKey: () => this.deps.getCurrentContext()?.sessionKey }),
@@ -1 +1 @@
1
- {"version":3,"file":"factory.js","names":["parseRoutingSessionKey"],"sources":["../../../../src/agent/tools/factory.ts"],"sourcesContent":["/**\n * Agent Tools Factory - Creates and configures agent tools\n *\n * Centralizes tool creation logic to keep service.ts focused on orchestration.\n *\n * TTS: auto TTS is applied at the ChannelManager via maybeApplyTtsToPayload().\n * Optional \\`text_to_speech\\` tool sends explicit voice when TTS is enabled.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { Model, Api } from '@earendil-works/pi-ai';\nimport type { Page } from 'playwright-core';\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport {\n createReadFileTool,\n createWriteFileTool,\n createEditFileTool,\n createListDirTool,\n createGrepTool,\n createFindTool,\n createShellTool,\n createWebSearchTool,\n createWebFetchTool,\n createWebExtractTool,\n createMessageTool,\n createSendMediaTool,\n createReadMediaTool,\n createCreateShareTool,\n isShareToolAvailable,\n createMemorySearchTool,\n createMemoryGetTool,\n createTodoTool,\n createSessionStatusTool,\n createDreamingTool,\n createClarifyTool,\n createToolManualTool,\n createGoalTool,\n} from './index.js';\nimport { createCuratedMemoryTool } from './curated-memory-tool.js';\nimport { createSessionSearchTool } from './session-search-tool.js';\nimport type { BuiltinMemoryStore } from '../memory/builtin-memory-store.js';\nimport type { MemoryManager } from '../memory/manager.js';\nimport { shouldRegisterCuratedMemoryTool } from '../memory/memory-config.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { parseSessionKey as parseRoutingSessionKey } from '../../routing/session-key.js';\nimport type { GatewayClarifyRequestFn } from './clarify-tool.js';\nimport { createImageTool } from './image-tool.js';\nimport { createImageGenerateTool } from './image-generate-tool.js';\nimport {\n BrowserManager,\n BrowserNotReadyError,\n CdpSupervisor,\n checkBrowserReadiness,\n resolveBrowserBackendFromConfig,\n} from '../../browser/index.js';\nimport { createBrowserUseTool } from './browser/tool/browser-use-tool.js';\nimport { createDelegateTool } from './delegate-tool.js';\nimport { createWorkflowTool } from './workflow-tool.js';\nimport { createWorkflowCatalog } from '../workflow/catalog.js';\nimport { buildSandboxToolMap, createExecuteCodeTool } from './execute-code-tool.js';\nimport { createCronjobTool } from './cronjob-tool.js';\nimport type { CronService } from '../../cron/index.js';\nimport type { WorkflowRunServiceLike } from '../../workflows/service/workflow-run-service.types.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillManager } from '../skills/skill-manager.js';\nimport { wrapToolsWithProtection, type ToolExecutorConfig } from './executor.js';\nimport { createSkillsListTool, createSkillViewTool } from './skills-tools.js';\nimport { createSkillManageTool } from './skill-manage-tool.js';\nimport { createTextToSpeechTool } from './tts-tool.js';\nimport { mergeTtsConfigFromAppConfig } from '../../voice/tts/merge-config.js';\nimport { createGoalEvidenceRecorder } from './goal-evidence-recorder.js';\n\nconst log = createLogger('AgentToolsFactory');\n\n/** Channels where `clarify` can block for a user answer (web UI, Telegram, CLI readline). */\nconst CLARIFY_SUPPORTED_CHANNELS = new Set(['webchat', 'telegram', 'cli']);\n\nfunction clarifyTransportSource(sessionKey: string): string | undefined {\n const parsed = parseRoutingSessionKey(sessionKey);\n if (parsed) return parsed.source;\n // Fallback for simple `<channel>:<chatId>` keys used by webchat and CLI.\n const first = sessionKey.split(':').filter(Boolean)[0] ?? '';\n if (first === 'cli' || first === 'webchat') return first;\n return undefined;\n}\n\nexport interface ToolFactoryDeps {\n workspace: string;\n extensionRegistry?: any;\n getCurrentContext: () => { channel: string; chatId: string; sessionKey: string } | null;\n hookRunner?: import('../../extensions/index.js').ExtensionHookRunner;\n bus: MessageBus;\n toolExecutorConfig?: Partial<ToolExecutorConfig>;\n /** Agent defaults (image tools, etc.); use getter so hot-reloaded config applies. */\n getConfig?: () => Config | undefined;\n /** Session / default chat model for vision tool description. */\n getPrimaryModel?: () => Model<Api>;\n /** Built-in curated memory store (agent home `memories/`). */\n getBuiltinMemoryStore?: () => BuiltinMemoryStore;\n /** Memory orchestration (prefetch/sync + external tools). */\n getMemoryManager?: () => MemoryManager;\n /** Session store for `session_search`. */\n getSessionStore?: () => SessionStore;\n /** When set (gateway webchat), enables the `clarify` tool. */\n gatewayClarify?: { requestClarification: GatewayClarifyRequestFn };\n /** Gateway: enables the `cronjob` tool. */\n getCronService?: () => CronService | undefined;\n /** Gateway: starts persisted workflow runs (dedicated chat session per run). */\n getWorkflowRunService?: () => WorkflowRunServiceLike | undefined;\n /** Current session skill indexing (tool gating + allowlist); used by skills_list / skill_view. */\n getSkillIndexingContext?: () =>\n | { registeredToolNames: string[]; skillAllowlist?: string[] }\n | undefined;\n /** After skill_manage mutates disk, reload skills + refresh agent prompts (optional). */\n onSkillsFilesystemMutate?: () => void;\n /** Names registered via skill_view for shell env passthrough. */\n getSkillPassthroughEnvVarNames?: () => string[];\n /** Add declared env names for the current session (no values stored). */\n registerSkillEnvPassthrough?: (names: string[]) => void;\n}\n\nexport interface CreateCoreToolsOptions {\n /** Workspace root for file/shell tools (defaults to factory workspace). */\n workspace?: string;\n /** Canonical `agents/<id>/profile/`: bare SOUL.md / IDENTITY.md resolve here after the workspace. */\n profileMarkdownRoot?: string;\n /** Tool `name` values to omit (e.g. `shell`, `extensions` for extension tools). */\n disabledTools?: Set<string>;\n /** Optional primary model for image tool heuristics. */\n getPrimaryModel?: () => Model<Api>;\n getBuiltinMemoryStore?: () => BuiltinMemoryStore;\n getMemoryManager?: () => MemoryManager;\n /** When set, registers `skills_list` and `skill_view` bound to this workspace\\'s skills. */\n getSkillManager?: () => SkillManager;\n}\n\nexport class AgentToolsFactory {\n private browserManager: BrowserManager | null = null;\n /** One dialog/console supervisor per chat session (browser tab). */\n private readonly browserTaskSupervisors = new Map<string, CdpSupervisor>();\n /** Cached readiness probe — keyed by backend mode + extension host:port. */\n private browserReadinessCache: {\n key: string;\n expiresAt: number;\n inflight?: Promise<BrowserNotReadyError | null>;\n result?: BrowserNotReadyError | null;\n } | null = null;\n\n constructor(private deps: ToolFactoryDeps) {}\n\n private browserReadinessKey(): string {\n const cfg = this.deps.getConfig?.();\n const backend = resolveBrowserBackendFromConfig(cfg);\n const ext = cfg?.agents?.defaults?.browser?.extension;\n const host = typeof ext?.host === 'string' && ext.host.trim() ? ext.host.trim() : '127.0.0.1';\n const port = typeof ext?.port === 'number' ? ext.port : 19820;\n const cdpUrl = backend.mode === 'cdp' ? backend.config.wsEndpoint : '';\n const cloudKind = backend.mode === 'cloud' ? backend.config.type : '';\n return `${backend.mode}@${host}:${port}|${cdpUrl}|${cloudKind}`;\n }\n\n private async checkBrowserReadinessCached(): Promise<BrowserNotReadyError | null> {\n const key = this.browserReadinessKey();\n const now = Date.now();\n const cached = this.browserReadinessCache;\n if (cached && cached.key === key && cached.expiresAt > now && cached.inflight === undefined) {\n return cached.result ?? null;\n }\n if (cached && cached.key === key && cached.inflight) {\n return cached.inflight;\n }\n const inflight = checkBrowserReadiness(this.deps.getConfig?.());\n this.browserReadinessCache = { key, expiresAt: now + 30_000, inflight };\n try {\n const result = await inflight;\n this.browserReadinessCache = { key, expiresAt: Date.now() + 30_000, result };\n return result;\n } catch (e) {\n // Probe should never throw, but if it does we just bypass the cache.\n this.browserReadinessCache = null;\n log.warn({ err: e }, 'browserReadiness probe failed');\n return null;\n }\n }\n\n /** Invalidate the readiness cache (config hot-reload, settings-page save, etc.). */\n invalidateBrowserReadinessCache(): void {\n this.browserReadinessCache = null;\n }\n\n private browserSupervisorForTask(taskId: string): CdpSupervisor {\n let s = this.browserTaskSupervisors.get(taskId);\n if (!s) {\n const b = this.deps.getConfig?.()?.agents?.defaults?.browser;\n const dialogPolicy =\n b?.dialogPolicy === 'must_respond' || b?.dialogPolicy === 'auto_accept' || b?.dialogPolicy === 'auto_dismiss'\n ? b.dialogPolicy\n : 'auto_dismiss';\n const dialogTimeoutSeconds =\n typeof b?.dialogTimeoutSeconds === 'number' &&\n Number.isFinite(b.dialogTimeoutSeconds) &&\n b.dialogTimeoutSeconds >= 1\n ? Math.floor(b.dialogTimeoutSeconds)\n : 300;\n s = new CdpSupervisor({ dialogPolicy, dialogTimeoutSeconds });\n this.browserTaskSupervisors.set(taskId, s);\n }\n return s;\n }\n\n private async acquireBrowserPage(): Promise<Page> {\n const taskId = this.deps.getCurrentContext()?.sessionKey ?? 'default';\n const mgr = this.ensureBrowserManager();\n await mgr.ensureConnected();\n if (mgr.getExtensionProvider()) {\n return null as unknown as Page;\n }\n const page = await mgr.getPage(taskId);\n this.browserSupervisorForTask(taskId).attach(page);\n return page;\n }\n\n private ensureBrowserManager(): BrowserManager {\n if (!this.browserManager) {\n this.browserManager = new BrowserManager({\n getHeadless: () => this.deps.getConfig?.()?.agents?.defaults?.browser?.headless === true,\n getBackend: () => resolveBrowserBackendFromConfig(this.deps.getConfig?.()),\n });\n }\n return this.browserManager;\n }\n\n /** Close Playwright and all pages (gateway stop, agent manager dispose, or config hot-reload). */\n async shutdownBrowser(): Promise<void> {\n this.browserReadinessCache = null;\n if (!this.browserManager) {\n return;\n }\n await this.browserManager.shutdown();\n this.browserManager = null;\n this.browserTaskSupervisors.clear();\n }\n\n /** Drop the tab for a session when its agent instance is removed. */\n async closeBrowserPageForSession(sessionKey: string): Promise<void> {\n this.browserTaskSupervisors.delete(sessionKey);\n await this.browserManager?.closePage(sessionKey);\n }\n\n createCoreTools(options?: CreateCoreToolsOptions): AgentTool<any, any>[] {\n const workspace = options?.workspace ?? this.deps.workspace;\n const { bus } = this.deps;\n const getPrimary = options?.getPrimaryModel ?? this.deps.getPrimaryModel;\n const getBuiltin = options?.getBuiltinMemoryStore ?? this.deps.getBuiltinMemoryStore;\n const builtinStore = getBuiltin?.();\n const memoriesDir = builtinStore?.memoriesDir;\n const getMemMgr = options?.getMemoryManager ?? this.deps.getMemoryManager;\n const getSkillMgr = options?.getSkillManager;\n const disabled = options?.disabledTools;\n\n const primary = getPrimary?.();\n const modelHasVision = primary?.input?.includes('image') ?? false;\n const cfg = this.deps.getConfig?.();\n const recordGoalEvidence = createGoalEvidenceRecorder({\n getSessionKey: () => this.deps.getCurrentContext()?.sessionKey,\n });\n const imageTool = createImageTool({\n config: cfg,\n workspace,\n modelHasVision,\n });\n const imageGenerateTool = createImageGenerateTool({\n config: cfg,\n workspace,\n });\n\n const optionalTools = [imageTool, imageGenerateTool].filter((t) => t != null) as any[];\n\n const readTool = createReadFileTool(workspace, {\n profileMarkdownRoot: options?.profileMarkdownRoot,\n });\n const writeTool = createWriteFileTool(workspace, {\n profileMarkdownRoot: options?.profileMarkdownRoot,\n recordGoalEvidence,\n });\n const editTool = createEditFileTool(workspace, {\n profileMarkdownRoot: options?.profileMarkdownRoot,\n recordGoalEvidence,\n });\n const listDir = createListDirTool(workspace);\n const grep = createGrepTool(workspace);\n const find = createFindTool(workspace);\n\n const core: AgentTool<any, any>[] = [\n createSessionStatusTool(),\n createDreamingTool({\n getWorkspace: () => workspace,\n getConfig: () => this.deps.getConfig?.(),\n }),\n createToolManualTool(),\n createClarifyTool({\n resolveAskUser: () => {\n const req = this.deps.gatewayClarify?.requestClarification;\n if (!req) return null;\n const ctx = this.deps.getCurrentContext();\n if (!ctx?.sessionKey) return null;\n const source = clarifyTransportSource(ctx.sessionKey);\n if (!source || !CLARIFY_SUPPORTED_CHANNELS.has(source)) return null;\n return (r) => req(ctx.sessionKey, r);\n },\n }),\n createTodoTool({\n getSessionKey: () => this.deps.getCurrentContext()?.sessionKey,\n }),\n ...(getSkillMgr\n ? [\n createSkillsListTool({\n getSkillManager: getSkillMgr,\n getSkillIndexingContext: this.deps.getSkillIndexingContext,\n }),\n createSkillViewTool({\n getSkillManager: getSkillMgr,\n getSkillIndexingContext: this.deps.getSkillIndexingContext,\n registerSkillEnvPassthrough: this.deps.registerSkillEnvPassthrough,\n }),\n createSkillManageTool({\n getSkillManager: getSkillMgr,\n getWorkspace: () => workspace,\n onSkillsFilesystemMutate: this.deps.onSkillsFilesystemMutate,\n }),\n ]\n : []),\n readTool,\n writeTool,\n editTool,\n listDir,\n grep,\n find,\n createShellTool(workspace, {\n getSkillPassthroughEnvVarNames: this.deps.getSkillPassthroughEnvVarNames,\n recordGoalEvidence,\n }),\n createWebSearchTool(() => this.deps.getConfig?.()),\n createWebFetchTool(() => this.deps.getConfig?.()),\n createWebExtractTool({ getConfig: () => this.deps.getConfig?.() }),\n // Note: TTS is NOT handled by send_message tool anymore\n // TTS is applied at the ChannelManager dispatch layer\n createMessageTool(bus, () => this.deps.getCurrentContext()),\n ...(mergeTtsConfigFromAppConfig(cfg?.messages?.tts).enabled\n ? [\n createTextToSpeechTool({\n bus,\n getContext: () => this.deps.getCurrentContext(),\n getConfig: () => this.deps.getConfig?.(),\n }),\n ]\n : []),\n createSendMediaTool(workspace, bus, () => this.deps.getCurrentContext()),\n createReadMediaTool(),\n ...(isShareToolAvailable(cfg)\n ? [\n createCreateShareTool({\n workspace,\n getConfig: () => this.deps.getConfig?.(),\n }),\n ]\n : []),\n createMemorySearchTool({ workspaceDir: workspace, memoriesDir }),\n createMemoryGetTool({ workspaceDir: workspace, memoriesDir }),\n ...(getBuiltin && shouldRegisterCuratedMemoryTool(this.deps.getConfig?.())\n ? [\n createCuratedMemoryTool(getBuiltin, {\n onMemoryWrite: (action, target, content) => {\n getMemMgr?.().onMemoryWrite(action, target, content);\n },\n }),\n ]\n : []),\n ...(getMemMgr?.().getAdditionalTools() ?? []),\n ...(this.deps.getSessionStore\n ? [\n createSessionSearchTool({\n getSessionStore: this.deps.getSessionStore,\n getConfig: this.deps.getConfig,\n getCurrentSessionKey: () => this.deps.getCurrentContext()?.sessionKey,\n }),\n ]\n : []),\n ...(this.deps.getCronService\n ? [\n createCronjobTool({\n getCronService: this.deps.getCronService,\n }),\n ]\n : []),\n createGoalTool(),\n ...(cfg?.agents?.defaults?.browser?.enabled !== false\n ? [\n createBrowserUseTool({\n getManager: () => this.ensureBrowserManager(),\n getPageForTask: () => this.acquireBrowserPage(),\n getTaskId: () => this.deps.getCurrentContext()?.sessionKey ?? 'default',\n getConfig: () => this.deps.getConfig?.(),\n getReadiness: () => this.checkBrowserReadinessCached(),\n getSupervisor: () =>\n this.browserSupervisorForTask(this.deps.getCurrentContext()?.sessionKey ?? 'default'),\n notifyBrowserPageClosed: (taskId) => {\n this.browserTaskSupervisors.delete(taskId);\n },\n }),\n ]\n : []),\n ...(cfg?.agents?.defaults?.workflow?.enabled !== false && primary\n ? [\n createWorkflowTool({\n catalog: createWorkflowCatalog(),\n getCurrentSessionKey: () => this.deps.getCurrentContext()?.sessionKey,\n getConfig: () => this.deps.getConfig?.(),\n startWorkflowRun: this.deps.getWorkflowRunService\n ? (params) => this.deps.getWorkflowRunService!().startWorkflowRun(params)\n : undefined,\n }),\n ]\n : []),\n ...(cfg?.agents?.defaults?.delegate?.enabled === true && primary\n ? [\n createDelegateTool({\n workspace,\n getSubagentModel: () => {\n const gp = options?.getPrimaryModel ?? this.deps.getPrimaryModel;\n const m = gp?.();\n if (!m) {\n throw new Error('No primary model configured for delegate_task');\n }\n return m;\n },\n bus: this.deps.bus,\n getConfig: () => this.deps.getConfig?.(),\n getCurrentContext: () => this.deps.getCurrentContext?.() ?? null,\n hookRunner: this.deps.hookRunner,\n toolExecutorConfig: this.deps.toolExecutorConfig,\n // Injected so `child-agent-factory.ts` does not need to import\n // `AgentToolsFactory` directly (which would form a cycle).\n buildChildTools: (childOpts) => {\n const childFactory = new AgentToolsFactory({\n workspace: childOpts.workspace,\n bus: childOpts.bus,\n getCurrentContext: () => null,\n getConfig: childOpts.getConfig,\n getPrimaryModel: () => childOpts.model,\n toolExecutorConfig: childOpts.toolExecutorConfig,\n });\n return childFactory.createAllTools({\n workspace: childOpts.workspace,\n getPrimaryModel: () => childOpts.model,\n disabledTools: new Set(['extensions']),\n });\n },\n }),\n ]\n : []),\n ...optionalTools,\n ];\n\n return filterToolsByDisabledSet(core, disabled);\n }\n\n createAllTools(coreOptions?: CreateCoreToolsOptions): AgentTool<any, any>[] {\n const coreTools = this.createCoreTools(coreOptions);\n const disableExtensions = coreOptions?.disabledTools?.has('extensions');\n const cfg = this.deps.getConfig?.();\n\n let bundled: AgentTool<any, any>[];\n if (!this.deps.extensionRegistry || disableExtensions) {\n bundled = coreTools;\n } else {\n const extensionTools = this.deps.extensionRegistry.getAllTools();\n log.info({ count: extensionTools.length }, 'Loaded extension tools');\n bundled = [...coreTools, ...extensionTools];\n }\n\n const wrapped = wrapToolsWithProtection(bundled, this.deps.toolExecutorConfig);\n\n const executeEnabled =\n cfg?.agents?.defaults?.executeCode?.enabled === true &&\n !coreOptions?.disabledTools?.has('execute_code');\n\n if (executeEnabled) {\n const sandboxMap = buildSandboxToolMap(wrapped);\n const executeTool = createExecuteCodeTool({ getSandboxToolMap: () => sandboxMap });\n const wrappedExecute = wrapToolsWithProtection([executeTool as any], this.deps.toolExecutorConfig);\n return [...wrapped, ...wrappedExecute];\n }\n\n return wrapped;\n }\n}\n\nfunction filterToolsByDisabledSet(\n tools: any[],\n disabled: Set<string> | undefined,\n): any[] {\n if (!disabled || disabled.size === 0) {\n return tools;\n }\n return tools.filter((t) => !disabled.has(t.name));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"factory.js","names":[],"sources":["../../../../src/agent/tools/factory.ts"],"sourcesContent":["/**\n * Agent Tools Factory - Creates and configures agent tools\n *\n * Centralizes tool creation logic to keep service.ts focused on orchestration.\n *\n * TTS: auto TTS is applied at the ChannelManager via maybeApplyTtsToPayload().\n * Optional \\`text_to_speech\\` tool sends explicit voice when TTS is enabled.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { Model, Api } from '@earendil-works/pi-ai';\nimport type { Page } from 'playwright-core';\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport {\n createReadFileTool,\n createWriteFileTool,\n createEditFileTool,\n createListDirTool,\n createGrepTool,\n createFindTool,\n createShellTool,\n createWebSearchTool,\n createWebFetchTool,\n createWebExtractTool,\n createMessageTool,\n createSendMediaTool,\n createReadMediaTool,\n createCreateShareTool,\n isShareToolAvailable,\n createMemorySearchTool,\n createMemoryGetTool,\n createTodoTool,\n createSessionStatusTool,\n createDreamingTool,\n createClarifyTool,\n createToolManualTool,\n createGoalTool,\n} from './index.js';\nimport { createCuratedMemoryTool } from './curated-memory-tool.js';\nimport { createSessionSearchTool } from './session-search-tool.js';\nimport type { BuiltinMemoryStore } from '../memory/builtin-memory-store.js';\nimport type { MemoryManager } from '../memory/manager.js';\nimport { shouldRegisterCuratedMemoryTool } from '../memory/memory-config.js';\nimport type { SessionStore } from '../../session/store.js';\nimport type { GatewayClarifyRequestFn } from './clarify-tool.js';\nimport { createImageTool } from './image-tool.js';\nimport { createImageGenerateTool } from './image-generate-tool.js';\nimport {\n BrowserManager,\n BrowserNotReadyError,\n CdpSupervisor,\n checkBrowserReadiness,\n resolveBrowserBackendFromConfig,\n} from '../../browser/index.js';\nimport { createBrowserUseTool } from './browser/tool/browser-use-tool.js';\nimport { createDelegateTool } from './delegate-tool.js';\nimport { createWorkflowTool } from './workflow-tool.js';\nimport { createWorkflowCatalog } from '../workflow/catalog.js';\nimport { buildSandboxToolMap, createExecuteCodeTool } from './execute-code-tool.js';\nimport { createCronjobTool } from './cronjob-tool.js';\nimport type { CronService } from '../../cron/index.js';\nimport type { WorkflowRunServiceLike } from '../../workflows/service/workflow-run-service.types.js';\nimport { createLogger } from '../../utils/logger.js';\nimport type { SkillManager } from '../skills/skill-manager.js';\nimport { wrapToolsWithProtection, type ToolExecutorConfig } from './executor.js';\nimport { createSkillsListTool, createSkillViewTool } from './skills-tools.js';\nimport { createSkillManageTool } from './skill-manage-tool.js';\nimport { createTextToSpeechTool } from './tts-tool.js';\nimport { mergeTtsConfigFromAppConfig } from '../../voice/tts/merge-config.js';\nimport { createGoalEvidenceRecorder } from './goal-evidence-recorder.js';\n\nconst log = createLogger('AgentToolsFactory');\n\n/** Channels where `clarify` can block for a user answer (web UI, Telegram, CLI readline). */\nconst CLARIFY_SUPPORTED_CHANNELS = new Set(['webchat', 'telegram', 'cli']);\n\nexport interface ToolFactoryDeps {\n workspace: string;\n extensionRegistry?: any;\n getCurrentContext: () => { channel: string; chatId: string; sessionKey: string } | null;\n hookRunner?: import('../../extensions/index.js').ExtensionHookRunner;\n bus: MessageBus;\n toolExecutorConfig?: Partial<ToolExecutorConfig>;\n /** Agent defaults (image tools, etc.); use getter so hot-reloaded config applies. */\n getConfig?: () => Config | undefined;\n /** Session / default chat model for vision tool description. */\n getPrimaryModel?: () => Model<Api>;\n /** Built-in curated memory store (agent home `memories/`). */\n getBuiltinMemoryStore?: () => BuiltinMemoryStore;\n /** Memory orchestration (prefetch/sync + external tools). */\n getMemoryManager?: () => MemoryManager;\n /** Session store for `session_search`. */\n getSessionStore?: () => SessionStore;\n /** When set (gateway webchat), enables the `clarify` tool. */\n gatewayClarify?: { requestClarification: GatewayClarifyRequestFn };\n /** Gateway: enables the `cronjob` tool. */\n getCronService?: () => CronService | undefined;\n /** Gateway: starts persisted workflow runs (dedicated chat session per run). */\n getWorkflowRunService?: () => WorkflowRunServiceLike | undefined;\n /** Current session skill indexing (tool gating + allowlist); used by skills_list / skill_view. */\n getSkillIndexingContext?: () =>\n | { registeredToolNames: string[]; skillAllowlist?: string[] }\n | undefined;\n /** After skill_manage mutates disk, reload skills + refresh agent prompts (optional). */\n onSkillsFilesystemMutate?: () => void;\n /** Names registered via skill_view for shell env passthrough. */\n getSkillPassthroughEnvVarNames?: () => string[];\n /** Add declared env names for the current session (no values stored). */\n registerSkillEnvPassthrough?: (names: string[]) => void;\n}\n\nexport interface CreateCoreToolsOptions {\n /** Workspace root for file/shell tools (defaults to factory workspace). */\n workspace?: string;\n /** Canonical `agents/<id>/profile/`: bare SOUL.md / IDENTITY.md resolve here after the workspace. */\n profileMarkdownRoot?: string;\n /** Tool `name` values to omit (e.g. `shell`, `extensions` for extension tools). */\n disabledTools?: Set<string>;\n /** Optional primary model for image tool heuristics. */\n getPrimaryModel?: () => Model<Api>;\n getBuiltinMemoryStore?: () => BuiltinMemoryStore;\n getMemoryManager?: () => MemoryManager;\n /** When set, registers `skills_list` and `skill_view` bound to this workspace\\'s skills. */\n getSkillManager?: () => SkillManager;\n}\n\nexport class AgentToolsFactory {\n private browserManager: BrowserManager | null = null;\n /** One dialog/console supervisor per chat session (browser tab). */\n private readonly browserTaskSupervisors = new Map<string, CdpSupervisor>();\n /** Cached readiness probe — keyed by backend mode + extension host:port. */\n private browserReadinessCache: {\n key: string;\n expiresAt: number;\n inflight?: Promise<BrowserNotReadyError | null>;\n result?: BrowserNotReadyError | null;\n } | null = null;\n\n constructor(private deps: ToolFactoryDeps) {}\n\n private browserReadinessKey(): string {\n const cfg = this.deps.getConfig?.();\n const backend = resolveBrowserBackendFromConfig(cfg);\n const ext = cfg?.agents?.defaults?.browser?.extension;\n const host = typeof ext?.host === 'string' && ext.host.trim() ? ext.host.trim() : '127.0.0.1';\n const port = typeof ext?.port === 'number' ? ext.port : 19820;\n const cdpUrl = backend.mode === 'cdp' ? backend.config.wsEndpoint : '';\n const cloudKind = backend.mode === 'cloud' ? backend.config.type : '';\n return `${backend.mode}@${host}:${port}|${cdpUrl}|${cloudKind}`;\n }\n\n private async checkBrowserReadinessCached(): Promise<BrowserNotReadyError | null> {\n const key = this.browserReadinessKey();\n const now = Date.now();\n const cached = this.browserReadinessCache;\n if (cached && cached.key === key && cached.expiresAt > now && cached.inflight === undefined) {\n return cached.result ?? null;\n }\n if (cached && cached.key === key && cached.inflight) {\n return cached.inflight;\n }\n const inflight = checkBrowserReadiness(this.deps.getConfig?.());\n this.browserReadinessCache = { key, expiresAt: now + 30_000, inflight };\n try {\n const result = await inflight;\n this.browserReadinessCache = { key, expiresAt: Date.now() + 30_000, result };\n return result;\n } catch (e) {\n // Probe should never throw, but if it does we just bypass the cache.\n this.browserReadinessCache = null;\n log.warn({ err: e }, 'browserReadiness probe failed');\n return null;\n }\n }\n\n /** Invalidate the readiness cache (config hot-reload, settings-page save, etc.). */\n invalidateBrowserReadinessCache(): void {\n this.browserReadinessCache = null;\n }\n\n private browserSupervisorForTask(taskId: string): CdpSupervisor {\n let s = this.browserTaskSupervisors.get(taskId);\n if (!s) {\n const b = this.deps.getConfig?.()?.agents?.defaults?.browser;\n const dialogPolicy =\n b?.dialogPolicy === 'must_respond' || b?.dialogPolicy === 'auto_accept' || b?.dialogPolicy === 'auto_dismiss'\n ? b.dialogPolicy\n : 'auto_dismiss';\n const dialogTimeoutSeconds =\n typeof b?.dialogTimeoutSeconds === 'number' &&\n Number.isFinite(b.dialogTimeoutSeconds) &&\n b.dialogTimeoutSeconds >= 1\n ? Math.floor(b.dialogTimeoutSeconds)\n : 300;\n s = new CdpSupervisor({ dialogPolicy, dialogTimeoutSeconds });\n this.browserTaskSupervisors.set(taskId, s);\n }\n return s;\n }\n\n private async acquireBrowserPage(): Promise<Page> {\n const taskId = this.deps.getCurrentContext()?.sessionKey ?? 'default';\n const mgr = this.ensureBrowserManager();\n await mgr.ensureConnected();\n if (mgr.getExtensionProvider()) {\n return null as unknown as Page;\n }\n const page = await mgr.getPage(taskId);\n this.browserSupervisorForTask(taskId).attach(page);\n return page;\n }\n\n private ensureBrowserManager(): BrowserManager {\n if (!this.browserManager) {\n this.browserManager = new BrowserManager({\n getHeadless: () => this.deps.getConfig?.()?.agents?.defaults?.browser?.headless === true,\n getBackend: () => resolveBrowserBackendFromConfig(this.deps.getConfig?.()),\n });\n }\n return this.browserManager;\n }\n\n /** Close Playwright and all pages (gateway stop, agent manager dispose, or config hot-reload). */\n async shutdownBrowser(): Promise<void> {\n this.browserReadinessCache = null;\n if (!this.browserManager) {\n return;\n }\n await this.browserManager.shutdown();\n this.browserManager = null;\n this.browserTaskSupervisors.clear();\n }\n\n /** Drop the tab for a session when its agent instance is removed. */\n async closeBrowserPageForSession(sessionKey: string): Promise<void> {\n this.browserTaskSupervisors.delete(sessionKey);\n await this.browserManager?.closePage(sessionKey);\n }\n\n createCoreTools(options?: CreateCoreToolsOptions): AgentTool<any, any>[] {\n const workspace = options?.workspace ?? this.deps.workspace;\n const { bus } = this.deps;\n const getPrimary = options?.getPrimaryModel ?? this.deps.getPrimaryModel;\n const getBuiltin = options?.getBuiltinMemoryStore ?? this.deps.getBuiltinMemoryStore;\n const builtinStore = getBuiltin?.();\n const memoriesDir = builtinStore?.memoriesDir;\n const getMemMgr = options?.getMemoryManager ?? this.deps.getMemoryManager;\n const getSkillMgr = options?.getSkillManager;\n const disabled = options?.disabledTools;\n\n const primary = getPrimary?.();\n const modelHasVision = primary?.input?.includes('image') ?? false;\n const cfg = this.deps.getConfig?.();\n const recordGoalEvidence = createGoalEvidenceRecorder({\n getSessionKey: () => this.deps.getCurrentContext()?.sessionKey,\n });\n const imageTool = createImageTool({\n config: cfg,\n workspace,\n modelHasVision,\n });\n const imageGenerateTool = createImageGenerateTool({\n config: cfg,\n workspace,\n });\n\n const optionalTools = [imageTool, imageGenerateTool].filter((t) => t != null) as any[];\n\n const readTool = createReadFileTool(workspace, {\n profileMarkdownRoot: options?.profileMarkdownRoot,\n });\n const writeTool = createWriteFileTool(workspace, {\n profileMarkdownRoot: options?.profileMarkdownRoot,\n recordGoalEvidence,\n });\n const editTool = createEditFileTool(workspace, {\n profileMarkdownRoot: options?.profileMarkdownRoot,\n recordGoalEvidence,\n });\n const listDir = createListDirTool(workspace);\n const grep = createGrepTool(workspace);\n const find = createFindTool(workspace);\n\n const core: AgentTool<any, any>[] = [\n createSessionStatusTool(),\n createDreamingTool({\n getWorkspace: () => workspace,\n getConfig: () => this.deps.getConfig?.(),\n }),\n createToolManualTool(),\n createClarifyTool({\n resolveAskUser: () => {\n const req = this.deps.gatewayClarify?.requestClarification;\n if (!req) return null;\n const ctx = this.deps.getCurrentContext();\n if (!ctx?.sessionKey) return null;\n if (!CLARIFY_SUPPORTED_CHANNELS.has(ctx.channel)) return null;\n return (r) => req(ctx.sessionKey, r);\n },\n }),\n createTodoTool({\n getSessionKey: () => this.deps.getCurrentContext()?.sessionKey,\n }),\n ...(getSkillMgr\n ? [\n createSkillsListTool({\n getSkillManager: getSkillMgr,\n getSkillIndexingContext: this.deps.getSkillIndexingContext,\n }),\n createSkillViewTool({\n getSkillManager: getSkillMgr,\n getSkillIndexingContext: this.deps.getSkillIndexingContext,\n registerSkillEnvPassthrough: this.deps.registerSkillEnvPassthrough,\n }),\n createSkillManageTool({\n getSkillManager: getSkillMgr,\n getWorkspace: () => workspace,\n onSkillsFilesystemMutate: this.deps.onSkillsFilesystemMutate,\n }),\n ]\n : []),\n readTool,\n writeTool,\n editTool,\n listDir,\n grep,\n find,\n createShellTool(workspace, {\n getSkillPassthroughEnvVarNames: this.deps.getSkillPassthroughEnvVarNames,\n recordGoalEvidence,\n }),\n createWebSearchTool(() => this.deps.getConfig?.()),\n createWebFetchTool(() => this.deps.getConfig?.()),\n createWebExtractTool({ getConfig: () => this.deps.getConfig?.() }),\n // Note: TTS is NOT handled by send_message tool anymore\n // TTS is applied at the ChannelManager dispatch layer\n createMessageTool(bus, () => this.deps.getCurrentContext()),\n ...(mergeTtsConfigFromAppConfig(cfg?.messages?.tts).enabled\n ? [\n createTextToSpeechTool({\n bus,\n getContext: () => this.deps.getCurrentContext(),\n getConfig: () => this.deps.getConfig?.(),\n }),\n ]\n : []),\n createSendMediaTool(workspace, bus, () => this.deps.getCurrentContext()),\n createReadMediaTool(),\n ...(isShareToolAvailable(cfg)\n ? [\n createCreateShareTool({\n workspace,\n getConfig: () => this.deps.getConfig?.(),\n }),\n ]\n : []),\n createMemorySearchTool({ workspaceDir: workspace, memoriesDir }),\n createMemoryGetTool({ workspaceDir: workspace, memoriesDir }),\n ...(getBuiltin && shouldRegisterCuratedMemoryTool(this.deps.getConfig?.())\n ? [\n createCuratedMemoryTool(getBuiltin, {\n onMemoryWrite: (action, target, content) => {\n getMemMgr?.().onMemoryWrite(action, target, content);\n },\n }),\n ]\n : []),\n ...(getMemMgr?.().getAdditionalTools() ?? []),\n ...(this.deps.getSessionStore\n ? [\n createSessionSearchTool({\n getSessionStore: this.deps.getSessionStore,\n getConfig: this.deps.getConfig,\n getCurrentSessionKey: () => this.deps.getCurrentContext()?.sessionKey,\n }),\n ]\n : []),\n ...(this.deps.getCronService\n ? [\n createCronjobTool({\n getCronService: this.deps.getCronService,\n }),\n ]\n : []),\n createGoalTool(),\n ...(cfg?.agents?.defaults?.browser?.enabled !== false\n ? [\n createBrowserUseTool({\n getManager: () => this.ensureBrowserManager(),\n getPageForTask: () => this.acquireBrowserPage(),\n getTaskId: () => this.deps.getCurrentContext()?.sessionKey ?? 'default',\n getConfig: () => this.deps.getConfig?.(),\n getReadiness: () => this.checkBrowserReadinessCached(),\n getSupervisor: () =>\n this.browserSupervisorForTask(this.deps.getCurrentContext()?.sessionKey ?? 'default'),\n notifyBrowserPageClosed: (taskId) => {\n this.browserTaskSupervisors.delete(taskId);\n },\n }),\n ]\n : []),\n ...(cfg?.agents?.defaults?.workflow?.enabled !== false && primary\n ? [\n createWorkflowTool({\n catalog: createWorkflowCatalog(),\n getCurrentSessionKey: () => this.deps.getCurrentContext()?.sessionKey,\n getConfig: () => this.deps.getConfig?.(),\n startWorkflowRun: this.deps.getWorkflowRunService\n ? (params) => this.deps.getWorkflowRunService!().startWorkflowRun(params)\n : undefined,\n }),\n ]\n : []),\n ...(cfg?.agents?.defaults?.delegate?.enabled === true && primary\n ? [\n createDelegateTool({\n workspace,\n getSubagentModel: () => {\n const gp = options?.getPrimaryModel ?? this.deps.getPrimaryModel;\n const m = gp?.();\n if (!m) {\n throw new Error('No primary model configured for delegate_task');\n }\n return m;\n },\n bus: this.deps.bus,\n getConfig: () => this.deps.getConfig?.(),\n getCurrentContext: () => this.deps.getCurrentContext?.() ?? null,\n hookRunner: this.deps.hookRunner,\n toolExecutorConfig: this.deps.toolExecutorConfig,\n // Injected so `child-agent-factory.ts` does not need to import\n // `AgentToolsFactory` directly (which would form a cycle).\n buildChildTools: (childOpts) => {\n const childFactory = new AgentToolsFactory({\n workspace: childOpts.workspace,\n bus: childOpts.bus,\n getCurrentContext: () => null,\n getConfig: childOpts.getConfig,\n getPrimaryModel: () => childOpts.model,\n toolExecutorConfig: childOpts.toolExecutorConfig,\n });\n return childFactory.createAllTools({\n workspace: childOpts.workspace,\n getPrimaryModel: () => childOpts.model,\n disabledTools: new Set(['extensions']),\n });\n },\n }),\n ]\n : []),\n ...optionalTools,\n ];\n\n return filterToolsByDisabledSet(core, disabled);\n }\n\n createAllTools(coreOptions?: CreateCoreToolsOptions): AgentTool<any, any>[] {\n const coreTools = this.createCoreTools(coreOptions);\n const disableExtensions = coreOptions?.disabledTools?.has('extensions');\n const cfg = this.deps.getConfig?.();\n\n let bundled: AgentTool<any, any>[];\n if (!this.deps.extensionRegistry || disableExtensions) {\n bundled = coreTools;\n } else {\n const extensionTools = this.deps.extensionRegistry.getAllTools();\n log.info({ count: extensionTools.length }, 'Loaded extension tools');\n bundled = [...coreTools, ...extensionTools];\n }\n\n const wrapped = wrapToolsWithProtection(bundled, this.deps.toolExecutorConfig);\n\n const executeEnabled =\n cfg?.agents?.defaults?.executeCode?.enabled === true &&\n !coreOptions?.disabledTools?.has('execute_code');\n\n if (executeEnabled) {\n const sandboxMap = buildSandboxToolMap(wrapped);\n const executeTool = createExecuteCodeTool({ getSandboxToolMap: () => sandboxMap });\n const wrappedExecute = wrapToolsWithProtection([executeTool as any], this.deps.toolExecutorConfig);\n return [...wrapped, ...wrappedExecute];\n }\n\n return wrapped;\n }\n}\n\nfunction filterToolsByDisabledSet(\n tools: any[],\n disabled: Set<string> | undefined,\n): any[] {\n if (!disabled || disabled.size === 0) {\n return tools;\n }\n return tools.filter((t) => !disabled.has(t.name));\n}\n"],"mappings":"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"}
@@ -40,7 +40,7 @@ function createSkillManageTool(deps) {
40
40
  return {
41
41
  name: "skill_manage",
42
42
  label: "🛠️ Skill",
43
- description: "Create, edit, patch, or delete user skills under ~/.xopc/skills and/or workspace skills/ (see skills.agentWritePolicy). Also write_file / remove_file under references/, templates/, scripts/, assets/. Bundled and extra-dir skills cannot be modified. Runs a security scan after writes.",
43
+ description: "Create, edit, patch, or delete user skills under ~/.xopc/skills and/or workspace .xopc/skills/ (see skills.agentWritePolicy). Also write_file / remove_file under references/, templates/, scripts/, assets/. Bundled and extra-dir skills cannot be modified. Runs a security scan after writes.",
44
44
  parameters: SkillManageSchema,
45
45
  async execute(_toolCallId, params) {
46
46
  const mgr = deps.getSkillManager();