@xopcai/xopc 0.0.116 → 0.0.118

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 (677) hide show
  1. package/README.md +44 -28
  2. package/README.zh-CN.md +63 -45
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/demo-memory/src/index.d.ts +6 -0
  5. package/dist/extensions/demo-memory/src/index.js +132 -0
  6. package/dist/extensions/demo-memory/src/index.js.map +1 -0
  7. package/dist/extensions/demo-memory/xopc.extension.json +15 -0
  8. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  9. package/dist/extensions/feishu/src/schema/config-schema.d.ts +3 -3
  10. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  11. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  12. package/dist/extensions/telegram/src/command-handler.js +1 -2
  13. package/dist/extensions/telegram/src/command-handler.js.map +1 -1
  14. package/dist/extensions/telegram/src/config-schema.d.ts +8 -8
  15. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  16. package/dist/extensions/telegram/src/plugin.js +1 -1
  17. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  18. package/dist/extensions/telegram/src/update-offset-store.js +1 -1
  19. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  20. package/dist/extensions/telegram/xopc.extension.json +1 -1
  21. package/dist/extensions/weixin/src/api/api.js +2 -2
  22. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  23. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  24. package/dist/extensions/weixin/src/config-schema.d.ts +3 -3
  25. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  26. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  27. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  28. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  29. package/dist/extensions/weixin/src/plugin.js +1 -1
  30. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  31. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  32. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-CWM1UU5P.js → agent-avatar-dicebear-dzUrQoeZ.js} +1 -1
  33. package/dist/gateway/static/root/assets/agents-BCxZbkOw.js +2 -0
  34. package/dist/gateway/static/root/assets/{app-management-settings-panel-yXSXY_bu.js → app-management-settings-panel-bxYJVJpx.js} +1 -1
  35. package/dist/gateway/static/root/assets/{appearance-settings-DjY1P_ug.js → appearance-settings-BCIykXlI.js} +1 -1
  36. package/dist/gateway/static/root/assets/apps-page--wMEL00f.js +1 -0
  37. package/dist/gateway/static/root/assets/{archive-plugin-CytE5j-e.js → archive-plugin-Cki4SfU2.js} +1 -1
  38. package/dist/gateway/static/root/assets/{attachment-load-BvvrN6rF.js → attachment-load-D-KnS2Do.js} +1 -1
  39. package/dist/gateway/static/root/assets/{binary-plugins-IBWSitnj.js → binary-plugins-D2sgvJja.js} +1 -1
  40. package/dist/gateway/static/root/assets/{block-editor-C-wDpsf-.js → block-editor-DIq-4Gvb.js} +27 -27
  41. package/dist/gateway/static/root/assets/browser-settings-page-DRhKdn81.js +8 -0
  42. package/dist/gateway/static/root/assets/capability-presets-api-CorhiHlg.js +1 -0
  43. package/dist/gateway/static/root/assets/capability-presets-settings-panel-qFx9Jtce.js +1 -0
  44. package/dist/gateway/static/root/assets/channels-settings-BAwAkqIA.js +1 -0
  45. package/dist/gateway/static/root/assets/connectors-page-BQLcfitM.js +2 -0
  46. package/dist/gateway/static/root/assets/cron-api-qGwmL-24.js +1 -0
  47. package/dist/gateway/static/root/assets/cron-page-BBWMAj8-.js +3 -0
  48. package/dist/gateway/static/root/assets/dreaming-settings-Dw89Obml.js +1 -0
  49. package/dist/gateway/static/root/assets/{extension-debug-page-BAIyjDlq.js → extension-debug-page-DYu1KaFQ.js} +1 -1
  50. package/dist/gateway/static/root/assets/{extension-page-DEhv2GpC.js → extension-page-B3W6QwlZ.js} +1 -1
  51. package/dist/gateway/static/root/assets/{extension-settings-page-DOuAxTDW.js → extension-settings-page-D7VQ-cxE.js} +1 -1
  52. package/dist/gateway/static/root/assets/{fetch-CTsREQIe.js → fetch-B7xDPu-R.js} +1 -1
  53. package/dist/gateway/static/root/assets/{format-interval-label-D35Bfhtx.js → format-interval-label-BzxafKxR.js} +1 -1
  54. package/dist/gateway/static/root/assets/gateway-config-api-BTBLSeUu.js +1 -0
  55. package/dist/gateway/static/root/assets/gateway-settings-Cmwy58rS.js +1 -0
  56. package/dist/gateway/static/root/assets/{gateway-startup-retry-C1KAHrd2.js → gateway-startup-retry-CYj9FWCp.js} +1 -1
  57. package/dist/gateway/static/root/assets/goal-detail-page-l7mu5GWX.js +1 -0
  58. package/dist/gateway/static/root/assets/{goals-config-api-KnLGpu6h.js → goals-config-api-CQQgzPr3.js} +1 -1
  59. package/dist/gateway/static/root/assets/goals-page-BHitvJAv.js +2 -0
  60. package/dist/gateway/static/root/assets/{goals-settings-DtPtqZi8.js → goals-settings-CYVY4NGp.js} +1 -1
  61. package/dist/gateway/static/root/assets/{heartbeat-config-api-uKw1f0IG.js → heartbeat-config-api-DriO_CN9.js} +1 -1
  62. package/dist/gateway/static/root/assets/heartbeat-settings-CUQTKxg7.js +1 -0
  63. package/dist/gateway/static/root/assets/index-C17Tsd_b.css +1 -0
  64. package/dist/gateway/static/root/assets/index-Cc41r16l.js +191 -0
  65. package/dist/gateway/static/root/assets/{interval-presets-Dq0FXJ65.js → interval-presets-DFPCKW_W.js} +1 -1
  66. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings-C9_t4m7t.js → keyboard-shortcuts-settings-CcVcqstx.js} +1 -1
  67. package/dist/gateway/static/root/assets/{logs-page-SNkWzidV.js → logs-page-C2Uqvae9.js} +2 -2
  68. package/dist/gateway/static/root/assets/{markdown-split-Ca87W8-h.js → markdown-split-BwOFrJ2E.js} +1 -1
  69. package/dist/gateway/static/root/assets/{media-plugins-BAcUjPRJ.js → media-plugins-Cnz6Q5G6.js} +1 -1
  70. package/dist/gateway/static/root/assets/messages-B1iSKjiw.js +3 -0
  71. package/dist/gateway/static/root/assets/models-hub-panel-BfLfcta8.js +2 -0
  72. package/dist/gateway/static/root/assets/note-detail-page-BjwOQBfT.js +2 -0
  73. package/dist/gateway/static/root/assets/{note-image-lightbox-hnSX5SSn.js → note-image-lightbox-B-Svpmza.js} +1 -1
  74. package/dist/gateway/static/root/assets/notes-page-DktdBiwB.js +1 -0
  75. package/dist/gateway/static/root/assets/{preview-open-alternatives-CNgM20H5.js → preview-open-alternatives-Bss4TiwP.js} +1 -1
  76. package/dist/gateway/static/root/assets/remote-access-hub-rfVx96fq.js +1 -0
  77. package/dist/gateway/static/root/assets/{save-bar-controls-CcdjGcfT.js → save-bar-controls-BRNjdgKq.js} +1 -1
  78. package/dist/gateway/static/root/assets/{schedule-field-CYr39z76.js → schedule-field-CUCKODde.js} +1 -1
  79. package/dist/gateway/static/root/assets/{schema-form-BRAJgZQ2.js → schema-form-Dub9sy8r.js} +1 -1
  80. package/dist/gateway/static/root/assets/sessions-page-DbtMFuuH.js +1 -0
  81. package/dist/gateway/static/root/assets/settings-advanced-gate-5re5gAnP.js +1 -0
  82. package/dist/gateway/static/root/assets/{settings-collapsible-section-BhzjeGWi.js → settings-collapsible-section-BeFLavGi.js} +1 -1
  83. package/dist/gateway/static/root/assets/{settings-form-section-Cz3Pcr9b.js → settings-form-section-dmyaPOTG.js} +1 -1
  84. package/dist/gateway/static/root/assets/settings-page-D-WMyLlj.js +1 -0
  85. package/dist/gateway/static/root/assets/setup-status-panel-Cl-DEJAU.js +1 -0
  86. package/dist/gateway/static/root/assets/{share-preview-page-DL4y9K5e.js → share-preview-page-C8glrdqe.js} +1 -1
  87. package/dist/gateway/static/root/assets/shares-settings-CyPVvbLt.js +1 -0
  88. package/dist/gateway/static/root/assets/skill-reload-api-CleTH1oz.js +1 -0
  89. package/dist/gateway/static/root/assets/skills-page-Ck8hdXqR.js +2 -0
  90. package/dist/gateway/static/root/assets/{system-settings-panel-FD2jxRZ3.js → system-settings-panel-DI-LN_8G.js} +1 -1
  91. package/dist/gateway/static/root/assets/typed-models-lib-kX9duch4.js +1 -0
  92. package/dist/gateway/static/root/assets/{use-channel-catalog-BInPrfR5.js → use-channel-catalog-DqlWTsDb.js} +1 -1
  93. package/dist/gateway/static/root/assets/user-profile-settings-panel-B-UFPMXy.js +1 -0
  94. package/dist/gateway/static/root/assets/utils-Dm0hKalR.js +1 -0
  95. package/dist/gateway/static/root/assets/voice-api-key-field-C73IVZeC.js +1 -0
  96. package/dist/gateway/static/root/assets/{voice-player-store-1U3vFppm.js → voice-player-store-C_ArLJPM.js} +1 -1
  97. package/dist/gateway/static/root/assets/workflows-page-BtFGp2y_.js +18 -0
  98. package/dist/gateway/static/root/index.html +5 -5
  99. package/dist/package.js +1 -1
  100. package/dist/src/agent/agent-manager.d.ts +1 -1
  101. package/dist/src/agent/agent-manager.js +14 -14
  102. package/dist/src/agent/agent-manager.js.map +1 -1
  103. package/dist/src/agent/agent-scope.js +5 -9
  104. package/dist/src/agent/agent-scope.js.map +1 -1
  105. package/dist/src/agent/background-review/coordinator.js +0 -1
  106. package/dist/src/agent/background-review/coordinator.js.map +1 -1
  107. package/dist/src/agent/background-review/prompts.d.ts +2 -2
  108. package/dist/src/agent/background-review/prompts.js +2 -2
  109. package/dist/src/agent/background-review/prompts.js.map +1 -1
  110. package/dist/src/agent/background-review/run-background-review.d.ts +0 -2
  111. package/dist/src/agent/background-review/run-background-review.js +2 -4
  112. package/dist/src/agent/background-review/run-background-review.js.map +1 -1
  113. package/dist/src/agent/background-review/settings.d.ts +1 -1
  114. package/dist/src/agent/background-review/settings.js +8 -8
  115. package/dist/src/agent/background-review/settings.js.map +1 -1
  116. package/dist/src/agent/bootstrap/bootstrap-cache.d.ts +1 -0
  117. package/dist/src/agent/bootstrap/bootstrap-cache.js +4 -3
  118. package/dist/src/agent/bootstrap/bootstrap-cache.js.map +1 -1
  119. package/dist/src/agent/bootstrap/bootstrap-context.d.ts +2 -2
  120. package/dist/src/agent/bootstrap/bootstrap-context.js +4 -4
  121. package/dist/src/agent/bootstrap/bootstrap-context.js.map +1 -1
  122. package/dist/src/agent/bootstrap/bootstrap-files.d.ts +4 -0
  123. package/dist/src/agent/bootstrap/bootstrap-files.js +4 -3
  124. package/dist/src/agent/bootstrap/bootstrap-files.js.map +1 -1
  125. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +4 -2
  126. package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
  127. package/dist/src/agent/bootstrap/load-bootstrap-files.d.ts +2 -1
  128. package/dist/src/agent/bootstrap/load-bootstrap-files.js +18 -17
  129. package/dist/src/agent/bootstrap/load-bootstrap-files.js.map +1 -1
  130. package/dist/src/agent/bootstrap/project-agents-context.js +1 -1
  131. package/dist/src/agent/bootstrap/types.d.ts +1 -1
  132. package/dist/src/agent/context/workspace-seed.js +3 -3
  133. package/dist/src/agent/context/workspace-state.js +1 -1
  134. package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
  135. package/dist/src/agent/context/workspace.d.ts +4 -2
  136. package/dist/src/agent/context/workspace.js +6 -5
  137. package/dist/src/agent/context/workspace.js.map +1 -1
  138. package/dist/src/agent/embedded/run-for-session.js +4 -1
  139. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  140. package/dist/src/agent/fallback/candidates.js +11 -9
  141. package/dist/src/agent/fallback/candidates.js.map +1 -1
  142. package/dist/src/agent/goals/goal-locale.js +2 -2
  143. package/dist/src/agent/goals/post-turn.js +3 -3
  144. package/dist/src/agent/image/generation/runtime-types.d.ts +2 -0
  145. package/dist/src/agent/image/generation/runtime.js +1 -1
  146. package/dist/src/agent/image/generation/runtime.js.map +1 -1
  147. package/dist/src/agent/image/image-helpers.d.ts +1 -1
  148. package/dist/src/agent/image/image-helpers.js +4 -17
  149. package/dist/src/agent/image/image-helpers.js.map +1 -1
  150. package/dist/src/agent/image/image-model-fallback.js +1 -1
  151. package/dist/src/agent/image/image-model-fallback.js.map +1 -1
  152. package/dist/src/agent/image/inbound-image-handling.js +1 -1
  153. package/dist/src/agent/image/inbound-image-handling.js.map +1 -1
  154. package/dist/src/agent/image/load-image-media.js +2 -2
  155. package/dist/src/agent/image/tool-model-config.d.ts +1 -1
  156. package/dist/src/agent/image/tool-model-config.js +2 -2
  157. package/dist/src/agent/image/tool-model-config.js.map +1 -1
  158. package/dist/src/agent/ipc/inbox.js +3 -3
  159. package/dist/src/agent/ipc/socket.js +1 -1
  160. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  161. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  162. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  163. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  164. package/dist/src/agent/mcp/resolve-embedded-mcp-tools.js +1 -1
  165. package/dist/src/agent/mcp/resolve-embedded-mcp-tools.js.map +1 -1
  166. package/dist/src/agent/media-generation/runtime-shared.d.ts +5 -2
  167. package/dist/src/agent/media-generation/runtime-shared.js +1 -1
  168. package/dist/src/agent/media-generation/runtime-shared.js.map +1 -1
  169. package/dist/src/agent/memory/builtin-memory-store.d.ts +6 -2
  170. package/dist/src/agent/memory/builtin-memory-store.js +15 -6
  171. package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
  172. package/dist/src/agent/memory/builtin-provider.d.ts +31 -9
  173. package/dist/src/agent/memory/builtin-provider.js +290 -11
  174. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  175. package/dist/src/agent/memory/candidate-extractor.d.ts +6 -0
  176. package/dist/src/agent/memory/candidate-extractor.js +60 -0
  177. package/dist/src/agent/memory/candidate-extractor.js.map +1 -0
  178. package/dist/src/agent/memory/context-assembler.d.ts +10 -0
  179. package/dist/src/agent/memory/context-assembler.js +26 -0
  180. package/dist/src/agent/memory/context-assembler.js.map +1 -0
  181. package/dist/src/agent/memory/create-memory-manager.js +25 -7
  182. package/dist/src/agent/memory/create-memory-manager.js.map +1 -1
  183. package/dist/src/agent/memory/dreaming/config.d.ts +1 -6
  184. package/dist/src/agent/memory/dreaming/config.js +8 -8
  185. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  186. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +2 -0
  187. package/dist/src/agent/memory/dreaming/deep-promotion.js +25 -1
  188. package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
  189. package/dist/src/agent/memory/dreaming/events.js +1 -1
  190. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  191. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  192. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  193. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  194. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  195. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  196. package/dist/src/agent/memory/index.d.ts +1 -0
  197. package/dist/src/agent/memory/index.js +4 -3
  198. package/dist/src/agent/memory/inject-prefetch.js +6 -2
  199. package/dist/src/agent/memory/inject-prefetch.js.map +1 -1
  200. package/dist/src/agent/memory/manager.d.ts +39 -2
  201. package/dist/src/agent/memory/manager.js +355 -39
  202. package/dist/src/agent/memory/manager.js.map +1 -1
  203. package/dist/src/agent/memory/memory-config.js +15 -15
  204. package/dist/src/agent/memory/memory-config.js.map +1 -1
  205. package/dist/src/agent/memory/memory-flush.js +1 -1
  206. package/dist/src/agent/memory/plugin-discovery.d.ts +19 -5
  207. package/dist/src/agent/memory/plugin-discovery.js +97 -31
  208. package/dist/src/agent/memory/plugin-discovery.js.map +1 -1
  209. package/dist/src/agent/memory/prefetch-coordinator.js.map +1 -1
  210. package/dist/src/agent/memory/provider.d.ts +20 -15
  211. package/dist/src/agent/memory/stub-memory-provider.d.ts +17 -2
  212. package/dist/src/agent/memory/stub-memory-provider.js +20 -3
  213. package/dist/src/agent/memory/stub-memory-provider.js.map +1 -1
  214. package/dist/src/agent/memory/types.d.ts +162 -3
  215. package/dist/src/agent/models/manager.d.ts +1 -1
  216. package/dist/src/agent/models/manager.js +2 -2
  217. package/dist/src/agent/models/manager.js.map +1 -1
  218. package/dist/src/agent/orchestration/agent-orchestrator.d.ts +1 -1
  219. package/dist/src/agent/orchestration/agent-orchestrator.js +2 -1
  220. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  221. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +2 -2
  222. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +1 -1
  223. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +1 -1
  224. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.d.ts +2 -6
  225. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js +2 -8
  226. package/dist/src/agent/orchestration/run-agent-turn-with-timeout.js.map +1 -1
  227. package/dist/src/agent/prompt/memory/index.d.ts +4 -2
  228. package/dist/src/agent/prompt/memory/index.js +19 -13
  229. package/dist/src/agent/prompt/memory/index.js.map +1 -1
  230. package/dist/src/agent/prompt/sections/memory-skills.js +1 -1
  231. package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -1
  232. package/dist/src/agent/prompt/service-prompt-builder.js +5 -20
  233. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  234. package/dist/src/agent/reply/post-compaction-context.js +10 -7
  235. package/dist/src/agent/reply/post-compaction-context.js.map +1 -1
  236. package/dist/src/agent/reply/startup-context.js +7 -12
  237. package/dist/src/agent/reply/startup-context.js.map +1 -1
  238. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  239. package/dist/src/agent/sandbox/path-policy.js +2 -2
  240. package/dist/src/agent/service/process-direct-streaming.js +1 -4
  241. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  242. package/dist/src/agent/service/session-context-report.js +1 -1
  243. package/dist/src/agent/service/session-context-report.js.map +1 -1
  244. package/dist/src/agent/service.d.ts +3 -3
  245. package/dist/src/agent/service.js +30 -35
  246. package/dist/src/agent/service.js.map +1 -1
  247. package/dist/src/agent/service.types.d.ts +1 -2
  248. package/dist/src/agent/session/session-hydrator.js +1 -2
  249. package/dist/src/agent/session/session-hydrator.js.map +1 -1
  250. package/dist/src/agent/session/session-inspector.d.ts +1 -1
  251. package/dist/src/agent/session/session-inspector.js +10 -15
  252. package/dist/src/agent/session/session-inspector.js.map +1 -1
  253. package/dist/src/agent/skills/config.js +2 -2
  254. package/dist/src/agent/skills/filesystem-watcher.js +1 -1
  255. package/dist/src/agent/skills/hub-hash.js +2 -2
  256. package/dist/src/agent/skills/hub-lock.js +1 -1
  257. package/dist/src/agent/skills/hub-pull.js +3 -3
  258. package/dist/src/agent/skills/index.js +2 -2
  259. package/dist/src/agent/skills/installer.js +2 -2
  260. package/dist/src/agent/skills/managed-store.js +1 -1
  261. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  262. package/dist/src/agent/skills/skill-manager.js +1 -1
  263. package/dist/src/agent/skills/skill-view-path.js +1 -1
  264. package/dist/src/agent/skills/test-framework.js +1 -1
  265. package/dist/src/agent/starter-agents.d.ts +1 -3
  266. package/dist/src/agent/starter-agents.js +14 -22
  267. package/dist/src/agent/starter-agents.js.map +1 -1
  268. package/dist/src/agent/tools/browser/tool/browser-use-tool.js +1 -2
  269. package/dist/src/agent/tools/browser/tool/browser-use-tool.js.map +1 -1
  270. package/dist/src/agent/tools/curated-memory-tool.d.ts +2 -5
  271. package/dist/src/agent/tools/curated-memory-tool.js +77 -18
  272. package/dist/src/agent/tools/curated-memory-tool.js.map +1 -1
  273. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  274. package/dist/src/agent/tools/factory.d.ts +0 -4
  275. package/dist/src/agent/tools/factory.js +19 -58
  276. package/dist/src/agent/tools/factory.js.map +1 -1
  277. package/dist/src/agent/tools/find.js +1 -1
  278. package/dist/src/agent/tools/grep.js +1 -1
  279. package/dist/src/agent/tools/image-generate-tool.d.ts +1 -1
  280. package/dist/src/agent/tools/image-generate-tool.js +20 -15
  281. package/dist/src/agent/tools/image-generate-tool.js.map +1 -1
  282. package/dist/src/agent/tools/image-tool.js +1 -3
  283. package/dist/src/agent/tools/image-tool.js.map +1 -1
  284. package/dist/src/agent/tools/memory-tool.d.ts +2 -2
  285. package/dist/src/agent/tools/memory-tool.js +39 -14
  286. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  287. package/dist/src/agent/tools/session-search-tool.js +1 -3
  288. package/dist/src/agent/tools/session-search-tool.js.map +1 -1
  289. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  290. package/dist/src/agent/tools/web-extract.js +8 -9
  291. package/dist/src/agent/tools/web-extract.js.map +1 -1
  292. package/dist/src/agent/tools/workflow-tool.js +1 -1
  293. package/dist/src/agent/workflow/catalog.js +1 -1
  294. package/dist/src/agent/workflow/subagent-runner.js +1 -3
  295. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  296. package/dist/src/agent-manifest/index.d.ts +4 -0
  297. package/dist/src/agent-manifest/index.js +10 -0
  298. package/dist/src/agent-manifest/index.js.map +1 -0
  299. package/dist/src/agent-manifest/prompt.d.ts +2 -0
  300. package/dist/src/agent-manifest/prompt.js +57 -0
  301. package/dist/src/agent-manifest/prompt.js.map +1 -0
  302. package/dist/src/agent-manifest/resolver.d.ts +12 -0
  303. package/dist/src/agent-manifest/resolver.js +95 -0
  304. package/dist/src/agent-manifest/resolver.js.map +1 -0
  305. package/dist/src/agent-manifest/schema.d.ts +1010 -0
  306. package/dist/src/agent-manifest/schema.js +269 -0
  307. package/dist/src/agent-manifest/schema.js.map +1 -0
  308. package/dist/src/agent-manifest/validator.d.ts +25 -0
  309. package/dist/src/agent-manifest/validator.js +88 -0
  310. package/dist/src/agent-manifest/validator.js.map +1 -0
  311. package/dist/src/agent-runtime/boundary-guard.d.ts +12 -0
  312. package/dist/src/agent-runtime/boundary-guard.js +23 -0
  313. package/dist/src/agent-runtime/boundary-guard.js.map +1 -0
  314. package/dist/src/agent-runtime/index.d.ts +7 -0
  315. package/dist/src/agent-runtime/index.js +8 -0
  316. package/dist/src/agent-runtime/memory-runtime.d.ts +21 -0
  317. package/dist/src/agent-runtime/memory-runtime.js +50 -0
  318. package/dist/src/agent-runtime/memory-runtime.js.map +1 -0
  319. package/dist/src/agent-runtime/model-router.d.ts +11 -0
  320. package/dist/src/agent-runtime/model-router.js +16 -0
  321. package/dist/src/agent-runtime/model-router.js.map +1 -0
  322. package/dist/src/agent-runtime/run-trace.d.ts +27 -0
  323. package/dist/src/agent-runtime/run-trace.js +53 -0
  324. package/dist/src/agent-runtime/run-trace.js.map +1 -0
  325. package/dist/src/agent-runtime/runtime-profile.d.ts +24 -0
  326. package/dist/src/agent-runtime/runtime-profile.js +44 -0
  327. package/dist/src/agent-runtime/runtime-profile.js.map +1 -0
  328. package/dist/src/agent-runtime/tool-registry.d.ts +28 -0
  329. package/dist/src/agent-runtime/tool-registry.js +52 -0
  330. package/dist/src/agent-runtime/tool-registry.js.map +1 -0
  331. package/dist/src/agent-runtime/workflow-runtime.d.ts +31 -0
  332. package/dist/src/agent-runtime/workflow-runtime.js +34 -0
  333. package/dist/src/agent-runtime/workflow-runtime.js.map +1 -0
  334. package/dist/src/ai-assist/text-assist.js +1 -1
  335. package/dist/src/auth/credentials.js +2 -2
  336. package/dist/src/auth/profiles/store.js +2 -2
  337. package/dist/src/auth/sync-provider-auth.js +1 -1
  338. package/dist/src/browser/actions/extension-registry-bridge.js +1 -1
  339. package/dist/src/browser/actions/extension-registry-bridge.js.map +1 -1
  340. package/dist/src/browser/actions/registry.js +5 -8
  341. package/dist/src/browser/actions/registry.js.map +1 -1
  342. package/dist/src/browser/backend-from-config.d.ts +1 -1
  343. package/dist/src/browser/backend-from-config.js +50 -71
  344. package/dist/src/browser/backend-from-config.js.map +1 -1
  345. package/dist/src/browser/browser-command-timeout.d.ts +0 -1
  346. package/dist/src/browser/browser-command-timeout.js +3 -7
  347. package/dist/src/browser/browser-command-timeout.js.map +1 -1
  348. package/dist/src/browser/cache-dir-policy.js +1 -1
  349. package/dist/src/browser/cdp-local-launcher.js +2 -2
  350. package/dist/src/browser/pipeline/source.js +1 -1
  351. package/dist/src/browser/providers/browser-ext-install.d.ts +2 -12
  352. package/dist/src/browser/providers/browser-ext-install.js +7 -12
  353. package/dist/src/browser/providers/browser-ext-install.js.map +1 -1
  354. package/dist/src/browser/providers/cloakbrowser.js +5 -5
  355. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  356. package/dist/src/browser/readiness.js +16 -16
  357. package/dist/src/browser/readiness.js.map +1 -1
  358. package/dist/src/browser/schemas.js +1 -1
  359. package/dist/src/browser/schemas.js.map +1 -1
  360. package/dist/src/browser/stealth.js +1 -1
  361. package/dist/src/channels/catalog/channel-catalog-service.js +1 -1
  362. package/dist/src/channels/outbound/persist-store.js +1 -1
  363. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  364. package/dist/src/channels/pairing/pairing-store.js +2 -2
  365. package/dist/src/channels/pipeline.d.ts +1 -1
  366. package/dist/src/channels/pipeline.js.map +1 -1
  367. package/dist/src/chat-commands/agent-edit.js +2 -3
  368. package/dist/src/chat-commands/agent-edit.js.map +1 -1
  369. package/dist/src/chat-commands/builtins/config.js +6 -6
  370. package/dist/src/chat-commands/builtins/config.js.map +1 -1
  371. package/dist/src/chat-commands/builtins/model.js +2 -2
  372. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  373. package/dist/src/chat-commands/builtins/thinking.js +16 -42
  374. package/dist/src/chat-commands/builtins/thinking.js.map +1 -1
  375. package/dist/src/chat-commands/config-paths.js +1 -1
  376. package/dist/src/chat-commands/config-paths.js.map +1 -1
  377. package/dist/src/chat-commands/context.js +3 -4
  378. package/dist/src/chat-commands/context.js.map +1 -1
  379. package/dist/src/cli/command-manifest.d.ts +1 -1
  380. package/dist/src/cli/command-manifest.js +2 -2
  381. package/dist/src/cli/command-manifest.js.map +1 -1
  382. package/dist/src/cli/commands/agent.js +3 -1
  383. package/dist/src/cli/commands/agent.js.map +1 -1
  384. package/dist/src/cli/commands/agents.js +3 -6
  385. package/dist/src/cli/commands/agents.js.map +1 -1
  386. package/dist/src/cli/commands/browser-cli-helpers.js +9 -11
  387. package/dist/src/cli/commands/browser-cli-helpers.js.map +1 -1
  388. package/dist/src/cli/commands/config.js +6 -6
  389. package/dist/src/cli/commands/config.js.map +1 -1
  390. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  391. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  392. package/dist/src/cli/commands/doctor/checks/provider-auth.js +3 -18
  393. package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
  394. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  395. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -2
  396. package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -1
  397. package/dist/src/cli/commands/extension-create.js +1 -1
  398. package/dist/src/cli/commands/extension-dev.js +2 -2
  399. package/dist/src/cli/commands/extension-marketplace.js +2 -2
  400. package/dist/src/cli/commands/extension-pack.js +2 -2
  401. package/dist/src/cli/commands/extension.js +3 -3
  402. package/dist/src/cli/commands/gateway/logs.js +1 -1
  403. package/dist/src/cli/commands/goal.js +1 -1
  404. package/dist/src/cli/commands/image.js +13 -372
  405. package/dist/src/cli/commands/image.js.map +1 -1
  406. package/dist/src/cli/commands/init.js +7 -6
  407. package/dist/src/cli/commands/init.js.map +1 -1
  408. package/dist/src/cli/commands/models.js +14 -16
  409. package/dist/src/cli/commands/models.js.map +1 -1
  410. package/dist/src/cli/commands/onboard/channels/registry.js.map +1 -1
  411. package/dist/src/cli/commands/onboard/model.js +28 -23
  412. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  413. package/dist/src/cli/commands/onboard.js +3 -3
  414. package/dist/src/cli/commands/onboard.js.map +1 -1
  415. package/dist/src/cli/commands/skills-test.js +1 -1
  416. package/dist/src/cli/commands/tui.js +2 -2
  417. package/dist/src/cli/commands/tui.js.map +1 -1
  418. package/dist/src/cli/index.d.ts +1 -0
  419. package/dist/src/cli/index.js +10 -5
  420. package/dist/src/cli/index.js.map +1 -1
  421. package/dist/src/cli/registry.js +1 -1
  422. package/dist/src/cli/registry.js.map +1 -1
  423. package/dist/src/cli/templates.d.ts +1 -1
  424. package/dist/src/cli/templates.js +2 -12
  425. package/dist/src/cli/templates.js.map +1 -1
  426. package/dist/src/cli/utils/gateway-client.js +1 -1
  427. package/dist/src/cli/utils/init-workspace-core.d.ts +1 -4
  428. package/dist/src/cli/utils/init-workspace-core.js +9 -8
  429. package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
  430. package/dist/src/commands/agents.config.d.ts +0 -1
  431. package/dist/src/commands/agents.config.js +59 -13
  432. package/dist/src/commands/agents.config.js.map +1 -1
  433. package/dist/src/config/agent-profile.d.ts +5 -17
  434. package/dist/src/config/agent-profile.js +32 -64
  435. package/dist/src/config/agent-profile.js.map +1 -1
  436. package/dist/src/config/agent-typed-models.d.ts +1 -1
  437. package/dist/src/config/agent-typed-models.js +3 -6
  438. package/dist/src/config/agent-typed-models.js.map +1 -1
  439. package/dist/src/config/gateway-bind.js +1 -1
  440. package/dist/src/config/index.js +9 -9
  441. package/dist/src/config/integration.d.ts +1 -1
  442. package/dist/src/config/loader.js +4 -4
  443. package/dist/src/config/models-json.js +2 -2
  444. package/dist/src/config/paths-state.js +1 -1
  445. package/dist/src/config/paths.d.ts +8 -1
  446. package/dist/src/config/paths.js +17 -4
  447. package/dist/src/config/paths.js.map +1 -1
  448. package/dist/src/config/profile.js +1 -1
  449. package/dist/src/config/reload.js +2 -2
  450. package/dist/src/config/reload.js.map +1 -1
  451. package/dist/src/config/rules.js +6 -56
  452. package/dist/src/config/rules.js.map +1 -1
  453. package/dist/src/config/schema.d.ts +916 -779
  454. package/dist/src/config/schema.js +174 -423
  455. package/dist/src/config/schema.js.map +1 -1
  456. package/dist/src/config/workspace-path.js +1 -1
  457. package/dist/src/connectors/composio-triggers.js +1 -1
  458. package/dist/src/cron/executor.js +1 -1
  459. package/dist/src/cron/index.js +1 -1
  460. package/dist/src/cron/service.js +2 -2
  461. package/dist/src/cron/validation.d.ts +3 -3
  462. package/dist/src/daemon/constants.js +1 -1
  463. package/dist/src/daemon/install-plan.js +2 -2
  464. package/dist/src/daemon/launchd.js +2 -2
  465. package/dist/src/daemon/schtasks.js +2 -2
  466. package/dist/src/daemon/systemd.js +2 -2
  467. package/dist/src/extensions/activation-context.js +13 -7
  468. package/dist/src/extensions/activation-context.js.map +1 -1
  469. package/dist/src/extensions/bundle-mcp.js +1 -1
  470. package/dist/src/extensions/discover-extensions.js +2 -2
  471. package/dist/src/extensions/health.js +1 -1
  472. package/dist/src/extensions/install.js +2 -2
  473. package/dist/src/extensions/loader.js +2 -2
  474. package/dist/src/extensions/lockfile.js +3 -3
  475. package/dist/src/extensions/security.js +1 -1
  476. package/dist/src/extensions/update.js +2 -2
  477. package/dist/src/gateway/agents-admin.d.ts +24 -18
  478. package/dist/src/gateway/agents-admin.js +158 -92
  479. package/dist/src/gateway/agents-admin.js.map +1 -1
  480. package/dist/src/gateway/capability-presets-admin.d.ts +56 -0
  481. package/dist/src/gateway/capability-presets-admin.js +214 -0
  482. package/dist/src/gateway/capability-presets-admin.js.map +1 -0
  483. package/dist/src/gateway/chat-stream/mapper.js +9 -2
  484. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  485. package/dist/src/gateway/file-path-classifier.js +2 -2
  486. package/dist/src/gateway/global-defaults-admin.d.ts +36 -0
  487. package/dist/src/gateway/global-defaults-admin.js +146 -0
  488. package/dist/src/gateway/global-defaults-admin.js.map +1 -0
  489. package/dist/src/gateway/hono/lib/agent-model.d.ts +1 -1
  490. package/dist/src/gateway/hono/lib/agent-model.js +1 -1
  491. package/dist/src/gateway/hono/lib/agent-model.js.map +1 -1
  492. package/dist/src/gateway/hono/lib/config-payload.d.ts +234 -127
  493. package/dist/src/gateway/hono/lib/config-payload.js +14 -38
  494. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  495. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  496. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  497. package/dist/src/gateway/hono/routes/agents.js +88 -33
  498. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  499. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  500. package/dist/src/gateway/hono/routes/browser.js +8 -15
  501. package/dist/src/gateway/hono/routes/browser.js.map +1 -1
  502. package/dist/src/gateway/hono/routes/capability-presets.d.ts +3 -0
  503. package/dist/src/gateway/hono/routes/capability-presets.js +145 -0
  504. package/dist/src/gateway/hono/routes/capability-presets.js.map +1 -0
  505. package/dist/src/gateway/hono/routes/commands-skills.js +4 -5
  506. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  507. package/dist/src/gateway/hono/routes/config-patch/agents.d.ts +1 -17
  508. package/dist/src/gateway/hono/routes/config-patch/agents.js +2 -443
  509. package/dist/src/gateway/hono/routes/config-patch/agents.js.map +1 -1
  510. package/dist/src/gateway/hono/routes/config-patch/misc.js +7 -1
  511. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  512. package/dist/src/gateway/hono/routes/config.js +1 -1
  513. package/dist/src/gateway/hono/routes/config.js.map +1 -1
  514. package/dist/src/gateway/hono/routes/dreaming.js +8 -1
  515. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  516. package/dist/src/gateway/hono/routes/global-defaults.d.ts +3 -0
  517. package/dist/src/gateway/hono/routes/global-defaults.js +61 -0
  518. package/dist/src/gateway/hono/routes/global-defaults.js.map +1 -0
  519. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  520. package/dist/src/gateway/hono/routes/index.js +2 -0
  521. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  522. package/dist/src/gateway/hono/routes/lazy-bundles.js +17 -1
  523. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  524. package/dist/src/gateway/hono/routes/memory.d.ts +3 -0
  525. package/dist/src/gateway/hono/routes/memory.js +361 -0
  526. package/dist/src/gateway/hono/routes/memory.js.map +1 -0
  527. package/dist/src/gateway/hono/routes/models.js +2 -2
  528. package/dist/src/gateway/hono/routes/shares.js +1 -1
  529. package/dist/src/gateway/hono/routes/workflows.js +1 -1
  530. package/dist/src/gateway/hono/routes/workspace.js +2 -2
  531. package/dist/src/gateway/lock.js +3 -3
  532. package/dist/src/gateway/ports.js +1 -1
  533. package/dist/src/gateway/service/config-coordinator.js +1 -1
  534. package/dist/src/gateway/service/marketplace-service.d.ts +4 -4
  535. package/dist/src/gateway/service/marketplace-service.js +13 -9
  536. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  537. package/dist/src/gateway/service.d.ts +1 -1
  538. package/dist/src/gateway/service.js +15 -16
  539. package/dist/src/gateway/service.js.map +1 -1
  540. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  541. package/dist/src/goals/goal-workflow-judge.js +2 -2
  542. package/dist/src/i18n/goals-bundle.js +1 -1
  543. package/dist/src/i18n/index.js +1 -1
  544. package/dist/src/i18n/share-tool-bundle.js +2 -2
  545. package/dist/src/infra/brew.js +1 -1
  546. package/dist/src/infra/package-json.js +1 -1
  547. package/dist/src/infra/package-update-steps.js +1 -1
  548. package/dist/src/infra/path-env.js +2 -2
  549. package/dist/src/infra/restart.js +1 -1
  550. package/dist/src/infra/stable-node-path.js +1 -1
  551. package/dist/src/infra/update-check.js +1 -1
  552. package/dist/src/infra/update-global.js +1 -1
  553. package/dist/src/infra/update-lock.js +2 -2
  554. package/dist/src/infra/update-restart.js +1 -1
  555. package/dist/src/infra/update-runner.js +1 -1
  556. package/dist/src/infra/update-startup.js +1 -1
  557. package/dist/src/infra/write-file-atomic.js +2 -2
  558. package/dist/src/media/store.js +1 -1
  559. package/dist/src/notes/agent-context.js +3 -3
  560. package/dist/src/notes/service.js +4 -2
  561. package/dist/src/notes/service.js.map +1 -1
  562. package/dist/src/notes/store.js +2 -2
  563. package/dist/src/project-trust/trust-store.js +2 -2
  564. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  565. package/dist/src/providers/index.d.ts +5 -6
  566. package/dist/src/providers/index.js +26 -30
  567. package/dist/src/providers/index.js.map +1 -1
  568. package/dist/src/providers/model-registry.js +4 -4
  569. package/dist/src/session/index.js +1 -1
  570. package/dist/src/session/init-session-turn.js +1 -1
  571. package/dist/src/session/resolve-session.js +1 -1
  572. package/dist/src/session/session-title.js +2 -2
  573. package/dist/src/session/store.js +1 -1
  574. package/dist/src/session/thinking-resolve.d.ts +1 -1
  575. package/dist/src/session/thinking-resolve.js +1 -1
  576. package/dist/src/session/thinking-resolve.js.map +1 -1
  577. package/dist/src/share/share-auto.js +2 -2
  578. package/dist/src/share/share-store.js +3 -3
  579. package/dist/src/share/share-thumbnail.js +2 -2
  580. package/dist/src/share/share-zip.js +1 -1
  581. package/dist/src/share/site-share-store.js +3 -3
  582. package/dist/src/share/site-static-serve.js +1 -1
  583. package/dist/src/storage/sqlite/connection.js +2 -2
  584. package/dist/src/storage/sqlite/index.d.ts +1 -0
  585. package/dist/src/storage/sqlite/index.js +2 -1
  586. package/dist/src/storage/sqlite/memory-index-repository.d.ts +1 -0
  587. package/dist/src/storage/sqlite/memory-index-repository.js +17 -16
  588. package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -1
  589. package/dist/src/storage/sqlite/memory-records-repository.d.ts +144 -0
  590. package/dist/src/storage/sqlite/memory-records-repository.js +453 -0
  591. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -0
  592. package/dist/src/storage/sqlite/migrations/012_memory_records.sql +63 -0
  593. package/dist/src/storage/sqlite/migrations/013_memory_trace_events.sql +21 -0
  594. package/dist/src/storage/sqlite/migrations/014_memory_record_governance.sql +10 -0
  595. package/dist/src/storage/sqlite/migrations/015_memory_trace_feedback.sql +4 -0
  596. package/dist/src/storage/sqlite/migrations/discover.js +1 -1
  597. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  598. package/dist/src/storage/sqlite/migrations/runner.js +4 -4
  599. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  600. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  601. package/dist/src/storage/sqlite/schema.js +2 -2
  602. package/dist/src/storage/sqlite/schema.sql +86 -0
  603. package/dist/src/tui/backends/embedded-backend.d.ts +3 -0
  604. package/dist/src/tui/backends/embedded-backend.js +43 -24
  605. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  606. package/dist/src/tui/backends/gateway-sse-backend.d.ts +1 -0
  607. package/dist/src/tui/backends/gateway-sse-backend.js +16 -3
  608. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  609. package/dist/src/tui/clipboard-image.js +3 -3
  610. package/dist/src/tui/components/tui-header.d.ts +0 -1
  611. package/dist/src/tui/components/tui-header.js +3 -8
  612. package/dist/src/tui/components/tui-header.js.map +1 -1
  613. package/dist/src/tui/extension-host/load-extensions.js +1 -1
  614. package/dist/src/tui/extension-host/load-extensions.js.map +1 -1
  615. package/dist/src/tui/theme-manager.js +1 -1
  616. package/dist/src/tui/tui-command-formatters.js +4 -4
  617. package/dist/src/tui/tui-commands.js +2 -2
  618. package/dist/src/tui/tui-keybindings-file.js +1 -1
  619. package/dist/src/tui/tui-scoped-models.js +2 -2
  620. package/dist/src/tui/tui-settings.js +1 -1
  621. package/dist/src/tui/tui-startup-resources.js +2 -1
  622. package/dist/src/tui/tui-startup-resources.js.map +1 -1
  623. package/dist/src/tui/tui-startup-text.js +12 -12
  624. package/dist/src/tui/tui-startup-text.js.map +1 -1
  625. package/dist/src/tui/tui.js +10 -7
  626. package/dist/src/tui/tui.js.map +1 -1
  627. package/dist/src/tunnel/frpc-binary.js +4 -4
  628. package/dist/src/tunnel/frpc-config.js +1 -1
  629. package/dist/src/tunnel/frpc-extract.js +1 -1
  630. package/dist/src/tunnel/tunnel-state.js +1 -1
  631. package/dist/src/utils/logger/audit.js +1 -1
  632. package/dist/src/utils/logger/log-store.js +1 -1
  633. package/dist/src/utils/logger/rotation.js +1 -1
  634. package/dist/src/utils/logger/streams.js +1 -1
  635. package/dist/src/voice/tts/audio.js +1 -1
  636. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  637. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  638. package/dist/src/workflows/service/workflow-run-service.js +4 -5
  639. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  640. package/dist/src/workflows/service/workflow-session-bridge.js +1 -1
  641. package/dist/src/workflows/store/event-store.js +1 -1
  642. package/dist/src/workflows/store/run-store.js +1 -1
  643. package/package.json +3 -2
  644. package/dist/gateway/static/root/assets/agent-browser-settings-page-D1SyFYeh.js +0 -6
  645. package/dist/gateway/static/root/assets/agent-defaults-tabbed-page-C9YxgvuI.js +0 -1
  646. package/dist/gateway/static/root/assets/agents-CteVs3UO.js +0 -71
  647. package/dist/gateway/static/root/assets/apps-page-CVQ1M8Ax.js +0 -1
  648. package/dist/gateway/static/root/assets/channels-settings-Cd3JbeQ1.js +0 -1
  649. package/dist/gateway/static/root/assets/config-api-C4RAtTKW.js +0 -3
  650. package/dist/gateway/static/root/assets/connectors-page-MsMa5qBr.js +0 -2
  651. package/dist/gateway/static/root/assets/cron-api-sJNMqB6P.js +0 -1
  652. package/dist/gateway/static/root/assets/cron-page-D30CSwkn.js +0 -3
  653. package/dist/gateway/static/root/assets/dreaming-settings-6fCUWRQf.js +0 -1
  654. package/dist/gateway/static/root/assets/gateway-config-api-C6989a-W.js +0 -1
  655. package/dist/gateway/static/root/assets/gateway-settings-BpF26t91.js +0 -1
  656. package/dist/gateway/static/root/assets/goal-detail-page-DOjhmRyf.js +0 -1
  657. package/dist/gateway/static/root/assets/goals-page-Xl9_wrFc.js +0 -2
  658. package/dist/gateway/static/root/assets/heartbeat-settings-DN9vEj9P.js +0 -1
  659. package/dist/gateway/static/root/assets/index-C8ytlAF2.js +0 -122
  660. package/dist/gateway/static/root/assets/index-CVpJW2NS.css +0 -1
  661. package/dist/gateway/static/root/assets/messages-BqzIDrlr.js +0 -3
  662. package/dist/gateway/static/root/assets/models-hub-panel-BO4o-GmO.js +0 -2
  663. package/dist/gateway/static/root/assets/note-detail-page-DLV_XDmT.js +0 -2
  664. package/dist/gateway/static/root/assets/notes-page-ycsDlkFA.js +0 -1
  665. package/dist/gateway/static/root/assets/remote-access-hub-DQpnE8K9.js +0 -1
  666. package/dist/gateway/static/root/assets/sessions-page-BZui7iAY.js +0 -1
  667. package/dist/gateway/static/root/assets/settings-advanced-gate-DEfzZ1ax.js +0 -1
  668. package/dist/gateway/static/root/assets/settings-page-CLuSsu1-.js +0 -1
  669. package/dist/gateway/static/root/assets/setup-status-panel-Cq4qpXLi.js +0 -1
  670. package/dist/gateway/static/root/assets/shares-settings-B9F3HyYQ.js +0 -1
  671. package/dist/gateway/static/root/assets/skill-reload-api-Bp9UPPwm.js +0 -1
  672. package/dist/gateway/static/root/assets/skills-page-BIoBsfSV.js +0 -2
  673. package/dist/gateway/static/root/assets/use-agent-defaults-form-Cz2_pPzu.js +0 -1
  674. package/dist/gateway/static/root/assets/use-settings-tab-guard-nuHMmZQv.js +0 -1
  675. package/dist/gateway/static/root/assets/voice-api-key-field-BUIrKb8s.js +0 -1
  676. package/dist/gateway/static/root/assets/workflows-page-qE3SexnO.js +0 -18
  677. package/dist/src/agent/context/workspace-templates/USER.md +0 -24
