@xopcai/xopc 0.0.118 → 0.0.119

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 (468) hide show
  1. package/README.md +2 -1
  2. package/README.zh-CN.md +2 -1
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-dzUrQoeZ.js → agent-avatar-dicebear-CU8J6zou.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-B0hkpLhP.js +2 -0
  7. package/dist/gateway/static/root/assets/app-management-settings-panel-B9vfYoEr.js +1 -0
  8. package/dist/gateway/static/root/assets/appearance-settings-ClOzIO24.js +1 -0
  9. package/dist/gateway/static/root/assets/{apps-page--wMEL00f.js → apps-page-DU0dz9Zo.js} +1 -1
  10. package/dist/gateway/static/root/assets/{archive-plugin-Cki4SfU2.js → archive-plugin-BkVIgZzA.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-D-KnS2Do.js → attachment-load-CaCMWh1D.js} +1 -1
  12. package/dist/gateway/static/root/assets/automation-suggestion-card-DhGDpKP3.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-page-CTedroVo.js +1 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-D2sgvJja.js → binary-plugins-B4TO_bsn.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-DIq-4Gvb.js → block-editor-DJRWwWNI.js} +28 -28
  16. package/dist/gateway/static/root/assets/browser-settings-page-FCDwOOBK.js +8 -0
  17. package/dist/gateway/static/root/assets/capability-presets-api-Befi89CL.js +1 -0
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-_G8eb2vJ.js +1 -0
  19. package/dist/gateway/static/root/assets/channel-recipient-api-BNSuJb5f.js +1 -0
  20. package/dist/gateway/static/root/assets/channels-settings-C3d5JBJX.js +1 -0
  21. package/dist/gateway/static/root/assets/cn-BQ_8x0bT.js +1 -0
  22. package/dist/gateway/static/root/assets/connectors-page-yaUNvt5u.js +2 -0
  23. package/dist/gateway/static/root/assets/cron-expression-B3B1eqnr.js +2 -0
  24. package/dist/gateway/static/root/assets/dreaming-settings-DNrdg1Ve.js +1 -0
  25. package/dist/gateway/static/root/assets/{extension-debug-page-DYu1KaFQ.js → extension-debug-page-DYh402XV.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-page-B3W6QwlZ.js → extension-page-Cr_TizrN.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-settings-page-D7VQ-cxE.js → extension-settings-page-BU1KoKRj.js} +1 -1
  28. package/dist/gateway/static/root/assets/{fetch-B7xDPu-R.js → fetch-Y7AEX4H3.js} +1 -1
  29. package/dist/gateway/static/root/assets/format-cron-label-arqgGlVV.js +1 -0
  30. package/dist/gateway/static/root/assets/{gateway-config-api-BTBLSeUu.js → gateway-config-api-RbMmAOpX.js} +1 -1
  31. package/dist/gateway/static/root/assets/gateway-settings-C79wkXef.js +1 -0
  32. package/dist/gateway/static/root/assets/{gateway-startup-retry-CYj9FWCp.js → gateway-startup-retry-DiD_Tx4N.js} +1 -1
  33. package/dist/gateway/static/root/assets/goal-detail-page-9paXuHdo.js +1 -0
  34. package/dist/gateway/static/root/assets/{goals-config-api-CQQgzPr3.js → goals-config-api-DqxVi0p5.js} +1 -1
  35. package/dist/gateway/static/root/assets/{goals-page-BHitvJAv.js → goals-page-CS0R-Af2.js} +2 -2
  36. package/dist/gateway/static/root/assets/goals-settings-CSuzZ8Ae.js +1 -0
  37. package/dist/gateway/static/root/assets/heartbeat-settings-DXPaYJm3.js +1 -0
  38. package/dist/gateway/static/root/assets/index-BoKafJIZ.js +191 -0
  39. package/dist/gateway/static/root/assets/index-CArhCcYn.css +1 -0
  40. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-Dvg53qnd.js +1 -0
  41. package/dist/gateway/static/root/assets/{logs-page-C2Uqvae9.js → logs-page-DLXPcksQ.js} +2 -2
  42. package/dist/gateway/static/root/assets/{markdown-split-BwOFrJ2E.js → markdown-split-CpHxbtWJ.js} +1 -1
  43. package/dist/gateway/static/root/assets/{media-plugins-Cnz6Q5G6.js → media-plugins-SFPQRSxq.js} +1 -1
  44. package/dist/gateway/static/root/assets/messages-CrDHEbss.js +3 -0
  45. package/dist/gateway/static/root/assets/models-hub-panel-BDF2iyRk.js +2 -0
  46. package/dist/gateway/static/root/assets/note-detail-page-CSb_hwig.js +2 -0
  47. package/dist/gateway/static/root/assets/{note-image-lightbox-B-Svpmza.js → note-image-lightbox-BUYURRgn.js} +1 -1
  48. package/dist/gateway/static/root/assets/notes-page-BsIBSFyZ.js +1 -0
  49. package/dist/gateway/static/root/assets/{preview-open-alternatives-Bss4TiwP.js → preview-open-alternatives-BHz9iWYA.js} +1 -1
  50. package/dist/gateway/static/root/assets/remote-access-hub-CwzSovcS.js +1 -0
  51. package/dist/gateway/static/root/assets/{save-bar-controls-BRNjdgKq.js → save-bar-controls-CefkOlRg.js} +1 -1
  52. package/dist/gateway/static/root/assets/schedule-field-CmTRoOcE.js +1 -0
  53. package/dist/gateway/static/root/assets/{schema-form-Dub9sy8r.js → schema-form-FMKv1vGu.js} +1 -1
  54. package/dist/gateway/static/root/assets/sessions-page-PHmX-NmA.js +1 -0
  55. package/dist/gateway/static/root/assets/settings-advanced-gate-BRAeKJN4.js +1 -0
  56. package/dist/gateway/static/root/assets/{settings-collapsible-section-BeFLavGi.js → settings-collapsible-section-BouO6JTi.js} +1 -1
  57. package/dist/gateway/static/root/assets/{settings-form-section-dmyaPOTG.js → settings-form-section-D-4lBl6X.js} +1 -1
  58. package/dist/gateway/static/root/assets/settings-page-KKrbFjy8.js +1 -0
  59. package/dist/gateway/static/root/assets/settings-page-layout-BJ4Gsef5.js +1 -0
  60. package/dist/gateway/static/root/assets/setup-status-panel-CrUjHPQo.js +1 -0
  61. package/dist/gateway/static/root/assets/{share-preview-page-C8glrdqe.js → share-preview-page-BDy2btRN.js} +1 -1
  62. package/dist/gateway/static/root/assets/shares-settings-B18OBmH5.js +1 -0
  63. package/dist/gateway/static/root/assets/skill-reload-api-C28-2uKQ.js +1 -0
  64. package/dist/gateway/static/root/assets/skills-page-Bm2ebkwl.js +2 -0
  65. package/dist/gateway/static/root/assets/system-settings-panel-CRngrlnZ.js +1 -0
  66. package/dist/gateway/static/root/assets/typed-models-lib-BltBc0b-.js +1 -0
  67. package/dist/gateway/static/root/assets/{use-channel-catalog-DqlWTsDb.js → use-channel-catalog-CjN-51e6.js} +1 -1
  68. package/dist/gateway/static/root/assets/user-profile-settings-panel-DJ1dKwZy.js +1 -0
  69. package/dist/gateway/static/root/assets/utils-B5M5-YvK.js +1 -0
  70. package/dist/gateway/static/root/assets/{voice-api-key-field-C73IVZeC.js → voice-api-key-field-CeEevm7z.js} +1 -1
  71. package/dist/gateway/static/root/assets/{voice-player-store-C_ArLJPM.js → voice-player-store-B7ykUlHM.js} +1 -1
  72. package/dist/gateway/static/root/assets/workflow-run-setup-panel-C4PzUQjB.js +3 -0
  73. package/dist/gateway/static/root/assets/workflows-page-BL84_-Ky.js +18 -0
  74. package/dist/gateway/static/root/index.html +6 -7
  75. package/dist/package.js +1 -1
  76. package/dist/src/agent/agent-manager.d.ts +4 -5
  77. package/dist/src/agent/agent-manager.js +4 -8
  78. package/dist/src/agent/agent-manager.js.map +1 -1
  79. package/dist/src/agent/embedded/run-for-session.js +102 -14
  80. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  81. package/dist/src/agent/fallback/candidates.d.ts +0 -8
  82. package/dist/src/agent/fallback/candidates.js.map +1 -1
  83. package/dist/src/agent/index.js +1 -1
  84. package/dist/src/agent/lifecycle/handlers/compaction.d.ts +1 -3
  85. package/dist/src/agent/lifecycle/handlers/compaction.js +1 -16
  86. package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
  87. package/dist/src/agent/lifecycle/progress.d.ts +0 -1
  88. package/dist/src/agent/lifecycle/progress.js +1 -6
  89. package/dist/src/agent/lifecycle/progress.js.map +1 -1
  90. package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +1 -2
  91. package/dist/src/agent/lifecycle/timeout-wrapper.js +1 -7
  92. package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
  93. package/dist/src/agent/middleware/self-verify.d.ts +0 -1
  94. package/dist/src/agent/middleware/self-verify.js +0 -2
  95. package/dist/src/agent/middleware/self-verify.js.map +1 -1
  96. package/dist/src/agent/models/index.d.ts +1 -1
  97. package/dist/src/agent/models/manager.d.ts +4 -20
  98. package/dist/src/agent/models/manager.js +9 -126
  99. package/dist/src/agent/models/manager.js.map +1 -1
  100. package/dist/src/agent/orchestration/agent-orchestrator.d.ts +0 -4
  101. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -9
  102. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  103. package/dist/src/agent/prompt/sections/tooling.js +2 -2
  104. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  105. package/dist/src/agent/prompt/service-prompt-builder.d.ts +0 -1
  106. package/dist/src/agent/prompt/service-prompt-builder.js +0 -12
  107. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  108. package/dist/src/agent/prompt/subagent-context.js +1 -1
  109. package/dist/src/agent/prompt/subagent-context.js.map +1 -1
  110. package/dist/src/agent/prompt/types.d.ts +1 -1
  111. package/dist/src/agent/service.d.ts +1 -9
  112. package/dist/src/agent/service.js +3 -40
  113. package/dist/src/agent/service.js.map +1 -1
  114. package/dist/src/agent/service.types.d.ts +2 -2
  115. package/dist/src/agent/session/session-config-service.d.ts +11 -11
  116. package/dist/src/agent/session/session-config-service.js +14 -14
  117. package/dist/src/agent/session/session-config-service.js.map +1 -1
  118. package/dist/src/agent/session/session-inspector.js +3 -2
  119. package/dist/src/agent/session/session-inspector.js.map +1 -1
  120. package/dist/src/agent/starter-agents.js +12 -12
  121. package/dist/src/agent/starter-agents.js.map +1 -1
  122. package/dist/src/agent/tools/automation-tool.d.ts +14 -0
  123. package/dist/src/agent/tools/automation-tool.js +102 -0
  124. package/dist/src/agent/tools/automation-tool.js.map +1 -0
  125. package/dist/src/agent/tools/delegate-tool.js +1 -1
  126. package/dist/src/agent/tools/delegate-tool.js.map +1 -1
  127. package/dist/src/agent/tools/factory.d.ts +3 -3
  128. package/dist/src/agent/tools/factory.js +2 -2
  129. package/dist/src/agent/tools/factory.js.map +1 -1
  130. package/dist/src/agent/tools/index.d.ts +1 -1
  131. package/dist/src/agent/tools/index.js +2 -2
  132. package/dist/src/agent-manifest/resolver.d.ts +1 -0
  133. package/dist/src/agent-manifest/resolver.js +1 -0
  134. package/dist/src/agent-manifest/resolver.js.map +1 -1
  135. package/dist/src/agent-manifest/schema.d.ts +6 -0
  136. package/dist/src/agent-manifest/schema.js +12 -3
  137. package/dist/src/agent-manifest/schema.js.map +1 -1
  138. package/dist/src/ai-assist/text-assist.d.ts +1 -1
  139. package/dist/src/ai-assist/text-assist.js +56 -0
  140. package/dist/src/ai-assist/text-assist.js.map +1 -1
  141. package/dist/src/auth/profiles/store.js.map +1 -1
  142. package/dist/src/automations/api/routes.d.ts +3 -0
  143. package/dist/src/automations/api/routes.js +193 -0
  144. package/dist/src/automations/api/routes.js.map +1 -0
  145. package/dist/src/automations/domain/index.d.ts +3 -0
  146. package/dist/src/automations/domain/index.js +3 -0
  147. package/dist/src/automations/domain/schedule.d.ts +4 -0
  148. package/dist/src/automations/domain/schedule.js +37 -0
  149. package/dist/src/automations/domain/schedule.js.map +1 -0
  150. package/dist/src/automations/domain/types.d.ts +160 -0
  151. package/dist/src/automations/domain/validation.d.ts +370 -0
  152. package/dist/src/automations/domain/validation.js +149 -0
  153. package/dist/src/automations/domain/validation.js.map +1 -0
  154. package/dist/src/automations/draft/automation-draft-prompt.d.ts +26 -0
  155. package/dist/src/automations/draft/automation-draft-prompt.js +127 -0
  156. package/dist/src/automations/draft/automation-draft-prompt.js.map +1 -0
  157. package/dist/src/automations/draft/automation-draft-service.d.ts +12 -0
  158. package/dist/src/automations/draft/automation-draft-service.js +135 -0
  159. package/dist/src/automations/draft/automation-draft-service.js.map +1 -0
  160. package/dist/src/automations/draft/automation-draft-validator.d.ts +99 -0
  161. package/dist/src/automations/draft/automation-draft-validator.js +105 -0
  162. package/dist/src/automations/draft/automation-draft-validator.js.map +1 -0
  163. package/dist/src/automations/draft/automation-draft.types.d.ts +40 -0
  164. package/dist/src/automations/draft/index.d.ts +3 -0
  165. package/dist/src/automations/draft/index.js +3 -0
  166. package/dist/src/automations/index.d.ts +3 -0
  167. package/dist/src/automations/index.js +8 -0
  168. package/dist/src/automations/product-events.d.ts +5 -0
  169. package/dist/src/automations/product-events.js +21 -0
  170. package/dist/src/automations/product-events.js.map +1 -0
  171. package/dist/src/automations/service/action-executor.d.ts +9 -0
  172. package/dist/src/automations/service/action-executor.js +157 -0
  173. package/dist/src/automations/service/action-executor.js.map +1 -0
  174. package/dist/src/automations/service/automation-service.d.ts +54 -0
  175. package/dist/src/automations/service/automation-service.js +404 -0
  176. package/dist/src/automations/service/automation-service.js.map +1 -0
  177. package/dist/src/automations/service/index.d.ts +2 -0
  178. package/dist/src/automations/service/index.js +3 -0
  179. package/dist/src/automations/storage/automation-repository.d.ts +6 -0
  180. package/dist/src/automations/storage/automation-repository.js +61 -0
  181. package/dist/src/automations/storage/automation-repository.js.map +1 -0
  182. package/dist/src/automations/storage/automation-run-repository.d.ts +17 -0
  183. package/dist/src/automations/storage/automation-run-repository.js +130 -0
  184. package/dist/src/automations/storage/automation-run-repository.js.map +1 -0
  185. package/dist/src/automations/storage/index.d.ts +2 -0
  186. package/dist/src/automations/storage/index.js +3 -0
  187. package/dist/src/channels/plugin-types.d.ts +3 -0
  188. package/dist/src/chat-commands/builtins/thinking.js.map +1 -1
  189. package/dist/src/cli/command-catalog.js +0 -39
  190. package/dist/src/cli/command-catalog.js.map +1 -1
  191. package/dist/src/cli/command-loaders.js +0 -1
  192. package/dist/src/cli/command-loaders.js.map +1 -1
  193. package/dist/src/cli/command-manifest.js +0 -4
  194. package/dist/src/cli/command-manifest.js.map +1 -1
  195. package/dist/src/cli/commands/agents.js +7 -6
  196. package/dist/src/cli/commands/agents.js.map +1 -1
  197. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  198. package/dist/src/cli/commands/doctor/checks/{cron-health.d.ts → migrations.d.ts} +1 -1
  199. package/dist/src/cli/commands/doctor/checks/migrations.js +40 -0
  200. package/dist/src/cli/commands/doctor/checks/migrations.js.map +1 -0
  201. package/dist/src/cli/commands/doctor/flow.js +2 -2
  202. package/dist/src/cli/commands/doctor/flow.js.map +1 -1
  203. package/dist/src/cli/commands/gateway/call.js +2 -2
  204. package/dist/src/cli/commands/gateway/call.js.map +1 -1
  205. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  206. package/dist/src/cli/commands/gateway/run-foreground.js +4 -2
  207. package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
  208. package/dist/src/cli/commands/init.js +26 -8
  209. package/dist/src/cli/commands/init.js.map +1 -1
  210. package/dist/src/cli/commands/tui.js +24 -2
  211. package/dist/src/cli/commands/tui.js.map +1 -1
  212. package/dist/src/cli/utils/init-workspace-core.js +2 -0
  213. package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
  214. package/dist/src/commands/agents.config.d.ts +9 -0
  215. package/dist/src/commands/agents.config.js +40 -2
  216. package/dist/src/commands/agents.config.js.map +1 -1
  217. package/dist/src/config/agent-profile.js +4 -3
  218. package/dist/src/config/agent-profile.js.map +1 -1
  219. package/dist/src/config/agent-typed-models.js.map +1 -1
  220. package/dist/src/config/config-surface.d.ts +3 -0
  221. package/dist/src/config/index.d.ts +0 -1
  222. package/dist/src/config/index.js +3 -3
  223. package/dist/src/config/index.js.map +1 -1
  224. package/dist/src/config/paths.d.ts +0 -9
  225. package/dist/src/config/paths.js +1 -14
  226. package/dist/src/config/paths.js.map +1 -1
  227. package/dist/src/config/profile.js +0 -1
  228. package/dist/src/config/profile.js.map +1 -1
  229. package/dist/src/config/rules.js +0 -5
  230. package/dist/src/config/rules.js.map +1 -1
  231. package/dist/src/config/schema.d.ts +13 -12
  232. package/dist/src/config/schema.js +22 -26
  233. package/dist/src/config/schema.js.map +1 -1
  234. package/dist/src/config/web-patch.d.ts +0 -12
  235. package/dist/src/config/web-patch.js +2 -29
  236. package/dist/src/config/web-patch.js.map +1 -1
  237. package/dist/src/extensions/api.d.ts +2 -0
  238. package/dist/src/extensions/api.js +10 -0
  239. package/dist/src/extensions/api.js.map +1 -1
  240. package/dist/src/extensions/extension-registry-impl.d.ts +4 -1
  241. package/dist/src/extensions/extension-registry-impl.js +8 -0
  242. package/dist/src/extensions/extension-registry-impl.js.map +1 -1
  243. package/dist/src/extensions/loader.d.ts +3 -3
  244. package/dist/src/extensions/loader.js +3 -3
  245. package/dist/src/extensions/loader.js.map +1 -1
  246. package/dist/src/extensions/sdk/testing.d.ts +2 -0
  247. package/dist/src/extensions/sdk/testing.js +7 -0
  248. package/dist/src/extensions/sdk/testing.js.map +1 -1
  249. package/dist/src/extensions/types/core.d.ts +10 -1
  250. package/dist/src/extensions/types/index.d.ts +1 -1
  251. package/dist/src/extensions/types/{phase4.d.ts → registration.d.ts} +2 -2
  252. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  253. package/dist/src/gateway/agent-builtin-tools.js +1 -1
  254. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  255. package/dist/src/gateway/agents-admin.d.ts +1 -0
  256. package/dist/src/gateway/agents-admin.js +13 -15
  257. package/dist/src/gateway/agents-admin.js.map +1 -1
  258. package/dist/src/gateway/capability-presets-admin.d.ts +1 -0
  259. package/dist/src/gateway/capability-presets-admin.js +19 -10
  260. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  261. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +11 -0
  262. package/dist/src/gateway/dreaming-automation-reconciler.js +105 -0
  263. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -0
  264. package/dist/src/gateway/heartbeat/service.d.ts +0 -2
  265. package/dist/src/gateway/heartbeat/service.js +0 -7
  266. package/dist/src/gateway/heartbeat/service.js.map +1 -1
  267. package/dist/src/gateway/hono/lib/config-payload.d.ts +5 -6
  268. package/dist/src/gateway/hono/lib/config-payload.js +2 -2
  269. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  270. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  271. package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +1 -1
  272. package/dist/src/gateway/hono/routes/config-patch/misc.js +12 -6
  273. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  274. package/dist/src/gateway/hono/routes/dreaming.js +27 -37
  275. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  276. package/dist/src/gateway/hono/routes/home.d.ts +2 -2
  277. package/dist/src/gateway/hono/routes/home.js +34 -25
  278. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  279. package/dist/src/gateway/hono/routes/lazy-bundles.js +10 -6
  280. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  281. package/dist/src/gateway/hono/routes/migrations.d.ts +3 -0
  282. package/dist/src/gateway/hono/routes/migrations.js +35 -0
  283. package/dist/src/gateway/hono/routes/migrations.js.map +1 -0
  284. package/dist/src/gateway/hono/routes/public-gateway.js +2 -1
  285. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  286. package/dist/src/gateway/hono/routes/sessions.js +14 -0
  287. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  288. package/dist/src/gateway/run-loop.js +2 -0
  289. package/dist/src/gateway/run-loop.js.map +1 -1
  290. package/dist/src/gateway/security/operator-scopes.js +5 -1
  291. package/dist/src/gateway/security/operator-scopes.js.map +1 -1
  292. package/dist/src/gateway/service/config-coordinator.d.ts +4 -4
  293. package/dist/src/gateway/service/config-coordinator.js +14 -8
  294. package/dist/src/gateway/service/config-coordinator.js.map +1 -1
  295. package/dist/src/gateway/service/sessions-api.d.ts +2 -1
  296. package/dist/src/gateway/service/sessions-api.js +6 -1
  297. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  298. package/dist/src/gateway/service.d.ts +7 -3
  299. package/dist/src/gateway/service.js +61 -27
  300. package/dist/src/gateway/service.js.map +1 -1
  301. package/dist/src/goals/goal-service.js +45 -4
  302. package/dist/src/goals/goal-service.js.map +1 -1
  303. package/dist/src/infra/update-restart.js +1 -1
  304. package/dist/src/migrations/config/default-capability-preset.d.ts +10 -0
  305. package/dist/src/migrations/config/default-capability-preset.js +135 -0
  306. package/dist/src/migrations/config/default-capability-preset.js.map +1 -0
  307. package/dist/src/migrations/index.d.ts +4 -0
  308. package/dist/src/migrations/index.js +4 -0
  309. package/dist/src/migrations/registry.d.ts +8 -0
  310. package/dist/src/migrations/registry.js +18 -0
  311. package/dist/src/migrations/registry.js.map +1 -0
  312. package/dist/src/migrations/runner.d.ts +17 -0
  313. package/dist/src/migrations/runner.js +191 -0
  314. package/dist/src/migrations/runner.js.map +1 -0
  315. package/dist/src/migrations/types.d.ts +34 -0
  316. package/dist/src/notes/service.js +24 -1
  317. package/dist/src/notes/service.js.map +1 -1
  318. package/dist/src/providers/model-registry.d.ts +0 -1
  319. package/dist/src/providers/model-registry.js +0 -3
  320. package/dist/src/providers/model-registry.js.map +1 -1
  321. package/dist/src/routing/resolve-tui-session-key.d.ts +3 -0
  322. package/dist/src/routing/resolve-tui-session-key.js +14 -3
  323. package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
  324. package/dist/src/session/transcript-outline.d.ts +47 -0
  325. package/dist/src/session/transcript-outline.js +481 -0
  326. package/dist/src/session/transcript-outline.js.map +1 -0
  327. package/dist/src/storage/sqlite/index.d.ts +0 -2
  328. package/dist/src/storage/sqlite/index.js +1 -3
  329. package/dist/src/storage/sqlite/migrations/016_automations.sql +47 -0
  330. package/dist/src/storage/sqlite/migrations/017_automation_run_events.sql +14 -0
  331. package/dist/src/storage/sqlite/migrations/018_automation_safety.sql +1 -0
  332. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  333. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  334. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  335. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  336. package/dist/src/storage/sqlite/schema.js +1 -1
  337. package/dist/src/storage/sqlite/schema.sql +56 -46
  338. package/dist/src/tui/backends/embedded-backend.d.ts +6 -0
  339. package/dist/src/tui/backends/embedded-backend.js +18 -7
  340. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  341. package/dist/src/tui/backends/gateway-sse-backend.d.ts +3 -0
  342. package/dist/src/tui/backends/gateway-sse-backend.js +14 -0
  343. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  344. package/dist/src/tui/tui-backend.d.ts +4 -0
  345. package/dist/src/tui/tui-commands.d.ts +5 -0
  346. package/dist/src/tui/tui-commands.js +43 -0
  347. package/dist/src/tui/tui-commands.js.map +1 -1
  348. package/dist/src/tui/tui-transcript-tree.d.ts +1 -1
  349. package/dist/src/tui/tui-transcript-tree.js +17 -257
  350. package/dist/src/tui/tui-transcript-tree.js.map +1 -1
  351. package/dist/src/tui/tui-types.d.ts +2 -0
  352. package/dist/src/tui/tui-types.js.map +1 -1
  353. package/dist/src/tui/tui.js +7 -2
  354. package/dist/src/tui/tui.js.map +1 -1
  355. package/dist/src/workflows/domain/index.js +1 -1
  356. package/dist/src/workflows/domain/run.d.ts +7 -7
  357. package/dist/src/workflows/domain/run.js.map +1 -1
  358. package/dist/src/workflows/index.js +2 -2
  359. package/dist/src/workflows/service/workflow-run-service.d.ts +2 -0
  360. package/dist/src/workflows/service/workflow-run-service.js +31 -9
  361. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  362. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -1
  363. package/package.json +4 -2
  364. package/dist/gateway/static/root/assets/agents-BCxZbkOw.js +0 -2
  365. package/dist/gateway/static/root/assets/app-management-settings-panel-bxYJVJpx.js +0 -1
  366. package/dist/gateway/static/root/assets/appearance-settings-BCIykXlI.js +0 -1
  367. package/dist/gateway/static/root/assets/browser-settings-page-DRhKdn81.js +0 -8
  368. package/dist/gateway/static/root/assets/capability-presets-api-CorhiHlg.js +0 -1
  369. package/dist/gateway/static/root/assets/capability-presets-settings-panel-qFx9Jtce.js +0 -1
  370. package/dist/gateway/static/root/assets/channels-settings-BAwAkqIA.js +0 -1
  371. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +0 -1
  372. package/dist/gateway/static/root/assets/connectors-page-BQLcfitM.js +0 -2
  373. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +0 -1
  374. package/dist/gateway/static/root/assets/cron-api-qGwmL-24.js +0 -1
  375. package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +0 -1
  376. package/dist/gateway/static/root/assets/cron-page-BBWMAj8-.js +0 -3
  377. package/dist/gateway/static/root/assets/dreaming-settings-Dw89Obml.js +0 -1
  378. package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +0 -2
  379. package/dist/gateway/static/root/assets/format-interval-label-BzxafKxR.js +0 -1
  380. package/dist/gateway/static/root/assets/gateway-settings-Cmwy58rS.js +0 -1
  381. package/dist/gateway/static/root/assets/goal-detail-page-l7mu5GWX.js +0 -1
  382. package/dist/gateway/static/root/assets/goals-settings-CYVY4NGp.js +0 -1
  383. package/dist/gateway/static/root/assets/heartbeat-config-api-DriO_CN9.js +0 -1
  384. package/dist/gateway/static/root/assets/heartbeat-settings-CUQTKxg7.js +0 -1
  385. package/dist/gateway/static/root/assets/index-C17Tsd_b.css +0 -1
  386. package/dist/gateway/static/root/assets/index-Cc41r16l.js +0 -191
  387. package/dist/gateway/static/root/assets/interval-presets-DFPCKW_W.js +0 -1
  388. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-CcVcqstx.js +0 -1
  389. package/dist/gateway/static/root/assets/messages-B1iSKjiw.js +0 -3
  390. package/dist/gateway/static/root/assets/models-hub-panel-BfLfcta8.js +0 -2
  391. package/dist/gateway/static/root/assets/note-detail-page-BjwOQBfT.js +0 -2
  392. package/dist/gateway/static/root/assets/notes-page-DktdBiwB.js +0 -1
  393. package/dist/gateway/static/root/assets/remote-access-hub-rfVx96fq.js +0 -1
  394. package/dist/gateway/static/root/assets/schedule-field-CUCKODde.js +0 -1
  395. package/dist/gateway/static/root/assets/sessions-page-DbtMFuuH.js +0 -1
  396. package/dist/gateway/static/root/assets/settings-advanced-gate-5re5gAnP.js +0 -1
  397. package/dist/gateway/static/root/assets/settings-page-D-WMyLlj.js +0 -1
  398. package/dist/gateway/static/root/assets/setup-status-panel-Cl-DEJAU.js +0 -1
  399. package/dist/gateway/static/root/assets/shares-settings-CyPVvbLt.js +0 -1
  400. package/dist/gateway/static/root/assets/skill-reload-api-CleTH1oz.js +0 -1
  401. package/dist/gateway/static/root/assets/skills-page-Ck8hdXqR.js +0 -2
  402. package/dist/gateway/static/root/assets/system-settings-panel-DI-LN_8G.js +0 -1
  403. package/dist/gateway/static/root/assets/typed-models-lib-kX9duch4.js +0 -1
  404. package/dist/gateway/static/root/assets/user-profile-settings-panel-B-UFPMXy.js +0 -1
  405. package/dist/gateway/static/root/assets/utils-Dm0hKalR.js +0 -1
  406. package/dist/gateway/static/root/assets/workflows-page-BtFGp2y_.js +0 -18
  407. package/dist/src/agent/fallback/error.d.ts +0 -22
  408. package/dist/src/agent/fallback/error.js +0 -32
  409. package/dist/src/agent/fallback/error.js.map +0 -1
  410. package/dist/src/agent/fallback/index.d.ts +0 -5
  411. package/dist/src/agent/fallback/index.js +0 -9
  412. package/dist/src/agent/fallback/index.js.map +0 -1
  413. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +0 -29
  414. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +0 -76
  415. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +0 -1
  416. package/dist/src/agent/service/reconcile-dreaming-cron.d.ts +0 -6
  417. package/dist/src/agent/service/reconcile-dreaming-cron.js +0 -84
  418. package/dist/src/agent/service/reconcile-dreaming-cron.js.map +0 -1
  419. package/dist/src/agent/tools/cronjob-tool.d.ts +0 -29
  420. package/dist/src/agent/tools/cronjob-tool.js +0 -274
  421. package/dist/src/agent/tools/cronjob-tool.js.map +0 -1
  422. package/dist/src/cli/commands/cron-cli.d.ts +0 -2
  423. package/dist/src/cli/commands/cron-cli.js +0 -15
  424. package/dist/src/cli/commands/cron-cli.js.map +0 -1
  425. package/dist/src/cli/commands/cron.d.ts +0 -4
  426. package/dist/src/cli/commands/cron.js +0 -188
  427. package/dist/src/cli/commands/cron.js.map +0 -1
  428. package/dist/src/cli/commands/doctor/checks/cron-health.js +0 -35
  429. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +0 -1
  430. package/dist/src/cron/execution-types.d.ts +0 -42
  431. package/dist/src/cron/executor.d.ts +0 -67
  432. package/dist/src/cron/executor.js +0 -669
  433. package/dist/src/cron/executor.js.map +0 -1
  434. package/dist/src/cron/index.d.ts +0 -7
  435. package/dist/src/cron/index.js +0 -7
  436. package/dist/src/cron/job-content.d.ts +0 -5
  437. package/dist/src/cron/job-content.js +0 -15
  438. package/dist/src/cron/job-content.js.map +0 -1
  439. package/dist/src/cron/run-log-store.d.ts +0 -12
  440. package/dist/src/cron/run-log-store.js +0 -58
  441. package/dist/src/cron/run-log-store.js.map +0 -1
  442. package/dist/src/cron/schedule.d.ts +0 -10
  443. package/dist/src/cron/schedule.js +0 -85
  444. package/dist/src/cron/schedule.js.map +0 -1
  445. package/dist/src/cron/service.d.ts +0 -58
  446. package/dist/src/cron/service.js +0 -419
  447. package/dist/src/cron/service.js.map +0 -1
  448. package/dist/src/cron/types.d.ts +0 -183
  449. package/dist/src/cron/validation.d.ts +0 -500
  450. package/dist/src/cron/validation.js +0 -192
  451. package/dist/src/cron/validation.js.map +0 -1
  452. package/dist/src/cron/workflow-run-completion.d.ts +0 -23
  453. package/dist/src/cron/workflow-run-completion.js +0 -72
  454. package/dist/src/cron/workflow-run-completion.js.map +0 -1
  455. package/dist/src/extensions/types/phase4.js +0 -1
  456. package/dist/src/gateway/hono/routes/cron.d.ts +0 -3
  457. package/dist/src/gateway/hono/routes/cron.js +0 -109
  458. package/dist/src/gateway/hono/routes/cron.js.map +0 -1
  459. package/dist/src/storage/sqlite/cron-job-repository.d.ts +0 -6
  460. package/dist/src/storage/sqlite/cron-job-repository.js +0 -70
  461. package/dist/src/storage/sqlite/cron-job-repository.js.map +0 -1
  462. package/dist/src/storage/sqlite/cron-run-repository.d.ts +0 -5
  463. package/dist/src/storage/sqlite/cron-run-repository.js +0 -96
  464. package/dist/src/storage/sqlite/cron-run-repository.js.map +0 -1
  465. /package/dist/src/{cron → automations/domain}/types.js +0 -0
  466. /package/dist/src/{config/defaults.d.ts → automations/draft/automation-draft.types.js} +0 -0
  467. /package/dist/src/{config/defaults.js → extensions/types/registration.js} +0 -0
  468. /package/dist/src/{cron/execution-types.js → migrations/types.js} +0 -0
