@xopcai/xopc 0.0.145 → 0.0.147

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 (380) hide show
  1. package/README.md +2 -2
  2. package/dist/browser-ext/manifest.json +1 -1
  3. package/dist/extensions/demo-memory/src/index.js +6 -4
  4. package/dist/extensions/demo-memory/src/index.js.map +1 -1
  5. package/dist/extensions/telegram/xopc.extension.json +1 -1
  6. package/dist/gateway/static/root/assets/Combination-14nmIgxH.js +41 -0
  7. package/dist/gateway/static/root/assets/activity-store-DXeSSlw1.js +1 -0
  8. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BEUxdhZx.js → agent-avatar-dicebear-CFdJKSjY.js} +1 -1
  9. package/dist/gateway/static/root/assets/agents-DKjbRpbA.js +2 -0
  10. package/dist/gateway/static/root/assets/api-Bs69B5zA.js +1 -0
  11. package/dist/gateway/static/root/assets/{app-management-settings-panel-CRHSZJWi.js → app-management-settings-panel-ag1ViXT_.js} +1 -1
  12. package/dist/gateway/static/root/assets/{appearance-settings-BunADYJb.js → appearance-settings-C6iMpwOM.js} +1 -1
  13. package/dist/gateway/static/root/assets/apps-page-CpX3lBFF.js +1 -0
  14. package/dist/gateway/static/root/assets/{archive-plugin-B6vTkH2A.js → archive-plugin-Dwi3mIBy.js} +1 -1
  15. package/dist/gateway/static/root/assets/{attachment-load-BjZXzaNv.js → attachment-load-BaCDoq40.js} +1 -1
  16. package/dist/gateway/static/root/assets/{automation-suggestion-card-ZDA-Stg1.js → automation-suggestion-card-CwqtFgnw.js} +1 -1
  17. package/dist/gateway/static/root/assets/automations-page-DlupOxFQ.js +6 -0
  18. package/dist/gateway/static/root/assets/{binary-plugins-DYZfLvPz.js → binary-plugins-DoAYhsxa.js} +1 -1
  19. package/dist/gateway/static/root/assets/{block-editor-C3MUlYC9.js → block-editor-Bw72pO7S.js} +31 -31
  20. package/dist/gateway/static/root/assets/browser-settings-page-BwLoUBcZ.js +8 -0
  21. package/dist/gateway/static/root/assets/capability-presets-api-vdbAR65Q.js +1 -0
  22. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BAsKbJgm.js +2 -0
  23. package/dist/gateway/static/root/assets/{channel-recipient-api-fTlTnWB4.js → channel-recipient-api-rTG26jpV.js} +1 -1
  24. package/dist/gateway/static/root/assets/channels-settings-CxFWy0cE.js +1 -0
  25. package/dist/gateway/static/root/assets/channels-status-swr-OKlqTtKJ.js +1 -0
  26. package/dist/gateway/static/root/assets/{connector-logo-BVFNT2zW.js → connector-logo-DIMP4NWY.js} +1 -1
  27. package/dist/gateway/static/root/assets/connectors-page-BjQQwX62.js +2 -0
  28. package/dist/gateway/static/root/assets/{desktop-pet-_jUmoXd3.js → desktop-pet-kQq2e0BN.js} +1 -1
  29. package/dist/gateway/static/root/assets/{desktop-pet-settings-DwGOy4AQ.js → desktop-pet-settings-B6vtozMY.js} +1 -1
  30. package/dist/gateway/static/root/assets/{directory-picker-path-field-akvF0F-u.js → directory-picker-path-field-Dn5-e3v4.js} +1 -1
  31. package/dist/gateway/static/root/assets/dist-C230izr8.js +1 -0
  32. package/dist/gateway/static/root/assets/dist-CxGUk8J-.js +1 -0
  33. package/dist/gateway/static/root/assets/dreaming-settings-BzwIujPG.js +3 -0
  34. package/dist/gateway/static/root/assets/extension-debug-page-D_e_hsEy.js +1 -0
  35. package/dist/gateway/static/root/assets/{extension-page-CwWktRNz.js → extension-page-D15CWHBd.js} +1 -1
  36. package/dist/gateway/static/root/assets/{extension-settings-page-CuggWOIl.js → extension-settings-page-D4P0n1om.js} +1 -1
  37. package/dist/gateway/static/root/assets/{gateway-config-api-B7sxIbza.js → gateway-config-api-B4qZctjG.js} +1 -1
  38. package/dist/gateway/static/root/assets/{gateway-settings-DIv0eKMf.js → gateway-settings-BvndV7TP.js} +1 -1
  39. package/dist/gateway/static/root/assets/{gateway-startup-retry-DtoLihQE.js → gateway-startup-retry-BpgMunEb.js} +1 -1
  40. package/dist/gateway/static/root/assets/{goal-create-dialog-C4Kw0mfS.js → goal-create-dialog-DrVHKXHq.js} +1 -1
  41. package/dist/gateway/static/root/assets/goal-detail-page-PHlCwv68.js +4 -0
  42. package/dist/gateway/static/root/assets/{goals-config-api-B0jm5JaA.js → goals-config-api-B6YJB_ct.js} +1 -1
  43. package/dist/gateway/static/root/assets/goals-page-Hg9uyO6e.js +2 -0
  44. package/dist/gateway/static/root/assets/{goals-settings-N5_iL7es.js → goals-settings-BROWCIcL.js} +1 -1
  45. package/dist/gateway/static/root/assets/{heartbeat-settings-XzH3lbRR.js → heartbeat-settings-CoCwIOIg.js} +1 -1
  46. package/dist/gateway/static/root/assets/index-CxkNzw3e.js +259 -0
  47. package/dist/gateway/static/root/assets/index-DjCSOyaN.css +1 -0
  48. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-Bm_AIYQ7.js +1 -0
  49. package/dist/gateway/static/root/assets/local-app-workbench-page-BJWFcxwG.js +2 -0
  50. package/dist/gateway/static/root/assets/local-apps-page-BsiZMrEf.js +1 -0
  51. package/dist/gateway/static/root/assets/{locale-store-CiM-D9jA.js → locale-store-Bp8joZck.js} +1 -1
  52. package/dist/gateway/static/root/assets/logs-page-DOmK61ey.js +7 -0
  53. package/dist/gateway/static/root/assets/{markdown-split-5rJx5flj.js → markdown-split-Dy7QpaAz.js} +1 -1
  54. package/dist/gateway/static/root/assets/{media-plugins-DYXccwAd.js → media-plugins-3Lxliy9D.js} +1 -1
  55. package/dist/gateway/static/root/assets/messages-CQGpD-dC.js +5 -0
  56. package/dist/gateway/static/root/assets/models-hub-panel-DGCZom4o.js +2 -0
  57. package/dist/gateway/static/root/assets/{notes-page-BgLyndCO.js → notes-page-BJtT4vSf.js} +1 -1
  58. package/dist/gateway/static/root/assets/notes-workbench-B_bN7cOR.js +4 -0
  59. package/dist/gateway/static/root/assets/{page-tabs-6Al9_sGz.js → page-tabs-DKB6RDre.js} +1 -1
  60. package/dist/gateway/static/root/assets/{preview-open-alternatives-Cm3G72Hv.js → preview-open-alternatives-Br_YhYHp.js} +1 -1
  61. package/dist/gateway/static/root/assets/project-detail-page-Dq8JouJj.js +1 -0
  62. package/dist/gateway/static/root/assets/projects-page-DvfL7fSe.js +1 -0
  63. package/dist/gateway/static/root/assets/remote-access-hub-DqwMXSXP.js +1 -0
  64. package/dist/gateway/static/root/assets/{save-bar-controls-BYtfzu_F.js → save-bar-controls-BgIE9BBh.js} +1 -1
  65. package/dist/gateway/static/root/assets/{schedule-field-CvIRc6yK.js → schedule-field-BXDP-oMz.js} +1 -1
  66. package/dist/gateway/static/root/assets/{schema-form-CQuKx0n7.js → schema-form-Dhv-SmjG.js} +1 -1
  67. package/dist/gateway/static/root/assets/sessions-page-B_mOZkQk.js +1 -0
  68. package/dist/gateway/static/root/assets/settings-advanced-gate-BHGmH6YS.js +1 -0
  69. package/dist/gateway/static/root/assets/{settings-collapsible-section-CF3HHM-t.js → settings-collapsible-section-CUTExnlK.js} +1 -1
  70. package/dist/gateway/static/root/assets/{settings-form-section-CwWjoRN6.js → settings-form-section-CmnDhsf0.js} +1 -1
  71. package/dist/gateway/static/root/assets/{settings-loading-skeleton-aUFmJa13.js → settings-loading-skeleton-B79dq-XY.js} +1 -1
  72. package/dist/gateway/static/root/assets/{settings-page-B2UUU9TF.js → settings-page-Db8uAv3X.js} +1 -1
  73. package/dist/gateway/static/root/assets/{settings-page-layout-DqpbTWqI.js → settings-page-layout-DaFwstQw.js} +1 -1
  74. package/dist/gateway/static/root/assets/setup-status-panel-BUSEj0KK.js +1 -0
  75. package/dist/gateway/static/root/assets/{share-preview-page-BOhlPsS1.js → share-preview-page-Bi00uXzV.js} +1 -1
  76. package/dist/gateway/static/root/assets/shares-settings-DzsTYfuX.js +1 -0
  77. package/dist/gateway/static/root/assets/skill-reload-api-DSsdU081.js +1 -0
  78. package/dist/gateway/static/root/assets/skills-page-DeB1tQZL.js +2 -0
  79. package/dist/gateway/static/root/assets/{system-settings-panel-CWxSvuwD.js → system-settings-panel-Cxaph7hW.js} +1 -1
  80. package/dist/gateway/static/root/assets/{theme-store-C9Dxcppm.js → theme-store-eCTN1RpG.js} +1 -1
  81. package/dist/gateway/static/root/assets/{typed-models-lib-qROAvqTw.js → typed-models-lib-CcZ_tyFY.js} +1 -1
  82. package/dist/gateway/static/root/assets/{use-channel-catalog-DE9cpn4G.js → use-channel-catalog-C4PWbNoi.js} +1 -1
  83. package/dist/gateway/static/root/assets/user-context-page-QTVMx_hG.js +1 -0
  84. package/dist/gateway/static/root/assets/{user-profile-fields-editor-CWxc0ghP.js → user-profile-fields-editor-CPOO9Jz5.js} +1 -1
  85. package/dist/gateway/static/root/assets/{user-profile-settings-panel-DW-Up6vt.js → user-profile-settings-panel-C8cgtSF7.js} +1 -1
  86. package/dist/gateway/static/root/assets/{utils-D53uRXVr.js → utils-CiZK2KwH.js} +1 -1
  87. package/dist/gateway/static/root/assets/voice-api-key-field-b-YZtvUu.js +1 -0
  88. package/dist/gateway/static/root/assets/work-discovery-page-4zVDOl2G.js +1 -0
  89. package/dist/gateway/static/root/assets/work-item-detail-page-CHe2tfkc.js +1 -0
  90. package/dist/gateway/static/root/assets/{workflow-run-setup-panel-D_x9ELJp.js → workflow-run-setup-panel-8SLCYeXE.js} +2 -2
  91. package/dist/gateway/static/root/assets/workflows-page-DEOFqiWn.js +11 -0
  92. package/dist/gateway/static/root/index.html +10 -9
  93. package/dist/package.js +1 -1
  94. package/dist/src/activity/types.d.ts +1 -1
  95. package/dist/src/agent/agent-instance-gateway.d.ts +1 -1
  96. package/dist/src/agent/agent-manager.d.ts +1 -1
  97. package/dist/src/agent/agent-manager.js +5 -4
  98. package/dist/src/agent/agent-manager.js.map +1 -1
  99. package/dist/src/agent/background-review/coordinator.js +0 -1
  100. package/dist/src/agent/background-review/coordinator.js.map +1 -1
  101. package/dist/src/agent/background-review/settings.d.ts +1 -1
  102. package/dist/src/agent/background-review/settings.js +10 -17
  103. package/dist/src/agent/background-review/settings.js.map +1 -1
  104. package/dist/src/agent/bootstrap/filter-bootstrap-files.d.ts +1 -1
  105. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +1 -1
  106. package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
  107. package/dist/src/agent/bootstrap/load-bootstrap-files.js +2 -3
  108. package/dist/src/agent/bootstrap/load-bootstrap-files.js.map +1 -1
  109. package/dist/src/agent/code-intelligence/binary.js +1 -1
  110. package/dist/src/agent/context/project-context.d.ts +14 -0
  111. package/dist/src/agent/context/project-context.js +23 -1
  112. package/dist/src/agent/context/project-context.js.map +1 -1
  113. package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
  114. package/dist/src/agent/context/workspace.d.ts +1 -2
  115. package/dist/src/agent/context/workspace.js +2 -4
  116. package/dist/src/agent/context/workspace.js.map +1 -1
  117. package/dist/src/agent/embedded/run-for-session.js +1 -2
  118. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  119. package/dist/src/agent/embedded/run-turn.js +6 -1
  120. package/dist/src/agent/embedded/run-turn.js.map +1 -1
  121. package/dist/src/agent/embedded/types.d.ts +17 -0
  122. package/dist/src/agent/memory/builtin-memory-store.d.ts +2 -2
  123. package/dist/src/agent/memory/builtin-memory-store.js +2 -2
  124. package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
  125. package/dist/src/agent/memory/builtin-provider.d.ts +1 -3
  126. package/dist/src/agent/memory/builtin-provider.js +21 -48
  127. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  128. package/dist/src/agent/memory/context/planner.js +48 -9
  129. package/dist/src/agent/memory/context/planner.js.map +1 -1
  130. package/dist/src/agent/memory/context/types.d.ts +7 -1
  131. package/dist/src/agent/memory/context-fence.js +1 -1
  132. package/dist/src/agent/memory/context-fence.js.map +1 -1
  133. package/dist/src/agent/memory/create-memory-manager.js +2 -9
  134. package/dist/src/agent/memory/create-memory-manager.js.map +1 -1
  135. package/dist/src/agent/memory/dreaming/config.js +5 -10
  136. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  137. package/dist/src/agent/memory/dreaming/promotion-lifecycle.js +2 -2
  138. package/dist/src/agent/memory/dreaming/promotion-lifecycle.js.map +1 -1
  139. package/dist/src/agent/memory/dreaming/scope.d.ts +2 -3
  140. package/dist/src/agent/memory/dreaming/scope.js +8 -8
  141. package/dist/src/agent/memory/dreaming/scope.js.map +1 -1
  142. package/dist/src/agent/memory/manager.d.ts +1 -5
  143. package/dist/src/agent/memory/manager.js +2 -23
  144. package/dist/src/agent/memory/manager.js.map +1 -1
  145. package/dist/src/agent/memory/memory-config.d.ts +3 -3
  146. package/dist/src/agent/memory/memory-config.js +9 -14
  147. package/dist/src/agent/memory/memory-config.js.map +1 -1
  148. package/dist/src/agent/memory/types.d.ts +9 -5
  149. package/dist/src/agent/memory/understanding/service.js +21 -8
  150. package/dist/src/agent/memory/understanding/service.js.map +1 -1
  151. package/dist/src/agent/memory/understanding/types.d.ts +5 -0
  152. package/dist/src/agent/memory/user-context-coordinator.d.ts +1 -1
  153. package/dist/src/agent/memory/user-context-coordinator.js +6 -2
  154. package/dist/src/agent/memory/user-context-coordinator.js.map +1 -1
  155. package/dist/src/agent/orchestration/agent-orchestrator.js +2 -2
  156. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  157. package/dist/src/agent/prompt/memory/index.d.ts +1 -2
  158. package/dist/src/agent/prompt/memory/index.js +6 -7
  159. package/dist/src/agent/prompt/memory/index.js.map +1 -1
  160. package/dist/src/agent/prompt/sections/tooling.js +1 -1
  161. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  162. package/dist/src/agent/service/direct-turn-helpers.js +13 -2
  163. package/dist/src/agent/service/direct-turn-helpers.js.map +1 -1
  164. package/dist/src/agent/tools/curated-memory-tool.js +4 -4
  165. package/dist/src/agent/tools/curated-memory-tool.js.map +1 -1
  166. package/dist/src/agent/tools/factory.d.ts +1 -1
  167. package/dist/src/agent/tools/factory.js +2 -2
  168. package/dist/src/agent/tools/factory.js.map +1 -1
  169. package/dist/src/agent/tools/memory-tool.js +1 -1
  170. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  171. package/dist/src/agent/workflow/workflow-child-tools.js +2 -3
  172. package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -1
  173. package/dist/src/agent/workspace-runtime/registry.d.ts +5 -5
  174. package/dist/src/agent/workspace-runtime/registry.js +6 -11
  175. package/dist/src/agent/workspace-runtime/registry.js.map +1 -1
  176. package/dist/src/agent-manifest/index.js +2 -2
  177. package/dist/src/agent-manifest/prompt.js +1 -7
  178. package/dist/src/agent-manifest/prompt.js.map +1 -1
  179. package/dist/src/agent-manifest/schema.d.ts +0 -598
  180. package/dist/src/agent-manifest/schema.js +2 -143
  181. package/dist/src/agent-manifest/schema.js.map +1 -1
  182. package/dist/src/agent-manifest/validator.js +0 -12
  183. package/dist/src/agent-manifest/validator.js.map +1 -1
  184. package/dist/src/agent-runtime/index.js +1 -1
  185. package/dist/src/agent-runtime/memory-runtime.d.ts +2 -2
  186. package/dist/src/agent-runtime/memory-runtime.js +8 -7
  187. package/dist/src/agent-runtime/memory-runtime.js.map +1 -1
  188. package/dist/src/agent-runtime/runtime-profile.d.ts +2 -0
  189. package/dist/src/agent-runtime/runtime-profile.js +2 -2
  190. package/dist/src/agent-runtime/runtime-profile.js.map +1 -1
  191. package/dist/src/chat-commands/agent-edit.js +1 -2
  192. package/dist/src/chat-commands/agent-edit.js.map +1 -1
  193. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  194. package/dist/src/cli/commands/init.js +0 -22
  195. package/dist/src/cli/commands/init.js.map +1 -1
  196. package/dist/src/cli/templates.d.ts +1 -1
  197. package/dist/src/cli/templates.js +1 -16
  198. package/dist/src/cli/templates.js.map +1 -1
  199. package/dist/src/commands/agents.config.js +0 -10
  200. package/dist/src/commands/agents.config.js.map +1 -1
  201. package/dist/src/config/agent-profile.js +1 -1
  202. package/dist/src/config/index.js +2 -2
  203. package/dist/src/config/paths.d.ts +0 -1
  204. package/dist/src/config/paths.js +1 -2
  205. package/dist/src/config/paths.js.map +1 -1
  206. package/dist/src/config/schema.d.ts +118 -532
  207. package/dist/src/config/schema.js +32 -26
  208. package/dist/src/config/schema.js.map +1 -1
  209. package/dist/src/extensions/loader.js +2 -1
  210. package/dist/src/extensions/loader.js.map +1 -1
  211. package/dist/src/gateway/agents-admin.d.ts +0 -2
  212. package/dist/src/gateway/agents-admin.js +1 -7
  213. package/dist/src/gateway/agents-admin.js.map +1 -1
  214. package/dist/src/gateway/capability-presets-admin.d.ts +0 -2
  215. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  216. package/dist/src/gateway/chat-stream/mapper.js +26 -0
  217. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  218. package/dist/src/gateway/chat-stream/protocol.d.ts +16 -1
  219. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +0 -1
  220. package/dist/src/gateway/dreaming-automation-reconciler.js +41 -63
  221. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -1
  222. package/dist/src/gateway/heartbeat/service.js +1 -1
  223. package/dist/src/gateway/hono/app.js +3 -1
  224. package/dist/src/gateway/hono/app.js.map +1 -1
  225. package/dist/src/gateway/hono/lib/config-payload.d.ts +0 -130
  226. package/dist/src/gateway/hono/lib/config-payload.js +0 -1
  227. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  228. package/dist/src/gateway/hono/routes/agents.js +6 -12
  229. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  230. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +6 -0
  231. package/dist/src/gateway/hono/routes/auth-registry-extensions.js.map +1 -1
  232. package/dist/src/gateway/hono/routes/capability-presets.js +2 -2
  233. package/dist/src/gateway/hono/routes/capability-presets.js.map +1 -1
  234. package/dist/src/gateway/hono/routes/dreaming.js +9 -20
  235. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  236. package/dist/src/gateway/hono/routes/index.js +4 -0
  237. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  238. package/dist/src/gateway/hono/routes/local-apps.d.ts +5 -0
  239. package/dist/src/gateway/hono/routes/local-apps.js +99 -0
  240. package/dist/src/gateway/hono/routes/local-apps.js.map +1 -0
  241. package/dist/src/gateway/hono/routes/memory.js +48 -65
  242. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  243. package/dist/src/gateway/hono/routes/projects.js +2 -2
  244. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  245. package/dist/src/gateway/hono/routes/work-discovery.d.ts +3 -0
  246. package/dist/src/gateway/hono/routes/work-discovery.js +150 -0
  247. package/dist/src/gateway/hono/routes/work-discovery.js.map +1 -0
  248. package/dist/src/gateway/hono/routes/you.d.ts +3 -0
  249. package/dist/src/gateway/hono/routes/you.js +358 -91
  250. package/dist/src/gateway/hono/routes/you.js.map +1 -1
  251. package/dist/src/gateway/service.d.ts +3 -0
  252. package/dist/src/gateway/service.js +12 -0
  253. package/dist/src/gateway/service.js.map +1 -1
  254. package/dist/src/heartbeat/index.js +1 -1
  255. package/dist/src/knowledge/connected-knowledge-pipeline.js +9 -5
  256. package/dist/src/knowledge/connected-knowledge-pipeline.js.map +1 -1
  257. package/dist/src/local-apps/acceptance.d.ts +30 -0
  258. package/dist/src/local-apps/acceptance.js +93 -0
  259. package/dist/src/local-apps/acceptance.js.map +1 -0
  260. package/dist/src/local-apps/index.d.ts +5 -0
  261. package/dist/src/local-apps/index.js +4 -0
  262. package/dist/src/local-apps/preview-runtime-bridge.d.ts +4 -0
  263. package/dist/src/local-apps/preview-runtime-bridge.js +171 -0
  264. package/dist/src/local-apps/preview-runtime-bridge.js.map +1 -0
  265. package/dist/src/local-apps/runtime-entry.d.ts +8 -0
  266. package/dist/src/local-apps/runtime-entry.js +25 -0
  267. package/dist/src/local-apps/runtime-entry.js.map +1 -0
  268. package/dist/src/local-apps/scaffold.d.ts +8 -0
  269. package/dist/src/local-apps/scaffold.js +122 -0
  270. package/dist/src/local-apps/scaffold.js.map +1 -0
  271. package/dist/src/local-apps/service.d.ts +37 -0
  272. package/dist/src/local-apps/service.js +553 -0
  273. package/dist/src/local-apps/service.js.map +1 -0
  274. package/dist/src/local-apps/store.d.ts +44 -0
  275. package/dist/src/local-apps/store.js +195 -0
  276. package/dist/src/local-apps/store.js.map +1 -0
  277. package/dist/src/local-apps/types.d.ts +105 -0
  278. package/dist/src/local-apps/types.js +1 -0
  279. package/dist/src/storage/sqlite/index.d.ts +3 -2
  280. package/dist/src/storage/sqlite/index.js +4 -3
  281. package/dist/src/storage/sqlite/memory-index-repository.d.ts +2 -3
  282. package/dist/src/storage/sqlite/memory-index-repository.js +16 -20
  283. package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -1
  284. package/dist/src/storage/sqlite/memory-records-repository.d.ts +18 -10
  285. package/dist/src/storage/sqlite/memory-records-repository.js +79 -34
  286. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
  287. package/dist/src/storage/sqlite/memory-reference-consent-repository.d.ts +27 -0
  288. package/dist/src/storage/sqlite/memory-reference-consent-repository.js +109 -0
  289. package/dist/src/storage/sqlite/memory-reference-consent-repository.js.map +1 -0
  290. package/dist/src/storage/sqlite/migrations/038_user_owned_memory.sql +68 -0
  291. package/dist/src/storage/sqlite/migrations/039_memory_reference_consents.sql +19 -0
  292. package/dist/src/storage/sqlite/migrations/040_local_apps.sql +32 -0
  293. package/dist/src/storage/sqlite/migrations/041_local_app_release_lifecycle.sql +17 -0
  294. package/dist/src/storage/sqlite/migrations/042_work_discovery.sql +41 -0
  295. package/dist/src/storage/sqlite/migrations/043_local_app_acceptance_runs.sql +16 -0
  296. package/dist/src/storage/sqlite/migrations/044_repair_work_discovery_foreign_keys.sql +75 -0
  297. package/dist/src/storage/sqlite/migrations/045_extension_ui_grants.sql +13 -0
  298. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  299. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  300. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  301. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  302. package/dist/src/storage/sqlite/schema.js +1 -1
  303. package/dist/src/storage/sqlite/schema.sql +20 -0
  304. package/dist/src/user-context/config.d.ts +227 -0
  305. package/dist/src/user-context/config.js +158 -0
  306. package/dist/src/user-context/config.js.map +1 -0
  307. package/dist/src/user-context/import.d.ts +1 -1
  308. package/dist/src/user-context/import.js +6 -1
  309. package/dist/src/user-context/import.js.map +1 -1
  310. package/dist/src/user-context/owner.d.ts +5 -0
  311. package/dist/src/user-context/owner.js +9 -0
  312. package/dist/src/user-context/owner.js.map +1 -0
  313. package/dist/src/user-context/projection.d.ts +11 -9
  314. package/dist/src/user-context/projection.js +74 -47
  315. package/dist/src/user-context/projection.js.map +1 -1
  316. package/dist/src/user-context/runtime.d.ts +13 -0
  317. package/dist/src/user-context/runtime.js +36 -0
  318. package/dist/src/user-context/runtime.js.map +1 -0
  319. package/dist/src/work-discovery/analyzer.d.ts +11 -0
  320. package/dist/src/work-discovery/analyzer.js +171 -0
  321. package/dist/src/work-discovery/analyzer.js.map +1 -0
  322. package/dist/src/work-discovery/index.d.ts +5 -0
  323. package/dist/src/work-discovery/index.js +5 -0
  324. package/dist/src/work-discovery/probe.d.ts +12 -0
  325. package/dist/src/work-discovery/probe.js +335 -0
  326. package/dist/src/work-discovery/probe.js.map +1 -0
  327. package/dist/src/work-discovery/repository.d.ts +11 -0
  328. package/dist/src/work-discovery/repository.js +100 -0
  329. package/dist/src/work-discovery/repository.js.map +1 -0
  330. package/dist/src/work-discovery/service.d.ts +30 -0
  331. package/dist/src/work-discovery/service.js +387 -0
  332. package/dist/src/work-discovery/service.js.map +1 -0
  333. package/dist/src/work-discovery/types.d.ts +114 -0
  334. package/dist/src/work-discovery/types.js +1 -0
  335. package/dist/src/workflows/service/workflow-session-bridge.js +1 -1
  336. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  337. package/package.json +5 -3
  338. package/skills/engineering/build-xopc-local-app/SKILL.md +45 -0
  339. package/skills/engineering/build-xopc-local-app/references/app-contract.md +33 -0
  340. package/skills/engineering/build-xopc-local-app/scripts/validate-local-app.mjs +72 -0
  341. package/dist/gateway/static/root/assets/Combination-DolwnuKi.js +0 -41
  342. package/dist/gateway/static/root/assets/activity-center-store-3l9ahUqb.js +0 -1
  343. package/dist/gateway/static/root/assets/agents-1bpT0xRO.js +0 -2
  344. package/dist/gateway/static/root/assets/apps-page-Cc4JgVUQ.js +0 -1
  345. package/dist/gateway/static/root/assets/automations-page-mb0fdVpq.js +0 -6
  346. package/dist/gateway/static/root/assets/browser-settings-page-Bb0xhaMN.js +0 -8
  347. package/dist/gateway/static/root/assets/capability-presets-api-BV76yN9a.js +0 -1
  348. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CUcGKZqC.js +0 -2
  349. package/dist/gateway/static/root/assets/channels-settings-BlSDMGdy.js +0 -1
  350. package/dist/gateway/static/root/assets/channels-status-swr-CJauF1CW.js +0 -1
  351. package/dist/gateway/static/root/assets/connectors-page-CMgAFGvb.js +0 -2
  352. package/dist/gateway/static/root/assets/dist-C99RGfAH.js +0 -1
  353. package/dist/gateway/static/root/assets/dreaming-settings-BLetQiYY.js +0 -3
  354. package/dist/gateway/static/root/assets/extension-debug-page-Cof2ncxE.js +0 -1
  355. package/dist/gateway/static/root/assets/goal-detail-page-BMmzYpZL.js +0 -4
  356. package/dist/gateway/static/root/assets/goals-page-CGeT77PC.js +0 -2
  357. package/dist/gateway/static/root/assets/index-CSLF84-Q.css +0 -1
  358. package/dist/gateway/static/root/assets/index-I-ZCenVw.js +0 -259
  359. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-x_v0nrIi.js +0 -1
  360. package/dist/gateway/static/root/assets/logs-page-BSh1t8cD.js +0 -7
  361. package/dist/gateway/static/root/assets/messages-Cb1VMeqP.js +0 -5
  362. package/dist/gateway/static/root/assets/models-hub-panel-BNpTenAI.js +0 -2
  363. package/dist/gateway/static/root/assets/notes-workbench-teklkhcE.js +0 -4
  364. package/dist/gateway/static/root/assets/project-detail-page-CCB_dKoh.js +0 -1
  365. package/dist/gateway/static/root/assets/projects-page-VOAFAHYj.js +0 -1
  366. package/dist/gateway/static/root/assets/remote-access-hub-USYu64Ru.js +0 -1
  367. package/dist/gateway/static/root/assets/sessions-page-oGC8O5h_.js +0 -1
  368. package/dist/gateway/static/root/assets/settings-advanced-gate-D4rP66R1.js +0 -1
  369. package/dist/gateway/static/root/assets/setup-status-panel-Ck9keROI.js +0 -1
  370. package/dist/gateway/static/root/assets/shares-settings-BYLsCuqj.js +0 -1
  371. package/dist/gateway/static/root/assets/skill-reload-api-BNHUyVML.js +0 -1
  372. package/dist/gateway/static/root/assets/skills-page-CpXbQH4n.js +0 -2
  373. package/dist/gateway/static/root/assets/user-context-page-DbNEK4Yp.js +0 -1
  374. package/dist/gateway/static/root/assets/voice-api-key-field-Cs7MOrg0.js +0 -1
  375. package/dist/gateway/static/root/assets/work-item-detail-page-D1ziG1Pp.js +0 -1
  376. package/dist/gateway/static/root/assets/workflows-page-DHGV_n6i.js +0 -11
  377. package/dist/src/agent/context/workspace-templates/MEMORY.md +0 -33
  378. package/dist/src/agent/memory/access-policy.d.ts +0 -12
  379. package/dist/src/agent/memory/access-policy.js +0 -44
  380. package/dist/src/agent/memory/access-policy.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"service.js","names":["writeConfigToDisk","reconcileDreamingAutomationRecords"],"sources":["../../../src/gateway/service.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from '../agent/agent-scope.js';\nimport { AgentService } from '../agent/service.js';\nimport { ensureStarterAgentsInitialized } from '../agent/starter-agents.js';\nimport { ChannelManager } from '../channels/manager.js';\nimport {\n buildChannelCatalogForConfig,\n buildChannelCatalogFromSnapshot,\n} from '../channels/catalog/channel-catalog-service.js';\nimport { setPairingBroadcastSink } from '../channels/pairing/pairing-events.js';\nimport { MessageBus, MessageBusShutdownError } from '../infra/bus/index.js';\nimport { loadConfig, saveConfig as writeConfigToDisk } from '../config/index.js';\nimport { getWorkspacePath } from '../config/workspace-path-helpers.js';\nimport { AutomationService } from '../automations/index.js';\nimport { onAutomationProductEvent, publishAutomationProductEvent } from '../automations/product-events.js';\nimport { buildNoteAgentContext, NotesService, NotesStore } from '../notes/index.js';\nimport { buildWorkflowChildTools } from '../agent/workflow/workflow-child-tools.js';\nimport { WorkflowRunService } from '../workflows/service/workflow-run-service.js';\nimport { WorkflowSessionBridge } from '../workflows/service/workflow-session-bridge.js';\nimport { ExtensionLoader, areExtensionsGloballyDisabled, buildExtensionMetadataSnapshot } from '../extensions/index.js';\nimport type { ManifestRegistryEntry } from '../extensions/manifest-registry.js';\nimport type { ResolvedExtensionConfig } from '../extensions/types/index.js';\nimport { HeartbeatService, heartbeatRunnerConfigFromConfig } from './heartbeat/index.js';\nimport { SessionIndex } from '../session/index.js';\nimport { onSessionTranscriptUpdate } from '../session/transcript-events.js';\nimport type { Config } from '../config/schema.js';\nimport { getAgentDefaultModelRef } from '../config/schema.js';\nimport { wireTunnelEventsToGateway } from '../tunnel/gateway-lifecycle.js';\nimport {\n stopTailscaleExposure,\n} from './tailscale-lifecycle.js';\nimport { getExposureManager } from '../remote-access/exposure-manager.js';\nimport { sanitizeTunnelConfig } from '../tunnel/tunnel-config.js';\nimport { resolveGatewayAuth, assertGatewayAuthConfigured, validateToken, extractToken, type ResolvedGatewayAuth } from './auth.js';\nimport { assertGatewayAuthNotKnownWeak } from './security/known-weak-secrets.js';\nimport { auditGatewayConfig } from './security/audit.js';\nimport { assertGatewayRuntimeConfig } from './runtime-config.js';\nimport { resolveEffectiveGatewayPort } from './host.js';\nimport { buckets, isGatewayStrictSecurityEnabled } from './rate-limit/index.js';\nimport { prewarmModelRegistry } from '../providers/index.js';\nimport { runBootstrapMigrationsSync } from '../migrations/runner.js';\nimport { createLogger, getLogDir, getRuntimeLogStats } from '../utils/logger.js';\nimport {\n resolveConfigPath,\n resolveAgentDir,\n resolveExtensionsDir,\n} from '../config/paths.js';\nimport { AgentRunRelay, type RelayEvent } from './agent-run-relay.js';\nimport { registerClarifyBridge } from './clarify-runtime.js';\nimport { PACKAGE_VERSION } from '../package-version.js';\nimport { GoalNotificationService, GoalRunner, type EnqueueGoalRunOptions } from '../goals/index.js';\nimport { MobileNotificationService } from '../mobile/notification-service.js';\nimport { ProjectService } from '../projects/index.js';\nimport { buildWorkItemAgentContext, WorkItemService } from '../work-items/index.js';\n\nimport { disposeAllSessionMcpRuntimes } from '../agent/mcp/bundle-mcp-tools.js';\nimport { getDefaultAgentId } from '../routing/resolve-route.js';\nimport { buildSessionKey, sanitizeSegment } from '../routing/session-key.js';\nimport { scheduleGatewayUpdateCheck } from '../infra/update-startup.js';\nimport { resolveChannelConnectDeferSet } from './resolve-channel-connect-defer.js';\nimport { restartGatewayProcessWithFreshPid } from './respawn.js';\nimport { GatewaySessionsApi } from './service/sessions-api.js';\nimport { GatewayMarketplaceService } from './service/marketplace-service.js';\nimport { GatewayConfigCoordinator } from './service/config-coordinator.js';\nimport { GatewayAgentRunner } from './service/agent-runner.js';\nimport { GatewaySseHub } from './service/sse-hub.js';\nimport { reconcileDreamingAutomations as reconcileDreamingAutomationRecords } from './dreaming-automation-reconciler.js';\nimport type {\n GatewayChannelStartupPhase1Metrics,\n GatewayChannelStartupPhase2Metrics,\n GatewayServiceConfig,\n ServiceEvent,\n} from './service/types.js';\nimport {\n GatewayReadiness,\n type GatewayReadinessSnapshot,\n} from './startup-readiness.js';\nimport { createGatewayStartupTrace, type GatewayStartupTrace } from './startup-trace.js';\nimport { closeXopcDatabase, openXopcDatabase } from '../storage/sqlite/index.js';\nimport { startConnectorSupervisor, type ConnectorSupervisor } from '../connectors/supervisor.js';\nimport {\n applyAutomaticVoiceLanguage,\n inferProductLanguageFromEnvironment,\n initializeVoiceDefaults,\n prepareConfiguredLocalVoiceModel,\n type ProductLanguage,\n} from '../voice/language-profile.js';\nimport {\n startConnectedKnowledgeCoordinator,\n type ConnectedKnowledgeCoordinator,\n} from '../knowledge/index.js';\n\nexport type {\n GatewayChannelStartupPhase1Metrics,\n GatewayChannelStartupPhase2Metrics,\n GatewayServiceConfig,\n ServiceEvent,\n} from './service/types.js';\n\nconst log = createLogger('Gateway:Service');\n\nexport class GatewayService {\n private bus: MessageBus;\n private config: Config;\n private configPath: string;\n private _agentService: AgentService | null = null;\n private channelManager: ChannelManager;\n private automationService: AutomationService;\n private notesService: NotesService;\n private extensionLoader: ExtensionLoader | null = null;\n private extensionMetadataSnapshot: import('../extensions/extension-metadata-snapshot.js').ExtensionMetadataSnapshot | null = null;\n private browserExtensionProvider: import('../browser/providers/extension.js').ExtensionBrowserProvider | null = null;\n private browserExtensionRelease: (() => Promise<void>) | null = null;\n /** `${host}:${port}` when the gateway holds the extension bridge listener. */\n private browserExtensionBindKey: string | null = null;\n private heartbeatService: HeartbeatService | null = null;\n private sessionIndex: SessionIndex;\n private running = false;\n private startTime = Date.now();\n private workspacePath: string;\n private readonly configCoordinator: GatewayConfigCoordinator;\n\n // Authentication\n private auth: ResolvedGatewayAuth;\n\n private readonly sse = new GatewaySseHub();\n\n getConfig(): Config {\n return this.config;\n }\n\n private stopGatewayUpdateCheck: (() => void) | null = null;\n\n /** When set (e.g. by `GatewayServer`), `triggerGatewayProcessRestart` can stop HTTP then exit. */\n private gatewayShutdownForRestart: (() => Promise<void>) | null = null;\n\n /** Snapshot for phase-2 metrics / logs (ids deferred at phase-1 `start()`). */\n private lastDeferredChannelConnectIds: string[] = [];\n private lastChannelConnectDeferMode: 'auto' | 'off' | 'explicit' = 'auto';\n private lastChannelConnectDeferSource: 'off' | 'explicit' | 'meta' = 'off';\n\n private readonly readiness = new GatewayReadiness();\n private startupTrace: GatewayStartupTrace | null = null;\n private workflowSessionBridge: WorkflowSessionBridge | null = null;\n private workflowRunServiceInstance: WorkflowRunService | null = null;\n private goalRunner: GoalRunner | null = null;\n private goalNotifications: GoalNotificationService | null = null;\n private mobileNotifications: MobileNotificationService | null = null;\n private connectorSupervisor: ConnectorSupervisor | null = null;\n private connectedKnowledgeCoordinator: ConnectedKnowledgeCoordinator | null = null;\n private stopAutomationProductEventBridge: (() => void) | null = null;\n private stopSessionTranscriptAutomationEvents: (() => void) | null = null;\n\n /**\n * Webchat agent invocation surface (`runAgent`, `abortAgentRun`, `steer*`,\n * `submitClarifyResponse`, clarify-bridge dispatch). Owns the\n * `activeWebchatRunBySession` + `runAbortControllers` maps.\n */\n readonly agentRunner: GatewayAgentRunner;\n\n /** Read-only alias re-exported from `agentRunner.runRelay` for legacy callers. */\n get runRelay(): AgentRunRelay { return this.agentRunner.runRelay; }\n\n /**\n * Session CRUD / search / compaction / tag-archive-pin / stats — the gateway\n * REST surface for sessions. Routes should depend on this narrow service\n * rather than the full GatewayService composition root.\n */\n readonly sessions: GatewaySessionsApi;\n\n /**\n * Skills + extensions marketplace surface (browse / install / uninstall) plus\n * local-only managed-skill ops. Routes depend on this narrow service.\n */\n readonly marketplace: GatewayMarketplaceService;\n\n /** First-class project grouping surface. */\n readonly projects: ProjectService;\n\n constructor(private serviceConfig: GatewayServiceConfig = {}) {\n this.bus = new MessageBus();\n this.configPath = serviceConfig.configPath || resolveConfigPath();\n runBootstrapMigrationsSync(this.configPath);\n this.config = loadConfig(this.configPath);\n let bootstrapConfigChanged = initializeVoiceDefaults(\n this.config,\n inferProductLanguageFromEnvironment(),\n );\n const starterResult = ensureStarterAgentsInitialized(this.config);\n if (starterResult.changed) {\n this.config = starterResult.config;\n bootstrapConfigChanged = true;\n }\n if (sanitizeTunnelConfig(this.config)) {\n bootstrapConfigChanged = true;\n }\n if (bootstrapConfigChanged) {\n void writeConfigToDisk(this.config, this.configPath).catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, phase: 'bootstrap_config_init', errorMessage: em }, `Bootstrap config persist failed: ${em}`);\n });\n }\n\n // Initialize authentication\n this.auth = resolveGatewayAuth({\n authConfig: this.config.gateway?.auth,\n });\n\n // Validate auth configuration\n assertGatewayAuthConfigured(this.auth);\n\n // Reject known weak / placeholder credentials at startup\n assertGatewayAuthNotKnownWeak(this.auth);\n\n const gatewayPort = this.getEffectiveListenPort();\n const runtimeConfig = assertGatewayRuntimeConfig({\n cfg: this.config,\n auth: this.auth,\n bindOverride: serviceConfig.listenBind,\n port: gatewayPort,\n });\n\n // Security audit: non-blocking warnings for remaining risk signals\n auditGatewayConfig({\n auth: this.auth,\n bindHost: runtimeConfig.bindHost,\n corsOrigins: runtimeConfig.corsOrigins,\n rateLimitEnabled: runtimeConfig.rateLimitEnabled,\n tlsEnabled: runtimeConfig.tlsEnabled,\n trustedProxies: this.config.gateway?.trustedProxies,\n allowRealIpFallback: this.config.gateway?.allowRealIpFallback === true,\n dangerouslyAllowHostHeaderOriginFallback: runtimeConfig.dangerouslyAllowHostHeaderOriginFallback,\n strictSecurityEnabled: isGatewayStrictSecurityEnabled(this.config),\n rateLimitConfigured: this.config.gateway?.auth?.rateLimit !== undefined,\n });\n\n // Log token info (not the token itself)\n if (this.auth.mode === 'token') {\n const tokenPreview = this.auth.token ? `${this.auth.token.slice(0, 4)}***` : 'none';\n log.info({ mode: this.auth.mode, token: tokenPreview }, 'Authentication configured');\n } else if (this.auth.mode === 'trusted-proxy') {\n log.info(\n {\n mode: this.auth.mode,\n userHeader: this.auth.trustedProxy?.userHeader,\n trustedProxyCount: this.config.gateway?.trustedProxies?.length ?? 0,\n },\n 'Trusted-proxy authentication configured',\n );\n } else {\n log.info({ mode: this.auth.mode }, 'Authentication configured');\n }\n\n // Initialize channel manager\n this.channelManager = new ChannelManager(this.config, this.bus);\n\n // Initialize extension loader (manifest snapshot only — code load in start()).\n this.workspacePath = getWorkspacePath(this.config) || './workspace';\n this.initializeExtensionLoader();\n\n // Session index + files shared with AgentService for chat transcript and goal execution context.\n this.sessionIndex = new SessionIndex({\n config: this.config,\n });\n\n this.automationService = new AutomationService();\n\n this.notesService = new NotesService(new NotesStore());\n\n this.projects = new ProjectService();\n\n this.agentRunner = new GatewayAgentRunner({\n bus: this.bus,\n sessionIndex: this.sessionIndex,\n getAgentService: () => this.ensureAgentService(),\n getChannelManager: () => this.channelManager,\n getConfig: () => this.config,\n emit: (type, payload) => this.sse.emit(type, payload),\n });\n\n this.sessions = new GatewaySessionsApi({\n sessionIndex: this.sessionIndex,\n getAgentService: () => this.ensureAgentService(),\n getActiveWebchatRunId: (sk) => this.agentRunner.getActiveRunId(sk),\n });\n\n this.marketplace = new GatewayMarketplaceService({\n getConfig: () => this.config,\n getAgentService: () => this.ensureAgentService(),\n getExtensionLoader: () => this.extensionLoader,\n getChannelManager: () => this.channelManager,\n getWorkspacePath: () => this.currentWorkspacePath,\n saveConfig: (cfg) => this.saveConfig(cfg),\n emit: (type, payload) => this.emit(type, payload),\n });\n\n this.configCoordinator = new GatewayConfigCoordinator({\n configPath: this.configPath,\n bus: this.bus,\n enableHotReload: this.serviceConfig.enableHotReload !== false,\n getConfig: () => this.config,\n setConfig: (next) => { this.config = next; },\n getAgentService: () => this.ensureAgentService(),\n getChannelManager: () => this.channelManager,\n getHeartbeatService: () => this.heartbeatService,\n getExtensionLoader: () => this.extensionLoader,\n reconcileBrowserExtensionServer: () => this.reconcileBrowserExtensionServer(),\n reconcileDreamingAutomations: () => this.reconcileDreamingAutomations(),\n getChannelsStatus: () => this.getChannelsStatus(),\n emit: (type, payload) => this.emit(type, payload),\n });\n }\n\n /** Lazy AgentService — constructed on first use or during `start()`. */\n get agentService(): AgentService {\n return this.ensureAgentService();\n }\n\n refreshActionTrustPolicy(): void {\n this._agentService?.refreshActionTrustPolicy();\n }\n\n refreshUserProfileContext(): void {\n this._agentService?.refreshUserProfileContext();\n }\n\n private ensureAgentService(): AgentService {\n if (this._agentService) {\n return this._agentService;\n }\n\n this._agentService = new AgentService(this.bus, {\n workspace: this.workspacePath,\n model: getAgentDefaultModelRef(this.config),\n config: this.config,\n sessionStore: this.sessionIndex.getStore(),\n onSessionMetadataUpdated: (sessionKey, patch) => {\n this.sessionIndex.emit('sessionUpdated', { key: sessionKey, name: patch?.name });\n this.emit('session.updated', { key: sessionKey, name: patch?.name });\n },\n onSessionTranscriptUpdated: (sessionKey) => {\n this.emit('session.transcript_updated', { key: sessionKey });\n },\n onGoalStatusUpdated: (payload) => {\n this.emit('goal.status.updated', payload);\n },\n onSkillsUpdated: (payload) => {\n this.emit('config.reload', {\n section: 'skills',\n source: payload.reason === 'disk' ? 'skills-filesystem' : 'skills-config',\n });\n },\n extensionRegistry: this.extensionLoader?.getRegistry(),\n getAutomationService: () => this.automationService,\n getNotesService: () => this.notesService,\n getProjectService: () => this.projects,\n getWorkItemService: () => new WorkItemService(),\n getWorkflowRunService: () => this.createWorkflowRunService(),\n sourceContextResolver: async (binding) => {\n if (binding.kind === 'note') {\n const note = await this.notesService.getNote(binding.sourceId);\n if (!note) return null;\n return buildNoteAgentContext({\n note,\n notesService: this.notesService,\n config: this.config,\n });\n }\n if (binding.kind === 'work_item') {\n const item = new WorkItemService().getWorkItem(binding.sourceId);\n return item ? await buildWorkItemAgentContext(item) : null;\n }\n return null;\n },\n gatewayClarify: {\n requestClarification: (sessionKey, request) =>\n this.agentRunner.requestClarification({\n sessionKey,\n request,\n publishSseFor: (_runId) => (e: RelayEvent) => {\n this._agentService!.turnDispatcher.enqueueWebchatSseEvent(sessionKey, e);\n },\n }),\n },\n });\n\n this._agentService.setChannelManager(this.channelManager);\n this.channelManager.setSessionModelHooks({\n getModelForSession: (sk) => this._agentService!.getModelForSession(sk),\n switchModelForSession: (sk, id) => this._agentService!.switchModelForSession(sk, id),\n });\n\n this.automationService.setDeps({\n agentService: this._agentService,\n getDefaultAgentId: () => getDefaultAgentId(this.config),\n getProjectWorkspaceRoot: (projectId) => this.projects.get(projectId)?.workspaceRoot,\n workflowRunService: this.createWorkflowRunService(),\n onRunCompleted: (run) => this.emit('automation.run.completed', { run }),\n });\n\n this._agentService.persistentGoals.setWebchatContinuationScheduler((sessionKey, message) => {\n const scheduleWhenIdle = () => {\n if (this._agentService!.getInboundTurnDepth(sessionKey) > 0) {\n setTimeout(scheduleWhenIdle, 50);\n return;\n }\n if (this.agentRunner.hasActiveRun(sessionKey)) {\n setTimeout(scheduleWhenIdle, 50);\n return;\n }\n void this.agentRunner.drainScheduledWebchatContinuation(sessionKey, message);\n };\n queueMicrotask(scheduleWhenIdle);\n });\n\n return this._agentService;\n }\n\n private ensureHeartbeatService(): HeartbeatService {\n if (this.heartbeatService) {\n return this.heartbeatService;\n }\n this.heartbeatService = new HeartbeatService({\n agentService: this.ensureAgentService(),\n messageBus: this.bus,\n sessionStore: this.sessionIndex.getStore(),\n getConfig: () => this.config,\n });\n return this.heartbeatService;\n }\n\n // ── Webchat agent runner (delegated to GatewayAgentRunner) ────────────\n\n private createGoalRunner(): GoalRunner {\n if (!this.goalRunner) {\n this.goalRunner = new GoalRunner({\n maxConcurrent: 1,\n defaultMaxRetries: 2,\n ensureSession: async (goal) => {\n const existing = goal.activeSessionKey?.trim();\n if (existing) return existing;\n const agentId = goal.agentId || getDefaultAgentId(this.config);\n const peerId = `goal-${sanitizeSegment(goal.id) || Date.now()}`;\n const sessionKey = buildSessionKey({\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId,\n });\n await this.sessionIndex.saveMessages(sessionKey, [], {\n metadata: {\n sourceChannel: 'webchat',\n sourceChatId: `default:direct:${peerId}`,\n sessionType: 'chat',\n routing: {\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId,\n },\n },\n });\n if (goal.projectId) {\n this.projects.attachSession(sessionKey, goal.projectId);\n }\n const { GoalService } = await import('../goals/index.js');\n new GoalService().attachSession(goal.id, sessionKey);\n return sessionKey;\n },\n hasActiveRun: (sessionKey) => this.agentRunner.hasActiveRun(sessionKey),\n runTurn: (sessionKey, userTurn) =>\n this.agentRunner.runScheduledWebchatTurn(sessionKey, userTurn),\n emit: (type, payload) => this.emit(type, payload),\n });\n }\n return this.goalRunner;\n }\n\n private createGoalNotificationService(): GoalNotificationService {\n if (!this.goalNotifications) {\n this.goalNotifications = new GoalNotificationService({\n getConfig: () => this.config,\n getSessionMetadata: (sessionKey) => this.sessionIndex.getSessionMetadata(sessionKey),\n send: async (target) => {\n await this.channelManager.send({\n channel: target.channel,\n chat_id: target.chatId,\n content: target.text,\n type: 'message',\n silent: target.silent,\n metadata: {\n accountId: target.accountId,\n threadId: target.threadId,\n source: 'goal-notification',\n },\n });\n },\n });\n }\n return this.goalNotifications;\n }\n\n private createMobileNotificationService(): MobileNotificationService {\n if (!this.mobileNotifications) {\n this.mobileNotifications = new MobileNotificationService();\n }\n return this.mobileNotifications;\n }\n\n enqueueGoalRun(goalId: string, options?: EnqueueGoalRunOptions) {\n return this.createGoalRunner().enqueue(goalId, options);\n }\n\n getGoalQueueSnapshot() {\n return this.createGoalRunner().snapshot();\n }\n\n runAgent(\n ...args: Parameters<GatewayAgentRunner['runAgent']>\n ): ReturnType<GatewayAgentRunner['runAgent']> {\n return this.agentRunner.runAgent(...args);\n }\n\n abortAgentRun(runId: string): boolean {\n return this.agentRunner.abortAgentRun(runId);\n }\n\n getActiveWebchatRunId(sessionKey: string): string | undefined {\n return this.agentRunner.getActiveRunId(sessionKey);\n }\n\n steerWebchatAgent(\n sessionKey: string,\n message: string,\n ): ReturnType<GatewayAgentRunner['steerWebchatAgent']> {\n return this.agentRunner.steerWebchatAgent(sessionKey, message);\n }\n\n submitClarifyResponse(requestId: string, answer: string): boolean {\n return this.agentRunner.submitClarifyResponse(requestId, answer);\n }\n\n private initializeExtensionLoader(): void {\n try {\n if (areExtensionsGloballyDisabled(this.config)) {\n log.info('Extensions globally disabled — skipping loader initialization');\n return;\n }\n\n const loaderOptions = {\n workspaceDir: this.workspacePath,\n extensionsDir: resolveExtensionsDir(),\n };\n this.extensionMetadataSnapshot = buildExtensionMetadataSnapshot(loaderOptions, this.config);\n this.extensionLoader = new ExtensionLoader(loaderOptions);\n this.extensionLoader.setManifestSnapshot(this.extensionMetadataSnapshot);\n this.extensionLoader.setConfig(this.config as Parameters<ExtensionLoader['setConfig']>[0]);\n } catch (error) {\n log.warn({ error }, 'Failed to initialize extension loader');\n }\n }\n\n private registerExtensionChannelPlugins(): void {\n if (!this.extensionLoader) {\n return;\n }\n const reg = this.extensionLoader.getRegistry();\n for (const plugin of reg.channelPlugins) {\n this.channelManager.registerPlugin(plugin);\n }\n }\n\n /**\n * Load extensions and register SDK / full ChannelPlugin instances with ChannelManager.\n */\n private async loadExtensionsAndRegisterChannels(): Promise<void> {\n if (!this.extensionLoader) {\n return;\n }\n try {\n await this.extensionLoader.loadByActivationPlan({ phase: 'startup' });\n this.registerExtensionChannelPlugins();\n const reg = this.extensionLoader.getRegistry();\n log.debug(\n {\n extensionRecords: reg.extensions.size,\n channelPlugins: reg.channelPlugins.length,\n },\n 'Startup-phase extensions loaded and channel plugins registered',\n );\n } catch (err) {\n log.warn({ err }, 'Failed to load startup-phase extensions');\n }\n }\n\n private findChannelContributionExtension(channelId: string): ManifestRegistryEntry | undefined {\n const normalized = channelId.trim().toLowerCase();\n const registry = this.extensionLoader?.getManifestRegistry();\n if (!registry) return undefined;\n return registry\n .getAllEntries()\n .find((entry) => Object.keys(entry.manifest.channelContributions ?? {}).some((id) => id.toLowerCase() === normalized));\n }\n\n async ensureChannelRuntimePlugin(channelId: string) {\n const existing = this.channelManager.getPlugin(channelId);\n if (existing) {\n await this.channelManager.initializeChannel(channelId);\n return this.channelManager.getPlugin(channelId);\n }\n\n if (!this.extensionLoader || areExtensionsGloballyDisabled(this.config)) {\n return undefined;\n }\n\n const entry = this.findChannelContributionExtension(channelId);\n if (!entry) {\n return undefined;\n }\n\n const extensionConfig: ResolvedExtensionConfig = {\n id: entry.id,\n name: entry.manifest.name || entry.id,\n source: entry.source,\n path: entry.path,\n enabled: true,\n config: {},\n };\n await this.extensionLoader.loadExtension(extensionConfig);\n this.registerExtensionChannelPlugins();\n const plugin = this.channelManager.getPlugin(channelId);\n if (!plugin) {\n return undefined;\n }\n await this.channelManager.initializeChannel(channelId);\n return this.channelManager.getPlugin(channelId);\n }\n\n private async loadDeferredExtensions(): Promise<void> {\n if (!this.extensionLoader) {\n return;\n }\n try {\n await this.extensionLoader.loadByActivationPlan({ phase: 'deferred' });\n this.registerExtensionChannelPlugins();\n log.debug('Deferred-phase extensions loaded');\n } catch (err) {\n log.warn({ err }, 'Failed to load deferred extensions');\n }\n }\n\n private schedulePostReadySidecars(): void {\n queueMicrotask(() => {\n void this.runPostReadySidecars();\n });\n }\n\n private async runPostReadySidecars(): Promise<void> {\n const trace = this.startupTrace;\n try {\n if (trace) {\n await trace.measure('sidecars.model-prewarm', () => prewarmModelRegistry());\n } else {\n await prewarmModelRegistry();\n }\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em, phase: 'sidecars.model_prewarm' }, `Model registry prewarm failed: ${em}`);\n }\n\n if (!this.extensionLoader || areExtensionsGloballyDisabled(this.config)) {\n return;\n }\n\n try {\n if (trace) {\n await trace.measure('extensions.deferred-load', () => this.loadDeferredExtensions());\n } else {\n await this.loadDeferredExtensions();\n }\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em, phase: 'extensions.deferred_load' }, `Deferred extension load failed: ${em}`);\n }\n }\n\n async start(): Promise<void> {\n if (this.running) return;\n\n setPairingBroadcastSink((type, payload) => {\n this.emit(type, payload);\n });\n\n log.debug('Starting gateway service...');\n openXopcDatabase();\n this.startTime = Date.now();\n this.running = true;\n prepareConfiguredLocalVoiceModel(this.config);\n this.startupTrace = createGatewayStartupTrace();\n this.readiness.markStarting(this.startTime);\n const trace = this.startupTrace;\n\n registerClarifyBridge(this.agentRunner.getClarifyBridge());\n\n this.ensureAgentService();\n\n this.channelManager.setOutboundHooks({\n runMessageSending: (to, content, channel) =>\n this.agentService.outboundCoordinator.invokeOutboundMessageSending(to, content, channel),\n runMessageSent: (to, content, success, error, channel) =>\n this.agentService.outboundCoordinator.invokeOutboundMessageSent(to, content, success, error, channel),\n });\n this.channelManager.enableOutboundPersistence(resolveAgentDir(this.config, getDefaultAgentId(this.config)));\n\n if (this.extensionLoader) {\n this.extensionLoader.setRuntimeContext({\n bus: this.bus,\n sessionManager: this.sessionIndex,\n scheduleWebchatContinuation: (sessionKey: string, continuationMessage: string) => {\n queueMicrotask(() => {\n void this.agentRunner.drainScheduledWebchatContinuation(sessionKey, continuationMessage);\n });\n },\n });\n }\n\n await trace.measure('extensions.load', () => this.loadExtensionsAndRegisterChannels());\n\n const skipChannels =\n process.env.XOPC_SKIP_CHANNELS === '1' ||\n process.env.XOPC_SKIP_CHANNELS === 'true' ||\n process.env.XOPC_SKIP_PROVIDERS === '1' ||\n process.env.XOPC_SKIP_PROVIDERS === 'true';\n\n // Start channels: init all; optional defer for meta.deferConnectUntilAfterListen (GatewayServer)\n const phase1StartedAt = performance.now();\n let channelInitMs = 0;\n let deferPlanMs = 0;\n let channelPhase1StartMs = 0;\n let replayOutboundMs: number | null = null;\n let deferConnect = new Set<string>();\n\n if (skipChannels) {\n log.info('Skipping channel startup (XOPC_SKIP_CHANNELS or XOPC_SKIP_PROVIDERS)');\n } else {\n const t0 = performance.now();\n await trace.measure('channels.initialize', () => this.channelManager.initialize());\n channelInitMs = performance.now() - t0;\n\n const t1 = performance.now();\n const deferResolution = resolveChannelConnectDeferSet({\n config: this.config,\n channelManager: this.channelManager,\n deferChannelConnectUntilAfterHttp: this.serviceConfig.deferChannelConnectUntilAfterHttp === true,\n });\n deferConnect = deferResolution.deferPluginIds;\n deferPlanMs = performance.now() - t1;\n this.lastDeferredChannelConnectIds = [...deferConnect];\n this.lastChannelConnectDeferMode = deferResolution.mode;\n this.lastChannelConnectDeferSource = deferResolution.source;\n\n if (deferConnect.size > 0) {\n log.info({ channels: [...deferConnect] }, 'Deferring channel outbound connect until HTTP listen');\n }\n\n const t2 = performance.now();\n await trace.measure('channels.start', () =>\n this.channelManager.start(\n deferConnect.size > 0 ? { deferConnectPluginIds: deferConnect } : undefined,\n ),\n );\n channelPhase1StartMs = performance.now() - t2;\n\n if (this.serviceConfig.deferChannelConnectUntilAfterHttp !== true) {\n const tr = performance.now();\n await trace.measure('channels.replay-outbound', () =>\n this.channelManager.replayPendingOutboundMessages(),\n );\n replayOutboundMs = performance.now() - tr;\n }\n }\n\n const channelStartupPhase1TotalMs = performance.now() - phase1StartedAt;\n const gwDeferMode = this.config.gateway?.channelConnectDeferMode ?? 'auto';\n const phase1Metrics: GatewayChannelStartupPhase1Metrics = {\n deferChannelConnectUntilAfterHttp: this.serviceConfig.deferChannelConnectUntilAfterHttp === true,\n channelConnectDeferMode: this.serviceConfig.deferChannelConnectUntilAfterHttp\n ? this.lastChannelConnectDeferMode\n : gwDeferMode,\n channelConnectDeferSource: this.lastChannelConnectDeferSource,\n deferredChannelIds: this.lastDeferredChannelConnectIds,\n deferredChannelCount: this.lastDeferredChannelConnectIds.length,\n channelInitMs: Math.round(channelInitMs),\n deferPlanMs: Math.round(deferPlanMs),\n channelPhase1StartMs: Math.round(channelPhase1StartMs),\n replayOutboundMs: replayOutboundMs === null ? null : Math.round(replayOutboundMs),\n channelStartupPhase1TotalMs: Math.round(channelStartupPhase1TotalMs),\n };\n log.info(\n { phase: 'gateway.channel_startup', stage: 'phase1', ...phase1Metrics },\n 'Gateway channel startup phase-1 complete',\n );\n\n // Initialize session manager\n await trace.measure('sessions.initialize', () => this.sessionIndex.initialize());\n log.debug('Session manager initialized');\n\n this.automationService.setDeps({\n agentService: this.agentService,\n getDefaultAgentId: () => getDefaultAgentId(this.config),\n workflowRunService: this.createWorkflowRunService(),\n onRunCompleted: (run) => this.emit('automation.run.completed', { run }),\n });\n this.startAutomationProductEventBridge();\n\n await trace.measure('workflows.reconcile', () => this.reconcileInterruptedWorkflowRuns());\n\n this.sessionIndex.on('sessionUpdated', (data: { key: string; name?: string; tags?: string[] }) => {\n this.emit('session.updated', { key: data.key, name: data.name, tags: data.tags });\n });\n\n await trace.measure('automations.initialize', () => this.automationService.initialize());\n await trace.measure('dreaming.reconcile', () => this.reconcileDreamingAutomations());\n\n await this.notesService.initialize();\n\n this.ensureHeartbeatService().start(heartbeatRunnerConfigFromConfig(this.config));\n\n this.connectorSupervisor = startConnectorSupervisor({\n getConfig: () => this.config,\n saveConfig: (cfg) => this.saveConfig(cfg),\n });\n this.connectedKnowledgeCoordinator = startConnectedKnowledgeCoordinator({\n resolvePipelineOptions: () => ({\n agentId: resolveDefaultAgentId(this.config),\n workspaceId: this.currentWorkspacePath,\n }),\n });\n\n void import('../browser/providers/browser-ext-install.js')\n .then(({ ensureBrowserExtensionOnStartup }) => ensureBrowserExtensionOnStartup(this.config))\n .catch((err) => log.warn({ err }, 'Browser extension artifact ensure failed'));\n\n // Start browser extension WS server if configured\n await trace.measure('browser-extension.start', () => this.startBrowserExtensionServerIfNeeded());\n\n // Start agent service (runs in background)\n this.agentService.start().catch((err) => {\n log.error({ err }, 'Agent service error');\n });\n\n // Outbound drain: after deferred channel connects when using HTTP lifecycle (avoid racing Telegram).\n if (this.serviceConfig.deferChannelConnectUntilAfterHttp !== true) {\n this.startOutboundProcessor().catch((err) => {\n log.error({ err }, 'Outbound processor error');\n });\n }\n\n // Setup config hot reload\n if (this.serviceConfig.enableHotReload !== false) {\n this.configCoordinator.startHotReloader();\n }\n\n this.stopGatewayUpdateCheck = scheduleGatewayUpdateCheck({\n config: this.config,\n onUpdateAvailableChange: (update) => {\n this.emit('update.available', update);\n },\n triggerInProcessRestart: () => this.triggerGatewayProcessRestart(),\n });\n\n wireTunnelEventsToGateway(this);\n\n // Drop orphan single-HTML site-share staging dirs left behind by a\n // process death between create and cleanup. Re-registers live ones into\n // the in-process map so post-restart revoke/expire still cleans them.\n void import('../share/share-auto.js')\n .then(({ runStagingSweep }) => runStagingSweep())\n .catch((err) => log.warn({ err }, 'Share staging sweep failed'));\n\n if (this.serviceConfig.deferChannelConnectUntilAfterHttp !== true) {\n this.markGatewayReady();\n } else {\n trace.mark('service.started-awaiting-http');\n }\n\n log.debug('Gateway service started');\n }\n\n /** Called when the HTTP listener is bound (before deferred channel work). */\n markHttpListening(): void {\n this.readiness.markHttpListening();\n this.startupTrace?.mark('http.listening');\n }\n\n isGatewayReady(): boolean {\n return this.readiness.isReady();\n }\n\n getGatewayReadiness(): GatewayReadinessSnapshot {\n return this.readiness.getSnapshot();\n }\n\n private async applyStartupReadyDelayForTesting(): Promise<void> {\n const raw = process.env.XOPC_GATEWAY_STARTUP_SLOW_MS?.trim();\n if (!raw) {\n return;\n }\n const delayMs = Number.parseInt(raw, 10);\n if (!Number.isFinite(delayMs) || delayMs <= 0) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n private markGatewayReady(): void {\n if (this.readiness.isReady()) {\n return;\n }\n this.readiness.markReady();\n this.startupTrace?.mark('ready');\n this.schedulePostReadySidecars();\n }\n\n /** After HTTP is listening: exposure auto-start (Tailscale, then FRP tunnel). */\n private async runExposureAutoStartIfConfigured(): Promise<void> {\n const port = this.getEffectiveListenPort();\n await getExposureManager().autoStart(this.config, port, this.getAuthToken());\n }\n\n /**\n * Called by `GatewayServer` when the HTTP listener is bound. Starts channels that\n * opted into `meta.deferConnectUntilAfterListen`, then replays outbound queue.\n */\n async onHttpListening(): Promise<void> {\n await this.applyStartupReadyDelayForTesting();\n this.markGatewayReady();\n\n await this.runExposureAutoStartIfConfigured();\n\n if (this.serviceConfig.deferChannelConnectUntilAfterHttp !== true) {\n return;\n }\n const listenStartedAt = performance.now();\n const trace = this.startupTrace;\n try {\n const tDef = performance.now();\n if (trace) {\n await trace.measure('channels.deferred-connect', () => this.channelManager.startDeferredConnects());\n } else {\n await this.channelManager.startDeferredConnects();\n }\n const channelPhase2DeferredMs = performance.now() - tDef;\n\n const tr = performance.now();\n if (trace) {\n await trace.measure('channels.replay-outbound', () =>\n this.channelManager.replayPendingOutboundMessages(),\n );\n } else {\n await this.channelManager.replayPendingOutboundMessages();\n }\n const replayOutboundMs = performance.now() - tr;\n\n this.startOutboundProcessor().catch((err) => {\n log.error({ err }, 'Outbound processor error');\n });\n this.emit('channels.status', { channels: this.getChannelsStatus() });\n\n const onHttpListeningTotalMs = performance.now() - listenStartedAt;\n const phase2Metrics: GatewayChannelStartupPhase2Metrics = {\n channelConnectDeferMode: this.lastChannelConnectDeferMode,\n channelConnectDeferSource: this.lastChannelConnectDeferSource,\n deferredChannelIds: this.lastDeferredChannelConnectIds,\n channelPhase2DeferredMs: Math.round(channelPhase2DeferredMs),\n replayOutboundMs: Math.round(replayOutboundMs),\n onHttpListeningTotalMs: Math.round(onHttpListeningTotalMs),\n };\n log.info(\n { phase: 'gateway.channel_startup', stage: 'phase2', ...phase2Metrics },\n 'Gateway channel startup phase-2 complete (HTTP listening)',\n );\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error(\n {\n err,\n errorMessage: em,\n phase: 'gateway.channel_startup',\n stage: 'phase2',\n deferredChannelIds: this.lastDeferredChannelConnectIds,\n elapsedMs: Math.round(performance.now() - listenStartedAt),\n },\n `Deferred channel startup after HTTP listen failed: ${em}`,\n );\n } finally {\n this.markGatewayReady();\n }\n }\n\n async stop(): Promise<void> {\n if (!this.running) return;\n\n setPairingBroadcastSink(null);\n\n log.debug('Stopping gateway service...');\n this.readiness.markStarting();\n\n await stopTailscaleExposure().catch((err) => {\n log.warn({ err }, 'Tailscale exposure shutdown failed');\n });\n\n if (this.stopGatewayUpdateCheck) {\n this.stopGatewayUpdateCheck();\n this.stopGatewayUpdateCheck = null;\n }\n\n await this.configCoordinator.stopHotReloader();\n\n // Stop heartbeat service\n this.heartbeatService?.stop();\n this.connectorSupervisor?.stop();\n this.connectorSupervisor = null;\n this.connectedKnowledgeCoordinator?.stop();\n this.connectedKnowledgeCoordinator = null;\n\n // Stop browser extension WS server (shared acquire/release with BrowserManager)\n if (this.browserExtensionRelease) {\n await this.browserExtensionRelease();\n this.browserExtensionRelease = null;\n }\n this.browserExtensionProvider = null;\n this.browserExtensionBindKey = null;\n\n registerClarifyBridge(null);\n this.agentRunner.disposeClarifyBridge();\n await disposeAllSessionMcpRuntimes().catch((err) => {\n log.warn({ err }, 'MCP runtime shutdown failed');\n });\n this._agentService?.stop();\n\n // Unblock `consumeOutbound()` / `consumeInbound()` waiters before stopping channels (CLI agent does the same).\n this.running = false;\n this.bus.shutdown();\n\n this.lastDeferredChannelConnectIds = [];\n this.lastChannelConnectDeferMode = 'auto';\n this.lastChannelConnectDeferSource = 'off';\n\n await this.channelManager.stop();\n\n await this.automationService.stop();\n this.stopAutomationProductEventBridge?.();\n this.stopAutomationProductEventBridge = null;\n this.stopSessionTranscriptAutomationEvents?.();\n this.stopSessionTranscriptAutomationEvents = null;\n\n // Flush notes to disk\n await this.notesService.flush();\n\n // Tear down rate-limit cleanup timers so the process can exit cleanly.\n buckets.destroyAll();\n\n closeXopcDatabase();\n\n log.debug('Gateway service stopped');\n }\n\n /** Start the browser extension WS server when backend is 'extension'. */\n private async startBrowserExtensionServerIfNeeded(): Promise<void> {\n await this.reconcileBrowserExtensionServer();\n }\n\n /** Release the gateway's hold on the shared extension bridge (does not restart). */\n async releaseBrowserExtensionBridge(): Promise<void> {\n if (!this.browserExtensionRelease) return;\n await this.browserExtensionRelease();\n this.browserExtensionRelease = null;\n this.browserExtensionProvider = null;\n this.browserExtensionBindKey = null;\n log.debug('Browser extension WS server released');\n }\n\n /**\n * Start/stop/rebind the Chrome extension bridge.\n * PATCH saves update config in memory without re-running gateway startup, so this must run on save too.\n */\n async reconcileBrowserExtensionServer(): Promise<void> {\n const { shouldRunExtensionBridgeServer } = await import('../browser/backend-from-config.js');\n const wantsExtension = shouldRunExtensionBridgeServer(this.config);\n\n if (!wantsExtension) {\n if (this.browserExtensionRelease) {\n await this.browserExtensionRelease();\n this.browserExtensionRelease = null;\n this.browserExtensionProvider = null;\n this.browserExtensionBindKey = null;\n log.debug('Browser extension WS server stopped (backend is not extension)');\n }\n return;\n }\n\n const port = 19820;\n const host = '127.0.0.1';\n const connectionTimeout = undefined;\n const commandTimeout = undefined;\n const bindKey = `${host}:${port}`;\n\n if (this.browserExtensionRelease && this.browserExtensionBindKey === bindKey) {\n return;\n }\n\n if (this.browserExtensionRelease) {\n await this.browserExtensionRelease();\n this.browserExtensionRelease = null;\n this.browserExtensionProvider = null;\n this.browserExtensionBindKey = null;\n }\n\n try {\n const { acquireExtensionBrowserServer } = await import('../browser/providers/extension-ws-acquire.js');\n const { provider, release } = await acquireExtensionBrowserServer({\n port,\n host,\n connectionTimeout,\n commandTimeout,\n });\n this.browserExtensionProvider = provider;\n this.browserExtensionRelease = release;\n this.browserExtensionBindKey = bindKey;\n log.info({ port, host }, 'Browser extension WS server started');\n } catch (err) {\n const code = err && typeof err === 'object' && 'code' in err ? (err as { code: unknown }).code : undefined;\n if (code === 'EADDRINUSE') {\n log.warn(\n {\n err,\n phase: 'browser_extension_ws',\n bindPort: port,\n bindHost: host,\n hint: 'Another process holds the browser extension bridge port 19820. Stop it before starting xopc.',\n },\n `Browser extension WS server port is already in use: ${host}:${port}`,\n );\n return;\n }\n\n log.error(\n { err, phase: 'browser_extension_ws' },\n `Failed to start browser extension WS server: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n /**\n * Start processing outbound messages and send through channels\n */\n private async startOutboundProcessor(): Promise<void> {\n log.debug('Starting outbound message processor');\n while (this.running) {\n try {\n const msg = await this.bus.consumeOutbound();\n await this.channelManager.send(msg);\n } catch (error) {\n if (error instanceof MessageBusShutdownError) {\n break;\n }\n const em = error instanceof Error ? error.message : String(error);\n log.error(\n { err: error, errorMessage: em, phase: 'outbound_consume' },\n `Outbound pipeline failed (will retry in 1s): ${em}`,\n );\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n }\n\n // ── Config persistence / hot reload (delegated to GatewayConfigCoordinator) ──\n\n reloadHeartbeatFromCurrentConfig(): void {\n this.configCoordinator.reloadHeartbeatFromCurrentConfig();\n }\n\n reloadConfig(): Promise<{ reloaded: boolean; error?: string }> {\n return this.configCoordinator.reloadConfig();\n }\n\n afterWeixinCredentialsPersisted(): Promise<void> {\n return this.configCoordinator.afterWeixinCredentialsPersisted();\n }\n\n afterFeishuCredentialsPersisted(): Promise<void> {\n return this.configCoordinator.afterFeishuCredentialsPersisted();\n }\n\n saveConfig(config: Config): Promise<{ saved: boolean; error?: string }> {\n return this.configCoordinator.saveConfig(config);\n }\n\n async syncVoiceLanguage(language: ProductLanguage): Promise<{\n applied: boolean;\n language: ProductLanguage;\n mode: 'auto' | 'manual';\n error?: string;\n }> {\n const mode = this.config.voice?.languageMode ?? 'auto';\n if (mode === 'manual') {\n return { applied: false, language, mode };\n }\n const changed = applyAutomaticVoiceLanguage(this.config, language);\n if (changed) {\n const saved = await this.configCoordinator.saveConfig(this.config);\n if (!saved.saved) {\n return { applied: false, language, mode, error: saved.error ?? 'Failed to save voice language' };\n }\n }\n prepareConfiguredLocalVoiceModel(this.config);\n return { applied: changed, language, mode };\n }\n\n setBundledExtensionActivationTarget(\n extensionId: string,\n wanted: boolean,\n ): Promise<{ ok: boolean; error?: string; requiresGatewayRestart: boolean }> {\n return this.configCoordinator.setBundledExtensionActivationTarget(extensionId, wanted);\n }\n\n updateConfig(updates: Partial<Config>): Promise<{ updated: boolean; error?: string }> {\n return this.configCoordinator.updateConfig(updates);\n }\n\n /**\n * Send message through a channel\n */\n async sendMessage(\n channel: string,\n chatId: string,\n content: string\n ): Promise<{ sent: boolean; messageId?: string }> {\n try {\n await this.channelManager.send({\n channel,\n chat_id: chatId,\n content,\n });\n const messageId = `msg_${Date.now()}`;\n this.emit('message.sent', { channel, chatId, messageId });\n return { sent: true, messageId };\n } catch (error) {\n log.error({ channel, chatId, error }, 'Failed to send message');\n throw error;\n }\n }\n\n /**\n * Get channel statuses\n */\n getChannelsStatus(): Array<{\n name: string;\n enabled: boolean;\n connected: boolean;\n }> {\n const runningChannels = new Set(this.channelManager.getRunningChannels());\n const channels = this.config.channels as Record<string, { enabled?: boolean } | undefined> | undefined;\n const catalog = this.extensionMetadataSnapshot\n ? buildChannelCatalogFromSnapshot(this.extensionMetadataSnapshot)\n : buildChannelCatalogForConfig(this.config);\n\n return catalog.entries.map((entry) => ({\n name: entry.id,\n enabled: channels?.[entry.id]?.enabled === true,\n connected: runningChannels.has(entry.id),\n }));\n }\n\n getRunningChannelIds(): string[] {\n return this.channelManager.getRunningChannels();\n }\n\n getChannelRuntimePlugin(channelId: string) {\n return this.channelManager.getPlugin(channelId);\n }\n\n async restartChannel(channelId: string): Promise<void> {\n await this.channelManager.stopChannel(channelId);\n await this.channelManager.startChannel(channelId);\n }\n\n /**\n * Hub metadata for gateway console (built-in registry + registered channel plugins).\n */\n getChannelsHubMeta(): Array<{\n id: string;\n label: string;\n description: string;\n manageable: boolean;\n order: number;\n }> {\n const catalog = this.extensionMetadataSnapshot\n ? buildChannelCatalogFromSnapshot(this.extensionMetadataSnapshot)\n : buildChannelCatalogForConfig(this.config);\n\n return catalog.entries.map((entry) => ({\n id: entry.id,\n label: entry.label,\n description: entry.description ?? '',\n manageable: true,\n order: entry.order,\n })).toSorted((a, b) => {\n if (a.order !== b.order) return a.order - b.order;\n return a.id.localeCompare(b.id);\n });\n }\n\n /**\n * Request an immediate heartbeat run (coalesced like interval/cron wakes).\n */\n requestHeartbeatNow(opts?: { reason?: string }): void {\n this.heartbeatService?.requestNow({ reason: opts?.reason ?? 'manual' });\n }\n\n /**\n * Register graceful shutdown used after spawning a replacement gateway process (foreground CLI server).\n */\n registerGatewayShutdownForRestart(handler: () => Promise<void>): void {\n this.gatewayShutdownForRestart = handler;\n }\n\n /**\n * Respawn the gateway process when supported (spawn + exit, supervisor exit, or disabled when XOPC_NO_RESPAWN).\n */\n triggerGatewayProcessRestart(): { ok: boolean; mode: string; message?: string } {\n const result = restartGatewayProcessWithFreshPid();\n if (result.mode === 'failed') {\n return { ok: false, mode: result.mode, message: result.detail ?? 'spawn failed' };\n }\n if (result.mode === 'disabled') {\n return {\n ok: false,\n mode: 'disabled',\n message:\n 'Process respawn is disabled (XOPC_NO_RESPAWN). Restart the gateway manually (e.g. xopc gateway restart).',\n };\n }\n const shutdown = this.gatewayShutdownForRestart;\n if (!shutdown) {\n return {\n ok: false,\n mode: result.mode,\n message: 'Gateway restart is not available in this process.',\n };\n }\n setImmediate(() => {\n void shutdown().finally(() => {\n process.exit(0);\n });\n });\n return { ok: true, mode: result.mode };\n }\n\n /**\n * Get health status\n */\n getHealth(): {\n status: string;\n service: string;\n version: string;\n uptime: number;\n ready: boolean;\n httpListening: boolean;\n startupDurationMs: number | null;\n channels: { running: number; total: number };\n configPath: string;\n logs?: {\n dir: string;\n errors24h: number;\n stats: Record<string, number>;\n };\n } {\n const runningChannels = this.channelManager.getRunningChannels();\n const allChannels = this.channelManager.getAllChannels();\n const logStats = getRuntimeLogStats();\n const readiness = this.readiness.getSnapshot();\n\n return {\n status: 'ok',\n service: 'xopc-gateway',\n version: PACKAGE_VERSION,\n uptime: Math.floor((Date.now() - this.startTime) / 1000),\n ready: readiness.ready,\n httpListening: readiness.httpListening,\n startupDurationMs: readiness.startupDurationMs,\n channels: {\n running: runningChannels.length,\n total: allChannels.length,\n },\n configPath: this.configPath,\n logs: {\n dir: getLogDir(),\n errors24h: logStats.errorsLast24h,\n stats: logStats.byLevel,\n },\n };\n }\n\n get isRunning(): boolean {\n return this.running;\n }\n\n /**\n * Get extension registry for external access (HTTP routes, gateway methods)\n */\n getExtensionRegistry() {\n return this.extensionLoader?.getRegistry();\n }\n\n /** Extension loader for discovery and frontend asset APIs (may be null if extensions failed to init). */\n getExtensionLoader(): ExtensionLoader | null {\n return this.extensionLoader;\n }\n\n /**\n * Get model registry for external access (HTTP routes)\n */\n getModelRegistry() {\n const { getModelRegistry } = require('../providers/index.js');\n return getModelRegistry();\n }\n\n /**\n * Invoke a gateway method registered by extensions\n */\n async invokeGatewayMethod(method: string, params: Record<string, unknown>): Promise<unknown> {\n const registry = this.getExtensionRegistry();\n if (!registry) {\n throw new Error('Extension registry not available');\n }\n\n const handler = registry.getGatewayMethod(method);\n if (!handler) {\n throw new Error(`Gateway method not found: ${method}`);\n }\n\n return await handler(params);\n }\n\n get currentConfig(): Config {\n return this.config;\n }\n\n get currentWorkspacePath(): string {\n return this.workspacePath;\n }\n\n get messageBusInstance(): MessageBus {\n return this.bus;\n }\n\n /** Effective HTTP listen port (CLI `--port` override or config default). */\n getEffectiveListenPort(): number {\n return resolveEffectiveGatewayPort(this.config, this.serviceConfig.listenPort);\n }\n\n get automationServiceInstance(): AutomationService {\n return this.automationService;\n }\n\n private async reconcileDreamingAutomations(): Promise<void> {\n await reconcileDreamingAutomationRecords({\n config: this.config,\n automationService: this.automationService,\n });\n }\n\n get notesServiceInstance(): NotesService {\n return this.notesService;\n }\n\n get sessionIndexInstance(): SessionIndex {\n return this.sessionIndex;\n }\n\n /** Shared workflow run orchestrator + session bridge (one instance per gateway). */\n createWorkflowRunService(): WorkflowRunService {\n if (!this.workflowRunServiceInstance) {\n this.workflowSessionBridge = new WorkflowSessionBridge(this);\n this.workflowRunServiceInstance = new WorkflowRunService({\n service: this,\n sessionBridge: this.workflowSessionBridge,\n buildChildTools: buildWorkflowChildTools,\n });\n }\n return this.workflowRunServiceInstance;\n }\n\n private async reconcileInterruptedWorkflowRuns(): Promise<void> {\n const workflowService = this.createWorkflowRunService();\n const agentIds = this.collectWorkflowAgentIds();\n let total = 0;\n for (const agentId of agentIds) {\n try {\n total += await workflowService.reconcileInterruptedRuns(agentId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, agentId, errorMessage: msg },\n `Workflow run reconcile failed for agent ${agentId}: ${msg}`,\n );\n }\n }\n if (total > 0) {\n log.info({ count: total, agentIds }, 'Reconciled interrupted workflow runs');\n }\n }\n\n private collectWorkflowAgentIds(): string[] {\n const ids = new Set<string>();\n ids.add(resolveDefaultAgentId(this.config));\n for (const entry of listAgentEntries(this.config)) {\n if (entry.enabled === false) continue;\n ids.add(normalizeAgentId(entry.id));\n }\n return [...ids];\n }\n\n /** Process a message directly through the agent (for CLI mode). */\n async processDirect(content: string, sessionKey = 'agent:main:main'): Promise<string> {\n return this.agentService.turnDispatcher.processDirect(content, sessionKey);\n }\n\n // ========== SSE Event System ==========\n\n subscribe(\n sessionId: string,\n listener: (event: ServiceEvent) => Promise<void> | void,\n ): () => void {\n return this.sse.subscribe(sessionId, listener);\n }\n\n emit(type: string, payload: unknown): void {\n this.sse.emit(type, payload);\n this.createGoalNotificationService().handleGatewayEvent(type, payload);\n this.createMobileNotificationService().handleGatewayEvent(type, payload);\n }\n\n private startAutomationProductEventBridge(): void {\n this.stopAutomationProductEventBridge?.();\n this.stopSessionTranscriptAutomationEvents?.();\n this.stopAutomationProductEventBridge = onAutomationProductEvent((event) => {\n void this.automationService.triggerEvent(event).catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, eventType: event.type, source: event.source }, `Automation product event failed: ${em}`);\n });\n });\n this.stopSessionTranscriptAutomationEvents = onSessionTranscriptUpdate((update) => {\n if (!update.sessionKey || update.sessionKey.includes(':automation:')) return;\n publishAutomationProductEvent({\n type: 'session.transcript.updated',\n source: 'sessions',\n payload: {\n sessionKey: update.sessionKey,\n messageId: update.messageId,\n hasMessage: update.message !== undefined,\n },\n });\n });\n }\n\n /** Replay events since `lastEventId` for SSE reconnection. */\n getEventsSince(sessionId: string, lastEventId: string): ServiceEvent[] {\n return this.sse.getEventsSince(sessionId, lastEventId);\n }\n\n /**\n * Validate authentication token from request headers.\n * Returns true if auth is disabled (mode: 'none') or token is valid.\n */\n validateAuth(headers?: Record<string, string | string[] | undefined>): boolean {\n const token = extractToken(headers);\n return validateToken(this.auth, token);\n }\n\n /**\n * Get current auth mode.\n */\n getAuthMode(): 'none' | 'token' | 'password' | 'trusted-proxy' {\n return this.auth.mode;\n }\n\n /** Resolved gateway auth (mode, credentials, trusted-proxy config). */\n getResolvedAuth(): ResolvedGatewayAuth {\n return this.auth;\n }\n\n /**\n * Get current auth token (for CLI server integration).\n * Returns undefined if mode is not token.\n */\n getAuthToken(): string | undefined {\n return this.auth.mode === 'token' ? this.auth.token : undefined;\n }\n\n /**\n * Refresh (regenerate) the gateway auth token.\n * Returns the new token.\n */\n async refreshAuthToken(): Promise<string> {\n if (this.auth.mode !== 'token') {\n throw new Error('Cannot refresh token: auth mode is not token');\n }\n\n // Generate new token\n const newToken = crypto.randomBytes(24).toString('hex');\n \n // Update in-memory auth\n this.auth.token = newToken;\n \n // Update config\n this.config = {\n ...this.config,\n gateway: {\n ...this.config.gateway,\n auth: {\n ...this.config.gateway?.auth,\n mode: 'token',\n token: newToken,\n },\n },\n };\n \n await this.saveConfig(this.config);\n\n log.info({ tokenPreview: `${newToken.slice(0, 8)}...` }, 'Gateway token refreshed');\n \n return newToken;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"service.js","names":["writeConfigToDisk","reconcileDreamingAutomationRecords"],"sources":["../../../src/gateway/service.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { listAgentEntries, normalizeAgentId, resolveDefaultAgentId } from '../agent/agent-scope.js';\nimport { AgentService } from '../agent/service.js';\nimport { ensureStarterAgentsInitialized } from '../agent/starter-agents.js';\nimport { ChannelManager } from '../channels/manager.js';\nimport {\n buildChannelCatalogForConfig,\n buildChannelCatalogFromSnapshot,\n} from '../channels/catalog/channel-catalog-service.js';\nimport { setPairingBroadcastSink } from '../channels/pairing/pairing-events.js';\nimport { MessageBus, MessageBusShutdownError } from '../infra/bus/index.js';\nimport { loadConfig, saveConfig as writeConfigToDisk } from '../config/index.js';\nimport { getWorkspacePath } from '../config/workspace-path-helpers.js';\nimport { AutomationService } from '../automations/index.js';\nimport { onAutomationProductEvent, publishAutomationProductEvent } from '../automations/product-events.js';\nimport { buildNoteAgentContext, NotesService, NotesStore } from '../notes/index.js';\nimport { buildWorkflowChildTools } from '../agent/workflow/workflow-child-tools.js';\nimport { WorkflowRunService } from '../workflows/service/workflow-run-service.js';\nimport { WorkflowSessionBridge } from '../workflows/service/workflow-session-bridge.js';\nimport { ExtensionLoader, areExtensionsGloballyDisabled, buildExtensionMetadataSnapshot } from '../extensions/index.js';\nimport type { ManifestRegistryEntry } from '../extensions/manifest-registry.js';\nimport type { ResolvedExtensionConfig } from '../extensions/types/index.js';\nimport { HeartbeatService, heartbeatRunnerConfigFromConfig } from './heartbeat/index.js';\nimport { SessionIndex } from '../session/index.js';\nimport { onSessionTranscriptUpdate } from '../session/transcript-events.js';\nimport type { Config } from '../config/schema.js';\nimport { getAgentDefaultModelRef } from '../config/schema.js';\nimport { wireTunnelEventsToGateway } from '../tunnel/gateway-lifecycle.js';\nimport {\n stopTailscaleExposure,\n} from './tailscale-lifecycle.js';\nimport { getExposureManager } from '../remote-access/exposure-manager.js';\nimport { sanitizeTunnelConfig } from '../tunnel/tunnel-config.js';\nimport { resolveGatewayAuth, assertGatewayAuthConfigured, validateToken, extractToken, type ResolvedGatewayAuth } from './auth.js';\nimport { assertGatewayAuthNotKnownWeak } from './security/known-weak-secrets.js';\nimport { auditGatewayConfig } from './security/audit.js';\nimport { assertGatewayRuntimeConfig } from './runtime-config.js';\nimport { resolveEffectiveGatewayPort } from './host.js';\nimport { buckets, isGatewayStrictSecurityEnabled } from './rate-limit/index.js';\nimport { prewarmModelRegistry } from '../providers/index.js';\nimport { runBootstrapMigrationsSync } from '../migrations/runner.js';\nimport { createLogger, getLogDir, getRuntimeLogStats } from '../utils/logger.js';\nimport {\n resolveConfigPath,\n resolveAgentDir,\n resolveExtensionsDir,\n} from '../config/paths.js';\nimport { AgentRunRelay, type RelayEvent } from './agent-run-relay.js';\nimport { registerClarifyBridge } from './clarify-runtime.js';\nimport { PACKAGE_VERSION } from '../package-version.js';\nimport { GoalNotificationService, GoalRunner, type EnqueueGoalRunOptions } from '../goals/index.js';\nimport { MobileNotificationService } from '../mobile/notification-service.js';\nimport { ProjectService } from '../projects/index.js';\nimport { LocalAppService } from '../local-apps/index.js';\nimport { buildWorkItemAgentContext, WorkItemService } from '../work-items/index.js';\n\nimport { disposeAllSessionMcpRuntimes } from '../agent/mcp/bundle-mcp-tools.js';\nimport { getDefaultAgentId } from '../routing/resolve-route.js';\nimport { buildSessionKey, sanitizeSegment } from '../routing/session-key.js';\nimport { scheduleGatewayUpdateCheck } from '../infra/update-startup.js';\nimport { resolveChannelConnectDeferSet } from './resolve-channel-connect-defer.js';\nimport { restartGatewayProcessWithFreshPid } from './respawn.js';\nimport { GatewaySessionsApi } from './service/sessions-api.js';\nimport { GatewayMarketplaceService } from './service/marketplace-service.js';\nimport { GatewayConfigCoordinator } from './service/config-coordinator.js';\nimport { GatewayAgentRunner } from './service/agent-runner.js';\nimport { GatewaySseHub } from './service/sse-hub.js';\nimport { reconcileDreamingAutomations as reconcileDreamingAutomationRecords } from './dreaming-automation-reconciler.js';\nimport type {\n GatewayChannelStartupPhase1Metrics,\n GatewayChannelStartupPhase2Metrics,\n GatewayServiceConfig,\n ServiceEvent,\n} from './service/types.js';\nimport {\n GatewayReadiness,\n type GatewayReadinessSnapshot,\n} from './startup-readiness.js';\nimport { createGatewayStartupTrace, type GatewayStartupTrace } from './startup-trace.js';\nimport { closeXopcDatabase, openXopcDatabase } from '../storage/sqlite/index.js';\nimport { startConnectorSupervisor, type ConnectorSupervisor } from '../connectors/supervisor.js';\nimport {\n applyAutomaticVoiceLanguage,\n inferProductLanguageFromEnvironment,\n initializeVoiceDefaults,\n prepareConfiguredLocalVoiceModel,\n type ProductLanguage,\n} from '../voice/language-profile.js';\nimport {\n startConnectedKnowledgeCoordinator,\n type ConnectedKnowledgeCoordinator,\n} from '../knowledge/index.js';\n\nexport type {\n GatewayChannelStartupPhase1Metrics,\n GatewayChannelStartupPhase2Metrics,\n GatewayServiceConfig,\n ServiceEvent,\n} from './service/types.js';\n\nconst log = createLogger('Gateway:Service');\n\nexport class GatewayService {\n private bus: MessageBus;\n private config: Config;\n private configPath: string;\n private _agentService: AgentService | null = null;\n private channelManager: ChannelManager;\n private automationService: AutomationService;\n private notesService: NotesService;\n private extensionLoader: ExtensionLoader | null = null;\n private extensionMetadataSnapshot: import('../extensions/extension-metadata-snapshot.js').ExtensionMetadataSnapshot | null = null;\n private browserExtensionProvider: import('../browser/providers/extension.js').ExtensionBrowserProvider | null = null;\n private browserExtensionRelease: (() => Promise<void>) | null = null;\n /** `${host}:${port}` when the gateway holds the extension bridge listener. */\n private browserExtensionBindKey: string | null = null;\n private heartbeatService: HeartbeatService | null = null;\n private sessionIndex: SessionIndex;\n private running = false;\n private startTime = Date.now();\n private workspacePath: string;\n private readonly configCoordinator: GatewayConfigCoordinator;\n\n // Authentication\n private auth: ResolvedGatewayAuth;\n\n private readonly sse = new GatewaySseHub();\n\n getConfig(): Config {\n return this.config;\n }\n\n private stopGatewayUpdateCheck: (() => void) | null = null;\n\n /** When set (e.g. by `GatewayServer`), `triggerGatewayProcessRestart` can stop HTTP then exit. */\n private gatewayShutdownForRestart: (() => Promise<void>) | null = null;\n\n /** Snapshot for phase-2 metrics / logs (ids deferred at phase-1 `start()`). */\n private lastDeferredChannelConnectIds: string[] = [];\n private lastChannelConnectDeferMode: 'auto' | 'off' | 'explicit' = 'auto';\n private lastChannelConnectDeferSource: 'off' | 'explicit' | 'meta' = 'off';\n\n private readonly readiness = new GatewayReadiness();\n private startupTrace: GatewayStartupTrace | null = null;\n private workflowSessionBridge: WorkflowSessionBridge | null = null;\n private workflowRunServiceInstance: WorkflowRunService | null = null;\n private goalRunner: GoalRunner | null = null;\n private goalNotifications: GoalNotificationService | null = null;\n private mobileNotifications: MobileNotificationService | null = null;\n private connectorSupervisor: ConnectorSupervisor | null = null;\n private connectedKnowledgeCoordinator: ConnectedKnowledgeCoordinator | null = null;\n private stopAutomationProductEventBridge: (() => void) | null = null;\n private stopSessionTranscriptAutomationEvents: (() => void) | null = null;\n\n /**\n * Webchat agent invocation surface (`runAgent`, `abortAgentRun`, `steer*`,\n * `submitClarifyResponse`, clarify-bridge dispatch). Owns the\n * `activeWebchatRunBySession` + `runAbortControllers` maps.\n */\n readonly agentRunner: GatewayAgentRunner;\n\n /** Read-only alias re-exported from `agentRunner.runRelay` for legacy callers. */\n get runRelay(): AgentRunRelay { return this.agentRunner.runRelay; }\n\n /**\n * Session CRUD / search / compaction / tag-archive-pin / stats — the gateway\n * REST surface for sessions. Routes should depend on this narrow service\n * rather than the full GatewayService composition root.\n */\n readonly sessions: GatewaySessionsApi;\n\n /**\n * Skills + extensions marketplace surface (browse / install / uninstall) plus\n * local-only managed-skill ops. Routes depend on this narrow service.\n */\n readonly marketplace: GatewayMarketplaceService;\n\n /** First-class project grouping surface. */\n readonly projects: ProjectService;\n\n /** Local user-created apps, their coder projects, previews, and installs. */\n readonly localApps: LocalAppService;\n\n constructor(private serviceConfig: GatewayServiceConfig = {}) {\n this.bus = new MessageBus();\n this.configPath = serviceConfig.configPath || resolveConfigPath();\n runBootstrapMigrationsSync(this.configPath);\n this.config = loadConfig(this.configPath);\n let bootstrapConfigChanged = initializeVoiceDefaults(\n this.config,\n inferProductLanguageFromEnvironment(),\n );\n const starterResult = ensureStarterAgentsInitialized(this.config);\n if (starterResult.changed) {\n this.config = starterResult.config;\n bootstrapConfigChanged = true;\n }\n if (sanitizeTunnelConfig(this.config)) {\n bootstrapConfigChanged = true;\n }\n if (bootstrapConfigChanged) {\n void writeConfigToDisk(this.config, this.configPath).catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, phase: 'bootstrap_config_init', errorMessage: em }, `Bootstrap config persist failed: ${em}`);\n });\n }\n\n // Initialize authentication\n this.auth = resolveGatewayAuth({\n authConfig: this.config.gateway?.auth,\n });\n\n // Validate auth configuration\n assertGatewayAuthConfigured(this.auth);\n\n // Reject known weak / placeholder credentials at startup\n assertGatewayAuthNotKnownWeak(this.auth);\n\n const gatewayPort = this.getEffectiveListenPort();\n const runtimeConfig = assertGatewayRuntimeConfig({\n cfg: this.config,\n auth: this.auth,\n bindOverride: serviceConfig.listenBind,\n port: gatewayPort,\n });\n\n // Security audit: non-blocking warnings for remaining risk signals\n auditGatewayConfig({\n auth: this.auth,\n bindHost: runtimeConfig.bindHost,\n corsOrigins: runtimeConfig.corsOrigins,\n rateLimitEnabled: runtimeConfig.rateLimitEnabled,\n tlsEnabled: runtimeConfig.tlsEnabled,\n trustedProxies: this.config.gateway?.trustedProxies,\n allowRealIpFallback: this.config.gateway?.allowRealIpFallback === true,\n dangerouslyAllowHostHeaderOriginFallback: runtimeConfig.dangerouslyAllowHostHeaderOriginFallback,\n strictSecurityEnabled: isGatewayStrictSecurityEnabled(this.config),\n rateLimitConfigured: this.config.gateway?.auth?.rateLimit !== undefined,\n });\n\n // Log token info (not the token itself)\n if (this.auth.mode === 'token') {\n const tokenPreview = this.auth.token ? `${this.auth.token.slice(0, 4)}***` : 'none';\n log.info({ mode: this.auth.mode, token: tokenPreview }, 'Authentication configured');\n } else if (this.auth.mode === 'trusted-proxy') {\n log.info(\n {\n mode: this.auth.mode,\n userHeader: this.auth.trustedProxy?.userHeader,\n trustedProxyCount: this.config.gateway?.trustedProxies?.length ?? 0,\n },\n 'Trusted-proxy authentication configured',\n );\n } else {\n log.info({ mode: this.auth.mode }, 'Authentication configured');\n }\n\n // Initialize channel manager\n this.channelManager = new ChannelManager(this.config, this.bus);\n\n // Initialize extension loader (manifest snapshot only — code load in start()).\n this.workspacePath = getWorkspacePath(this.config) || './workspace';\n this.initializeExtensionLoader();\n\n // Session index + files shared with AgentService for chat transcript and goal execution context.\n this.sessionIndex = new SessionIndex({\n config: this.config,\n });\n\n this.automationService = new AutomationService();\n\n this.notesService = new NotesService(new NotesStore());\n\n this.projects = new ProjectService();\n\n this.localApps = new LocalAppService({\n projects: this.projects,\n workspaceRoot: this.workspacePath,\n getConfig: () => this.config,\n saveConfig: (cfg) => this.saveConfig(cfg),\n getExtensionLoader: () => this.extensionLoader,\n emit: (type, payload) => this.emit(type, payload),\n });\n\n this.agentRunner = new GatewayAgentRunner({\n bus: this.bus,\n sessionIndex: this.sessionIndex,\n getAgentService: () => this.ensureAgentService(),\n getChannelManager: () => this.channelManager,\n getConfig: () => this.config,\n emit: (type, payload) => this.sse.emit(type, payload),\n });\n\n this.sessions = new GatewaySessionsApi({\n sessionIndex: this.sessionIndex,\n getAgentService: () => this.ensureAgentService(),\n getActiveWebchatRunId: (sk) => this.agentRunner.getActiveRunId(sk),\n });\n\n this.marketplace = new GatewayMarketplaceService({\n getConfig: () => this.config,\n getAgentService: () => this.ensureAgentService(),\n getExtensionLoader: () => this.extensionLoader,\n getChannelManager: () => this.channelManager,\n getWorkspacePath: () => this.currentWorkspacePath,\n saveConfig: (cfg) => this.saveConfig(cfg),\n emit: (type, payload) => this.emit(type, payload),\n });\n\n this.configCoordinator = new GatewayConfigCoordinator({\n configPath: this.configPath,\n bus: this.bus,\n enableHotReload: this.serviceConfig.enableHotReload !== false,\n getConfig: () => this.config,\n setConfig: (next) => { this.config = next; },\n getAgentService: () => this.ensureAgentService(),\n getChannelManager: () => this.channelManager,\n getHeartbeatService: () => this.heartbeatService,\n getExtensionLoader: () => this.extensionLoader,\n reconcileBrowserExtensionServer: () => this.reconcileBrowserExtensionServer(),\n reconcileDreamingAutomations: () => this.reconcileDreamingAutomations(),\n getChannelsStatus: () => this.getChannelsStatus(),\n emit: (type, payload) => this.emit(type, payload),\n });\n }\n\n /** Lazy AgentService — constructed on first use or during `start()`. */\n get agentService(): AgentService {\n return this.ensureAgentService();\n }\n\n refreshActionTrustPolicy(): void {\n this._agentService?.refreshActionTrustPolicy();\n }\n\n refreshUserProfileContext(): void {\n this._agentService?.refreshUserProfileContext();\n }\n\n private ensureAgentService(): AgentService {\n if (this._agentService) {\n return this._agentService;\n }\n\n this._agentService = new AgentService(this.bus, {\n workspace: this.workspacePath,\n model: getAgentDefaultModelRef(this.config),\n config: this.config,\n sessionStore: this.sessionIndex.getStore(),\n onSessionMetadataUpdated: (sessionKey, patch) => {\n this.sessionIndex.emit('sessionUpdated', { key: sessionKey, name: patch?.name });\n this.emit('session.updated', { key: sessionKey, name: patch?.name });\n },\n onSessionTranscriptUpdated: (sessionKey) => {\n this.emit('session.transcript_updated', { key: sessionKey });\n },\n onGoalStatusUpdated: (payload) => {\n this.emit('goal.status.updated', payload);\n },\n onSkillsUpdated: (payload) => {\n this.emit('config.reload', {\n section: 'skills',\n source: payload.reason === 'disk' ? 'skills-filesystem' : 'skills-config',\n });\n },\n extensionRegistry: this.extensionLoader?.getRegistry(),\n getAutomationService: () => this.automationService,\n getNotesService: () => this.notesService,\n getProjectService: () => this.projects,\n getWorkItemService: () => new WorkItemService(),\n getWorkflowRunService: () => this.createWorkflowRunService(),\n sourceContextResolver: async (binding) => {\n if (binding.kind === 'note') {\n const note = await this.notesService.getNote(binding.sourceId);\n if (!note) return null;\n return buildNoteAgentContext({\n note,\n notesService: this.notesService,\n config: this.config,\n });\n }\n if (binding.kind === 'work_item') {\n const item = new WorkItemService().getWorkItem(binding.sourceId);\n return item ? await buildWorkItemAgentContext(item) : null;\n }\n return null;\n },\n gatewayClarify: {\n requestClarification: (sessionKey, request) =>\n this.agentRunner.requestClarification({\n sessionKey,\n request,\n publishSseFor: (_runId) => (e: RelayEvent) => {\n this._agentService!.turnDispatcher.enqueueWebchatSseEvent(sessionKey, e);\n },\n }),\n },\n });\n\n this._agentService.setChannelManager(this.channelManager);\n this.channelManager.setSessionModelHooks({\n getModelForSession: (sk) => this._agentService!.getModelForSession(sk),\n switchModelForSession: (sk, id) => this._agentService!.switchModelForSession(sk, id),\n });\n\n this.automationService.setDeps({\n agentService: this._agentService,\n getDefaultAgentId: () => getDefaultAgentId(this.config),\n getProjectWorkspaceRoot: (projectId) => this.projects.get(projectId)?.workspaceRoot,\n workflowRunService: this.createWorkflowRunService(),\n onRunCompleted: (run) => this.emit('automation.run.completed', { run }),\n });\n\n this._agentService.persistentGoals.setWebchatContinuationScheduler((sessionKey, message) => {\n const scheduleWhenIdle = () => {\n if (this._agentService!.getInboundTurnDepth(sessionKey) > 0) {\n setTimeout(scheduleWhenIdle, 50);\n return;\n }\n if (this.agentRunner.hasActiveRun(sessionKey)) {\n setTimeout(scheduleWhenIdle, 50);\n return;\n }\n void this.agentRunner.drainScheduledWebchatContinuation(sessionKey, message);\n };\n queueMicrotask(scheduleWhenIdle);\n });\n\n return this._agentService;\n }\n\n private ensureHeartbeatService(): HeartbeatService {\n if (this.heartbeatService) {\n return this.heartbeatService;\n }\n this.heartbeatService = new HeartbeatService({\n agentService: this.ensureAgentService(),\n messageBus: this.bus,\n sessionStore: this.sessionIndex.getStore(),\n getConfig: () => this.config,\n });\n return this.heartbeatService;\n }\n\n // ── Webchat agent runner (delegated to GatewayAgentRunner) ────────────\n\n private createGoalRunner(): GoalRunner {\n if (!this.goalRunner) {\n this.goalRunner = new GoalRunner({\n maxConcurrent: 1,\n defaultMaxRetries: 2,\n ensureSession: async (goal) => {\n const existing = goal.activeSessionKey?.trim();\n if (existing) return existing;\n const agentId = goal.agentId || getDefaultAgentId(this.config);\n const peerId = `goal-${sanitizeSegment(goal.id) || Date.now()}`;\n const sessionKey = buildSessionKey({\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId,\n });\n await this.sessionIndex.saveMessages(sessionKey, [], {\n metadata: {\n sourceChannel: 'webchat',\n sourceChatId: `default:direct:${peerId}`,\n sessionType: 'chat',\n routing: {\n agentId,\n source: 'webchat',\n accountId: 'default',\n peerKind: 'direct',\n peerId,\n },\n },\n });\n if (goal.projectId) {\n this.projects.attachSession(sessionKey, goal.projectId);\n }\n const { GoalService } = await import('../goals/index.js');\n new GoalService().attachSession(goal.id, sessionKey);\n return sessionKey;\n },\n hasActiveRun: (sessionKey) => this.agentRunner.hasActiveRun(sessionKey),\n runTurn: (sessionKey, userTurn) =>\n this.agentRunner.runScheduledWebchatTurn(sessionKey, userTurn),\n emit: (type, payload) => this.emit(type, payload),\n });\n }\n return this.goalRunner;\n }\n\n private createGoalNotificationService(): GoalNotificationService {\n if (!this.goalNotifications) {\n this.goalNotifications = new GoalNotificationService({\n getConfig: () => this.config,\n getSessionMetadata: (sessionKey) => this.sessionIndex.getSessionMetadata(sessionKey),\n send: async (target) => {\n await this.channelManager.send({\n channel: target.channel,\n chat_id: target.chatId,\n content: target.text,\n type: 'message',\n silent: target.silent,\n metadata: {\n accountId: target.accountId,\n threadId: target.threadId,\n source: 'goal-notification',\n },\n });\n },\n });\n }\n return this.goalNotifications;\n }\n\n private createMobileNotificationService(): MobileNotificationService {\n if (!this.mobileNotifications) {\n this.mobileNotifications = new MobileNotificationService();\n }\n return this.mobileNotifications;\n }\n\n enqueueGoalRun(goalId: string, options?: EnqueueGoalRunOptions) {\n return this.createGoalRunner().enqueue(goalId, options);\n }\n\n getGoalQueueSnapshot() {\n return this.createGoalRunner().snapshot();\n }\n\n runAgent(\n ...args: Parameters<GatewayAgentRunner['runAgent']>\n ): ReturnType<GatewayAgentRunner['runAgent']> {\n return this.agentRunner.runAgent(...args);\n }\n\n abortAgentRun(runId: string): boolean {\n return this.agentRunner.abortAgentRun(runId);\n }\n\n getActiveWebchatRunId(sessionKey: string): string | undefined {\n return this.agentRunner.getActiveRunId(sessionKey);\n }\n\n steerWebchatAgent(\n sessionKey: string,\n message: string,\n ): ReturnType<GatewayAgentRunner['steerWebchatAgent']> {\n return this.agentRunner.steerWebchatAgent(sessionKey, message);\n }\n\n submitClarifyResponse(requestId: string, answer: string): boolean {\n return this.agentRunner.submitClarifyResponse(requestId, answer);\n }\n\n private initializeExtensionLoader(): void {\n try {\n if (areExtensionsGloballyDisabled(this.config)) {\n log.info('Extensions globally disabled — skipping loader initialization');\n return;\n }\n\n const loaderOptions = {\n workspaceDir: this.workspacePath,\n extensionsDir: resolveExtensionsDir(),\n };\n this.extensionMetadataSnapshot = buildExtensionMetadataSnapshot(loaderOptions, this.config);\n this.extensionLoader = new ExtensionLoader(loaderOptions);\n this.extensionLoader.setManifestSnapshot(this.extensionMetadataSnapshot);\n this.extensionLoader.setConfig(this.config as Parameters<ExtensionLoader['setConfig']>[0]);\n } catch (error) {\n log.warn({ error }, 'Failed to initialize extension loader');\n }\n }\n\n private registerExtensionChannelPlugins(): void {\n if (!this.extensionLoader) {\n return;\n }\n const reg = this.extensionLoader.getRegistry();\n for (const plugin of reg.channelPlugins) {\n this.channelManager.registerPlugin(plugin);\n }\n }\n\n /**\n * Load extensions and register SDK / full ChannelPlugin instances with ChannelManager.\n */\n private async loadExtensionsAndRegisterChannels(): Promise<void> {\n if (!this.extensionLoader) {\n return;\n }\n try {\n await this.extensionLoader.loadByActivationPlan({ phase: 'startup' });\n this.registerExtensionChannelPlugins();\n const reg = this.extensionLoader.getRegistry();\n log.debug(\n {\n extensionRecords: reg.extensions.size,\n channelPlugins: reg.channelPlugins.length,\n },\n 'Startup-phase extensions loaded and channel plugins registered',\n );\n } catch (err) {\n log.warn({ err }, 'Failed to load startup-phase extensions');\n }\n }\n\n private findChannelContributionExtension(channelId: string): ManifestRegistryEntry | undefined {\n const normalized = channelId.trim().toLowerCase();\n const registry = this.extensionLoader?.getManifestRegistry();\n if (!registry) return undefined;\n return registry\n .getAllEntries()\n .find((entry) => Object.keys(entry.manifest.channelContributions ?? {}).some((id) => id.toLowerCase() === normalized));\n }\n\n async ensureChannelRuntimePlugin(channelId: string) {\n const existing = this.channelManager.getPlugin(channelId);\n if (existing) {\n await this.channelManager.initializeChannel(channelId);\n return this.channelManager.getPlugin(channelId);\n }\n\n if (!this.extensionLoader || areExtensionsGloballyDisabled(this.config)) {\n return undefined;\n }\n\n const entry = this.findChannelContributionExtension(channelId);\n if (!entry) {\n return undefined;\n }\n\n const extensionConfig: ResolvedExtensionConfig = {\n id: entry.id,\n name: entry.manifest.name || entry.id,\n source: entry.source,\n path: entry.path,\n enabled: true,\n config: {},\n };\n await this.extensionLoader.loadExtension(extensionConfig);\n this.registerExtensionChannelPlugins();\n const plugin = this.channelManager.getPlugin(channelId);\n if (!plugin) {\n return undefined;\n }\n await this.channelManager.initializeChannel(channelId);\n return this.channelManager.getPlugin(channelId);\n }\n\n private async loadDeferredExtensions(): Promise<void> {\n if (!this.extensionLoader) {\n return;\n }\n try {\n await this.extensionLoader.loadByActivationPlan({ phase: 'deferred' });\n this.registerExtensionChannelPlugins();\n log.debug('Deferred-phase extensions loaded');\n } catch (err) {\n log.warn({ err }, 'Failed to load deferred extensions');\n }\n }\n\n private schedulePostReadySidecars(): void {\n queueMicrotask(() => {\n void this.runPostReadySidecars();\n });\n }\n\n private async runPostReadySidecars(): Promise<void> {\n const trace = this.startupTrace;\n try {\n if (trace) {\n await trace.measure('sidecars.model-prewarm', () => prewarmModelRegistry());\n } else {\n await prewarmModelRegistry();\n }\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em, phase: 'sidecars.model_prewarm' }, `Model registry prewarm failed: ${em}`);\n }\n\n if (!this.extensionLoader || areExtensionsGloballyDisabled(this.config)) {\n return;\n }\n\n try {\n if (trace) {\n await trace.measure('extensions.deferred-load', () => this.loadDeferredExtensions());\n } else {\n await this.loadDeferredExtensions();\n }\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, errorMessage: em, phase: 'extensions.deferred_load' }, `Deferred extension load failed: ${em}`);\n }\n }\n\n async start(): Promise<void> {\n if (this.running) return;\n\n setPairingBroadcastSink((type, payload) => {\n this.emit(type, payload);\n });\n\n log.debug('Starting gateway service...');\n openXopcDatabase();\n this.startTime = Date.now();\n this.running = true;\n prepareConfiguredLocalVoiceModel(this.config);\n this.startupTrace = createGatewayStartupTrace();\n this.readiness.markStarting(this.startTime);\n const trace = this.startupTrace;\n\n registerClarifyBridge(this.agentRunner.getClarifyBridge());\n\n this.ensureAgentService();\n\n this.channelManager.setOutboundHooks({\n runMessageSending: (to, content, channel) =>\n this.agentService.outboundCoordinator.invokeOutboundMessageSending(to, content, channel),\n runMessageSent: (to, content, success, error, channel) =>\n this.agentService.outboundCoordinator.invokeOutboundMessageSent(to, content, success, error, channel),\n });\n this.channelManager.enableOutboundPersistence(resolveAgentDir(this.config, getDefaultAgentId(this.config)));\n\n if (this.extensionLoader) {\n this.extensionLoader.setRuntimeContext({\n bus: this.bus,\n sessionManager: this.sessionIndex,\n scheduleWebchatContinuation: (sessionKey: string, continuationMessage: string) => {\n queueMicrotask(() => {\n void this.agentRunner.drainScheduledWebchatContinuation(sessionKey, continuationMessage);\n });\n },\n });\n }\n\n await trace.measure('extensions.load', () => this.loadExtensionsAndRegisterChannels());\n\n const skipChannels =\n process.env.XOPC_SKIP_CHANNELS === '1' ||\n process.env.XOPC_SKIP_CHANNELS === 'true' ||\n process.env.XOPC_SKIP_PROVIDERS === '1' ||\n process.env.XOPC_SKIP_PROVIDERS === 'true';\n\n // Start channels: init all; optional defer for meta.deferConnectUntilAfterListen (GatewayServer)\n const phase1StartedAt = performance.now();\n let channelInitMs = 0;\n let deferPlanMs = 0;\n let channelPhase1StartMs = 0;\n let replayOutboundMs: number | null = null;\n let deferConnect = new Set<string>();\n\n if (skipChannels) {\n log.info('Skipping channel startup (XOPC_SKIP_CHANNELS or XOPC_SKIP_PROVIDERS)');\n } else {\n const t0 = performance.now();\n await trace.measure('channels.initialize', () => this.channelManager.initialize());\n channelInitMs = performance.now() - t0;\n\n const t1 = performance.now();\n const deferResolution = resolveChannelConnectDeferSet({\n config: this.config,\n channelManager: this.channelManager,\n deferChannelConnectUntilAfterHttp: this.serviceConfig.deferChannelConnectUntilAfterHttp === true,\n });\n deferConnect = deferResolution.deferPluginIds;\n deferPlanMs = performance.now() - t1;\n this.lastDeferredChannelConnectIds = [...deferConnect];\n this.lastChannelConnectDeferMode = deferResolution.mode;\n this.lastChannelConnectDeferSource = deferResolution.source;\n\n if (deferConnect.size > 0) {\n log.info({ channels: [...deferConnect] }, 'Deferring channel outbound connect until HTTP listen');\n }\n\n const t2 = performance.now();\n await trace.measure('channels.start', () =>\n this.channelManager.start(\n deferConnect.size > 0 ? { deferConnectPluginIds: deferConnect } : undefined,\n ),\n );\n channelPhase1StartMs = performance.now() - t2;\n\n if (this.serviceConfig.deferChannelConnectUntilAfterHttp !== true) {\n const tr = performance.now();\n await trace.measure('channels.replay-outbound', () =>\n this.channelManager.replayPendingOutboundMessages(),\n );\n replayOutboundMs = performance.now() - tr;\n }\n }\n\n const channelStartupPhase1TotalMs = performance.now() - phase1StartedAt;\n const gwDeferMode = this.config.gateway?.channelConnectDeferMode ?? 'auto';\n const phase1Metrics: GatewayChannelStartupPhase1Metrics = {\n deferChannelConnectUntilAfterHttp: this.serviceConfig.deferChannelConnectUntilAfterHttp === true,\n channelConnectDeferMode: this.serviceConfig.deferChannelConnectUntilAfterHttp\n ? this.lastChannelConnectDeferMode\n : gwDeferMode,\n channelConnectDeferSource: this.lastChannelConnectDeferSource,\n deferredChannelIds: this.lastDeferredChannelConnectIds,\n deferredChannelCount: this.lastDeferredChannelConnectIds.length,\n channelInitMs: Math.round(channelInitMs),\n deferPlanMs: Math.round(deferPlanMs),\n channelPhase1StartMs: Math.round(channelPhase1StartMs),\n replayOutboundMs: replayOutboundMs === null ? null : Math.round(replayOutboundMs),\n channelStartupPhase1TotalMs: Math.round(channelStartupPhase1TotalMs),\n };\n log.info(\n { phase: 'gateway.channel_startup', stage: 'phase1', ...phase1Metrics },\n 'Gateway channel startup phase-1 complete',\n );\n\n // Initialize session manager\n await trace.measure('sessions.initialize', () => this.sessionIndex.initialize());\n log.debug('Session manager initialized');\n\n this.automationService.setDeps({\n agentService: this.agentService,\n getDefaultAgentId: () => getDefaultAgentId(this.config),\n workflowRunService: this.createWorkflowRunService(),\n onRunCompleted: (run) => this.emit('automation.run.completed', { run }),\n });\n this.startAutomationProductEventBridge();\n\n await trace.measure('workflows.reconcile', () => this.reconcileInterruptedWorkflowRuns());\n\n this.sessionIndex.on('sessionUpdated', (data: { key: string; name?: string; tags?: string[] }) => {\n this.emit('session.updated', { key: data.key, name: data.name, tags: data.tags });\n });\n\n await trace.measure('automations.initialize', () => this.automationService.initialize());\n await trace.measure('dreaming.reconcile', () => this.reconcileDreamingAutomations());\n\n await this.notesService.initialize();\n\n this.ensureHeartbeatService().start(heartbeatRunnerConfigFromConfig(this.config));\n\n this.connectorSupervisor = startConnectorSupervisor({\n getConfig: () => this.config,\n saveConfig: (cfg) => this.saveConfig(cfg),\n });\n this.connectedKnowledgeCoordinator = startConnectedKnowledgeCoordinator({\n resolvePipelineOptions: () => ({\n agentId: resolveDefaultAgentId(this.config),\n workspaceId: this.currentWorkspacePath,\n }),\n });\n\n void import('../browser/providers/browser-ext-install.js')\n .then(({ ensureBrowserExtensionOnStartup }) => ensureBrowserExtensionOnStartup(this.config))\n .catch((err) => log.warn({ err }, 'Browser extension artifact ensure failed'));\n\n // Start browser extension WS server if configured\n await trace.measure('browser-extension.start', () => this.startBrowserExtensionServerIfNeeded());\n\n // Start agent service (runs in background)\n this.agentService.start().catch((err) => {\n log.error({ err }, 'Agent service error');\n });\n\n // Outbound drain: after deferred channel connects when using HTTP lifecycle (avoid racing Telegram).\n if (this.serviceConfig.deferChannelConnectUntilAfterHttp !== true) {\n this.startOutboundProcessor().catch((err) => {\n log.error({ err }, 'Outbound processor error');\n });\n }\n\n // Setup config hot reload\n if (this.serviceConfig.enableHotReload !== false) {\n this.configCoordinator.startHotReloader();\n }\n\n this.stopGatewayUpdateCheck = scheduleGatewayUpdateCheck({\n config: this.config,\n onUpdateAvailableChange: (update) => {\n this.emit('update.available', update);\n },\n triggerInProcessRestart: () => this.triggerGatewayProcessRestart(),\n });\n\n wireTunnelEventsToGateway(this);\n\n // Drop orphan single-HTML site-share staging dirs left behind by a\n // process death between create and cleanup. Re-registers live ones into\n // the in-process map so post-restart revoke/expire still cleans them.\n void import('../share/share-auto.js')\n .then(({ runStagingSweep }) => runStagingSweep())\n .catch((err) => log.warn({ err }, 'Share staging sweep failed'));\n\n if (this.serviceConfig.deferChannelConnectUntilAfterHttp !== true) {\n this.markGatewayReady();\n } else {\n trace.mark('service.started-awaiting-http');\n }\n\n log.debug('Gateway service started');\n }\n\n /** Called when the HTTP listener is bound (before deferred channel work). */\n markHttpListening(): void {\n this.readiness.markHttpListening();\n this.startupTrace?.mark('http.listening');\n }\n\n isGatewayReady(): boolean {\n return this.readiness.isReady();\n }\n\n getGatewayReadiness(): GatewayReadinessSnapshot {\n return this.readiness.getSnapshot();\n }\n\n private async applyStartupReadyDelayForTesting(): Promise<void> {\n const raw = process.env.XOPC_GATEWAY_STARTUP_SLOW_MS?.trim();\n if (!raw) {\n return;\n }\n const delayMs = Number.parseInt(raw, 10);\n if (!Number.isFinite(delayMs) || delayMs <= 0) {\n return;\n }\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n\n private markGatewayReady(): void {\n if (this.readiness.isReady()) {\n return;\n }\n this.readiness.markReady();\n this.startupTrace?.mark('ready');\n this.schedulePostReadySidecars();\n }\n\n /** After HTTP is listening: exposure auto-start (Tailscale, then FRP tunnel). */\n private async runExposureAutoStartIfConfigured(): Promise<void> {\n const port = this.getEffectiveListenPort();\n await getExposureManager().autoStart(this.config, port, this.getAuthToken());\n }\n\n /**\n * Called by `GatewayServer` when the HTTP listener is bound. Starts channels that\n * opted into `meta.deferConnectUntilAfterListen`, then replays outbound queue.\n */\n async onHttpListening(): Promise<void> {\n await this.applyStartupReadyDelayForTesting();\n this.markGatewayReady();\n\n await this.runExposureAutoStartIfConfigured();\n\n if (this.serviceConfig.deferChannelConnectUntilAfterHttp !== true) {\n return;\n }\n const listenStartedAt = performance.now();\n const trace = this.startupTrace;\n try {\n const tDef = performance.now();\n if (trace) {\n await trace.measure('channels.deferred-connect', () => this.channelManager.startDeferredConnects());\n } else {\n await this.channelManager.startDeferredConnects();\n }\n const channelPhase2DeferredMs = performance.now() - tDef;\n\n const tr = performance.now();\n if (trace) {\n await trace.measure('channels.replay-outbound', () =>\n this.channelManager.replayPendingOutboundMessages(),\n );\n } else {\n await this.channelManager.replayPendingOutboundMessages();\n }\n const replayOutboundMs = performance.now() - tr;\n\n this.startOutboundProcessor().catch((err) => {\n log.error({ err }, 'Outbound processor error');\n });\n this.emit('channels.status', { channels: this.getChannelsStatus() });\n\n const onHttpListeningTotalMs = performance.now() - listenStartedAt;\n const phase2Metrics: GatewayChannelStartupPhase2Metrics = {\n channelConnectDeferMode: this.lastChannelConnectDeferMode,\n channelConnectDeferSource: this.lastChannelConnectDeferSource,\n deferredChannelIds: this.lastDeferredChannelConnectIds,\n channelPhase2DeferredMs: Math.round(channelPhase2DeferredMs),\n replayOutboundMs: Math.round(replayOutboundMs),\n onHttpListeningTotalMs: Math.round(onHttpListeningTotalMs),\n };\n log.info(\n { phase: 'gateway.channel_startup', stage: 'phase2', ...phase2Metrics },\n 'Gateway channel startup phase-2 complete (HTTP listening)',\n );\n } catch (err) {\n const em = err instanceof Error ? err.message : String(err);\n log.error(\n {\n err,\n errorMessage: em,\n phase: 'gateway.channel_startup',\n stage: 'phase2',\n deferredChannelIds: this.lastDeferredChannelConnectIds,\n elapsedMs: Math.round(performance.now() - listenStartedAt),\n },\n `Deferred channel startup after HTTP listen failed: ${em}`,\n );\n } finally {\n this.markGatewayReady();\n }\n }\n\n async stop(): Promise<void> {\n if (!this.running) return;\n\n setPairingBroadcastSink(null);\n\n log.debug('Stopping gateway service...');\n this.readiness.markStarting();\n\n await stopTailscaleExposure().catch((err) => {\n log.warn({ err }, 'Tailscale exposure shutdown failed');\n });\n\n if (this.stopGatewayUpdateCheck) {\n this.stopGatewayUpdateCheck();\n this.stopGatewayUpdateCheck = null;\n }\n\n await this.configCoordinator.stopHotReloader();\n\n // Stop heartbeat service\n this.heartbeatService?.stop();\n this.connectorSupervisor?.stop();\n this.connectorSupervisor = null;\n this.connectedKnowledgeCoordinator?.stop();\n this.connectedKnowledgeCoordinator = null;\n\n // Stop browser extension WS server (shared acquire/release with BrowserManager)\n if (this.browserExtensionRelease) {\n await this.browserExtensionRelease();\n this.browserExtensionRelease = null;\n }\n this.browserExtensionProvider = null;\n this.browserExtensionBindKey = null;\n\n registerClarifyBridge(null);\n this.agentRunner.disposeClarifyBridge();\n await disposeAllSessionMcpRuntimes().catch((err) => {\n log.warn({ err }, 'MCP runtime shutdown failed');\n });\n this._agentService?.stop();\n\n // Unblock `consumeOutbound()` / `consumeInbound()` waiters before stopping channels (CLI agent does the same).\n this.running = false;\n this.bus.shutdown();\n\n this.lastDeferredChannelConnectIds = [];\n this.lastChannelConnectDeferMode = 'auto';\n this.lastChannelConnectDeferSource = 'off';\n\n await this.channelManager.stop();\n\n await this.automationService.stop();\n this.stopAutomationProductEventBridge?.();\n this.stopAutomationProductEventBridge = null;\n this.stopSessionTranscriptAutomationEvents?.();\n this.stopSessionTranscriptAutomationEvents = null;\n\n // Flush notes to disk\n await this.notesService.flush();\n\n // Tear down rate-limit cleanup timers so the process can exit cleanly.\n buckets.destroyAll();\n\n closeXopcDatabase();\n\n log.debug('Gateway service stopped');\n }\n\n /** Start the browser extension WS server when backend is 'extension'. */\n private async startBrowserExtensionServerIfNeeded(): Promise<void> {\n await this.reconcileBrowserExtensionServer();\n }\n\n /** Release the gateway's hold on the shared extension bridge (does not restart). */\n async releaseBrowserExtensionBridge(): Promise<void> {\n if (!this.browserExtensionRelease) return;\n await this.browserExtensionRelease();\n this.browserExtensionRelease = null;\n this.browserExtensionProvider = null;\n this.browserExtensionBindKey = null;\n log.debug('Browser extension WS server released');\n }\n\n /**\n * Start/stop/rebind the Chrome extension bridge.\n * PATCH saves update config in memory without re-running gateway startup, so this must run on save too.\n */\n async reconcileBrowserExtensionServer(): Promise<void> {\n const { shouldRunExtensionBridgeServer } = await import('../browser/backend-from-config.js');\n const wantsExtension = shouldRunExtensionBridgeServer(this.config);\n\n if (!wantsExtension) {\n if (this.browserExtensionRelease) {\n await this.browserExtensionRelease();\n this.browserExtensionRelease = null;\n this.browserExtensionProvider = null;\n this.browserExtensionBindKey = null;\n log.debug('Browser extension WS server stopped (backend is not extension)');\n }\n return;\n }\n\n const port = 19820;\n const host = '127.0.0.1';\n const connectionTimeout = undefined;\n const commandTimeout = undefined;\n const bindKey = `${host}:${port}`;\n\n if (this.browserExtensionRelease && this.browserExtensionBindKey === bindKey) {\n return;\n }\n\n if (this.browserExtensionRelease) {\n await this.browserExtensionRelease();\n this.browserExtensionRelease = null;\n this.browserExtensionProvider = null;\n this.browserExtensionBindKey = null;\n }\n\n try {\n const { acquireExtensionBrowserServer } = await import('../browser/providers/extension-ws-acquire.js');\n const { provider, release } = await acquireExtensionBrowserServer({\n port,\n host,\n connectionTimeout,\n commandTimeout,\n });\n this.browserExtensionProvider = provider;\n this.browserExtensionRelease = release;\n this.browserExtensionBindKey = bindKey;\n log.info({ port, host }, 'Browser extension WS server started');\n } catch (err) {\n const code = err && typeof err === 'object' && 'code' in err ? (err as { code: unknown }).code : undefined;\n if (code === 'EADDRINUSE') {\n log.warn(\n {\n err,\n phase: 'browser_extension_ws',\n bindPort: port,\n bindHost: host,\n hint: 'Another process holds the browser extension bridge port 19820. Stop it before starting xopc.',\n },\n `Browser extension WS server port is already in use: ${host}:${port}`,\n );\n return;\n }\n\n log.error(\n { err, phase: 'browser_extension_ws' },\n `Failed to start browser extension WS server: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n /**\n * Start processing outbound messages and send through channels\n */\n private async startOutboundProcessor(): Promise<void> {\n log.debug('Starting outbound message processor');\n while (this.running) {\n try {\n const msg = await this.bus.consumeOutbound();\n await this.channelManager.send(msg);\n } catch (error) {\n if (error instanceof MessageBusShutdownError) {\n break;\n }\n const em = error instanceof Error ? error.message : String(error);\n log.error(\n { err: error, errorMessage: em, phase: 'outbound_consume' },\n `Outbound pipeline failed (will retry in 1s): ${em}`,\n );\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n }\n\n // ── Config persistence / hot reload (delegated to GatewayConfigCoordinator) ──\n\n reloadHeartbeatFromCurrentConfig(): void {\n this.configCoordinator.reloadHeartbeatFromCurrentConfig();\n }\n\n reloadConfig(): Promise<{ reloaded: boolean; error?: string }> {\n return this.configCoordinator.reloadConfig();\n }\n\n afterWeixinCredentialsPersisted(): Promise<void> {\n return this.configCoordinator.afterWeixinCredentialsPersisted();\n }\n\n afterFeishuCredentialsPersisted(): Promise<void> {\n return this.configCoordinator.afterFeishuCredentialsPersisted();\n }\n\n saveConfig(config: Config): Promise<{ saved: boolean; error?: string }> {\n return this.configCoordinator.saveConfig(config);\n }\n\n async syncVoiceLanguage(language: ProductLanguage): Promise<{\n applied: boolean;\n language: ProductLanguage;\n mode: 'auto' | 'manual';\n error?: string;\n }> {\n const mode = this.config.voice?.languageMode ?? 'auto';\n if (mode === 'manual') {\n return { applied: false, language, mode };\n }\n const changed = applyAutomaticVoiceLanguage(this.config, language);\n if (changed) {\n const saved = await this.configCoordinator.saveConfig(this.config);\n if (!saved.saved) {\n return { applied: false, language, mode, error: saved.error ?? 'Failed to save voice language' };\n }\n }\n prepareConfiguredLocalVoiceModel(this.config);\n return { applied: changed, language, mode };\n }\n\n setBundledExtensionActivationTarget(\n extensionId: string,\n wanted: boolean,\n ): Promise<{ ok: boolean; error?: string; requiresGatewayRestart: boolean }> {\n return this.configCoordinator.setBundledExtensionActivationTarget(extensionId, wanted);\n }\n\n updateConfig(updates: Partial<Config>): Promise<{ updated: boolean; error?: string }> {\n return this.configCoordinator.updateConfig(updates);\n }\n\n /**\n * Send message through a channel\n */\n async sendMessage(\n channel: string,\n chatId: string,\n content: string\n ): Promise<{ sent: boolean; messageId?: string }> {\n try {\n await this.channelManager.send({\n channel,\n chat_id: chatId,\n content,\n });\n const messageId = `msg_${Date.now()}`;\n this.emit('message.sent', { channel, chatId, messageId });\n return { sent: true, messageId };\n } catch (error) {\n log.error({ channel, chatId, error }, 'Failed to send message');\n throw error;\n }\n }\n\n /**\n * Get channel statuses\n */\n getChannelsStatus(): Array<{\n name: string;\n enabled: boolean;\n connected: boolean;\n }> {\n const runningChannels = new Set(this.channelManager.getRunningChannels());\n const channels = this.config.channels as Record<string, { enabled?: boolean } | undefined> | undefined;\n const catalog = this.extensionMetadataSnapshot\n ? buildChannelCatalogFromSnapshot(this.extensionMetadataSnapshot)\n : buildChannelCatalogForConfig(this.config);\n\n return catalog.entries.map((entry) => ({\n name: entry.id,\n enabled: channels?.[entry.id]?.enabled === true,\n connected: runningChannels.has(entry.id),\n }));\n }\n\n getRunningChannelIds(): string[] {\n return this.channelManager.getRunningChannels();\n }\n\n getChannelRuntimePlugin(channelId: string) {\n return this.channelManager.getPlugin(channelId);\n }\n\n async restartChannel(channelId: string): Promise<void> {\n await this.channelManager.stopChannel(channelId);\n await this.channelManager.startChannel(channelId);\n }\n\n /**\n * Hub metadata for gateway console (built-in registry + registered channel plugins).\n */\n getChannelsHubMeta(): Array<{\n id: string;\n label: string;\n description: string;\n manageable: boolean;\n order: number;\n }> {\n const catalog = this.extensionMetadataSnapshot\n ? buildChannelCatalogFromSnapshot(this.extensionMetadataSnapshot)\n : buildChannelCatalogForConfig(this.config);\n\n return catalog.entries.map((entry) => ({\n id: entry.id,\n label: entry.label,\n description: entry.description ?? '',\n manageable: true,\n order: entry.order,\n })).toSorted((a, b) => {\n if (a.order !== b.order) return a.order - b.order;\n return a.id.localeCompare(b.id);\n });\n }\n\n /**\n * Request an immediate heartbeat run (coalesced like interval/cron wakes).\n */\n requestHeartbeatNow(opts?: { reason?: string }): void {\n this.heartbeatService?.requestNow({ reason: opts?.reason ?? 'manual' });\n }\n\n /**\n * Register graceful shutdown used after spawning a replacement gateway process (foreground CLI server).\n */\n registerGatewayShutdownForRestart(handler: () => Promise<void>): void {\n this.gatewayShutdownForRestart = handler;\n }\n\n /**\n * Respawn the gateway process when supported (spawn + exit, supervisor exit, or disabled when XOPC_NO_RESPAWN).\n */\n triggerGatewayProcessRestart(): { ok: boolean; mode: string; message?: string } {\n const result = restartGatewayProcessWithFreshPid();\n if (result.mode === 'failed') {\n return { ok: false, mode: result.mode, message: result.detail ?? 'spawn failed' };\n }\n if (result.mode === 'disabled') {\n return {\n ok: false,\n mode: 'disabled',\n message:\n 'Process respawn is disabled (XOPC_NO_RESPAWN). Restart the gateway manually (e.g. xopc gateway restart).',\n };\n }\n const shutdown = this.gatewayShutdownForRestart;\n if (!shutdown) {\n return {\n ok: false,\n mode: result.mode,\n message: 'Gateway restart is not available in this process.',\n };\n }\n setImmediate(() => {\n void shutdown().finally(() => {\n process.exit(0);\n });\n });\n return { ok: true, mode: result.mode };\n }\n\n /**\n * Get health status\n */\n getHealth(): {\n status: string;\n service: string;\n version: string;\n uptime: number;\n ready: boolean;\n httpListening: boolean;\n startupDurationMs: number | null;\n channels: { running: number; total: number };\n configPath: string;\n logs?: {\n dir: string;\n errors24h: number;\n stats: Record<string, number>;\n };\n } {\n const runningChannels = this.channelManager.getRunningChannels();\n const allChannels = this.channelManager.getAllChannels();\n const logStats = getRuntimeLogStats();\n const readiness = this.readiness.getSnapshot();\n\n return {\n status: 'ok',\n service: 'xopc-gateway',\n version: PACKAGE_VERSION,\n uptime: Math.floor((Date.now() - this.startTime) / 1000),\n ready: readiness.ready,\n httpListening: readiness.httpListening,\n startupDurationMs: readiness.startupDurationMs,\n channels: {\n running: runningChannels.length,\n total: allChannels.length,\n },\n configPath: this.configPath,\n logs: {\n dir: getLogDir(),\n errors24h: logStats.errorsLast24h,\n stats: logStats.byLevel,\n },\n };\n }\n\n get isRunning(): boolean {\n return this.running;\n }\n\n /**\n * Get extension registry for external access (HTTP routes, gateway methods)\n */\n getExtensionRegistry() {\n return this.extensionLoader?.getRegistry();\n }\n\n /** Extension loader for discovery and frontend asset APIs (may be null if extensions failed to init). */\n getExtensionLoader(): ExtensionLoader | null {\n return this.extensionLoader;\n }\n\n /**\n * Get model registry for external access (HTTP routes)\n */\n getModelRegistry() {\n const { getModelRegistry } = require('../providers/index.js');\n return getModelRegistry();\n }\n\n /**\n * Invoke a gateway method registered by extensions\n */\n async invokeGatewayMethod(method: string, params: Record<string, unknown>): Promise<unknown> {\n const registry = this.getExtensionRegistry();\n if (!registry) {\n throw new Error('Extension registry not available');\n }\n\n const handler = registry.getGatewayMethod(method);\n if (!handler) {\n throw new Error(`Gateway method not found: ${method}`);\n }\n\n return await handler(params);\n }\n\n get currentConfig(): Config {\n return this.config;\n }\n\n get currentWorkspacePath(): string {\n return this.workspacePath;\n }\n\n get messageBusInstance(): MessageBus {\n return this.bus;\n }\n\n /** Effective HTTP listen port (CLI `--port` override or config default). */\n getEffectiveListenPort(): number {\n return resolveEffectiveGatewayPort(this.config, this.serviceConfig.listenPort);\n }\n\n get automationServiceInstance(): AutomationService {\n return this.automationService;\n }\n\n private async reconcileDreamingAutomations(): Promise<void> {\n await reconcileDreamingAutomationRecords({\n config: this.config,\n automationService: this.automationService,\n });\n }\n\n get notesServiceInstance(): NotesService {\n return this.notesService;\n }\n\n get sessionIndexInstance(): SessionIndex {\n return this.sessionIndex;\n }\n\n /** Shared workflow run orchestrator + session bridge (one instance per gateway). */\n createWorkflowRunService(): WorkflowRunService {\n if (!this.workflowRunServiceInstance) {\n this.workflowSessionBridge = new WorkflowSessionBridge(this);\n this.workflowRunServiceInstance = new WorkflowRunService({\n service: this,\n sessionBridge: this.workflowSessionBridge,\n buildChildTools: buildWorkflowChildTools,\n });\n }\n return this.workflowRunServiceInstance;\n }\n\n private async reconcileInterruptedWorkflowRuns(): Promise<void> {\n const workflowService = this.createWorkflowRunService();\n const agentIds = this.collectWorkflowAgentIds();\n let total = 0;\n for (const agentId of agentIds) {\n try {\n total += await workflowService.reconcileInterruptedRuns(agentId);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, agentId, errorMessage: msg },\n `Workflow run reconcile failed for agent ${agentId}: ${msg}`,\n );\n }\n }\n if (total > 0) {\n log.info({ count: total, agentIds }, 'Reconciled interrupted workflow runs');\n }\n }\n\n private collectWorkflowAgentIds(): string[] {\n const ids = new Set<string>();\n ids.add(resolveDefaultAgentId(this.config));\n for (const entry of listAgentEntries(this.config)) {\n if (entry.enabled === false) continue;\n ids.add(normalizeAgentId(entry.id));\n }\n return [...ids];\n }\n\n /** Process a message directly through the agent (for CLI mode). */\n async processDirect(content: string, sessionKey = 'agent:main:main'): Promise<string> {\n return this.agentService.turnDispatcher.processDirect(content, sessionKey);\n }\n\n // ========== SSE Event System ==========\n\n subscribe(\n sessionId: string,\n listener: (event: ServiceEvent) => Promise<void> | void,\n ): () => void {\n return this.sse.subscribe(sessionId, listener);\n }\n\n emit(type: string, payload: unknown): void {\n this.sse.emit(type, payload);\n this.createGoalNotificationService().handleGatewayEvent(type, payload);\n this.createMobileNotificationService().handleGatewayEvent(type, payload);\n }\n\n private startAutomationProductEventBridge(): void {\n this.stopAutomationProductEventBridge?.();\n this.stopSessionTranscriptAutomationEvents?.();\n this.stopAutomationProductEventBridge = onAutomationProductEvent((event) => {\n void this.automationService.triggerEvent(event).catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.warn({ err, eventType: event.type, source: event.source }, `Automation product event failed: ${em}`);\n });\n });\n this.stopSessionTranscriptAutomationEvents = onSessionTranscriptUpdate((update) => {\n if (!update.sessionKey || update.sessionKey.includes(':automation:')) return;\n publishAutomationProductEvent({\n type: 'session.transcript.updated',\n source: 'sessions',\n payload: {\n sessionKey: update.sessionKey,\n messageId: update.messageId,\n hasMessage: update.message !== undefined,\n },\n });\n });\n }\n\n /** Replay events since `lastEventId` for SSE reconnection. */\n getEventsSince(sessionId: string, lastEventId: string): ServiceEvent[] {\n return this.sse.getEventsSince(sessionId, lastEventId);\n }\n\n /**\n * Validate authentication token from request headers.\n * Returns true if auth is disabled (mode: 'none') or token is valid.\n */\n validateAuth(headers?: Record<string, string | string[] | undefined>): boolean {\n const token = extractToken(headers);\n return validateToken(this.auth, token);\n }\n\n /**\n * Get current auth mode.\n */\n getAuthMode(): 'none' | 'token' | 'password' | 'trusted-proxy' {\n return this.auth.mode;\n }\n\n /** Resolved gateway auth (mode, credentials, trusted-proxy config). */\n getResolvedAuth(): ResolvedGatewayAuth {\n return this.auth;\n }\n\n /**\n * Get current auth token (for CLI server integration).\n * Returns undefined if mode is not token.\n */\n getAuthToken(): string | undefined {\n return this.auth.mode === 'token' ? this.auth.token : undefined;\n }\n\n /**\n * Refresh (regenerate) the gateway auth token.\n * Returns the new token.\n */\n async refreshAuthToken(): Promise<string> {\n if (this.auth.mode !== 'token') {\n throw new Error('Cannot refresh token: auth mode is not token');\n }\n\n // Generate new token\n const newToken = crypto.randomBytes(24).toString('hex');\n \n // Update in-memory auth\n this.auth.token = newToken;\n \n // Update config\n this.config = {\n ...this.config,\n gateway: {\n ...this.config.gateway,\n auth: {\n ...this.config.gateway?.auth,\n mode: 'token',\n token: newToken,\n },\n },\n };\n \n await this.saveConfig(this.config);\n\n log.info({ tokenPreview: `${newToken.slice(0, 8)}...` }, 'Gateway token refreshed');\n \n return newToken;\n }\n}\n"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, shouldSilence, stripHeartbeatToken } from "./tokens.js";
2
+ import { appendCronEventLines } from "./event-prompt.js";
2
3
  import { isWithinActiveHours } from "./active-hours.js";
3
4
  import { isHeartbeatContentEmpty } from "./content-check.js";
4
- import { appendCronEventLines } from "./event-prompt.js";
5
5
  import { createHeartbeatWake } from "./wake.js";
6
6
  export { DEFAULT_ACK_MAX_CHARS, HEARTBEAT_OK, NO_REPLY, appendCronEventLines, createHeartbeatWake, isHeartbeatContentEmpty, isWithinActiveHours, shouldSilence, stripHeartbeatToken };
@@ -68,7 +68,7 @@ var ConnectedKnowledgePipeline = class {
68
68
  id: existing.id,
69
69
  providerId: "connected-knowledge",
70
70
  kind: existing.kind,
71
- agentId: existing.scope.agentId,
71
+ sourceAgentId: existing.provenance.sourceAgentId,
72
72
  workspaceId: existing.scope.workspaceId,
73
73
  content: existing.content,
74
74
  source: existing.source,
@@ -112,12 +112,13 @@ var ConnectedKnowledgePipeline = class {
112
112
  id: recordId,
113
113
  providerId: "connected-knowledge",
114
114
  kind: "workspace_fact",
115
- agentId: ownerAgentId(item, this.options.agentId),
115
+ sourceAgentId: ownerAgentId(item, this.options.agentId),
116
116
  workspaceId: ownerWorkspaceId(item, this.options.workspaceId),
117
117
  content,
118
118
  canonicalKey: `source-item:${item.sourceInstanceId}:${item.externalId}`,
119
119
  source: {
120
120
  provider: sourceProvider,
121
+ sourceInstanceId: item.sourceInstanceId,
121
122
  path: item.payloadRef
122
123
  },
123
124
  confidence: .78,
@@ -190,7 +191,7 @@ var ConnectedKnowledgePipeline = class {
190
191
  id: existing.id,
191
192
  providerId: "connected-knowledge",
192
193
  kind: existing.kind,
193
- agentId: existing.scope.agentId,
194
+ sourceAgentId: existing.provenance.sourceAgentId,
194
195
  workspaceId: existing.scope.workspaceId,
195
196
  content: existing.content,
196
197
  source: existing.source,
@@ -224,11 +225,14 @@ var ConnectedKnowledgePipeline = class {
224
225
  id: summaryRecordId(sourceInstanceId, day),
225
226
  providerId: "connected-knowledge",
226
227
  kind: "daily_note",
227
- agentId: ownerAgentId(items[0], this.options.agentId),
228
+ sourceAgentId: ownerAgentId(items[0], this.options.agentId),
228
229
  workspaceId: ownerWorkspaceId(items[0], this.options.workspaceId),
229
230
  content,
230
231
  canonicalKey: `source-day:${sourceInstanceId}:${day}`,
231
- source: { provider: sourceProvider },
232
+ source: {
233
+ provider: sourceProvider,
234
+ sourceInstanceId
235
+ },
232
236
  confidence: .72,
233
237
  tags: [
234
238
  "connected-source",
@@ -1 +1 @@
1
- {"version":3,"file":"connected-knowledge-pipeline.js","names":[],"sources":["../../../src/knowledge/connected-knowledge-pipeline.ts"],"sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\n\nimport {\n attachMemoryEvidence,\n claimKnowledgeSourceItems,\n completeKnowledgeSourceItemSynthesis,\n deleteMemoryEvidenceForRecord,\n getMemoryRecord,\n listKnowledgeSourceItems,\n upsertMemoryRecord,\n} from '../storage/sqlite/index.js';\nimport { createLogger } from '../utils/logger.js';\nimport type { KnowledgeSourceItem } from './types.js';\n\nconst log = createLogger('ConnectedKnowledge');\nconst MAX_ITEM_CHARS = 8_000;\nconst MAX_SUMMARY_CHARS = 6_000;\nconst MAX_SUMMARY_ITEMS = 24;\n\nexport type ConnectedKnowledgePipelineOptions = {\n agentId: string;\n workspaceId: string;\n workerId?: string;\n batchSize?: number;\n};\n\nexport type KnowledgeSynthesisBatchResult = {\n claimed: number;\n completed: number;\n ignored: number;\n failed: number;\n recordIds: string[];\n};\n\nfunction providerId(item: KnowledgeSourceItem): string {\n const connectorId = item.metadata.connectorId;\n if (typeof connectorId === 'string' && connectorId.trim()) return connectorId.trim();\n return item.sourceInstanceId.split(':')[0] || 'connected-source';\n}\n\nfunction ownerAgentId(item: KnowledgeSourceItem, fallback: string): string {\n const agentId = item.metadata.agentId;\n return typeof agentId === 'string' && agentId.trim() ? agentId.trim() : fallback;\n}\n\nfunction ownerWorkspaceId(item: KnowledgeSourceItem, fallback: string): string {\n const workspaceId = item.metadata.workspaceId;\n return typeof workspaceId === 'string' && workspaceId.trim() ? workspaceId.trim() : fallback;\n}\n\nfunction knowledgeRecordId(itemId: string): string {\n return `knowledge:${itemId}`;\n}\n\nfunction boundedText(item: KnowledgeSourceItem): string {\n const text = item.normalizedText?.trim() ?? '';\n return text.length > MAX_ITEM_CHARS ? `${text.slice(0, MAX_ITEM_CHARS)}\\n…` : text;\n}\n\nfunction dayFor(item: KnowledgeSourceItem): string {\n const timestamp = item.occurredAt ?? item.sourceUpdatedAt ?? item.updatedAt;\n return timestamp.slice(0, 10);\n}\n\nfunction summaryRecordId(sourceInstanceId: string, day: string): string {\n const key = createHash('sha256').update(`${sourceInstanceId}:${day}`).digest('hex').slice(0, 24);\n return `knowledge-summary:${key}`;\n}\n\nexport class ConnectedKnowledgePipeline {\n private readonly workerId: string;\n private readonly batchSize: number;\n\n constructor(private readonly options: ConnectedKnowledgePipelineOptions) {\n this.workerId = options.workerId ?? `connected-knowledge:${process.pid}:${randomUUID()}`;\n this.batchSize = Math.max(1, Math.min(100, options.batchSize ?? 20));\n }\n\n async processPending(sourceInstanceId?: string): Promise<KnowledgeSynthesisBatchResult> {\n const claimed = claimKnowledgeSourceItems({\n workerId: this.workerId,\n sourceInstanceId,\n synthesisPipeline: 'connected_knowledge',\n limit: this.batchSize,\n });\n const result: KnowledgeSynthesisBatchResult = {\n claimed: claimed.length,\n completed: 0,\n ignored: 0,\n failed: 0,\n recordIds: [],\n };\n const summaryKeys = new Set<string>();\n\n for (const item of claimed) {\n try {\n const recordId = knowledgeRecordId(item.id);\n const content = boundedText(item);\n if (item.deletedAt) {\n const existing = getMemoryRecord(recordId);\n if (existing) {\n upsertMemoryRecord({\n id: existing.id,\n providerId: 'connected-knowledge',\n kind: existing.kind,\n agentId: existing.scope.agentId,\n workspaceId: existing.scope.workspaceId,\n content: existing.content,\n source: existing.source,\n confidence: existing.confidence,\n tags: existing.tags,\n status: 'archived',\n sensitivity: existing.sensitivity,\n explicitness: existing.explicitness,\n durability: existing.durability,\n importance: existing.importance,\n disclosurePolicy: existing.disclosurePolicy,\n evidence: existing.evidence,\n validFrom: existing.validFrom,\n validTo: item.deletedAt,\n reviewAfter: existing.reviewAfter,\n expiresAt: existing.expiresAt,\n canonicalKey: existing.canonicalKey,\n supersedesRecordId: existing.supersedesRecordId,\n conflictGroupId: existing.conflictGroupId,\n });\n }\n completeKnowledgeSourceItemSynthesis({\n itemId: item.id,\n workerId: this.workerId,\n status: 'ignored',\n });\n result.ignored += 1;\n summaryKeys.add(`${item.sourceInstanceId}\\u0000${dayFor(item)}`);\n continue;\n }\n if (!content || item.sensitivity === 'secret' || item.sensitivity === 'regulated') {\n completeKnowledgeSourceItemSynthesis({\n itemId: item.id,\n workerId: this.workerId,\n status: 'ignored',\n });\n result.ignored += 1;\n continue;\n }\n\n const sourceProvider = providerId(item);\n const record = upsertMemoryRecord({\n id: recordId,\n providerId: 'connected-knowledge',\n kind: 'workspace_fact',\n agentId: ownerAgentId(item, this.options.agentId),\n workspaceId: ownerWorkspaceId(item, this.options.workspaceId),\n content,\n canonicalKey: `source-item:${item.sourceInstanceId}:${item.externalId}`,\n source: { provider: sourceProvider, path: item.payloadRef },\n confidence: 0.78,\n tags: ['connected-source', 'external', sourceProvider, item.itemType],\n status: 'active',\n sensitivity: item.sensitivity,\n explicitness: 'observed',\n durability: item.retentionClass === 'durable' ? 'durable' : 'recurring',\n importance: 0.5,\n disclosurePolicy: 'referenceable',\n evidence: [{\n sourceItemId: item.id,\n relation: 'derived_from',\n sourceText: content.slice(0, 1_000),\n confidence: 0.78,\n observedAt: item.occurredAt ?? item.sourceUpdatedAt,\n }],\n validFrom: item.occurredAt ?? item.sourceUpdatedAt,\n });\n attachMemoryEvidence({\n recordId: record.id,\n sourceItemId: item.id,\n relation: 'derived_from',\n excerpt: content.slice(0, 1_000),\n confidence: 0.78,\n observedAt: item.occurredAt ?? item.sourceUpdatedAt,\n });\n completeKnowledgeSourceItemSynthesis({\n itemId: item.id,\n workerId: this.workerId,\n status: 'completed',\n });\n result.completed += 1;\n result.recordIds.push(record.id);\n summaryKeys.add(`${item.sourceInstanceId}\\u0000${dayFor(item)}`);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n completeKnowledgeSourceItemSynthesis({\n itemId: item.id,\n workerId: this.workerId,\n status: 'failed',\n error: errorMessage.slice(0, 1_000),\n });\n result.failed += 1;\n log.warn(\n { err, itemId: item.id, sourceInstanceId: item.sourceInstanceId },\n `Connected knowledge synthesis failed: ${errorMessage}`,\n );\n }\n }\n\n for (const key of summaryKeys) {\n const [sourceInstanceId, day] = key.split('\\u0000');\n if (sourceInstanceId && day) this.rebuildDailySummary(sourceInstanceId, day);\n }\n return result;\n }\n\n private rebuildDailySummary(sourceInstanceId: string, day: string): void {\n const items = listKnowledgeSourceItems({ sourceInstanceId, limit: 500 })\n .filter((item) => dayFor(item) === day && item.synthesisStatus === 'completed')\n .slice(0, MAX_SUMMARY_ITEMS);\n if (items.length === 0) {\n const existing = getMemoryRecord(summaryRecordId(sourceInstanceId, day));\n if (existing) {\n upsertMemoryRecord({\n id: existing.id,\n providerId: 'connected-knowledge',\n kind: existing.kind,\n agentId: existing.scope.agentId,\n workspaceId: existing.scope.workspaceId,\n content: existing.content,\n source: existing.source,\n confidence: existing.confidence,\n tags: existing.tags,\n status: 'archived',\n sensitivity: existing.sensitivity,\n explicitness: existing.explicitness,\n durability: existing.durability,\n importance: existing.importance,\n disclosurePolicy: existing.disclosurePolicy,\n evidence: existing.evidence,\n validFrom: existing.validFrom,\n validTo: new Date().toISOString(),\n reviewAfter: existing.reviewAfter,\n expiresAt: existing.expiresAt,\n canonicalKey: existing.canonicalKey,\n });\n }\n return;\n }\n const sourceProvider = providerId(items[0]!);\n const lines = [`# ${sourceProvider} updates for ${day}`, ''];\n for (const item of items) {\n const text = boundedText(item).replace(/\\s+/g, ' ').trim();\n if (!text) continue;\n lines.push(`- ${text.slice(0, 360)}`);\n if (lines.join('\\n').length >= MAX_SUMMARY_CHARS) break;\n }\n const content = lines.join('\\n').slice(0, MAX_SUMMARY_CHARS);\n const summary = upsertMemoryRecord({\n id: summaryRecordId(sourceInstanceId, day),\n providerId: 'connected-knowledge',\n kind: 'daily_note',\n agentId: ownerAgentId(items[0]!, this.options.agentId),\n workspaceId: ownerWorkspaceId(items[0]!, this.options.workspaceId),\n content,\n canonicalKey: `source-day:${sourceInstanceId}:${day}`,\n source: { provider: sourceProvider },\n confidence: 0.72,\n tags: ['connected-source', 'source-day-summary', sourceProvider],\n status: 'active',\n sensitivity: items.some((item) => item.sensitivity === 'personal') ? 'personal' : 'normal',\n explicitness: 'observed',\n durability: 'recurring',\n importance: 0.55,\n disclosurePolicy: 'referenceable',\n evidence: items.map((item) => ({\n sourceItemId: item.id,\n relation: 'derived_from' as const,\n sourceText: boundedText(item).slice(0, 500),\n confidence: 0.72,\n observedAt: item.occurredAt ?? item.sourceUpdatedAt,\n })),\n validFrom: `${day}T00:00:00.000Z`,\n });\n deleteMemoryEvidenceForRecord(summary.id, 'derived_from');\n for (const item of items) {\n attachMemoryEvidence({\n recordId: summary.id,\n sourceItemId: item.id,\n relation: 'derived_from',\n excerpt: boundedText(item).slice(0, 500),\n confidence: 0.72,\n observedAt: item.occurredAt ?? item.sourceUpdatedAt,\n });\n }\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"connected-knowledge-pipeline.js","names":[],"sources":["../../../src/knowledge/connected-knowledge-pipeline.ts"],"sourcesContent":["import { createHash, randomUUID } from 'node:crypto';\n\nimport {\n attachMemoryEvidence,\n claimKnowledgeSourceItems,\n completeKnowledgeSourceItemSynthesis,\n deleteMemoryEvidenceForRecord,\n getMemoryRecord,\n listKnowledgeSourceItems,\n upsertMemoryRecord,\n} from '../storage/sqlite/index.js';\nimport { createLogger } from '../utils/logger.js';\nimport type { KnowledgeSourceItem } from './types.js';\n\nconst log = createLogger('ConnectedKnowledge');\nconst MAX_ITEM_CHARS = 8_000;\nconst MAX_SUMMARY_CHARS = 6_000;\nconst MAX_SUMMARY_ITEMS = 24;\n\nexport type ConnectedKnowledgePipelineOptions = {\n agentId: string;\n workspaceId: string;\n workerId?: string;\n batchSize?: number;\n};\n\nexport type KnowledgeSynthesisBatchResult = {\n claimed: number;\n completed: number;\n ignored: number;\n failed: number;\n recordIds: string[];\n};\n\nfunction providerId(item: KnowledgeSourceItem): string {\n const connectorId = item.metadata.connectorId;\n if (typeof connectorId === 'string' && connectorId.trim()) return connectorId.trim();\n return item.sourceInstanceId.split(':')[0] || 'connected-source';\n}\n\nfunction ownerAgentId(item: KnowledgeSourceItem, fallback: string): string {\n const agentId = item.metadata.agentId;\n return typeof agentId === 'string' && agentId.trim() ? agentId.trim() : fallback;\n}\n\nfunction ownerWorkspaceId(item: KnowledgeSourceItem, fallback: string): string {\n const workspaceId = item.metadata.workspaceId;\n return typeof workspaceId === 'string' && workspaceId.trim() ? workspaceId.trim() : fallback;\n}\n\nfunction knowledgeRecordId(itemId: string): string {\n return `knowledge:${itemId}`;\n}\n\nfunction boundedText(item: KnowledgeSourceItem): string {\n const text = item.normalizedText?.trim() ?? '';\n return text.length > MAX_ITEM_CHARS ? `${text.slice(0, MAX_ITEM_CHARS)}\\n…` : text;\n}\n\nfunction dayFor(item: KnowledgeSourceItem): string {\n const timestamp = item.occurredAt ?? item.sourceUpdatedAt ?? item.updatedAt;\n return timestamp.slice(0, 10);\n}\n\nfunction summaryRecordId(sourceInstanceId: string, day: string): string {\n const key = createHash('sha256').update(`${sourceInstanceId}:${day}`).digest('hex').slice(0, 24);\n return `knowledge-summary:${key}`;\n}\n\nexport class ConnectedKnowledgePipeline {\n private readonly workerId: string;\n private readonly batchSize: number;\n\n constructor(private readonly options: ConnectedKnowledgePipelineOptions) {\n this.workerId = options.workerId ?? `connected-knowledge:${process.pid}:${randomUUID()}`;\n this.batchSize = Math.max(1, Math.min(100, options.batchSize ?? 20));\n }\n\n async processPending(sourceInstanceId?: string): Promise<KnowledgeSynthesisBatchResult> {\n const claimed = claimKnowledgeSourceItems({\n workerId: this.workerId,\n sourceInstanceId,\n synthesisPipeline: 'connected_knowledge',\n limit: this.batchSize,\n });\n const result: KnowledgeSynthesisBatchResult = {\n claimed: claimed.length,\n completed: 0,\n ignored: 0,\n failed: 0,\n recordIds: [],\n };\n const summaryKeys = new Set<string>();\n\n for (const item of claimed) {\n try {\n const recordId = knowledgeRecordId(item.id);\n const content = boundedText(item);\n if (item.deletedAt) {\n const existing = getMemoryRecord(recordId);\n if (existing) {\n upsertMemoryRecord({\n id: existing.id,\n providerId: 'connected-knowledge',\n kind: existing.kind,\n sourceAgentId: existing.provenance.sourceAgentId,\n workspaceId: existing.scope.workspaceId,\n content: existing.content,\n source: existing.source,\n confidence: existing.confidence,\n tags: existing.tags,\n status: 'archived',\n sensitivity: existing.sensitivity,\n explicitness: existing.explicitness,\n durability: existing.durability,\n importance: existing.importance,\n disclosurePolicy: existing.disclosurePolicy,\n evidence: existing.evidence,\n validFrom: existing.validFrom,\n validTo: item.deletedAt,\n reviewAfter: existing.reviewAfter,\n expiresAt: existing.expiresAt,\n canonicalKey: existing.canonicalKey,\n supersedesRecordId: existing.supersedesRecordId,\n conflictGroupId: existing.conflictGroupId,\n });\n }\n completeKnowledgeSourceItemSynthesis({\n itemId: item.id,\n workerId: this.workerId,\n status: 'ignored',\n });\n result.ignored += 1;\n summaryKeys.add(`${item.sourceInstanceId}\\u0000${dayFor(item)}`);\n continue;\n }\n if (!content || item.sensitivity === 'secret' || item.sensitivity === 'regulated') {\n completeKnowledgeSourceItemSynthesis({\n itemId: item.id,\n workerId: this.workerId,\n status: 'ignored',\n });\n result.ignored += 1;\n continue;\n }\n\n const sourceProvider = providerId(item);\n const record = upsertMemoryRecord({\n id: recordId,\n providerId: 'connected-knowledge',\n kind: 'workspace_fact',\n sourceAgentId: ownerAgentId(item, this.options.agentId),\n workspaceId: ownerWorkspaceId(item, this.options.workspaceId),\n content,\n canonicalKey: `source-item:${item.sourceInstanceId}:${item.externalId}`,\n source: { provider: sourceProvider, sourceInstanceId: item.sourceInstanceId, path: item.payloadRef },\n confidence: 0.78,\n tags: ['connected-source', 'external', sourceProvider, item.itemType],\n status: 'active',\n sensitivity: item.sensitivity,\n explicitness: 'observed',\n durability: item.retentionClass === 'durable' ? 'durable' : 'recurring',\n importance: 0.5,\n disclosurePolicy: 'referenceable',\n evidence: [{\n sourceItemId: item.id,\n relation: 'derived_from',\n sourceText: content.slice(0, 1_000),\n confidence: 0.78,\n observedAt: item.occurredAt ?? item.sourceUpdatedAt,\n }],\n validFrom: item.occurredAt ?? item.sourceUpdatedAt,\n });\n attachMemoryEvidence({\n recordId: record.id,\n sourceItemId: item.id,\n relation: 'derived_from',\n excerpt: content.slice(0, 1_000),\n confidence: 0.78,\n observedAt: item.occurredAt ?? item.sourceUpdatedAt,\n });\n completeKnowledgeSourceItemSynthesis({\n itemId: item.id,\n workerId: this.workerId,\n status: 'completed',\n });\n result.completed += 1;\n result.recordIds.push(record.id);\n summaryKeys.add(`${item.sourceInstanceId}\\u0000${dayFor(item)}`);\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : String(err);\n completeKnowledgeSourceItemSynthesis({\n itemId: item.id,\n workerId: this.workerId,\n status: 'failed',\n error: errorMessage.slice(0, 1_000),\n });\n result.failed += 1;\n log.warn(\n { err, itemId: item.id, sourceInstanceId: item.sourceInstanceId },\n `Connected knowledge synthesis failed: ${errorMessage}`,\n );\n }\n }\n\n for (const key of summaryKeys) {\n const [sourceInstanceId, day] = key.split('\\u0000');\n if (sourceInstanceId && day) this.rebuildDailySummary(sourceInstanceId, day);\n }\n return result;\n }\n\n private rebuildDailySummary(sourceInstanceId: string, day: string): void {\n const items = listKnowledgeSourceItems({ sourceInstanceId, limit: 500 })\n .filter((item) => dayFor(item) === day && item.synthesisStatus === 'completed')\n .slice(0, MAX_SUMMARY_ITEMS);\n if (items.length === 0) {\n const existing = getMemoryRecord(summaryRecordId(sourceInstanceId, day));\n if (existing) {\n upsertMemoryRecord({\n id: existing.id,\n providerId: 'connected-knowledge',\n kind: existing.kind,\n sourceAgentId: existing.provenance.sourceAgentId,\n workspaceId: existing.scope.workspaceId,\n content: existing.content,\n source: existing.source,\n confidence: existing.confidence,\n tags: existing.tags,\n status: 'archived',\n sensitivity: existing.sensitivity,\n explicitness: existing.explicitness,\n durability: existing.durability,\n importance: existing.importance,\n disclosurePolicy: existing.disclosurePolicy,\n evidence: existing.evidence,\n validFrom: existing.validFrom,\n validTo: new Date().toISOString(),\n reviewAfter: existing.reviewAfter,\n expiresAt: existing.expiresAt,\n canonicalKey: existing.canonicalKey,\n });\n }\n return;\n }\n const sourceProvider = providerId(items[0]!);\n const lines = [`# ${sourceProvider} updates for ${day}`, ''];\n for (const item of items) {\n const text = boundedText(item).replace(/\\s+/g, ' ').trim();\n if (!text) continue;\n lines.push(`- ${text.slice(0, 360)}`);\n if (lines.join('\\n').length >= MAX_SUMMARY_CHARS) break;\n }\n const content = lines.join('\\n').slice(0, MAX_SUMMARY_CHARS);\n const summary = upsertMemoryRecord({\n id: summaryRecordId(sourceInstanceId, day),\n providerId: 'connected-knowledge',\n kind: 'daily_note',\n sourceAgentId: ownerAgentId(items[0]!, this.options.agentId),\n workspaceId: ownerWorkspaceId(items[0]!, this.options.workspaceId),\n content,\n canonicalKey: `source-day:${sourceInstanceId}:${day}`,\n source: { provider: sourceProvider, sourceInstanceId },\n confidence: 0.72,\n tags: ['connected-source', 'source-day-summary', sourceProvider],\n status: 'active',\n sensitivity: items.some((item) => item.sensitivity === 'personal') ? 'personal' : 'normal',\n explicitness: 'observed',\n durability: 'recurring',\n importance: 0.55,\n disclosurePolicy: 'referenceable',\n evidence: items.map((item) => ({\n sourceItemId: item.id,\n relation: 'derived_from' as const,\n sourceText: boundedText(item).slice(0, 500),\n confidence: 0.72,\n observedAt: item.occurredAt ?? item.sourceUpdatedAt,\n })),\n validFrom: `${day}T00:00:00.000Z`,\n });\n deleteMemoryEvidenceForRecord(summary.id, 'derived_from');\n for (const item of items) {\n attachMemoryEvidence({\n recordId: summary.id,\n sourceItemId: item.id,\n relation: 'derived_from',\n excerpt: boundedText(item).slice(0, 500),\n confidence: 0.72,\n observedAt: item.occurredAt ?? item.sourceUpdatedAt,\n });\n }\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ export type LocalAppAcceptanceStep = {
2
+ action: 'click';
3
+ target: string;
4
+ } | {
5
+ action: 'fill';
6
+ target: string;
7
+ value: string;
8
+ } | {
9
+ assert: 'text_visible';
10
+ text: string;
11
+ } | {
12
+ assert: 'element_exists';
13
+ target: string;
14
+ } | {
15
+ assert: 'value_equals';
16
+ target: string;
17
+ value: string;
18
+ };
19
+ export interface LocalAppAcceptanceScenario {
20
+ id: string;
21
+ name: string;
22
+ steps: LocalAppAcceptanceStep[];
23
+ }
24
+ export interface LocalAppAcceptanceConfig {
25
+ schemaVersion: 1;
26
+ scenarios: LocalAppAcceptanceScenario[];
27
+ }
28
+ export declare function parseLocalAppAcceptanceConfig(value: unknown): LocalAppAcceptanceConfig;
29
+ export declare function readLocalAppAcceptanceConfig(root: string): LocalAppAcceptanceConfig;
30
+ export declare function encodeLocalAppAcceptanceConfig(config: LocalAppAcceptanceConfig): string;