@@ -26,10 +26,10 @@ import { resolveBrowserBackendFromConfig } from "../../browser/backend-from-conf
26
26
  import { checkBrowserReadiness } from "../../browser/readiness.js";
27
27
  import { CdpSupervisor } from "../../browser/cdp-supervisor.js";
28
28
  import "../../browser/index.js";
29
- import { createDelegateTool } from "./delegate-tool.js";
29
+ import "./delegate-tool.js";
30
30
  import { createWorkflowCatalog } from "../workflow/catalog.js";
31
31
  import { createWorkflowTool } from "./workflow-tool.js";
32
- import { buildSandboxToolMap, createExecuteCodeTool } from "./execute-code-tool.js";
32
+ import "./execute-code-tool.js";
33
33
  import { createCronjobTool } from "./cronjob-tool.js";
34
34
  import { createGoalTool } from "./goal-tool.js";
35
35
  import { createSkillViewTool, createSkillsListTool } from "./skills-tools.js";
@@ -53,7 +53,7 @@ const CLARIFY_SUPPORTED_CHANNELS = new Set([
53
53
  "telegram",
54
54
  "cli"
55
55
  ]);
56
- var AgentToolsFactory = class AgentToolsFactory {
56
+ var AgentToolsFactory = class {
57
57
  browserManager = null;
58
58
  /** One dialog/console supervisor per chat session (browser tab). */
59
59
  browserTaskSupervisors = /* @__PURE__ */ new Map();
@@ -65,9 +65,8 @@ var AgentToolsFactory = class AgentToolsFactory {
65
65
  browserReadinessKey() {
66
66
  const cfg = this.deps.getConfig?.();
67
67
  const backend = resolveBrowserBackendFromConfig(cfg);
68
- const ext = cfg?.agents?.defaults?.browser?.extension;
69
- const host = typeof ext?.host === "string" && ext.host.trim() ? ext.host.trim() : "127.0.0.1";
70
- const port = typeof ext?.port === "number" ? ext.port : 19820;
68
+ const host = "127.0.0.1";
69
+ const port = 19820;
71
70
  const cdpUrl = backend.mode === "cdp" ? backend.config.wsEndpoint : "";
72
71
  const cloudKind = backend.mode === "cloud" ? backend.config.type : "";
73
72
  return `${backend.mode}@${host}:${port}|${cdpUrl}|${cloudKind}`;
@@ -105,10 +104,9 @@ var AgentToolsFactory = class AgentToolsFactory {
105
104
  browserSupervisorForTask(taskId) {
106
105
  let s = this.browserTaskSupervisors.get(taskId);
107
106
  if (!s) {
108
- const b = this.deps.getConfig?.()?.agents?.defaults?.browser;
109
107
  s = new CdpSupervisor({
110
- dialogPolicy: b?.dialogPolicy === "must_respond" || b?.dialogPolicy === "auto_accept" || b?.dialogPolicy === "auto_dismiss" ? b.dialogPolicy : "auto_dismiss",
111
- dialogTimeoutSeconds: typeof b?.dialogTimeoutSeconds === "number" && Number.isFinite(b.dialogTimeoutSeconds) && b.dialogTimeoutSeconds >= 1 ? Math.floor(b.dialogTimeoutSeconds) : 300
108
+ dialogPolicy: "auto_dismiss",
109
+ dialogTimeoutSeconds: 300
112
110
  });
113
111
  this.browserTaskSupervisors.set(taskId, s);
114
112
  }
@@ -125,7 +123,7 @@ var AgentToolsFactory = class AgentToolsFactory {
125
123
  }
126
124
  ensureBrowserManager() {
127
125
  if (!this.browserManager) this.browserManager = new BrowserManager({
128
- getHeadless: () => this.deps.getConfig?.()?.agents?.defaults?.browser?.headless === true,
126
+ getHeadless: () => false,
129
127
  getBackend: () => resolveBrowserBackendFromConfig(this.deps.getConfig?.())
130
128
  });
131
129
  return this.browserManager;
@@ -147,14 +145,13 @@ var AgentToolsFactory = class AgentToolsFactory {
147
145
  const workspace = options?.workspace ?? this.deps.workspace;
148
146
  const { bus } = this.deps;
149
147
  const getPrimary = options?.getPrimaryModel ?? this.deps.getPrimaryModel;
150
- const getBuiltin = options?.getBuiltinMemoryStore ?? this.deps.getBuiltinMemoryStore;
151
- const memoriesDir = (getBuiltin?.())?.memoriesDir;
152
148
  const getMemMgr = options?.getMemoryManager ?? this.deps.getMemoryManager;
153
149
  const getSkillMgr = options?.getSkillManager;
154
150
  const disabled = options?.disabledTools;
155
151
  const primary = getPrimary?.();
156
152
  const modelHasVision = primary?.input?.includes("image") ?? false;
157
153
  const cfg = this.deps.getConfig?.();
154
+ const browserEnabled = cfg?.browser?.enabled !== false;
158
155
  const recordGoalEvidence = createGoalEvidenceRecorder({ getSessionKey: () => this.deps.getCurrentContext()?.sessionKey });
159
156
  const optionalTools = [
160
157
  createImageTool({
@@ -237,17 +234,14 @@ var AgentToolsFactory = class AgentToolsFactory {
237
234
  workspace,
238
235
  getConfig: () => this.deps.getConfig?.()
239
236
  })] : [],
240
- createMemorySearchTool({
237
+ ...getMemMgr ? [createMemorySearchTool({
241
238
  workspaceDir: workspace,
242
- memoriesDir
243
- }),
244
- createMemoryGetTool({
239
+ getMemoryManager: () => getMemMgr()
240
+ }), createMemoryGetTool({
245
241
  workspaceDir: workspace,
246
- memoriesDir
247
- }),
248
- ...getBuiltin && shouldRegisterCuratedMemoryTool(this.deps.getConfig?.()) ? [createCuratedMemoryTool(getBuiltin, { onMemoryWrite: (action, target, content) => {
249
- getMemMgr?.().onMemoryWrite(action, target, content);
250
- } })] : [],
242
+ getMemoryManager: () => getMemMgr()
243
+ })] : [],
244
+ ...getMemMgr && shouldRegisterCuratedMemoryTool(this.deps.getConfig?.()) ? [createCuratedMemoryTool(() => getMemMgr())] : [],
251
245
  ...getMemMgr?.().getAdditionalTools() ?? [],
252
246
  ...this.deps.getSessionStore ? [createSessionSearchTool({
253
247
  getSessionStore: this.deps.getSessionStore,
@@ -256,7 +250,7 @@ var AgentToolsFactory = class AgentToolsFactory {
256
250
  })] : [],
257
251
  ...this.deps.getCronService ? [createCronjobTool({ getCronService: this.deps.getCronService })] : [],
258
252
  createGoalTool(),
259
- ...cfg?.agents?.defaults?.browser?.enabled !== false ? [createBrowserUseTool({
253
+ ...browserEnabled ? [createBrowserUseTool({
260
254
  getManager: () => this.ensureBrowserManager(),
261
255
  getPageForTask: () => this.acquireBrowserPage(),
262
256
  getTaskId: () => this.deps.getCurrentContext()?.sessionKey ?? "default",
@@ -267,46 +261,19 @@ var AgentToolsFactory = class AgentToolsFactory {
267
261
  this.browserTaskSupervisors.delete(taskId);
268
262
  }
269
263
  })] : [],
270
- ...cfg?.agents?.defaults?.workflow?.enabled !== false && primary ? [createWorkflowTool({
264
+ ...primary ? [createWorkflowTool({
271
265
  catalog: createWorkflowCatalog(),
272
266
  getCurrentSessionKey: () => this.deps.getCurrentContext()?.sessionKey,
273
267
  getConfig: () => this.deps.getConfig?.(),
274
268
  startWorkflowRun: this.deps.getWorkflowRunService ? (params) => this.deps.getWorkflowRunService().startWorkflowRun(params) : void 0
275
269
  })] : [],
276
- ...cfg?.agents?.defaults?.delegate?.enabled === true && primary ? [createDelegateTool({
277
- workspace,
278
- getSubagentModel: () => {
279
- const m = (options?.getPrimaryModel ?? this.deps.getPrimaryModel)?.();
280
- if (!m) throw new Error("No primary model configured for delegate_task");
281
- return m;
282
- },
283
- bus: this.deps.bus,
284
- getConfig: () => this.deps.getConfig?.(),
285
- getCurrentContext: () => this.deps.getCurrentContext?.() ?? null,
286
- hookRunner: this.deps.hookRunner,
287
- toolExecutorConfig: this.deps.toolExecutorConfig,
288
- buildChildTools: (childOpts) => {
289
- return new AgentToolsFactory({
290
- workspace: childOpts.workspace,
291
- bus: childOpts.bus,
292
- getCurrentContext: () => null,
293
- getConfig: childOpts.getConfig,
294
- getPrimaryModel: () => childOpts.model,
295
- toolExecutorConfig: childOpts.toolExecutorConfig
296
- }).createAllTools({
297
- workspace: childOpts.workspace,
298
- getPrimaryModel: () => childOpts.model,
299
- disabledTools: new Set(["extensions"])
300
- });
301
- }
302
- })] : [],
270
+ ...[],
303
271
  ...optionalTools
304
272
  ], disabled);
305
273
  }
306
274
  createAllTools(coreOptions) {
307
275
  const coreTools = this.createCoreTools(coreOptions);
308
276
  const disableExtensions = coreOptions?.disabledTools?.has("extensions");
309
- const cfg = this.deps.getConfig?.();
310
277
  let bundled;
311
278
  if (!this.deps.extensionRegistry || disableExtensions) bundled = coreTools;
312
279
  else {
@@ -314,13 +281,7 @@ var AgentToolsFactory = class AgentToolsFactory {
314
281
  log.info({ count: extensionTools.length }, "Loaded extension tools");
315
282
  bundled = [...coreTools, ...extensionTools];
316
283
  }
317
- const wrapped = wrapToolsWithProtection(bundled, this.deps.toolExecutorConfig);
318
- if (cfg?.agents?.defaults?.executeCode?.enabled === true && !coreOptions?.disabledTools?.has("execute_code")) {
319
- const sandboxMap = buildSandboxToolMap(wrapped);
320
- const wrappedExecute = wrapToolsWithProtection([createExecuteCodeTool({ getSandboxToolMap: () => sandboxMap })], this.deps.toolExecutorConfig);
321
- return [...wrapped, ...wrappedExecute];
322
- }
323
- return wrapped;
284
+ return wrapToolsWithProtection(bundled, this.deps.toolExecutorConfig);
324
285
  }
325
286
  };
326
287
  function filterToolsByDisabledSet(tools, disabled) {
@@ -1 +1 @@
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 createComposioExecuteTool,\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 composioTool = createComposioExecuteTool(() => this.deps.getConfig?.());\n const optionalTools = [imageTool, imageGenerateTool, composioTool].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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"}
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 createComposioExecuteTool,\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 { 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 /** 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 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 host = '127.0.0.1';\n const 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 s = new CdpSupervisor({ dialogPolicy: 'auto_dismiss', dialogTimeoutSeconds: 300 });\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: () => false,\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 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 browserEnabled = cfg?.browser?.enabled !== false;\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 composioTool = createComposioExecuteTool(() => this.deps.getConfig?.());\n const optionalTools = [imageTool, imageGenerateTool, composioTool].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 ...(getMemMgr\n ? [\n createMemorySearchTool({ workspaceDir: workspace, getMemoryManager: () => getMemMgr() }),\n createMemoryGetTool({ workspaceDir: workspace, getMemoryManager: () => getMemMgr() }),\n ]\n : []),\n ...(getMemMgr && shouldRegisterCuratedMemoryTool(this.deps.getConfig?.())\n ? [\n createCuratedMemoryTool(() => getMemMgr()),\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 ...(browserEnabled\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 ...(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 ...(false && 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\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 = false && !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,7 +1,7 @@
1
1
  import { DEFAULT_MAX_BYTES, formatSize, truncateHead } from "./truncate.js";
2
2
  import { resolveToCwd } from "../../utils/helpers.js";
3
- import { existsSync } from "fs";
4
3
  import path from "path";
4
+ import { existsSync } from "fs";
5
5
  import { Type } from "@sinclair/typebox";
6
6
  import { globSync } from "glob";
7
7
  //#region src/agent/tools/find.ts
@@ -1,7 +1,7 @@
1
1
  import { DEFAULT_MAX_BYTES, formatSize, truncateHead, truncateLine } from "./truncate.js";
2
2
  import { resolveToCwd } from "../../utils/helpers.js";
3
- import { existsSync, readFileSync, statSync } from "fs";
4
3
  import path from "path";
4
+ import { existsSync, readFileSync, statSync } from "fs";
5
5
  import { Type } from "@sinclair/typebox";
6
6
  import { globSync } from "glob";
7
7
  //#region src/agent/tools/grep.ts
@@ -1,7 +1,7 @@
1
1
  import type { AgentTool } from '@earendil-works/pi-agent-core';
2
2
  import type { Config } from '../../config/schema.js';
3
3
  import { parseImageDataUrl } from '../image/generation/image-assets.js';
4
- import { type ToolModelConfig } from '../image/tool-model-config.js';
4
+ import type { ToolModelConfig } from '../image/tool-model-config.js';
5
5
  export { parseImageDataUrl };
6
6
  export declare function resolveImageGenerationModelConfigForTool(params: {
7
7
  cfg?: Config;
@@ -1,12 +1,11 @@
1
- import { buildToolModelConfigFromCandidates, coerceToolModelConfig, hasToolModelConfig } from "../image/tool-model-config.js";
2
1
  import { applyImageGenerationModelConfigDefaults } from "../image/image-helpers.js";
3
2
  import { isFailoverError } from "../failover-error.js";
4
3
  import { imageAssetFromDataUrl, imageFileExtensionForMimeType, mimeTypeFromFileName, parseImageDataUrl, sniffImageMimeType } from "../image/generation/image-assets.js";
5
4
  import { getImageGenerationProvider } from "../image/generation/provider-registry.js";
6
5
  import { generateImage, listImageGenerationProvidersSummary } from "../image/generation/runtime.js";
6
+ import path from "node:path";
7
7
  import { randomBytes } from "node:crypto";
8
8
  import { mkdir, readFile, writeFile } from "node:fs/promises";
9
- import path from "node:path";
10
9
  import { Type } from "@sinclair/typebox";
11
10
  //#region src/agent/tools/image-generate-tool.ts
12
11
  const DEFAULT_COUNT = 1;
@@ -124,19 +123,24 @@ async function loadInputImages(params) {
124
123
  return out;
125
124
  }
126
125
  function resolveImageGenerationModelConfigForTool(params) {
127
- const explicit = coerceToolModelConfig(params.cfg?.agents?.defaults?.imageGenerationModel);
128
- if (hasToolModelConfig(explicit)) return explicit;
129
- return buildToolModelConfigFromCandidates({
130
- explicit,
131
- candidates: listImageGenerationProvidersSummary(params.cfg).filter((p) => {
132
- const provider = getImageGenerationProvider(p.id, params.cfg);
133
- try {
134
- return provider?.isConfigured?.({ cfg: params.cfg }) ?? false;
135
- } catch {
136
- return false;
137
- }
138
- }).map((p) => `${p.id}/${p.defaultModel ?? p.models[0] ?? ""}`).filter((s) => /^[a-z0-9-]+\/.+/.test(s))
139
- });
126
+ const providers = listImageGenerationProvidersSummary(params.cfg);
127
+ const candidates = [];
128
+ for (const providerSummary of providers) {
129
+ const provider = getImageGenerationProvider(providerSummary.id, params.cfg);
130
+ let configured = false;
131
+ try {
132
+ configured = provider?.isConfigured?.({ cfg: params.cfg }) ?? false;
133
+ } catch {
134
+ configured = false;
135
+ }
136
+ const modelRef = `${providerSummary.id}/${providerSummary.defaultModel ?? providerSummary.models[0] ?? ""}`;
137
+ if (configured && /^[a-z0-9-]+\/.+/.test(modelRef) && !candidates.includes(modelRef)) candidates.push(modelRef);
138
+ }
139
+ if (candidates.length === 0) return null;
140
+ return {
141
+ primary: candidates[0],
142
+ ...candidates.length > 1 ? { fallbacks: candidates.slice(1) } : {}
143
+ };
140
144
  }
141
145
  async function saveGeneratedImages(params) {
142
146
  const dir = path.join(params.workspace, "media", "generated");
@@ -220,6 +224,7 @@ function createImageGenerateTool(options) {
220
224
  try {
221
225
  const result = await generateImage({
222
226
  cfg: effectiveCfg,
227
+ modelConfig: imageGenerationModelConfig,
223
228
  prompt,
224
229
  ...modelOverride ? { modelOverride } : {},
225
230
  count,
@@ -1 +1 @@
1
- {"version":3,"file":"image-generate-tool.js","names":[],"sources":["../../../../src/agent/tools/image-generate-tool.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { Config } from '../../config/schema.js';\nimport { isFailoverError } from '../failover-error.js';\nimport {\n imageAssetFromDataUrl,\n imageFileExtensionForMimeType,\n mimeTypeFromFileName,\n parseImageDataUrl,\n sniffImageMimeType,\n} from '../image/generation/image-assets.js';\nimport {\n generateImage,\n listImageGenerationProvidersSummary,\n} from '../image/generation/runtime.js';\nimport { getImageGenerationProvider } from '../image/generation/provider-registry.js';\nimport type {\n ImageGenerationBackground,\n ImageGenerationOutputFormat,\n ImageGenerationProviderOptions,\n ImageGenerationQuality,\n ImageGenerationResolution,\n ImageGenerationSourceImage,\n} from '../image/generation/types.js';\nimport { applyImageGenerationModelConfigDefaults } from '../image/image-helpers.js';\nimport {\n buildToolModelConfigFromCandidates,\n coerceToolModelConfig,\n hasToolModelConfig,\n type ToolModelConfig,\n} from '../image/tool-model-config.js';\n\nconst DEFAULT_COUNT = 1;\nconst MAX_COUNT = 9;\nconst ALLOWED_QUALITIES: ImageGenerationQuality[] = ['low', 'medium', 'high', 'auto'];\nconst ALLOWED_OUTPUT_FORMATS: ImageGenerationOutputFormat[] = ['png', 'jpeg', 'webp'];\nconst ALLOWED_BACKGROUNDS: ImageGenerationBackground[] = ['transparent', 'opaque', 'auto'];\nconst ALLOWED_RESOLUTIONS: ImageGenerationResolution[] = ['1K', '2K', '4K'];\n\nconst ImageGenerateToolSchema = Type.Object({\n action: Type.Optional(\n Type.String({\n description: 'Optional: \"generate\" (default) or \"list\" available image-generation providers.',\n }),\n ),\n prompt: Type.Optional(Type.String({ description: 'Image generation prompt.' })),\n model: Type.Optional(\n Type.String({\n description:\n 'Optional provider/model override, e.g. openai/gpt-image-1 / dashscope/wan2.7-image-pro / minimax/image-01.',\n }),\n ),\n filename: Type.Optional(Type.String({ description: 'Optional basename hint for saved files.' })),\n size: Type.Optional(Type.String({ description: 'Optional pixel size, e.g. 1024x1024.' })),\n aspectRatio: Type.Optional(\n Type.String({ description: 'Optional aspect ratio, e.g. 16:9 / 9:16 / 1:1.' }),\n ),\n resolution: Type.Optional(\n Type.String({\n description: 'Optional resolution tier: 1K / 2K / 4K (provider-dependent).',\n }),\n ),\n count: Type.Optional(\n Type.Number({ minimum: 1, maximum: MAX_COUNT, description: `Number of images (1–${MAX_COUNT}).` }),\n ),\n quality: Type.Optional(\n Type.String({ description: 'Optional quality: low / medium / high / auto.' }),\n ),\n outputFormat: Type.Optional(\n Type.String({ description: 'Optional output format: png / jpeg / webp.' }),\n ),\n background: Type.Optional(\n Type.String({ description: 'Optional background: transparent / opaque / auto.' }),\n ),\n inputImages: Type.Optional(\n Type.Array(\n Type.Object({\n source: Type.String({\n description: 'Workspace-relative file path or `data:image/...;base64,...` URL.',\n }),\n }),\n { description: 'Reference images for edit mode (provider must support edit).' },\n ),\n ),\n providerOptions: Type.Optional(\n Type.Object({\n openai: Type.Optional(\n Type.Object({\n moderation: Type.Optional(Type.String()),\n outputCompression: Type.Optional(Type.Number()),\n user: Type.Optional(Type.String()),\n }),\n ),\n }),\n ),\n});\n\nfunction readStringParam(args: Record<string, unknown>, key: string): string | undefined {\n const v = args[key];\n return typeof v === 'string' && v.trim() ? v.trim() : undefined;\n}\n\nfunction readEnumParam<T extends string>(\n args: Record<string, unknown>,\n key: string,\n allowed: ReadonlyArray<T>,\n): T | undefined {\n const raw = readStringParam(args, key);\n if (!raw) return undefined;\n const lower = raw.toLowerCase() as T;\n return allowed.includes(lower) ? lower : undefined;\n}\n\nfunction readResolutionParam(args: Record<string, unknown>): ImageGenerationResolution | undefined {\n const raw = readStringParam(args, 'resolution');\n if (!raw) return undefined;\n const upper = raw.toUpperCase();\n return (ALLOWED_RESOLUTIONS as ReadonlyArray<string>).includes(upper)\n ? (upper as ImageGenerationResolution)\n : undefined;\n}\n\nfunction readProviderOptions(args: Record<string, unknown>): ImageGenerationProviderOptions | undefined {\n const raw = args.providerOptions;\n if (!raw || typeof raw !== 'object') return undefined;\n const out: ImageGenerationProviderOptions = {};\n const oa = (raw as Record<string, unknown>).openai;\n if (oa && typeof oa === 'object') {\n const oaRec = oa as Record<string, unknown>;\n const moderation = typeof oaRec.moderation === 'string' ? oaRec.moderation.toLowerCase() : undefined;\n const outputCompression =\n typeof oaRec.outputCompression === 'number' && Number.isFinite(oaRec.outputCompression)\n ? oaRec.outputCompression\n : undefined;\n const user = typeof oaRec.user === 'string' && oaRec.user.trim() ? oaRec.user.trim() : undefined;\n out.openai = {\n ...(moderation === 'low' || moderation === 'auto' ? { moderation: moderation as 'low' | 'auto' } : {}),\n ...(outputCompression !== undefined ? { outputCompression } : {}),\n ...(user ? { user } : {}),\n };\n if (Object.keys(out.openai).length === 0) delete out.openai;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nclass ToolInputError extends Error {}\n\nasync function loadInputImages(params: {\n workspace: string;\n sources: ReadonlyArray<{ source: string }>;\n}): Promise<ImageGenerationSourceImage[]> {\n if (!params.sources?.length) return [];\n const out: ImageGenerationSourceImage[] = [];\n const workspaceAbs = path.resolve(params.workspace);\n for (const entry of params.sources) {\n const source = entry?.source;\n if (typeof source !== 'string' || !source.trim()) {\n throw new ToolInputError('inputImages[].source is required.');\n }\n const trimmed = source.trim();\n if (/^data:image\\//i.test(trimmed)) {\n const parsed = imageAssetFromDataUrl(trimmed);\n if (!parsed) throw new ToolInputError('Invalid data URL in inputImages[].source.');\n out.push(parsed);\n continue;\n }\n if (/^https?:\\/\\//i.test(trimmed)) {\n throw new ToolInputError('Sandboxed image_generate does not allow remote URLs.');\n }\n const resolved = path.resolve(workspaceAbs, trimmed);\n if (resolved !== workspaceAbs && !resolved.startsWith(workspaceAbs + path.sep)) {\n throw new ToolInputError('inputImages[].source escapes workspace.');\n }\n let buffer: Buffer;\n try {\n buffer = await readFile(resolved);\n } catch (e) {\n const em = e instanceof Error ? e.message : String(e);\n throw new ToolInputError(`inputImages[].source not readable: ${em}`);\n }\n const mimeType = mimeTypeFromFileName(resolved) ?? sniffImageMimeType(buffer).mimeType;\n out.push({ buffer, mimeType, fileName: path.basename(resolved) });\n }\n return out;\n}\n\n// Re-exported for callers / tests; no behavioural change vs imported helper.\nexport { parseImageDataUrl };\n\nexport function resolveImageGenerationModelConfigForTool(params: { cfg?: Config }): ToolModelConfig | null {\n const explicit = coerceToolModelConfig(params.cfg?.agents?.defaults?.imageGenerationModel);\n if (hasToolModelConfig(explicit)) {\n return explicit;\n }\n // Step 2: tool default = enumerate every provider whose isConfigured() is true,\n // ordered as registered. No more hard-coded openai/dashscope fallback.\n const providers = listImageGenerationProvidersSummary(params.cfg);\n const candidates = providers\n .filter((p) => {\n const provider = getImageGenerationProvider(p.id, params.cfg);\n try {\n return provider?.isConfigured?.({ cfg: params.cfg }) ?? false;\n } catch {\n return false;\n }\n })\n .map((p) => `${p.id}/${p.defaultModel ?? p.models[0] ?? ''}`)\n .filter((s) => /^[a-z0-9-]+\\/.+/.test(s));\n\n return buildToolModelConfigFromCandidates({ explicit, candidates });\n}\n\nasync function saveGeneratedImages(params: {\n workspace: string;\n images: Array<{ buffer: Buffer; mimeType: string; fileName?: string }>;\n filenameHint?: string;\n}): Promise<string[]> {\n const dir = path.join(params.workspace, 'media', 'generated');\n await mkdir(dir, { recursive: true });\n const out: string[] = [];\n const random = randomBytes(4).toString('hex');\n let i = 0;\n for (const img of params.images) {\n i += 1;\n const ext = imageFileExtensionForMimeType(img.mimeType);\n const base = (params.filenameHint?.replace(/[^\\w.-]/g, '') || 'image') + `-${random}`;\n const name = `${base}-${i}.${ext}`;\n const full = path.join(dir, name);\n await writeFile(full, img.buffer);\n out.push(full);\n }\n return out;\n}\n\nexport function createImageGenerateTool(options: {\n config?: Config;\n workspace: string;\n}): AgentTool<any, Record<string, unknown>> | null {\n const imageGenerationModelConfig = resolveImageGenerationModelConfigForTool({ cfg: options.config });\n if (!imageGenerationModelConfig) {\n return null;\n }\n\n const effectiveCfg =\n applyImageGenerationModelConfigDefaults(options.config, imageGenerationModelConfig) ??\n options.config;\n\n return {\n name: 'image_generate',\n label: 'Image Generation',\n description:\n 'Generate images with the configured image-generation model (default OpenAI). Use action=\"list\" to see providers. Saves files under workspace/media/generated/.',\n parameters: ImageGenerateToolSchema,\n async execute(\n _toolCallId: string,\n args: Record<string, unknown>,\n ): Promise<AgentToolResult<Record<string, unknown>>> {\n const params = args as Record<string, unknown>;\n const action = (readStringParam(params, 'action') || 'generate').toLowerCase();\n if (action === 'list') {\n const providers = listImageGenerationProvidersSummary(effectiveCfg);\n const lines = providers.flatMap((p) => [\n `${p.id}${p.defaultModel ? ` (default ${p.defaultModel})` : ''}`,\n ` models: ${p.models.join(', ')}`,\n ]);\n return {\n content: [{ type: 'text', text: lines.join('\\n') }],\n details: { providers },\n };\n }\n if (action !== 'generate') {\n return {\n content: [{ type: 'text', text: 'action must be \"generate\" or \"list\".' }],\n details: { error: 'bad_action' },\n };\n }\n\n const prompt = readStringParam(params, 'prompt');\n if (!prompt) {\n return {\n content: [{ type: 'text', text: 'prompt is required for image generation.' }],\n details: { error: 'missing_prompt' },\n };\n }\n\n const modelOverride = readStringParam(params, 'model');\n const filename = readStringParam(params, 'filename');\n const size = readStringParam(params, 'size');\n const aspectRatio = readStringParam(params, 'aspectRatio');\n const resolution = readResolutionParam(params);\n const quality = readEnumParam(params, 'quality', ALLOWED_QUALITIES);\n const outputFormat = readEnumParam(params, 'outputFormat', ALLOWED_OUTPUT_FORMATS);\n const background = readEnumParam(params, 'background', ALLOWED_BACKGROUNDS);\n const providerOptions = readProviderOptions(params);\n\n const countRaw = params.count;\n const count =\n typeof countRaw === 'number' && Number.isFinite(countRaw)\n ? Math.min(MAX_COUNT, Math.max(1, Math.floor(countRaw)))\n : DEFAULT_COUNT;\n\n let inputImages: ImageGenerationSourceImage[] = [];\n try {\n inputImages = await loadInputImages({\n workspace: options.workspace,\n sources: (params.inputImages as Array<{ source: string }>) ?? [],\n });\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n content: [{ type: 'text', text: `Image generation failed: ${msg}` }],\n details: {\n error: e instanceof ToolInputError ? 'invalid_input_images' : 'generation_failed',\n },\n };\n }\n\n try {\n const result = await generateImage({\n cfg: effectiveCfg,\n prompt,\n ...(modelOverride ? { modelOverride } : {}),\n count,\n ...(size ? { size } : {}),\n ...(aspectRatio ? { aspectRatio } : {}),\n ...(resolution ? { resolution } : {}),\n ...(quality ? { quality } : {}),\n ...(outputFormat ? { outputFormat } : {}),\n ...(background ? { background } : {}),\n ...(inputImages.length > 0 ? { inputImages } : {}),\n ...(providerOptions ? { providerOptions } : {}),\n });\n\n const paths = await saveGeneratedImages({\n workspace: options.workspace,\n images: result.images,\n ...(filename ? { filenameHint: filename } : {}),\n });\n\n const workspaceRelativePaths = paths.map((p) =>\n path.relative(options.workspace, p).split(path.sep).join('/'),\n );\n\n const lines: string[] = [\n `Generated ${paths.length} image(s) with ${result.provider}/${result.model}.`,\n ...paths.map((p) => `Saved: ${p}`),\n ];\n for (const note of buildNormalizationNotes(result.normalization, result.ignoredOverrides)) {\n lines.push(note);\n }\n\n return {\n content: [{ type: 'text', text: lines.join('\\n') }],\n details: {\n provider: result.provider,\n model: result.model,\n paths,\n workspaceRelativePaths,\n attempts: result.attempts,\n ...(result.normalization ? { normalization: result.normalization } : {}),\n ...(result.ignoredOverrides.length > 0\n ? { ignoredOverrides: result.ignoredOverrides }\n : {}),\n ...(result.metadata ? { metadata: result.metadata } : {}),\n },\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n const failoverFields = isFailoverError(e)\n ? {\n ...(e.reason !== undefined ? { reason: e.reason } : {}),\n ...(e.status !== undefined ? { status: e.status } : {}),\n ...(e.code !== undefined ? { code: e.code } : {}),\n ...(e.provider !== undefined ? { provider: e.provider } : {}),\n ...(e.model !== undefined ? { model: e.model } : {}),\n attempts: e.attempts,\n }\n : {};\n return {\n content: [{ type: 'text', text: `Image generation failed: ${msg}` }],\n details: { error: 'generation_failed', ...failoverFields },\n };\n }\n },\n } as any;\n}\n\nfunction buildNormalizationNotes(\n normalization: import('../image/generation/types.js').ImageGenerationNormalization | undefined,\n ignoredOverrides: ReadonlyArray<import('../image/generation/types.js').ImageGenerationIgnoredOverride>,\n): string[] {\n const notes: string[] = [];\n if (normalization) {\n for (const [key, entry] of Object.entries(normalization)) {\n if (!entry) continue;\n const requested = entry.requested;\n const applied = entry.applied;\n if (requested !== undefined && applied !== undefined && requested !== applied) {\n notes.push(`Note: requested ${key}=\"${requested}\" → applied \"${applied}\".`);\n } else if (applied !== undefined && entry.derivedFrom) {\n notes.push(`Note: ${key}=\"${applied}\" derived from ${entry.derivedFrom}.`);\n }\n }\n }\n for (const ig of ignoredOverrides) {\n notes.push(`Note: ignored ${ig.key}=\"${ig.value}\" (not supported by provider).`);\n }\n return notes;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"image-generate-tool.js","names":[],"sources":["../../../../src/agent/tools/image-generate-tool.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { Config } from '../../config/schema.js';\nimport { isFailoverError } from '../failover-error.js';\nimport {\n imageAssetFromDataUrl,\n imageFileExtensionForMimeType,\n mimeTypeFromFileName,\n parseImageDataUrl,\n sniffImageMimeType,\n} from '../image/generation/image-assets.js';\nimport {\n generateImage,\n listImageGenerationProvidersSummary,\n} from '../image/generation/runtime.js';\nimport { getImageGenerationProvider } from '../image/generation/provider-registry.js';\nimport type {\n ImageGenerationBackground,\n ImageGenerationOutputFormat,\n ImageGenerationProviderOptions,\n ImageGenerationQuality,\n ImageGenerationResolution,\n ImageGenerationSourceImage,\n} from '../image/generation/types.js';\nimport { applyImageGenerationModelConfigDefaults } from '../image/image-helpers.js';\nimport type { ToolModelConfig } from '../image/tool-model-config.js';\n\nconst DEFAULT_COUNT = 1;\nconst MAX_COUNT = 9;\nconst ALLOWED_QUALITIES: ImageGenerationQuality[] = ['low', 'medium', 'high', 'auto'];\nconst ALLOWED_OUTPUT_FORMATS: ImageGenerationOutputFormat[] = ['png', 'jpeg', 'webp'];\nconst ALLOWED_BACKGROUNDS: ImageGenerationBackground[] = ['transparent', 'opaque', 'auto'];\nconst ALLOWED_RESOLUTIONS: ImageGenerationResolution[] = ['1K', '2K', '4K'];\n\nconst ImageGenerateToolSchema = Type.Object({\n action: Type.Optional(\n Type.String({\n description: 'Optional: \"generate\" (default) or \"list\" available image-generation providers.',\n }),\n ),\n prompt: Type.Optional(Type.String({ description: 'Image generation prompt.' })),\n model: Type.Optional(\n Type.String({\n description:\n 'Optional provider/model override, e.g. openai/gpt-image-1 / dashscope/wan2.7-image-pro / minimax/image-01.',\n }),\n ),\n filename: Type.Optional(Type.String({ description: 'Optional basename hint for saved files.' })),\n size: Type.Optional(Type.String({ description: 'Optional pixel size, e.g. 1024x1024.' })),\n aspectRatio: Type.Optional(\n Type.String({ description: 'Optional aspect ratio, e.g. 16:9 / 9:16 / 1:1.' }),\n ),\n resolution: Type.Optional(\n Type.String({\n description: 'Optional resolution tier: 1K / 2K / 4K (provider-dependent).',\n }),\n ),\n count: Type.Optional(\n Type.Number({ minimum: 1, maximum: MAX_COUNT, description: `Number of images (1–${MAX_COUNT}).` }),\n ),\n quality: Type.Optional(\n Type.String({ description: 'Optional quality: low / medium / high / auto.' }),\n ),\n outputFormat: Type.Optional(\n Type.String({ description: 'Optional output format: png / jpeg / webp.' }),\n ),\n background: Type.Optional(\n Type.String({ description: 'Optional background: transparent / opaque / auto.' }),\n ),\n inputImages: Type.Optional(\n Type.Array(\n Type.Object({\n source: Type.String({\n description: 'Workspace-relative file path or `data:image/...;base64,...` URL.',\n }),\n }),\n { description: 'Reference images for edit mode (provider must support edit).' },\n ),\n ),\n providerOptions: Type.Optional(\n Type.Object({\n openai: Type.Optional(\n Type.Object({\n moderation: Type.Optional(Type.String()),\n outputCompression: Type.Optional(Type.Number()),\n user: Type.Optional(Type.String()),\n }),\n ),\n }),\n ),\n});\n\nfunction readStringParam(args: Record<string, unknown>, key: string): string | undefined {\n const v = args[key];\n return typeof v === 'string' && v.trim() ? v.trim() : undefined;\n}\n\nfunction readEnumParam<T extends string>(\n args: Record<string, unknown>,\n key: string,\n allowed: ReadonlyArray<T>,\n): T | undefined {\n const raw = readStringParam(args, key);\n if (!raw) return undefined;\n const lower = raw.toLowerCase() as T;\n return allowed.includes(lower) ? lower : undefined;\n}\n\nfunction readResolutionParam(args: Record<string, unknown>): ImageGenerationResolution | undefined {\n const raw = readStringParam(args, 'resolution');\n if (!raw) return undefined;\n const upper = raw.toUpperCase();\n return (ALLOWED_RESOLUTIONS as ReadonlyArray<string>).includes(upper)\n ? (upper as ImageGenerationResolution)\n : undefined;\n}\n\nfunction readProviderOptions(args: Record<string, unknown>): ImageGenerationProviderOptions | undefined {\n const raw = args.providerOptions;\n if (!raw || typeof raw !== 'object') return undefined;\n const out: ImageGenerationProviderOptions = {};\n const oa = (raw as Record<string, unknown>).openai;\n if (oa && typeof oa === 'object') {\n const oaRec = oa as Record<string, unknown>;\n const moderation = typeof oaRec.moderation === 'string' ? oaRec.moderation.toLowerCase() : undefined;\n const outputCompression =\n typeof oaRec.outputCompression === 'number' && Number.isFinite(oaRec.outputCompression)\n ? oaRec.outputCompression\n : undefined;\n const user = typeof oaRec.user === 'string' && oaRec.user.trim() ? oaRec.user.trim() : undefined;\n out.openai = {\n ...(moderation === 'low' || moderation === 'auto' ? { moderation: moderation as 'low' | 'auto' } : {}),\n ...(outputCompression !== undefined ? { outputCompression } : {}),\n ...(user ? { user } : {}),\n };\n if (Object.keys(out.openai).length === 0) delete out.openai;\n }\n return Object.keys(out).length > 0 ? out : undefined;\n}\n\nclass ToolInputError extends Error {}\n\nasync function loadInputImages(params: {\n workspace: string;\n sources: ReadonlyArray<{ source: string }>;\n}): Promise<ImageGenerationSourceImage[]> {\n if (!params.sources?.length) return [];\n const out: ImageGenerationSourceImage[] = [];\n const workspaceAbs = path.resolve(params.workspace);\n for (const entry of params.sources) {\n const source = entry?.source;\n if (typeof source !== 'string' || !source.trim()) {\n throw new ToolInputError('inputImages[].source is required.');\n }\n const trimmed = source.trim();\n if (/^data:image\\//i.test(trimmed)) {\n const parsed = imageAssetFromDataUrl(trimmed);\n if (!parsed) throw new ToolInputError('Invalid data URL in inputImages[].source.');\n out.push(parsed);\n continue;\n }\n if (/^https?:\\/\\//i.test(trimmed)) {\n throw new ToolInputError('Sandboxed image_generate does not allow remote URLs.');\n }\n const resolved = path.resolve(workspaceAbs, trimmed);\n if (resolved !== workspaceAbs && !resolved.startsWith(workspaceAbs + path.sep)) {\n throw new ToolInputError('inputImages[].source escapes workspace.');\n }\n let buffer: Buffer;\n try {\n buffer = await readFile(resolved);\n } catch (e) {\n const em = e instanceof Error ? e.message : String(e);\n throw new ToolInputError(`inputImages[].source not readable: ${em}`);\n }\n const mimeType = mimeTypeFromFileName(resolved) ?? sniffImageMimeType(buffer).mimeType;\n out.push({ buffer, mimeType, fileName: path.basename(resolved) });\n }\n return out;\n}\n\n// Re-exported for callers / tests; no behavioural change vs imported helper.\nexport { parseImageDataUrl };\n\nexport function resolveImageGenerationModelConfigForTool(params: { cfg?: Config }): ToolModelConfig | null {\n // Step 2: tool default = enumerate every provider whose isConfigured() is true,\n // ordered as registered. No more hard-coded openai/dashscope fallback.\n const providers = listImageGenerationProvidersSummary(params.cfg);\n const candidates: string[] = [];\n for (const providerSummary of providers) {\n const provider = getImageGenerationProvider(providerSummary.id, params.cfg);\n let configured = false;\n try {\n configured = provider?.isConfigured?.({ cfg: params.cfg }) ?? false;\n } catch {\n configured = false;\n }\n const modelRef = `${providerSummary.id}/${providerSummary.defaultModel ?? providerSummary.models[0] ?? ''}`;\n if (configured && /^[a-z0-9-]+\\/.+/.test(modelRef) && !candidates.includes(modelRef)) {\n candidates.push(modelRef);\n }\n }\n\n if (candidates.length === 0) {\n return null;\n }\n\n return {\n primary: candidates[0],\n ...(candidates.length > 1 ? { fallbacks: candidates.slice(1) } : {}),\n };\n}\n\nasync function saveGeneratedImages(params: {\n workspace: string;\n images: Array<{ buffer: Buffer; mimeType: string; fileName?: string }>;\n filenameHint?: string;\n}): Promise<string[]> {\n const dir = path.join(params.workspace, 'media', 'generated');\n await mkdir(dir, { recursive: true });\n const out: string[] = [];\n const random = randomBytes(4).toString('hex');\n let i = 0;\n for (const img of params.images) {\n i += 1;\n const ext = imageFileExtensionForMimeType(img.mimeType);\n const base = (params.filenameHint?.replace(/[^\\w.-]/g, '') || 'image') + `-${random}`;\n const name = `${base}-${i}.${ext}`;\n const full = path.join(dir, name);\n await writeFile(full, img.buffer);\n out.push(full);\n }\n return out;\n}\n\nexport function createImageGenerateTool(options: {\n config?: Config;\n workspace: string;\n}): AgentTool<any, Record<string, unknown>> | null {\n const imageGenerationModelConfig = resolveImageGenerationModelConfigForTool({ cfg: options.config });\n if (!imageGenerationModelConfig) {\n return null;\n }\n\n const effectiveCfg =\n applyImageGenerationModelConfigDefaults(options.config, imageGenerationModelConfig) ??\n options.config;\n\n return {\n name: 'image_generate',\n label: 'Image Generation',\n description:\n 'Generate images with the configured image-generation model (default OpenAI). Use action=\"list\" to see providers. Saves files under workspace/media/generated/.',\n parameters: ImageGenerateToolSchema,\n async execute(\n _toolCallId: string,\n args: Record<string, unknown>,\n ): Promise<AgentToolResult<Record<string, unknown>>> {\n const params = args as Record<string, unknown>;\n const action = (readStringParam(params, 'action') || 'generate').toLowerCase();\n if (action === 'list') {\n const providers = listImageGenerationProvidersSummary(effectiveCfg);\n const lines = providers.flatMap((p) => [\n `${p.id}${p.defaultModel ? ` (default ${p.defaultModel})` : ''}`,\n ` models: ${p.models.join(', ')}`,\n ]);\n return {\n content: [{ type: 'text', text: lines.join('\\n') }],\n details: { providers },\n };\n }\n if (action !== 'generate') {\n return {\n content: [{ type: 'text', text: 'action must be \"generate\" or \"list\".' }],\n details: { error: 'bad_action' },\n };\n }\n\n const prompt = readStringParam(params, 'prompt');\n if (!prompt) {\n return {\n content: [{ type: 'text', text: 'prompt is required for image generation.' }],\n details: { error: 'missing_prompt' },\n };\n }\n\n const modelOverride = readStringParam(params, 'model');\n const filename = readStringParam(params, 'filename');\n const size = readStringParam(params, 'size');\n const aspectRatio = readStringParam(params, 'aspectRatio');\n const resolution = readResolutionParam(params);\n const quality = readEnumParam(params, 'quality', ALLOWED_QUALITIES);\n const outputFormat = readEnumParam(params, 'outputFormat', ALLOWED_OUTPUT_FORMATS);\n const background = readEnumParam(params, 'background', ALLOWED_BACKGROUNDS);\n const providerOptions = readProviderOptions(params);\n\n const countRaw = params.count;\n const count =\n typeof countRaw === 'number' && Number.isFinite(countRaw)\n ? Math.min(MAX_COUNT, Math.max(1, Math.floor(countRaw)))\n : DEFAULT_COUNT;\n\n let inputImages: ImageGenerationSourceImage[] = [];\n try {\n inputImages = await loadInputImages({\n workspace: options.workspace,\n sources: (params.inputImages as Array<{ source: string }>) ?? [],\n });\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n content: [{ type: 'text', text: `Image generation failed: ${msg}` }],\n details: {\n error: e instanceof ToolInputError ? 'invalid_input_images' : 'generation_failed',\n },\n };\n }\n\n try {\n const result = await generateImage({\n cfg: effectiveCfg,\n modelConfig: imageGenerationModelConfig,\n prompt,\n ...(modelOverride ? { modelOverride } : {}),\n count,\n ...(size ? { size } : {}),\n ...(aspectRatio ? { aspectRatio } : {}),\n ...(resolution ? { resolution } : {}),\n ...(quality ? { quality } : {}),\n ...(outputFormat ? { outputFormat } : {}),\n ...(background ? { background } : {}),\n ...(inputImages.length > 0 ? { inputImages } : {}),\n ...(providerOptions ? { providerOptions } : {}),\n });\n\n const paths = await saveGeneratedImages({\n workspace: options.workspace,\n images: result.images,\n ...(filename ? { filenameHint: filename } : {}),\n });\n\n const workspaceRelativePaths = paths.map((p) =>\n path.relative(options.workspace, p).split(path.sep).join('/'),\n );\n\n const lines: string[] = [\n `Generated ${paths.length} image(s) with ${result.provider}/${result.model}.`,\n ...paths.map((p) => `Saved: ${p}`),\n ];\n for (const note of buildNormalizationNotes(result.normalization, result.ignoredOverrides)) {\n lines.push(note);\n }\n\n return {\n content: [{ type: 'text', text: lines.join('\\n') }],\n details: {\n provider: result.provider,\n model: result.model,\n paths,\n workspaceRelativePaths,\n attempts: result.attempts,\n ...(result.normalization ? { normalization: result.normalization } : {}),\n ...(result.ignoredOverrides.length > 0\n ? { ignoredOverrides: result.ignoredOverrides }\n : {}),\n ...(result.metadata ? { metadata: result.metadata } : {}),\n },\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n const failoverFields = isFailoverError(e)\n ? {\n ...(e.reason !== undefined ? { reason: e.reason } : {}),\n ...(e.status !== undefined ? { status: e.status } : {}),\n ...(e.code !== undefined ? { code: e.code } : {}),\n ...(e.provider !== undefined ? { provider: e.provider } : {}),\n ...(e.model !== undefined ? { model: e.model } : {}),\n attempts: e.attempts,\n }\n : {};\n return {\n content: [{ type: 'text', text: `Image generation failed: ${msg}` }],\n details: { error: 'generation_failed', ...failoverFields },\n };\n }\n },\n } as any;\n}\n\nfunction buildNormalizationNotes(\n normalization: import('../image/generation/types.js').ImageGenerationNormalization | undefined,\n ignoredOverrides: ReadonlyArray<import('../image/generation/types.js').ImageGenerationIgnoredOverride>,\n): string[] {\n const notes: string[] = [];\n if (normalization) {\n for (const [key, entry] of Object.entries(normalization)) {\n if (!entry) continue;\n const requested = entry.requested;\n const applied = entry.applied;\n if (requested !== undefined && applied !== undefined && requested !== applied) {\n notes.push(`Note: requested ${key}=\"${requested}\" → applied \"${applied}\".`);\n } else if (applied !== undefined && entry.derivedFrom) {\n notes.push(`Note: ${key}=\"${applied}\" derived from ${entry.derivedFrom}.`);\n }\n }\n }\n for (const ig of ignoredOverrides) {\n notes.push(`Note: ignored ${ig.key}=\"${ig.value}\" (not supported by provider).`);\n }\n return notes;\n}\n"],"mappings":"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"}
@@ -9,14 +9,12 @@ const DEFAULT_PROMPT = "Describe the image.";
9
9
  const DEFAULT_MAX_IMAGES = 20;
10
10
  function pickMaxBytes(cfg, maxBytesMb) {
11
11
  if (typeof maxBytesMb === "number" && Number.isFinite(maxBytesMb) && maxBytesMb > 0) return Math.floor(maxBytesMb * 1024 * 1024);
12
- const configured = cfg?.agents?.defaults?.mediaMaxMb;
13
- if (typeof configured === "number" && Number.isFinite(configured) && configured > 0) return Math.floor(configured * 1024 * 1024);
14
12
  return 20 * 1024 * 1024;
15
13
  }
16
14
  function createImageTool(options) {
17
15
  const imageModelConfig = resolveImageModelConfigForTool({ cfg: options.config });
18
16
  if (!imageModelConfig) return null;
19
- const description = options.modelHasVision ? "Analyze one or more images with a vision model. Use `image` for a single path/URL, or `images` for multiple (up to 20). Only use when images were NOT already in the user message." : "Analyze one or more images using the configured image model (agents.defaults.imageModel). Use `image` or `images` for paths/URLs; optional `prompt` for what to extract.";
17
+ const description = options.modelHasVision ? "Analyze one or more images with a vision model. Use `image` for a single path/URL, or `images` for multiple (up to 20). Only use when images were NOT already in the user message." : "Analyze one or more images using the available image model. Use `image` or `images` for paths/URLs; optional `prompt` for what to extract.";
20
18
  const localRoots = [options.workspace];
21
19
  return {
22
20
  name: "image",
@@ -1 +1 @@
1
- {"version":3,"file":"image-tool.js","names":[],"sources":["../../../../src/agent/tools/image-tool.ts"],"sourcesContent":["import { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { Config } from '../../config/schema.js';\nimport { describeImages } from '../image/understanding/runtime.js';\nimport { buildImageToolTextResult, resolvePromptAndModelOverride } from '../image/image-helpers.js';\nimport { runWithImageModelFallback } from '../image/image-model-fallback.js';\nimport { loadImageForToolInput } from '../image/load-image-media.js';\nimport { resolveImageModelConfigForTool } from '../image/tool-model-config.js';\n\nconst DEFAULT_PROMPT = 'Describe the image.';\nconst DEFAULT_MAX_IMAGES = 20;\n\nexport { resolveImageModelConfigForTool } from '../image/tool-model-config.js';\n\nfunction pickMaxBytes(cfg?: Config, maxBytesMb?: number): number {\n if (typeof maxBytesMb === 'number' && Number.isFinite(maxBytesMb) && maxBytesMb > 0) {\n return Math.floor(maxBytesMb * 1024 * 1024);\n }\n const configured = cfg?.agents?.defaults?.mediaMaxMb;\n if (typeof configured === 'number' && Number.isFinite(configured) && configured > 0) {\n return Math.floor(configured * 1024 * 1024);\n }\n return 20 * 1024 * 1024;\n}\n\nexport function createImageTool(options: {\n config?: Config;\n workspace: string;\n /** When true, session model already receives images in the user message. */\n modelHasVision?: boolean;\n}): AgentTool<any, Record<string, unknown>> | null {\n const imageModelConfig = resolveImageModelConfigForTool({ cfg: options.config });\n if (!imageModelConfig) {\n return null;\n }\n\n const description = options.modelHasVision\n ? 'Analyze one or more images with a vision model. Use `image` for a single path/URL, or `images` for multiple (up to 20). Only use when images were NOT already in the user message.'\n : 'Analyze one or more images using the configured image model (agents.defaults.imageModel). Use `image` or `images` for paths/URLs; optional `prompt` for what to extract.';\n\n const localRoots = [options.workspace];\n\n return {\n name: 'image',\n label: 'Image',\n description,\n parameters: Type.Object({\n prompt: Type.Optional(Type.String()),\n image: Type.Optional(Type.String({ description: 'Single image path or URL.' })),\n images: Type.Optional(\n Type.Array(Type.String(), {\n description: 'Multiple image paths or URLs (up to maxImages, default 20).',\n }),\n ),\n model: Type.Optional(Type.String({ description: 'Optional provider/model override.' })),\n maxBytesMb: Type.Optional(Type.Number()),\n maxImages: Type.Optional(Type.Number()),\n }),\n async execute(\n _toolCallId: string,\n args: Record<string, unknown>,\n ): Promise<AgentToolResult<Record<string, unknown>>> {\n const record = args && typeof args === 'object' ? args : {};\n\n const imageCandidates: string[] = [];\n if (typeof record.image === 'string') {\n imageCandidates.push(record.image);\n }\n if (Array.isArray(record.images)) {\n imageCandidates.push(...record.images.filter((v): v is string => typeof v === 'string'));\n }\n\n const seenImages = new Set<string>();\n const imageInputs: string[] = [];\n for (const candidate of imageCandidates) {\n const trimmedCandidate = candidate.trim();\n const normalizedForDedupe = trimmedCandidate.startsWith('@')\n ? trimmedCandidate.slice(1).trim()\n : trimmedCandidate;\n if (!normalizedForDedupe || seenImages.has(normalizedForDedupe)) {\n continue;\n }\n seenImages.add(normalizedForDedupe);\n imageInputs.push(trimmedCandidate);\n }\n\n if (imageInputs.length === 0) {\n return {\n content: [{ type: 'text', text: 'Error: provide `image` or `images`.' }],\n details: { error: 'missing_image' },\n };\n }\n\n const maxImagesRaw = typeof record.maxImages === 'number' ? record.maxImages : undefined;\n const maxImages =\n typeof maxImagesRaw === 'number' && Number.isFinite(maxImagesRaw) && maxImagesRaw > 0\n ? Math.floor(maxImagesRaw)\n : DEFAULT_MAX_IMAGES;\n if (imageInputs.length > maxImages) {\n return {\n content: [\n {\n type: 'text',\n text: `Too many images: ${imageInputs.length} (max ${maxImages}).`,\n },\n ],\n details: { error: 'too_many_images', count: imageInputs.length, max: maxImages },\n };\n }\n\n const { prompt: promptRaw, modelOverride } = resolvePromptAndModelOverride(\n record,\n DEFAULT_PROMPT,\n );\n const maxBytesMb = typeof record.maxBytesMb === 'number' ? record.maxBytesMb : undefined;\n const maxBytes = pickMaxBytes(options.config, maxBytesMb);\n\n const loadedImages: Array<{ buffer: Buffer; mimeType: string; resolvedImage: string }> = [];\n\n for (const imageRawInput of imageInputs) {\n const trimmed = imageRawInput.trim();\n const imageRaw = trimmed.startsWith('@') ? trimmed.slice(1).trim() : trimmed;\n if (!imageRaw) {\n return {\n content: [{ type: 'text', text: 'Error: empty image entry.' }],\n details: { error: 'empty_image' },\n };\n }\n\n const looksLikeWindowsDrivePath = /^[a-zA-Z]:[\\\\/]/.test(imageRaw);\n const hasScheme = /^[a-z][a-z0-9+.-]*:/i.test(imageRaw);\n const isFileUrl = /^file:/i.test(imageRaw);\n const isHttpUrl = /^https?:\\/\\//i.test(imageRaw);\n const isDataUrl = /^data:/i.test(imageRaw);\n if (hasScheme && !looksLikeWindowsDrivePath && !isFileUrl && !isHttpUrl && !isDataUrl) {\n return {\n content: [\n {\n type: 'text',\n text: `Unsupported image reference: ${imageRawInput}. Use a path, file://, data:, or http(s) URL.`,\n },\n ],\n details: { error: 'unsupported_image_reference', image: imageRawInput },\n };\n }\n\n try {\n const media = await loadImageForToolInput(imageRaw, {\n maxBytes,\n workspace: options.workspace,\n localRoots,\n });\n loadedImages.push({\n buffer: media.buffer,\n mimeType: media.mimeType,\n resolvedImage: imageRaw,\n });\n } catch (e) {\n return {\n content: [\n {\n type: 'text',\n text: `Failed to load image (${imageRawInput}): ${e instanceof Error ? e.message : String(e)}`,\n },\n ],\n details: { error: 'load_failed', image: imageRawInput },\n };\n }\n }\n\n const runResult = await runWithImageModelFallback({\n toolConfig: imageModelConfig,\n modelOverride,\n run: async (modelRef) => {\n const { text, provider, model } = await describeImages({\n modelRef,\n prompt: promptRaw,\n images: loadedImages.map((img) => ({ buffer: img.buffer, mimeType: img.mimeType })),\n timeoutMs: 60_000,\n });\n return { text, provider, model };\n },\n });\n\n const { result: inner, attempts } = runResult;\n const result = {\n text: inner.text,\n provider: inner.provider,\n model: inner.model,\n attempts,\n };\n\n const imageDetails =\n loadedImages.length === 1\n ? { image: loadedImages[0].resolvedImage }\n : {\n images: loadedImages.map((img) => ({ image: img.resolvedImage })),\n };\n\n return buildImageToolTextResult(result, imageDetails);\n },\n } as any;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"image-tool.js","names":[],"sources":["../../../../src/agent/tools/image-tool.ts"],"sourcesContent":["import { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\nimport type { Config } from '../../config/schema.js';\nimport { describeImages } from '../image/understanding/runtime.js';\nimport { buildImageToolTextResult, resolvePromptAndModelOverride } from '../image/image-helpers.js';\nimport { runWithImageModelFallback } from '../image/image-model-fallback.js';\nimport { loadImageForToolInput } from '../image/load-image-media.js';\nimport { resolveImageModelConfigForTool } from '../image/tool-model-config.js';\n\nconst DEFAULT_PROMPT = 'Describe the image.';\nconst DEFAULT_MAX_IMAGES = 20;\n\nexport { resolveImageModelConfigForTool } from '../image/tool-model-config.js';\n\nfunction pickMaxBytes(cfg?: Config, maxBytesMb?: number): number {\n if (typeof maxBytesMb === 'number' && Number.isFinite(maxBytesMb) && maxBytesMb > 0) {\n return Math.floor(maxBytesMb * 1024 * 1024);\n }\n return 20 * 1024 * 1024;\n}\n\nexport function createImageTool(options: {\n config?: Config;\n workspace: string;\n /** When true, session model already receives images in the user message. */\n modelHasVision?: boolean;\n}): AgentTool<any, Record<string, unknown>> | null {\n const imageModelConfig = resolveImageModelConfigForTool({ cfg: options.config });\n if (!imageModelConfig) {\n return null;\n }\n\n const description = options.modelHasVision\n ? 'Analyze one or more images with a vision model. Use `image` for a single path/URL, or `images` for multiple (up to 20). Only use when images were NOT already in the user message.'\n : 'Analyze one or more images using the available image model. Use `image` or `images` for paths/URLs; optional `prompt` for what to extract.';\n\n const localRoots = [options.workspace];\n\n return {\n name: 'image',\n label: 'Image',\n description,\n parameters: Type.Object({\n prompt: Type.Optional(Type.String()),\n image: Type.Optional(Type.String({ description: 'Single image path or URL.' })),\n images: Type.Optional(\n Type.Array(Type.String(), {\n description: 'Multiple image paths or URLs (up to maxImages, default 20).',\n }),\n ),\n model: Type.Optional(Type.String({ description: 'Optional provider/model override.' })),\n maxBytesMb: Type.Optional(Type.Number()),\n maxImages: Type.Optional(Type.Number()),\n }),\n async execute(\n _toolCallId: string,\n args: Record<string, unknown>,\n ): Promise<AgentToolResult<Record<string, unknown>>> {\n const record = args && typeof args === 'object' ? args : {};\n\n const imageCandidates: string[] = [];\n if (typeof record.image === 'string') {\n imageCandidates.push(record.image);\n }\n if (Array.isArray(record.images)) {\n imageCandidates.push(...record.images.filter((v): v is string => typeof v === 'string'));\n }\n\n const seenImages = new Set<string>();\n const imageInputs: string[] = [];\n for (const candidate of imageCandidates) {\n const trimmedCandidate = candidate.trim();\n const normalizedForDedupe = trimmedCandidate.startsWith('@')\n ? trimmedCandidate.slice(1).trim()\n : trimmedCandidate;\n if (!normalizedForDedupe || seenImages.has(normalizedForDedupe)) {\n continue;\n }\n seenImages.add(normalizedForDedupe);\n imageInputs.push(trimmedCandidate);\n }\n\n if (imageInputs.length === 0) {\n return {\n content: [{ type: 'text', text: 'Error: provide `image` or `images`.' }],\n details: { error: 'missing_image' },\n };\n }\n\n const maxImagesRaw = typeof record.maxImages === 'number' ? record.maxImages : undefined;\n const maxImages =\n typeof maxImagesRaw === 'number' && Number.isFinite(maxImagesRaw) && maxImagesRaw > 0\n ? Math.floor(maxImagesRaw)\n : DEFAULT_MAX_IMAGES;\n if (imageInputs.length > maxImages) {\n return {\n content: [\n {\n type: 'text',\n text: `Too many images: ${imageInputs.length} (max ${maxImages}).`,\n },\n ],\n details: { error: 'too_many_images', count: imageInputs.length, max: maxImages },\n };\n }\n\n const { prompt: promptRaw, modelOverride } = resolvePromptAndModelOverride(\n record,\n DEFAULT_PROMPT,\n );\n const maxBytesMb = typeof record.maxBytesMb === 'number' ? record.maxBytesMb : undefined;\n const maxBytes = pickMaxBytes(options.config, maxBytesMb);\n\n const loadedImages: Array<{ buffer: Buffer; mimeType: string; resolvedImage: string }> = [];\n\n for (const imageRawInput of imageInputs) {\n const trimmed = imageRawInput.trim();\n const imageRaw = trimmed.startsWith('@') ? trimmed.slice(1).trim() : trimmed;\n if (!imageRaw) {\n return {\n content: [{ type: 'text', text: 'Error: empty image entry.' }],\n details: { error: 'empty_image' },\n };\n }\n\n const looksLikeWindowsDrivePath = /^[a-zA-Z]:[\\\\/]/.test(imageRaw);\n const hasScheme = /^[a-z][a-z0-9+.-]*:/i.test(imageRaw);\n const isFileUrl = /^file:/i.test(imageRaw);\n const isHttpUrl = /^https?:\\/\\//i.test(imageRaw);\n const isDataUrl = /^data:/i.test(imageRaw);\n if (hasScheme && !looksLikeWindowsDrivePath && !isFileUrl && !isHttpUrl && !isDataUrl) {\n return {\n content: [\n {\n type: 'text',\n text: `Unsupported image reference: ${imageRawInput}. Use a path, file://, data:, or http(s) URL.`,\n },\n ],\n details: { error: 'unsupported_image_reference', image: imageRawInput },\n };\n }\n\n try {\n const media = await loadImageForToolInput(imageRaw, {\n maxBytes,\n workspace: options.workspace,\n localRoots,\n });\n loadedImages.push({\n buffer: media.buffer,\n mimeType: media.mimeType,\n resolvedImage: imageRaw,\n });\n } catch (e) {\n return {\n content: [\n {\n type: 'text',\n text: `Failed to load image (${imageRawInput}): ${e instanceof Error ? e.message : String(e)}`,\n },\n ],\n details: { error: 'load_failed', image: imageRawInput },\n };\n }\n }\n\n const runResult = await runWithImageModelFallback({\n toolConfig: imageModelConfig,\n modelOverride,\n run: async (modelRef) => {\n const { text, provider, model } = await describeImages({\n modelRef,\n prompt: promptRaw,\n images: loadedImages.map((img) => ({ buffer: img.buffer, mimeType: img.mimeType })),\n timeoutMs: 60_000,\n });\n return { text, provider, model };\n },\n });\n\n const { result: inner, attempts } = runResult;\n const result = {\n text: inner.text,\n provider: inner.provider,\n model: inner.model,\n attempts,\n };\n\n const imageDetails =\n loadedImages.length === 1\n ? { image: loadedImages[0].resolvedImage }\n : {\n images: loadedImages.map((img) => ({ image: img.resolvedImage })),\n };\n\n return buildImageToolTextResult(result, imageDetails);\n },\n } as any;\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import type { AgentTool } from '@earendil-works/pi-agent-core';
2
+ import type { MemoryManager } from '../memory/manager.js';
2
3
  export interface MemoryToolOptions {
3
4
  workspaceDir: string;
4
- /** Agent home curated memories dir, e.g. ~/.xopc/agents/<id>/memories/ */
5
- memoriesDir?: string;
5
+ getMemoryManager: () => MemoryManager;
6
6
  }
7
7
  export declare function createMemorySearchTool(options: MemoryToolOptions): AgentTool;
8
8
  export declare function createMemoryGetTool(options: MemoryToolOptions): AgentTool;