@xopcai/xopc 0.0.111 → 0.0.113

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 (443) hide show
  1. package/dist/browser-ext/icons/icon-128.png +0 -0
  2. package/dist/browser-ext/icons/icon-16.png +0 -0
  3. package/dist/browser-ext/icons/icon-32.png +0 -0
  4. package/dist/browser-ext/icons/icon-48.png +0 -0
  5. package/dist/browser-ext/manifest.json +1 -1
  6. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  7. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  8. package/dist/extensions/telegram/src/adapters/streaming-adapter.js +1 -1
  9. package/dist/extensions/telegram/src/inbound-processor.js +1 -1
  10. package/dist/extensions/telegram/src/plugin.js +1 -1
  11. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  12. package/dist/extensions/telegram/src/update-offset-store.js +1 -1
  13. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  14. package/dist/extensions/telegram/xopc.extension.json +1 -1
  15. package/dist/extensions/weixin/src/api/api.js +2 -2
  16. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  17. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  18. package/dist/extensions/weixin/src/delivery-to.d.ts +3 -3
  19. package/dist/extensions/weixin/src/delivery-to.js.map +1 -1
  20. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  21. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  22. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  23. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  24. package/dist/extensions/weixin/src/plugin.js +1 -1
  25. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  26. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  27. package/dist/gateway/static/root/apple-touch-icon.png +0 -0
  28. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-zlx9l5Yp.js → agent-avatar-dicebear-CBlklyNr.js} +1 -1
  29. package/dist/gateway/static/root/assets/agent-browser-settings-page-rGbKc2Hh.js +6 -0
  30. package/dist/gateway/static/root/assets/{agent-defaults-tabbed-page-Bz7JWjRM.js → agent-defaults-tabbed-page-CtwVbjOA.js} +1 -1
  31. package/dist/gateway/static/root/assets/agents-CCBmGcwc.js +71 -0
  32. package/dist/gateway/static/root/assets/{app-management-settings-panel-DaQwdeCq.js → app-management-settings-panel-28E_WfMe.js} +1 -1
  33. package/dist/gateway/static/root/assets/{appearance-settings-D2zv6r3P.js → appearance-settings-Do1z0XgJ.js} +1 -1
  34. package/dist/gateway/static/root/assets/{apps-page-BIppe_jj.js → apps-page-xwCsJS15.js} +1 -1
  35. package/dist/gateway/static/root/assets/{archive-plugin-DEmu8eH7.js → archive-plugin-BAFlsov_.js} +1 -1
  36. package/dist/gateway/static/root/assets/{attachment-load-B98lJoN5.js → attachment-load-V3qGPC3x.js} +1 -1
  37. package/dist/gateway/static/root/assets/{binary-plugins-CL9QKmyo.js → binary-plugins-DT8NvA6W.js} +1 -1
  38. package/dist/gateway/static/root/assets/{block-editor-BOAhMAhT.js → block-editor-CdLMEcHd.js} +1 -1
  39. package/dist/gateway/static/root/assets/{channels-settings-Br8iRnXp.js → channels-settings-C044DcYk.js} +1 -1
  40. package/dist/gateway/static/root/assets/{config-api-0o1WYdz2.js → config-api-Bf5mjpu7.js} +1 -1
  41. package/dist/gateway/static/root/assets/config-reload-event-Bjh2zoKp.js +1 -0
  42. package/dist/gateway/static/root/assets/connectors-settings-8VEWUOTj.js +2 -0
  43. package/dist/gateway/static/root/assets/cron-api--pAB_rps.js +1 -0
  44. package/dist/gateway/static/root/assets/cron-page-DqmNGNOy.js +3 -0
  45. package/dist/gateway/static/root/assets/dreaming-settings-6UZE1FSK.js +1 -0
  46. package/dist/gateway/static/root/assets/{extension-debug-page-Cjx6pZVz.js → extension-debug-page-BGhE7msg.js} +1 -1
  47. package/dist/gateway/static/root/assets/{extension-page-BSPNL90V.js → extension-page-CvpI45WG.js} +1 -1
  48. package/dist/gateway/static/root/assets/extension-settings-page-DAmR5FUe.js +1 -0
  49. package/dist/gateway/static/root/assets/{fetch-Bs7in_4F.js → fetch-NZmjSXLl.js} +1 -1
  50. package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +2 -0
  51. package/dist/gateway/static/root/assets/{format-interval-label-CftJ5uXu.js → format-interval-label-qhth3BMV.js} +1 -1
  52. package/dist/gateway/static/root/assets/{gateway-config-api-Clfck-hW.js → gateway-config-api-CaXBt-9R.js} +1 -1
  53. package/dist/gateway/static/root/assets/gateway-settings-DphpbLBc.js +1 -0
  54. package/dist/gateway/static/root/assets/{gateway-startup-retry-BkjVJc38.js → gateway-startup-retry-Be1omjh3.js} +1 -1
  55. package/dist/gateway/static/root/assets/{goal-detail-page-kqJue0sE.js → goal-detail-page-bv0VRDaf.js} +1 -1
  56. package/dist/gateway/static/root/assets/goals-page-1Ywnt4Cb.js +2 -0
  57. package/dist/gateway/static/root/assets/{goals-settings-CJnzNSDo.js → goals-settings-ceEBjnfc.js} +1 -1
  58. package/dist/gateway/static/root/assets/{heartbeat-config-api-Cp7CPuIn.js → heartbeat-config-api-BzO6G4fD.js} +1 -1
  59. package/dist/gateway/static/root/assets/{heartbeat-settings-ifSI1Wbh.js → heartbeat-settings-DCST9-du.js} +1 -1
  60. package/dist/gateway/static/root/assets/index-Cxm6xsps.js +122 -0
  61. package/dist/gateway/static/root/assets/index-b_R4tKqt.css +1 -0
  62. package/dist/gateway/static/root/assets/interval-presets-DJmshV8n.js +1 -0
  63. package/dist/gateway/static/root/assets/{keyboard-shortcuts-settings--MI1rYl7.js → keyboard-shortcuts-settings-9AUUlQ5Q.js} +1 -1
  64. package/dist/gateway/static/root/assets/{logs-page-BwrVNlyW.js → logs-page-B_wrxhee.js} +1 -1
  65. package/dist/gateway/static/root/assets/{markdown-split-B_oc9lJe.js → markdown-split-CYYELqAr.js} +1 -1
  66. package/dist/gateway/static/root/assets/{media-plugins-DLPvB5H3.js → media-plugins-BEcMR2M8.js} +1 -1
  67. package/dist/gateway/static/root/assets/messages-CkT-lcgP.js +3 -0
  68. package/dist/gateway/static/root/assets/models-hub-panel-D0JDSbNu.js +2 -0
  69. package/dist/gateway/static/root/assets/note-detail-page-DpFV-EO6.js +2 -0
  70. package/dist/gateway/static/root/assets/{note-image-lightbox-rSqAgOi9.js → note-image-lightbox-DNAoPcmm.js} +1 -1
  71. package/dist/gateway/static/root/assets/{notes-page-C9ACGEty.js → notes-page-CdkjTch8.js} +1 -1
  72. package/dist/gateway/static/root/assets/{preview-open-alternatives-Bw_N2oZi.js → preview-open-alternatives-BPLz0AIv.js} +1 -1
  73. package/dist/gateway/static/root/assets/{remote-access-hub-BhcWIKuM.js → remote-access-hub-DSYVAi96.js} +1 -1
  74. package/dist/gateway/static/root/assets/{save-bar-controls-CNP2jmw0.js → save-bar-controls-CrWwWRVK.js} +1 -1
  75. package/dist/gateway/static/root/assets/schedule-field-CF2sadvN.js +1 -0
  76. package/dist/gateway/static/root/assets/{schema-form-CDPzua9q.js → schema-form-Di5cKjYE.js} +1 -1
  77. package/dist/gateway/static/root/assets/{sessions-page-DzkpSDZr.js → sessions-page-CenkcVjF.js} +1 -1
  78. package/dist/gateway/static/root/assets/settings-advanced-gate-D9sva86V.js +1 -0
  79. package/dist/gateway/static/root/assets/{settings-collapsible-section-C9bff85B.js → settings-collapsible-section-Chh282jW.js} +1 -1
  80. package/dist/gateway/static/root/assets/settings-form-section-Dq-83cQd.js +1 -0
  81. package/dist/gateway/static/root/assets/{settings-page-DWK4Zo7s.js → settings-page-DL35U0x0.js} +1 -1
  82. package/dist/gateway/static/root/assets/setup-status-panel-Ctwbp9Er.js +1 -0
  83. package/dist/gateway/static/root/assets/{share-preview-page-DnutoY_S.js → share-preview-page-0FXYnSUA.js} +1 -1
  84. package/dist/gateway/static/root/assets/{shares-settings-6oRgJMpn.js → shares-settings-DIM3JNsr.js} +1 -1
  85. package/dist/gateway/static/root/assets/skill-reload-api-DAlNaNzL.js +1 -0
  86. package/dist/gateway/static/root/assets/skills-page-CLrHVzAt.js +2 -0
  87. package/dist/gateway/static/root/assets/{system-settings-panel-qP1JDtDd.js → system-settings-panel-W1pTcojB.js} +1 -1
  88. package/dist/gateway/static/root/assets/use-agent-defaults-form-BVRvkK7m.js +1 -0
  89. package/dist/gateway/static/root/assets/{use-channel-catalog-C4mg1hjD.js → use-channel-catalog-CgJibfMM.js} +1 -1
  90. package/dist/gateway/static/root/assets/{use-settings-tab-guard-F6C0mpJt.js → use-settings-tab-guard-Bw_qkRQE.js} +1 -1
  91. package/dist/gateway/static/root/assets/{voice-api-key-field-BnDDb6qO.js → voice-api-key-field-vYAO71Gn.js} +1 -1
  92. package/dist/gateway/static/root/assets/{voice-player-store-B2EwIhtY.js → voice-player-store-C7lziaAx.js} +1 -1
  93. package/dist/gateway/static/root/assets/{workflow-page.utils-CRB7WX9l.js → workflow-page.utils-sgHjOXOm.js} +1 -1
  94. package/dist/gateway/static/root/assets/{workflows-page-2Fptr0je.js → workflows-page-DYyOTmFx.js} +1 -1
  95. package/dist/gateway/static/root/favicon-16x16.png +0 -0
  96. package/dist/gateway/static/root/favicon-32x32.png +0 -0
  97. package/dist/gateway/static/root/favicon-icon.svg +1 -0
  98. package/dist/gateway/static/root/favicon.ico +0 -0
  99. package/dist/gateway/static/root/favicon.png +0 -0
  100. package/dist/gateway/static/root/favicon.svg +24 -15
  101. package/dist/gateway/static/root/index.html +11 -10
  102. package/dist/gateway/static/root/logo-dark.svg +23 -15
  103. package/dist/gateway/static/root/logo.svg +23 -16
  104. package/dist/package.js +1 -1
  105. package/dist/src/agent/agent-manager.d.ts +28 -2
  106. package/dist/src/agent/agent-manager.js +82 -11
  107. package/dist/src/agent/agent-manager.js.map +1 -1
  108. package/dist/src/agent/agent-scope.js +1 -1
  109. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  110. package/dist/src/agent/context/workspace-seed.js +2 -2
  111. package/dist/src/agent/context/workspace-state.js +1 -1
  112. package/dist/src/agent/context/workspace.js +1 -1
  113. package/dist/src/agent/goals/goal-locale.js +2 -2
  114. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  115. package/dist/src/agent/goals/post-turn.js +3 -3
  116. package/dist/src/agent/image/load-image-media.js +2 -2
  117. package/dist/src/agent/ipc/inbox.js +3 -3
  118. package/dist/src/agent/ipc/socket.js +1 -1
  119. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  120. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  121. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  122. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  123. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  124. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  125. package/dist/src/agent/memory/dreaming/events.js +1 -1
  126. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  127. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  128. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  129. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  130. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  131. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  132. package/dist/src/agent/memory/memory-flush.js +1 -1
  133. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  134. package/dist/src/agent/messaging/command-handler.d.ts +3 -0
  135. package/dist/src/agent/messaging/command-handler.js +5 -0
  136. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  137. package/dist/src/agent/models/manager.js +1 -1
  138. package/dist/src/agent/prompt/memory/index.js +1 -1
  139. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  140. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  141. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  142. package/dist/src/agent/sandbox/path-policy.js +2 -2
  143. package/dist/src/agent/service/process-direct-streaming.js +9 -4
  144. package/dist/src/agent/service/process-direct-streaming.js.map +1 -1
  145. package/dist/src/agent/service/reconcile-dreaming-cron.js +8 -5
  146. package/dist/src/agent/service/reconcile-dreaming-cron.js.map +1 -1
  147. package/dist/src/agent/service.d.ts +2 -1
  148. package/dist/src/agent/service.js +10 -5
  149. package/dist/src/agent/service.js.map +1 -1
  150. package/dist/src/agent/service.types.d.ts +4 -0
  151. package/dist/src/agent/session/session-config-service.d.ts +8 -0
  152. package/dist/src/agent/session/session-config-service.js +20 -0
  153. package/dist/src/agent/session/session-config-service.js.map +1 -1
  154. package/dist/src/agent/session/session-inspector.js +1 -1
  155. package/dist/src/agent/skills/config.js +2 -2
  156. package/dist/src/agent/skills/filesystem-watcher.d.ts +19 -0
  157. package/dist/src/agent/skills/filesystem-watcher.js +182 -0
  158. package/dist/src/agent/skills/filesystem-watcher.js.map +1 -0
  159. package/dist/src/agent/skills/hub-hash.js +2 -2
  160. package/dist/src/agent/skills/hub-lock.js +1 -1
  161. package/dist/src/agent/skills/hub-pull.js +30 -36
  162. package/dist/src/agent/skills/hub-pull.js.map +1 -1
  163. package/dist/src/agent/skills/index.js +82 -38
  164. package/dist/src/agent/skills/index.js.map +1 -1
  165. package/dist/src/agent/skills/installer.js +2 -2
  166. package/dist/src/agent/skills/managed-store.d.ts +19 -0
  167. package/dist/src/agent/skills/managed-store.js +97 -38
  168. package/dist/src/agent/skills/managed-store.js.map +1 -1
  169. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  170. package/dist/src/agent/skills/skill-manager.d.ts +16 -6
  171. package/dist/src/agent/skills/skill-manager.js +79 -24
  172. package/dist/src/agent/skills/skill-manager.js.map +1 -1
  173. package/dist/src/agent/skills/skill-view-path.js +1 -1
  174. package/dist/src/agent/skills/test-framework.js +1 -1
  175. package/dist/src/agent/skills/types.d.ts +11 -0
  176. package/dist/src/agent/skills/watcher.js +1 -1
  177. package/dist/src/agent/starter-agents.js +1 -1
  178. package/dist/src/agent/tools/cronjob-tool.d.ts +6 -3
  179. package/dist/src/agent/tools/cronjob-tool.js +58 -23
  180. package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
  181. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  182. package/dist/src/agent/tools/factory.js +1 -1
  183. package/dist/src/agent/tools/find.js +1 -1
  184. package/dist/src/agent/tools/grep.js +1 -1
  185. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  186. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  187. package/dist/src/agent/tools/workflow-tool.js +1 -1
  188. package/dist/src/agent/workflow/catalog.js +1 -1
  189. package/dist/src/agent/workspace-runtime/registry.d.ts +5 -0
  190. package/dist/src/agent/workspace-runtime/registry.js +7 -0
  191. package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
  192. package/dist/src/ai-assist/text-assist.d.ts +42 -0
  193. package/dist/src/ai-assist/text-assist.js +252 -0
  194. package/dist/src/ai-assist/text-assist.js.map +1 -0
  195. package/dist/src/auth/credentials.js +2 -2
  196. package/dist/src/auth/profiles/store.js +2 -2
  197. package/dist/src/auth/sync-provider-auth.js +1 -1
  198. package/dist/src/browser/cache-dir-policy.js +1 -1
  199. package/dist/src/browser/cdp-local-launcher.js +2 -2
  200. package/dist/src/browser/providers/browser-ext-install.js +4 -4
  201. package/dist/src/browser/providers/cloakbrowser.js +5 -5
  202. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  203. package/dist/src/browser/stealth.js +1 -1
  204. package/dist/src/channels/outbound/persist-store.js +1 -1
  205. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  206. package/dist/src/channels/pairing/pairing-store.js +2 -2
  207. package/dist/src/channels/plugins/types.adapters.d.ts +2 -2
  208. package/dist/src/chat-commands/agent-edit.js +2 -2
  209. package/dist/src/chat-commands/builtins/config.js +3 -3
  210. package/dist/src/chat-commands/builtins/system.js +11 -4
  211. package/dist/src/chat-commands/builtins/system.js.map +1 -1
  212. package/dist/src/chat-commands/context.d.ts +3 -0
  213. package/dist/src/chat-commands/context.js +7 -0
  214. package/dist/src/chat-commands/context.js.map +1 -1
  215. package/dist/src/chat-commands/types.d.ts +2 -0
  216. package/dist/src/cli/commands/config.js +1 -1
  217. package/dist/src/cli/commands/cron.js +55 -16
  218. package/dist/src/cli/commands/cron.js.map +1 -1
  219. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  220. package/dist/src/cli/commands/doctor/checks/cron-health.js +2 -83
  221. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -1
  222. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  223. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  224. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  225. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  226. package/dist/src/cli/commands/extension-create.js +1 -1
  227. package/dist/src/cli/commands/extension-dev.js +2 -2
  228. package/dist/src/cli/commands/extension-marketplace.js +2 -2
  229. package/dist/src/cli/commands/extension-pack.js +2 -2
  230. package/dist/src/cli/commands/extension.js +3 -3
  231. package/dist/src/cli/commands/gateway/logs.js +1 -1
  232. package/dist/src/cli/commands/image.js +1 -1
  233. package/dist/src/cli/commands/init.js +2 -2
  234. package/dist/src/cli/commands/models.js +1 -1
  235. package/dist/src/cli/commands/skills-test.js +1 -1
  236. package/dist/src/cli/templates.js +1 -1
  237. package/dist/src/cli/utils/gateway-client.js +1 -1
  238. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  239. package/dist/src/config/agent-profile.js +1 -1
  240. package/dist/src/config/agent-typed-models.js +1 -1
  241. package/dist/src/config/gateway-bind.js +1 -1
  242. package/dist/src/config/index.js +7 -7
  243. package/dist/src/config/loader.js +4 -4
  244. package/dist/src/config/models-json.js +2 -2
  245. package/dist/src/config/paths-state.js +1 -1
  246. package/dist/src/config/paths.js +1 -1
  247. package/dist/src/config/profile.js +1 -1
  248. package/dist/src/config/reload.js +1 -1
  249. package/dist/src/config/schema.d.ts +0 -2
  250. package/dist/src/config/schema.js +0 -3
  251. package/dist/src/config/schema.js.map +1 -1
  252. package/dist/src/config/web-patch.d.ts +0 -1
  253. package/dist/src/config/web-patch.js +0 -2
  254. package/dist/src/config/web-patch.js.map +1 -1
  255. package/dist/src/config/workspace-path.js +1 -1
  256. package/dist/src/cron/executor.js +102 -71
  257. package/dist/src/cron/executor.js.map +1 -1
  258. package/dist/src/cron/index.d.ts +1 -1
  259. package/dist/src/cron/index.js +3 -3
  260. package/dist/src/cron/run-log-store.d.ts +1 -0
  261. package/dist/src/cron/run-log-store.js +4 -2
  262. package/dist/src/cron/run-log-store.js.map +1 -1
  263. package/dist/src/cron/schedule.d.ts +10 -0
  264. package/dist/src/cron/schedule.js +85 -0
  265. package/dist/src/cron/schedule.js.map +1 -0
  266. package/dist/src/cron/service.d.ts +34 -77
  267. package/dist/src/cron/service.js +327 -264
  268. package/dist/src/cron/service.js.map +1 -1
  269. package/dist/src/cron/types.d.ts +80 -50
  270. package/dist/src/cron/validation.d.ts +358 -90
  271. package/dist/src/cron/validation.js +152 -132
  272. package/dist/src/cron/validation.js.map +1 -1
  273. package/dist/src/cron/workflow-run-completion.js +1 -1
  274. package/dist/src/daemon/constants.js +1 -1
  275. package/dist/src/daemon/install-plan.js +2 -2
  276. package/dist/src/daemon/launchd.js +2 -2
  277. package/dist/src/daemon/schtasks.js +2 -2
  278. package/dist/src/daemon/systemd.js +2 -2
  279. package/dist/src/extensions/bundle-mcp.js +1 -1
  280. package/dist/src/extensions/discover-extensions.js +2 -2
  281. package/dist/src/extensions/health.js +1 -1
  282. package/dist/src/extensions/install.js +2 -2
  283. package/dist/src/extensions/loader.js +2 -2
  284. package/dist/src/extensions/lockfile.js +3 -3
  285. package/dist/src/extensions/security.js +1 -1
  286. package/dist/src/extensions/update.js +2 -2
  287. package/dist/src/gateway/agents-admin.js +2 -2
  288. package/dist/src/gateway/chat-stream/mapper.d.ts +1 -0
  289. package/dist/src/gateway/chat-stream/mapper.js +6 -2
  290. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  291. package/dist/src/gateway/chat-stream/protocol.d.ts +2 -0
  292. package/dist/src/gateway/file-path-classifier.js +2 -2
  293. package/dist/src/gateway/hono/lib/config-payload.d.ts +0 -1
  294. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  295. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  296. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  297. package/dist/src/gateway/hono/oauth-async.js +1 -1
  298. package/dist/src/gateway/hono/routes/agents.js +1 -1
  299. package/dist/src/gateway/hono/routes/ai-assist.d.ts +3 -0
  300. package/dist/src/gateway/hono/routes/ai-assist.js +66 -0
  301. package/dist/src/gateway/hono/routes/ai-assist.js.map +1 -0
  302. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  303. package/dist/src/gateway/hono/routes/commands-skills.js +7 -0
  304. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  305. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  306. package/dist/src/gateway/hono/routes/cron.js +24 -5
  307. package/dist/src/gateway/hono/routes/cron.js.map +1 -1
  308. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  309. package/dist/src/gateway/hono/routes/home.js +5 -3
  310. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  311. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  312. package/dist/src/gateway/hono/routes/lazy-bundles.js +8 -0
  313. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  314. package/dist/src/gateway/hono/routes/models.js +1 -1
  315. package/dist/src/gateway/hono/routes/shares.js +1 -1
  316. package/dist/src/gateway/hono/routes/workflows.js +2 -2
  317. package/dist/src/gateway/hono/routes/workspace.js +2 -2
  318. package/dist/src/gateway/lock.js +3 -3
  319. package/dist/src/gateway/ports.js +1 -1
  320. package/dist/src/gateway/service/agent-runner.js +2 -2
  321. package/dist/src/gateway/service/config-coordinator.js +1 -1
  322. package/dist/src/gateway/service/marketplace-service.d.ts +22 -10
  323. package/dist/src/gateway/service/marketplace-service.js +46 -5
  324. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  325. package/dist/src/gateway/service.js +11 -5
  326. package/dist/src/gateway/service.js.map +1 -1
  327. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  328. package/dist/src/goals/goal-notifications.js +1 -1
  329. package/dist/src/goals/goal-workflow-judge.js +3 -3
  330. package/dist/src/i18n/goals-bundle.js +1 -1
  331. package/dist/src/i18n/index.js +1 -1
  332. package/dist/src/i18n/share-tool-bundle.js +2 -2
  333. package/dist/src/infra/brew.js +1 -1
  334. package/dist/src/infra/package-json.js +1 -1
  335. package/dist/src/infra/package-update-steps.js +1 -1
  336. package/dist/src/infra/path-env.js +2 -2
  337. package/dist/src/infra/restart.js +1 -1
  338. package/dist/src/infra/stable-node-path.js +1 -1
  339. package/dist/src/infra/update-check.js +1 -1
  340. package/dist/src/infra/update-global.js +1 -1
  341. package/dist/src/infra/update-lock.js +2 -2
  342. package/dist/src/infra/update-restart.js +1 -1
  343. package/dist/src/infra/update-runner.js +1 -1
  344. package/dist/src/infra/update-startup.js +1 -1
  345. package/dist/src/infra/write-file-atomic.js +2 -2
  346. package/dist/src/media/store.js +1 -1
  347. package/dist/src/notes/agent-context.js +1 -1
  348. package/dist/src/notes/service.js +1 -1
  349. package/dist/src/notes/store.js +2 -2
  350. package/dist/src/project-trust/trust-store.js +2 -2
  351. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  352. package/dist/src/providers/index.js +1 -1
  353. package/dist/src/providers/model-registry.js +4 -4
  354. package/dist/src/session/init-session-turn.js +2 -2
  355. package/dist/src/session/resolve-session.js +3 -3
  356. package/dist/src/session/session-title.js +2 -2
  357. package/dist/src/session/store-reader.d.ts +5 -0
  358. package/dist/src/session/store-reader.js +1 -0
  359. package/dist/src/session/store.js +1 -1
  360. package/dist/src/share/share-auto.js +2 -2
  361. package/dist/src/share/share-store.js +3 -3
  362. package/dist/src/share/share-thumbnail.js +2 -2
  363. package/dist/src/share/share-zip.js +1 -1
  364. package/dist/src/share/site-share-store.js +3 -3
  365. package/dist/src/share/site-static-serve.js +1 -1
  366. package/dist/src/storage/sqlite/connection.js +1 -1
  367. package/dist/src/storage/sqlite/cron-job-repository.d.ts +6 -0
  368. package/dist/src/storage/sqlite/cron-job-repository.js +70 -0
  369. package/dist/src/storage/sqlite/cron-job-repository.js.map +1 -0
  370. package/dist/src/storage/sqlite/cron-run-repository.js +0 -1
  371. package/dist/src/storage/sqlite/cron-run-repository.js.map +1 -1
  372. package/dist/src/storage/sqlite/index.d.ts +1 -0
  373. package/dist/src/storage/sqlite/index.js +2 -1
  374. package/dist/src/storage/sqlite/memory-index-repository.js +2 -2
  375. package/dist/src/storage/sqlite/migrations/009_cron_jobs.sql +24 -0
  376. package/dist/src/storage/sqlite/migrations/discover.js +1 -1
  377. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  378. package/dist/src/storage/sqlite/migrations/runner.js +4 -4
  379. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  380. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  381. package/dist/src/storage/sqlite/schema.js +2 -2
  382. package/dist/src/storage/sqlite/schema.sql +25 -0
  383. package/dist/src/tui/clipboard-image.js +3 -3
  384. package/dist/src/tui/extension-host/load-extensions.js +1 -1
  385. package/dist/src/tui/theme-manager.js +1 -1
  386. package/dist/src/tui/tui-command-formatters.js +4 -4
  387. package/dist/src/tui/tui-commands.js +2 -2
  388. package/dist/src/tui/tui-keybindings-file.js +1 -1
  389. package/dist/src/tui/tui-scoped-models.js +2 -2
  390. package/dist/src/tui/tui-settings.js +1 -1
  391. package/dist/src/tui/tui-startup-resources.js +1 -1
  392. package/dist/src/tui/tui.js +6 -6
  393. package/dist/src/tunnel/frpc-binary.js +4 -4
  394. package/dist/src/tunnel/frpc-config.js +1 -1
  395. package/dist/src/tunnel/frpc-extract.js +1 -1
  396. package/dist/src/tunnel/tunnel-state.js +1 -1
  397. package/dist/src/utils/logger/audit.js +1 -1
  398. package/dist/src/utils/logger/log-store.js +1 -1
  399. package/dist/src/utils/logger/rotation.js +1 -1
  400. package/dist/src/utils/logger/streams.js +1 -1
  401. package/dist/src/voice/tts/audio.js +1 -1
  402. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  403. package/dist/src/workflows/draft/workflow-draft-service.js +1 -1
  404. package/dist/src/workflows/engine/projector.js +23 -14
  405. package/dist/src/workflows/engine/projector.js.map +1 -1
  406. package/dist/src/workflows/engine/workflow-engine.d.ts +1 -0
  407. package/dist/src/workflows/engine/workflow-engine.js +36 -0
  408. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  409. package/dist/src/workflows/index.js +1 -1
  410. package/dist/src/workflows/service/workflow-run-service.js +2 -2
  411. package/dist/src/workflows/service/workflow-session-bridge.js +2 -2
  412. package/dist/src/workflows/store/event-store.js +1 -1
  413. package/dist/src/workflows/store/run-store.js +1 -1
  414. package/package.json +2 -3
  415. package/dist/gateway/static/root/assets/agent-browser-settings-page-B-0zGjt8.js +0 -6
  416. package/dist/gateway/static/root/assets/agents-DwDnJlXT.js +0 -71
  417. package/dist/gateway/static/root/assets/connectors-settings-DDvHo9in.js +0 -2
  418. package/dist/gateway/static/root/assets/cron-api-Dj_UZKST.js +0 -1
  419. package/dist/gateway/static/root/assets/cron-page-Dv7GII9G.js +0 -1
  420. package/dist/gateway/static/root/assets/cron-schedule-picker-DH10KgD6.js +0 -1
  421. package/dist/gateway/static/root/assets/dreaming-settings-L2rgZDQl.js +0 -1
  422. package/dist/gateway/static/root/assets/extension-settings-page-m_UQYkVc.js +0 -1
  423. package/dist/gateway/static/root/assets/gateway-settings-CS177xni.js +0 -1
  424. package/dist/gateway/static/root/assets/goals-page-C0FujUB5.js +0 -2
  425. package/dist/gateway/static/root/assets/index-COkF54xv.js +0 -121
  426. package/dist/gateway/static/root/assets/index-DIaSNGEO.css +0 -1
  427. package/dist/gateway/static/root/assets/interval-presets-B29Ss_2y.js +0 -2
  428. package/dist/gateway/static/root/assets/messages-Csef1aW7.js +0 -3
  429. package/dist/gateway/static/root/assets/models-hub-panel-DHGiTIvf.js +0 -2
  430. package/dist/gateway/static/root/assets/note-detail-page-BM7zlDiT.js +0 -2
  431. package/dist/gateway/static/root/assets/schedule-field-BPAWui3P.js +0 -1
  432. package/dist/gateway/static/root/assets/schedule-summary-B-hdSRdR.js +0 -1
  433. package/dist/gateway/static/root/assets/settings-advanced-gate-BYS-rpzn.js +0 -1
  434. package/dist/gateway/static/root/assets/settings-form-section-BsrK7TBF.js +0 -1
  435. package/dist/gateway/static/root/assets/setup-status-panel-DJiksNu4.js +0 -1
  436. package/dist/gateway/static/root/assets/skill-reload-api-CU9i0nJV.js +0 -1
  437. package/dist/gateway/static/root/assets/skills-page-ERbdWENm.js +0 -2
  438. package/dist/gateway/static/root/assets/use-agent-defaults-form-D3FGVLZb.js +0 -1
  439. package/dist/gateway/static/root/favicon-16.png +0 -0
  440. package/dist/gateway/static/root/favicon-32.png +0 -0
  441. package/dist/src/cron/persistence.d.ts +0 -62
  442. package/dist/src/cron/persistence.js +0 -188
  443. package/dist/src/cron/persistence.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"skill-manager.js","names":[],"sources":["../../../../src/agent/skills/skill-manager.ts"],"sourcesContent":["/**\n * Skill Manager - Manages skills loading and expansion\n *\n * Handles skill initialization, reloading, and command expansion.\n */\n\nimport { createSkillLoader, type Skill } from './index.js';\nimport { resolveBundledSkillsDir, resolveStateDir } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { createSkillConfigManager, isSkillEnabled } from './config.js';\nimport { formatSkillsForPrompt, selectSkillsVisibleInPrompt } from './format-skills-prompt.js';\n\nconst log = createLogger('SkillManager');\n\nexport interface SkillDiagnostic {\n type: 'collision' | 'warning' | 'error' | 'info';\n skillName: string;\n message: string;\n}\n\nexport interface SkillLoadResult {\n skills: Skill[];\n prompt: string;\n diagnostics: SkillDiagnostic[];\n}\n\nexport class SkillManager {\n private skillPrompt: string = '';\n private skills: Skill[] = [];\n private skillLoader = createSkillLoader();\n private workspace: string;\n private bundledSkillsDir: string;\n\n constructor(workspace: string, bundledSkillsDir?: string) {\n this.workspace = workspace;\n this.bundledSkillsDir = bundledSkillsDir || resolveBundledSkillsDir();\n this.initialize();\n }\n\n /**\n * Initialize skills from workspace and bundled directories\n */\n private initialize(): void {\n const result = this.skillLoader.init(this.workspace, this.bundledSkillsDir);\n this.skillPrompt = result.prompt;\n this.skills = result.skills;\n\n // Log diagnostics\n for (const diag of result.diagnostics) {\n if (diag.type === 'collision') {\n log.warn({ skill: diag.skillName, message: diag.message }, 'Skill collision');\n } else if (diag.type === 'warning') {\n log.warn({ skill: diag.skillName, message: diag.message }, 'Skill warning');\n } else if (diag.type === 'error') {\n log.error({ skill: diag.skillName, message: diag.message }, 'Skill error');\n } else {\n log.info({ skill: diag.skillName, message: diag.message }, 'Skill info');\n }\n }\n\n log.debug({ count: result.skills.length }, 'Skills loaded');\n }\n\n /**\n * Recompute skill XML prompt from current skills.json (no disk rescan).\n */\n refreshPromptFromConfig(): void {\n this.skillLoader.refreshPromptFromConfig();\n this.skillPrompt = this.skillLoader.getPrompt();\n }\n\n /**\n * Reload skills from disk\n */\n reload(): void {\n log.info('Reloading skills...');\n const result = this.skillLoader.reload();\n this.skillPrompt = result.prompt;\n this.skills = result.skills;\n\n for (const diag of result.diagnostics) {\n if (diag.type === 'collision') {\n log.warn({ skill: diag.skillName, message: diag.message }, 'Skill collision');\n } else if (diag.type === 'warning') {\n log.warn({ skill: diag.skillName, message: diag.message }, 'Skill warning');\n } else if (diag.type === 'error') {\n log.error({ skill: diag.skillName, message: diag.message }, 'Skill error');\n }\n }\n\n log.info({ count: result.skills.length }, 'Skills reloaded');\n }\n\n /**\n * Get the skill prompt to append to system prompt\n */\n getPrompt(): string {\n return this.skillPrompt;\n }\n\n /**\n * `<available_skills>` XML with optional per-agent allowlist and/or tool-based gating.\n * When both arguments are omitted, returns the cached prompt from disk load (no tool gating).\n */\n getPromptForSkillAllowlist(\n allowlist: string[] | undefined,\n registeredToolNames?: string[],\n ): string {\n if (allowlist === undefined && registeredToolNames === undefined) {\n return this.getPrompt();\n }\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n return formatSkillsForPrompt(this.getSkills(), skillsConfig, {\n skillAllowlist: allowlist,\n registeredToolNames,\n });\n }\n\n /** Skills visible for prompts and skills_list given the same indexing options as {@link getPromptForSkillAllowlist}. */\n selectSkillsForAgentIndexing(options?: {\n skillAllowlist?: string[];\n registeredToolNames?: string[];\n }): Skill[] {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n return selectSkillsVisibleInPrompt(this.getSkills(), skillsConfig, options);\n }\n\n /**\n * Get all loaded skills\n */\n getSkills(): Skill[] {\n return [...this.skills];\n }\n\n /**\n * Get skill names\n */\n getSkillNames(): string[] {\n return this.skills.map((s) => s.name);\n }\n\n /** Names of skills included in the agent system prompt (`<available_skills>`). */\n getSkillNamesForPrompt(): string[] {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n return this.getSkills()\n .filter((s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig))\n .map((s) => s.name);\n }\n\n /**\n * Skills that are enabled for model discovery (respects skills.json and requirement checks).\n */\n getEnabledSkills(): Skill[] {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n return this.getSkills().filter(\n (s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig),\n );\n }\n\n /**\n * Like {@link getEnabledSkills} plus optional allowlist and tool gating (matches `<available_skills>`).\n */\n getEnabledSkillsForAgentSession(options?: {\n skillAllowlist?: string[];\n registeredToolNames?: string[];\n }): Skill[] {\n return this.selectSkillsForAgentIndexing(options);\n }\n\n /**\n * Find a skill by name\n */\n findSkill(name: string): Skill | undefined {\n return this.skills.find(s => s.name === name);\n }\n\n /**\n * Check if a skill exists\n */\n hasSkill(name: string): boolean {\n return this.skills.some(s => s.name === name);\n }\n\n /**\n * Expand a skill command into a full skill block\n */\n expandCommand(text: string, options?: { skillAllowlist?: string[]; registeredToolNames?: string[] }): string {\n if (!text.startsWith('/skill:')) {\n return text;\n }\n\n const { skillName, args } = this.parseSkillCommand(text);\n const visible = this.selectSkillsForAgentIndexing(options);\n const skill = visible.find((s) => s.name === skillName);\n\n if (!skill) {\n log.warn({ skillName }, 'Skill not visible for expansion');\n return text;\n }\n\n return this.buildSkillBlock(skill, args);\n }\n\n /**\n * Parse a /skill: command\n */\n private parseSkillCommand(text: string): { skillName: string; args?: string } {\n // Format: /skill:name args...\n const withoutPrefix = text.slice(7); // Remove '/skill:'\n const spaceIndex = withoutPrefix.indexOf(' ');\n\n if (spaceIndex === -1) {\n return { skillName: withoutPrefix.trim() };\n }\n\n return {\n skillName: withoutPrefix.slice(0, spaceIndex).trim(),\n args: withoutPrefix.slice(spaceIndex + 1).trim(),\n };\n }\n\n /**\n * Build a skill block for inclusion in the prompt\n */\n private buildSkillBlock(skill: Skill, args?: string): string {\n let block = `\\n\\n## Skill: ${skill.name}\\n\\n`;\n \n if (skill.description) {\n block += `${skill.description}\\n\\n`;\n }\n\n // Include raw skill content (SKILL.md content)\n if (skill.content) {\n block += `${skill.content}\\n\\n`;\n }\n\n if (args) {\n block += `**Arguments**: ${args}\\n\\n`;\n }\n\n return block;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"skill-manager.js","names":[],"sources":["../../../../src/agent/skills/skill-manager.ts"],"sourcesContent":["/**\n * Skill Manager - Manages skills loading and expansion\n *\n * Handles skill initialization, reloading, and command expansion.\n */\n\nimport { createSkillLoader } from './index.js';\nimport { resolveBundledSkillsDir, resolveStateDir } from '../../config/paths.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { createSkillConfigManager, isSkillEnabled } from './config.js';\nimport { formatSkillsForPrompt, selectSkillsVisibleInPrompt } from './format-skills-prompt.js';\nimport type {\n LoadSkillsResult,\n Skill,\n SkillDiagnostic,\n SkillRuntimeStatus,\n} from './types.js';\n\nconst log = createLogger('SkillManager');\n\nexport interface SkillLoadResult {\n skills: Skill[];\n prompt: string;\n diagnostics: SkillDiagnostic[];\n}\n\nexport class SkillManager {\n private skillPrompt: string = '';\n private skills: Skill[] = [];\n private skillLoader = createSkillLoader();\n private workspace: string;\n private bundledSkillsDir: string;\n private version = 0;\n private loadedAt = 0;\n private reloadInProgress = false;\n private reloadPending = false;\n private lastReloadStartedAt: number | undefined;\n private lastReloadFinishedAt: number | undefined;\n private lastReloadReason: SkillRuntimeStatus['lastReloadReason'];\n private lastReloadOk: boolean | undefined;\n private lastReloadError: string | undefined;\n\n constructor(workspace: string, bundledSkillsDir?: string) {\n this.workspace = workspace;\n this.bundledSkillsDir = bundledSkillsDir || resolveBundledSkillsDir();\n this.initialize();\n }\n\n /**\n * Initialize skills from workspace and bundled directories\n */\n private initialize(): void {\n this.runReload('initial', () => this.skillLoader.init(this.workspace, this.bundledSkillsDir));\n }\n\n /**\n * Recompute skill XML prompt from current skills.json (no disk rescan).\n */\n refreshPromptFromConfig(): void {\n this.skillLoader.refreshPromptFromConfig();\n this.skillPrompt = this.skillLoader.getPrompt();\n this.version += 1;\n this.loadedAt = Date.now();\n this.lastReloadReason = 'config';\n this.lastReloadOk = true;\n this.lastReloadError = undefined;\n }\n\n /**\n * Reload skills from disk\n */\n reload(): void {\n this.runReload('disk', () => this.skillLoader.reload());\n }\n\n private runReload(reason: NonNullable<SkillRuntimeStatus['lastReloadReason']>, load: () => LoadSkillsResult): void {\n if (this.reloadInProgress) {\n this.reloadPending = true;\n return;\n }\n\n do {\n this.reloadPending = false;\n this.reloadInProgress = true;\n this.lastReloadStartedAt = Date.now();\n this.lastReloadReason = reason;\n try {\n const result = load();\n this.applyLoadResult(result);\n this.lastReloadOk = true;\n this.lastReloadError = undefined;\n log.info({ count: result.skills.length, version: this.version }, 'Skills reloaded');\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n this.lastReloadOk = false;\n this.lastReloadError = errorMessage;\n log.error({ err, errorMessage }, `Skills reload failed: ${errorMessage}`);\n } finally {\n this.lastReloadFinishedAt = Date.now();\n this.reloadInProgress = false;\n }\n } while (this.reloadPending);\n }\n\n private applyLoadResult(result: LoadSkillsResult): void {\n this.skillPrompt = result.prompt;\n this.skills = result.skills;\n this.version += 1;\n this.loadedAt = Date.now();\n\n for (const diag of result.diagnostics) {\n if (diag.type === 'collision') {\n log.warn({ skill: diag.skillName, path: diag.path, message: diag.message }, 'Skill collision');\n } else if (diag.type === 'warning') {\n log.warn({ skill: diag.skillName, path: diag.path, message: diag.message }, 'Skill warning');\n } else if (diag.type === 'error') {\n log.error({ skill: diag.skillName, path: diag.path, message: diag.message }, 'Skill error');\n }\n }\n }\n\n /**\n * Get the skill prompt to append to system prompt\n */\n getPrompt(): string {\n return this.skillPrompt;\n }\n\n /**\n * `<available_skills>` XML with optional per-agent allowlist and/or tool-based gating.\n * When both arguments are omitted, returns the cached prompt from disk load (no tool gating).\n */\n getPromptForSkillAllowlist(\n allowlist: string[] | undefined,\n registeredToolNames?: string[],\n ): string {\n if (allowlist === undefined && registeredToolNames === undefined) {\n return this.getPrompt();\n }\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n return formatSkillsForPrompt(this.getSkills(), skillsConfig, {\n skillAllowlist: allowlist,\n registeredToolNames,\n });\n }\n\n /** Skills visible for prompts and skills_list given the same indexing options as {@link getPromptForSkillAllowlist}. */\n selectSkillsForAgentIndexing(options?: {\n skillAllowlist?: string[];\n registeredToolNames?: string[];\n }): Skill[] {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n return selectSkillsVisibleInPrompt(this.getSkills(), skillsConfig, options);\n }\n\n /**\n * Get all loaded skills\n */\n getSkills(): Skill[] {\n return [...this.skills];\n }\n\n getDiagnostics(): SkillDiagnostic[] {\n return this.skillLoader.getDiagnostics();\n }\n\n getVersion(): string {\n return String(this.version);\n }\n\n getLoadedAt(): number {\n return this.loadedAt;\n }\n\n getStatus(): SkillRuntimeStatus {\n return {\n version: this.getVersion(),\n loadedAt: this.loadedAt,\n reloadInProgress: this.reloadInProgress,\n reloadPending: this.reloadPending,\n ...(this.lastReloadStartedAt !== undefined ? { lastReloadStartedAt: this.lastReloadStartedAt } : {}),\n ...(this.lastReloadFinishedAt !== undefined ? { lastReloadFinishedAt: this.lastReloadFinishedAt } : {}),\n ...(this.lastReloadReason !== undefined ? { lastReloadReason: this.lastReloadReason } : {}),\n ...(this.lastReloadOk !== undefined ? { lastReloadOk: this.lastReloadOk } : {}),\n ...(this.lastReloadError !== undefined ? { lastReloadError: this.lastReloadError } : {}),\n };\n }\n\n /**\n * Get skill names\n */\n getSkillNames(): string[] {\n return this.skills.map((s) => s.name);\n }\n\n /** Names of skills included in the agent system prompt (`<available_skills>`). */\n getSkillNamesForPrompt(): string[] {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n return this.getSkills()\n .filter((s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig))\n .map((s) => s.name);\n }\n\n /**\n * Skills that are enabled for model discovery (respects skills.json and requirement checks).\n */\n getEnabledSkills(): Skill[] {\n const skillsConfig = createSkillConfigManager(resolveStateDir()).load();\n return this.getSkills().filter(\n (s) => !s.disableModelInvocation && isSkillEnabled(s, skillsConfig),\n );\n }\n\n /**\n * Like {@link getEnabledSkills} plus optional allowlist and tool gating (matches `<available_skills>`).\n */\n getEnabledSkillsForAgentSession(options?: {\n skillAllowlist?: string[];\n registeredToolNames?: string[];\n }): Skill[] {\n return this.selectSkillsForAgentIndexing(options);\n }\n\n /**\n * Find a skill by name\n */\n findSkill(name: string): Skill | undefined {\n return this.skills.find(s => s.name === name);\n }\n\n /**\n * Check if a skill exists\n */\n hasSkill(name: string): boolean {\n return this.skills.some(s => s.name === name);\n }\n\n /**\n * Expand a skill command into a full skill block\n */\n expandCommand(text: string, options?: { skillAllowlist?: string[]; registeredToolNames?: string[] }): string {\n if (!text.startsWith('/skill:')) {\n return text;\n }\n\n const { skillName, args } = this.parseSkillCommand(text);\n const visible = this.selectSkillsForAgentIndexing(options);\n const skill = visible.find((s) => s.name === skillName);\n\n if (!skill) {\n log.warn({ skillName }, 'Skill not visible for expansion');\n return text;\n }\n\n return this.buildSkillBlock(skill, args);\n }\n\n /**\n * Parse a /skill: command\n */\n private parseSkillCommand(text: string): { skillName: string; args?: string } {\n // Format: /skill:name args...\n const withoutPrefix = text.slice(7); // Remove '/skill:'\n const spaceIndex = withoutPrefix.indexOf(' ');\n\n if (spaceIndex === -1) {\n return { skillName: withoutPrefix.trim() };\n }\n\n return {\n skillName: withoutPrefix.slice(0, spaceIndex).trim(),\n args: withoutPrefix.slice(spaceIndex + 1).trim(),\n };\n }\n\n /**\n * Build a skill block for inclusion in the prompt\n */\n private buildSkillBlock(skill: Skill, args?: string): string {\n let block = `\\n\\n## Skill: ${skill.name}\\n\\n`;\n \n if (skill.description) {\n block += `${skill.description}\\n\\n`;\n }\n\n // Include raw skill content (SKILL.md content)\n if (skill.content) {\n block += `${skill.content}\\n\\n`;\n }\n\n if (args) {\n block += `**Arguments**: ${args}\\n\\n`;\n }\n\n return block;\n }\n}\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { resolve, sep } from "path";
2
1
  import { existsSync, realpathSync } from "fs";
2
+ import { resolve, sep } from "path";
3
3
  //#region src/agent/skills/skill-view-path.ts
4
4
  /**
5
5
  * Resolve safe paths for skill_view: only SKILL.md (default) or files under allowlisted subdirs.
@@ -4,8 +4,8 @@ import { parseFrontmatter } from "../../markdown/frontmatter.js";
4
4
  import { hasBinary } from "./installer.js";
5
5
  import { scanSkillDirectory } from "./scanner.js";
6
6
  import { parseSkillMetadata } from "./parse-skill-metadata.js";
7
- import { basename, join, relative } from "path";
8
7
  import { existsSync, readFileSync, readdirSync } from "fs";
8
+ import { basename, join, relative } from "path";
9
9
  //#region src/agent/skills/test-framework.ts
10
10
  /**
11
11
  * Skill Test Framework
@@ -207,6 +207,17 @@ export interface SkillDiagnostic {
207
207
  message: string;
208
208
  path?: string;
209
209
  }
210
+ export interface SkillRuntimeStatus {
211
+ version: string;
212
+ loadedAt: number;
213
+ reloadInProgress: boolean;
214
+ reloadPending: boolean;
215
+ lastReloadStartedAt?: number;
216
+ lastReloadFinishedAt?: number;
217
+ lastReloadReason?: 'initial' | 'disk' | 'config';
218
+ lastReloadOk?: boolean;
219
+ lastReloadError?: string;
220
+ }
210
221
  export interface SkillSnapshot {
211
222
  version: string;
212
223
  skills: SkillEntry[];
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { join } from "path";
4
3
  import { watch } from "fs";
4
+ import { join } from "path";
5
5
  //#region src/agent/skills/watcher.ts
6
6
  /**
7
7
  * Skill Watcher
@@ -1,8 +1,8 @@
1
1
  import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentProfileDir, resolveAgentWorkspaceDir } from "./agent-scope.js";
2
2
  import { WORKSPACE_FILES, init_paths } from "../config/paths.js";
3
3
  import { applyAgentConfig } from "../commands/agents.config.js";
4
- import { join } from "node:path";
5
4
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
5
+ import { join } from "node:path";
6
6
  //#region src/agent/starter-agents.ts
7
7
  init_paths();
8
8
  init_agent_scope();
@@ -4,7 +4,11 @@ export declare function scanCronPrompt(prompt: string): string | null;
4
4
  export type CronjobToolParams = {
5
5
  action: 'list' | 'create' | 'update' | 'remove' | 'enable' | 'disable' | 'history';
6
6
  name?: string;
7
- schedule?: string;
7
+ scheduleKind?: 'cron' | 'at' | 'every';
8
+ cronExpr?: string;
9
+ at?: string;
10
+ everyMs?: number;
11
+ tz?: string;
8
12
  message?: string;
9
13
  workflowDefinitionId?: string;
10
14
  workflowGoal?: string;
@@ -14,8 +18,7 @@ export type CronjobToolParams = {
14
18
  waitForCompletion?: boolean;
15
19
  deliveryChannel?: string;
16
20
  deliveryTo?: string;
17
- timezone?: string;
18
- sessionTarget?: 'main' | 'isolated';
21
+ sessionTarget?: 'main' | 'isolated' | 'current';
19
22
  agentId?: string;
20
23
  workingDirectory?: string;
21
24
  jobId?: string;
@@ -1,5 +1,5 @@
1
+ import { describeSchedule } from "../../cron/schedule.js";
1
2
  import { getCronPayloadText } from "../../cron/job-content.js";
2
- import { DEFAULT_WORKFLOW_CRON_WAIT_MS } from "../../cron/workflow-run-completion.js";
3
3
  import { Type } from "@sinclair/typebox";
4
4
  //#region src/agent/tools/cronjob-tool.ts
5
5
  const CRON_THREAT_PATTERNS = [
@@ -25,9 +25,17 @@ const CronjobSchema = Type.Object({
25
25
  Type.Literal("history")
26
26
  ], { description: "Action to perform on cron jobs" }),
27
27
  name: Type.Optional(Type.String({ description: "Human-readable job name" })),
28
- schedule: Type.Optional(Type.String({ description: "Cron schedule expression. Examples:\n \"0 9 * * *\" = every day at 9:00 AM\n \"*/30 * * * *\" = every 30 minutes\n \"0 9 * * 1-5\" = weekdays at 9:00 AM\n \"0 0 1 * *\" = first day of each month" })),
28
+ scheduleKind: Type.Optional(Type.Union([
29
+ Type.Literal("cron"),
30
+ Type.Literal("at"),
31
+ Type.Literal("every")
32
+ ], { description: "Schedule kind. Use cronExpr for cron, at for one-time ISO time, everyMs for interval." })),
33
+ cronExpr: Type.Optional(Type.String({ description: "Cron schedule expression. Examples:\n \"0 9 * * *\" = every day at 9:00 AM\n \"*/30 * * * *\" = every 30 minutes\n \"0 9 * * 1-5\" = weekdays at 9:00 AM\n \"0 0 1 * *\" = first day of each month" })),
34
+ at: Type.Optional(Type.String({ description: "One-time run timestamp as ISO 8601 string." })),
35
+ everyMs: Type.Optional(Type.Number({ description: "Fixed interval in milliseconds." })),
36
+ tz: Type.Optional(Type.String({ description: "IANA timezone for cronExpr, e.g. Asia/Shanghai." })),
29
37
  message: Type.Optional(Type.String({ description: "Instruction for the agent when the job runs (agentTurn payload; typically a fresh session)." })),