@@ -0,0 +1,105 @@
1
+ import { init_agent_scope, resolveDefaultAgentId } from "../agent/agent-scope.js";
2
+ import { DREAMING_CRON_NAME, DREAMING_CRON_TAG, DREAMING_LIGHT_CRON_NAME, DREAMING_LIGHT_SWEEP_TOKEN, DREAMING_REM_CRON_NAME, DREAMING_REM_SWEEP_TOKEN, DREAMING_SWEEP_TOKEN } from "../agent/memory/dreaming/constants.js";
3
+ import { resolveDreamingConfig } from "../agent/memory/dreaming/config.js";
4
+ import { getWorkspacePath } from "../config/workspace-path-helpers.js";
5
+ //#region src/gateway/dreaming-automation-reconciler.ts
6
+ init_agent_scope();
7
+ const DREAMING_AUTOMATIONS = [
8
+ {
9
+ id: "system-dreaming-light",
10
+ phase: "light",
11
+ name: DREAMING_LIGHT_CRON_NAME,
12
+ token: DREAMING_LIGHT_SWEEP_TOKEN
13
+ },
14
+ {
15
+ id: "system-dreaming-deep",
16
+ phase: "deep",
17
+ name: DREAMING_CRON_NAME,
18
+ token: DREAMING_SWEEP_TOKEN
19
+ },
20
+ {
21
+ id: "system-dreaming-rem",
22
+ phase: "rem",
23
+ name: DREAMING_REM_CRON_NAME,
24
+ token: DREAMING_REM_SWEEP_TOKEN
25
+ }
26
+ ];
27
+ function phaseDescription(phase) {
28
+ return `${phase === "light" ? "Light sweep" : phase === "deep" ? "Deep promotion" : "REM pattern discovery"} for memory dreaming. ${DREAMING_CRON_TAG}`;
29
+ }
30
+ function buildTrigger(config, phase) {
31
+ return {
32
+ kind: "schedule",
33
+ schedule: {
34
+ kind: "cron",
35
+ expr: config.phases[phase].cron,
36
+ ...config.timezone ? { tz: config.timezone } : {}
37
+ }
38
+ };
39
+ }
40
+ function buildAction(config, agentId, token) {
41
+ const workspaceDir = getWorkspacePath(config);
42
+ return {
43
+ kind: "agent",
44
+ agentId,
45
+ instruction: token,
46
+ ...workspaceDir ? { workingDirectory: workspaceDir } : {},
47
+ timeoutSeconds: 3600
48
+ };
49
+ }
50
+ function automationNeedsUpdate(current, next) {
51
+ return current.name !== next.name || current.description !== next.description || current.enabled !== next.enabled || JSON.stringify(current.trigger) !== JSON.stringify(next.trigger) || JSON.stringify(current.action) !== JSON.stringify(next.action) || current.safety?.mode !== "auto_apply" || current.afterRun?.kind !== "none" || current.reliability?.disableAfterConsecutiveFailures !== 3;
52
+ }
53
+ async function reconcileDreamingAutomations(params) {
54
+ const { config, automationService } = params;
55
+ const resolved = resolveDreamingConfig(config);
56
+ const agentId = resolveDefaultAgentId(config);
57
+ const result = {
58
+ created: [],
59
+ updated: [],
60
+ disabled: []
61
+ };
62
+ for (const spec of DREAMING_AUTOMATIONS) {
63
+ const current = await automationService.get(spec.id);
64
+ const enabled = resolved.enabled && resolved.phases[spec.phase].enabled;
65
+ if (!resolved.enabled) {
66
+ if (current?.enabled) {
67
+ await automationService.update(spec.id, { enabled: false });
68
+ result.disabled.push(spec.id);
69
+ }
70
+ continue;
71
+ }
72
+ const next = {
73
+ name: spec.name,
74
+ description: phaseDescription(spec.phase),
75
+ enabled,
76
+ trigger: buildTrigger(resolved, spec.phase),
77
+ action: buildAction(config, agentId, spec.token)
78
+ };
79
+ if (!current) {
80
+ await automationService.create({
81
+ id: spec.id,
82
+ ...next,
83
+ safety: { mode: "auto_apply" },
84
+ afterRun: { kind: "none" },
85
+ reliability: { disableAfterConsecutiveFailures: 3 }
86
+ });
87
+ result.created.push(spec.id);
88
+ continue;
89
+ }
90
+ if (automationNeedsUpdate(current, next)) {
91
+ await automationService.update(spec.id, {
92
+ ...next,
93
+ safety: { mode: "auto_apply" },
94
+ afterRun: { kind: "none" },
95
+ reliability: { disableAfterConsecutiveFailures: 3 }
96
+ });
97
+ result.updated.push(spec.id);
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+ //#endregion
103
+ export { reconcileDreamingAutomations };
104
+
105
+ //# sourceMappingURL=dreaming-automation-reconciler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dreaming-automation-reconciler.js","names":[],"sources":["../../../src/gateway/dreaming-automation-reconciler.ts"],"sourcesContent":["import type { Config } from '../config/schema.js';\nimport { getWorkspacePath } from '../config/workspace-path-helpers.js';\nimport { resolveDefaultAgentId } from '../agent/agent-scope.js';\nimport { resolveDreamingConfig, type DreamingResolvedConfig } from '../agent/memory/dreaming/config.js';\nimport {\n DREAMING_CRON_NAME,\n DREAMING_CRON_TAG,\n DREAMING_LIGHT_CRON_NAME,\n DREAMING_LIGHT_SWEEP_TOKEN,\n DREAMING_REM_CRON_NAME,\n DREAMING_REM_SWEEP_TOKEN,\n DREAMING_SWEEP_TOKEN,\n type DreamingPhaseId,\n} from '../agent/memory/dreaming/constants.js';\nimport type { AutomationService } from '../automations/index.js';\nimport type { Automation, AutomationAction, AutomationTrigger } from '../automations/domain/types.js';\n\ntype DreamingAutomationSpec = {\n id: string;\n phase: DreamingPhaseId;\n name: string;\n token: string;\n};\n\nconst DREAMING_AUTOMATIONS: readonly DreamingAutomationSpec[] = [\n {\n id: 'system-dreaming-light',\n phase: 'light',\n name: DREAMING_LIGHT_CRON_NAME,\n token: DREAMING_LIGHT_SWEEP_TOKEN,\n },\n {\n id: 'system-dreaming-deep',\n phase: 'deep',\n name: DREAMING_CRON_NAME,\n token: DREAMING_SWEEP_TOKEN,\n },\n {\n id: 'system-dreaming-rem',\n phase: 'rem',\n name: DREAMING_REM_CRON_NAME,\n token: DREAMING_REM_SWEEP_TOKEN,\n },\n];\n\nexport type DreamingAutomationReconcileResult = {\n created: string[];\n updated: string[];\n disabled: string[];\n};\n\nfunction phaseDescription(phase: DreamingPhaseId): string {\n const label = phase === 'light' ? 'Light sweep' : phase === 'deep' ? 'Deep promotion' : 'REM pattern discovery';\n return `${label} for memory dreaming. ${DREAMING_CRON_TAG}`;\n}\n\nfunction buildTrigger(config: DreamingResolvedConfig, phase: DreamingPhaseId): AutomationTrigger {\n const phaseConfig = config.phases[phase];\n return {\n kind: 'schedule',\n schedule: {\n kind: 'cron',\n expr: phaseConfig.cron,\n ...(config.timezone ? { tz: config.timezone } : {}),\n },\n };\n}\n\nfunction buildAction(config: Config, agentId: string, token: string): AutomationAction {\n const workspaceDir = getWorkspacePath(config);\n return {\n kind: 'agent',\n agentId,\n instruction: token,\n ...(workspaceDir ? { workingDirectory: workspaceDir } : {}),\n timeoutSeconds: 3600,\n };\n}\n\nfunction automationNeedsUpdate(current: Automation, next: {\n name: string;\n description: string;\n enabled: boolean;\n trigger: AutomationTrigger;\n action: AutomationAction;\n}): boolean {\n return (\n current.name !== next.name ||\n current.description !== next.description ||\n current.enabled !== next.enabled ||\n JSON.stringify(current.trigger) !== JSON.stringify(next.trigger) ||\n JSON.stringify(current.action) !== JSON.stringify(next.action) ||\n current.safety?.mode !== 'auto_apply' ||\n current.afterRun?.kind !== 'none' ||\n current.reliability?.disableAfterConsecutiveFailures !== 3\n );\n}\n\nexport async function reconcileDreamingAutomations(params: {\n config: Config;\n automationService: AutomationService;\n}): Promise<DreamingAutomationReconcileResult> {\n const { config, automationService } = params;\n const resolved = resolveDreamingConfig(config);\n const agentId = resolveDefaultAgentId(config);\n const result: DreamingAutomationReconcileResult = { created: [], updated: [], disabled: [] };\n\n for (const spec of DREAMING_AUTOMATIONS) {\n const current = await automationService.get(spec.id);\n const enabled = resolved.enabled && resolved.phases[spec.phase].enabled;\n\n if (!resolved.enabled) {\n if (current?.enabled) {\n await automationService.update(spec.id, { enabled: false });\n result.disabled.push(spec.id);\n }\n continue;\n }\n\n const next = {\n name: spec.name,\n description: phaseDescription(spec.phase),\n enabled,\n trigger: buildTrigger(resolved, spec.phase),\n action: buildAction(config, agentId, spec.token),\n };\n\n if (!current) {\n await automationService.create({\n id: spec.id,\n ...next,\n safety: { mode: 'auto_apply' },\n afterRun: { kind: 'none' },\n reliability: { disableAfterConsecutiveFailures: 3 },\n });\n result.created.push(spec.id);\n continue;\n }\n\n if (automationNeedsUpdate(current, next)) {\n await automationService.update(spec.id, {\n ...next,\n safety: { mode: 'auto_apply' },\n afterRun: { kind: 'none' },\n reliability: { disableAfterConsecutiveFailures: 3 },\n });\n result.updated.push(spec.id);\n }\n }\n\n return result;\n}\n"],"mappings":";;;;;kBAEgE;AAsBhE,MAAM,uBAA0D;CAC9D;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,OAAO;EACR;CACD;EACE,IAAI;EACJ,OAAO;EACP,MAAM;EACN,OAAO;EACR;CACF;AAQD,SAAS,iBAAiB,OAAgC;AAExD,QAAO,GADO,UAAU,UAAU,gBAAgB,UAAU,SAAS,mBAAmB,wBACxE,wBAAwB;;AAG1C,SAAS,aAAa,QAAgC,OAA2C;AAE/F,QAAO;EACL,MAAM;EACN,UAAU;GACR,MAAM;GACN,MALgB,OAAO,OAAO,OAKZ;GAClB,GAAI,OAAO,WAAW,EAAE,IAAI,OAAO,UAAU,GAAG,EAAE;GACnD;EACF;;AAGH,SAAS,YAAY,QAAgB,SAAiB,OAAiC;CACrF,MAAM,eAAe,iBAAiB,OAAO;AAC7C,QAAO;EACL,MAAM;EACN;EACA,aAAa;EACb,GAAI,eAAe,EAAE,kBAAkB,cAAc,GAAG,EAAE;EAC1D,gBAAgB;EACjB;;AAGH,SAAS,sBAAsB,SAAqB,MAMxC;AACV,QACE,QAAQ,SAAS,KAAK,QACtB,QAAQ,gBAAgB,KAAK,eAC7B,QAAQ,YAAY,KAAK,WACzB,KAAK,UAAU,QAAQ,QAAQ,KAAK,KAAK,UAAU,KAAK,QAAQ,IAChE,KAAK,UAAU,QAAQ,OAAO,KAAK,KAAK,UAAU,KAAK,OAAO,IAC9D,QAAQ,QAAQ,SAAS,gBACzB,QAAQ,UAAU,SAAS,UAC3B,QAAQ,aAAa,oCAAoC;;AAI7D,eAAsB,6BAA6B,QAGJ;CAC7C,MAAM,EAAE,QAAQ,sBAAsB;CACtC,MAAM,WAAW,sBAAsB,OAAO;CAC9C,MAAM,UAAU,sBAAsB,OAAO;CAC7C,MAAM,SAA4C;EAAE,SAAS,EAAE;EAAE,SAAS,EAAE;EAAE,UAAU,EAAE;EAAE;AAE5F,MAAK,MAAM,QAAQ,sBAAsB;EACvC,MAAM,UAAU,MAAM,kBAAkB,IAAI,KAAK,GAAG;EACpD,MAAM,UAAU,SAAS,WAAW,SAAS,OAAO,KAAK,OAAO;AAEhE,MAAI,CAAC,SAAS,SAAS;AACrB,OAAI,SAAS,SAAS;AACpB,UAAM,kBAAkB,OAAO,KAAK,IAAI,EAAE,SAAS,OAAO,CAAC;AAC3D,WAAO,SAAS,KAAK,KAAK,GAAG;;AAE/B;;EAGF,MAAM,OAAO;GACX,MAAM,KAAK;GACX,aAAa,iBAAiB,KAAK,MAAM;GACzC;GACA,SAAS,aAAa,UAAU,KAAK,MAAM;GAC3C,QAAQ,YAAY,QAAQ,SAAS,KAAK,MAAM;GACjD;AAED,MAAI,CAAC,SAAS;AACZ,SAAM,kBAAkB,OAAO;IAC7B,IAAI,KAAK;IACT,GAAG;IACH,QAAQ,EAAE,MAAM,cAAc;IAC9B,UAAU,EAAE,MAAM,QAAQ;IAC1B,aAAa,EAAE,iCAAiC,GAAG;IACpD,CAAC;AACF,UAAO,QAAQ,KAAK,KAAK,GAAG;AAC5B;;AAGF,MAAI,sBAAsB,SAAS,KAAK,EAAE;AACxC,SAAM,kBAAkB,OAAO,KAAK,IAAI;IACtC,GAAG;IACH,QAAQ,EAAE,MAAM,cAAc;IAC9B,UAAU,EAAE,MAAM,QAAQ;IAC1B,aAAa,EAAE,iCAAiC,GAAG;IACpD,CAAC;AACF,UAAO,QAAQ,KAAK,KAAK,GAAG;;;AAIhC,QAAO"}
@@ -1,6 +1,5 @@
1
1
  import type { AgentService } from '../../agent/service.js';
2
2
  import type { Config } from '../../config/schema.js';
3
- import { CronService } from '../../cron/service.js';
4
3
  import type { MessageBus } from '../../infra/bus/index.js';
5
4
  import type { SessionStore } from '../../session/store.js';
6
5
  export interface HeartbeatRunnerConfig {
@@ -22,7 +21,6 @@ export declare function heartbeatRunnerConfigFromConfig(cfg: Config): HeartbeatR
22
21
  export interface HeartbeatServiceDeps {
23
22
  agentService: AgentService;
24
23
  messageBus: MessageBus;
25
- cronService: CronService;
26
24
  sessionStore: SessionStore;
27
25
  /** Current app config (for HEARTBEAT.md path under the default agent `profile/` directory). */
28
26
  getConfig: () => Config;
@@ -80,13 +80,6 @@ var HeartbeatService = class {
80
80
  log.debug({ reasons: reasonSummary }, "Heartbeat: skip (disabled)");
81
81
  return;
82
82
  }
83
- try {
84
- const metrics = await this.deps.cronService.getMetrics();
85
- log.trace({
86
- runningJobs: metrics.runningJobs,
87
- enabledJobs: metrics.enabledJobs
88
- }, "Heartbeat: cron metrics");
89
- } catch {}
90
83
  if (cfg.activeHours && !isWithinActiveHours(cfg.activeHours)) {
91
84
  log.debug({ reasons: reasonSummary }, "Heartbeat: skip (outside active hours)");
92
85
  return;
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","names":[],"sources":["../../../../src/gateway/heartbeat/service.ts"],"sourcesContent":["import { readFile } from 'fs/promises';\n\nimport type { AgentService } from '../../agent/service.js';\nimport type { Config } from '../../config/schema.js';\nimport { CronService } from '../../cron/service.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { appendCronEventLines } from '../../heartbeat/event-prompt.js';\nimport { isWithinActiveHours } from '../../heartbeat/active-hours.js';\nimport { isHeartbeatContentEmpty } from '../../heartbeat/content-check.js';\nimport {\n DEFAULT_ACK_MAX_CHARS,\n stripHeartbeatToken,\n shouldSilence,\n} from '../../heartbeat/tokens.js';\nimport { createHeartbeatWake } from '../../heartbeat/wake.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveHeartbeatMdPath } from '../workspace-heartbeat-path.js';\n\nconst log = createLogger('HeartbeatService');\n\nconst DEFAULT_PROMPT =\n 'Read HEARTBEAT.md if it exists. Follow it strictly. If nothing needs attention, reply HEARTBEAT_OK.';\n\nexport interface HeartbeatRunnerConfig {\n enabled: boolean;\n intervalMs: number;\n target?: string;\n targetChatId?: string;\n prompt?: string;\n ackMaxChars?: number;\n isolatedSession?: boolean;\n activeHours?: {\n start: string;\n end: string;\n timezone?: string;\n };\n}\n\nfunction mapConfigToRunner(cfg: Config | undefined): HeartbeatRunnerConfig {\n const h = cfg?.gateway?.heartbeat;\n return {\n enabled: h?.enabled ?? true,\n intervalMs: h?.intervalMs ?? 1_800_000,\n target: h?.target,\n targetChatId: h?.targetChatId,\n prompt: h?.prompt,\n ackMaxChars: h?.ackMaxChars,\n isolatedSession: h?.isolatedSession,\n activeHours: h?.activeHours,\n };\n}\n\n/** Map persisted gateway config to runner options (gateway start / reload). */\nexport function heartbeatRunnerConfigFromConfig(cfg: Config): HeartbeatRunnerConfig {\n return mapConfigToRunner(cfg);\n}\n\nexport interface HeartbeatServiceDeps {\n agentService: AgentService;\n messageBus: MessageBus;\n cronService: CronService;\n sessionStore: SessionStore;\n /** Current app config (for HEARTBEAT.md path under the default agent `profile/` directory). */\n getConfig: () => Config;\n}\n\nexport class HeartbeatService {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private wake: ReturnType<typeof createHeartbeatWake>;\n private lastHeartbeatText = '';\n private lastHeartbeatAt = 0;\n private runnerConfig: HeartbeatRunnerConfig | null = null;\n\n constructor(private deps: HeartbeatServiceDeps) {\n this.wake = createHeartbeatWake((reasons) => this.runHeartbeatOnce(reasons));\n }\n\n start(config: HeartbeatRunnerConfig): void {\n if (!config.enabled) {\n log.info('Heartbeat disabled');\n this.runnerConfig = null;\n return;\n }\n\n this.runnerConfig = config;\n log.info({ intervalMs: config.intervalMs }, 'Heartbeat timer started (interval wake)');\n\n this.intervalId = setInterval(() => {\n this.wake.request({ reason: 'interval' });\n }, config.intervalMs);\n this.intervalId.unref?.();\n }\n\n /** Cron, exec completion, manual triggers, etc. */\n requestNow(opts?: { reason?: string }): void {\n this.wake.request({ reason: opts?.reason ?? 'manual' });\n }\n\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n this.wake.stop();\n this.runnerConfig = null;\n log.info('Heartbeat stopped');\n }\n\n updateConfig(config: Config): void {\n const mapped = mapConfigToRunner(config);\n this.stop();\n if (mapped.enabled) {\n this.start(mapped);\n }\n log.info('Heartbeat config updated');\n }\n\n isRunning(): boolean {\n return this.intervalId !== null;\n }\n\n private async runHeartbeatOnce(reasons: string[]): Promise<void> {\n const reasonSummary = [...new Set(reasons)].join(', ') || 'unknown';\n\n const cfg = this.runnerConfig;\n if (!cfg?.enabled) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (disabled)');\n return;\n }\n\n try {\n const metrics = await this.deps.cronService.getMetrics();\n log.trace(\n { runningJobs: metrics.runningJobs, enabledJobs: metrics.enabledJobs },\n 'Heartbeat: cron metrics',\n );\n } catch {\n /* optional */\n }\n\n if (cfg.activeHours && !isWithinActiveHours(cfg.activeHours)) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (outside active hours)');\n return;\n }\n\n const heartbeatPath = resolveHeartbeatMdPath(this.deps.getConfig());\n if (!heartbeatPath) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (no HEARTBEAT path)');\n return;\n }\n let heartbeatContent: string | undefined;\n try {\n const raw = await readFile(heartbeatPath, 'utf-8');\n if (isHeartbeatContentEmpty(raw)) {\n log.debug({ path: heartbeatPath, reasons: reasonSummary }, 'Heartbeat: skip (HEARTBEAT.md empty)');\n return;\n }\n heartbeatContent = raw.trim();\n } catch {\n log.debug({ path: heartbeatPath, reasons: reasonSummary }, 'Heartbeat: HEARTBEAT.md missing; continuing');\n }\n\n const sessionKey = cfg.isolatedSession\n ? `heartbeat:isolated:${Date.now()}`\n : 'heartbeat:main';\n\n let basePrompt = (cfg.prompt?.trim() || DEFAULT_PROMPT).trim();\n if (heartbeatContent) {\n basePrompt = `${basePrompt}\\n\\n---\\nHEARTBEAT.md:\\n${heartbeatContent}\\n---`;\n }\n basePrompt = appendCronEventLines(basePrompt, reasons);\n const prompt = `${basePrompt}\\n\\nCurrent time: ${new Date().toISOString()}`;\n\n const ackMax = cfg.ackMaxChars ?? DEFAULT_ACK_MAX_CHARS;\n\n log.debug({ sessionKey, reasons: reasonSummary }, 'Heartbeat: invoking agent');\n\n // `heartbeat:main` reuses one session key; each run would otherwise append to the transcript\n // until the model rejects the request (context window exceeded). Heartbeat prompts are\n // self-contained (HEARTBEAT.md + this turn's text), so we start from an empty history.\n if (sessionKey === 'heartbeat:main') {\n try {\n await this.deps.sessionStore.saveMessages(sessionKey, [], {\n metadata: {\n sourceChannel: 'heartbeat',\n sourceChatId: 'main',\n sessionType: 'heartbeat',\n customData: { heartbeatTarget: 'main' },\n routing: {\n agentId: 'main',\n source: 'heartbeat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: 'main',\n },\n },\n });\n } catch (err) {\n log.warn({ err, sessionKey }, 'Heartbeat: failed to reset main session transcript');\n }\n }\n\n let reply: string;\n try {\n reply = await this.deps.agentService.turnDispatcher.processDirect(prompt, sessionKey);\n } catch (error) {\n log.error({ err: error }, 'Heartbeat: agent call failed');\n return;\n }\n\n if (!reply?.trim()) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (empty model reply)');\n return;\n }\n\n if (shouldSilence(reply, ackMax)) {\n log.info(\n { ackMax, replyChars: reply.length, reasons: reasonSummary },\n 'Heartbeat: not sent — silent (HEARTBEAT_OK / short ack)',\n );\n return;\n }\n\n const { stripped } = stripHeartbeatToken(reply);\n const finalText = stripped || reply.trim();\n\n if (this.isDuplicate(finalText)) {\n log.info(\n { finalTextChars: finalText.length, reasons: reasonSummary },\n 'Heartbeat: not sent — duplicate within 24h',\n );\n return;\n }\n\n const target = cfg.target?.trim();\n const targetChatId = cfg.targetChatId?.trim();\n const hasDeliveryTarget = Boolean(target && targetChatId);\n\n if (hasDeliveryTarget) {\n await this.deps.messageBus.publishOutbound({\n channel: target!,\n chat_id: targetChatId!,\n content: finalText,\n type: 'message',\n });\n log.info(\n {\n reasons: reasonSummary,\n channel: target,\n chatId: targetChatId,\n contentChars: finalText.length,\n },\n 'Heartbeat: sent — outbound queued',\n );\n } else {\n log.info(\n { reasons: reasonSummary, finalTextChars: finalText.length },\n 'Heartbeat: not sent — no delivery target (set gateway.heartbeat.target + targetChatId)',\n );\n }\n\n this.lastHeartbeatText = finalText;\n this.lastHeartbeatAt = Date.now();\n }\n\n private isDuplicate(text: string): boolean {\n const DEDUP_WINDOW_MS = 24 * 60 * 60 * 1000;\n return (\n text.trim() === this.lastHeartbeatText.trim() &&\n Date.now() - this.lastHeartbeatAt < DEDUP_WINDOW_MS\n );\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service.js","names":[],"sources":["../../../../src/gateway/heartbeat/service.ts"],"sourcesContent":["import { readFile } from 'fs/promises';\n\nimport type { AgentService } from '../../agent/service.js';\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { appendCronEventLines } from '../../heartbeat/event-prompt.js';\nimport { isWithinActiveHours } from '../../heartbeat/active-hours.js';\nimport { isHeartbeatContentEmpty } from '../../heartbeat/content-check.js';\nimport {\n DEFAULT_ACK_MAX_CHARS,\n stripHeartbeatToken,\n shouldSilence,\n} from '../../heartbeat/tokens.js';\nimport { createHeartbeatWake } from '../../heartbeat/wake.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { resolveHeartbeatMdPath } from '../workspace-heartbeat-path.js';\n\nconst log = createLogger('HeartbeatService');\n\nconst DEFAULT_PROMPT =\n 'Read HEARTBEAT.md if it exists. Follow it strictly. If nothing needs attention, reply HEARTBEAT_OK.';\n\nexport interface HeartbeatRunnerConfig {\n enabled: boolean;\n intervalMs: number;\n target?: string;\n targetChatId?: string;\n prompt?: string;\n ackMaxChars?: number;\n isolatedSession?: boolean;\n activeHours?: {\n start: string;\n end: string;\n timezone?: string;\n };\n}\n\nfunction mapConfigToRunner(cfg: Config | undefined): HeartbeatRunnerConfig {\n const h = cfg?.gateway?.heartbeat;\n return {\n enabled: h?.enabled ?? true,\n intervalMs: h?.intervalMs ?? 1_800_000,\n target: h?.target,\n targetChatId: h?.targetChatId,\n prompt: h?.prompt,\n ackMaxChars: h?.ackMaxChars,\n isolatedSession: h?.isolatedSession,\n activeHours: h?.activeHours,\n };\n}\n\n/** Map persisted gateway config to runner options (gateway start / reload). */\nexport function heartbeatRunnerConfigFromConfig(cfg: Config): HeartbeatRunnerConfig {\n return mapConfigToRunner(cfg);\n}\n\nexport interface HeartbeatServiceDeps {\n agentService: AgentService;\n messageBus: MessageBus;\n sessionStore: SessionStore;\n /** Current app config (for HEARTBEAT.md path under the default agent `profile/` directory). */\n getConfig: () => Config;\n}\n\nexport class HeartbeatService {\n private intervalId: ReturnType<typeof setInterval> | null = null;\n private wake: ReturnType<typeof createHeartbeatWake>;\n private lastHeartbeatText = '';\n private lastHeartbeatAt = 0;\n private runnerConfig: HeartbeatRunnerConfig | null = null;\n\n constructor(private deps: HeartbeatServiceDeps) {\n this.wake = createHeartbeatWake((reasons) => this.runHeartbeatOnce(reasons));\n }\n\n start(config: HeartbeatRunnerConfig): void {\n if (!config.enabled) {\n log.info('Heartbeat disabled');\n this.runnerConfig = null;\n return;\n }\n\n this.runnerConfig = config;\n log.info({ intervalMs: config.intervalMs }, 'Heartbeat timer started (interval wake)');\n\n this.intervalId = setInterval(() => {\n this.wake.request({ reason: 'interval' });\n }, config.intervalMs);\n this.intervalId.unref?.();\n }\n\n /** Cron, exec completion, manual triggers, etc. */\n requestNow(opts?: { reason?: string }): void {\n this.wake.request({ reason: opts?.reason ?? 'manual' });\n }\n\n stop(): void {\n if (this.intervalId) {\n clearInterval(this.intervalId);\n this.intervalId = null;\n }\n this.wake.stop();\n this.runnerConfig = null;\n log.info('Heartbeat stopped');\n }\n\n updateConfig(config: Config): void {\n const mapped = mapConfigToRunner(config);\n this.stop();\n if (mapped.enabled) {\n this.start(mapped);\n }\n log.info('Heartbeat config updated');\n }\n\n isRunning(): boolean {\n return this.intervalId !== null;\n }\n\n private async runHeartbeatOnce(reasons: string[]): Promise<void> {\n const reasonSummary = [...new Set(reasons)].join(', ') || 'unknown';\n\n const cfg = this.runnerConfig;\n if (!cfg?.enabled) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (disabled)');\n return;\n }\n\n if (cfg.activeHours && !isWithinActiveHours(cfg.activeHours)) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (outside active hours)');\n return;\n }\n\n const heartbeatPath = resolveHeartbeatMdPath(this.deps.getConfig());\n if (!heartbeatPath) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (no HEARTBEAT path)');\n return;\n }\n let heartbeatContent: string | undefined;\n try {\n const raw = await readFile(heartbeatPath, 'utf-8');\n if (isHeartbeatContentEmpty(raw)) {\n log.debug({ path: heartbeatPath, reasons: reasonSummary }, 'Heartbeat: skip (HEARTBEAT.md empty)');\n return;\n }\n heartbeatContent = raw.trim();\n } catch {\n log.debug({ path: heartbeatPath, reasons: reasonSummary }, 'Heartbeat: HEARTBEAT.md missing; continuing');\n }\n\n const sessionKey = cfg.isolatedSession\n ? `heartbeat:isolated:${Date.now()}`\n : 'heartbeat:main';\n\n let basePrompt = (cfg.prompt?.trim() || DEFAULT_PROMPT).trim();\n if (heartbeatContent) {\n basePrompt = `${basePrompt}\\n\\n---\\nHEARTBEAT.md:\\n${heartbeatContent}\\n---`;\n }\n basePrompt = appendCronEventLines(basePrompt, reasons);\n const prompt = `${basePrompt}\\n\\nCurrent time: ${new Date().toISOString()}`;\n\n const ackMax = cfg.ackMaxChars ?? DEFAULT_ACK_MAX_CHARS;\n\n log.debug({ sessionKey, reasons: reasonSummary }, 'Heartbeat: invoking agent');\n\n // `heartbeat:main` reuses one session key; each run would otherwise append to the transcript\n // until the model rejects the request (context window exceeded). Heartbeat prompts are\n // self-contained (HEARTBEAT.md + this turn's text), so we start from an empty history.\n if (sessionKey === 'heartbeat:main') {\n try {\n await this.deps.sessionStore.saveMessages(sessionKey, [], {\n metadata: {\n sourceChannel: 'heartbeat',\n sourceChatId: 'main',\n sessionType: 'heartbeat',\n customData: { heartbeatTarget: 'main' },\n routing: {\n agentId: 'main',\n source: 'heartbeat',\n accountId: 'default',\n peerKind: 'direct',\n peerId: 'main',\n },\n },\n });\n } catch (err) {\n log.warn({ err, sessionKey }, 'Heartbeat: failed to reset main session transcript');\n }\n }\n\n let reply: string;\n try {\n reply = await this.deps.agentService.turnDispatcher.processDirect(prompt, sessionKey);\n } catch (error) {\n log.error({ err: error }, 'Heartbeat: agent call failed');\n return;\n }\n\n if (!reply?.trim()) {\n log.debug({ reasons: reasonSummary }, 'Heartbeat: skip (empty model reply)');\n return;\n }\n\n if (shouldSilence(reply, ackMax)) {\n log.info(\n { ackMax, replyChars: reply.length, reasons: reasonSummary },\n 'Heartbeat: not sent — silent (HEARTBEAT_OK / short ack)',\n );\n return;\n }\n\n const { stripped } = stripHeartbeatToken(reply);\n const finalText = stripped || reply.trim();\n\n if (this.isDuplicate(finalText)) {\n log.info(\n { finalTextChars: finalText.length, reasons: reasonSummary },\n 'Heartbeat: not sent — duplicate within 24h',\n );\n return;\n }\n\n const target = cfg.target?.trim();\n const targetChatId = cfg.targetChatId?.trim();\n const hasDeliveryTarget = Boolean(target && targetChatId);\n\n if (hasDeliveryTarget) {\n await this.deps.messageBus.publishOutbound({\n channel: target!,\n chat_id: targetChatId!,\n content: finalText,\n type: 'message',\n });\n log.info(\n {\n reasons: reasonSummary,\n channel: target,\n chatId: targetChatId,\n contentChars: finalText.length,\n },\n 'Heartbeat: sent — outbound queued',\n );\n } else {\n log.info(\n { reasons: reasonSummary, finalTextChars: finalText.length },\n 'Heartbeat: not sent — no delivery target (set gateway.heartbeat.target + targetChatId)',\n );\n }\n\n this.lastHeartbeatText = finalText;\n this.lastHeartbeatAt = Date.now();\n }\n\n private isDuplicate(text: string): boolean {\n const DEDUP_WINDOW_MS = 24 * 60 * 60 * 1000;\n return (\n text.trim() === this.lastHeartbeatText.trim() &&\n Date.now() - this.lastHeartbeatAt < DEDUP_WINDOW_MS\n );\n }\n}\n"],"mappings":"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"}
@@ -44,6 +44,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
44
44
  defaultRole: string;
45
45
  roles: Record<string, {
46
46
  model: string;
47
+ fallbacks?: string[];
47
48
  description?: string;
48
49
  }>;
49
50
  policy?: {
@@ -165,6 +166,7 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
165
166
  defaultRole?: string;
166
167
  roles?: Record<string, {
167
168
  model: string;
169
+ fallbacks?: string[];
168
170
  description?: string;
169
171
  }>;
170
172
  policy?: {
@@ -365,12 +367,6 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
365
367
  dialogPolicy: unknown;
366
368
  dialogTimeoutSeconds: number;
367
369
  };
368
- cron: {
369
- enabled: boolean;
370
- maxConcurrentJobs: number;
371
- historyRetentionDays: number;
372
- enableMetrics: boolean;
373
- };
374
370
  goals: {
375
371
  maxTurns: number;
376
372
  checklistMode: boolean;
@@ -401,6 +397,9 @@ export declare function buildSafeWebConfigPayload(service: GatewayService, optio
401
397
  maxEntries: number;
402
398
  };
403
399
  };
400
+ tui: {
401
+ defaultAgent: string;
402
+ };
404
403
  tunnel: {
405
404
  enabled: boolean;
406
405
  autoStart: boolean;
@@ -7,7 +7,7 @@ import { getProviderRegistry, init_plugin_registry } from "../../../providers/pl
7
7
  import { getAllProviders, init_providers, isProviderConfigured } from "../../../providers/index.js";
8
8
  import { resolveShareConfig } from "../../../share/share-config.js";
9
9
  import { normalizeConfiguredMcpServers } from "../../../config/mcp-config-normalize.js";
10
- import { resolveCronConfigForWeb, resolveGoalsConfigForWeb, resolveSessionConfigForWeb, resolveUpdateConfigForWeb } from "../../../config/web-patch.js";
10
+ import { resolveGoalsConfigForWeb, resolveSessionConfigForWeb, resolveUpdateConfigForWeb } from "../../../config/web-patch.js";
11
11
  import { GENERIC_MASKED_SECRET, maskSecretLength } from "./mask-secret-length.js";
12
12
  import { safeToolsWebForGet } from "../../config-tools-web.js";
13
13
  import { maskTunnelSecretForWeb } from "../../../tunnel/env.js";
@@ -174,9 +174,9 @@ async function buildSafeWebConfigPayload(service, options = {}) {
174
174
  skillsStoreBaseUrl: config.gateway?.skillsStoreBaseUrl ?? "https://store.xopc.ai"
175
175
  },
176
176
  browser: buildSafeBrowserConfigForWeb(config.browser),
177
- cron: resolveCronConfigForWeb(config),
178
177
  goals: resolveGoalsConfigForWeb(config),
179
178
  session: resolveSessionConfigForWeb(config),
179
+ tui: { defaultAgent: config.tui?.defaultAgent ?? "coder" },
180
180
  tunnel: {
181
181
  enabled: config.tunnel?.enabled === true,
182
182
  autoStart: config.tunnel?.autoStart === true,
@@ -1 +1 @@
1
- {"version":3,"file":"config-payload.js","names":["getModelsJsonPath"],"sources":["../../../../../src/gateway/hono/lib/config-payload.ts"],"sourcesContent":["import {\n listAgentEntries,\n normalizeAgentId,\n resolveDefaultAgentId,\n} from '../../../agent/agent-scope.js';\nimport {\n buildChannelCatalogForConfig,\n buildChannelCatalogFromSnapshot,\n getChannelSetupStatus,\n} from '../../../channels/catalog/channel-catalog-service.js';\nimport { normalizeConfiguredMcpServers } from '../../../config/mcp-config-normalize.js';\nimport type { Config } from '../../../config/schema.js';\nimport {\n GENERIC_MASKED_SECRET,\n maskSecretLength,\n} from './mask-secret-length.js';\nimport { maskTunnelSecretForWeb } from '../../../tunnel/env.js';\nimport { resolveShareConfig } from '../../../share/share-config.js';\nimport {\n resolveCronConfigForWeb,\n resolveGoalsConfigForWeb,\n resolveSessionConfigForWeb,\n resolveUpdateConfigForWeb,\n} from '../../../config/web-patch.js';\nimport { CredentialResolver } from '../../../auth/credentials.js';\nimport { loadModelsJson, getModelsJsonPath } from '../../../config/models-json.js';\nimport { getAllProviders, isProviderConfigured } from '../../../providers/index.js';\nimport { getProviderRegistry } from '../../../providers/plugin-registry.js';\nimport type { GatewayService } from '../../service.js';\nimport { safeToolsWebForGet } from '../../config-tools-web.js';\nimport { buildSafeProvidersConfigForWeb } from './safe-providers-config.js';\nimport { maskSttConfigForWeb, maskTtsConfigForWeb } from './safe-voice-config.js';\n\nfunction readModelsJsonProviderApiKey(providerId: string): string | undefined {\n const { config } = loadModelsJson(getModelsJsonPath());\n const entry = config.providers?.[providerId];\n const key = entry?.apiKey;\n return typeof key === 'string' && key.trim() ? key.trim() : undefined;\n}\n\n/** Length-preserving mask for LLM provider keys in GET `/api/config`. */\nasync function maskLlmProviderApiKeyForWeb(provider: string): Promise<string> {\n const resolver = new CredentialResolver();\n const stored = await resolver.revealGatewayStoredApiKey(provider);\n if (stored) return maskSecretLength(stored);\n\n const fromModelsJson = readModelsJsonProviderApiKey(provider);\n if (fromModelsJson) return maskSecretLength(fromModelsJson);\n\n // Extension plugins manage their own auth; don't show a fake gateway key mask.\n if (getProviderRegistry().has(provider)) return '';\n\n if (await isProviderConfigured(provider)) return GENERIC_MASKED_SECRET;\n return '';\n}\n\n/** MCP block for GET/PATCH `/api/config` (authenticated console editing). */\nexport function buildSafeMcpConfigForWeb(config: Config) {\n const mcp = config.mcp;\n if (!mcp) {\n return { servers: {} as Record<string, Record<string, unknown>> };\n }\n return {\n ...(mcp.sessionIdleTtlMs !== undefined ? { sessionIdleTtlMs: mcp.sessionIdleTtlMs } : {}),\n servers: normalizeConfiguredMcpServers(mcp.servers),\n };\n}\n\nfunction maskBrowserCloudConfigForWeb(cloud: unknown): Record<string, unknown> | null {\n if (!cloud || typeof cloud !== 'object' || Array.isArray(cloud)) {\n return null;\n }\n const raw = cloud as Record<string, unknown>;\n const safe: Record<string, unknown> = {};\n if (typeof raw.apiKey === 'string' && raw.apiKey.trim()) {\n safe.apiKey = maskSecretLength(raw.apiKey);\n }\n if (typeof raw.projectId === 'string' && raw.projectId.trim()) {\n safe.projectId = raw.projectId.trim();\n }\n if (typeof raw.region === 'string' && raw.region.trim()) {\n safe.region = raw.region.trim();\n }\n return Object.keys(safe).length > 0 ? safe : null;\n}\n\nexport function buildSafeBrowserConfigForWeb(browser: unknown) {\n if (!browser || typeof browser !== 'object') {\n return {\n enabled: false,\n headless: false,\n allowPrivateUrls: false,\n commandTimeout: null,\n backend: null,\n cloudProvider: null,\n cloud: null,\n cdpUrl: null,\n extension: null,\n cloakbrowser: null,\n humanize: null,\n humanPreset: null,\n dialogPolicy: null,\n dialogTimeoutSeconds: null,\n };\n }\n\n return {\n enabled: (browser as Record<string, unknown>).enabled !== false,\n headless: (browser as Record<string, unknown>).headless === true,\n allowPrivateUrls: (browser as Record<string, unknown>).allowPrivateUrls === true,\n commandTimeout:\n typeof (browser as Record<string, unknown>).commandTimeout === 'number' &&\n Number.isFinite((browser as Record<string, unknown>).commandTimeout as number)\n ? Math.floor((browser as Record<string, unknown>).commandTimeout as number)\n : null,\n backend:\n (browser as Record<string, unknown>).backend === 'local' ||\n (browser as Record<string, unknown>).backend === 'cdp' ||\n (browser as Record<string, unknown>).backend === 'cloud' ||\n (browser as Record<string, unknown>).backend === 'extension' ||\n (browser as Record<string, unknown>).backend === 'cloakbrowser'\n ? (browser as Record<string, unknown>).backend\n : null,\n cloudProvider:\n (browser as Record<string, unknown>).cloudProvider === 'browserbase' ||\n (browser as Record<string, unknown>).cloudProvider === 'browser-use'\n ? (browser as Record<string, unknown>).cloudProvider\n : null,\n cloud: maskBrowserCloudConfigForWeb((browser as Record<string, unknown>).cloud),\n cdpUrl:\n typeof (browser as Record<string, unknown>).cdpUrl === 'string' &&\n ((browser as Record<string, unknown>).cdpUrl as string).trim()\n ? ((browser as Record<string, unknown>).cdpUrl as string).trim()\n : null,\n extension:\n (browser as Record<string, unknown>).extension &&\n typeof (browser as Record<string, unknown>).extension === 'object' &&\n !Array.isArray((browser as Record<string, unknown>).extension)\n ? (browser as Record<string, unknown>).extension\n : null,\n cloakbrowser:\n (browser as Record<string, unknown>).cloakbrowser &&\n typeof (browser as Record<string, unknown>).cloakbrowser === 'object' &&\n !Array.isArray((browser as Record<string, unknown>).cloakbrowser)\n ? (browser as Record<string, unknown>).cloakbrowser\n : null,\n humanize:\n typeof (browser as Record<string, unknown>).humanize === 'boolean'\n ? (browser as Record<string, unknown>).humanize\n : null,\n humanPreset:\n (browser as Record<string, unknown>).humanPreset === 'default' ||\n (browser as Record<string, unknown>).humanPreset === 'careful'\n ? (browser as Record<string, unknown>).humanPreset\n : null,\n dialogPolicy:\n (browser as Record<string, unknown>).dialogPolicy === 'must_respond' ||\n (browser as Record<string, unknown>).dialogPolicy === 'auto_accept' ||\n (browser as Record<string, unknown>).dialogPolicy === 'auto_dismiss'\n ? (browser as Record<string, unknown>).dialogPolicy\n : null,\n dialogTimeoutSeconds:\n typeof (browser as Record<string, unknown>).dialogTimeoutSeconds === 'number' &&\n Number.isFinite((browser as Record<string, unknown>).dialogTimeoutSeconds as number)\n ? Math.floor((browser as Record<string, unknown>).dialogTimeoutSeconds as number)\n : null,\n };\n}\n\n/** Sanitized config snapshot for GET/PATCH `/api/config` (matches persisted `service.currentConfig`). */\nexport async function buildSafeWebConfigPayload(service: GatewayService, options: { locale?: string } = {}) {\n const config = service.currentConfig;\n const extensionLoader =\n typeof service.getExtensionLoader === 'function' ? service.getExtensionLoader() : undefined;\n const snapshot = extensionLoader?.getManifestSnapshot();\n const catalog = snapshot\n ? buildChannelCatalogFromSnapshot(snapshot, { locale: options.locale })\n : buildChannelCatalogForConfig(config, { locale: options.locale });\n const channelsPayload = Object.fromEntries(\n catalog.entries.map((entry) => {\n const plugin =\n typeof service.getChannelRuntimePlugin === 'function'\n ? service.getChannelRuntimePlugin(entry.id)\n : undefined;\n const channelCfgKey = entry.configPath.startsWith('channels.')\n ? entry.configPath.slice('channels.'.length).split('.')[0] || entry.id\n : entry.id;\n const channelCfg = config.channels?.[channelCfgKey] as Record<string, unknown> | undefined;\n const setupStatus = getChannelSetupStatus(config, entry.id, entry);\n return [\n entry.id,\n {\n enabled: setupStatus.enabled,\n configured: setupStatus.ready,\n setupStatus,\n config: plugin?.configSurface?.buildConfigSurface(config) ?? channelCfg ?? {},\n schema: entry.configSchema,\n uiHints: entry.uiHints,\n },\n ];\n }),\n );\n return {\n agents: {\n defaultId: resolveDefaultAgentId(config),\n list: listAgentEntries(config)\n .filter((e) => e.enabled !== false)\n .map((e) => ({\n id: normalizeAgentId(e.id),\n identity: e.identity,\n workspace: e.workspace,\n models: e.models,\n tools: e.tools,\n skills: e.skills,\n memory: e.memory,\n workflows: e.workflows,\n boundaries: e.boundaries,\n })),\n capabilityPresets: config.agents?.capabilityPresets ?? {},\n },\n channels: channelsPayload,\n providers: Object.fromEntries(\n await Promise.all(\n getAllProviders().map(async (provider) => [\n provider,\n await maskLlmProviderApiKeyForWeb(provider),\n ]),\n ),\n ),\n /** Masked `cfg.providers` for capability keys (image / STT / etc.). */\n providersConfig: buildSafeProvidersConfigForWeb(config.providers),\n gateway: {\n bind: config.gateway?.bind ?? 'loopback',\n customBindHost: config.gateway?.customBindHost,\n port: config.gateway?.port,\n corsOrigins: Array.isArray(config.gateway?.corsOrigins) ? config.gateway.corsOrigins : [],\n trustedProxies: Array.isArray(config.gateway?.trustedProxies)\n ? config.gateway.trustedProxies\n : [],\n allowRealIpFallback: config.gateway?.allowRealIpFallback === true,\n dangerouslyAllowHostHeaderOriginFallback:\n config.gateway?.dangerouslyAllowHostHeaderOriginFallback === true,\n security: {\n strict: config.gateway?.security?.strict === true,\n },\n auth: {\n mode: config.gateway?.auth?.mode || 'token',\n token: config.gateway?.auth?.token ? maskSecretLength(config.gateway.auth.token) : '',\n password: config.gateway?.auth?.password\n ? maskSecretLength(config.gateway.auth.password)\n : '',\n trustedProxy: config.gateway?.auth?.trustedProxy\n ? {\n userHeader: config.gateway.auth.trustedProxy.userHeader,\n requiredHeaders: config.gateway.auth.trustedProxy.requiredHeaders ?? [],\n allowUsers: config.gateway.auth.trustedProxy.allowUsers ?? [],\n allowLoopback: config.gateway.auth.trustedProxy.allowLoopback === true,\n }\n : undefined,\n rateLimit: {\n enabled: config.gateway?.auth?.rateLimit?.enabled !== false,\n maxAttempts:\n typeof config.gateway?.auth?.rateLimit?.maxAttempts === 'number'\n ? config.gateway.auth.rateLimit.maxAttempts\n : 5,\n windowMs:\n typeof config.gateway?.auth?.rateLimit?.windowMs === 'number'\n ? config.gateway.auth.rateLimit.windowMs\n : 900_000,\n blockDurationMs:\n typeof config.gateway?.auth?.rateLimit?.blockDurationMs === 'number'\n ? config.gateway.auth.rateLimit.blockDurationMs\n : typeof config.gateway?.auth?.rateLimit?.lockoutMs === 'number'\n ? config.gateway.auth.rateLimit.lockoutMs\n : 300_000,\n exemptLoopback: config.gateway?.auth?.rateLimit?.exemptLoopback !== false,\n },\n },\n heartbeat: {\n enabled: config.gateway?.heartbeat?.enabled,\n intervalMs: config.gateway?.heartbeat?.intervalMs,\n includeSystemPromptSection: config.gateway?.heartbeat?.includeSystemPromptSection === true,\n target: config.gateway?.heartbeat?.target,\n targetChatId: config.gateway?.heartbeat?.targetChatId,\n prompt: config.gateway?.heartbeat?.prompt,\n ackMaxChars: config.gateway?.heartbeat?.ackMaxChars,\n isolatedSession: config.gateway?.heartbeat?.isolatedSession,\n activeHours: config.gateway?.heartbeat?.activeHours,\n },\n maxSseConnections:\n typeof config.gateway?.maxSseConnections === 'number'\n ? config.gateway.maxSseConnections\n : 100,\n channelConnectDeferMode: config.gateway?.channelConnectDeferMode ?? 'auto',\n channelConnectDeferIds: Array.isArray(config.gateway?.channelConnectDeferIds)\n ? config.gateway.channelConnectDeferIds\n : [],\n channelConnectDeferSkipIds: Array.isArray(config.gateway?.channelConnectDeferSkipIds)\n ? config.gateway.channelConnectDeferSkipIds\n : [],\n share: resolveShareConfig(config.gateway?.share),\n publicUrl: config.gateway?.publicUrl ?? null,\n skillsMarketplaceProvider: config.gateway?.skillsMarketplaceProvider ?? 'skillhub',\n skillsStoreBaseUrl: config.gateway?.skillsStoreBaseUrl ?? 'https://store.xopc.ai',\n },\n browser: buildSafeBrowserConfigForWeb(config.browser),\n cron: resolveCronConfigForWeb(config),\n goals: resolveGoalsConfigForWeb(config),\n session: resolveSessionConfigForWeb(config),\n tunnel: {\n enabled: config.tunnel?.enabled === true,\n autoStart: config.tunnel?.autoStart === true,\n brokerUrl: config.tunnel?.brokerUrl ?? 'https://frp.xopc.ai/api',\n registrationSecret: config.tunnel?.registrationSecret\n ? maskTunnelSecretForWeb(config.tunnel.registrationSecret)\n : '',\n consent: config.tunnel?.consent\n ? {\n version: config.tunnel.consent.version,\n acceptedAt: config.tunnel.consent.acceptedAt,\n }\n : undefined,\n transport: { tls: 'broker_terminated' as const },\n },\n update: {\n ...resolveUpdateConfigForWeb(config),\n },\n stt: maskSttConfigForWeb(config.tools?.media?.audio),\n tts: maskTtsConfigForWeb(config.messages?.tts),\n tools: safeToolsWebForGet(config),\n bindings: Array.isArray(config.bindings) ? config.bindings : [],\n mcp: buildSafeMcpConfigForWeb(config),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config-payload.js","names":["getModelsJsonPath"],"sources":["../../../../../src/gateway/hono/lib/config-payload.ts"],"sourcesContent":["import {\n listAgentEntries,\n normalizeAgentId,\n resolveDefaultAgentId,\n} from '../../../agent/agent-scope.js';\nimport {\n buildChannelCatalogForConfig,\n buildChannelCatalogFromSnapshot,\n getChannelSetupStatus,\n} from '../../../channels/catalog/channel-catalog-service.js';\nimport { normalizeConfiguredMcpServers } from '../../../config/mcp-config-normalize.js';\nimport type { Config } from '../../../config/schema.js';\nimport {\n GENERIC_MASKED_SECRET,\n maskSecretLength,\n} from './mask-secret-length.js';\nimport { maskTunnelSecretForWeb } from '../../../tunnel/env.js';\nimport { resolveShareConfig } from '../../../share/share-config.js';\nimport {\n resolveGoalsConfigForWeb,\n resolveSessionConfigForWeb,\n resolveUpdateConfigForWeb,\n} from '../../../config/web-patch.js';\nimport { CredentialResolver } from '../../../auth/credentials.js';\nimport { loadModelsJson, getModelsJsonPath } from '../../../config/models-json.js';\nimport { getAllProviders, isProviderConfigured } from '../../../providers/index.js';\nimport { getProviderRegistry } from '../../../providers/plugin-registry.js';\nimport type { GatewayService } from '../../service.js';\nimport { safeToolsWebForGet } from '../../config-tools-web.js';\nimport { buildSafeProvidersConfigForWeb } from './safe-providers-config.js';\nimport { maskSttConfigForWeb, maskTtsConfigForWeb } from './safe-voice-config.js';\n\nfunction readModelsJsonProviderApiKey(providerId: string): string | undefined {\n const { config } = loadModelsJson(getModelsJsonPath());\n const entry = config.providers?.[providerId];\n const key = entry?.apiKey;\n return typeof key === 'string' && key.trim() ? key.trim() : undefined;\n}\n\n/** Length-preserving mask for LLM provider keys in GET `/api/config`. */\nasync function maskLlmProviderApiKeyForWeb(provider: string): Promise<string> {\n const resolver = new CredentialResolver();\n const stored = await resolver.revealGatewayStoredApiKey(provider);\n if (stored) return maskSecretLength(stored);\n\n const fromModelsJson = readModelsJsonProviderApiKey(provider);\n if (fromModelsJson) return maskSecretLength(fromModelsJson);\n\n // Extension plugins manage their own auth; don't show a fake gateway key mask.\n if (getProviderRegistry().has(provider)) return '';\n\n if (await isProviderConfigured(provider)) return GENERIC_MASKED_SECRET;\n return '';\n}\n\n/** MCP block for GET/PATCH `/api/config` (authenticated console editing). */\nexport function buildSafeMcpConfigForWeb(config: Config) {\n const mcp = config.mcp;\n if (!mcp) {\n return { servers: {} as Record<string, Record<string, unknown>> };\n }\n return {\n ...(mcp.sessionIdleTtlMs !== undefined ? { sessionIdleTtlMs: mcp.sessionIdleTtlMs } : {}),\n servers: normalizeConfiguredMcpServers(mcp.servers),\n };\n}\n\nfunction maskBrowserCloudConfigForWeb(cloud: unknown): Record<string, unknown> | null {\n if (!cloud || typeof cloud !== 'object' || Array.isArray(cloud)) {\n return null;\n }\n const raw = cloud as Record<string, unknown>;\n const safe: Record<string, unknown> = {};\n if (typeof raw.apiKey === 'string' && raw.apiKey.trim()) {\n safe.apiKey = maskSecretLength(raw.apiKey);\n }\n if (typeof raw.projectId === 'string' && raw.projectId.trim()) {\n safe.projectId = raw.projectId.trim();\n }\n if (typeof raw.region === 'string' && raw.region.trim()) {\n safe.region = raw.region.trim();\n }\n return Object.keys(safe).length > 0 ? safe : null;\n}\n\nexport function buildSafeBrowserConfigForWeb(browser: unknown) {\n if (!browser || typeof browser !== 'object') {\n return {\n enabled: false,\n headless: false,\n allowPrivateUrls: false,\n commandTimeout: null,\n backend: null,\n cloudProvider: null,\n cloud: null,\n cdpUrl: null,\n extension: null,\n cloakbrowser: null,\n humanize: null,\n humanPreset: null,\n dialogPolicy: null,\n dialogTimeoutSeconds: null,\n };\n }\n\n return {\n enabled: (browser as Record<string, unknown>).enabled !== false,\n headless: (browser as Record<string, unknown>).headless === true,\n allowPrivateUrls: (browser as Record<string, unknown>).allowPrivateUrls === true,\n commandTimeout:\n typeof (browser as Record<string, unknown>).commandTimeout === 'number' &&\n Number.isFinite((browser as Record<string, unknown>).commandTimeout as number)\n ? Math.floor((browser as Record<string, unknown>).commandTimeout as number)\n : null,\n backend:\n (browser as Record<string, unknown>).backend === 'local' ||\n (browser as Record<string, unknown>).backend === 'cdp' ||\n (browser as Record<string, unknown>).backend === 'cloud' ||\n (browser as Record<string, unknown>).backend === 'extension' ||\n (browser as Record<string, unknown>).backend === 'cloakbrowser'\n ? (browser as Record<string, unknown>).backend\n : null,\n cloudProvider:\n (browser as Record<string, unknown>).cloudProvider === 'browserbase' ||\n (browser as Record<string, unknown>).cloudProvider === 'browser-use'\n ? (browser as Record<string, unknown>).cloudProvider\n : null,\n cloud: maskBrowserCloudConfigForWeb((browser as Record<string, unknown>).cloud),\n cdpUrl:\n typeof (browser as Record<string, unknown>).cdpUrl === 'string' &&\n ((browser as Record<string, unknown>).cdpUrl as string).trim()\n ? ((browser as Record<string, unknown>).cdpUrl as string).trim()\n : null,\n extension:\n (browser as Record<string, unknown>).extension &&\n typeof (browser as Record<string, unknown>).extension === 'object' &&\n !Array.isArray((browser as Record<string, unknown>).extension)\n ? (browser as Record<string, unknown>).extension\n : null,\n cloakbrowser:\n (browser as Record<string, unknown>).cloakbrowser &&\n typeof (browser as Record<string, unknown>).cloakbrowser === 'object' &&\n !Array.isArray((browser as Record<string, unknown>).cloakbrowser)\n ? (browser as Record<string, unknown>).cloakbrowser\n : null,\n humanize:\n typeof (browser as Record<string, unknown>).humanize === 'boolean'\n ? (browser as Record<string, unknown>).humanize\n : null,\n humanPreset:\n (browser as Record<string, unknown>).humanPreset === 'default' ||\n (browser as Record<string, unknown>).humanPreset === 'careful'\n ? (browser as Record<string, unknown>).humanPreset\n : null,\n dialogPolicy:\n (browser as Record<string, unknown>).dialogPolicy === 'must_respond' ||\n (browser as Record<string, unknown>).dialogPolicy === 'auto_accept' ||\n (browser as Record<string, unknown>).dialogPolicy === 'auto_dismiss'\n ? (browser as Record<string, unknown>).dialogPolicy\n : null,\n dialogTimeoutSeconds:\n typeof (browser as Record<string, unknown>).dialogTimeoutSeconds === 'number' &&\n Number.isFinite((browser as Record<string, unknown>).dialogTimeoutSeconds as number)\n ? Math.floor((browser as Record<string, unknown>).dialogTimeoutSeconds as number)\n : null,\n };\n}\n\n/** Sanitized config snapshot for GET/PATCH `/api/config` (matches persisted `service.currentConfig`). */\nexport async function buildSafeWebConfigPayload(service: GatewayService, options: { locale?: string } = {}) {\n const config = service.currentConfig;\n const extensionLoader =\n typeof service.getExtensionLoader === 'function' ? service.getExtensionLoader() : undefined;\n const snapshot = extensionLoader?.getManifestSnapshot();\n const catalog = snapshot\n ? buildChannelCatalogFromSnapshot(snapshot, { locale: options.locale })\n : buildChannelCatalogForConfig(config, { locale: options.locale });\n const channelsPayload = Object.fromEntries(\n catalog.entries.map((entry) => {\n const plugin =\n typeof service.getChannelRuntimePlugin === 'function'\n ? service.getChannelRuntimePlugin(entry.id)\n : undefined;\n const channelCfgKey = entry.configPath.startsWith('channels.')\n ? entry.configPath.slice('channels.'.length).split('.')[0] || entry.id\n : entry.id;\n const channelCfg = config.channels?.[channelCfgKey] as Record<string, unknown> | undefined;\n const setupStatus = getChannelSetupStatus(config, entry.id, entry);\n return [\n entry.id,\n {\n enabled: setupStatus.enabled,\n configured: setupStatus.ready,\n setupStatus,\n config: plugin?.configSurface?.buildConfigSurface(config) ?? channelCfg ?? {},\n schema: entry.configSchema,\n uiHints: entry.uiHints,\n },\n ];\n }),\n );\n return {\n agents: {\n defaultId: resolveDefaultAgentId(config),\n list: listAgentEntries(config)\n .filter((e) => e.enabled !== false)\n .map((e) => ({\n id: normalizeAgentId(e.id),\n identity: e.identity,\n workspace: e.workspace,\n models: e.models,\n tools: e.tools,\n skills: e.skills,\n memory: e.memory,\n workflows: e.workflows,\n boundaries: e.boundaries,\n })),\n capabilityPresets: config.agents?.capabilityPresets ?? {},\n },\n channels: channelsPayload,\n providers: Object.fromEntries(\n await Promise.all(\n getAllProviders().map(async (provider) => [\n provider,\n await maskLlmProviderApiKeyForWeb(provider),\n ]),\n ),\n ),\n /** Masked `cfg.providers` for capability keys (image / STT / etc.). */\n providersConfig: buildSafeProvidersConfigForWeb(config.providers),\n gateway: {\n bind: config.gateway?.bind ?? 'loopback',\n customBindHost: config.gateway?.customBindHost,\n port: config.gateway?.port,\n corsOrigins: Array.isArray(config.gateway?.corsOrigins) ? config.gateway.corsOrigins : [],\n trustedProxies: Array.isArray(config.gateway?.trustedProxies)\n ? config.gateway.trustedProxies\n : [],\n allowRealIpFallback: config.gateway?.allowRealIpFallback === true,\n dangerouslyAllowHostHeaderOriginFallback:\n config.gateway?.dangerouslyAllowHostHeaderOriginFallback === true,\n security: {\n strict: config.gateway?.security?.strict === true,\n },\n auth: {\n mode: config.gateway?.auth?.mode || 'token',\n token: config.gateway?.auth?.token ? maskSecretLength(config.gateway.auth.token) : '',\n password: config.gateway?.auth?.password\n ? maskSecretLength(config.gateway.auth.password)\n : '',\n trustedProxy: config.gateway?.auth?.trustedProxy\n ? {\n userHeader: config.gateway.auth.trustedProxy.userHeader,\n requiredHeaders: config.gateway.auth.trustedProxy.requiredHeaders ?? [],\n allowUsers: config.gateway.auth.trustedProxy.allowUsers ?? [],\n allowLoopback: config.gateway.auth.trustedProxy.allowLoopback === true,\n }\n : undefined,\n rateLimit: {\n enabled: config.gateway?.auth?.rateLimit?.enabled !== false,\n maxAttempts:\n typeof config.gateway?.auth?.rateLimit?.maxAttempts === 'number'\n ? config.gateway.auth.rateLimit.maxAttempts\n : 5,\n windowMs:\n typeof config.gateway?.auth?.rateLimit?.windowMs === 'number'\n ? config.gateway.auth.rateLimit.windowMs\n : 900_000,\n blockDurationMs:\n typeof config.gateway?.auth?.rateLimit?.blockDurationMs === 'number'\n ? config.gateway.auth.rateLimit.blockDurationMs\n : typeof config.gateway?.auth?.rateLimit?.lockoutMs === 'number'\n ? config.gateway.auth.rateLimit.lockoutMs\n : 300_000,\n exemptLoopback: config.gateway?.auth?.rateLimit?.exemptLoopback !== false,\n },\n },\n heartbeat: {\n enabled: config.gateway?.heartbeat?.enabled,\n intervalMs: config.gateway?.heartbeat?.intervalMs,\n includeSystemPromptSection: config.gateway?.heartbeat?.includeSystemPromptSection === true,\n target: config.gateway?.heartbeat?.target,\n targetChatId: config.gateway?.heartbeat?.targetChatId,\n prompt: config.gateway?.heartbeat?.prompt,\n ackMaxChars: config.gateway?.heartbeat?.ackMaxChars,\n isolatedSession: config.gateway?.heartbeat?.isolatedSession,\n activeHours: config.gateway?.heartbeat?.activeHours,\n },\n maxSseConnections:\n typeof config.gateway?.maxSseConnections === 'number'\n ? config.gateway.maxSseConnections\n : 100,\n channelConnectDeferMode: config.gateway?.channelConnectDeferMode ?? 'auto',\n channelConnectDeferIds: Array.isArray(config.gateway?.channelConnectDeferIds)\n ? config.gateway.channelConnectDeferIds\n : [],\n channelConnectDeferSkipIds: Array.isArray(config.gateway?.channelConnectDeferSkipIds)\n ? config.gateway.channelConnectDeferSkipIds\n : [],\n share: resolveShareConfig(config.gateway?.share),\n publicUrl: config.gateway?.publicUrl ?? null,\n skillsMarketplaceProvider: config.gateway?.skillsMarketplaceProvider ?? 'skillhub',\n skillsStoreBaseUrl: config.gateway?.skillsStoreBaseUrl ?? 'https://store.xopc.ai',\n },\n browser: buildSafeBrowserConfigForWeb(config.browser),\n goals: resolveGoalsConfigForWeb(config),\n session: resolveSessionConfigForWeb(config),\n tui: {\n defaultAgent: config.tui?.defaultAgent ?? 'coder',\n },\n tunnel: {\n enabled: config.tunnel?.enabled === true,\n autoStart: config.tunnel?.autoStart === true,\n brokerUrl: config.tunnel?.brokerUrl ?? 'https://frp.xopc.ai/api',\n registrationSecret: config.tunnel?.registrationSecret\n ? maskTunnelSecretForWeb(config.tunnel.registrationSecret)\n : '',\n consent: config.tunnel?.consent\n ? {\n version: config.tunnel.consent.version,\n acceptedAt: config.tunnel.consent.acceptedAt,\n }\n : undefined,\n transport: { tls: 'broker_terminated' as const },\n },\n update: {\n ...resolveUpdateConfigForWeb(config),\n },\n stt: maskSttConfigForWeb(config.tools?.media?.audio),\n tts: maskTtsConfigForWeb(config.messages?.tts),\n tools: safeToolsWebForGet(config),\n bindings: Array.isArray(config.bindings) ? config.bindings : [],\n mcp: buildSafeMcpConfigForWeb(config),\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"agents.js","names":[],"sources":["../../../../../src/gateway/hono/routes/agents.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { AgentModelsSchema, type Config, parseModelRef } from '../../../config/schema.js';\nimport { MemoryPolicySchema, ToolPolicySetSchema } from '../../../agent-manifest/schema.js';\nimport { getVoiceModelsConfig } from '../../../config/voice.js';\nimport {\n isProviderConfigured,\n resolveModel,\n} from '../../../providers/index.js';\nimport { normalizeAgentId } from '../../../agent/agent-scope.js';\nimport {\n deleteAgentAvatarFile,\n finalizeCreateAgentDirs,\n getGatewayAgentEffectiveManifest,\n listAgentProfileFiles,\n listGatewayAgents,\n prepareCreateAgent,\n prepareDeleteAgent,\n prepareUpdateAgent,\n readAgentAvatarFile,\n readAgentProfileFile,\n readUserProfileFile,\n runAfterDeletePurge,\n writeAgentAvatarFromBase64,\n writeAgentProfileFile,\n writeUserProfileFile,\n type CreateAgentBody,\n} from '../../agents-admin.js';\nimport {\n resolveImageGenerationCapabilities,\n resolveImageUnderstandingCapabilities,\n} from '../../image-capabilities.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction parseProfileFiles(raw: unknown): Record<string, string> | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'profileFiles must be an object' };\n }\n const profileFiles: Record<string, string> = {};\n for (const [name, content] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof content !== 'string') {\n return { error: `profileFiles[\"${name}\"] must be a string` };\n }\n profileFiles[name] = content;\n }\n return profileFiles;\n}\n\nfunction isParseError(value: unknown): value is { error: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'error' in value &&\n typeof (value as { error: string }).error === 'string'\n );\n}\n\nfunction parseCreateAgentBody(raw: unknown): CreateAgentBody | { error: string } {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'each agent must be an object' };\n }\n const body = raw as Record<string, unknown>;\n if (Object.hasOwn(body, 'model')) {\n return { error: 'model is not supported; use models.defaultRole and models.roles' };\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return { error: 'toolsDisable was removed; use tools.builtin policies' };\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return { error: 'typedModels is not supported; use models.roles' };\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return { error: 'agentDir was removed from agent manifests' };\n }\n if (Object.hasOwn(body, 'name')) {\n return { error: 'name is not supported; write IDENTITY.md in profileFiles' };\n }\n if (Object.hasOwn(body, 'description')) {\n return { error: 'description is not supported; write IDENTITY.md in profileFiles' };\n }\n const workspace = typeof body.workspace === 'string' ? body.workspace : '';\n const models = Object.hasOwn(body, 'models')\n ? AgentModelsSchema.safeParse(body.models)\n : undefined;\n if (models && !models.success) {\n return { error: `models ${models.error.issues[0]?.message ?? 'is invalid'}` };\n }\n const id = typeof body.id === 'string' ? body.id : undefined;\n const skills = Object.hasOwn(body, 'skills')\n ? Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : null\n : undefined;\n if (skills === null) {\n return { error: 'skills must be an array' };\n }\n const toolsRaw = Object.hasOwn(body, 'tools') ? body.tools : undefined;\n let tools: CreateAgentBody['tools'] | undefined;\n if (toolsRaw !== undefined) {\n if (toolsRaw === null || typeof toolsRaw !== 'object' || Array.isArray(toolsRaw)) {\n return { error: 'tools must be an object' };\n }\n const parsedTools = ToolPolicySetSchema.safeParse(toolsRaw);\n if (!parsedTools.success) {\n return { error: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` };\n }\n tools = parsedTools.data;\n }\n let profileFiles: Record<string, string> | undefined;\n if (Object.hasOwn(body, 'profileFiles')) {\n const parsed = parseProfileFiles(body.profileFiles);\n if (isParseError(parsed)) {\n return parsed;\n }\n profileFiles = parsed;\n }\n if (!profileFiles?.['IDENTITY.md'] && typeof body.cloneFrom !== 'string') {\n return { error: 'profileFiles.IDENTITY.md is required' };\n }\n const cloneFrom = typeof body.cloneFrom === 'string' ? body.cloneFrom : undefined;\n return {\n workspace,\n ...(models && models.data !== undefined ? { models: models.data } : {}),\n ...(id !== undefined ? { id } : {}),\n ...(skills !== undefined ? { skills } : {}),\n ...(tools !== undefined ? { tools } : {}),\n ...(profileFiles !== undefined ? { profileFiles } : {}),\n ...(cloneFrom !== undefined ? { cloneFrom } : {}),\n };\n}\n\ntype PatchModels = {\n defaultRole?: string | null;\n roles?: Record<string, { model: string; description?: string }>;\n};\n\nfunction parsePatchModels(raw: unknown): PatchModels | null | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null) {\n return null;\n }\n if (typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'models must be an object or null' };\n }\n const body = raw as Record<string, unknown>;\n const out: PatchModels = {};\n if (Object.hasOwn(body, 'defaultRole')) {\n out.defaultRole = body.defaultRole === null ? null : String(body.defaultRole ?? '').trim();\n }\n if (Object.hasOwn(body, 'roles')) {\n if (body.roles === null) {\n return { error: 'models.roles must be an object' };\n } else {\n const parsed = AgentModelsSchema.safeParse({ roles: body.roles });\n if (!parsed.success) {\n return { error: `models.roles ${parsed.error.issues[0]?.message ?? 'is invalid'}` };\n }\n out.roles = parsed.data?.roles;\n }\n }\n return out;\n}\n\nexport function registerAgentsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/agents', async (c) => {\n const cfg = service.currentConfig as Config;\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const payload = await listGatewayAgents(cfg, { locale });\n return c.json({ ok: true, payload });\n });\n\n authenticated.get('/api/user-profile', async (c) => {\n const res = await readUserProfileFile();\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.put('/api/user-profile', strictRateLimitMiddleware, async (c) => {\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeUserProfileFile(content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.post('/api/agents', strictRateLimitMiddleware, async (c) => {\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const parsed = parseCreateAgentBody(body);\n if ('error' in parsed) {\n return c.json({ ok: false, error: { message: parsed.error } }, 400);\n }\n const prep = prepareCreateAgent(service.currentConfig as Config, parsed);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const finalized = await finalizeCreateAgentDirs(service.currentConfig as Config, agentId, {\n ...(parsed.profileFiles !== undefined ? { profileFiles: parsed.profileFiles } : {}),\n ...(parsed.cloneFrom ? { cloneFrom: parsed.cloneFrom } : {}),\n });\n if (finalized.ok === false) {\n return c.json({ ok: false, error: { message: finalized.error } }, finalized.status ?? 400);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: {\n agentId,\n agents: agentsPayload,\n },\n });\n });\n\n authenticated.get('/api/agents/:id/effective-manifest', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = getGatewayAgentEffectiveManifest(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.patch('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n if (Object.hasOwn(body, 'model')) {\n return c.json({ ok: false, error: { message: 'model is not supported; use models.defaultRole and models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return c.json({ ok: false, error: { message: 'typedModels is not supported; use models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return c.json({ ok: false, error: { message: 'toolsDisable was removed; use tools.builtin policies' } }, 400);\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return c.json({ ok: false, error: { message: 'agentDir was removed from agent manifests' } }, 400);\n }\n if (Object.hasOwn(body, 'name')) {\n return c.json({ ok: false, error: { message: 'name is not supported; edit IDENTITY.md' } }, 400);\n }\n if (Object.hasOwn(body, 'description')) {\n return c.json({ ok: false, error: { message: 'description is not supported; edit IDENTITY.md' } }, 400);\n }\n const skillsPatch =\n body.skills === null\n ? null\n : Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined;\n const extendsPatch = Object.hasOwn(body, 'extends')\n ? Array.isArray(body.extends)\n ? body.extends.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined\n : undefined;\n if (Object.hasOwn(body, 'extends') && extendsPatch === undefined) {\n return c.json({ ok: false, error: { message: 'extends must be an array' } }, 400);\n }\n let toolsPatch: CreateAgentBody['tools'] | null | undefined;\n if (Object.hasOwn(body, 'tools')) {\n if (body.tools === null) {\n toolsPatch = null;\n } else if (typeof body.tools === 'object' && !Array.isArray(body.tools)) {\n const parsedTools = ToolPolicySetSchema.safeParse(body.tools);\n if (!parsedTools.success) {\n return c.json({ ok: false, error: { message: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n toolsPatch = parsedTools.data;\n } else {\n return c.json({ ok: false, error: { message: 'tools must be an object or null' } }, 400);\n }\n }\n const modelsPatch = Object.hasOwn(body, 'models') ? parsePatchModels(body.models) : undefined;\n if (isParseError(modelsPatch)) {\n return c.json({ ok: false, error: { message: modelsPatch.error } }, 400);\n }\n let memoryPatch: Config['agents']['list'][number]['memory'] | undefined;\n if (Object.hasOwn(body, 'memory')) {\n const parsedMemory = MemoryPolicySchema.safeParse(body.memory);\n if (!parsedMemory.success) {\n return c.json({ ok: false, error: { message: `memory ${parsedMemory.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n memoryPatch = parsedMemory.data;\n }\n\n const prep = prepareUpdateAgent(service.currentConfig as Config, id, {\n workspace: typeof body.workspace === 'string' ? body.workspace : undefined,\n ...(extendsPatch !== undefined ? { extends: extendsPatch } : {}),\n ...(modelsPatch !== undefined ? { models: modelsPatch } : {}),\n setDefault: body.setDefault === true,\n ...(skillsPatch !== undefined ? { skills: skillsPatch } : {}),\n ...(toolsPatch !== undefined ? { tools: toolsPatch } : {}),\n ...(memoryPatch !== undefined ? { memory: memoryPatch } : {}),\n });\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const save = await service.saveConfig(prep.data.nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({ ok: true, payload: agentsPayload });\n });\n\n authenticated.delete('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const purge = c.req.query('purge') === '1' || c.req.query('purge') === 'true';\n const prep = prepareDeleteAgent(service.currentConfig as Config, id);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n if (purge) {\n await runAfterDeletePurge(service.currentConfig as Config, agentId);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: { agentId, purged: purge, agents: agentsPayload },\n });\n });\n\n authenticated.get('/api/agents/:id/avatar', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await readAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return new Response(res.data.buffer, {\n status: 200,\n headers: {\n 'Content-Type': res.data.contentType,\n 'Cache-Control': 'private, max-age=3600',\n },\n });\n });\n\n authenticated.put('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const base64 = typeof body.base64 === 'string' ? body.base64 : '';\n const mimeType = typeof body.mimeType === 'string' ? body.mimeType : '';\n const res = await writeAgentAvatarFromBase64(service.currentConfig as Config, id, base64, mimeType);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.delete('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await deleteAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.get('/api/agents/:id/files', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await listAgentProfileFiles(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.get('/api/agents/:id/files/:name', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n const res = await readAgentProfileFile(service.currentConfig as Config, id, name);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name, content: res.data.content } });\n });\n\n authenticated.put('/api/agents/:id/files/:name', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeAgentProfileFile(service.currentConfig as Config, id, name, content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name } });\n });\n\n // GET /api/voice/models - Get available STT/TTS models\n authenticated.get('/api/voice/models', (c) => {\n const models = getVoiceModelsConfig();\n return c.json({ ok: true, payload: { models } });\n });\n\n authenticated.get('/api/image/capabilities', async (c) => {\n const config = service.currentConfig as Config;\n const imageGenerationProviders = await resolveImageGenerationCapabilities(config);\n const imageUnderstandingProviders = await resolveImageUnderstandingCapabilities(config);\n return c.json({\n ok: true,\n payload: {\n current: {\n imageModel: null,\n imageModelFallbacks: [],\n imageGenerationModel: null,\n imageGenerationModelFallbacks: [],\n mediaMaxMb: null,\n },\n imageGeneration: { providers: imageGenerationProviders },\n imageUnderstanding: { providers: imageUnderstandingProviders },\n },\n });\n });\n\n authenticated.post('/api/image/validate-model', strictRateLimitMiddleware, async (c) => {\n let body: { modelRef?: unknown };\n try {\n body = (await c.req.json()) as { modelRef?: unknown };\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const modelRef = body.modelRef;\n if (!modelRef || typeof modelRef !== 'string') {\n return c.json({ ok: false, error: 'modelRef is required' }, 400);\n }\n\n const parsed = parseModelRef(modelRef);\n if (!parsed) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'invalid_format',\n message: 'Model reference must be in \"provider/model\" format',\n },\n });\n }\n\n const configured = await isProviderConfigured(parsed.provider);\n if (!configured) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'provider_not_configured',\n message: `Provider \"${parsed.provider}\" is not configured. Set the API key first.`,\n provider: parsed.provider,\n },\n });\n }\n\n try {\n resolveModel(modelRef);\n } catch {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'model_not_found',\n message: `Model not found in registry: ${modelRef}`,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n }\n\n return c.json({\n ok: true,\n payload: {\n valid: true,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n });\n\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agents.js","names":[],"sources":["../../../../../src/gateway/hono/routes/agents.ts"],"sourcesContent":["import type { Hono } from 'hono';\n\nimport { AgentModelsSchema, type Config, parseModelRef } from '../../../config/schema.js';\nimport { MemoryPolicySchema, ToolPolicySetSchema } from '../../../agent-manifest/schema.js';\nimport { getVoiceModelsConfig } from '../../../config/voice.js';\nimport {\n isProviderConfigured,\n resolveModel,\n} from '../../../providers/index.js';\nimport { normalizeAgentId } from '../../../agent/agent-scope.js';\nimport {\n deleteAgentAvatarFile,\n finalizeCreateAgentDirs,\n getGatewayAgentEffectiveManifest,\n listAgentProfileFiles,\n listGatewayAgents,\n prepareCreateAgent,\n prepareDeleteAgent,\n prepareUpdateAgent,\n readAgentAvatarFile,\n readAgentProfileFile,\n readUserProfileFile,\n runAfterDeletePurge,\n writeAgentAvatarFromBase64,\n writeAgentProfileFile,\n writeUserProfileFile,\n type CreateAgentBody,\n} from '../../agents-admin.js';\nimport {\n resolveImageGenerationCapabilities,\n resolveImageUnderstandingCapabilities,\n} from '../../image-capabilities.js';\nimport type { AuthenticatedRouteDeps } from './deps.js';\n\nfunction parseProfileFiles(raw: unknown): Record<string, string> | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'profileFiles must be an object' };\n }\n const profileFiles: Record<string, string> = {};\n for (const [name, content] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof content !== 'string') {\n return { error: `profileFiles[\"${name}\"] must be a string` };\n }\n profileFiles[name] = content;\n }\n return profileFiles;\n}\n\nfunction isParseError(value: unknown): value is { error: string } {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'error' in value &&\n typeof (value as { error: string }).error === 'string'\n );\n}\n\nfunction parseCreateAgentBody(raw: unknown): CreateAgentBody | { error: string } {\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'each agent must be an object' };\n }\n const body = raw as Record<string, unknown>;\n if (Object.hasOwn(body, 'model')) {\n return { error: 'model is not supported; use models.defaultRole and models.roles' };\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return { error: 'toolsDisable was removed; use tools.builtin policies' };\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return { error: 'typedModels is not supported; use models.roles' };\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return { error: 'agentDir was removed from agent manifests' };\n }\n if (Object.hasOwn(body, 'name')) {\n return { error: 'name is not supported; write IDENTITY.md in profileFiles' };\n }\n if (Object.hasOwn(body, 'description')) {\n return { error: 'description is not supported; write IDENTITY.md in profileFiles' };\n }\n const workspace = typeof body.workspace === 'string' ? body.workspace : '';\n const models = Object.hasOwn(body, 'models')\n ? AgentModelsSchema.safeParse(body.models)\n : undefined;\n if (models && !models.success) {\n return { error: `models ${models.error.issues[0]?.message ?? 'is invalid'}` };\n }\n const id = typeof body.id === 'string' ? body.id : undefined;\n const skills = Object.hasOwn(body, 'skills')\n ? Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : null\n : undefined;\n if (skills === null) {\n return { error: 'skills must be an array' };\n }\n const toolsRaw = Object.hasOwn(body, 'tools') ? body.tools : undefined;\n let tools: CreateAgentBody['tools'] | undefined;\n if (toolsRaw !== undefined) {\n if (toolsRaw === null || typeof toolsRaw !== 'object' || Array.isArray(toolsRaw)) {\n return { error: 'tools must be an object' };\n }\n const parsedTools = ToolPolicySetSchema.safeParse(toolsRaw);\n if (!parsedTools.success) {\n return { error: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` };\n }\n tools = parsedTools.data;\n }\n let profileFiles: Record<string, string> | undefined;\n if (Object.hasOwn(body, 'profileFiles')) {\n const parsed = parseProfileFiles(body.profileFiles);\n if (isParseError(parsed)) {\n return parsed;\n }\n profileFiles = parsed;\n }\n if (!profileFiles?.['IDENTITY.md'] && typeof body.cloneFrom !== 'string') {\n return { error: 'profileFiles.IDENTITY.md is required' };\n }\n const cloneFrom = typeof body.cloneFrom === 'string' ? body.cloneFrom : undefined;\n return {\n workspace,\n ...(models && models.data !== undefined ? { models: models.data } : {}),\n ...(id !== undefined ? { id } : {}),\n ...(skills !== undefined ? { skills } : {}),\n ...(tools !== undefined ? { tools } : {}),\n ...(profileFiles !== undefined ? { profileFiles } : {}),\n ...(cloneFrom !== undefined ? { cloneFrom } : {}),\n };\n}\n\ntype PatchModels = {\n defaultRole?: string | null;\n roles?: Record<string, { model: string; fallbacks?: string[]; description?: string }>;\n};\n\nfunction parsePatchModels(raw: unknown): PatchModels | null | undefined | { error: string } {\n if (raw === undefined) {\n return undefined;\n }\n if (raw === null) {\n return null;\n }\n if (typeof raw !== 'object' || Array.isArray(raw)) {\n return { error: 'models must be an object or null' };\n }\n const body = raw as Record<string, unknown>;\n const out: PatchModels = {};\n if (Object.hasOwn(body, 'defaultRole')) {\n out.defaultRole = body.defaultRole === null ? null : String(body.defaultRole ?? '').trim();\n }\n if (Object.hasOwn(body, 'roles')) {\n if (body.roles === null) {\n return { error: 'models.roles must be an object' };\n } else {\n const parsed = AgentModelsSchema.safeParse({ roles: body.roles });\n if (!parsed.success) {\n return { error: `models.roles ${parsed.error.issues[0]?.message ?? 'is invalid'}` };\n }\n out.roles = parsed.data?.roles;\n }\n }\n return out;\n}\n\nexport function registerAgentsRoutes(authenticated: Hono, deps: AuthenticatedRouteDeps): void {\n const { service, strictRateLimitMiddleware } = deps;\n\n authenticated.get('/api/agents', async (c) => {\n const cfg = service.currentConfig as Config;\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const payload = await listGatewayAgents(cfg, { locale });\n return c.json({ ok: true, payload });\n });\n\n authenticated.get('/api/user-profile', async (c) => {\n const res = await readUserProfileFile();\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.put('/api/user-profile', strictRateLimitMiddleware, async (c) => {\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeUserProfileFile(content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.post('/api/agents', strictRateLimitMiddleware, async (c) => {\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const parsed = parseCreateAgentBody(body);\n if ('error' in parsed) {\n return c.json({ ok: false, error: { message: parsed.error } }, 400);\n }\n const prep = prepareCreateAgent(service.currentConfig as Config, parsed);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const finalized = await finalizeCreateAgentDirs(service.currentConfig as Config, agentId, {\n ...(parsed.profileFiles !== undefined ? { profileFiles: parsed.profileFiles } : {}),\n ...(parsed.cloneFrom ? { cloneFrom: parsed.cloneFrom } : {}),\n });\n if (finalized.ok === false) {\n return c.json({ ok: false, error: { message: finalized.error } }, finalized.status ?? 400);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: {\n agentId,\n agents: agentsPayload,\n },\n });\n });\n\n authenticated.get('/api/agents/:id/effective-manifest', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = getGatewayAgentEffectiveManifest(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.patch('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n if (Object.hasOwn(body, 'model')) {\n return c.json({ ok: false, error: { message: 'model is not supported; use models.defaultRole and models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'typedModels')) {\n return c.json({ ok: false, error: { message: 'typedModels is not supported; use models.roles' } }, 400);\n }\n if (Object.hasOwn(body, 'toolsDisable')) {\n return c.json({ ok: false, error: { message: 'toolsDisable was removed; use tools.builtin policies' } }, 400);\n }\n if (Object.hasOwn(body, 'agentDir')) {\n return c.json({ ok: false, error: { message: 'agentDir was removed from agent manifests' } }, 400);\n }\n if (Object.hasOwn(body, 'name')) {\n return c.json({ ok: false, error: { message: 'name is not supported; edit IDENTITY.md' } }, 400);\n }\n if (Object.hasOwn(body, 'description')) {\n return c.json({ ok: false, error: { message: 'description is not supported; edit IDENTITY.md' } }, 400);\n }\n const skillsPatch =\n body.skills === null\n ? null\n : Array.isArray(body.skills)\n ? body.skills.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined;\n const extendsPatch = Object.hasOwn(body, 'extends')\n ? Array.isArray(body.extends)\n ? body.extends.map((x: unknown) => String(x).trim()).filter(Boolean)\n : undefined\n : undefined;\n if (Object.hasOwn(body, 'extends') && extendsPatch === undefined) {\n return c.json({ ok: false, error: { message: 'extends must be an array' } }, 400);\n }\n let toolsPatch: CreateAgentBody['tools'] | null | undefined;\n if (Object.hasOwn(body, 'tools')) {\n if (body.tools === null) {\n toolsPatch = null;\n } else if (typeof body.tools === 'object' && !Array.isArray(body.tools)) {\n const parsedTools = ToolPolicySetSchema.safeParse(body.tools);\n if (!parsedTools.success) {\n return c.json({ ok: false, error: { message: `tools ${parsedTools.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n toolsPatch = parsedTools.data;\n } else {\n return c.json({ ok: false, error: { message: 'tools must be an object or null' } }, 400);\n }\n }\n const modelsPatch = Object.hasOwn(body, 'models') ? parsePatchModels(body.models) : undefined;\n if (isParseError(modelsPatch)) {\n return c.json({ ok: false, error: { message: modelsPatch.error } }, 400);\n }\n let memoryPatch: Config['agents']['list'][number]['memory'] | undefined;\n if (Object.hasOwn(body, 'memory')) {\n const parsedMemory = MemoryPolicySchema.safeParse(body.memory);\n if (!parsedMemory.success) {\n return c.json({ ok: false, error: { message: `memory ${parsedMemory.error.issues[0]?.message ?? 'is invalid'}` } }, 400);\n }\n memoryPatch = parsedMemory.data;\n }\n\n const prep = prepareUpdateAgent(service.currentConfig as Config, id, {\n workspace: typeof body.workspace === 'string' ? body.workspace : undefined,\n ...(extendsPatch !== undefined ? { extends: extendsPatch } : {}),\n ...(modelsPatch !== undefined ? { models: modelsPatch } : {}),\n setDefault: body.setDefault === true,\n ...(skillsPatch !== undefined ? { skills: skillsPatch } : {}),\n ...(toolsPatch !== undefined ? { tools: toolsPatch } : {}),\n ...(memoryPatch !== undefined ? { memory: memoryPatch } : {}),\n });\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const save = await service.saveConfig(prep.data.nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({ ok: true, payload: agentsPayload });\n });\n\n authenticated.delete('/api/agents/:id', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const purge = c.req.query('purge') === '1' || c.req.query('purge') === 'true';\n const prep = prepareDeleteAgent(service.currentConfig as Config, id);\n if (prep.ok === false) {\n return c.json({ ok: false, error: { message: prep.error } }, prep.status ?? 400);\n }\n const { nextConfig, agentId } = prep.data;\n const save = await service.saveConfig(nextConfig);\n if (!save.saved) {\n return c.json({ ok: false, error: { message: save.error ?? 'save failed' } }, 500);\n }\n if (purge) {\n await runAfterDeletePurge(service.currentConfig as Config, agentId);\n }\n const locale = c.req.query('locale') || c.req.header('Accept-Language')?.split(',')[0]?.trim();\n const agentsPayload = await listGatewayAgents(service.currentConfig as Config, { locale });\n return c.json({\n ok: true,\n payload: { agentId, purged: purge, agents: agentsPayload },\n });\n });\n\n authenticated.get('/api/agents/:id/avatar', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await readAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return new Response(res.data.buffer, {\n status: 200,\n headers: {\n 'Content-Type': res.data.contentType,\n 'Cache-Control': 'private, max-age=3600',\n },\n });\n });\n\n authenticated.put('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n let body: Record<string, unknown> = {};\n try {\n body = (await c.req.json()) as Record<string, unknown>;\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const base64 = typeof body.base64 === 'string' ? body.base64 : '';\n const mimeType = typeof body.mimeType === 'string' ? body.mimeType : '';\n const res = await writeAgentAvatarFromBase64(service.currentConfig as Config, id, base64, mimeType);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.delete('/api/agents/:id/avatar', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await deleteAgentAvatarFile(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId } });\n });\n\n authenticated.get('/api/agents/:id/files', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const res = await listAgentProfileFiles(service.currentConfig as Config, id);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: res.data });\n });\n\n authenticated.get('/api/agents/:id/files/:name', async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n const res = await readAgentProfileFile(service.currentConfig as Config, id, name);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name, content: res.data.content } });\n });\n\n authenticated.put('/api/agents/:id/files/:name', strictRateLimitMiddleware, async (c) => {\n const id = normalizeAgentId(c.req.param('id') ?? '');\n const name = decodeURIComponent(c.req.param('name') ?? '');\n let content = '';\n try {\n const body = (await c.req.json()) as { content?: unknown };\n content = typeof body.content === 'string' ? body.content : '';\n } catch {\n return c.json({ ok: false, error: { message: 'Invalid JSON' } }, 400);\n }\n const res = await writeAgentProfileFile(service.currentConfig as Config, id, name, content);\n if (res.ok === false) {\n return c.json({ ok: false, error: { message: res.error } }, res.status ?? 400);\n }\n return c.json({ ok: true, payload: { agentId: res.data.agentId, name } });\n });\n\n // GET /api/voice/models - Get available STT/TTS models\n authenticated.get('/api/voice/models', (c) => {\n const models = getVoiceModelsConfig();\n return c.json({ ok: true, payload: { models } });\n });\n\n authenticated.get('/api/image/capabilities', async (c) => {\n const config = service.currentConfig as Config;\n const imageGenerationProviders = await resolveImageGenerationCapabilities(config);\n const imageUnderstandingProviders = await resolveImageUnderstandingCapabilities(config);\n return c.json({\n ok: true,\n payload: {\n current: {\n imageModel: null,\n imageModelFallbacks: [],\n imageGenerationModel: null,\n imageGenerationModelFallbacks: [],\n mediaMaxMb: null,\n },\n imageGeneration: { providers: imageGenerationProviders },\n imageUnderstanding: { providers: imageUnderstandingProviders },\n },\n });\n });\n\n authenticated.post('/api/image/validate-model', strictRateLimitMiddleware, async (c) => {\n let body: { modelRef?: unknown };\n try {\n body = (await c.req.json()) as { modelRef?: unknown };\n } catch {\n return c.json({ ok: false, error: 'Invalid JSON' }, 400);\n }\n const modelRef = body.modelRef;\n if (!modelRef || typeof modelRef !== 'string') {\n return c.json({ ok: false, error: 'modelRef is required' }, 400);\n }\n\n const parsed = parseModelRef(modelRef);\n if (!parsed) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'invalid_format',\n message: 'Model reference must be in \"provider/model\" format',\n },\n });\n }\n\n const configured = await isProviderConfigured(parsed.provider);\n if (!configured) {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'provider_not_configured',\n message: `Provider \"${parsed.provider}\" is not configured. Set the API key first.`,\n provider: parsed.provider,\n },\n });\n }\n\n try {\n resolveModel(modelRef);\n } catch {\n return c.json({\n ok: true,\n payload: {\n valid: false,\n reason: 'model_not_found',\n message: `Model not found in registry: ${modelRef}`,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n }\n\n return c.json({\n ok: true,\n payload: {\n valid: true,\n provider: parsed.provider,\n model: parsed.model,\n },\n });\n });\n\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * `PATCH /api/config` — tail sections that are each <50 lines:
3
- * update / cron / goals / session / gateway.{skillsMarketplaceProvider,
3
+ * update / goals / session / gateway.{skillsMarketplaceProvider,
4
4
  * skillsStoreBaseUrl} / providers / providersConfig / stt / tts / tools /
5
5
  * tunnel / bindings / mcp.
6
6
  *
@@ -1,7 +1,8 @@
1
1
  import { BindingsConfigSchema, BrowserConfigSchema, McpConfigSchema, init_schema } from "../../../../config/schema.js";
2
2
  import { CredentialResolver, init_credentials } from "../../../../auth/credentials.js";
3
3
  import { canonicalizeConfiguredMcpServer } from "../../../../config/mcp-config-normalize.js";
4
- import { mergeCronConfigPatch, mergeGatewaySkillsMarketplacePatch, mergeGoalsConfigPatch, mergeSessionConfigPatch, mergeUpdateConfigPatch } from "../../../../config/web-patch.js";
4
+ import { setTuiDefaultAgentConfig } from "../../../../commands/agents.config.js";
5
+ import { mergeGatewaySkillsMarketplacePatch, mergeGoalsConfigPatch, mergeSessionConfigPatch, mergeUpdateConfigPatch } from "../../../../config/web-patch.js";
5
6
  import { assertGatewayAuthConfigured, resolveGatewayAuth } from "../../../auth.js";
6
7
  import { isMaskedSecretPatchValue } from "../../lib/mask-secret-length.js";
7
8
  import { applyToolsWebPatch } from "../../../config-tools-web.js";
@@ -17,11 +18,6 @@ async function applyMiscPatch(config, body) {
17
18
  const updateResult = mergeUpdateConfigPatch(config, body.update);
18
19
  if (updateResult.ok === false) return patchError(updateResult.message);
19
20
  }
20
- if (body.cron !== void 0) {
21
- if (typeof body.cron !== "object" || body.cron === null || Array.isArray(body.cron)) return patchError("cron must be an object");
22
- const cronResult = mergeCronConfigPatch(config, body.cron);
23
- if (cronResult.ok === false) return patchError(cronResult.message);
24
- }
25
21
  if (body.goals !== void 0) {
26
22
  if (typeof body.goals !== "object" || body.goals === null || Array.isArray(body.goals)) return patchError("goals must be an object");
27
23
  const goalsResult = mergeGoalsConfigPatch(config, body.goals);
@@ -32,6 +28,16 @@ async function applyMiscPatch(config, body) {
32
28
  const sessionResult = mergeSessionConfigPatch(config, body.session);
33
29
  if (sessionResult.ok === false) return patchError(sessionResult.message);
34
30
  }
31
+ if (body.tui !== void 0) {
32
+ if (typeof body.tui !== "object" || body.tui === null || Array.isArray(body.tui)) return patchError("tui must be an object");
33
+ const tuiPatch = body.tui;
34
+ if (tuiPatch.defaultAgent !== void 0) {
35
+ if (typeof tuiPatch.defaultAgent !== "string" || !tuiPatch.defaultAgent.trim()) return patchError("tui.defaultAgent must be a non-empty string");
36
+ const result = setTuiDefaultAgentConfig(config, tuiPatch.defaultAgent);
37
+ if (result.ok === false) return patchError(result.message);
38
+ config.tui = result.config.tui;
39
+ }
40
+ }
35
41
  if (body.browser !== void 0) {
36
42
  if (typeof body.browser !== "object" || body.browser === null || Array.isArray(body.browser)) return patchError("browser must be an object");
37
43
  const parsed = BrowserConfigSchema.safeParse(body.browser);