@xopcai/xopc 0.0.124 → 0.0.125

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 (304) hide show
  1. package/dist/browser-ext/manifest.json +1 -1
  2. package/dist/extensions/telegram/xopc.extension.json +1 -1
  3. package/dist/gateway/static/root/assets/Combination-BzaXOLd9.js +41 -0
  4. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-B5uSVAyJ.js → agent-avatar-dicebear-BKDKICZV.js} +1 -1
  5. package/dist/gateway/static/root/assets/agents-BnTB7-c5.js +2 -0
  6. package/dist/gateway/static/root/assets/app-management-settings-panel-DI4BqHKW.js +1 -0
  7. package/dist/gateway/static/root/assets/appearance-settings-6_ie3NQ4.js +1 -0
  8. package/dist/gateway/static/root/assets/apps-page-B6bG65SW.js +1 -0
  9. package/dist/gateway/static/root/assets/{archive-plugin-CXUGRp2i.js → archive-plugin-kUHEJ1HK.js} +1 -1
  10. package/dist/gateway/static/root/assets/{attachment-load-Cmiub3Wg.js → attachment-load-Dm-9prpU.js} +1 -1
  11. package/dist/gateway/static/root/assets/automation-suggestion-card-OTxQTPnC.js +1 -0
  12. package/dist/gateway/static/root/assets/automations-page-1lVbo0dS.js +1 -0
  13. package/dist/gateway/static/root/assets/{binary-plugins-0Izz-N3p.js → binary-plugins-DllA_jQ0.js} +1 -1
  14. package/dist/gateway/static/root/assets/{block-editor-C1Kv0IkJ.js → block-editor-Cm6CWNj1.js} +6 -6
  15. package/dist/gateway/static/root/assets/browser-settings-page-CzDBlOK0.js +8 -0
  16. package/dist/gateway/static/root/assets/capability-presets-api-VJ89b6I2.js +1 -0
  17. package/dist/gateway/static/root/assets/capability-presets-settings-panel-BaPj8wC2.js +1 -0
  18. package/dist/gateway/static/root/assets/{channel-recipient-api-BeA2aVor.js → channel-recipient-api-B5PwBEUx.js} +1 -1
  19. package/dist/gateway/static/root/assets/channels-settings-Df4m7p1k.js +1 -0
  20. package/dist/gateway/static/root/assets/code-editor-gbRgS14t.js +1 -0
  21. package/dist/gateway/static/root/assets/connectors-page-BMTphmHS.js +2 -0
  22. package/dist/gateway/static/root/assets/{directory-picker-path-field-2rjzUu57.js → directory-picker-path-field-DySMzOF6.js} +1 -1
  23. package/dist/gateway/static/root/assets/dist-By6Rh2ee.js +1 -0
  24. package/dist/gateway/static/root/assets/dist-CkobR7mk.js +1 -0
  25. package/dist/gateway/static/root/assets/dist-DokQNVMQ.js +1 -0
  26. package/dist/gateway/static/root/assets/dreaming-settings-D_AjSnV_.js +3 -0
  27. package/dist/gateway/static/root/assets/extension-debug-page-BaM0FpW7.js +1 -0
  28. package/dist/gateway/static/root/assets/extension-page-DuZWVOGA.js +1 -0
  29. package/dist/gateway/static/root/assets/extension-settings-page-DarVtbmJ.js +1 -0
  30. package/dist/gateway/static/root/assets/{fetch-BU5S0Sn7.js → fetch-NFKfkqrd.js} +1 -1
  31. package/dist/gateway/static/root/assets/{gateway-config-api-BIPGwrl1.js → gateway-config-api-CFEm9rgy.js} +1 -1
  32. package/dist/gateway/static/root/assets/gateway-settings-BMk2S5td.js +1 -0
  33. package/dist/gateway/static/root/assets/{gateway-startup-retry-Cd0Zz30N.js → gateway-startup-retry-Dtwh_yGg.js} +1 -1
  34. package/dist/gateway/static/root/assets/goal-create-dialog-BKP7ylcG.js +1 -0
  35. package/dist/gateway/static/root/assets/goal-detail-page-C2cTxf71.js +1 -0
  36. package/dist/gateway/static/root/assets/{goals-config-api-B95KdGMj.js → goals-config-api-DTWZNA_Y.js} +1 -1
  37. package/dist/gateway/static/root/assets/goals-page-CTmA3hWK.js +2 -0
  38. package/dist/gateway/static/root/assets/goals-settings-Bhct0ZT-.js +1 -0
  39. package/dist/gateway/static/root/assets/heartbeat-settings-C-UxSU4a.js +1 -0
  40. package/dist/gateway/static/root/assets/{html-workspace-editor-CQLWDiwE.js → html-workspace-editor-DV90ddkE.js} +1 -1
  41. package/dist/gateway/static/root/assets/index-BNHDd2j1.css +1 -0
  42. package/dist/gateway/static/root/assets/index-BPXLPMuY.js +193 -0
  43. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-DCjy2y4d.js +1 -0
  44. package/dist/gateway/static/root/assets/logs-page-CGc3_CQU.js +2 -0
  45. package/dist/gateway/static/root/assets/{markdown-editor-AssmZFx4.js → markdown-editor-BFOjBBla.js} +2 -2
  46. package/dist/gateway/static/root/assets/markdown-split-BaqxP-GQ.js +1 -0
  47. package/dist/gateway/static/root/assets/{media-plugins-BhIQU5yS.js → media-plugins-DQ_EXloK.js} +1 -1
  48. package/dist/gateway/static/root/assets/messages-CjuIJcZl.js +3 -0
  49. package/dist/gateway/static/root/assets/models-hub-panel-Drz4UQMb.js +2 -0
  50. package/dist/gateway/static/root/assets/notes-page-CY1ylng1.js +1 -0
  51. package/dist/gateway/static/root/assets/notes-workbench-X7IaD--t.js +2 -0
  52. package/dist/gateway/static/root/assets/page-tabs-EIZhLppK.js +1 -0
  53. package/dist/gateway/static/root/assets/{preview-open-alternatives-DGzet1d7.js → preview-open-alternatives-r_uB4Epr.js} +1 -1
  54. package/dist/gateway/static/root/assets/project-detail-page-DE5adRBE.js +1 -0
  55. package/dist/gateway/static/root/assets/projects-page-CuOb1k6F.js +1 -0
  56. package/dist/gateway/static/root/assets/remote-access-hub-BOxNrUVA.js +1 -0
  57. package/dist/gateway/static/root/assets/{save-bar-controls-Cqgb-jqa.js → save-bar-controls-B132Uf-2.js} +1 -1
  58. package/dist/gateway/static/root/assets/{schedule-field-DVZcI8Yt.js → schedule-field-B5qshALm.js} +1 -1
  59. package/dist/gateway/static/root/assets/{schema-form-Bj7sOxC8.js → schema-form-CvLmkdS9.js} +1 -1
  60. package/dist/gateway/static/root/assets/sessions-page-CY0IQcGW.js +1 -0
  61. package/dist/gateway/static/root/assets/settings-advanced-gate-D4NBNVCB.js +1 -0
  62. package/dist/gateway/static/root/assets/{settings-collapsible-section-BmXn-8N6.js → settings-collapsible-section-pRlvqsAf.js} +1 -1
  63. package/dist/gateway/static/root/assets/{settings-form-section-BnqYMWHR.js → settings-form-section-BBYUDLVd.js} +1 -1
  64. package/dist/gateway/static/root/assets/settings-page-DaO7zYZM.js +1 -0
  65. package/dist/gateway/static/root/assets/{settings-page-layout-CdWZU1hd.js → settings-page-layout-D8g9PAek.js} +1 -1
  66. package/dist/gateway/static/root/assets/setup-status-panel-Bks0CLLT.js +1 -0
  67. package/dist/gateway/static/root/assets/{share-preview-page-IB1v8i86.js → share-preview-page-v6-IOp8t.js} +1 -1
  68. package/dist/gateway/static/root/assets/shares-settings-CEZsKm9r.js +1 -0
  69. package/dist/gateway/static/root/assets/skill-reload-api-oTkHbb9W.js +1 -0
  70. package/dist/gateway/static/root/assets/skills-page-DigsbZ6K.js +2 -0
  71. package/dist/gateway/static/root/assets/{system-settings-panel-BxQ384RC.js → system-settings-panel-HUU2FFjM.js} +1 -1
  72. package/dist/gateway/static/root/assets/{typed-models-lib-BkcpvFYO.js → typed-models-lib-AH160QHh.js} +1 -1
  73. package/dist/gateway/static/root/assets/{use-channel-catalog-Cd0FaEQ4.js → use-channel-catalog-BXzDmjCQ.js} +1 -1
  74. package/dist/gateway/static/root/assets/{user-profile-settings-panel-DQ7NnRSY.js → user-profile-settings-panel-DxwnQvQ3.js} +1 -1
  75. package/dist/gateway/static/root/assets/{utils-YKhVf7Ka.js → utils-i5POEtqd.js} +1 -1
  76. package/dist/gateway/static/root/assets/{vendor-codemirror-CNP1wPe7.js → vendor-codemirror-BvNgyE1Q.js} +1 -1
  77. package/dist/gateway/static/root/assets/voice-api-key-field-CEJklEgb.js +1 -0
  78. package/dist/gateway/static/root/assets/work-item-detail-page-CD6FL_Rs.js +1 -0
  79. package/dist/gateway/static/root/assets/workflow-run-setup-panel-ClVVMgN-.js +3 -0
  80. package/dist/gateway/static/root/assets/{workflow-start-dialog-BNJVCWoS.js → workflow-start-dialog-Dv4ZA1T0.js} +1 -1
  81. package/dist/gateway/static/root/assets/workflows-page-OLQiUpoW.js +18 -0
  82. package/dist/gateway/static/root/index.html +8 -7
  83. package/dist/package.js +1 -1
  84. package/dist/src/agent/agent-manager.js +6 -2
  85. package/dist/src/agent/agent-manager.js.map +1 -1
  86. package/dist/src/agent/child-agent-factory.d.ts +2 -0
  87. package/dist/src/agent/child-agent-factory.js +2 -0
  88. package/dist/src/agent/child-agent-factory.js.map +1 -1
  89. package/dist/src/agent/coding/index.d.ts +1 -0
  90. package/dist/src/agent/coding/index.js +2 -0
  91. package/dist/src/agent/coding/turn-diff-tracker.d.ts +67 -0
  92. package/dist/src/agent/coding/turn-diff-tracker.js +233 -0
  93. package/dist/src/agent/coding/turn-diff-tracker.js.map +1 -0
  94. package/dist/src/agent/memory/dreaming/config.d.ts +2 -2
  95. package/dist/src/agent/memory/dreaming/config.js +3 -3
  96. package/dist/src/agent/memory/dreaming/config.js.map +1 -1
  97. package/dist/src/agent/memory/dreaming/constants.d.ts +1 -1
  98. package/dist/src/agent/memory/dreaming/constants.js +1 -1
  99. package/dist/src/agent/memory/dreaming/constants.js.map +1 -1
  100. package/dist/src/agent/memory/dreaming/deep-promotion.d.ts +1 -0
  101. package/dist/src/agent/memory/dreaming/deep-promotion.js +11 -20
  102. package/dist/src/agent/memory/dreaming/deep-promotion.js.map +1 -1
  103. package/dist/src/agent/memory/dreaming/events.d.ts +3 -3
  104. package/dist/src/agent/memory/dreaming/events.js +6 -6
  105. package/dist/src/agent/memory/dreaming/events.js.map +1 -1
  106. package/dist/src/agent/memory/dreaming/last-run.d.ts +2 -2
  107. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  108. package/dist/src/agent/memory/dreaming/last-run.js.map +1 -1
  109. package/dist/src/agent/memory/dreaming/light-sweep.d.ts +1 -1
  110. package/dist/src/agent/memory/dreaming/light-sweep.js +3 -3
  111. package/dist/src/agent/memory/dreaming/light-sweep.js.map +1 -1
  112. package/dist/src/agent/memory/dreaming/preview.d.ts +1 -0
  113. package/dist/src/agent/memory/dreaming/preview.js +2 -2
  114. package/dist/src/agent/memory/dreaming/preview.js.map +1 -1
  115. package/dist/src/agent/memory/dreaming/rem-patterns.d.ts +1 -1
  116. package/dist/src/agent/memory/dreaming/rem-patterns.js +13 -13
  117. package/dist/src/agent/memory/dreaming/rem-patterns.js.map +1 -1
  118. package/dist/src/agent/memory/dreaming/scope.d.ts +14 -0
  119. package/dist/src/agent/memory/dreaming/scope.js +27 -0
  120. package/dist/src/agent/memory/dreaming/scope.js.map +1 -0
  121. package/dist/src/agent/memory/dreaming/short-term-store.d.ts +4 -4
  122. package/dist/src/agent/memory/dreaming/short-term-store.js +17 -17
  123. package/dist/src/agent/memory/dreaming/short-term-store.js.map +1 -1
  124. package/dist/src/agent/orchestration/agent-event-handler.d.ts +2 -0
  125. package/dist/src/agent/orchestration/agent-event-handler.js +13 -0
  126. package/dist/src/agent/orchestration/agent-event-handler.js.map +1 -1
  127. package/dist/src/agent/orchestration/agent-orchestrator.js +22 -12
  128. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  129. package/dist/src/agent/sandbox/command-validator.js +12 -0
  130. package/dist/src/agent/sandbox/command-validator.js.map +1 -1
  131. package/dist/src/agent/service.d.ts +2 -1
  132. package/dist/src/agent/service.js +18 -6
  133. package/dist/src/agent/service.js.map +1 -1
  134. package/dist/src/agent/session/session-inspector.d.ts +5 -3
  135. package/dist/src/agent/session/session-inspector.js +16 -7
  136. package/dist/src/agent/session/session-inspector.js.map +1 -1
  137. package/dist/src/agent/source-context/types.d.ts +1 -1
  138. package/dist/src/agent/source-context/types.js +1 -1
  139. package/dist/src/agent/source-context/types.js.map +1 -1
  140. package/dist/src/agent/tools/apply-patch.js +116 -62
  141. package/dist/src/agent/tools/apply-patch.js.map +1 -1
  142. package/dist/src/agent/tools/concurrency.d.ts +8 -0
  143. package/dist/src/agent/tools/concurrency.js +31 -0
  144. package/dist/src/agent/tools/concurrency.js.map +1 -0
  145. package/dist/src/agent/tools/dreaming-tool.d.ts +2 -0
  146. package/dist/src/agent/tools/dreaming-tool.js +13 -10
  147. package/dist/src/agent/tools/dreaming-tool.js.map +1 -1
  148. package/dist/src/agent/tools/exec-command.js +4 -0
  149. package/dist/src/agent/tools/exec-command.js.map +1 -1
  150. package/dist/src/agent/tools/executor.d.ts +6 -4
  151. package/dist/src/agent/tools/executor.js +7 -4
  152. package/dist/src/agent/tools/executor.js.map +1 -1
  153. package/dist/src/agent/tools/factory.d.ts +3 -0
  154. package/dist/src/agent/tools/factory.js +7 -1
  155. package/dist/src/agent/tools/factory.js.map +1 -1
  156. package/dist/src/agent/tools/find.js +2 -0
  157. package/dist/src/agent/tools/find.js.map +1 -1
  158. package/dist/src/agent/tools/grep.js +2 -0
  159. package/dist/src/agent/tools/grep.js.map +1 -1
  160. package/dist/src/agent/tools/index.d.ts +2 -0
  161. package/dist/src/agent/tools/index.js +3 -1
  162. package/dist/src/agent/tools/list-dir.js +2 -0
  163. package/dist/src/agent/tools/list-dir.js.map +1 -1
  164. package/dist/src/agent/tools/memory-tool.d.ts +1 -0
  165. package/dist/src/agent/tools/memory-tool.js +2 -2
  166. package/dist/src/agent/tools/memory-tool.js.map +1 -1
  167. package/dist/src/agent/tools/metadata.d.ts +15 -0
  168. package/dist/src/agent/tools/metadata.js +26 -0
  169. package/dist/src/agent/tools/metadata.js.map +1 -0
  170. package/dist/src/agent/tools/read.js +2 -0
  171. package/dist/src/agent/tools/read.js.map +1 -1
  172. package/dist/src/agent/tools/write.js +6 -0
  173. package/dist/src/agent/tools/write.js.map +1 -1
  174. package/dist/src/agent/workflow/subagent-runner.d.ts +1 -0
  175. package/dist/src/agent/workflow/subagent-runner.js +5 -1
  176. package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
  177. package/dist/src/agent/workflow/workflow-child-tools.js +5 -0
  178. package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -1
  179. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  180. package/dist/src/connectors/health.d.ts +2 -1
  181. package/dist/src/connectors/health.js +59 -1
  182. package/dist/src/connectors/health.js.map +1 -1
  183. package/dist/src/connectors/install.d.ts +1 -0
  184. package/dist/src/connectors/install.js +28 -1
  185. package/dist/src/connectors/install.js.map +1 -1
  186. package/dist/src/connectors/instances.js +7 -0
  187. package/dist/src/connectors/instances.js.map +1 -1
  188. package/dist/src/connectors/materialize.js +2 -1
  189. package/dist/src/connectors/materialize.js.map +1 -1
  190. package/dist/src/connectors/registries/modelscope.js +38 -13
  191. package/dist/src/connectors/registries/modelscope.js.map +1 -1
  192. package/dist/src/connectors/types.d.ts +2 -0
  193. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +1 -0
  194. package/dist/src/gateway/dreaming-automation-reconciler.js +62 -42
  195. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -1
  196. package/dist/src/gateway/hono/app.js +7 -1
  197. package/dist/src/gateway/hono/app.js.map +1 -1
  198. package/dist/src/gateway/hono/routes/connectors.js +46 -2
  199. package/dist/src/gateway/hono/routes/connectors.js.map +1 -1
  200. package/dist/src/gateway/hono/routes/dreaming.js +111 -66
  201. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  202. package/dist/src/gateway/hono/routes/projects.js +846 -43
  203. package/dist/src/gateway/hono/routes/projects.js.map +1 -1
  204. package/dist/src/gateway/hono/routes/sessions.js +1 -0
  205. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  206. package/dist/src/gateway/service.js +17 -8
  207. package/dist/src/gateway/service.js.map +1 -1
  208. package/dist/src/media/store.js +1 -1
  209. package/dist/src/media/store.js.map +1 -1
  210. package/dist/src/media/types.d.ts +1 -1
  211. package/dist/src/media/uri.js +2 -1
  212. package/dist/src/media/uri.js.map +1 -1
  213. package/dist/src/session/session-context-for-llm.d.ts +2 -0
  214. package/dist/src/session/session-context-for-llm.js +14 -1
  215. package/dist/src/session/session-context-for-llm.js.map +1 -1
  216. package/dist/src/session/store.js +2 -2
  217. package/dist/src/session/store.js.map +1 -1
  218. package/dist/src/storage/sqlite/migrations/022_work_items.sql +61 -0
  219. package/dist/src/storage/sqlite/migrations/023_work_item_attachments.sql +15 -0
  220. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  221. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  222. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  223. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  224. package/dist/src/storage/sqlite/schema.js +1 -1
  225. package/dist/src/storage/sqlite/schema.sql +78 -0
  226. package/dist/src/tui/components/assistant-message.js +12 -2
  227. package/dist/src/tui/components/assistant-message.js.map +1 -1
  228. package/dist/src/tui/components/tool-execution.d.ts +8 -0
  229. package/dist/src/tui/components/tool-execution.js +87 -77
  230. package/dist/src/tui/components/tool-execution.js.map +1 -1
  231. package/dist/src/tui/components/visual-truncate.d.ts +1 -0
  232. package/dist/src/tui/components/visual-truncate.js +28 -1
  233. package/dist/src/tui/components/visual-truncate.js.map +1 -1
  234. package/dist/src/tui/tool-summary.d.ts +22 -0
  235. package/dist/src/tui/tool-summary.js +212 -0
  236. package/dist/src/tui/tool-summary.js.map +1 -0
  237. package/dist/src/tui/tui-tool-diff.d.ts +15 -0
  238. package/dist/src/tui/tui-tool-diff.js +178 -7
  239. package/dist/src/tui/tui-tool-diff.js.map +1 -1
  240. package/dist/src/work-items/agent-context.d.ts +3 -0
  241. package/dist/src/work-items/agent-context.js +39 -0
  242. package/dist/src/work-items/agent-context.js.map +1 -0
  243. package/dist/src/work-items/index.d.ts +4 -0
  244. package/dist/src/work-items/index.js +4 -0
  245. package/dist/src/work-items/types.d.ts +112 -0
  246. package/dist/src/work-items/types.js +1 -0
  247. package/dist/src/work-items/work-item-service.d.ts +33 -0
  248. package/dist/src/work-items/work-item-service.js +180 -0
  249. package/dist/src/work-items/work-item-service.js.map +1 -0
  250. package/dist/src/work-items/work-item-store.d.ts +21 -0
  251. package/dist/src/work-items/work-item-store.js +302 -0
  252. package/dist/src/work-items/work-item-store.js.map +1 -0
  253. package/dist/src/workflows/service/workflow-run-service.js +4 -3
  254. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  255. package/dist/src/workflows/service/workflow-session-bridge.js +3 -0
  256. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -1
  257. package/package.json +1 -1
  258. package/dist/gateway/static/root/assets/Combination-HAlzriaz.js +0 -41
  259. package/dist/gateway/static/root/assets/agents-BjIxt67Z.js +0 -2
  260. package/dist/gateway/static/root/assets/app-management-settings-panel-CYCONLIL.js +0 -1
  261. package/dist/gateway/static/root/assets/appearance-settings-Clw3ryKg.js +0 -1
  262. package/dist/gateway/static/root/assets/apps-page-QICTeGjX.js +0 -1
  263. package/dist/gateway/static/root/assets/automation-suggestion-card-CU0-4nQ-.js +0 -1
  264. package/dist/gateway/static/root/assets/automations-page-Car-jtiz.js +0 -1
  265. package/dist/gateway/static/root/assets/browser-settings-page-CMeBJzlS.js +0 -8
  266. package/dist/gateway/static/root/assets/capability-presets-api-BmQTM9Il.js +0 -1
  267. package/dist/gateway/static/root/assets/capability-presets-settings-panel-DZEJEoCF.js +0 -1
  268. package/dist/gateway/static/root/assets/channels-settings-kkW-xFau.js +0 -1
  269. package/dist/gateway/static/root/assets/code-editor-dZTY2dRW.js +0 -1
  270. package/dist/gateway/static/root/assets/connectors-page-BvaQvO5F.js +0 -2
  271. package/dist/gateway/static/root/assets/dist-Mys7eFJ5.js +0 -1
  272. package/dist/gateway/static/root/assets/dist-wO9a2_ID.js +0 -1
  273. package/dist/gateway/static/root/assets/dreaming-settings-DnHO686d.js +0 -1
  274. package/dist/gateway/static/root/assets/extension-debug-page-BGLRuWVN.js +0 -1
  275. package/dist/gateway/static/root/assets/extension-page-D978ePp9.js +0 -1
  276. package/dist/gateway/static/root/assets/extension-settings-page-B6Ih4Swx.js +0 -1
  277. package/dist/gateway/static/root/assets/gateway-settings-CMEA3r5u.js +0 -1
  278. package/dist/gateway/static/root/assets/goal-create-dialog-B-KHKeXN.js +0 -1
  279. package/dist/gateway/static/root/assets/goal-detail-page-BxrSoWdj.js +0 -1
  280. package/dist/gateway/static/root/assets/goals-page-BTJzIl28.js +0 -2
  281. package/dist/gateway/static/root/assets/goals-settings-BJyEuLLm.js +0 -1
  282. package/dist/gateway/static/root/assets/heartbeat-settings-wkOjYNQT.js +0 -1
  283. package/dist/gateway/static/root/assets/index-BLaXr6Ev.css +0 -1
  284. package/dist/gateway/static/root/assets/index-c_9TVr_C.js +0 -191
  285. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-BT8T4DyC.js +0 -1
  286. package/dist/gateway/static/root/assets/logs-page-CrxBJUgI.js +0 -2
  287. package/dist/gateway/static/root/assets/markdown-split-Dv66bO2b.js +0 -1
  288. package/dist/gateway/static/root/assets/messages-O6TAtdFC.js +0 -3
  289. package/dist/gateway/static/root/assets/models-hub-panel-DOOpz6y1.js +0 -2
  290. package/dist/gateway/static/root/assets/notes-page-Br16pK9v.js +0 -1
  291. package/dist/gateway/static/root/assets/notes-workbench-PSJAi0ZC.js +0 -2
  292. package/dist/gateway/static/root/assets/project-detail-page-CIGGgKuw.js +0 -1
  293. package/dist/gateway/static/root/assets/projects-page-B2grhsBt.js +0 -1
  294. package/dist/gateway/static/root/assets/remote-access-hub-CXMORxBD.js +0 -1
  295. package/dist/gateway/static/root/assets/sessions-page-Bi2wkBzU.js +0 -1
  296. package/dist/gateway/static/root/assets/settings-advanced-gate-B1L3G4IA.js +0 -1
  297. package/dist/gateway/static/root/assets/settings-page-BfRSHJmO.js +0 -1
  298. package/dist/gateway/static/root/assets/setup-status-panel-CWtPM7RK.js +0 -1
  299. package/dist/gateway/static/root/assets/shares-settings-ngbsBgij.js +0 -1
  300. package/dist/gateway/static/root/assets/skill-reload-api-BIe442Gv.js +0 -1
  301. package/dist/gateway/static/root/assets/skills-page-BfchZRVa.js +0 -2
  302. package/dist/gateway/static/root/assets/voice-api-key-field-C5Ov8Uk_.js +0 -1
  303. package/dist/gateway/static/root/assets/workflow-run-setup-panel-BYD9BtOq.js +0 -3
  304. package/dist/gateway/static/root/assets/workflows-page-BYF29ANm.js +0 -18