30
- workflowDefinitionId: Type.Optional(Type.String({ description: "Workflow definition id for a direct workflowRun job (mutually exclusive with message on create)." })),
38
+ workflowDefinitionId: Type.Optional(Type.String({ description: "Workflow definition id for a workflowRun job (mutually exclusive with message on create)." })),
31
39
  workflowGoal: Type.Optional(Type.String({ description: "Optional goal override when creating a workflowRun job." })),
32
40
  workflowInputJson: Type.Optional(Type.String({ description: "JSON object for workflow input payload (workflowRun create/update)." })),
33
41
  goalId: Type.Optional(Type.String({ description: "Durable goal id for a goalContinue job (mutually exclusive with message and workflowDefinitionId)." })),
@@ -35,7 +43,6 @@ const CronjobSchema = Type.Object({
35
43
  waitForCompletion: Type.Optional(Type.Boolean({ description: "For workflowRun jobs: when true (default), cron waits for terminal status before succeeding." })),
36
44
  deliveryChannel: Type.Optional(Type.String({ description: "Delivery channel when workflow completes (e.g. telegram)." })),
37
45
  deliveryTo: Type.Optional(Type.String({ description: "Delivery recipient chat id when workflow completes." })),
38
- timezone: Type.Optional(Type.String({ description: "IANA timezone (e.g. Asia/Shanghai, America/New_York). Must be one supported by the cron store." })),
39
46
  sessionTarget: Type.Optional(Type.Union([Type.Literal("main"), Type.Literal("isolated")], { description: "\"main\" uses the main session context; \"isolated\" (default on create) uses a separate session per run." })),
40
47
  agentId: Type.Optional(Type.String({ description: "Agent profile id for isolated jobs (session key). Omit to use the configured default agent (usually `main`)." })),
41
48
  workingDirectory: Type.Optional(Type.String({ description: "Absolute workspace path on the gateway host for isolated jobs. Omit to use the agent default workspace." })),
@@ -51,21 +58,47 @@ function textResult(text) {
51
58
  };
52
59
  }
53
60
  function formatJob(job) {
54
- const status = job.enabled ? "▶️ active" : "⏸️ disabled";
61
+ const status = job.enabled ? "active" : "disabled";
55
62
  const payloadText = getCronPayloadText(job);
56
63
  const truncatedPayload = payloadText.length > 100 ? `${payloadText.slice(0, 100)}...` : payloadText;
57
64
  const payloadLine = job.payload.kind === "workflowRun" ? ` Workflow: ${job.payload.definitionId}${job.payload.goal ? ` — ${job.payload.goal}` : ""}` : ` Message: ${truncatedPayload}`;
58
65
  return [
59
66
  `${status} ${job.name ?? "(unnamed)"} (${job.id})`,
60
- ` Schedule: ${job.schedule}${job.timezone ? ` (${job.timezone})` : ""}`,
67
+ ` Schedule: ${describeSchedule(job.schedule)}`,
61
68
  ` Type: ${job.payload.kind}`,
62
69
  payloadLine,
63
- ` Next run: ${job.next_run ?? "N/A"}`,
70
+ ` Next run: ${job.state.nextRunAtMs ? new Date(job.state.nextRunAtMs).toISOString() : "N/A"}`,
64
71
  ` Session: ${job.sessionTarget ?? "main"}`,
65
72
  ` Agent: ${job.agentId?.trim() || "(default)"}`,
66
73
  ` Workspace: ${job.workingDirectory?.trim() || "(agent default)"}`
67
74
  ].join("\n");
68
75
  }
76
+ function scheduleFromParams(params) {
77
+ const kind = params.scheduleKind;
78
+ if (!kind) return void 0;
79
+ if (kind === "cron") {
80
+ const expr = params.cronExpr?.trim();
81
+ if (!expr) return void 0;
82
+ return {
83
+ kind,
84
+ expr,
85
+ ...params.tz?.trim() ? { tz: params.tz.trim() } : {}
86
+ };
87
+ }
88
+ if (kind === "at") {
89
+ const at = params.at?.trim();
90
+ if (!at) return void 0;
91
+ return {
92
+ kind,
93
+ at
94
+ };
95
+ }
96
+ if (!Number.isFinite(params.everyMs) || !params.everyMs || params.everyMs <= 0) return void 0;
97
+ return {
98
+ kind,
99
+ everyMs: Math.floor(params.everyMs)
100
+ };
101
+ }
69
102
  function formatExecution(exec) {
70
103
  const dur = exec.duration != null ? `${(exec.duration / 1e3).toFixed(1)}s` : "N/A";
71
104
  const lines = [`[${exec.status}] ${exec.startedAt} (${dur})`];
@@ -77,7 +110,7 @@ function createCronjobTool(deps) {
77
110
  return {
78
111
  name: "cronjob",
79
112
  label: "⏰ Cronjob",
80
- description: "Manage scheduled tasks (cron jobs) that run automatically.\n\nJobs can run an agent message (agentTurn), a workflow directly (workflowRun), or continue a durable goal (goalContinue).\n\nACTIONS:\n- list: Show all scheduled jobs with status and next run time\n- create: Create a job (schedule + exactly one of message, workflowDefinitionId, or goalId)\n- update: Change schedule, message, workflow fields, name, timezone, sessionTarget, agentId, or workingDirectory (requires jobId)\n- remove: Delete a job (requires jobId)\n- enable / disable: Toggle a job (requires jobId)\n- history: Recent executions for a job (requires jobId)",
113
+ description: "Manage scheduled tasks (cron jobs) that run automatically.\n\nJobs can run an agent message (agentTurn), a workflow directly (workflowRun), or continue a durable goal (goalContinue).\n\nACTIONS:\n- list: Show all scheduled jobs with status and next run time\n- create: Create a job (scheduleKind plus exactly one of message, workflowDefinitionId, or goalId)\n- update: Change schedule, message, workflow fields, name, sessionTarget, agentId, or workingDirectory (requires jobId)\n- remove: Delete a job (requires jobId)\n- enable / disable: Toggle a job (requires jobId)\n- history: Recent executions for a job (requires jobId)",
81
114
  parameters: CronjobSchema,
82
115
  async execute(_toolCallId, params, _signal) {
83
116
  const cron = deps.getCronService();
@@ -104,13 +137,13 @@ function createCronjobTool(deps) {
104
137
  goalId,
105
138
  hasMessage ? "message" : ""
106
139
  ].filter(Boolean).length;
107
- if (!params.schedule?.trim() || targetCount !== 1) return textResult("Error: create requires schedule and exactly one of message, workflowDefinitionId, or goalId.");
140
+ const schedule = scheduleFromParams(params);
141
+ if (!schedule || targetCount !== 1) return textResult("Error: create requires scheduleKind with matching cronExpr/at/everyMs and exactly one of message, workflowDefinitionId, or goalId.");
108
142
  if (hasMessage) {
109
143
  const scanResult = scanCronPrompt(params.message);
110
144
  if (scanResult) return textResult(`Error: ${scanResult}`);
111
145
  }
112
146
  let payload;
113
- let timeout;
114
147
  let sessionTarget = params.sessionTarget ?? "isolated";
115
148
  let delivery;
116
149
  if (goalId) {
@@ -137,9 +170,8 @@ function createCronjobTool(deps) {
137
170
  ...params.waitForCompletion === false ? { waitForCompletion: false } : {}
138
171
  };
139
172
  sessionTarget = "isolated";
140
- timeout = DEFAULT_WORKFLOW_CRON_WAIT_MS;
141
173
  if (params.deliveryChannel?.trim() && params.deliveryTo?.trim()) delivery = {
142
- mode: "direct",
174
+ mode: "announce",
143
175
  channel: params.deliveryChannel.trim(),
144
176
  to: params.deliveryTo.trim()
145
177
  };
@@ -147,22 +179,21 @@ function createCronjobTool(deps) {
147
179
  kind: "agentTurn",
148
180
  message: params.message.trim()
149
181
  };
150
- const result = await cron.addJob(params.schedule.trim(), {
182
+ const result = await cron.addJob(schedule, {
151
183
  name: params.name?.trim() || void 0,
152
- timezone: params.timezone?.trim() || void 0,
153
184
  sessionTarget,
154
- ...timeout ? { timeout } : {},
155
185
  ...delivery ? { delivery } : {},
156
186
  ...params.agentId?.trim() ? { agentId: params.agentId.trim() } : {},
157
187
  ...params.workingDirectory?.trim() ? { workingDirectory: params.workingDirectory.trim() } : {},
158
188
  payload
159
189
  });
160
- return textResult(`Created ${goalId ? `goal job (${goalId})` : workflowId ? `workflow job (${workflowId})` : "job"}${params.name ? ` "${params.name.trim()}"` : ""} (${result.id})\nSchedule: ${result.schedule}`);
190
+ return textResult(`Created ${goalId ? `goal job (${goalId})` : workflowId ? `workflow job (${workflowId})` : "job"}${params.name ? ` "${params.name.trim()}"` : ""} (${result.id})\nSchedule: ${describeSchedule(result.schedule)}`);
161
191
  }
162
192
  case "update": {
163
193
  if (!params.jobId?.trim()) return textResult("Error: update requires jobId.");
164
194
  const updates = {};
165
- if (params.schedule?.trim()) updates.schedule = params.schedule.trim();
195
+ const nextSchedule = scheduleFromParams(params);
196
+ if (nextSchedule) updates.schedule = nextSchedule;
166
197
  if (params.message != null && params.message.trim()) {
167
198
  const scanResult = scanCronPrompt(params.message);
168
199
  if (scanResult) return textResult(`Error: ${scanResult}`);
@@ -196,19 +227,23 @@ function createCronjobTool(deps) {
196
227
  ...params.waitForCompletion === false ? { waitForCompletion: false } : {}
197
228
  };
198
229
  updates.sessionTarget = "isolated";
199
- updates.timeout = DEFAULT_WORKFLOW_CRON_WAIT_MS;
200
230
  }
201
231
  if (params.deliveryChannel?.trim() && params.deliveryTo?.trim()) updates.delivery = {
202
- mode: "direct",
232
+ mode: "announce",
203
233
  channel: params.deliveryChannel.trim(),
204
234
  to: params.deliveryTo.trim()
205
235
  };
206
- if (params.timezone?.trim()) updates.timezone = params.timezone.trim();
207
236
  if (params.name !== void 0) updates.name = params.name.trim() || void 0;
208
237
  if (params.sessionTarget !== void 0) updates.sessionTarget = params.sessionTarget;
209
- if (params.agentId !== void 0) updates.agentId = params.agentId.trim() || null;
210
- if (params.workingDirectory !== void 0) updates.workingDirectory = params.workingDirectory.trim() || null;
211
- if (Object.keys(updates).length === 0) return textResult("Error: update requires at least one of schedule, message, workflowDefinitionId, name, timezone, sessionTarget, agentId, workingDirectory, deliveryChannel/deliveryTo.");
238
+ if (params.agentId !== void 0) {
239
+ const t = params.agentId.trim();
240
+ if (t) updates.agentId = t;
241
+ }
242
+ if (params.workingDirectory !== void 0) {
243
+ const t = params.workingDirectory.trim();
244
+ if (t) updates.workingDirectory = t;
245
+ }
246
+ if (Object.keys(updates).length === 0) return textResult("Error: update requires at least one of scheduleKind, message, workflowDefinitionId, name, sessionTarget, agentId, workingDirectory, deliveryChannel/deliveryTo.");
212
247
  return textResult(await cron.updateJob(params.jobId.trim(), updates) ? `Updated job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`);
213
248
  }
214
249
  case "remove":
@@ -1 +1 @@
1
- {"version":3,"file":"cronjob-tool.js","names":[],"sources":["../../../../src/agent/tools/cronjob-tool.ts"],"sourcesContent":["// Agent tool for managing scheduled cron jobs (CronService-backed)\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport type { CronService } from '../../cron/index.js';\nimport { getCronPayloadText } from '../../cron/job-content.js';\nimport { DEFAULT_WORKFLOW_CRON_WAIT_MS } from '../../cron/workflow-run-completion.js';\nimport type { CronPayload, JobData, JobExecution, JobWithNextRun } from '../../cron/types.js';\n\nconst CRON_THREAT_PATTERNS: Array<[RegExp, string]> = [\n [/ignore\\s+(previous|all|above)\\s+instructions/i, 'prompt_injection'],\n [/do\\s+not\\s+tell\\s+the\\s+user/i, 'deception'],\n [/system\\s+prompt\\s+override/i, 'sys_prompt_override'],\n [/curl\\s+[^\\n]*\\$\\{?\\w*(KEY|TOKEN|SECRET|PASSWORD)/i, 'exfil_curl'],\n [/cat\\s+[^\\n]*(\\.env|credentials|\\.netrc)/i, 'read_secrets'],\n [/rm\\s+-rf\\s+\\//i, 'destructive_rm'],\n];\n\nexport function scanCronPrompt(prompt: string): string | null {\n for (const [pattern, id] of CRON_THREAT_PATTERNS) {\n if (pattern.test(prompt)) {\n return (\n `Blocked: prompt matches threat pattern '${id}'. ` +\n 'Cron prompts must not contain injection or exfiltration payloads.'\n );\n }\n }\n return null;\n}\n\nconst CronjobSchema = Type.Object({\n action: Type.Union(\n [\n Type.Literal('list'),\n Type.Literal('create'),\n Type.Literal('update'),\n Type.Literal('remove'),\n Type.Literal('enable'),\n Type.Literal('disable'),\n Type.Literal('history'),\n ],\n { description: 'Action to perform on cron jobs' },\n ),\n\n name: Type.Optional(Type.String({ description: 'Human-readable job name' })),\n schedule: Type.Optional(\n Type.String({\n description:\n 'Cron schedule expression. Examples:\\n' +\n ' \"0 9 * * *\" = every day at 9:00 AM\\n' +\n ' \"*/30 * * * *\" = every 30 minutes\\n' +\n ' \"0 9 * * 1-5\" = weekdays at 9:00 AM\\n' +\n ' \"0 0 1 * *\" = first day of each month',\n }),\n ),\n message: Type.Optional(\n Type.String({\n description:\n 'Instruction for the agent when the job runs (agentTurn payload; typically a fresh session).',\n }),\n ),\n workflowDefinitionId: Type.Optional(\n Type.String({\n description:\n 'Workflow definition id for a direct workflowRun job (mutually exclusive with message on create).',\n }),\n ),\n workflowGoal: Type.Optional(\n Type.String({ description: 'Optional goal override when creating a workflowRun job.' }),\n ),\n workflowInputJson: Type.Optional(\n Type.String({\n description: 'JSON object for workflow input payload (workflowRun create/update).',\n }),\n ),\n goalId: Type.Optional(\n Type.String({\n description:\n 'Durable goal id for a goalContinue job (mutually exclusive with message and workflowDefinitionId).',\n }),\n ),\n goalMessage: Type.Optional(\n Type.String({\n description: 'Optional custom continuation message for a goalContinue job.',\n }),\n ),\n waitForCompletion: Type.Optional(\n Type.Boolean({\n description:\n 'For workflowRun jobs: when true (default), cron waits for terminal status before succeeding.',\n }),\n ),\n deliveryChannel: Type.Optional(\n Type.String({ description: 'Delivery channel when workflow completes (e.g. telegram).' }),\n ),\n deliveryTo: Type.Optional(\n Type.String({ description: 'Delivery recipient chat id when workflow completes.' }),\n ),\n timezone: Type.Optional(\n Type.String({\n description:\n 'IANA timezone (e.g. Asia/Shanghai, America/New_York). Must be one supported by the cron store.',\n }),\n ),\n sessionTarget: Type.Optional(\n Type.Union([Type.Literal('main'), Type.Literal('isolated')], {\n description:\n '\"main\" uses the main session context; \"isolated\" (default on create) uses a separate session per run.',\n }),\n ),\n agentId: Type.Optional(\n Type.String({\n description:\n 'Agent profile id for isolated jobs (session key). Omit to use the configured default agent (usually `main`).',\n }),\n ),\n workingDirectory: Type.Optional(\n Type.String({\n description:\n 'Absolute workspace path on the gateway host for isolated jobs. Omit to use the agent default workspace.',\n }),\n ),\n\n jobId: Type.Optional(Type.String({ description: 'Job ID (from list output)' })),\n});\n\nexport type CronjobToolParams = {\n action: 'list' | 'create' | 'update' | 'remove' | 'enable' | 'disable' | 'history';\n name?: string;\n schedule?: string;\n message?: string;\n workflowDefinitionId?: string;\n workflowGoal?: string;\n workflowInputJson?: string;\n goalId?: string;\n goalMessage?: string;\n waitForCompletion?: boolean;\n deliveryChannel?: string;\n deliveryTo?: string;\n timezone?: string;\n sessionTarget?: 'main' | 'isolated';\n agentId?: string;\n workingDirectory?: string;\n jobId?: string;\n};\n\nexport interface CronjobToolDeps {\n getCronService: () => CronService | undefined;\n}\n\nfunction textResult(text: string): AgentToolResult<{}> {\n return { content: [{ type: 'text', text }], details: {} };\n}\n\nfunction formatJob(job: JobWithNextRun): string {\n const status = job.enabled ? '▶️ active' : '⏸️ disabled';\n const payloadText = getCronPayloadText(job);\n const truncatedPayload =\n payloadText.length > 100 ? `${payloadText.slice(0, 100)}...` : payloadText;\n const payloadLine =\n job.payload.kind === 'workflowRun'\n ? ` Workflow: ${job.payload.definitionId}${job.payload.goal ? ` — ${job.payload.goal}` : ''}`\n : ` Message: ${truncatedPayload}`;\n\n return [\n `${status} ${job.name ?? '(unnamed)'} (${job.id})`,\n ` Schedule: ${job.schedule}${job.timezone ? ` (${job.timezone})` : ''}`,\n ` Type: ${job.payload.kind}`,\n payloadLine,\n ` Next run: ${job.next_run ?? 'N/A'}`,\n ` Session: ${job.sessionTarget ?? 'main'}`,\n ` Agent: ${job.agentId?.trim() || '(default)'}`,\n ` Workspace: ${job.workingDirectory?.trim() || '(agent default)'}`,\n ].join('\\n');\n}\n\nfunction formatExecution(exec: JobExecution): string {\n const dur = exec.duration != null ? `${(exec.duration / 1000).toFixed(1)}s` : 'N/A';\n const lines = [`[${exec.status}] ${exec.startedAt} (${dur})`];\n if (exec.summary) {\n lines.push(` Summary: ${exec.summary.slice(0, 200)}`);\n }\n if (exec.error) {\n lines.push(` Error: ${exec.error.slice(0, 200)}`);\n }\n return lines.join('\\n');\n}\n\nexport function createCronjobTool(deps: CronjobToolDeps): AgentTool {\n return {\n name: 'cronjob',\n label: '⏰ Cronjob',\n description:\n 'Manage scheduled tasks (cron jobs) that run automatically.\\n\\n' +\n 'Jobs can run an agent message (agentTurn), a workflow directly (workflowRun), or continue a durable goal (goalContinue).\\n\\n' +\n 'ACTIONS:\\n' +\n '- list: Show all scheduled jobs with status and next run time\\n' +\n '- create: Create a job (schedule + exactly one of message, workflowDefinitionId, or goalId)\\n' +\n '- update: Change schedule, message, workflow fields, name, timezone, sessionTarget, agentId, or workingDirectory (requires jobId)\\n' +\n '- remove: Delete a job (requires jobId)\\n' +\n '- enable / disable: Toggle a job (requires jobId)\\n' +\n '- history: Recent executions for a job (requires jobId)',\n parameters: CronjobSchema,\n\n async execute(_toolCallId, params: CronjobToolParams, _signal) {\n const cron = deps.getCronService();\n if (!cron) {\n return textResult('Cron service is not available in this environment.');\n }\n\n try {\n switch (params.action) {\n case 'list': {\n const jobs = await cron.listJobs();\n if (jobs.length === 0) {\n return textResult('No scheduled jobs.');\n }\n const formatted = jobs.map(formatJob).join('\\n\\n');\n return { content: [{ type: 'text', text: formatted }], details: {} };\n }\n\n case 'create': {\n const workflowId = params.workflowDefinitionId?.trim();\n const goalId = params.goalId?.trim();\n const hasMessage = Boolean(params.message?.trim());\n const targetCount = [workflowId, goalId, hasMessage ? 'message' : ''].filter(Boolean).length;\n if (!params.schedule?.trim() || targetCount !== 1) {\n return textResult(\n 'Error: create requires schedule and exactly one of message, workflowDefinitionId, or goalId.',\n );\n }\n\n if (hasMessage) {\n const scanResult = scanCronPrompt(params.message!);\n if (scanResult) {\n return textResult(`Error: ${scanResult}`);\n }\n }\n\n let payload: CronPayload;\n let timeout: number | undefined;\n let sessionTarget = params.sessionTarget ?? 'isolated';\n let delivery: JobData['delivery'];\n\n if (goalId) {\n payload = {\n kind: 'goalContinue',\n goalId,\n ...(params.goalMessage?.trim() ? { message: params.goalMessage.trim() } : {}),\n };\n sessionTarget = 'isolated';\n } else if (workflowId) {\n let inputEnvelope: { payload: unknown } | undefined;\n if (params.workflowInputJson?.trim()) {\n try {\n inputEnvelope = { payload: JSON.parse(params.workflowInputJson) as unknown };\n } catch {\n return textResult('Error: workflowInputJson must be valid JSON.');\n }\n }\n const agentId = params.agentId?.trim() || undefined;\n payload = {\n kind: 'workflowRun',\n definitionId: workflowId,\n ...(params.workflowGoal?.trim() ? { goal: params.workflowGoal.trim() } : {}),\n ...(inputEnvelope ? { inputEnvelope } : {}),\n ...(agentId ? { agentId } : {}),\n ...(params.waitForCompletion === false ? { waitForCompletion: false } : {}),\n };\n sessionTarget = 'isolated';\n timeout = DEFAULT_WORKFLOW_CRON_WAIT_MS;\n if (params.deliveryChannel?.trim() && params.deliveryTo?.trim()) {\n delivery = {\n mode: 'direct',\n channel: params.deliveryChannel.trim(),\n to: params.deliveryTo.trim(),\n };\n }\n } else {\n payload = {\n kind: 'agentTurn',\n message: params.message!.trim(),\n };\n }\n\n const result = await cron.addJob(params.schedule.trim(), {\n name: params.name?.trim() || undefined,\n timezone: params.timezone?.trim() || undefined,\n sessionTarget,\n ...(timeout ? { timeout } : {}),\n ...(delivery ? { delivery } : {}),\n ...(params.agentId?.trim() ? { agentId: params.agentId.trim() } : {}),\n ...(params.workingDirectory?.trim()\n ? { workingDirectory: params.workingDirectory.trim() }\n : {}),\n payload,\n });\n\n const kindLabel = goalId ? `goal job (${goalId})` : workflowId ? `workflow job (${workflowId})` : 'job';\n return textResult(\n `Created ${kindLabel}${params.name ? ` \"${params.name.trim()}\"` : ''} (${result.id})\\n` +\n `Schedule: ${result.schedule}`,\n );\n }\n\n case 'update': {\n if (!params.jobId?.trim()) {\n return textResult('Error: update requires jobId.');\n }\n\n const updates: Partial<Omit<JobData, 'id' | 'created_at' | 'updated_at'>> = {};\n if (params.schedule?.trim()) {\n updates.schedule = params.schedule.trim();\n }\n if (params.message != null && params.message.trim()) {\n const scanResult = scanCronPrompt(params.message);\n if (scanResult) {\n return textResult(`Error: ${scanResult}`);\n }\n updates.payload = { kind: 'agentTurn', message: params.message.trim() };\n }\n if (params.goalId?.trim()) {\n updates.payload = {\n kind: 'goalContinue',\n goalId: params.goalId.trim(),\n ...(params.goalMessage?.trim() ? { message: params.goalMessage.trim() } : {}),\n };\n updates.sessionTarget = 'isolated';\n }\n if (params.workflowDefinitionId?.trim()) {\n let inputEnvelope: { payload: unknown } | undefined;\n if (params.workflowInputJson?.trim()) {\n try {\n inputEnvelope = { payload: JSON.parse(params.workflowInputJson) as unknown };\n } catch {\n return textResult('Error: workflowInputJson must be valid JSON.');\n }\n }\n const agentId = params.agentId?.trim() || undefined;\n updates.payload = {\n kind: 'workflowRun',\n definitionId: params.workflowDefinitionId.trim(),\n ...(params.workflowGoal?.trim() ? { goal: params.workflowGoal.trim() } : {}),\n ...(inputEnvelope ? { inputEnvelope } : {}),\n ...(agentId ? { agentId } : {}),\n ...(params.waitForCompletion === false ? { waitForCompletion: false } : {}),\n };\n updates.sessionTarget = 'isolated';\n updates.timeout = DEFAULT_WORKFLOW_CRON_WAIT_MS;\n }\n if (params.deliveryChannel?.trim() && params.deliveryTo?.trim()) {\n updates.delivery = {\n mode: 'direct',\n channel: params.deliveryChannel.trim(),\n to: params.deliveryTo.trim(),\n };\n }\n if (params.timezone?.trim()) {\n updates.timezone = params.timezone.trim();\n }\n if (params.name !== undefined) {\n updates.name = params.name.trim() || undefined;\n }\n if (params.sessionTarget !== undefined) {\n updates.sessionTarget = params.sessionTarget;\n }\n if (params.agentId !== undefined) {\n const t = params.agentId.trim();\n updates.agentId = t || null;\n }\n if (params.workingDirectory !== undefined) {\n const t = params.workingDirectory.trim();\n updates.workingDirectory = t || null;\n }\n\n if (Object.keys(updates).length === 0) {\n return textResult(\n 'Error: update requires at least one of schedule, message, workflowDefinitionId, name, timezone, sessionTarget, agentId, workingDirectory, deliveryChannel/deliveryTo.',\n );\n }\n\n const success = await cron.updateJob(params.jobId.trim(), updates);\n return textResult(\n success ? `Updated job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`,\n );\n }\n\n case 'remove': {\n if (!params.jobId?.trim()) {\n return textResult('Error: remove requires jobId.');\n }\n const removed = await cron.removeJob(params.jobId.trim());\n return textResult(\n removed ? `Removed job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`,\n );\n }\n\n case 'disable': {\n if (!params.jobId?.trim()) {\n return textResult('Error: disable requires jobId.');\n }\n const toggled = await cron.toggleJob(params.jobId.trim(), false);\n return textResult(\n toggled ? `Disabled job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`,\n );\n }\n\n case 'enable': {\n if (!params.jobId?.trim()) {\n return textResult('Error: enable requires jobId.');\n }\n const toggled = await cron.toggleJob(params.jobId.trim(), true);\n return textResult(\n toggled ? `Enabled job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`,\n );\n }\n\n case 'history': {\n if (!params.jobId?.trim()) {\n return textResult('Error: history requires jobId.');\n }\n const history = await cron.getJobHistory(params.jobId.trim(), 5);\n if (history.length === 0) {\n return textResult(`No execution history for job ${params.jobId.trim()}.`);\n }\n const formatted = history.map(formatExecution).join('\\n\\n');\n return textResult(formatted);\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return textResult(`Error: ${message}`);\n }\n },\n } as any;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"cronjob-tool.js","names":[],"sources":["../../../../src/agent/tools/cronjob-tool.ts"],"sourcesContent":["// Agent tool for managing scheduled cron jobs (CronService-backed)\nimport { Type } from '@sinclair/typebox';\nimport type { AgentTool, AgentToolResult } from '@earendil-works/pi-agent-core';\n\nimport type { CronService } from '../../cron/index.js';\nimport { describeSchedule } from '../../cron/schedule.js';\nimport { getCronPayloadText } from '../../cron/job-content.js';\nimport type { CronDelivery, CronPayload, CronSchedule, CronJobPatch, JobData, JobExecution } from '../../cron/types.js';\n\nconst CRON_THREAT_PATTERNS: Array<[RegExp, string]> = [\n [/ignore\\s+(previous|all|above)\\s+instructions/i, 'prompt_injection'],\n [/do\\s+not\\s+tell\\s+the\\s+user/i, 'deception'],\n [/system\\s+prompt\\s+override/i, 'sys_prompt_override'],\n [/curl\\s+[^\\n]*\\$\\{?\\w*(KEY|TOKEN|SECRET|PASSWORD)/i, 'exfil_curl'],\n [/cat\\s+[^\\n]*(\\.env|credentials|\\.netrc)/i, 'read_secrets'],\n [/rm\\s+-rf\\s+\\//i, 'destructive_rm'],\n];\n\nexport function scanCronPrompt(prompt: string): string | null {\n for (const [pattern, id] of CRON_THREAT_PATTERNS) {\n if (pattern.test(prompt)) {\n return (\n `Blocked: prompt matches threat pattern '${id}'. ` +\n 'Cron prompts must not contain injection or exfiltration payloads.'\n );\n }\n }\n return null;\n}\n\nconst CronjobSchema = Type.Object({\n action: Type.Union(\n [\n Type.Literal('list'),\n Type.Literal('create'),\n Type.Literal('update'),\n Type.Literal('remove'),\n Type.Literal('enable'),\n Type.Literal('disable'),\n Type.Literal('history'),\n ],\n { description: 'Action to perform on cron jobs' },\n ),\n\n name: Type.Optional(Type.String({ description: 'Human-readable job name' })),\n scheduleKind: Type.Optional(\n Type.Union([Type.Literal('cron'), Type.Literal('at'), Type.Literal('every')], {\n description: 'Schedule kind. Use cronExpr for cron, at for one-time ISO time, everyMs for interval.',\n }),\n ),\n cronExpr: Type.Optional(\n Type.String({\n description:\n 'Cron schedule expression. Examples:\\n' +\n ' \"0 9 * * *\" = every day at 9:00 AM\\n' +\n ' \"*/30 * * * *\" = every 30 minutes\\n' +\n ' \"0 9 * * 1-5\" = weekdays at 9:00 AM\\n' +\n ' \"0 0 1 * *\" = first day of each month',\n }),\n ),\n at: Type.Optional(Type.String({ description: 'One-time run timestamp as ISO 8601 string.' })),\n everyMs: Type.Optional(Type.Number({ description: 'Fixed interval in milliseconds.' })),\n tz: Type.Optional(Type.String({ description: 'IANA timezone for cronExpr, e.g. Asia/Shanghai.' })),\n message: Type.Optional(\n Type.String({\n description:\n 'Instruction for the agent when the job runs (agentTurn payload; typically a fresh session).',\n }),\n ),\n workflowDefinitionId: Type.Optional(\n Type.String({\n description:\n 'Workflow definition id for a workflowRun job (mutually exclusive with message on create).',\n }),\n ),\n workflowGoal: Type.Optional(\n Type.String({ description: 'Optional goal override when creating a workflowRun job.' }),\n ),\n workflowInputJson: Type.Optional(\n Type.String({\n description: 'JSON object for workflow input payload (workflowRun create/update).',\n }),\n ),\n goalId: Type.Optional(\n Type.String({\n description:\n 'Durable goal id for a goalContinue job (mutually exclusive with message and workflowDefinitionId).',\n }),\n ),\n goalMessage: Type.Optional(\n Type.String({\n description: 'Optional custom continuation message for a goalContinue job.',\n }),\n ),\n waitForCompletion: Type.Optional(\n Type.Boolean({\n description:\n 'For workflowRun jobs: when true (default), cron waits for terminal status before succeeding.',\n }),\n ),\n deliveryChannel: Type.Optional(\n Type.String({ description: 'Delivery channel when workflow completes (e.g. telegram).' }),\n ),\n deliveryTo: Type.Optional(\n Type.String({ description: 'Delivery recipient chat id when workflow completes.' }),\n ),\n sessionTarget: Type.Optional(\n Type.Union([Type.Literal('main'), Type.Literal('isolated')], {\n description:\n '\"main\" uses the main session context; \"isolated\" (default on create) uses a separate session per run.',\n }),\n ),\n agentId: Type.Optional(\n Type.String({\n description:\n 'Agent profile id for isolated jobs (session key). Omit to use the configured default agent (usually `main`).',\n }),\n ),\n workingDirectory: Type.Optional(\n Type.String({\n description:\n 'Absolute workspace path on the gateway host for isolated jobs. Omit to use the agent default workspace.',\n }),\n ),\n\n jobId: Type.Optional(Type.String({ description: 'Job ID (from list output)' })),\n});\n\nexport type CronjobToolParams = {\n action: 'list' | 'create' | 'update' | 'remove' | 'enable' | 'disable' | 'history';\n name?: string;\n scheduleKind?: 'cron' | 'at' | 'every';\n cronExpr?: string;\n at?: string;\n everyMs?: number;\n tz?: string;\n message?: string;\n workflowDefinitionId?: string;\n workflowGoal?: string;\n workflowInputJson?: string;\n goalId?: string;\n goalMessage?: string;\n waitForCompletion?: boolean;\n deliveryChannel?: string;\n deliveryTo?: string;\n sessionTarget?: 'main' | 'isolated' | 'current';\n agentId?: string;\n workingDirectory?: string;\n jobId?: string;\n};\n\nexport interface CronjobToolDeps {\n getCronService: () => CronService | undefined;\n}\n\nfunction textResult(text: string): AgentToolResult<{}> {\n return { content: [{ type: 'text', text }], details: {} };\n}\n\nfunction formatJob(job: JobData): string {\n const status = job.enabled ? 'active' : 'disabled';\n const payloadText = getCronPayloadText(job);\n const truncatedPayload =\n payloadText.length > 100 ? `${payloadText.slice(0, 100)}...` : payloadText;\n const payloadLine =\n job.payload.kind === 'workflowRun'\n ? ` Workflow: ${job.payload.definitionId}${job.payload.goal ? ` — ${job.payload.goal}` : ''}`\n : ` Message: ${truncatedPayload}`;\n\n return [\n `${status} ${job.name ?? '(unnamed)'} (${job.id})`,\n ` Schedule: ${describeSchedule(job.schedule)}`,\n ` Type: ${job.payload.kind}`,\n payloadLine,\n ` Next run: ${job.state.nextRunAtMs ? new Date(job.state.nextRunAtMs).toISOString() : 'N/A'}`,\n ` Session: ${job.sessionTarget ?? 'main'}`,\n ` Agent: ${job.agentId?.trim() || '(default)'}`,\n ` Workspace: ${job.workingDirectory?.trim() || '(agent default)'}`,\n ].join('\\n');\n}\n\nfunction scheduleFromParams(params: Pick<CronjobToolParams, 'scheduleKind' | 'cronExpr' | 'at' | 'everyMs' | 'tz'>): CronSchedule | undefined {\n const kind = params.scheduleKind;\n if (!kind) return undefined;\n if (kind === 'cron') {\n const expr = params.cronExpr?.trim();\n if (!expr) return undefined;\n return { kind, expr, ...(params.tz?.trim() ? { tz: params.tz.trim() } : {}) };\n }\n if (kind === 'at') {\n const at = params.at?.trim();\n if (!at) return undefined;\n return { kind, at };\n }\n if (!Number.isFinite(params.everyMs) || !params.everyMs || params.everyMs <= 0) return undefined;\n return { kind, everyMs: Math.floor(params.everyMs) };\n}\n\nfunction formatExecution(exec: JobExecution): string {\n const dur = exec.duration != null ? `${(exec.duration / 1000).toFixed(1)}s` : 'N/A';\n const lines = [`[${exec.status}] ${exec.startedAt} (${dur})`];\n if (exec.summary) {\n lines.push(` Summary: ${exec.summary.slice(0, 200)}`);\n }\n if (exec.error) {\n lines.push(` Error: ${exec.error.slice(0, 200)}`);\n }\n return lines.join('\\n');\n}\n\nexport function createCronjobTool(deps: CronjobToolDeps): AgentTool {\n return {\n name: 'cronjob',\n label: '⏰ Cronjob',\n description:\n 'Manage scheduled tasks (cron jobs) that run automatically.\\n\\n' +\n 'Jobs can run an agent message (agentTurn), a workflow directly (workflowRun), or continue a durable goal (goalContinue).\\n\\n' +\n 'ACTIONS:\\n' +\n '- list: Show all scheduled jobs with status and next run time\\n' +\n '- create: Create a job (scheduleKind plus exactly one of message, workflowDefinitionId, or goalId)\\n' +\n '- update: Change schedule, message, workflow fields, name, sessionTarget, agentId, or workingDirectory (requires jobId)\\n' +\n '- remove: Delete a job (requires jobId)\\n' +\n '- enable / disable: Toggle a job (requires jobId)\\n' +\n '- history: Recent executions for a job (requires jobId)',\n parameters: CronjobSchema,\n\n async execute(_toolCallId, params: CronjobToolParams, _signal) {\n const cron = deps.getCronService();\n if (!cron) {\n return textResult('Cron service is not available in this environment.');\n }\n\n try {\n switch (params.action) {\n case 'list': {\n const jobs = await cron.listJobs();\n if (jobs.length === 0) {\n return textResult('No scheduled jobs.');\n }\n const formatted = jobs.map(formatJob).join('\\n\\n');\n return { content: [{ type: 'text', text: formatted }], details: {} };\n }\n\n case 'create': {\n const workflowId = params.workflowDefinitionId?.trim();\n const goalId = params.goalId?.trim();\n const hasMessage = Boolean(params.message?.trim());\n const targetCount = [workflowId, goalId, hasMessage ? 'message' : ''].filter(Boolean).length;\n const schedule = scheduleFromParams(params);\n if (!schedule || targetCount !== 1) {\n return textResult(\n 'Error: create requires scheduleKind with matching cronExpr/at/everyMs and exactly one of message, workflowDefinitionId, or goalId.',\n );\n }\n\n if (hasMessage) {\n const scanResult = scanCronPrompt(params.message!);\n if (scanResult) {\n return textResult(`Error: ${scanResult}`);\n }\n }\n\n let payload: CronPayload;\n let sessionTarget = params.sessionTarget ?? 'isolated';\n let delivery: CronDelivery | undefined;\n\n if (goalId) {\n payload = {\n kind: 'goalContinue',\n goalId,\n ...(params.goalMessage?.trim() ? { message: params.goalMessage.trim() } : {}),\n };\n sessionTarget = 'isolated';\n } else if (workflowId) {\n let inputEnvelope: { payload: unknown } | undefined;\n if (params.workflowInputJson?.trim()) {\n try {\n inputEnvelope = { payload: JSON.parse(params.workflowInputJson) as unknown };\n } catch {\n return textResult('Error: workflowInputJson must be valid JSON.');\n }\n }\n const agentId = params.agentId?.trim() || undefined;\n payload = {\n kind: 'workflowRun',\n definitionId: workflowId,\n ...(params.workflowGoal?.trim() ? { goal: params.workflowGoal.trim() } : {}),\n ...(inputEnvelope ? { inputEnvelope } : {}),\n ...(agentId ? { agentId } : {}),\n ...(params.waitForCompletion === false ? { waitForCompletion: false } : {}),\n };\n sessionTarget = 'isolated';\n if (params.deliveryChannel?.trim() && params.deliveryTo?.trim()) {\n delivery = {\n mode: 'announce',\n channel: params.deliveryChannel.trim(),\n to: params.deliveryTo.trim(),\n };\n }\n } else {\n payload = {\n kind: 'agentTurn',\n message: params.message!.trim(),\n };\n }\n\n const result = await cron.addJob(schedule, {\n name: params.name?.trim() || undefined,\n sessionTarget,\n ...(delivery ? { delivery } : {}),\n ...(params.agentId?.trim() ? { agentId: params.agentId.trim() } : {}),\n ...(params.workingDirectory?.trim()\n ? { workingDirectory: params.workingDirectory.trim() }\n : {}),\n payload,\n });\n\n const kindLabel = goalId ? `goal job (${goalId})` : workflowId ? `workflow job (${workflowId})` : 'job';\n return textResult(\n `Created ${kindLabel}${params.name ? ` \"${params.name.trim()}\"` : ''} (${result.id})\\n` +\n `Schedule: ${describeSchedule(result.schedule)}`,\n );\n }\n\n case 'update': {\n if (!params.jobId?.trim()) {\n return textResult('Error: update requires jobId.');\n }\n\n const updates: CronJobPatch = {};\n const nextSchedule = scheduleFromParams(params);\n if (nextSchedule) {\n updates.schedule = nextSchedule;\n }\n if (params.message != null && params.message.trim()) {\n const scanResult = scanCronPrompt(params.message);\n if (scanResult) {\n return textResult(`Error: ${scanResult}`);\n }\n updates.payload = { kind: 'agentTurn', message: params.message.trim() };\n }\n if (params.goalId?.trim()) {\n updates.payload = {\n kind: 'goalContinue',\n goalId: params.goalId.trim(),\n ...(params.goalMessage?.trim() ? { message: params.goalMessage.trim() } : {}),\n };\n updates.sessionTarget = 'isolated';\n }\n if (params.workflowDefinitionId?.trim()) {\n let inputEnvelope: { payload: unknown } | undefined;\n if (params.workflowInputJson?.trim()) {\n try {\n inputEnvelope = { payload: JSON.parse(params.workflowInputJson) as unknown };\n } catch {\n return textResult('Error: workflowInputJson must be valid JSON.');\n }\n }\n const agentId = params.agentId?.trim() || undefined;\n updates.payload = {\n kind: 'workflowRun',\n definitionId: params.workflowDefinitionId.trim(),\n ...(params.workflowGoal?.trim() ? { goal: params.workflowGoal.trim() } : {}),\n ...(inputEnvelope ? { inputEnvelope } : {}),\n ...(agentId ? { agentId } : {}),\n ...(params.waitForCompletion === false ? { waitForCompletion: false } : {}),\n };\n updates.sessionTarget = 'isolated';\n }\n if (params.deliveryChannel?.trim() && params.deliveryTo?.trim()) {\n updates.delivery = {\n mode: 'announce',\n channel: params.deliveryChannel.trim(),\n to: params.deliveryTo.trim(),\n };\n }\n if (params.name !== undefined) {\n updates.name = params.name.trim() || undefined;\n }\n if (params.sessionTarget !== undefined) {\n updates.sessionTarget = params.sessionTarget;\n }\n if (params.agentId !== undefined) {\n const t = params.agentId.trim();\n if (t) updates.agentId = t;\n }\n if (params.workingDirectory !== undefined) {\n const t = params.workingDirectory.trim();\n if (t) updates.workingDirectory = t;\n }\n\n if (Object.keys(updates).length === 0) {\n return textResult(\n 'Error: update requires at least one of scheduleKind, message, workflowDefinitionId, name, sessionTarget, agentId, workingDirectory, deliveryChannel/deliveryTo.',\n );\n }\n\n const success = await cron.updateJob(params.jobId.trim(), updates);\n return textResult(\n success ? `Updated job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`,\n );\n }\n\n case 'remove': {\n if (!params.jobId?.trim()) {\n return textResult('Error: remove requires jobId.');\n }\n const removed = await cron.removeJob(params.jobId.trim());\n return textResult(\n removed ? `Removed job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`,\n );\n }\n\n case 'disable': {\n if (!params.jobId?.trim()) {\n return textResult('Error: disable requires jobId.');\n }\n const toggled = await cron.toggleJob(params.jobId.trim(), false);\n return textResult(\n toggled ? `Disabled job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`,\n );\n }\n\n case 'enable': {\n if (!params.jobId?.trim()) {\n return textResult('Error: enable requires jobId.');\n }\n const toggled = await cron.toggleJob(params.jobId.trim(), true);\n return textResult(\n toggled ? `Enabled job ${params.jobId.trim()}.` : `Job ${params.jobId.trim()} not found.`,\n );\n }\n\n case 'history': {\n if (!params.jobId?.trim()) {\n return textResult('Error: history requires jobId.');\n }\n const history = await cron.getJobHistory(params.jobId.trim(), 5);\n if (history.length === 0) {\n return textResult(`No execution history for job ${params.jobId.trim()}.`);\n }\n const formatted = history.map(formatExecution).join('\\n\\n');\n return textResult(formatted);\n }\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return textResult(`Error: ${message}`);\n }\n },\n } as any;\n}\n"],"mappings":";;;;AASA,MAAM,uBAAgD;CACpD,CAAC,iDAAiD,mBAAmB;CACrE,CAAC,iCAAiC,YAAY;CAC9C,CAAC,+BAA+B,sBAAsB;CACtD,CAAC,qDAAqD,aAAa;CACnE,CAAC,4CAA4C,eAAe;CAC5D,CAAC,kBAAkB,iBAAiB;CACrC;AAED,SAAgB,eAAe,QAA+B;AAC5D,MAAK,MAAM,CAAC,SAAS,OAAO,qBAC1B,KAAI,QAAQ,KAAK,OAAO,CACtB,QACE,2CAA2C,GAAG;AAKpD,QAAO;;AAGT,MAAM,gBAAgB,KAAK,OAAO;CAChC,QAAQ,KAAK,MACX;EACE,KAAK,QAAQ,OAAO;EACpB,KAAK,QAAQ,SAAS;EACtB,KAAK,QAAQ,SAAS;EACtB,KAAK,QAAQ,SAAS;EACtB,KAAK,QAAQ,SAAS;EACtB,KAAK,QAAQ,UAAU;EACvB,KAAK,QAAQ,UAAU;EACxB,EACD,EAAE,aAAa,kCAAkC,CAClD;CAED,MAAM,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,2BAA2B,CAAC,CAAC;CAC5E,cAAc,KAAK,SACjB,KAAK,MAAM;EAAC,KAAK,QAAQ,OAAO;EAAE,KAAK,QAAQ,KAAK;EAAE,KAAK,QAAQ,QAAQ;EAAC,EAAE,EAC5E,aAAa,yFACd,CAAC,CACH;CACD,UAAU,KAAK,SACb,KAAK,OAAO,EACV,aACE,0MAKH,CAAC,CACH;CACD,IAAI,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,8CAA8C,CAAC,CAAC;CAC7F,SAAS,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,mCAAmC,CAAC,CAAC;CACvF,IAAI,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,mDAAmD,CAAC,CAAC;CAClG,SAAS,KAAK,SACZ,KAAK,OAAO,EACV,aACE,+FACH,CAAC,CACH;CACD,sBAAsB,KAAK,SACzB,KAAK,OAAO,EACV,aACE,6FACH,CAAC,CACH;CACD,cAAc,KAAK,SACjB,KAAK,OAAO,EAAE,aAAa,2DAA2D,CAAC,CACxF;CACD,mBAAmB,KAAK,SACtB,KAAK,OAAO,EACV,aAAa,uEACd,CAAC,CACH;CACD,QAAQ,KAAK,SACX,KAAK,OAAO,EACV,aACE,sGACH,CAAC,CACH;CACD,aAAa,KAAK,SAChB,KAAK,OAAO,EACV,aAAa,gEACd,CAAC,CACH;CACD,mBAAmB,KAAK,SACtB,KAAK,QAAQ,EACX,aACE,gGACH,CAAC,CACH;CACD,iBAAiB,KAAK,SACpB,KAAK,OAAO,EAAE,aAAa,6DAA6D,CAAC,CAC1F;CACD,YAAY,KAAK,SACf,KAAK,OAAO,EAAE,aAAa,uDAAuD,CAAC,CACpF;CACD,eAAe,KAAK,SAClB,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,EAAE,KAAK,QAAQ,WAAW,CAAC,EAAE,EAC3D,aACE,6GACH,CAAC,CACH;CACD,SAAS,KAAK,SACZ,KAAK,OAAO,EACV,aACE,gHACH,CAAC,CACH;CACD,kBAAkB,KAAK,SACrB,KAAK,OAAO,EACV,aACE,2GACH,CAAC,CACH;CAED,OAAO,KAAK,SAAS,KAAK,OAAO,EAAE,aAAa,6BAA6B,CAAC,CAAC;CAChF,CAAC;AA6BF,SAAS,WAAW,MAAmC;AACrD,QAAO;EAAE,SAAS,CAAC;GAAE,MAAM;GAAQ;GAAM,CAAC;EAAE,SAAS,EAAE;EAAE;;AAG3D,SAAS,UAAU,KAAsB;CACvC,MAAM,SAAS,IAAI,UAAU,WAAW;CACxC,MAAM,cAAc,mBAAmB,IAAI;CAC3C,MAAM,mBACJ,YAAY,SAAS,MAAM,GAAG,YAAY,MAAM,GAAG,IAAI,CAAC,OAAO;CACjE,MAAM,cACJ,IAAI,QAAQ,SAAS,gBACjB,eAAe,IAAI,QAAQ,eAAe,IAAI,QAAQ,OAAO,MAAM,IAAI,QAAQ,SAAS,OACxF,cAAc;AAEpB,QAAO;EACL,GAAG,OAAO,GAAG,IAAI,QAAQ,YAAY,IAAI,IAAI,GAAG;EAChD,eAAe,iBAAiB,IAAI,SAAS;EAC7C,WAAW,IAAI,QAAQ;EACvB;EACA,eAAe,IAAI,MAAM,cAAc,IAAI,KAAK,IAAI,MAAM,YAAY,CAAC,aAAa,GAAG;EACvF,cAAc,IAAI,iBAAiB;EACnC,YAAY,IAAI,SAAS,MAAM,IAAI;EACnC,gBAAgB,IAAI,kBAAkB,MAAM,IAAI;EACjD,CAAC,KAAK,KAAK;;AAGd,SAAS,mBAAmB,QAAkH;CAC5I,MAAM,OAAO,OAAO;AACpB,KAAI,CAAC,KAAM,QAAO,KAAA;AAClB,KAAI,SAAS,QAAQ;EACnB,MAAM,OAAO,OAAO,UAAU,MAAM;AACpC,MAAI,CAAC,KAAM,QAAO,KAAA;AAClB,SAAO;GAAE;GAAM;GAAM,GAAI,OAAO,IAAI,MAAM,GAAG,EAAE,IAAI,OAAO,GAAG,MAAM,EAAE,GAAG,EAAE;GAAG;;AAE/E,KAAI,SAAS,MAAM;EACjB,MAAM,KAAK,OAAO,IAAI,MAAM;AAC5B,MAAI,CAAC,GAAI,QAAO,KAAA;AAChB,SAAO;GAAE;GAAM;GAAI;;AAErB,KAAI,CAAC,OAAO,SAAS,OAAO,QAAQ,IAAI,CAAC,OAAO,WAAW,OAAO,WAAW,EAAG,QAAO,KAAA;AACvF,QAAO;EAAE;EAAM,SAAS,KAAK,MAAM,OAAO,QAAQ;EAAE;;AAGtD,SAAS,gBAAgB,MAA4B;CACnD,MAAM,MAAM,KAAK,YAAY,OAAO,IAAI,KAAK,WAAW,KAAM,QAAQ,EAAE,CAAC,KAAK;CAC9E,MAAM,QAAQ,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,UAAU,IAAI,IAAI,GAAG;AAC7D,KAAI,KAAK,QACP,OAAM,KAAK,cAAc,KAAK,QAAQ,MAAM,GAAG,IAAI,GAAG;AAExD,KAAI,KAAK,MACP,OAAM,KAAK,YAAY,KAAK,MAAM,MAAM,GAAG,IAAI,GAAG;AAEpD,QAAO,MAAM,KAAK,KAAK;;AAGzB,SAAgB,kBAAkB,MAAkC;AAClE,QAAO;EACL,MAAM;EACN,OAAO;EACP,aACE;EASF,YAAY;EAEZ,MAAM,QAAQ,aAAa,QAA2B,SAAS;GAC7D,MAAM,OAAO,KAAK,gBAAgB;AAClC,OAAI,CAAC,KACH,QAAO,WAAW,qDAAqD;AAGzE,OAAI;AACF,YAAQ,OAAO,QAAf;KACE,KAAK,QAAQ;MACX,MAAM,OAAO,MAAM,KAAK,UAAU;AAClC,UAAI,KAAK,WAAW,EAClB,QAAO,WAAW,qBAAqB;AAGzC,aAAO;OAAE,SAAS,CAAC;QAAE,MAAM;QAAQ,MADjB,KAAK,IAAI,UAAU,CAAC,KAAK,OACO;QAAE,CAAC;OAAE,SAAS,EAAE;OAAE;;KAGtE,KAAK,UAAU;MACb,MAAM,aAAa,OAAO,sBAAsB,MAAM;MACtD,MAAM,SAAS,OAAO,QAAQ,MAAM;MACpC,MAAM,aAAa,QAAQ,OAAO,SAAS,MAAM,CAAC;MAClD,MAAM,cAAc;OAAC;OAAY;OAAQ,aAAa,YAAY;OAAG,CAAC,OAAO,QAAQ,CAAC;MACtF,MAAM,WAAW,mBAAmB,OAAO;AAC3C,UAAI,CAAC,YAAY,gBAAgB,EAC/B,QAAO,WACL,qIACD;AAGH,UAAI,YAAY;OACd,MAAM,aAAa,eAAe,OAAO,QAAS;AAClD,WAAI,WACF,QAAO,WAAW,UAAU,aAAa;;MAI7C,IAAI;MACJ,IAAI,gBAAgB,OAAO,iBAAiB;MAC5C,IAAI;AAEJ,UAAI,QAAQ;AACV,iBAAU;QACR,MAAM;QACN;QACA,GAAI,OAAO,aAAa,MAAM,GAAG,EAAE,SAAS,OAAO,YAAY,MAAM,EAAE,GAAG,EAAE;QAC7E;AACD,uBAAgB;iBACP,YAAY;OACrB,IAAI;AACJ,WAAI,OAAO,mBAAmB,MAAM,CAClC,KAAI;AACF,wBAAgB,EAAE,SAAS,KAAK,MAAM,OAAO,kBAAkB,EAAa;eACtE;AACN,eAAO,WAAW,+CAA+C;;OAGrE,MAAM,UAAU,OAAO,SAAS,MAAM,IAAI,KAAA;AAC1C,iBAAU;QACR,MAAM;QACN,cAAc;QACd,GAAI,OAAO,cAAc,MAAM,GAAG,EAAE,MAAM,OAAO,aAAa,MAAM,EAAE,GAAG,EAAE;QAC3E,GAAI,gBAAgB,EAAE,eAAe,GAAG,EAAE;QAC1C,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;QAC9B,GAAI,OAAO,sBAAsB,QAAQ,EAAE,mBAAmB,OAAO,GAAG,EAAE;QAC3E;AACD,uBAAgB;AAChB,WAAI,OAAO,iBAAiB,MAAM,IAAI,OAAO,YAAY,MAAM,CAC7D,YAAW;QACT,MAAM;QACN,SAAS,OAAO,gBAAgB,MAAM;QACtC,IAAI,OAAO,WAAW,MAAM;QAC7B;YAGH,WAAU;OACR,MAAM;OACN,SAAS,OAAO,QAAS,MAAM;OAChC;MAGH,MAAM,SAAS,MAAM,KAAK,OAAO,UAAU;OACzC,MAAM,OAAO,MAAM,MAAM,IAAI,KAAA;OAC7B;OACA,GAAI,WAAW,EAAE,UAAU,GAAG,EAAE;OAChC,GAAI,OAAO,SAAS,MAAM,GAAG,EAAE,SAAS,OAAO,QAAQ,MAAM,EAAE,GAAG,EAAE;OACpE,GAAI,OAAO,kBAAkB,MAAM,GAC/B,EAAE,kBAAkB,OAAO,iBAAiB,MAAM,EAAE,GACpD,EAAE;OACN;OACD,CAAC;AAGF,aAAO,WACL,WAFgB,SAAS,aAAa,OAAO,KAAK,aAAa,iBAAiB,WAAW,KAAK,QAEzE,OAAO,OAAO,KAAK,OAAO,KAAK,MAAM,CAAC,KAAK,GAAG,IAAI,OAAO,GAAG,eACpE,iBAAiB,OAAO,SAAS,GACjD;;KAGH,KAAK,UAAU;AACb,UAAI,CAAC,OAAO,OAAO,MAAM,CACvB,QAAO,WAAW,gCAAgC;MAGpD,MAAM,UAAwB,EAAE;MAChC,MAAM,eAAe,mBAAmB,OAAO;AAC/C,UAAI,aACF,SAAQ,WAAW;AAErB,UAAI,OAAO,WAAW,QAAQ,OAAO,QAAQ,MAAM,EAAE;OACnD,MAAM,aAAa,eAAe,OAAO,QAAQ;AACjD,WAAI,WACF,QAAO,WAAW,UAAU,aAAa;AAE3C,eAAQ,UAAU;QAAE,MAAM;QAAa,SAAS,OAAO,QAAQ,MAAM;QAAE;;AAEzE,UAAI,OAAO,QAAQ,MAAM,EAAE;AACzB,eAAQ,UAAU;QAChB,MAAM;QACN,QAAQ,OAAO,OAAO,MAAM;QAC5B,GAAI,OAAO,aAAa,MAAM,GAAG,EAAE,SAAS,OAAO,YAAY,MAAM,EAAE,GAAG,EAAE;QAC7E;AACD,eAAQ,gBAAgB;;AAE1B,UAAI,OAAO,sBAAsB,MAAM,EAAE;OACvC,IAAI;AACJ,WAAI,OAAO,mBAAmB,MAAM,CAClC,KAAI;AACF,wBAAgB,EAAE,SAAS,KAAK,MAAM,OAAO,kBAAkB,EAAa;eACtE;AACN,eAAO,WAAW,+CAA+C;;OAGrE,MAAM,UAAU,OAAO,SAAS,MAAM,IAAI,KAAA;AAC1C,eAAQ,UAAU;QAChB,MAAM;QACN,cAAc,OAAO,qBAAqB,MAAM;QAChD,GAAI,OAAO,cAAc,MAAM,GAAG,EAAE,MAAM,OAAO,aAAa,MAAM,EAAE,GAAG,EAAE;QAC3E,GAAI,gBAAgB,EAAE,eAAe,GAAG,EAAE;QAC1C,GAAI,UAAU,EAAE,SAAS,GAAG,EAAE;QAC9B,GAAI,OAAO,sBAAsB,QAAQ,EAAE,mBAAmB,OAAO,GAAG,EAAE;QAC3E;AACD,eAAQ,gBAAgB;;AAE1B,UAAI,OAAO,iBAAiB,MAAM,IAAI,OAAO,YAAY,MAAM,CAC7D,SAAQ,WAAW;OACjB,MAAM;OACN,SAAS,OAAO,gBAAgB,MAAM;OACtC,IAAI,OAAO,WAAW,MAAM;OAC7B;AAEH,UAAI,OAAO,SAAS,KAAA,EAClB,SAAQ,OAAO,OAAO,KAAK,MAAM,IAAI,KAAA;AAEvC,UAAI,OAAO,kBAAkB,KAAA,EAC3B,SAAQ,gBAAgB,OAAO;AAEjC,UAAI,OAAO,YAAY,KAAA,GAAW;OAChC,MAAM,IAAI,OAAO,QAAQ,MAAM;AAC/B,WAAI,EAAG,SAAQ,UAAU;;AAE3B,UAAI,OAAO,qBAAqB,KAAA,GAAW;OACzC,MAAM,IAAI,OAAO,iBAAiB,MAAM;AACxC,WAAI,EAAG,SAAQ,mBAAmB;;AAGpC,UAAI,OAAO,KAAK,QAAQ,CAAC,WAAW,EAClC,QAAO,WACL,kKACD;AAIH,aAAO,WACL,MAFoB,KAAK,UAAU,OAAO,MAAM,MAAM,EAAE,QAAQ,GAEtD,eAAe,OAAO,MAAM,MAAM,CAAC,KAAK,OAAO,OAAO,MAAM,MAAM,CAAC,aAC9E;;KAGH,KAAK;AACH,UAAI,CAAC,OAAO,OAAO,MAAM,CACvB,QAAO,WAAW,gCAAgC;AAGpD,aAAO,WACL,MAFoB,KAAK,UAAU,OAAO,MAAM,MAAM,CAAC,GAE7C,eAAe,OAAO,MAAM,MAAM,CAAC,KAAK,OAAO,OAAO,MAAM,MAAM,CAAC,aAC9E;KAGH,KAAK;AACH,UAAI,CAAC,OAAO,OAAO,MAAM,CACvB,QAAO,WAAW,iCAAiC;AAGrD,aAAO,WACL,MAFoB,KAAK,UAAU,OAAO,MAAM,MAAM,EAAE,MAAM,GAEpD,gBAAgB,OAAO,MAAM,MAAM,CAAC,KAAK,OAAO,OAAO,MAAM,MAAM,CAAC,aAC/E;KAGH,KAAK;AACH,UAAI,CAAC,OAAO,OAAO,MAAM,CACvB,QAAO,WAAW,gCAAgC;AAGpD,aAAO,WACL,MAFoB,KAAK,UAAU,OAAO,MAAM,MAAM,EAAE,KAAK,GAEnD,eAAe,OAAO,MAAM,MAAM,CAAC,KAAK,OAAO,OAAO,MAAM,MAAM,CAAC,aAC9E;KAGH,KAAK,WAAW;AACd,UAAI,CAAC,OAAO,OAAO,MAAM,CACvB,QAAO,WAAW,iCAAiC;MAErD,MAAM,UAAU,MAAM,KAAK,cAAc,OAAO,MAAM,MAAM,EAAE,EAAE;AAChE,UAAI,QAAQ,WAAW,EACrB,QAAO,WAAW,gCAAgC,OAAO,MAAM,MAAM,CAAC,GAAG;AAG3E,aAAO,WADW,QAAQ,IAAI,gBAAgB,CAAC,KAAK,OACzB,CAAC;;;YAGzB,OAAO;AAEd,WAAO,WAAW,UADF,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,GAChC;;;EAG3C"}
@@ -3,8 +3,8 @@ import { init_logger } from "../../utils/logger.js";
3
3
  import { SHORT_TERM_PROMOTION_LOCK_RELATIVE, SHORT_TERM_RECALL_STORE_RELATIVE } from "../memory/dreaming/constants.js";
4
4
  import { loadDreamingStore, saveDreamingStore } from "../memory/dreaming/short-term-store.js";
5
5
  import { resolveDreamingConfig } from "../memory/dreaming/config.js";
6
- import path from "node:path";
7
6
  import fs from "node:fs/promises";
7
+ import path from "node:path";
8
8
  import { Type } from "@sinclair/typebox";
9
9
  //#region src/agent/tools/dreaming-tool.ts
10
10
  init_logger();
@@ -1,6 +1,6 @@
1
- import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
2
1
  import { createLogger } from "../../utils/logger/index.js";
3
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
4
4
  import { createReadFileTool } from "./read.js";
5
5
  import { createWriteFileTool } from "./write.js";
6
6
  import { createEditFileTool } from "./edit.js";
@@ -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 path from "path";
4
3
  import { existsSync } from "fs";
4
+ import path from "path";
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 path from "path";
4
3
  import { existsSync, readFileSync, statSync } from "fs";
4
+ import path from "path";
5
5
  import { Type } from "@sinclair/typebox";
6
6
  import { globSync } from "glob";
7
7
  //#region src/agent/tools/grep.ts
@@ -4,9 +4,9 @@ import { isFailoverError } from "../failover-error.js";
4
4
  import { imageAssetFromDataUrl, imageFileExtensionForMimeType, mimeTypeFromFileName, parseImageDataUrl, sniffImageMimeType } from "../image/generation/image-assets.js";
5
5
  import { getImageGenerationProvider } from "../image/generation/provider-registry.js";
6
6
  import { generateImage, listImageGenerationProvidersSummary } from "../image/generation/runtime.js";
7
- import path from "node:path";
8
7
  import { randomBytes } from "node:crypto";
9
8
  import { mkdir, readFile, writeFile } from "node:fs/promises";
9
+ import path from "node:path";
10
10
  import { Type } from "@sinclair/typebox";
11
11
  //#region src/agent/tools/image-generate-tool.ts
12
12
  const DEFAULT_COUNT = 1;
@@ -2,8 +2,8 @@ import { resolveStateDir } from "../../config/paths-state.js";
2
2
  import { init_paths } from "../../config/paths.js";
3
3
  import { createSkillConfigManager } from "../skills/config.js";
4
4
  import { applyPatchToContent, atomicWriteUtf8, effectiveAgentWritePolicy, ensureCategorySegment, isPathInsideDir, maxSkillMdChars, maxSupportFileBytes, mutatableSkillOrNull, resolveCreateSkillDir, scanSkillDirOrError, validateSkillMdContent, validateSkillNameSegment, validateSupportingRelativePath } from "../skills/skill-manage-ops.js";
5
- import { join } from "path";
6
5
  import { existsSync, rmSync } from "fs";
6
+ import { join } from "path";
7
7
  import { readFile, rm } from "fs/promises";
8
8
  import { Type } from "@sinclair/typebox";
9
9
  //#region src/agent/tools/skill-manage-tool.ts
@@ -1,6 +1,6 @@
1
- import { extractProfileAgentId } from "../../config/agent-profile.js";
2
1
  import { createLogger } from "../../utils/logger/index.js";
3
2
  import { init_logger } from "../../utils/logger.js";
3
+ import { extractProfileAgentId } from "../../config/agent-profile.js";
4
4
  import { parseWorkflowScript } from "../workflow/parser.js";
5
5
  import "../workflow/index.js";
6
6
  import { Type } from "@sinclair/typebox";
@@ -1,8 +1,8 @@
1
1
  import { init_paths_state, resolveStateDir } from "../../config/paths-state.js";
2
2
  import { BUILTIN_WORKFLOWS } from "./builtins/index.js";
3
3
  import { parseWorkflowScript } from "./parser.js";
4
- import { join } from "node:path";
5
4
  import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
5
+ import { join } from "node:path";
6
6
  //#region src/agent/workflow/catalog.ts
7
7
  /**
8
8
  * Catalog for named workflows.
@@ -30,16 +30,21 @@ export interface WorkspaceRuntimeRegistryOptions {
30
30
  getConfig: () => Config;
31
31
  /** Absolute path to the bundled skills directory shared by every workspace. */
32
32
  bundledSkillsDir: string;
33
+ /** Called after a runtime is first created for a workspace. */
34
+ onRuntimeCreated?: (resolvedPath: string) => void;
33
35
  }
34
36
  export declare class WorkspaceRuntimeRegistry {
35
37
  private readonly runtimes;
36
38
  private readonly getConfig;
37
39
  private readonly bundledSkillsDir;
40
+ private readonly onRuntimeCreated?;
38
41
  constructor(opts: WorkspaceRuntimeRegistryOptions);
39
42
  /** Lazily construct (and cache) the runtime for a resolved workspace path. */
40
43
  getOrCreate(resolvedPath: string): WorkspaceRuntime;
41
44
  /** Iterate every live workspace runtime (used by skill / config hot-reload). */
42
45
  values(): IterableIterator<WorkspaceRuntime>;
46
+ /** Iterate live workspace runtime entries keyed by resolved workspace path. */
47
+ entries(): IterableIterator<[string, WorkspaceRuntime]>;
43
48
  /**
44
49
  * Tear down every runtime (shutdown memory providers) and forget the cache.
45
50
  * Used by `AgentManager.updateAgentDefaults` and `AgentManager.dispose`.
@@ -12,9 +12,11 @@ var WorkspaceRuntimeRegistry = class {
12
12
  runtimes = /* @__PURE__ */ new Map();
13
13
  getConfig;
14
14
  bundledSkillsDir;
15
+ onRuntimeCreated;
15
16
  constructor(opts) {
16
17
  this.getConfig = opts.getConfig;
17
18
  this.bundledSkillsDir = opts.bundledSkillsDir;
19
+ this.onRuntimeCreated = opts.onRuntimeCreated;
18
20
  }
19
21
  /** Lazily construct (and cache) the runtime for a resolved workspace path. */
20
22
  getOrCreate(resolvedPath) {
@@ -35,12 +37,17 @@ var WorkspaceRuntimeRegistry = class {
35
37
  memoryManager
36
38
  };
37
39
  this.runtimes.set(resolvedPath, rt);
40
+ this.onRuntimeCreated?.(resolvedPath);
38
41
  return rt;
39
42
  }
40
43
  /** Iterate every live workspace runtime (used by skill / config hot-reload). */
41
44
  values() {
42
45
  return this.runtimes.values();
43
46
  }
47
+ /** Iterate live workspace runtime entries keyed by resolved workspace path. */
48
+ entries() {
49
+ return this.runtimes.entries();
50
+ }
44
51
  /**
45
52
  * Tear down every runtime (shutdown memory providers) and forget the cache.
46
53
  * Used by `AgentManager.updateAgentDefaults` and `AgentManager.dispose`.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":[],"sources":["../../../../src/agent/workspace-runtime/registry.ts"],"sourcesContent":["/**\n * WorkspaceRuntimeRegistry — lazy per-workspace cache of skill/memory/prompt-builder runtimes.\n *\n * Previously these four collaborators (`SkillManager`, `SystemPromptBuilder`,\n * `BuiltinMemoryStore`, `MemoryManager`) were created inline inside\n * `AgentManager.getWorkspaceRuntime` and cached in a private Map. They live\n * outside `AgentInstance` because multiple session keys may share a workspace\n * (the runtime is keyed by **resolved workspace path**, not session key).\n *\n * Extracted so:\n * - `AgentManager` no longer juggles four sibling caches.\n * - Hot-reload teardown (`clearAll`) lives in one place — there are now no\n * callers that forget to shut down `memoryManager`.\n * - Future per-workspace runtimes (e.g. embedding store, vector cache) plug in\n * through `getOrCreate` without touching `AgentManager`.\n */\n\nimport type { Config } from '../../config/schema.js';\nimport { BuiltinMemoryStore } from '../memory/builtin-memory-store.js';\nimport { createMemoryManagerFromConfig } from '../memory/create-memory-manager.js';\nimport { resolveBuiltinMemoryStoreConfig } from '../memory/memory-config.js';\nimport type { MemoryManager } from '../memory/manager.js';\nimport { SkillManager } from '../skills/skill-manager.js';\nimport { SystemPromptBuilder } from '../prompt/service-prompt-builder.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('WorkspaceRuntimeRegistry');\n\nexport interface WorkspaceRuntime {\n skillManager: SkillManager;\n systemPromptBuilder: SystemPromptBuilder;\n builtinMemoryStore: BuiltinMemoryStore;\n memoryManager: MemoryManager;\n}\n\nexport interface WorkspaceRuntimeRegistryOptions {\n /** Effective config snapshot accessor (must always return a value when called). */\n getConfig: () => Config;\n /** Absolute path to the bundled skills directory shared by every workspace. */\n bundledSkillsDir: string;\n}\n\nexport class WorkspaceRuntimeRegistry {\n private readonly runtimes = new Map<string, WorkspaceRuntime>();\n private readonly getConfig: () => Config;\n private readonly bundledSkillsDir: string;\n\n constructor(opts: WorkspaceRuntimeRegistryOptions) {\n this.getConfig = opts.getConfig;\n this.bundledSkillsDir = opts.bundledSkillsDir;\n }\n\n /** Lazily construct (and cache) the runtime for a resolved workspace path. */\n getOrCreate(resolvedPath: string): WorkspaceRuntime {\n const existing = this.runtimes.get(resolvedPath);\n if (existing) {\n return existing;\n }\n\n const cfg = this.getConfig();\n const builtinMemoryStore = new BuiltinMemoryStore(\n resolveBuiltinMemoryStoreConfig(resolvedPath, cfg),\n );\n const memoryManager = createMemoryManagerFromConfig(resolvedPath, builtinMemoryStore, cfg);\n const skillManager = new SkillManager(resolvedPath, this.bundledSkillsDir);\n const systemPromptBuilder = new SystemPromptBuilder({\n workspace: resolvedPath,\n config: cfg,\n skillManager,\n });\n\n const rt: WorkspaceRuntime = {\n skillManager,\n systemPromptBuilder,\n builtinMemoryStore,\n memoryManager,\n };\n this.runtimes.set(resolvedPath, rt);\n return rt;\n }\n\n /** Iterate every live workspace runtime (used by skill / config hot-reload). */\n values(): IterableIterator<WorkspaceRuntime> {\n return this.runtimes.values();\n }\n\n /**\n * Tear down every runtime (shutdown memory providers) and forget the cache.\n * Used by `AgentManager.updateAgentDefaults` and `AgentManager.dispose`.\n */\n async clearAll(): Promise<void> {\n const toShutdown = [...this.runtimes.values()];\n this.runtimes.clear();\n await Promise.allSettled(\n toShutdown.map((rt) =>\n rt.memoryManager.shutdownAll().catch((err) => {\n log.warn({ err }, 'memoryManager.shutdownAll failed');\n }),\n ),\n );\n }\n}\n"],"mappings":";;;;;;;;aAwBqD;AAErD,MAAM,MAAM,aAAa,2BAA2B;AAgBpD,IAAa,2BAAb,MAAsC;CACpC,2BAA4B,IAAI,KAA+B;CAC/D;CACA;CAEA,YAAY,MAAuC;AACjD,OAAK,YAAY,KAAK;AACtB,OAAK,mBAAmB,KAAK;;;CAI/B,YAAY,cAAwC;EAClD,MAAM,WAAW,KAAK,SAAS,IAAI,aAAa;AAChD,MAAI,SACF,QAAO;EAGT,MAAM,MAAM,KAAK,WAAW;EAC5B,MAAM,qBAAqB,IAAI,mBAC7B,gCAAgC,cAAc,IAAI,CACnD;EACD,MAAM,gBAAgB,8BAA8B,cAAc,oBAAoB,IAAI;EAC1F,MAAM,eAAe,IAAI,aAAa,cAAc,KAAK,iBAAiB;EAO1E,MAAM,KAAuB;GAC3B;GACA,qBAAA,IAR8B,oBAAoB;IAClD,WAAW;IACX,QAAQ;IACR;IACD,CAIoB;GACnB;GACA;GACD;AACD,OAAK,SAAS,IAAI,cAAc,GAAG;AACnC,SAAO;;;CAIT,SAA6C;AAC3C,SAAO,KAAK,SAAS,QAAQ;;;;;;CAO/B,MAAM,WAA0B;EAC9B,MAAM,aAAa,CAAC,GAAG,KAAK,SAAS,QAAQ,CAAC;AAC9C,OAAK,SAAS,OAAO;AACrB,QAAM,QAAQ,WACZ,WAAW,KAAK,OACd,GAAG,cAAc,aAAa,CAAC,OAAO,QAAQ;AAC5C,OAAI,KAAK,EAAE,KAAK,EAAE,mCAAmC;IACrD,CACH,CACF"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../../../src/agent/workspace-runtime/registry.ts"],"sourcesContent":["/**\n * WorkspaceRuntimeRegistry — lazy per-workspace cache of skill/memory/prompt-builder runtimes.\n *\n * Previously these four collaborators (`SkillManager`, `SystemPromptBuilder`,\n * `BuiltinMemoryStore`, `MemoryManager`) were created inline inside\n * `AgentManager.getWorkspaceRuntime` and cached in a private Map. They live\n * outside `AgentInstance` because multiple session keys may share a workspace\n * (the runtime is keyed by **resolved workspace path**, not session key).\n *\n * Extracted so:\n * - `AgentManager` no longer juggles four sibling caches.\n * - Hot-reload teardown (`clearAll`) lives in one place — there are now no\n * callers that forget to shut down `memoryManager`.\n * - Future per-workspace runtimes (e.g. embedding store, vector cache) plug in\n * through `getOrCreate` without touching `AgentManager`.\n */\n\nimport type { Config } from '../../config/schema.js';\nimport { BuiltinMemoryStore } from '../memory/builtin-memory-store.js';\nimport { createMemoryManagerFromConfig } from '../memory/create-memory-manager.js';\nimport { resolveBuiltinMemoryStoreConfig } from '../memory/memory-config.js';\nimport type { MemoryManager } from '../memory/manager.js';\nimport { SkillManager } from '../skills/skill-manager.js';\nimport { SystemPromptBuilder } from '../prompt/service-prompt-builder.js';\nimport { createLogger } from '../../utils/logger.js';\n\nconst log = createLogger('WorkspaceRuntimeRegistry');\n\nexport interface WorkspaceRuntime {\n skillManager: SkillManager;\n systemPromptBuilder: SystemPromptBuilder;\n builtinMemoryStore: BuiltinMemoryStore;\n memoryManager: MemoryManager;\n}\n\nexport interface WorkspaceRuntimeRegistryOptions {\n /** Effective config snapshot accessor (must always return a value when called). */\n getConfig: () => Config;\n /** Absolute path to the bundled skills directory shared by every workspace. */\n bundledSkillsDir: string;\n /** Called after a runtime is first created for a workspace. */\n onRuntimeCreated?: (resolvedPath: string) => void;\n}\n\nexport class WorkspaceRuntimeRegistry {\n private readonly runtimes = new Map<string, WorkspaceRuntime>();\n private readonly getConfig: () => Config;\n private readonly bundledSkillsDir: string;\n private readonly onRuntimeCreated?: (resolvedPath: string) => void;\n\n constructor(opts: WorkspaceRuntimeRegistryOptions) {\n this.getConfig = opts.getConfig;\n this.bundledSkillsDir = opts.bundledSkillsDir;\n this.onRuntimeCreated = opts.onRuntimeCreated;\n }\n\n /** Lazily construct (and cache) the runtime for a resolved workspace path. */\n getOrCreate(resolvedPath: string): WorkspaceRuntime {\n const existing = this.runtimes.get(resolvedPath);\n if (existing) {\n return existing;\n }\n\n const cfg = this.getConfig();\n const builtinMemoryStore = new BuiltinMemoryStore(\n resolveBuiltinMemoryStoreConfig(resolvedPath, cfg),\n );\n const memoryManager = createMemoryManagerFromConfig(resolvedPath, builtinMemoryStore, cfg);\n const skillManager = new SkillManager(resolvedPath, this.bundledSkillsDir);\n const systemPromptBuilder = new SystemPromptBuilder({\n workspace: resolvedPath,\n config: cfg,\n skillManager,\n });\n\n const rt: WorkspaceRuntime = {\n skillManager,\n systemPromptBuilder,\n builtinMemoryStore,\n memoryManager,\n };\n this.runtimes.set(resolvedPath, rt);\n this.onRuntimeCreated?.(resolvedPath);\n return rt;\n }\n\n /** Iterate every live workspace runtime (used by skill / config hot-reload). */\n values(): IterableIterator<WorkspaceRuntime> {\n return this.runtimes.values();\n }\n\n /** Iterate live workspace runtime entries keyed by resolved workspace path. */\n entries(): IterableIterator<[string, WorkspaceRuntime]> {\n return this.runtimes.entries();\n }\n\n /**\n * Tear down every runtime (shutdown memory providers) and forget the cache.\n * Used by `AgentManager.updateAgentDefaults` and `AgentManager.dispose`.\n */\n async clearAll(): Promise<void> {\n const toShutdown = [...this.runtimes.values()];\n this.runtimes.clear();\n await Promise.allSettled(\n toShutdown.map((rt) =>\n rt.memoryManager.shutdownAll().catch((err) => {\n log.warn({ err }, 'memoryManager.shutdownAll failed');\n }),\n ),\n );\n }\n}\n"],"mappings":";;;;;;;;aAwBqD;AAErD,MAAM,MAAM,aAAa,2BAA2B;AAkBpD,IAAa,2BAAb,MAAsC;CACpC,2BAA4B,IAAI,KAA+B;CAC/D;CACA;CACA;CAEA,YAAY,MAAuC;AACjD,OAAK,YAAY,KAAK;AACtB,OAAK,mBAAmB,KAAK;AAC7B,OAAK,mBAAmB,KAAK;;;CAI/B,YAAY,cAAwC;EAClD,MAAM,WAAW,KAAK,SAAS,IAAI,aAAa;AAChD,MAAI,SACF,QAAO;EAGT,MAAM,MAAM,KAAK,WAAW;EAC5B,MAAM,qBAAqB,IAAI,mBAC7B,gCAAgC,cAAc,IAAI,CACnD;EACD,MAAM,gBAAgB,8BAA8B,cAAc,oBAAoB,IAAI;EAC1F,MAAM,eAAe,IAAI,aAAa,cAAc,KAAK,iBAAiB;EAO1E,MAAM,KAAuB;GAC3B;GACA,qBAAA,IAR8B,oBAAoB;IAClD,WAAW;IACX,QAAQ;IACR;IACD,CAIoB;GACnB;GACA;GACD;AACD,OAAK,SAAS,IAAI,cAAc,GAAG;AACnC,OAAK,mBAAmB,aAAa;AACrC,SAAO;;;CAIT,SAA6C;AAC3C,SAAO,KAAK,SAAS,QAAQ;;;CAI/B,UAAwD;AACtD,SAAO,KAAK,SAAS,SAAS;;;;;;CAOhC,MAAM,WAA0B;EAC9B,MAAM,aAAa,CAAC,GAAG,KAAK,SAAS,QAAQ,CAAC;AAC9C,OAAK,SAAS,OAAO;AACrB,QAAM,QAAQ,WACZ,WAAW,KAAK,OACd,GAAG,cAAc,aAAa,CAAC,OAAO,QAAQ;AAC5C,OAAI,KAAK,EAAE,KAAK,EAAE,mCAAmC;IACrD,CACH,CACF"}