@@ -1 +1 @@
1
- {"version":3,"file":"subagent-runner.js","names":[],"sources":["../../../../src/agent/workflow/subagent-runner.ts"],"sourcesContent":["/**\n * Adapter: spawns one isolated child agent per `agent()` call from a workflow.\n *\n * Wraps the existing `createDelegateChildHandle` so the workflow runtime stays\n * decoupled from the LLM stack (it sees only the `SubagentRunner` interface).\n *\n * Key behaviour:\n * - When `opts.schema` is provided, we inject `structured_output` into the child\n * tool set and unwrap the captured value on success. If the subagent finishes\n * without ever calling `structured_output`, we treat it as failure (`null`).\n * - Failures and aborts resolve to `null`. The workflow runtime continues — this\n * matches the pi-dynamic-workflows contract and keeps fan-out pipelines robust.\n * - We do NOT mutate `createDelegateChildHandle` — we just leverage its\n * `buildChildTools` injection point.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { Api, Model } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { emitSessionTranscriptUpdate } from '../../session/transcript-events.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport {\n type BuildChildToolsOptions,\n createDelegateChildHandle,\n type DelegateChildHandleOptions,\n} from '../child-agent-factory.js';\nimport {\n DEFAULT_DELEGATE_TOOLS,\n DELEGATE_BLOCKED_TOOLS,\n} from '../tools/delegate-tool.js';\nimport type { ToolExecutorConfig } from '../tools/executor.js';\n\nimport {\n createStructuredOutputTool,\n STRUCTURED_OUTPUT_TOOL_NAME,\n type StructuredOutputCapture,\n} from './structured-output-tool.js';\nimport type { SubagentRunOptions, SubagentRunner, SubagentProgressEvent } from './types.js';\n\nconst log = createLogger('Agent:WorkflowSubagent');\n\nconst DEFAULT_MAX_ITERATIONS = 30;\n\nexport interface DelegateSubagentRunnerDeps {\n workspace: string;\n bus: MessageBus;\n /** Resolves the default subagent model (typically the parent agent's primary model). */\n getDefaultModel: () => Model<Api>;\n getConfig: () => Config | undefined;\n toolExecutorConfig?: Partial<ToolExecutorConfig>;\n sessionStore?: SessionStore;\n /**\n * Provided by the workflow tool from `AgentToolsFactory` — mirrors how\n * `delegate-tool` is wired (avoids importing `tools/factory.ts` here and\n * breaking the existing factory ↔ delegate-tool ↔ child-agent-factory\n * dependency contract).\n */\n buildChildTools: (opts: BuildChildToolsOptions) => AgentTool<any, any>[];\n}\n\nexport class DelegateSubagentRunner implements SubagentRunner {\n constructor(private readonly deps: DelegateSubagentRunnerDeps) {}\n\n async run<T = string>(prompt: string, opts: SubagentRunOptions<T>): Promise<T | null> {\n if (opts.signal?.aborted) return null;\n\n const capture: StructuredOutputCapture<T> = { called: false, value: undefined };\n const wantStructured = Boolean(opts.schema);\n\n const allowed = resolveAllowedToolNames(opts.allowedToolNames, wantStructured);\n const model = opts.model ?? safeResolveDefaultModel(this.deps.getDefaultModel);\n if (!model) {\n log.warn({ label: opts.label }, 'subagent run skipped: no primary model resolved');\n return null;\n }\n\n const fullPrompt = buildPrompt(prompt, opts, wantStructured);\n const streamMode = resolveSubagentStreamMode(this.deps.getConfig);\n\n let transcriptPersistQueue: Promise<void> = Promise.resolve();\n const persistTranscriptSnapshot = opts.sessionKey && this.deps.sessionStore\n ? (messages: Parameters<SessionStore['saveMessages']>[1]) => {\n const store = this.deps.sessionStore;\n const key = opts.sessionKey;\n if (!store || !key) return;\n const snapshot = cloneAgentMessages(messages);\n transcriptPersistQueue = transcriptPersistQueue\n .then(async () => {\n await store.saveMessages(key, snapshot);\n emitSessionTranscriptUpdate({ sessionKey: key });\n })\n .catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, sessionKey: key, errorMessage: msg },\n `Failed to persist workflow subagent transcript snapshot: ${msg}`,\n );\n });\n }\n : undefined;\n\n const childOptions: DelegateChildHandleOptions = {\n workspace: this.deps.workspace,\n goal: fullPrompt,\n allowedToolNames: allowed,\n maxIterations: opts.maxIterations ?? DEFAULT_MAX_ITERATIONS,\n model,\n bus: this.deps.bus,\n getConfig: this.deps.getConfig,\n toolExecutorConfig: this.deps.toolExecutorConfig,\n buildChildTools: (childOpts) => {\n const base = this.deps.buildChildTools(childOpts);\n if (!wantStructured || !opts.schema) return base;\n // Replace any existing tool with the same name so the per-run capture wins.\n const filtered = base.filter((t) => t.name !== STRUCTURED_OUTPUT_TOOL_NAME);\n return [\n ...filtered,\n createStructuredOutputTool({ schema: opts.schema, capture }) as unknown as AgentTool<any, any>,\n ];\n },\n progressHooks:\n opts.onProgress && streamMode !== 'off'\n ? {\n mode: streamMode === 'full' ? 'full' : 'steps',\n onProgress: (event) => {\n opts.onProgress?.(mapChildProgressEvent(event));\n },\n }\n : undefined,\n onTranscriptSnapshot: persistTranscriptSnapshot,\n };\n\n if (opts.sessionKey && opts.sessionMetadata && this.deps.sessionStore) {\n await this.preparePersistentSubagentSession(opts.sessionKey, opts.sessionMetadata);\n }\n\n const handle = createDelegateChildHandle(childOptions);\n const onAbort = () => handle.abort();\n opts.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const { summary, messages } = await handle.run();\n await transcriptPersistQueue;\n if (opts.sessionKey && this.deps.sessionStore) {\n await this.deps.sessionStore.saveMessages(opts.sessionKey, messages);\n emitSessionTranscriptUpdate({ sessionKey: opts.sessionKey });\n }\n if (opts.signal?.aborted) return null;\n\n if (wantStructured) {\n if (!capture.called) {\n log.warn({ label: opts.label }, 'subagent finished without calling structured_output');\n return null;\n }\n return capture.value as T;\n }\n return summary as unknown as T;\n } catch (e) {\n if (opts.rethrow) throw e;\n const msg = e instanceof Error ? e.message : String(e);\n log.warn({ err: e, label: opts.label, errorMessage: msg }, `subagent run failed: ${msg}`);\n return null;\n } finally {\n opts.signal?.removeEventListener('abort', onAbort);\n }\n }\n\n private async preparePersistentSubagentSession(\n sessionKey: string,\n metadata: NonNullable<SubagentRunOptions['sessionMetadata']>,\n ): Promise<void> {\n const store = this.deps.sessionStore;\n if (!store) return;\n await store.resolveTranscriptPath(sessionKey, {\n metadata: {\n sessionType: 'workflow-subagent',\n hiddenFromSessionList: true,\n parentSessionKey: metadata.parentSessionKey,\n workflowRunId: metadata.workflowRunId,\n workflowDefinitionId: metadata.workflowDefinitionId,\n workflowAgentId: metadata.workflowAgentId,\n workflowAgentLabel: metadata.workflowAgentLabel,\n sourceChannel: 'workflow',\n sourceChatId: metadata.workflowRunId,\n routing: {\n agentId: metadata.workflowAgentId || 'main',\n source: 'workflow',\n accountId: 'default',\n peerKind: 'subagent',\n peerId: metadata.workflowRunId,\n },\n },\n });\n await store.updateMetadata(sessionKey, {\n sessionType: 'workflow-subagent',\n hiddenFromSessionList: true,\n parentSessionKey: metadata.parentSessionKey,\n workflowRunId: metadata.workflowRunId,\n workflowDefinitionId: metadata.workflowDefinitionId,\n workflowAgentId: metadata.workflowAgentId,\n workflowAgentLabel: metadata.workflowAgentLabel,\n name: metadata.workflowAgentLabel,\n tags: ['workflow-subagent', metadata.workflowDefinitionId],\n });\n }\n}\n\nfunction cloneAgentMessages(messages: Parameters<SessionStore['saveMessages']>[1]): Parameters<SessionStore['saveMessages']>[1] {\n return messages.map((message) => structuredClone(message));\n}\n\nfunction resolveAllowedToolNames(\n requested: string[] | undefined,\n wantStructured: boolean,\n): string[] {\n const base = requested && requested.length > 0 ? requested : [...DEFAULT_DELEGATE_TOOLS];\n const filtered = base\n .map((s) => String(s).trim())\n .filter((s) => s.length > 0)\n .filter((s) => !DELEGATE_BLOCKED_TOOLS.has(s));\n if (wantStructured && !filtered.includes(STRUCTURED_OUTPUT_TOOL_NAME)) {\n filtered.push(STRUCTURED_OUTPUT_TOOL_NAME);\n }\n return [...new Set(filtered)];\n}\n\nfunction buildPrompt(prompt: string, opts: SubagentRunOptions<unknown>, structured: boolean): string {\n const parts: string[] = [];\n if (opts.instructions?.trim()) parts.push(opts.instructions.trim());\n if (opts.label) parts.push(`Task label: ${opts.label}`);\n if (opts.phase) parts.push(`Workflow phase: ${opts.phase}`);\n parts.push(prompt);\n if (structured) {\n parts.push(\n [\n 'Final output contract:',\n '- Your final action MUST be a structured_output tool call.',\n '- The structured_output arguments are the return value of this subagent.',\n '- Do not emit a prose final answer instead of structured_output.',\n '- If you need to inspect files or run commands first, do so, then call structured_output exactly once.',\n ].join('\\n'),\n );\n }\n return parts.join('\\n\\n');\n}\n\nfunction safeResolveDefaultModel(get: () => Model<Api>): Model<Api> | null {\n try {\n return get();\n } catch (e) {\n log.warn({ err: e }, 'failed to resolve default subagent model');\n return null;\n }\n}\n\nfunction resolveSubagentStreamMode(\n _getConfig: () => Config | undefined,\n): 'off' | 'steps' | 'full' {\n return 'steps';\n}\n\nfunction mapChildProgressEvent(event: {\n type: 'tool_start' | 'tool_end' | 'iteration' | 'text_delta' | 'thinking_delta';\n toolCallId?: string;\n toolName?: string;\n args?: Record<string, unknown>;\n isError?: boolean;\n resultPreview?: string;\n error?: string;\n count?: number;\n max?: number;\n delta?: string;\n}): SubagentProgressEvent {\n switch (event.type) {\n case 'tool_start':\n return {\n type: 'tool_start',\n toolCallId: event.toolCallId ?? '',\n toolName: event.toolName ?? 'tool',\n args: event.args ?? {},\n };\n case 'tool_end':\n return {\n type: 'tool_end',\n toolCallId: event.toolCallId ?? '',\n toolName: event.toolName ?? 'tool',\n isError: Boolean(event.isError),\n resultPreview: event.resultPreview,\n error: event.error,\n };\n case 'iteration':\n return {\n type: 'iteration',\n count: event.count ?? 0,\n max: event.max ?? 0,\n };\n case 'text_delta':\n return { type: 'text_delta', delta: event.delta ?? '' };\n case 'thinking_delta':\n return { type: 'thinking_delta', delta: event.delta ?? '' };\n default:\n return { type: 'text_delta', delta: '' };\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"subagent-runner.js","names":[],"sources":["../../../../src/agent/workflow/subagent-runner.ts"],"sourcesContent":["/**\n * Adapter: spawns one isolated child agent per `agent()` call from a workflow.\n *\n * Wraps the existing `createDelegateChildHandle` so the workflow runtime stays\n * decoupled from the LLM stack (it sees only the `SubagentRunner` interface).\n *\n * Key behaviour:\n * - When `opts.schema` is provided, we inject `structured_output` into the child\n * tool set and unwrap the captured value on success. If the subagent finishes\n * without ever calling `structured_output`, we treat it as failure (`null`).\n * - Failures and aborts resolve to `null`. The workflow runtime continues — this\n * matches the pi-dynamic-workflows contract and keeps fan-out pipelines robust.\n * - We do NOT mutate `createDelegateChildHandle` — we just leverage its\n * `buildChildTools` injection point.\n */\n\nimport type { AgentTool } from '@earendil-works/pi-agent-core';\nimport type { Api, Model } from '@earendil-works/pi-ai';\n\nimport type { Config } from '../../config/schema.js';\nimport type { MessageBus } from '../../infra/bus/index.js';\nimport type { SessionStore } from '../../session/store.js';\nimport { emitSessionTranscriptUpdate } from '../../session/transcript-events.js';\nimport { createLogger } from '../../utils/logger.js';\n\nimport {\n type BuildChildToolsOptions,\n createDelegateChildHandle,\n type DelegateChildHandleOptions,\n} from '../child-agent-factory.js';\nimport {\n DEFAULT_DELEGATE_TOOLS,\n DELEGATE_BLOCKED_TOOLS,\n} from '../tools/delegate-tool.js';\nimport type { ToolExecutorConfig } from '../tools/executor.js';\n\nimport {\n createStructuredOutputTool,\n STRUCTURED_OUTPUT_TOOL_NAME,\n type StructuredOutputCapture,\n} from './structured-output-tool.js';\nimport type { SubagentRunOptions, SubagentRunner, SubagentProgressEvent } from './types.js';\n\nconst log = createLogger('Agent:WorkflowSubagent');\n\nconst DEFAULT_MAX_ITERATIONS = 30;\n\nexport interface DelegateSubagentRunnerDeps {\n workspace: string;\n bus: MessageBus;\n agentId?: string;\n /** Resolves the default subagent model (typically the parent agent's primary model). */\n getDefaultModel: () => Model<Api>;\n getConfig: () => Config | undefined;\n toolExecutorConfig?: Partial<ToolExecutorConfig>;\n sessionStore?: SessionStore;\n /**\n * Provided by the workflow tool from `AgentToolsFactory` — mirrors how\n * `delegate-tool` is wired (avoids importing `tools/factory.ts` here and\n * breaking the existing factory ↔ delegate-tool ↔ child-agent-factory\n * dependency contract).\n */\n buildChildTools: (opts: BuildChildToolsOptions) => AgentTool<any, any>[];\n}\n\nexport class DelegateSubagentRunner implements SubagentRunner {\n constructor(private readonly deps: DelegateSubagentRunnerDeps) {}\n\n async run<T = string>(prompt: string, opts: SubagentRunOptions<T>): Promise<T | null> {\n if (opts.signal?.aborted) return null;\n\n const capture: StructuredOutputCapture<T> = { called: false, value: undefined };\n const wantStructured = Boolean(opts.schema);\n\n const allowed = resolveAllowedToolNames(opts.allowedToolNames, wantStructured);\n const model = opts.model ?? safeResolveDefaultModel(this.deps.getDefaultModel);\n if (!model) {\n log.warn({ label: opts.label }, 'subagent run skipped: no primary model resolved');\n return null;\n }\n\n const fullPrompt = buildPrompt(prompt, opts, wantStructured);\n const streamMode = resolveSubagentStreamMode(this.deps.getConfig);\n\n let transcriptPersistQueue: Promise<void> = Promise.resolve();\n const persistTranscriptSnapshot = opts.sessionKey && this.deps.sessionStore\n ? (messages: Parameters<SessionStore['saveMessages']>[1]) => {\n const store = this.deps.sessionStore;\n const key = opts.sessionKey;\n if (!store || !key) return;\n const snapshot = cloneAgentMessages(messages);\n transcriptPersistQueue = transcriptPersistQueue\n .then(async () => {\n await store.saveMessages(key, snapshot);\n emitSessionTranscriptUpdate({ sessionKey: key });\n })\n .catch((err) => {\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(\n { err, sessionKey: key, errorMessage: msg },\n `Failed to persist workflow subagent transcript snapshot: ${msg}`,\n );\n });\n }\n : undefined;\n\n const childOptions: DelegateChildHandleOptions = {\n workspace: this.deps.workspace,\n goal: fullPrompt,\n allowedToolNames: allowed,\n maxIterations: opts.maxIterations ?? DEFAULT_MAX_ITERATIONS,\n model,\n bus: this.deps.bus,\n agentId: this.deps.agentId,\n getConfig: this.deps.getConfig,\n toolExecutorConfig: this.deps.toolExecutorConfig,\n buildChildTools: (childOpts) => {\n const base = this.deps.buildChildTools({ ...childOpts, agentId: this.deps.agentId ?? childOpts.agentId });\n if (!wantStructured || !opts.schema) return base;\n // Replace any existing tool with the same name so the per-run capture wins.\n const filtered = base.filter((t) => t.name !== STRUCTURED_OUTPUT_TOOL_NAME);\n return [\n ...filtered,\n createStructuredOutputTool({ schema: opts.schema, capture }) as unknown as AgentTool<any, any>,\n ];\n },\n progressHooks:\n opts.onProgress && streamMode !== 'off'\n ? {\n mode: streamMode === 'full' ? 'full' : 'steps',\n onProgress: (event) => {\n opts.onProgress?.(mapChildProgressEvent(event));\n },\n }\n : undefined,\n onTranscriptSnapshot: persistTranscriptSnapshot,\n };\n\n if (opts.sessionKey && opts.sessionMetadata && this.deps.sessionStore) {\n await this.preparePersistentSubagentSession(opts.sessionKey, opts.sessionMetadata);\n }\n\n const handle = createDelegateChildHandle(childOptions);\n const onAbort = () => handle.abort();\n opts.signal?.addEventListener('abort', onAbort, { once: true });\n\n try {\n const { summary, messages } = await handle.run();\n await transcriptPersistQueue;\n if (opts.sessionKey && this.deps.sessionStore) {\n await this.deps.sessionStore.saveMessages(opts.sessionKey, messages);\n emitSessionTranscriptUpdate({ sessionKey: opts.sessionKey });\n }\n if (opts.signal?.aborted) return null;\n\n if (wantStructured) {\n if (!capture.called) {\n log.warn({ label: opts.label }, 'subagent finished without calling structured_output');\n return null;\n }\n return capture.value as T;\n }\n return summary as unknown as T;\n } catch (e) {\n if (opts.rethrow) throw e;\n const msg = e instanceof Error ? e.message : String(e);\n log.warn({ err: e, label: opts.label, errorMessage: msg }, `subagent run failed: ${msg}`);\n return null;\n } finally {\n opts.signal?.removeEventListener('abort', onAbort);\n }\n }\n\n private async preparePersistentSubagentSession(\n sessionKey: string,\n metadata: NonNullable<SubagentRunOptions['sessionMetadata']>,\n ): Promise<void> {\n const store = this.deps.sessionStore;\n if (!store) return;\n await store.resolveTranscriptPath(sessionKey, {\n metadata: {\n sessionType: 'workflow-subagent',\n hiddenFromSessionList: true,\n parentSessionKey: metadata.parentSessionKey,\n workflowRunId: metadata.workflowRunId,\n workflowDefinitionId: metadata.workflowDefinitionId,\n workflowAgentId: metadata.workflowAgentId,\n workflowAgentLabel: metadata.workflowAgentLabel,\n sourceChannel: 'workflow',\n sourceChatId: metadata.workflowRunId,\n routing: {\n agentId: metadata.workflowAgentId || 'main',\n source: 'workflow',\n accountId: 'default',\n peerKind: 'subagent',\n peerId: metadata.workflowRunId,\n },\n },\n });\n await store.updateMetadata(sessionKey, {\n sessionType: 'workflow-subagent',\n hiddenFromSessionList: true,\n parentSessionKey: metadata.parentSessionKey,\n workflowRunId: metadata.workflowRunId,\n workflowDefinitionId: metadata.workflowDefinitionId,\n workflowAgentId: metadata.workflowAgentId,\n workflowAgentLabel: metadata.workflowAgentLabel,\n name: metadata.workflowAgentLabel,\n tags: ['workflow-subagent', metadata.workflowDefinitionId],\n });\n }\n}\n\nfunction cloneAgentMessages(messages: Parameters<SessionStore['saveMessages']>[1]): Parameters<SessionStore['saveMessages']>[1] {\n return messages.map((message) => structuredClone(message));\n}\n\nfunction resolveAllowedToolNames(\n requested: string[] | undefined,\n wantStructured: boolean,\n): string[] {\n const base = requested && requested.length > 0 ? requested : [...DEFAULT_DELEGATE_TOOLS];\n const filtered = base\n .map((s) => String(s).trim())\n .filter((s) => s.length > 0)\n .filter((s) => !DELEGATE_BLOCKED_TOOLS.has(s));\n if (wantStructured && !filtered.includes(STRUCTURED_OUTPUT_TOOL_NAME)) {\n filtered.push(STRUCTURED_OUTPUT_TOOL_NAME);\n }\n return [...new Set(filtered)];\n}\n\nfunction buildPrompt(prompt: string, opts: SubagentRunOptions<unknown>, structured: boolean): string {\n const parts: string[] = [];\n if (opts.instructions?.trim()) parts.push(opts.instructions.trim());\n if (opts.label) parts.push(`Task label: ${opts.label}`);\n if (opts.phase) parts.push(`Workflow phase: ${opts.phase}`);\n parts.push(prompt);\n if (structured) {\n parts.push(\n [\n 'Final output contract:',\n '- Your final action MUST be a structured_output tool call.',\n '- The structured_output arguments are the return value of this subagent.',\n '- Do not emit a prose final answer instead of structured_output.',\n '- If you need to inspect files or run commands first, do so, then call structured_output exactly once.',\n ].join('\\n'),\n );\n }\n return parts.join('\\n\\n');\n}\n\nfunction safeResolveDefaultModel(get: () => Model<Api>): Model<Api> | null {\n try {\n return get();\n } catch (e) {\n log.warn({ err: e }, 'failed to resolve default subagent model');\n return null;\n }\n}\n\nfunction resolveSubagentStreamMode(\n _getConfig: () => Config | undefined,\n): 'off' | 'steps' | 'full' {\n return 'steps';\n}\n\nfunction mapChildProgressEvent(event: {\n type: 'tool_start' | 'tool_end' | 'iteration' | 'text_delta' | 'thinking_delta';\n toolCallId?: string;\n toolName?: string;\n args?: Record<string, unknown>;\n isError?: boolean;\n resultPreview?: string;\n error?: string;\n count?: number;\n max?: number;\n delta?: string;\n}): SubagentProgressEvent {\n switch (event.type) {\n case 'tool_start':\n return {\n type: 'tool_start',\n toolCallId: event.toolCallId ?? '',\n toolName: event.toolName ?? 'tool',\n args: event.args ?? {},\n };\n case 'tool_end':\n return {\n type: 'tool_end',\n toolCallId: event.toolCallId ?? '',\n toolName: event.toolName ?? 'tool',\n isError: Boolean(event.isError),\n resultPreview: event.resultPreview,\n error: event.error,\n };\n case 'iteration':\n return {\n type: 'iteration',\n count: event.count ?? 0,\n max: event.max ?? 0,\n };\n case 'text_delta':\n return { type: 'text_delta', delta: event.delta ?? '' };\n case 'thinking_delta':\n return { type: 'thinking_delta', delta: event.delta ?? '' };\n default:\n return { type: 'text_delta', delta: '' };\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,10 @@
1
+ import { resolveDreamingRootForAgent } from "../memory/dreaming/scope.js";
1
2
  import { AgentToolsFactory } from "../tools/factory.js";
2
3
  //#region src/agent/workflow/workflow-child-tools.ts
3
4
  /** Builds the tool set for workflow child agents (wired from gateway to avoid cycles). */
4
5
  function buildWorkflowChildTools(childOptions) {
6
+ const config = childOptions.getConfig();
7
+ const dreamingRoot = config && childOptions.agentId ? resolveDreamingRootForAgent(config, childOptions.agentId) : void 0;
5
8
  return new AgentToolsFactory({
6
9
  workspace: childOptions.workspace,
7
10
  bus: childOptions.bus,
@@ -12,6 +15,8 @@ function buildWorkflowChildTools(childOptions) {
12
15
  }).createAllTools({
13
16
  workspace: childOptions.workspace,
14
17
  getPrimaryModel: () => childOptions.model,
18
+ agentId: childOptions.agentId,
19
+ dreamingRoot,
15
20
  disabledTools: new Set(["extensions"])
16
21
  });
17
22
  }
@@ -1 +1 @@
1
- {"version":3,"file":"workflow-child-tools.js","names":[],"sources":["../../../../src/agent/workflow/workflow-child-tools.ts"],"sourcesContent":["import type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport type { BuildChildToolsOptions } from '../child-agent-factory.js';\nimport { AgentToolsFactory } from '../tools/factory.js';\n\n/** Builds the tool set for workflow child agents (wired from gateway to avoid cycles). */\nexport function buildWorkflowChildTools(childOptions: BuildChildToolsOptions): AgentTool<any, any>[] {\n const childFactory = new AgentToolsFactory({\n workspace: childOptions.workspace,\n bus: childOptions.bus,\n getCurrentContext: () => null,\n getConfig: childOptions.getConfig,\n getPrimaryModel: () => childOptions.model,\n toolExecutorConfig: childOptions.toolExecutorConfig,\n });\n return childFactory.createAllTools({\n workspace: childOptions.workspace,\n getPrimaryModel: () => childOptions.model,\n disabledTools: new Set(['extensions']),\n });\n}\n"],"mappings":";;;AAMA,SAAgB,wBAAwB,cAA6D;AASnG,QAAO,IARkB,kBAAkB;EACzC,WAAW,aAAa;EACxB,KAAK,aAAa;EAClB,yBAAyB;EACzB,WAAW,aAAa;EACxB,uBAAuB,aAAa;EACpC,oBAAoB,aAAa;EAClC,CACkB,CAAC,eAAe;EACjC,WAAW,aAAa;EACxB,uBAAuB,aAAa;EACpC,eAAe,IAAI,IAAI,CAAC,aAAa,CAAC;EACvC,CAAC"}
1
+ {"version":3,"file":"workflow-child-tools.js","names":[],"sources":["../../../../src/agent/workflow/workflow-child-tools.ts"],"sourcesContent":["import type { AgentTool } from '@earendil-works/pi-agent-core';\n\nimport type { BuildChildToolsOptions } from '../child-agent-factory.js';\nimport { resolveDreamingRootForAgent } from '../memory/dreaming/scope.js';\nimport { AgentToolsFactory } from '../tools/factory.js';\n\n/** Builds the tool set for workflow child agents (wired from gateway to avoid cycles). */\nexport function buildWorkflowChildTools(childOptions: BuildChildToolsOptions): AgentTool<any, any>[] {\n const config = childOptions.getConfig();\n const dreamingRoot = config && childOptions.agentId\n ? resolveDreamingRootForAgent(config, childOptions.agentId)\n : undefined;\n const childFactory = new AgentToolsFactory({\n workspace: childOptions.workspace,\n bus: childOptions.bus,\n getCurrentContext: () => null,\n getConfig: childOptions.getConfig,\n getPrimaryModel: () => childOptions.model,\n toolExecutorConfig: childOptions.toolExecutorConfig,\n });\n return childFactory.createAllTools({\n workspace: childOptions.workspace,\n getPrimaryModel: () => childOptions.model,\n agentId: childOptions.agentId,\n dreamingRoot,\n disabledTools: new Set(['extensions']),\n });\n}\n"],"mappings":";;;;AAOA,SAAgB,wBAAwB,cAA6D;CACnG,MAAM,SAAS,aAAa,WAAW;CACvC,MAAM,eAAe,UAAU,aAAa,UACxC,4BAA4B,QAAQ,aAAa,QAAQ,GACzD,KAAA;AASJ,QAAO,IARkB,kBAAkB;EACzC,WAAW,aAAa;EACxB,KAAK,aAAa;EAClB,yBAAyB;EACzB,WAAW,aAAa;EACxB,uBAAuB,aAAa;EACpC,oBAAoB,aAAa;EAClC,CACkB,CAAC,eAAe;EACjC,WAAW,aAAa;EACxB,uBAAuB,aAAa;EACpC,SAAS,aAAa;EACtB;EACA,eAAe,IAAI,IAAI,CAAC,aAAa,CAAC;EACvC,CAAC"}
@@ -52,7 +52,7 @@ async function checkDatabaseSchema(ctx) {
52
52
  id: "database-schema",
53
53
  label: "Database schema",
54
54
  status: "pass",
55
- message: `SQLite schema v${status.dbVersion} (current release v21).`,
55
+ message: `SQLite schema v${status.dbVersion} (current release v23).`,
56
56
  hints: []
57
57
  };
58
58
  }
@@ -1,3 +1,4 @@
1
1
  import type { Config } from '../config/schema.js';
2
- import type { ConnectorHealthResult } from './types.js';
2
+ import type { ConnectorDefinition, ConnectorHealthResult, ConnectorInstallInput } from './types.js';
3
3
  export declare function testConnectorInstance(config: Config, serverId: string): Promise<ConnectorHealthResult>;
4
+ export declare function previewConnectorDefinition(config: Config, definition: ConnectorDefinition, input?: ConnectorInstallInput): Promise<ConnectorHealthResult>;
@@ -1,5 +1,6 @@
1
1
  import { listBundleMcpServerCapabilitiesForGateway } from "../agent/mcp/bundle-mcp-materialize.js";
2
2
  import { getWorkspacePath } from "../config/workspace-path-helpers.js";
3
+ import { materializeConnectorMcpServer } from "./materialize.js";
3
4
  import { getConnectorInstance } from "./instances.js";
4
5
  //#region src/connectors/health.ts
5
6
  function classifyConnectorHealthError(error) {
@@ -79,7 +80,64 @@ async function testConnectorInstance(config, serverId) {
79
80
  };
80
81
  }
81
82
  }
83
+ async function previewConnectorDefinition(config, definition, input = {}) {
84
+ if (definition.runtime.type !== "mcp") return {
85
+ serverId: definition.id,
86
+ ok: false,
87
+ status: "unknown_error",
88
+ toolCount: 0,
89
+ resourceCount: 0,
90
+ promptCount: 0,
91
+ tools: [],
92
+ resources: [],
93
+ prompts: [],
94
+ error: `Connector type "${definition.runtime.type}" does not support MCP capability preview.`
95
+ };
96
+ try {
97
+ const { serverId, server } = materializeConnectorMcpServer(definition, input);
98
+ const capabilities = await listBundleMcpServerCapabilitiesForGateway({
99
+ workspaceDir: getWorkspacePath(config) || "./workspace",
100
+ cfg: {
101
+ ...config,
102
+ mcp: {
103
+ ...config.mcp ?? {},
104
+ servers: {
105
+ ...config.mcp?.servers ?? {},
106
+ [serverId]: server
107
+ }
108
+ }
109
+ },
110
+ serverId
111
+ });
112
+ return {
113
+ serverId,
114
+ ok: true,
115
+ status: "ok",
116
+ toolCount: capabilities.toolCount,
117
+ resourceCount: capabilities.resourceCount,
118
+ promptCount: capabilities.promptCount,
119
+ tools: capabilities.tools,
120
+ resources: capabilities.resources,
121
+ prompts: capabilities.prompts
122
+ };
123
+ } catch (error) {
124
+ const status = classifyConnectorHealthError(error);
125
+ return {
126
+ serverId: definition.id,
127
+ ok: false,
128
+ status,
129
+ toolCount: 0,
130
+ resourceCount: 0,
131
+ promptCount: 0,
132
+ tools: [],
133
+ resources: [],
134
+ prompts: [],
135
+ error: error instanceof Error ? error.message : String(error),
136
+ action: healthActionForStatus(status)
137
+ };
138
+ }
139
+ }
82
140
  //#endregion
83
- export { testConnectorInstance };
141
+ export { previewConnectorDefinition, testConnectorInstance };
84
142
 
85
143
  //# sourceMappingURL=health.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"health.js","names":[],"sources":["../../../src/connectors/health.ts"],"sourcesContent":["import { getWorkspacePath } from '../config/workspace-path-helpers.js';\nimport {\n listBundleMcpServerCapabilitiesForGateway,\n} from '../agent/mcp/bundle-mcp-materialize.js';\nimport type { Config } from '../config/schema.js';\nimport { getConnectorInstance } from './instances.js';\nimport type { ConnectorHealthResult, ConnectorHealthStatus } from './types.js';\n\nfunction classifyConnectorHealthError(error: unknown): ConnectorHealthStatus {\n const message = error instanceof Error ? error.message : String(error);\n if (/timed out|timeout/i.test(message)) {\n return 'timeout';\n }\n if (/ECONN|ENOTFOUND|network|fetch failed/i.test(message)) {\n return 'network_failed';\n }\n if (/401|unauthorized|forbidden|permission denied/i.test(message)) {\n return 'unauthorized';\n }\n if (/missing|required|credential|api key|token/i.test(message)) {\n return 'missing_secret';\n }\n if (/tools|listTools/i.test(message)) {\n return 'tools_list_failed';\n }\n if (/spawn|command|start|connect/i.test(message)) {\n return 'startup_failed';\n }\n return 'unknown_error';\n}\n\nfunction healthActionForStatus(status: ConnectorHealthStatus): string | undefined {\n if (status === 'missing_secret') {\n return 'Reconnect the connector and provide the required secret.';\n }\n if (status === 'timeout' || status === 'network_failed') {\n return 'Check network access and retry the connector health check.';\n }\n if (status === 'startup_failed') {\n return 'Verify the connector runtime dependency is installed and reachable.';\n }\n if (status === 'unauthorized') {\n return 'Reconnect the connector or refresh its credentials.';\n }\n return undefined;\n}\n\nexport async function testConnectorInstance(config: Config, serverId: string): Promise<ConnectorHealthResult> {\n const instance = getConnectorInstance(config, serverId);\n if (!instance) {\n return {\n serverId,\n ok: false,\n status: 'server_not_found',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: `Connector instance not found: ${serverId}`,\n };\n }\n\n if (!instance.enabled) {\n return {\n serverId,\n ok: false,\n status: 'disabled',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n action: 'Enable the connector before running a health check.',\n };\n }\n\n const workspaceDir = getWorkspacePath(config) || './workspace';\n try {\n const capabilities = await listBundleMcpServerCapabilitiesForGateway({\n workspaceDir,\n cfg: config,\n serverId,\n });\n return {\n serverId,\n ok: true,\n status: 'ok',\n toolCount: capabilities.toolCount,\n resourceCount: capabilities.resourceCount,\n promptCount: capabilities.promptCount,\n tools: capabilities.tools,\n resources: capabilities.resources,\n prompts: capabilities.prompts,\n };\n } catch (error) {\n const status = classifyConnectorHealthError(error);\n return {\n serverId,\n ok: false,\n status,\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: error instanceof Error ? error.message : String(error),\n action: healthActionForStatus(status),\n };\n }\n}\n"],"mappings":";;;;AAQA,SAAS,6BAA6B,OAAuC;CAC3E,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,KAAI,qBAAqB,KAAK,QAAQ,CACpC,QAAO;AAET,KAAI,wCAAwC,KAAK,QAAQ,CACvD,QAAO;AAET,KAAI,gDAAgD,KAAK,QAAQ,CAC/D,QAAO;AAET,KAAI,6CAA6C,KAAK,QAAQ,CAC5D,QAAO;AAET,KAAI,mBAAmB,KAAK,QAAQ,CAClC,QAAO;AAET,KAAI,+BAA+B,KAAK,QAAQ,CAC9C,QAAO;AAET,QAAO;;AAGT,SAAS,sBAAsB,QAAmD;AAChF,KAAI,WAAW,iBACb,QAAO;AAET,KAAI,WAAW,aAAa,WAAW,iBACrC,QAAO;AAET,KAAI,WAAW,iBACb,QAAO;AAET,KAAI,WAAW,eACb,QAAO;;AAKX,eAAsB,sBAAsB,QAAgB,UAAkD;CAC5G,MAAM,WAAW,qBAAqB,QAAQ,SAAS;AACvD,KAAI,CAAC,SACH,QAAO;EACL;EACA,IAAI;EACJ,QAAQ;EACR,WAAW;EACX,eAAe;EACf,aAAa;EACb,OAAO,EAAE;EACT,WAAW,EAAE;EACb,SAAS,EAAE;EACX,OAAO,iCAAiC;EACzC;AAGH,KAAI,CAAC,SAAS,QACZ,QAAO;EACL;EACA,IAAI;EACJ,QAAQ;EACR,WAAW;EACX,eAAe;EACf,aAAa;EACb,OAAO,EAAE;EACT,WAAW,EAAE;EACb,SAAS,EAAE;EACX,QAAQ;EACT;CAGH,MAAM,eAAe,iBAAiB,OAAO,IAAI;AACjD,KAAI;EACF,MAAM,eAAe,MAAM,0CAA0C;GACnE;GACA,KAAK;GACL;GACD,CAAC;AACF,SAAO;GACL;GACA,IAAI;GACJ,QAAQ;GACR,WAAW,aAAa;GACxB,eAAe,aAAa;GAC5B,aAAa,aAAa;GAC1B,OAAO,aAAa;GACpB,WAAW,aAAa;GACxB,SAAS,aAAa;GACvB;UACM,OAAO;EACd,MAAM,SAAS,6BAA6B,MAAM;AAClD,SAAO;GACL;GACA,IAAI;GACJ;GACA,WAAW;GACX,eAAe;GACf,aAAa;GACb,OAAO,EAAE;GACT,WAAW,EAAE;GACb,SAAS,EAAE;GACX,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAC7D,QAAQ,sBAAsB,OAAO;GACtC"}
1
+ {"version":3,"file":"health.js","names":[],"sources":["../../../src/connectors/health.ts"],"sourcesContent":["import { getWorkspacePath } from '../config/workspace-path-helpers.js';\nimport {\n listBundleMcpServerCapabilitiesForGateway,\n} from '../agent/mcp/bundle-mcp-materialize.js';\nimport type { Config } from '../config/schema.js';\nimport { getConnectorInstance } from './instances.js';\nimport { materializeConnectorMcpServer } from './materialize.js';\nimport type { ConnectorDefinition, ConnectorHealthResult, ConnectorHealthStatus, ConnectorInstallInput } from './types.js';\n\nfunction classifyConnectorHealthError(error: unknown): ConnectorHealthStatus {\n const message = error instanceof Error ? error.message : String(error);\n if (/timed out|timeout/i.test(message)) {\n return 'timeout';\n }\n if (/ECONN|ENOTFOUND|network|fetch failed/i.test(message)) {\n return 'network_failed';\n }\n if (/401|unauthorized|forbidden|permission denied/i.test(message)) {\n return 'unauthorized';\n }\n if (/missing|required|credential|api key|token/i.test(message)) {\n return 'missing_secret';\n }\n if (/tools|listTools/i.test(message)) {\n return 'tools_list_failed';\n }\n if (/spawn|command|start|connect/i.test(message)) {\n return 'startup_failed';\n }\n return 'unknown_error';\n}\n\nfunction healthActionForStatus(status: ConnectorHealthStatus): string | undefined {\n if (status === 'missing_secret') {\n return 'Reconnect the connector and provide the required secret.';\n }\n if (status === 'timeout' || status === 'network_failed') {\n return 'Check network access and retry the connector health check.';\n }\n if (status === 'startup_failed') {\n return 'Verify the connector runtime dependency is installed and reachable.';\n }\n if (status === 'unauthorized') {\n return 'Reconnect the connector or refresh its credentials.';\n }\n return undefined;\n}\n\nexport async function testConnectorInstance(config: Config, serverId: string): Promise<ConnectorHealthResult> {\n const instance = getConnectorInstance(config, serverId);\n if (!instance) {\n return {\n serverId,\n ok: false,\n status: 'server_not_found',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: `Connector instance not found: ${serverId}`,\n };\n }\n\n if (!instance.enabled) {\n return {\n serverId,\n ok: false,\n status: 'disabled',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n action: 'Enable the connector before running a health check.',\n };\n }\n\n const workspaceDir = getWorkspacePath(config) || './workspace';\n try {\n const capabilities = await listBundleMcpServerCapabilitiesForGateway({\n workspaceDir,\n cfg: config,\n serverId,\n });\n return {\n serverId,\n ok: true,\n status: 'ok',\n toolCount: capabilities.toolCount,\n resourceCount: capabilities.resourceCount,\n promptCount: capabilities.promptCount,\n tools: capabilities.tools,\n resources: capabilities.resources,\n prompts: capabilities.prompts,\n };\n } catch (error) {\n const status = classifyConnectorHealthError(error);\n return {\n serverId,\n ok: false,\n status,\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: error instanceof Error ? error.message : String(error),\n action: healthActionForStatus(status),\n };\n }\n}\n\nexport async function previewConnectorDefinition(\n config: Config,\n definition: ConnectorDefinition,\n input: ConnectorInstallInput = {},\n): Promise<ConnectorHealthResult> {\n if (definition.runtime.type !== 'mcp') {\n return {\n serverId: definition.id,\n ok: false,\n status: 'unknown_error',\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: `Connector type \"${definition.runtime.type}\" does not support MCP capability preview.`,\n };\n }\n\n try {\n const { serverId, server } = materializeConnectorMcpServer(definition, input);\n const workspaceDir = getWorkspacePath(config) || './workspace';\n const previewConfig: Config = {\n ...config,\n mcp: {\n ...(config.mcp ?? {}),\n servers: {\n ...(config.mcp?.servers ?? {}),\n [serverId]: server,\n },\n },\n };\n const capabilities = await listBundleMcpServerCapabilitiesForGateway({\n workspaceDir,\n cfg: previewConfig,\n serverId,\n });\n return {\n serverId,\n ok: true,\n status: 'ok',\n toolCount: capabilities.toolCount,\n resourceCount: capabilities.resourceCount,\n promptCount: capabilities.promptCount,\n tools: capabilities.tools,\n resources: capabilities.resources,\n prompts: capabilities.prompts,\n };\n } catch (error) {\n const status = classifyConnectorHealthError(error);\n return {\n serverId: definition.id,\n ok: false,\n status,\n toolCount: 0,\n resourceCount: 0,\n promptCount: 0,\n tools: [],\n resources: [],\n prompts: [],\n error: error instanceof Error ? error.message : String(error),\n action: healthActionForStatus(status),\n };\n }\n}\n"],"mappings":"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"}
@@ -3,4 +3,5 @@ import type { Config } from '../config/schema.js';
3
3
  import type { ConnectorDefinition, ConnectorInstallInput, ConnectorInstance } from './types.js';
4
4
  export declare function installConnectorDefinition(config: Config, definition: ConnectorDefinition, input: ConnectorInstallInput, resolver?: CredentialResolver): Promise<ConnectorInstance>;
5
5
  export declare function installConnector(config: Config, connectorId: string, input: ConnectorInstallInput, resolver?: CredentialResolver): Promise<ConnectorInstance>;
6
+ export declare function updateConnectorConfig(config: Config, instanceId: string, input: ConnectorInstallInput): ConnectorInstance;
6
7
  export declare function uninstallConnector(config: Config, instanceId: string): ConnectorInstance;
@@ -51,6 +51,33 @@ async function installConnector(config, connectorId, input, resolver = new Crede
51
51
  if (!definition) throw new Error(`Unknown connector: ${connectorId}`);
52
52
  return installConnectorDefinition(config, definition, input, resolver);
53
53
  }
54
+ function updateConnectorConfig(config, instanceId, input) {
55
+ const existingServer = config.mcp?.servers?.[instanceId];
56
+ if (!existingServer || !isManagedConnectorServer(existingServer)) throw new Error(`MCP server "${instanceId}" is not managed by Connectors.`);
57
+ const definition = getConnectorDefinition(existingServer.xopcConnector.connectorId);
58
+ if (!definition) throw new Error(`Unknown connector: ${existingServer.xopcConnector.connectorId}`);
59
+ if (definition.runtime.type !== "mcp") throw new Error(`Connector type "${definition.runtime.type}" does not support config updates.`);
60
+ if ((definition.setup.secrets ?? []).length > 0) throw new Error("Connectors with secrets must be reinstalled to change configuration.");
61
+ const { serverId, server } = materializeConnectorMcpServer(definition, input);
62
+ if (serverId !== instanceId) throw new Error(`Connector config update cannot change server id from "${instanceId}" to "${serverId}".`);
63
+ config.mcp = config.mcp ?? {};
64
+ config.mcp.servers = {
65
+ ...config.mcp.servers ?? {},
66
+ [serverId]: {
67
+ ...server,
68
+ xopcConnector: {
69
+ ...existingServer.xopcConnector,
70
+ ...server.xopcConnector,
71
+ enabled: existingServer.xopcConnector.enabled,
72
+ lastConnectedAt: existingServer.xopcConnector.lastConnectedAt,
73
+ lastError: existingServer.xopcConnector.lastError
74
+ }
75
+ }
76
+ };
77
+ const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === serverId);
78
+ if (!instance) throw new Error(`Connector "${definition.id}" was updated but could not be resolved.`);
79
+ return instance;
80
+ }
54
81
  function uninstallConnector(config, instanceId) {
55
82
  const server = config.mcp?.servers?.[instanceId];
56
83
  const connectorRecord = config.connectors?.instances?.[instanceId];
@@ -78,6 +105,6 @@ function uninstallConnector(config, instanceId) {
78
105
  return instance;
79
106
  }
80
107
  //#endregion
81
- export { installConnector, installConnectorDefinition, uninstallConnector };
108
+ export { installConnector, installConnectorDefinition, uninstallConnector, updateConnectorConfig };
82
109
 
83
110
  //# sourceMappingURL=install.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","names":[],"sources":["../../../src/connectors/install.ts"],"sourcesContent":["import { CredentialResolver } from '../auth/credentials.js';\nimport type { Config } from '../config/schema.js';\nimport { getConnectorDefinition } from './catalog.js';\nimport { listConnectorInstances } from './instances.js';\nimport { isManagedConnectorServer, materializeConnectorMcpServer } from './materialize.js';\nimport { saveComposioApiKey } from './composio.js';\nimport { assertConnectorOAuthReady } from './oauth.js';\nimport { saveConnectorSecrets } from './secret-store.js';\nimport { appendConnectorAuditRecord } from './usage.js';\nimport type { ConnectorDefinition, ConnectorInstallInput, ConnectorInstance } from './types.js';\n\nexport async function installConnectorDefinition(\n config: Config,\n definition: ConnectorDefinition,\n input: ConnectorInstallInput,\n resolver = new CredentialResolver(),\n): Promise<ConnectorInstance> {\n if (definition.runtime.type !== 'mcp') {\n const instanceId = definition.id;\n if (definition.runtime.type === 'composio' && definition.id === 'composio-api-key') {\n await saveComposioApiKey(input, resolver);\n }\n config.connectors = config.connectors ?? {};\n config.connectors.instances = {\n ...(config.connectors.instances ?? {}),\n [instanceId]: {\n xopcConnector: {\n managed: true,\n connectorId: definition.id,\n version: definition.version,\n enabled: true,\n displayName: definition.displayName,\n },\n runtime: definition.runtime,\n ...(definition.runtime.type === 'composio' && definition.runtime.toolkit !== 'composio' ? { scope: 'read' } : {}),\n },\n };\n const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === instanceId);\n if (!instance) {\n throw new Error(`Connector \"${definition.id}\" was installed but could not be resolved.`);\n }\n return instance;\n }\n\n const { serverId, server } = materializeConnectorMcpServer(definition, input);\n const existingServer = config.mcp?.servers?.[serverId];\n if (existingServer && !isManagedConnectorServer(existingServer)) {\n throw new Error(`MCP server \"${serverId}\" already exists and is not managed by Connectors.`);\n }\n\n await assertConnectorOAuthReady(definition, resolver);\n await saveConnectorSecrets(definition, input, resolver);\n\n config.mcp = config.mcp ?? {};\n config.mcp.servers = {\n ...(config.mcp.servers ?? {}),\n [serverId]: server,\n };\n\n const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === serverId);\n if (!instance) {\n throw new Error(`Connector \"${definition.id}\" was installed but could not be resolved.`);\n }\n appendConnectorAuditRecord(config, serverId, { action: 'installed' });\n return instance;\n}\n\nexport async function installConnector(\n config: Config,\n connectorId: string,\n input: ConnectorInstallInput,\n resolver = new CredentialResolver(),\n): Promise<ConnectorInstance> {\n const definition = getConnectorDefinition(connectorId);\n if (!definition) {\n throw new Error(`Unknown connector: ${connectorId}`);\n }\n return installConnectorDefinition(config, definition, input, resolver);\n}\n\nexport function uninstallConnector(config: Config, instanceId: string): ConnectorInstance {\n const server = config.mcp?.servers?.[instanceId];\n const connectorRecord = config.connectors?.instances?.[instanceId];\n if (!server && !connectorRecord) {\n throw new Error(`Connector instance not found: ${instanceId}`);\n }\n if (server && !isManagedConnectorServer(server)) {\n throw new Error(`MCP server \"${instanceId}\" is not managed by Connectors.`);\n }\n\n const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === instanceId);\n if (!instance) {\n throw new Error(`Connector instance not found: ${instanceId}`);\n }\n appendConnectorAuditRecord(config, instanceId, { action: 'removed' });\n\n if (server) {\n const nextServers = { ...(config.mcp?.servers ?? {}) };\n delete nextServers[instanceId];\n config.mcp = {\n ...(config.mcp ?? {}),\n servers: nextServers,\n };\n }\n if (connectorRecord) {\n const nextInstances = { ...(config.connectors?.instances ?? {}) };\n delete nextInstances[instanceId];\n config.connectors = { ...(config.connectors ?? {}), instances: nextInstances };\n }\n return instance;\n}\n"],"mappings":";;;;;;;;;kBAA4D;AAW5D,eAAsB,2BACpB,QACA,YACA,OACA,WAAW,IAAI,oBAAoB,EACP;AAC5B,KAAI,WAAW,QAAQ,SAAS,OAAO;EACrC,MAAM,aAAa,WAAW;AAC9B,MAAI,WAAW,QAAQ,SAAS,cAAc,WAAW,OAAO,mBAC9D,OAAM,mBAAmB,OAAO,SAAS;AAE3C,SAAO,aAAa,OAAO,cAAc,EAAE;AAC3C,SAAO,WAAW,YAAY;GAC5B,GAAI,OAAO,WAAW,aAAa,EAAE;IACpC,aAAa;IACZ,eAAe;KACb,SAAS;KACT,aAAa,WAAW;KACxB,SAAS,WAAW;KACpB,SAAS;KACT,aAAa,WAAW;KACzB;IACD,SAAS,WAAW;IACpB,GAAI,WAAW,QAAQ,SAAS,cAAc,WAAW,QAAQ,YAAY,aAAa,EAAE,OAAO,QAAQ,GAAG,EAAE;IACjH;GACF;EACD,MAAM,WAAW,uBAAuB,OAAO,CAAC,MAAM,cAAc,UAAU,eAAe,WAAW;AACxG,MAAI,CAAC,SACH,OAAM,IAAI,MAAM,cAAc,WAAW,GAAG,4CAA4C;AAE1F,SAAO;;CAGT,MAAM,EAAE,UAAU,WAAW,8BAA8B,YAAY,MAAM;CAC7E,MAAM,iBAAiB,OAAO,KAAK,UAAU;AAC7C,KAAI,kBAAkB,CAAC,yBAAyB,eAAe,CAC7D,OAAM,IAAI,MAAM,eAAe,SAAS,oDAAoD;AAG9F,OAAM,0BAA0B,YAAY,SAAS;AACrD,OAAM,qBAAqB,YAAY,OAAO,SAAS;AAEvD,QAAO,MAAM,OAAO,OAAO,EAAE;AAC7B,QAAO,IAAI,UAAU;EACnB,GAAI,OAAO,IAAI,WAAW,EAAE;GAC3B,WAAW;EACb;CAED,MAAM,WAAW,uBAAuB,OAAO,CAAC,MAAM,cAAc,UAAU,eAAe,SAAS;AACtG,KAAI,CAAC,SACH,OAAM,IAAI,MAAM,cAAc,WAAW,GAAG,4CAA4C;AAE1F,4BAA2B,QAAQ,UAAU,EAAE,QAAQ,aAAa,CAAC;AACrE,QAAO;;AAGT,eAAsB,iBACpB,QACA,aACA,OACA,WAAW,IAAI,oBAAoB,EACP;CAC5B,MAAM,aAAa,uBAAuB,YAAY;AACtD,KAAI,CAAC,WACH,OAAM,IAAI,MAAM,sBAAsB,cAAc;AAEtD,QAAO,2BAA2B,QAAQ,YAAY,OAAO,SAAS;;AAGxE,SAAgB,mBAAmB,QAAgB,YAAuC;CACxF,MAAM,SAAS,OAAO,KAAK,UAAU;CACrC,MAAM,kBAAkB,OAAO,YAAY,YAAY;AACvD,KAAI,CAAC,UAAU,CAAC,gBACd,OAAM,IAAI,MAAM,iCAAiC,aAAa;AAEhE,KAAI,UAAU,CAAC,yBAAyB,OAAO,CAC7C,OAAM,IAAI,MAAM,eAAe,WAAW,iCAAiC;CAG7E,MAAM,WAAW,uBAAuB,OAAO,CAAC,MAAM,cAAc,UAAU,eAAe,WAAW;AACxG,KAAI,CAAC,SACH,OAAM,IAAI,MAAM,iCAAiC,aAAa;AAEhE,4BAA2B,QAAQ,YAAY,EAAE,QAAQ,WAAW,CAAC;AAErE,KAAI,QAAQ;EACV,MAAM,cAAc,EAAE,GAAI,OAAO,KAAK,WAAW,EAAE,EAAG;AACtD,SAAO,YAAY;AACnB,SAAO,MAAM;GACX,GAAI,OAAO,OAAO,EAAE;GACpB,SAAS;GACV;;AAEH,KAAI,iBAAiB;EACnB,MAAM,gBAAgB,EAAE,GAAI,OAAO,YAAY,aAAa,EAAE,EAAG;AACjE,SAAO,cAAc;AACrB,SAAO,aAAa;GAAE,GAAI,OAAO,cAAc,EAAE;GAAG,WAAW;GAAe;;AAEhF,QAAO"}
1
+ {"version":3,"file":"install.js","names":[],"sources":["../../../src/connectors/install.ts"],"sourcesContent":["import { CredentialResolver } from '../auth/credentials.js';\nimport type { Config } from '../config/schema.js';\nimport { getConnectorDefinition } from './catalog.js';\nimport { listConnectorInstances } from './instances.js';\nimport { isManagedConnectorServer, materializeConnectorMcpServer } from './materialize.js';\nimport { saveComposioApiKey } from './composio.js';\nimport { assertConnectorOAuthReady } from './oauth.js';\nimport { saveConnectorSecrets } from './secret-store.js';\nimport { appendConnectorAuditRecord } from './usage.js';\nimport type { ConnectorDefinition, ConnectorInstallInput, ConnectorInstance } from './types.js';\n\nexport async function installConnectorDefinition(\n config: Config,\n definition: ConnectorDefinition,\n input: ConnectorInstallInput,\n resolver = new CredentialResolver(),\n): Promise<ConnectorInstance> {\n if (definition.runtime.type !== 'mcp') {\n const instanceId = definition.id;\n if (definition.runtime.type === 'composio' && definition.id === 'composio-api-key') {\n await saveComposioApiKey(input, resolver);\n }\n config.connectors = config.connectors ?? {};\n config.connectors.instances = {\n ...(config.connectors.instances ?? {}),\n [instanceId]: {\n xopcConnector: {\n managed: true,\n connectorId: definition.id,\n version: definition.version,\n enabled: true,\n displayName: definition.displayName,\n },\n runtime: definition.runtime,\n ...(definition.runtime.type === 'composio' && definition.runtime.toolkit !== 'composio' ? { scope: 'read' } : {}),\n },\n };\n const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === instanceId);\n if (!instance) {\n throw new Error(`Connector \"${definition.id}\" was installed but could not be resolved.`);\n }\n return instance;\n }\n\n const { serverId, server } = materializeConnectorMcpServer(definition, input);\n const existingServer = config.mcp?.servers?.[serverId];\n if (existingServer && !isManagedConnectorServer(existingServer)) {\n throw new Error(`MCP server \"${serverId}\" already exists and is not managed by Connectors.`);\n }\n\n await assertConnectorOAuthReady(definition, resolver);\n await saveConnectorSecrets(definition, input, resolver);\n\n config.mcp = config.mcp ?? {};\n config.mcp.servers = {\n ...(config.mcp.servers ?? {}),\n [serverId]: server,\n };\n\n const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === serverId);\n if (!instance) {\n throw new Error(`Connector \"${definition.id}\" was installed but could not be resolved.`);\n }\n appendConnectorAuditRecord(config, serverId, { action: 'installed' });\n return instance;\n}\n\nexport async function installConnector(\n config: Config,\n connectorId: string,\n input: ConnectorInstallInput,\n resolver = new CredentialResolver(),\n): Promise<ConnectorInstance> {\n const definition = getConnectorDefinition(connectorId);\n if (!definition) {\n throw new Error(`Unknown connector: ${connectorId}`);\n }\n return installConnectorDefinition(config, definition, input, resolver);\n}\n\nexport function updateConnectorConfig(\n config: Config,\n instanceId: string,\n input: ConnectorInstallInput,\n): ConnectorInstance {\n const existingServer = config.mcp?.servers?.[instanceId];\n if (!existingServer || !isManagedConnectorServer(existingServer)) {\n throw new Error(`MCP server \"${instanceId}\" is not managed by Connectors.`);\n }\n const definition = getConnectorDefinition(existingServer.xopcConnector.connectorId);\n if (!definition) {\n throw new Error(`Unknown connector: ${existingServer.xopcConnector.connectorId}`);\n }\n if (definition.runtime.type !== 'mcp') {\n throw new Error(`Connector type \"${definition.runtime.type}\" does not support config updates.`);\n }\n if ((definition.setup.secrets ?? []).length > 0) {\n throw new Error('Connectors with secrets must be reinstalled to change configuration.');\n }\n\n const { serverId, server } = materializeConnectorMcpServer(definition, input);\n if (serverId !== instanceId) {\n throw new Error(`Connector config update cannot change server id from \"${instanceId}\" to \"${serverId}\".`);\n }\n\n config.mcp = config.mcp ?? {};\n config.mcp.servers = {\n ...(config.mcp.servers ?? {}),\n [serverId]: {\n ...server,\n xopcConnector: {\n ...existingServer.xopcConnector,\n ...(server.xopcConnector as Record<string, unknown>),\n enabled: existingServer.xopcConnector.enabled,\n lastConnectedAt: existingServer.xopcConnector.lastConnectedAt,\n lastError: existingServer.xopcConnector.lastError,\n },\n },\n };\n\n const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === serverId);\n if (!instance) {\n throw new Error(`Connector \"${definition.id}\" was updated but could not be resolved.`);\n }\n return instance;\n}\n\nexport function uninstallConnector(config: Config, instanceId: string): ConnectorInstance {\n const server = config.mcp?.servers?.[instanceId];\n const connectorRecord = config.connectors?.instances?.[instanceId];\n if (!server && !connectorRecord) {\n throw new Error(`Connector instance not found: ${instanceId}`);\n }\n if (server && !isManagedConnectorServer(server)) {\n throw new Error(`MCP server \"${instanceId}\" is not managed by Connectors.`);\n }\n\n const instance = listConnectorInstances(config).find((candidate) => candidate.instanceId === instanceId);\n if (!instance) {\n throw new Error(`Connector instance not found: ${instanceId}`);\n }\n appendConnectorAuditRecord(config, instanceId, { action: 'removed' });\n\n if (server) {\n const nextServers = { ...(config.mcp?.servers ?? {}) };\n delete nextServers[instanceId];\n config.mcp = {\n ...(config.mcp ?? {}),\n servers: nextServers,\n };\n }\n if (connectorRecord) {\n const nextInstances = { ...(config.connectors?.instances ?? {}) };\n delete nextInstances[instanceId];\n config.connectors = { ...(config.connectors ?? {}), instances: nextInstances };\n }\n return instance;\n}\n"],"mappings":"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"}
@@ -2,6 +2,11 @@ import { getConnectorDefinition } from "./catalog.js";
2
2
  import { isManagedConnectorServer } from "./materialize.js";
3
3
  import { getConnectorAuditFromMarker, getConnectorUsageFromMarker } from "./usage.js";
4
4
  //#region src/connectors/instances.ts
5
+ function readMarkerConfig(marker) {
6
+ if (!marker || typeof marker !== "object" || Array.isArray(marker)) return void 0;
7
+ const config = marker.config;
8
+ return config && typeof config === "object" && !Array.isArray(config) ? config : void 0;
9
+ }
5
10
  function secretStatusForServer(server) {
6
11
  const marker = server.xopcConnector;
7
12
  const definition = marker?.connectorId ? getConnectorDefinition(marker.connectorId) : void 0;
@@ -34,6 +39,7 @@ function connectorInstanceFromRecord(instanceId, record) {
34
39
  lastConnectedAt: typeof markerRecord.lastConnectedAt === "string" ? markerRecord.lastConnectedAt : void 0,
35
40
  lastError: typeof markerRecord.lastError === "string" ? markerRecord.lastError : void 0,
36
41
  secretStatus: {},
42
+ config: readMarkerConfig(markerRecord),
37
43
  materialized: runtimeType === "composio" ? {
38
44
  type: "composio",
39
45
  id: instanceId
@@ -74,6 +80,7 @@ function listConnectorInstances(config) {
74
80
  lastConnectedAt: server.xopcConnector.lastConnectedAt,
75
81
  lastError: server.xopcConnector.lastError,
76
82
  secretStatus: secretStatusForServer(server),
83
+ config: readMarkerConfig(server.xopcConnector),
77
84
  materialized: {
78
85
  type: "mcp",
79
86
  serverId
@@ -1 +1 @@
1
- {"version":3,"file":"instances.js","names":[],"sources":["../../../src/connectors/instances.ts"],"sourcesContent":["import type { Config } from '../config/schema.js';\nimport { getConnectorDefinition } from './catalog.js';\nimport { isManagedConnectorServer } from './materialize.js';\nimport { getConnectorAuditFromMarker, getConnectorUsageFromMarker } from './usage.js';\nimport type { ConnectorInstance } from './types.js';\n\nfunction secretStatusForServer(server: Record<string, unknown>): Record<string, boolean> {\n const marker = server.xopcConnector as { connectorId?: string } | undefined;\n const definition = marker?.connectorId ? getConnectorDefinition(marker.connectorId) : undefined;\n const env = server.env && typeof server.env === 'object' && !Array.isArray(server.env)\n ? (server.env as Record<string, unknown>)\n : {};\n const status: Record<string, boolean> = {};\n for (const secret of definition?.setup.secrets ?? []) {\n const value = env[secret.key];\n status[secret.key] = Boolean(\n value &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n 'xopcSecretRef' in value,\n );\n }\n return status;\n}\n\nfunction connectorInstanceFromRecord(instanceId: string, record: Record<string, unknown>): ConnectorInstance[] {\n const marker = record.xopcConnector;\n if (!marker || typeof marker !== 'object' || Array.isArray(marker)) return [];\n const markerRecord = marker as Record<string, unknown>;\n if (markerRecord.managed !== true || typeof markerRecord.connectorId !== 'string') return [];\n const connectorId = markerRecord.connectorId;\n const definition = getConnectorDefinition(connectorId);\n const runtime = record.runtime && typeof record.runtime === 'object' && !Array.isArray(record.runtime)\n ? record.runtime as Record<string, unknown>\n : {};\n const runtimeType = typeof runtime.type === 'string' ? runtime.type : 'composio';\n const enabled = markerRecord.enabled !== false;\n return [{\n instanceId,\n connectorId,\n displayName: definition?.displayName ?? (typeof markerRecord.displayName === 'string' ? markerRecord.displayName : connectorId),\n enabled,\n status: enabled ? 'installed' : 'disabled',\n connectionStatus: enabled ? 'unknown' : 'disabled',\n authStatus: definition?.auth.mode === 'none' ? 'none' : 'unknown',\n lastConnectedAt: typeof markerRecord.lastConnectedAt === 'string' ? markerRecord.lastConnectedAt : undefined,\n lastError: typeof markerRecord.lastError === 'string' ? markerRecord.lastError : undefined,\n secretStatus: {},\n materialized: runtimeType === 'composio'\n ? { type: 'composio', id: instanceId }\n : runtimeType === 'channel'\n ? { type: 'channel', id: instanceId }\n : runtimeType === 'nativeTool'\n ? { type: 'nativeTool', id: instanceId }\n : { type: 'memorySource', id: instanceId },\n usage: getConnectorUsageFromMarker(marker),\n audit: getConnectorAuditFromMarker(marker),\n }];\n}\n\nexport function listConnectorInstances(config: Config): ConnectorInstance[] {\n const servers = config.mcp?.servers ?? {};\n const mcpInstances = Object.entries(servers)\n .flatMap(([serverId, server]) => {\n if (!isManagedConnectorServer(server)) {\n return [];\n }\n const connectorId = server.xopcConnector.connectorId;\n const definition = getConnectorDefinition(connectorId);\n const enabled = server.xopcConnector.enabled !== false;\n const usage = getConnectorUsageFromMarker(server.xopcConnector);\n const lastHealthStatus = usage.lastHealthStatus;\n const connectionStatus: ConnectorInstance['connectionStatus'] = !enabled\n ? 'disabled'\n : lastHealthStatus === 'ok'\n ? 'connected'\n : lastHealthStatus === 'unauthorized'\n ? 'unauthorized'\n : lastHealthStatus\n ? 'error'\n : 'unknown';\n const authStatus: ConnectorInstance['authStatus'] = definition?.auth.mode === 'none'\n ? 'none'\n : lastHealthStatus === 'missing_secret'\n ? 'missing'\n : lastHealthStatus === 'unauthorized'\n ? 'unauthorized'\n : 'unknown';\n const status: ConnectorInstance['status'] = enabled ? (lastHealthStatus === 'ok' ? 'connected' : 'installed') : 'disabled';\n return [\n {\n instanceId: serverId,\n connectorId,\n displayName: definition?.displayName ?? server.xopcConnector.displayName ?? connectorId,\n enabled,\n status,\n connectionStatus,\n authStatus,\n lastConnectedAt: server.xopcConnector.lastConnectedAt,\n lastError: server.xopcConnector.lastError,\n secretStatus: secretStatusForServer(server),\n materialized: {\n type: 'mcp' as const,\n serverId,\n },\n usage,\n audit: getConnectorAuditFromMarker(server.xopcConnector),\n },\n ];\n });\n const genericInstances = Object.entries(config.connectors?.instances ?? {})\n .flatMap(([instanceId, record]) => (\n record && typeof record === 'object' && !Array.isArray(record)\n ? connectorInstanceFromRecord(instanceId, record as Record<string, unknown>)\n : []\n ));\n return [...mcpInstances, ...genericInstances]\n .sort((left, right) => left.displayName.localeCompare(right.displayName));\n}\n\nexport function getConnectorInstance(config: Config, instanceId: string): ConnectorInstance | undefined {\n return listConnectorInstances(config).find((instance) => instance.instanceId === instanceId);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"instances.js","names":[],"sources":["../../../src/connectors/instances.ts"],"sourcesContent":["import type { Config } from '../config/schema.js';\nimport { getConnectorDefinition } from './catalog.js';\nimport { isManagedConnectorServer } from './materialize.js';\nimport { getConnectorAuditFromMarker, getConnectorUsageFromMarker } from './usage.js';\nimport type { ConnectorInstance } from './types.js';\n\nfunction readMarkerConfig(marker: unknown): Record<string, unknown> | undefined {\n if (!marker || typeof marker !== 'object' || Array.isArray(marker)) return undefined;\n const config = (marker as Record<string, unknown>).config;\n return config && typeof config === 'object' && !Array.isArray(config)\n ? config as Record<string, unknown>\n : undefined;\n}\n\nfunction secretStatusForServer(server: Record<string, unknown>): Record<string, boolean> {\n const marker = server.xopcConnector as { connectorId?: string } | undefined;\n const definition = marker?.connectorId ? getConnectorDefinition(marker.connectorId) : undefined;\n const env = server.env && typeof server.env === 'object' && !Array.isArray(server.env)\n ? (server.env as Record<string, unknown>)\n : {};\n const status: Record<string, boolean> = {};\n for (const secret of definition?.setup.secrets ?? []) {\n const value = env[secret.key];\n status[secret.key] = Boolean(\n value &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n 'xopcSecretRef' in value,\n );\n }\n return status;\n}\n\nfunction connectorInstanceFromRecord(instanceId: string, record: Record<string, unknown>): ConnectorInstance[] {\n const marker = record.xopcConnector;\n if (!marker || typeof marker !== 'object' || Array.isArray(marker)) return [];\n const markerRecord = marker as Record<string, unknown>;\n if (markerRecord.managed !== true || typeof markerRecord.connectorId !== 'string') return [];\n const connectorId = markerRecord.connectorId;\n const definition = getConnectorDefinition(connectorId);\n const runtime = record.runtime && typeof record.runtime === 'object' && !Array.isArray(record.runtime)\n ? record.runtime as Record<string, unknown>\n : {};\n const runtimeType = typeof runtime.type === 'string' ? runtime.type : 'composio';\n const enabled = markerRecord.enabled !== false;\n return [{\n instanceId,\n connectorId,\n displayName: definition?.displayName ?? (typeof markerRecord.displayName === 'string' ? markerRecord.displayName : connectorId),\n enabled,\n status: enabled ? 'installed' : 'disabled',\n connectionStatus: enabled ? 'unknown' : 'disabled',\n authStatus: definition?.auth.mode === 'none' ? 'none' : 'unknown',\n lastConnectedAt: typeof markerRecord.lastConnectedAt === 'string' ? markerRecord.lastConnectedAt : undefined,\n lastError: typeof markerRecord.lastError === 'string' ? markerRecord.lastError : undefined,\n secretStatus: {},\n config: readMarkerConfig(markerRecord),\n materialized: runtimeType === 'composio'\n ? { type: 'composio', id: instanceId }\n : runtimeType === 'channel'\n ? { type: 'channel', id: instanceId }\n : runtimeType === 'nativeTool'\n ? { type: 'nativeTool', id: instanceId }\n : { type: 'memorySource', id: instanceId },\n usage: getConnectorUsageFromMarker(marker),\n audit: getConnectorAuditFromMarker(marker),\n }];\n}\n\nexport function listConnectorInstances(config: Config): ConnectorInstance[] {\n const servers = config.mcp?.servers ?? {};\n const mcpInstances = Object.entries(servers)\n .flatMap(([serverId, server]) => {\n if (!isManagedConnectorServer(server)) {\n return [];\n }\n const connectorId = server.xopcConnector.connectorId;\n const definition = getConnectorDefinition(connectorId);\n const enabled = server.xopcConnector.enabled !== false;\n const usage = getConnectorUsageFromMarker(server.xopcConnector);\n const lastHealthStatus = usage.lastHealthStatus;\n const connectionStatus: ConnectorInstance['connectionStatus'] = !enabled\n ? 'disabled'\n : lastHealthStatus === 'ok'\n ? 'connected'\n : lastHealthStatus === 'unauthorized'\n ? 'unauthorized'\n : lastHealthStatus\n ? 'error'\n : 'unknown';\n const authStatus: ConnectorInstance['authStatus'] = definition?.auth.mode === 'none'\n ? 'none'\n : lastHealthStatus === 'missing_secret'\n ? 'missing'\n : lastHealthStatus === 'unauthorized'\n ? 'unauthorized'\n : 'unknown';\n const status: ConnectorInstance['status'] = enabled ? (lastHealthStatus === 'ok' ? 'connected' : 'installed') : 'disabled';\n return [\n {\n instanceId: serverId,\n connectorId,\n displayName: definition?.displayName ?? server.xopcConnector.displayName ?? connectorId,\n enabled,\n status,\n connectionStatus,\n authStatus,\n lastConnectedAt: server.xopcConnector.lastConnectedAt,\n lastError: server.xopcConnector.lastError,\n secretStatus: secretStatusForServer(server),\n config: readMarkerConfig(server.xopcConnector),\n materialized: {\n type: 'mcp' as const,\n serverId,\n },\n usage,\n audit: getConnectorAuditFromMarker(server.xopcConnector),\n },\n ];\n });\n const genericInstances = Object.entries(config.connectors?.instances ?? {})\n .flatMap(([instanceId, record]) => (\n record && typeof record === 'object' && !Array.isArray(record)\n ? connectorInstanceFromRecord(instanceId, record as Record<string, unknown>)\n : []\n ));\n return [...mcpInstances, ...genericInstances]\n .sort((left, right) => left.displayName.localeCompare(right.displayName));\n}\n\nexport function getConnectorInstance(config: Config, instanceId: string): ConnectorInstance | undefined {\n return listConnectorInstances(config).find((instance) => instance.instanceId === instanceId);\n}\n"],"mappings":"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"}
@@ -53,7 +53,8 @@ function materializeConnectorMcpServer(definition, input) {
53
53
  managed: true,
54
54
  connectorId: definition.id,
55
55
  version: definition.version,
56
- displayName: definition.displayName
56
+ displayName: definition.displayName,
57
+ ...input.config && Object.keys(input.config).length > 0 ? { config: input.config } : {}
57
58
  };
58
59
  const server = {
59
60
  ...rawServer,
@@ -1 +1 @@
1
- {"version":3,"file":"materialize.js","names":[],"sources":["../../../src/connectors/materialize.ts"],"sourcesContent":["import { McpServerSchema } from '../config/schema.js';\nimport { createConnectorSecretReference } from './secret-store.js';\nimport type { ConnectorDefinition, ConnectorInstallInput, ManagedConnectorMarker } from './types.js';\n\nconst SERVER_ID_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;\nconst TEMPLATE_PATTERN = /^\\{\\{(secrets|config)\\.([A-Za-z0-9_.-]+)\\}\\}$/;\n\nexport function assertValidConnectorServerId(serverId: string): void {\n if (!SERVER_ID_PATTERN.test(serverId)) {\n throw new Error('Connector server name must start with a lowercase letter and only contain lowercase letters, numbers, dashes, and underscores.');\n }\n}\n\nfunction readInputValue(\n definition: ConnectorDefinition,\n input: ConnectorInstallInput,\n scope: 'secrets' | 'config',\n key: string,\n): unknown {\n if (scope === 'secrets') {\n return createConnectorSecretReference(definition.id, key);\n }\n return input.config?.[key];\n}\n\nfunction resolveTemplateValue(value: unknown, definition: ConnectorDefinition, input: ConnectorInstallInput): unknown {\n if (typeof value !== 'string') {\n return value;\n }\n const match = TEMPLATE_PATTERN.exec(value.trim());\n if (!match) {\n return value;\n }\n return readInputValue(definition, input, match[1] as 'secrets' | 'config', match[2]);\n}\n\nfunction materializeTemplate(value: unknown, definition: ConnectorDefinition, input: ConnectorInstallInput): unknown {\n const resolved = resolveTemplateValue(value, definition, input);\n if (Array.isArray(resolved)) {\n return resolved.map((item) => materializeTemplate(item, definition, input));\n }\n if (resolved && typeof resolved === 'object') {\n const output: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(resolved as Record<string, unknown>)) {\n const materializedChild = materializeTemplate(child, definition, input);\n if (materializedChild !== undefined) {\n output[key] = materializedChild;\n }\n }\n return output;\n }\n return resolved;\n}\n\nfunction assertRequiredInputs(definition: ConnectorDefinition, input: ConnectorInstallInput): void {\n for (const secret of definition.setup.secrets ?? []) {\n const value = input.secrets?.[secret.key];\n if (secret.required && (typeof value !== 'string' || value.trim().length === 0)) {\n throw new Error(`Missing required secret: ${secret.key}`);\n }\n }\n for (const field of definition.setup.config ?? []) {\n const value = input.config?.[field.key];\n if (field.required && (value === undefined || value === null || value === '')) {\n throw new Error(`Missing required config: ${field.key}`);\n }\n }\n}\n\nexport function materializeConnectorMcpServer(\n definition: ConnectorDefinition,\n input: ConnectorInstallInput,\n): { serverId: string; server: Record<string, unknown> } {\n assertRequiredInputs(definition, input);\n if (definition.runtime.type !== 'mcp') {\n throw new Error(`Unsupported connector runtime: ${definition.runtime.type}`);\n }\n\n const rawServerId = materializeTemplate(definition.runtime.serverId, definition, input);\n if (typeof rawServerId !== 'string') {\n throw new Error('Connector server name must be a string.');\n }\n const serverId = rawServerId.trim();\n assertValidConnectorServerId(serverId);\n\n const rawServer = materializeTemplate(definition.runtime.serverTemplate, definition, input);\n if (!rawServer || typeof rawServer !== 'object' || Array.isArray(rawServer)) {\n throw new Error('Connector MCP server template must resolve to a JSON object.');\n }\n\n const marker: ManagedConnectorMarker = {\n managed: true,\n connectorId: definition.id,\n version: definition.version,\n displayName: definition.displayName,\n };\n const server = {\n ...(rawServer as Record<string, unknown>),\n xopcConnector: marker,\n };\n const parsed = McpServerSchema.safeParse(server);\n if (!parsed.success) {\n throw new Error(parsed.error.issues[0]?.message ?? 'Invalid MCP server config.');\n }\n return { serverId, server };\n}\n\nexport function isManagedConnectorServer(server: unknown): server is Record<string, unknown> & { xopcConnector: ManagedConnectorMarker } {\n if (!server || typeof server !== 'object' || Array.isArray(server)) {\n return false;\n }\n const marker = (server as Record<string, unknown>).xopcConnector;\n return Boolean(\n marker &&\n typeof marker === 'object' &&\n !Array.isArray(marker) &&\n (marker as Record<string, unknown>).managed === true &&\n typeof (marker as Record<string, unknown>).connectorId === 'string',\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"materialize.js","names":[],"sources":["../../../src/connectors/materialize.ts"],"sourcesContent":["import { McpServerSchema } from '../config/schema.js';\nimport { createConnectorSecretReference } from './secret-store.js';\nimport type { ConnectorDefinition, ConnectorInstallInput, ManagedConnectorMarker } from './types.js';\n\nconst SERVER_ID_PATTERN = /^[a-z][a-z0-9_-]{0,63}$/;\nconst TEMPLATE_PATTERN = /^\\{\\{(secrets|config)\\.([A-Za-z0-9_.-]+)\\}\\}$/;\n\nexport function assertValidConnectorServerId(serverId: string): void {\n if (!SERVER_ID_PATTERN.test(serverId)) {\n throw new Error('Connector server name must start with a lowercase letter and only contain lowercase letters, numbers, dashes, and underscores.');\n }\n}\n\nfunction readInputValue(\n definition: ConnectorDefinition,\n input: ConnectorInstallInput,\n scope: 'secrets' | 'config',\n key: string,\n): unknown {\n if (scope === 'secrets') {\n return createConnectorSecretReference(definition.id, key);\n }\n return input.config?.[key];\n}\n\nfunction resolveTemplateValue(value: unknown, definition: ConnectorDefinition, input: ConnectorInstallInput): unknown {\n if (typeof value !== 'string') {\n return value;\n }\n const match = TEMPLATE_PATTERN.exec(value.trim());\n if (!match) {\n return value;\n }\n return readInputValue(definition, input, match[1] as 'secrets' | 'config', match[2]);\n}\n\nfunction materializeTemplate(value: unknown, definition: ConnectorDefinition, input: ConnectorInstallInput): unknown {\n const resolved = resolveTemplateValue(value, definition, input);\n if (Array.isArray(resolved)) {\n return resolved.map((item) => materializeTemplate(item, definition, input));\n }\n if (resolved && typeof resolved === 'object') {\n const output: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(resolved as Record<string, unknown>)) {\n const materializedChild = materializeTemplate(child, definition, input);\n if (materializedChild !== undefined) {\n output[key] = materializedChild;\n }\n }\n return output;\n }\n return resolved;\n}\n\nfunction assertRequiredInputs(definition: ConnectorDefinition, input: ConnectorInstallInput): void {\n for (const secret of definition.setup.secrets ?? []) {\n const value = input.secrets?.[secret.key];\n if (secret.required && (typeof value !== 'string' || value.trim().length === 0)) {\n throw new Error(`Missing required secret: ${secret.key}`);\n }\n }\n for (const field of definition.setup.config ?? []) {\n const value = input.config?.[field.key];\n if (field.required && (value === undefined || value === null || value === '')) {\n throw new Error(`Missing required config: ${field.key}`);\n }\n }\n}\n\nexport function materializeConnectorMcpServer(\n definition: ConnectorDefinition,\n input: ConnectorInstallInput,\n): { serverId: string; server: Record<string, unknown> } {\n assertRequiredInputs(definition, input);\n if (definition.runtime.type !== 'mcp') {\n throw new Error(`Unsupported connector runtime: ${definition.runtime.type}`);\n }\n\n const rawServerId = materializeTemplate(definition.runtime.serverId, definition, input);\n if (typeof rawServerId !== 'string') {\n throw new Error('Connector server name must be a string.');\n }\n const serverId = rawServerId.trim();\n assertValidConnectorServerId(serverId);\n\n const rawServer = materializeTemplate(definition.runtime.serverTemplate, definition, input);\n if (!rawServer || typeof rawServer !== 'object' || Array.isArray(rawServer)) {\n throw new Error('Connector MCP server template must resolve to a JSON object.');\n }\n\n const marker: ManagedConnectorMarker = {\n managed: true,\n connectorId: definition.id,\n version: definition.version,\n displayName: definition.displayName,\n ...(input.config && Object.keys(input.config).length > 0 ? { config: input.config } : {}),\n };\n const server = {\n ...(rawServer as Record<string, unknown>),\n xopcConnector: marker,\n };\n const parsed = McpServerSchema.safeParse(server);\n if (!parsed.success) {\n throw new Error(parsed.error.issues[0]?.message ?? 'Invalid MCP server config.');\n }\n return { serverId, server };\n}\n\nexport function isManagedConnectorServer(server: unknown): server is Record<string, unknown> & { xopcConnector: ManagedConnectorMarker } {\n if (!server || typeof server !== 'object' || Array.isArray(server)) {\n return false;\n }\n const marker = (server as Record<string, unknown>).xopcConnector;\n return Boolean(\n marker &&\n typeof marker === 'object' &&\n !Array.isArray(marker) &&\n (marker as Record<string, unknown>).managed === true &&\n typeof (marker as Record<string, unknown>).connectorId === 'string',\n );\n}\n"],"mappings":"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"}
@@ -12,6 +12,9 @@ function readArray(value) {
12
12
  function readRecord(value) {
13
13
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
14
14
  }
15
+ function isHttpUrl(value) {
16
+ return value?.startsWith("http://") || value?.startsWith("https://") || false;
17
+ }
15
18
  function slugFrom(value) {
16
19
  return value.trim().toLowerCase().replace(/^@/, "").replace(/[^a-z0-9_-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "modelscope-mcp";
17
20
  }
@@ -38,18 +41,29 @@ function secretFieldsFromEnvSchema(schema) {
38
41
  };
39
42
  });
40
43
  }
41
- function firstMcpServerConfig(server) {
42
- for (const config of readArray(server.ServerConfig ?? server.serverConfig)) {
43
- const mcpServers = readRecord(readRecord(config)?.mcpServers);
44
- if (!mcpServers) continue;
44
+ function readMcpServerConfigs(value) {
45
+ const configItems = Array.isArray(value) ? value : [value];
46
+ const configs = [];
47
+ for (const config of configItems) {
48
+ const configRecord = readRecord(config);
49
+ if (!configRecord) continue;
50
+ const mcpServers = readRecord(configRecord?.mcpServers);
51
+ if (!mcpServers) {
52
+ configs.push(configRecord);
53
+ continue;
54
+ }
45
55
  for (const value of Object.values(mcpServers)) {
46
56
  const serverConfig = readRecord(value);
47
- if (serverConfig && readString(serverConfig.command)) return serverConfig;
57
+ if (serverConfig) configs.push(serverConfig);
48
58
  }
49
59
  }
60
+ return configs;
61
+ }
62
+ function firstMcpServerConfig(server, predicate = (config) => Boolean(readString(config.command))) {
63
+ for (const config of readMcpServerConfigs(server.ServerConfig ?? server.serverConfig)) if (predicate(config)) return config;
50
64
  }
51
65
  function secretFieldsFromServerConfig(server) {
52
- const env = readRecord(firstMcpServerConfig(server)?.env);
66
+ const env = readRecord((firstMcpServerConfig(server, (candidate) => Boolean(readRecord(candidate.env))) ?? firstMcpServerConfig(server))?.env);
53
67
  if (!env) return [];
54
68
  return Object.keys(env).map((key) => ({
55
69
  key,
@@ -77,9 +91,12 @@ function normalizeEnv(env, secrets) {
77
91
  for (const field of secrets) if (output[field.key] === void 0) output[field.key] = `{{secrets.${field.key}}}`;
78
92
  return Object.keys(output).length ? output : void 0;
79
93
  }
94
+ function transportFromConfig(config, fallback) {
95
+ return (readString(config.transport ?? config.type)?.toLowerCase())?.includes("sse") ? "sse" : fallback;
96
+ }
80
97
  function normalizeServerTemplate(server, secrets) {
81
98
  const deployedUrl = readString(server.DeployedUrl ?? server.deployedUrl);
82
- if (deployedUrl?.startsWith("http://") || deployedUrl?.startsWith("https://")) return {
99
+ if (isHttpUrl(deployedUrl)) return {
83
100
  url: deployedUrl,
84
101
  transport: readString(server.DeployedUrlTransportType ?? server.deployedUrlTransportType)?.toLowerCase() === "sse" ? "sse" : "streamable-http"
85
102
  };
@@ -89,13 +106,21 @@ function normalizeServerTemplate(server, secrets) {
89
106
  "SSEServerConfig",
90
107
  "sseServerConfig"
91
108
  ]) {
92
- const config = readRecord(server[key]);
93
- const url = readString(config?.url ?? config?.endpoint);
94
- if (url?.startsWith("http://") || url?.startsWith("https://")) return {
95
- url,
96
- transport: key.toLowerCase().includes("sse") ? "sse" : "streamable-http"
97
- };
109
+ const fallbackTransport = key.toLowerCase().includes("sse") ? "sse" : "streamable-http";
110
+ for (const config of readMcpServerConfigs(server[key])) {
111
+ const url = readString(config.url ?? config.endpoint);
112
+ if (isHttpUrl(url)) return {
113
+ url,
114
+ transport: transportFromConfig(config, fallbackTransport)
115
+ };
116
+ }
98
117
  }
118
+ const remoteConfig = firstMcpServerConfig(server, (candidate) => isHttpUrl(readString(candidate.url ?? candidate.endpoint)));
119
+ const remoteUrl = readString(remoteConfig?.url ?? remoteConfig?.endpoint);
120
+ if (isHttpUrl(remoteUrl) && remoteConfig) return {
121
+ url: remoteUrl,
122
+ transport: transportFromConfig(remoteConfig, "streamable-http")
123
+ };
99
124
  const config = firstMcpServerConfig(server);
100
125
  const command = readString(config?.command);
101
126
  if (!command) return void 0;