@xopcai/xopc 0.0.117 → 0.0.119

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (590) hide show
  1. package/README.md +26 -24
  2. package/README.zh-CN.md +46 -42
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/telegram/xopc.extension.json +1 -1
  5. package/dist/gateway/static/root/assets/{agent-avatar-dicebear-BBLhJ2C6.js → agent-avatar-dicebear-CU8J6zou.js} +1 -1
  6. package/dist/gateway/static/root/assets/agents-B0hkpLhP.js +2 -0
  7. package/dist/gateway/static/root/assets/app-management-settings-panel-B9vfYoEr.js +1 -0
  8. package/dist/gateway/static/root/assets/appearance-settings-ClOzIO24.js +1 -0
  9. package/dist/gateway/static/root/assets/{apps-page-DdDx0V4z.js → apps-page-DU0dz9Zo.js} +1 -1
  10. package/dist/gateway/static/root/assets/{archive-plugin-DZsVqMhU.js → archive-plugin-BkVIgZzA.js} +1 -1
  11. package/dist/gateway/static/root/assets/{attachment-load-CIol6JWX.js → attachment-load-CaCMWh1D.js} +1 -1
  12. package/dist/gateway/static/root/assets/automation-suggestion-card-DhGDpKP3.js +1 -0
  13. package/dist/gateway/static/root/assets/automations-page-CTedroVo.js +1 -0
  14. package/dist/gateway/static/root/assets/{binary-plugins-B3UauMfp.js → binary-plugins-B4TO_bsn.js} +1 -1
  15. package/dist/gateway/static/root/assets/{block-editor-2HJoFchH.js → block-editor-DJRWwWNI.js} +6 -6
  16. package/dist/gateway/static/root/assets/browser-settings-page-FCDwOOBK.js +8 -0
  17. package/dist/gateway/static/root/assets/capability-presets-api-Befi89CL.js +1 -0
  18. package/dist/gateway/static/root/assets/capability-presets-settings-panel-_G8eb2vJ.js +1 -0
  19. package/dist/gateway/static/root/assets/channel-recipient-api-BNSuJb5f.js +1 -0
  20. package/dist/gateway/static/root/assets/channels-settings-C3d5JBJX.js +1 -0
  21. package/dist/gateway/static/root/assets/cn-BQ_8x0bT.js +1 -0
  22. package/dist/gateway/static/root/assets/connectors-page-yaUNvt5u.js +2 -0
  23. package/dist/gateway/static/root/assets/cron-expression-B3B1eqnr.js +2 -0
  24. package/dist/gateway/static/root/assets/dreaming-settings-DNrdg1Ve.js +1 -0
  25. package/dist/gateway/static/root/assets/{extension-debug-page-DX5WRE_t.js → extension-debug-page-DYh402XV.js} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-page-Buah7Bw-.js → extension-page-Cr_TizrN.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-settings-page-DuroLVnf.js → extension-settings-page-BU1KoKRj.js} +1 -1
  28. package/dist/gateway/static/root/assets/{fetch-B5zdl27C.js → fetch-Y7AEX4H3.js} +1 -1
  29. package/dist/gateway/static/root/assets/format-cron-label-arqgGlVV.js +1 -0
  30. package/dist/gateway/static/root/assets/{gateway-config-api-gT4ZhE7h.js → gateway-config-api-RbMmAOpX.js} +1 -1
  31. package/dist/gateway/static/root/assets/gateway-settings-C79wkXef.js +1 -0
  32. package/dist/gateway/static/root/assets/{gateway-startup-retry-B3kL8KGY.js → gateway-startup-retry-DiD_Tx4N.js} +1 -1
  33. package/dist/gateway/static/root/assets/goal-detail-page-9paXuHdo.js +1 -0
  34. package/dist/gateway/static/root/assets/{goals-config-api-AR-fVh0P.js → goals-config-api-DqxVi0p5.js} +1 -1
  35. package/dist/gateway/static/root/assets/{goals-page-Cpb21ezg.js → goals-page-CS0R-Af2.js} +2 -2
  36. package/dist/gateway/static/root/assets/goals-settings-CSuzZ8Ae.js +1 -0
  37. package/dist/gateway/static/root/assets/heartbeat-settings-DXPaYJm3.js +1 -0
  38. package/dist/gateway/static/root/assets/index-BoKafJIZ.js +191 -0
  39. package/dist/gateway/static/root/assets/index-CArhCcYn.css +1 -0
  40. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-Dvg53qnd.js +1 -0
  41. package/dist/gateway/static/root/assets/{logs-page-DefCgF4o.js → logs-page-DLXPcksQ.js} +2 -2
  42. package/dist/gateway/static/root/assets/{markdown-split-ChbR9LGO.js → markdown-split-CpHxbtWJ.js} +1 -1
  43. package/dist/gateway/static/root/assets/{media-plugins-B82oP80n.js → media-plugins-SFPQRSxq.js} +1 -1
  44. package/dist/gateway/static/root/assets/messages-CrDHEbss.js +3 -0
  45. package/dist/gateway/static/root/assets/models-hub-panel-BDF2iyRk.js +2 -0
  46. package/dist/gateway/static/root/assets/note-detail-page-CSb_hwig.js +2 -0
  47. package/dist/gateway/static/root/assets/{note-image-lightbox-CDknITM3.js → note-image-lightbox-BUYURRgn.js} +1 -1
  48. package/dist/gateway/static/root/assets/notes-page-BsIBSFyZ.js +1 -0
  49. package/dist/gateway/static/root/assets/{preview-open-alternatives-DV3xQsWB.js → preview-open-alternatives-BHz9iWYA.js} +1 -1
  50. package/dist/gateway/static/root/assets/remote-access-hub-CwzSovcS.js +1 -0
  51. package/dist/gateway/static/root/assets/{save-bar-controls-BODCXnvY.js → save-bar-controls-CefkOlRg.js} +1 -1
  52. package/dist/gateway/static/root/assets/schedule-field-CmTRoOcE.js +1 -0
  53. package/dist/gateway/static/root/assets/{schema-form-qtfEI6QM.js → schema-form-FMKv1vGu.js} +1 -1
  54. package/dist/gateway/static/root/assets/sessions-page-PHmX-NmA.js +1 -0
  55. package/dist/gateway/static/root/assets/settings-advanced-gate-BRAeKJN4.js +1 -0
  56. package/dist/gateway/static/root/assets/{settings-collapsible-section-BHZKjVcS.js → settings-collapsible-section-BouO6JTi.js} +1 -1
  57. package/dist/gateway/static/root/assets/{settings-form-section-5i35D-J1.js → settings-form-section-D-4lBl6X.js} +1 -1
  58. package/dist/gateway/static/root/assets/settings-page-KKrbFjy8.js +1 -0
  59. package/dist/gateway/static/root/assets/settings-page-layout-BJ4Gsef5.js +1 -0
  60. package/dist/gateway/static/root/assets/setup-status-panel-CrUjHPQo.js +1 -0
  61. package/dist/gateway/static/root/assets/{share-preview-page-B0H63tDv.js → share-preview-page-BDy2btRN.js} +1 -1
  62. package/dist/gateway/static/root/assets/shares-settings-B18OBmH5.js +1 -0
  63. package/dist/gateway/static/root/assets/skill-reload-api-C28-2uKQ.js +1 -0
  64. package/dist/gateway/static/root/assets/skills-page-Bm2ebkwl.js +2 -0
  65. package/dist/gateway/static/root/assets/system-settings-panel-CRngrlnZ.js +1 -0
  66. package/dist/gateway/static/root/assets/typed-models-lib-BltBc0b-.js +1 -0
  67. package/dist/gateway/static/root/assets/{use-channel-catalog-BCjP_VHb.js → use-channel-catalog-CjN-51e6.js} +1 -1
  68. package/dist/gateway/static/root/assets/user-profile-settings-panel-DJ1dKwZy.js +1 -0
  69. package/dist/gateway/static/root/assets/utils-B5M5-YvK.js +1 -0
  70. package/dist/gateway/static/root/assets/voice-api-key-field-CeEevm7z.js +1 -0
  71. package/dist/gateway/static/root/assets/{voice-player-store-BlF9V05n.js → voice-player-store-B7ykUlHM.js} +1 -1
  72. package/dist/gateway/static/root/assets/workflow-run-setup-panel-C4PzUQjB.js +3 -0
  73. package/dist/gateway/static/root/assets/workflows-page-BL84_-Ky.js +18 -0
  74. package/dist/gateway/static/root/index.html +6 -7
  75. package/dist/package.js +1 -1
  76. package/dist/src/agent/agent-manager.d.ts +4 -5
  77. package/dist/src/agent/agent-manager.js +6 -9
  78. package/dist/src/agent/agent-manager.js.map +1 -1
  79. package/dist/src/agent/agent-scope.js +0 -2
  80. package/dist/src/agent/agent-scope.js.map +1 -1
  81. package/dist/src/agent/background-review/prompts.d.ts +2 -2
  82. package/dist/src/agent/background-review/prompts.js +2 -2
  83. package/dist/src/agent/background-review/prompts.js.map +1 -1
  84. package/dist/src/agent/background-review/settings.d.ts +1 -1
  85. package/dist/src/agent/background-review/settings.js +7 -8
  86. package/dist/src/agent/background-review/settings.js.map +1 -1
  87. package/dist/src/agent/bootstrap/bootstrap-cache.d.ts +1 -0
  88. package/dist/src/agent/bootstrap/bootstrap-cache.js +4 -3
  89. package/dist/src/agent/bootstrap/bootstrap-cache.js.map +1 -1
  90. package/dist/src/agent/bootstrap/bootstrap-files.d.ts +4 -0
  91. package/dist/src/agent/bootstrap/bootstrap-files.js +4 -3
  92. package/dist/src/agent/bootstrap/bootstrap-files.js.map +1 -1
  93. package/dist/src/agent/bootstrap/filter-bootstrap-files.js +4 -2
  94. package/dist/src/agent/bootstrap/filter-bootstrap-files.js.map +1 -1
  95. package/dist/src/agent/bootstrap/load-bootstrap-files.d.ts +2 -1
  96. package/dist/src/agent/bootstrap/load-bootstrap-files.js +17 -16
  97. package/dist/src/agent/bootstrap/load-bootstrap-files.js.map +1 -1
  98. package/dist/src/agent/bootstrap/types.d.ts +1 -1
  99. package/dist/src/agent/context/workspace-templates/AGENTS.md +1 -1
  100. package/dist/src/agent/context/workspace.d.ts +4 -2
  101. package/dist/src/agent/context/workspace.js +5 -4
  102. package/dist/src/agent/context/workspace.js.map +1 -1
  103. package/dist/src/agent/embedded/run-for-session.js +106 -15
  104. package/dist/src/agent/embedded/run-for-session.js.map +1 -1
  105. package/dist/src/agent/fallback/candidates.d.ts +0 -8
  106. package/dist/src/agent/fallback/candidates.js +10 -11
  107. package/dist/src/agent/fallback/candidates.js.map +1 -1
  108. package/dist/src/agent/index.js +1 -1
  109. package/dist/src/agent/lifecycle/handlers/compaction.d.ts +1 -3
  110. package/dist/src/agent/lifecycle/handlers/compaction.js +1 -16
  111. package/dist/src/agent/lifecycle/handlers/compaction.js.map +1 -1
  112. package/dist/src/agent/lifecycle/progress.d.ts +0 -1
  113. package/dist/src/agent/lifecycle/progress.js +1 -6
  114. package/dist/src/agent/lifecycle/progress.js.map +1 -1
  115. package/dist/src/agent/lifecycle/timeout-wrapper.d.ts +1 -2
  116. package/dist/src/agent/lifecycle/timeout-wrapper.js +1 -7
  117. package/dist/src/agent/lifecycle/timeout-wrapper.js.map +1 -1
  118. package/dist/src/agent/memory/builtin-memory-store.d.ts +4 -2
  119. package/dist/src/agent/memory/builtin-memory-store.js +11 -6
  120. package/dist/src/agent/memory/builtin-memory-store.js.map +1 -1
  121. package/dist/src/agent/memory/builtin-provider.js +36 -7
  122. package/dist/src/agent/memory/builtin-provider.js.map +1 -1
  123. package/dist/src/agent/memory/candidate-extractor.d.ts +6 -0
  124. package/dist/src/agent/memory/candidate-extractor.js +60 -0
  125. package/dist/src/agent/memory/candidate-extractor.js.map +1 -0
  126. package/dist/src/agent/memory/manager.d.ts +2 -1
  127. package/dist/src/agent/memory/manager.js +27 -3
  128. package/dist/src/agent/memory/manager.js.map +1 -1
  129. package/dist/src/agent/memory/memory-config.js +3 -0
  130. package/dist/src/agent/memory/memory-config.js.map +1 -1
  131. package/dist/src/agent/memory/prefetch-coordinator.js.map +1 -1
  132. package/dist/src/agent/memory/types.d.ts +27 -4
  133. package/dist/src/agent/middleware/self-verify.d.ts +0 -1
  134. package/dist/src/agent/middleware/self-verify.js +0 -2
  135. package/dist/src/agent/middleware/self-verify.js.map +1 -1
  136. package/dist/src/agent/models/index.d.ts +1 -1
  137. package/dist/src/agent/models/manager.d.ts +4 -20
  138. package/dist/src/agent/models/manager.js +9 -126
  139. package/dist/src/agent/models/manager.js.map +1 -1
  140. package/dist/src/agent/orchestration/agent-orchestrator.d.ts +0 -4
  141. package/dist/src/agent/orchestration/agent-orchestrator.js +1 -9
  142. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  143. package/dist/src/agent/prompt/memory/index.d.ts +4 -2
  144. package/dist/src/agent/prompt/memory/index.js +18 -12
  145. package/dist/src/agent/prompt/memory/index.js.map +1 -1
  146. package/dist/src/agent/prompt/sections/memory-skills.js +1 -1
  147. package/dist/src/agent/prompt/sections/memory-skills.js.map +1 -1
  148. package/dist/src/agent/prompt/sections/tooling.js +2 -2
  149. package/dist/src/agent/prompt/sections/tooling.js.map +1 -1
  150. package/dist/src/agent/prompt/service-prompt-builder.d.ts +0 -1
  151. package/dist/src/agent/prompt/service-prompt-builder.js +4 -31
  152. package/dist/src/agent/prompt/service-prompt-builder.js.map +1 -1
  153. package/dist/src/agent/prompt/subagent-context.js +1 -1
  154. package/dist/src/agent/prompt/subagent-context.js.map +1 -1
  155. package/dist/src/agent/prompt/types.d.ts +1 -1
  156. package/dist/src/agent/reply/post-compaction-context.js +1 -3
  157. package/dist/src/agent/reply/post-compaction-context.js.map +1 -1
  158. package/dist/src/agent/reply/startup-context.js +1 -5
  159. package/dist/src/agent/reply/startup-context.js.map +1 -1
  160. package/dist/src/agent/service.d.ts +4 -12
  161. package/dist/src/agent/service.js +10 -48
  162. package/dist/src/agent/service.js.map +1 -1
  163. package/dist/src/agent/service.types.d.ts +2 -2
  164. package/dist/src/agent/session/session-config-service.d.ts +11 -11
  165. package/dist/src/agent/session/session-config-service.js +14 -14
  166. package/dist/src/agent/session/session-config-service.js.map +1 -1
  167. package/dist/src/agent/session/session-inspector.js +3 -2
  168. package/dist/src/agent/session/session-inspector.js.map +1 -1
  169. package/dist/src/agent/starter-agents.js +12 -12
  170. package/dist/src/agent/starter-agents.js.map +1 -1
  171. package/dist/src/agent/tools/automation-tool.d.ts +14 -0
  172. package/dist/src/agent/tools/automation-tool.js +102 -0
  173. package/dist/src/agent/tools/automation-tool.js.map +1 -0
  174. package/dist/src/agent/tools/curated-memory-tool.js +57 -2
  175. package/dist/src/agent/tools/curated-memory-tool.js.map +1 -1
  176. package/dist/src/agent/tools/delegate-tool.js +1 -1
  177. package/dist/src/agent/tools/delegate-tool.js.map +1 -1
  178. package/dist/src/agent/tools/factory.d.ts +3 -3
  179. package/dist/src/agent/tools/factory.js +2 -2
  180. package/dist/src/agent/tools/factory.js.map +1 -1
  181. package/dist/src/agent/tools/index.d.ts +1 -1
  182. package/dist/src/agent/tools/index.js +2 -2
  183. package/dist/src/agent/tools/web-extract.js +6 -8
  184. package/dist/src/agent/tools/web-extract.js.map +1 -1
  185. package/dist/src/agent-manifest/index.js +2 -2
  186. package/dist/src/agent-manifest/resolver.d.ts +4 -2
  187. package/dist/src/agent-manifest/resolver.js +6 -3
  188. package/dist/src/agent-manifest/resolver.js.map +1 -1
  189. package/dist/src/agent-manifest/schema.d.ts +238 -0
  190. package/dist/src/agent-manifest/schema.js +16 -5
  191. package/dist/src/agent-manifest/schema.js.map +1 -1
  192. package/dist/src/agent-manifest/validator.d.ts +3 -2
  193. package/dist/src/agent-manifest/validator.js +2 -1
  194. package/dist/src/agent-manifest/validator.js.map +1 -1
  195. package/dist/src/ai-assist/text-assist.d.ts +1 -1
  196. package/dist/src/ai-assist/text-assist.js +56 -0
  197. package/dist/src/ai-assist/text-assist.js.map +1 -1
  198. package/dist/src/auth/profiles/store.js.map +1 -1
  199. package/dist/src/automations/api/routes.d.ts +3 -0
  200. package/dist/src/automations/api/routes.js +193 -0
  201. package/dist/src/automations/api/routes.js.map +1 -0
  202. package/dist/src/automations/domain/index.d.ts +3 -0
  203. package/dist/src/automations/domain/index.js +3 -0
  204. package/dist/src/automations/domain/schedule.d.ts +4 -0
  205. package/dist/src/automations/domain/schedule.js +37 -0
  206. package/dist/src/automations/domain/schedule.js.map +1 -0
  207. package/dist/src/automations/domain/types.d.ts +160 -0
  208. package/dist/src/automations/domain/validation.d.ts +370 -0
  209. package/dist/src/automations/domain/validation.js +149 -0
  210. package/dist/src/automations/domain/validation.js.map +1 -0
  211. package/dist/src/automations/draft/automation-draft-prompt.d.ts +26 -0
  212. package/dist/src/automations/draft/automation-draft-prompt.js +127 -0
  213. package/dist/src/automations/draft/automation-draft-prompt.js.map +1 -0
  214. package/dist/src/automations/draft/automation-draft-service.d.ts +12 -0
  215. package/dist/src/automations/draft/automation-draft-service.js +135 -0
  216. package/dist/src/automations/draft/automation-draft-service.js.map +1 -0
  217. package/dist/src/automations/draft/automation-draft-validator.d.ts +99 -0
  218. package/dist/src/automations/draft/automation-draft-validator.js +105 -0
  219. package/dist/src/automations/draft/automation-draft-validator.js.map +1 -0
  220. package/dist/src/automations/draft/automation-draft.types.d.ts +40 -0
  221. package/dist/src/automations/draft/index.d.ts +3 -0
  222. package/dist/src/automations/draft/index.js +3 -0
  223. package/dist/src/automations/index.d.ts +3 -0
  224. package/dist/src/automations/index.js +8 -0
  225. package/dist/src/automations/product-events.d.ts +5 -0
  226. package/dist/src/automations/product-events.js +21 -0
  227. package/dist/src/automations/product-events.js.map +1 -0
  228. package/dist/src/automations/service/action-executor.d.ts +9 -0
  229. package/dist/src/automations/service/action-executor.js +157 -0
  230. package/dist/src/automations/service/action-executor.js.map +1 -0
  231. package/dist/src/automations/service/automation-service.d.ts +54 -0
  232. package/dist/src/automations/service/automation-service.js +404 -0
  233. package/dist/src/automations/service/automation-service.js.map +1 -0
  234. package/dist/src/automations/service/index.d.ts +2 -0
  235. package/dist/src/automations/service/index.js +3 -0
  236. package/dist/src/automations/storage/automation-repository.d.ts +6 -0
  237. package/dist/src/automations/storage/automation-repository.js +61 -0
  238. package/dist/src/automations/storage/automation-repository.js.map +1 -0
  239. package/dist/src/automations/storage/automation-run-repository.d.ts +17 -0
  240. package/dist/src/automations/storage/automation-run-repository.js +130 -0
  241. package/dist/src/automations/storage/automation-run-repository.js.map +1 -0
  242. package/dist/src/automations/storage/index.d.ts +2 -0
  243. package/dist/src/automations/storage/index.js +3 -0
  244. package/dist/src/channels/pipeline.d.ts +1 -1
  245. package/dist/src/channels/pipeline.js.map +1 -1
  246. package/dist/src/channels/plugin-types.d.ts +3 -0
  247. package/dist/src/chat-commands/agent-edit.js +0 -1
  248. package/dist/src/chat-commands/agent-edit.js.map +1 -1
  249. package/dist/src/chat-commands/builtins/model.js +2 -2
  250. package/dist/src/chat-commands/builtins/model.js.map +1 -1
  251. package/dist/src/chat-commands/builtins/thinking.js.map +1 -1
  252. package/dist/src/cli/command-catalog.js +0 -39
  253. package/dist/src/cli/command-catalog.js.map +1 -1
  254. package/dist/src/cli/command-loaders.js +0 -1
  255. package/dist/src/cli/command-loaders.js.map +1 -1
  256. package/dist/src/cli/command-manifest.d.ts +1 -1
  257. package/dist/src/cli/command-manifest.js +1 -5
  258. package/dist/src/cli/command-manifest.js.map +1 -1
  259. package/dist/src/cli/commands/agents.js +7 -6
  260. package/dist/src/cli/commands/agents.js.map +1 -1
  261. package/dist/src/cli/commands/doctor/checks/database-schema.js +1 -1
  262. package/dist/src/cli/commands/doctor/checks/{cron-health.d.ts → migrations.d.ts} +1 -1
  263. package/dist/src/cli/commands/doctor/checks/migrations.js +40 -0
  264. package/dist/src/cli/commands/doctor/checks/migrations.js.map +1 -0
  265. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -0
  266. package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -1
  267. package/dist/src/cli/commands/doctor/checks/workspace-status.js +0 -1
  268. package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -1
  269. package/dist/src/cli/commands/doctor/flow.js +2 -2
  270. package/dist/src/cli/commands/doctor/flow.js.map +1 -1
  271. package/dist/src/cli/commands/gateway/call.js +2 -2
  272. package/dist/src/cli/commands/gateway/call.js.map +1 -1
  273. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  274. package/dist/src/cli/commands/gateway/run-foreground.js +4 -2
  275. package/dist/src/cli/commands/gateway/run-foreground.js.map +1 -1
  276. package/dist/src/cli/commands/init.js +33 -14
  277. package/dist/src/cli/commands/init.js.map +1 -1
  278. package/dist/src/cli/commands/models.js +13 -31
  279. package/dist/src/cli/commands/models.js.map +1 -1
  280. package/dist/src/cli/commands/onboard/model.js +17 -10
  281. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  282. package/dist/src/cli/commands/onboard.js +2 -2
  283. package/dist/src/cli/commands/onboard.js.map +1 -1
  284. package/dist/src/cli/commands/tui.js +26 -4
  285. package/dist/src/cli/commands/tui.js.map +1 -1
  286. package/dist/src/cli/index.d.ts +1 -0
  287. package/dist/src/cli/index.js +10 -5
  288. package/dist/src/cli/index.js.map +1 -1
  289. package/dist/src/cli/registry.js +1 -1
  290. package/dist/src/cli/registry.js.map +1 -1
  291. package/dist/src/cli/templates.d.ts +1 -1
  292. package/dist/src/cli/templates.js +1 -11
  293. package/dist/src/cli/templates.js.map +1 -1
  294. package/dist/src/cli/utils/init-workspace-core.js +2 -0
  295. package/dist/src/cli/utils/init-workspace-core.js.map +1 -1
  296. package/dist/src/commands/agents.config.d.ts +9 -0
  297. package/dist/src/commands/agents.config.js +42 -12
  298. package/dist/src/commands/agents.config.js.map +1 -1
  299. package/dist/src/config/agent-profile.js +5 -3
  300. package/dist/src/config/agent-profile.js.map +1 -1
  301. package/dist/src/config/agent-typed-models.js +3 -5
  302. package/dist/src/config/agent-typed-models.js.map +1 -1
  303. package/dist/src/config/config-surface.d.ts +3 -0
  304. package/dist/src/config/index.d.ts +0 -1
  305. package/dist/src/config/index.js +3 -3
  306. package/dist/src/config/index.js.map +1 -1
  307. package/dist/src/config/paths.d.ts +8 -10
  308. package/dist/src/config/paths.js +16 -16
  309. package/dist/src/config/paths.js.map +1 -1
  310. package/dist/src/config/profile.js +0 -1
  311. package/dist/src/config/profile.js.map +1 -1
  312. package/dist/src/config/rules.js +0 -5
  313. package/dist/src/config/rules.js.map +1 -1
  314. package/dist/src/config/schema.d.ts +45 -44
  315. package/dist/src/config/schema.js +68 -52
  316. package/dist/src/config/schema.js.map +1 -1
  317. package/dist/src/config/web-patch.d.ts +0 -12
  318. package/dist/src/config/web-patch.js +2 -29
  319. package/dist/src/config/web-patch.js.map +1 -1
  320. package/dist/src/extensions/api.d.ts +2 -0
  321. package/dist/src/extensions/api.js +10 -0
  322. package/dist/src/extensions/api.js.map +1 -1
  323. package/dist/src/extensions/extension-registry-impl.d.ts +4 -1
  324. package/dist/src/extensions/extension-registry-impl.js +8 -0
  325. package/dist/src/extensions/extension-registry-impl.js.map +1 -1
  326. package/dist/src/extensions/loader.d.ts +3 -3
  327. package/dist/src/extensions/loader.js +3 -3
  328. package/dist/src/extensions/loader.js.map +1 -1
  329. package/dist/src/extensions/sdk/testing.d.ts +2 -0
  330. package/dist/src/extensions/sdk/testing.js +7 -0
  331. package/dist/src/extensions/sdk/testing.js.map +1 -1
  332. package/dist/src/extensions/types/core.d.ts +10 -1
  333. package/dist/src/extensions/types/index.d.ts +1 -1
  334. package/dist/src/extensions/types/{phase4.d.ts → registration.d.ts} +2 -2
  335. package/dist/src/gateway/agent-builtin-tools.d.ts +1 -1
  336. package/dist/src/gateway/agent-builtin-tools.js +1 -1
  337. package/dist/src/gateway/agent-builtin-tools.js.map +1 -1
  338. package/dist/src/gateway/agents-admin.d.ts +8 -0
  339. package/dist/src/gateway/agents-admin.js +63 -34
  340. package/dist/src/gateway/agents-admin.js.map +1 -1
  341. package/dist/src/gateway/capability-presets-admin.d.ts +1 -0
  342. package/dist/src/gateway/capability-presets-admin.js +19 -10
  343. package/dist/src/gateway/capability-presets-admin.js.map +1 -1
  344. package/dist/src/gateway/chat-stream/mapper.js +9 -2
  345. package/dist/src/gateway/chat-stream/mapper.js.map +1 -1
  346. package/dist/src/gateway/dreaming-automation-reconciler.d.ts +11 -0
  347. package/dist/src/gateway/dreaming-automation-reconciler.js +105 -0
  348. package/dist/src/gateway/dreaming-automation-reconciler.js.map +1 -0
  349. package/dist/src/gateway/global-defaults-admin.d.ts +36 -0
  350. package/dist/src/gateway/global-defaults-admin.js +146 -0
  351. package/dist/src/gateway/global-defaults-admin.js.map +1 -0
  352. package/dist/src/gateway/heartbeat/service.d.ts +0 -2
  353. package/dist/src/gateway/heartbeat/service.js +0 -7
  354. package/dist/src/gateway/heartbeat/service.js.map +1 -1
  355. package/dist/src/gateway/hono/lib/config-payload.d.ts +5 -6
  356. package/dist/src/gateway/hono/lib/config-payload.js +2 -2
  357. package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
  358. package/dist/src/gateway/hono/routes/agents.js +33 -1
  359. package/dist/src/gateway/hono/routes/agents.js.map +1 -1
  360. package/dist/src/gateway/hono/routes/commands-skills.js +4 -5
  361. package/dist/src/gateway/hono/routes/commands-skills.js.map +1 -1
  362. package/dist/src/gateway/hono/routes/config-patch/misc.d.ts +1 -1
  363. package/dist/src/gateway/hono/routes/config-patch/misc.js +12 -6
  364. package/dist/src/gateway/hono/routes/config-patch/misc.js.map +1 -1
  365. package/dist/src/gateway/hono/routes/dreaming.js +27 -37
  366. package/dist/src/gateway/hono/routes/dreaming.js.map +1 -1
  367. package/dist/src/gateway/hono/routes/global-defaults.d.ts +3 -0
  368. package/dist/src/gateway/hono/routes/global-defaults.js +61 -0
  369. package/dist/src/gateway/hono/routes/global-defaults.js.map +1 -0
  370. package/dist/src/gateway/hono/routes/home.d.ts +2 -2
  371. package/dist/src/gateway/hono/routes/home.js +34 -25
  372. package/dist/src/gateway/hono/routes/home.js.map +1 -1
  373. package/dist/src/gateway/hono/routes/lazy-bundles.js +21 -9
  374. package/dist/src/gateway/hono/routes/lazy-bundles.js.map +1 -1
  375. package/dist/src/gateway/hono/routes/memory.js +75 -4
  376. package/dist/src/gateway/hono/routes/memory.js.map +1 -1
  377. package/dist/src/gateway/hono/routes/migrations.d.ts +3 -0
  378. package/dist/src/gateway/hono/routes/migrations.js +35 -0
  379. package/dist/src/gateway/hono/routes/migrations.js.map +1 -0
  380. package/dist/src/gateway/hono/routes/models.js +1 -1
  381. package/dist/src/gateway/hono/routes/public-gateway.js +2 -1
  382. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  383. package/dist/src/gateway/hono/routes/sessions.js +14 -0
  384. package/dist/src/gateway/hono/routes/sessions.js.map +1 -1
  385. package/dist/src/gateway/run-loop.js +2 -0
  386. package/dist/src/gateway/run-loop.js.map +1 -1
  387. package/dist/src/gateway/security/operator-scopes.js +5 -1
  388. package/dist/src/gateway/security/operator-scopes.js.map +1 -1
  389. package/dist/src/gateway/service/config-coordinator.d.ts +4 -4
  390. package/dist/src/gateway/service/config-coordinator.js +14 -8
  391. package/dist/src/gateway/service/config-coordinator.js.map +1 -1
  392. package/dist/src/gateway/service/marketplace-service.d.ts +4 -4
  393. package/dist/src/gateway/service/marketplace-service.js +11 -7
  394. package/dist/src/gateway/service/marketplace-service.js.map +1 -1
  395. package/dist/src/gateway/service/sessions-api.d.ts +2 -1
  396. package/dist/src/gateway/service/sessions-api.js +6 -1
  397. package/dist/src/gateway/service/sessions-api.js.map +1 -1
  398. package/dist/src/gateway/service.d.ts +7 -3
  399. package/dist/src/gateway/service.js +61 -27
  400. package/dist/src/gateway/service.js.map +1 -1
  401. package/dist/src/goals/goal-service.js +45 -4
  402. package/dist/src/goals/goal-service.js.map +1 -1
  403. package/dist/src/infra/update-restart.js +1 -1
  404. package/dist/src/migrations/config/default-capability-preset.d.ts +10 -0
  405. package/dist/src/migrations/config/default-capability-preset.js +135 -0
  406. package/dist/src/migrations/config/default-capability-preset.js.map +1 -0
  407. package/dist/src/migrations/index.d.ts +4 -0
  408. package/dist/src/migrations/index.js +4 -0
  409. package/dist/src/migrations/registry.d.ts +8 -0
  410. package/dist/src/migrations/registry.js +18 -0
  411. package/dist/src/migrations/registry.js.map +1 -0
  412. package/dist/src/migrations/runner.d.ts +17 -0
  413. package/dist/src/migrations/runner.js +191 -0
  414. package/dist/src/migrations/runner.js.map +1 -0
  415. package/dist/src/migrations/types.d.ts +34 -0
  416. package/dist/src/notes/service.js +27 -2
  417. package/dist/src/notes/service.js.map +1 -1
  418. package/dist/src/providers/index.d.ts +4 -5
  419. package/dist/src/providers/index.js +16 -16
  420. package/dist/src/providers/index.js.map +1 -1
  421. package/dist/src/providers/model-registry.d.ts +0 -1
  422. package/dist/src/providers/model-registry.js +0 -3
  423. package/dist/src/providers/model-registry.js.map +1 -1
  424. package/dist/src/routing/resolve-tui-session-key.d.ts +3 -0
  425. package/dist/src/routing/resolve-tui-session-key.js +14 -3
  426. package/dist/src/routing/resolve-tui-session-key.js.map +1 -1
  427. package/dist/src/session/session-workspace.js +2 -7
  428. package/dist/src/session/session-workspace.js.map +1 -1
  429. package/dist/src/session/store.js +0 -5
  430. package/dist/src/session/store.js.map +1 -1
  431. package/dist/src/session/transcript-outline.d.ts +47 -0
  432. package/dist/src/session/transcript-outline.js +481 -0
  433. package/dist/src/session/transcript-outline.js.map +1 -0
  434. package/dist/src/storage/sqlite/index.d.ts +1 -3
  435. package/dist/src/storage/sqlite/index.js +2 -4
  436. package/dist/src/storage/sqlite/memory-index-repository.d.ts +1 -0
  437. package/dist/src/storage/sqlite/memory-index-repository.js +15 -14
  438. package/dist/src/storage/sqlite/memory-index-repository.js.map +1 -1
  439. package/dist/src/storage/sqlite/memory-records-repository.d.ts +44 -1
  440. package/dist/src/storage/sqlite/memory-records-repository.js +164 -20
  441. package/dist/src/storage/sqlite/memory-records-repository.js.map +1 -1
  442. package/dist/src/storage/sqlite/migrations/014_memory_record_governance.sql +10 -0
  443. package/dist/src/storage/sqlite/migrations/015_memory_trace_feedback.sql +4 -0
  444. package/dist/src/storage/sqlite/migrations/016_automations.sql +47 -0
  445. package/dist/src/storage/sqlite/migrations/017_automation_run_events.sql +14 -0
  446. package/dist/src/storage/sqlite/migrations/018_automation_safety.sql +1 -0
  447. package/dist/src/storage/sqlite/migrations/runner.d.ts +1 -1
  448. package/dist/src/storage/sqlite/migrations/runner.js +3 -3
  449. package/dist/src/storage/sqlite/migrations/runner.js.map +1 -1
  450. package/dist/src/storage/sqlite/migrations/runner.ts +1 -1
  451. package/dist/src/storage/sqlite/schema.js +1 -1
  452. package/dist/src/storage/sqlite/schema.sql +56 -46
  453. package/dist/src/tui/backends/embedded-backend.d.ts +9 -0
  454. package/dist/src/tui/backends/embedded-backend.js +55 -27
  455. package/dist/src/tui/backends/embedded-backend.js.map +1 -1
  456. package/dist/src/tui/backends/gateway-sse-backend.d.ts +4 -0
  457. package/dist/src/tui/backends/gateway-sse-backend.js +30 -3
  458. package/dist/src/tui/backends/gateway-sse-backend.js.map +1 -1
  459. package/dist/src/tui/components/tui-header.d.ts +0 -1
  460. package/dist/src/tui/components/tui-header.js +3 -8
  461. package/dist/src/tui/components/tui-header.js.map +1 -1
  462. package/dist/src/tui/tui-backend.d.ts +4 -0
  463. package/dist/src/tui/tui-commands.d.ts +5 -0
  464. package/dist/src/tui/tui-commands.js +43 -0
  465. package/dist/src/tui/tui-commands.js.map +1 -1
  466. package/dist/src/tui/tui-startup-resources.js +2 -1
  467. package/dist/src/tui/tui-startup-resources.js.map +1 -1
  468. package/dist/src/tui/tui-startup-text.js +12 -12
  469. package/dist/src/tui/tui-startup-text.js.map +1 -1
  470. package/dist/src/tui/tui-transcript-tree.d.ts +1 -1
  471. package/dist/src/tui/tui-transcript-tree.js +17 -257
  472. package/dist/src/tui/tui-transcript-tree.js.map +1 -1
  473. package/dist/src/tui/tui-types.d.ts +2 -0
  474. package/dist/src/tui/tui-types.js.map +1 -1
  475. package/dist/src/tui/tui.js +11 -3
  476. package/dist/src/tui/tui.js.map +1 -1
  477. package/dist/src/workflows/domain/index.js +1 -1
  478. package/dist/src/workflows/domain/run.d.ts +7 -7
  479. package/dist/src/workflows/domain/run.js.map +1 -1
  480. package/dist/src/workflows/index.js +2 -2
  481. package/dist/src/workflows/service/workflow-run-service.d.ts +2 -0
  482. package/dist/src/workflows/service/workflow-run-service.js +31 -9
  483. package/dist/src/workflows/service/workflow-run-service.js.map +1 -1
  484. package/dist/src/workflows/service/workflow-run-service.types.d.ts +1 -1
  485. package/package.json +4 -2
  486. package/dist/gateway/static/root/assets/agents-C6xgagZd.js +0 -71
  487. package/dist/gateway/static/root/assets/app-management-settings-panel-CBpLONvG.js +0 -1
  488. package/dist/gateway/static/root/assets/appearance-settings-CGcc54yj.js +0 -1
  489. package/dist/gateway/static/root/assets/browser-settings-page-CUOO-PQk.js +0 -8
  490. package/dist/gateway/static/root/assets/capability-presets-api-XQoMTI0A.js +0 -1
  491. package/dist/gateway/static/root/assets/capability-presets-settings-panel-CfqF-kGr.js +0 -1
  492. package/dist/gateway/static/root/assets/channels-settings-BYyRzsex.js +0 -1
  493. package/dist/gateway/static/root/assets/cn-JdwAhgNB.js +0 -1
  494. package/dist/gateway/static/root/assets/connectors-page-DIvEz4NX.js +0 -2
  495. package/dist/gateway/static/root/assets/createLucideIcon-DPHK1VkS.js +0 -1
  496. package/dist/gateway/static/root/assets/cron-api-R41aQCX9.js +0 -1
  497. package/dist/gateway/static/root/assets/cron-dreaming-jobs-nCMWCf0p.js +0 -1
  498. package/dist/gateway/static/root/assets/cron-page-D97nFqQD.js +0 -3
  499. package/dist/gateway/static/root/assets/dreaming-settings-Bceaw1PG.js +0 -1
  500. package/dist/gateway/static/root/assets/format-cron-label-BsotZDO5.js +0 -2
  501. package/dist/gateway/static/root/assets/format-interval-label-Dn_QKIqb.js +0 -1
  502. package/dist/gateway/static/root/assets/gateway-settings-iISWAZRm.js +0 -1
  503. package/dist/gateway/static/root/assets/goal-detail-page-DCUROLMQ.js +0 -1
  504. package/dist/gateway/static/root/assets/goals-settings-CPAuFwoD.js +0 -1
  505. package/dist/gateway/static/root/assets/heartbeat-config-api-D7bKFEeO.js +0 -1
  506. package/dist/gateway/static/root/assets/heartbeat-settings-CC69vNx0.js +0 -1
  507. package/dist/gateway/static/root/assets/index-CwhK8qCh.js +0 -122
  508. package/dist/gateway/static/root/assets/index-CyfhARL-.css +0 -1
  509. package/dist/gateway/static/root/assets/interval-presets-0DtsnxE0.js +0 -1
  510. package/dist/gateway/static/root/assets/keyboard-shortcuts-settings-BPREtN8B.js +0 -1
  511. package/dist/gateway/static/root/assets/messages-Cf1O9JB0.js +0 -3
  512. package/dist/gateway/static/root/assets/models-hub-panel-DmKiIihT.js +0 -2
  513. package/dist/gateway/static/root/assets/note-detail-page-CxxfLRJZ.js +0 -2
  514. package/dist/gateway/static/root/assets/notes-page-X2slSx7V.js +0 -1
  515. package/dist/gateway/static/root/assets/remote-access-hub-BvmUWqgu.js +0 -1
  516. package/dist/gateway/static/root/assets/schedule-field-CgJSCD3B.js +0 -1
  517. package/dist/gateway/static/root/assets/sessions-page-B0yESuuL.js +0 -1
  518. package/dist/gateway/static/root/assets/settings-advanced-gate-q2M8RKOo.js +0 -1
  519. package/dist/gateway/static/root/assets/settings-page-CGozabLD.js +0 -1
  520. package/dist/gateway/static/root/assets/setup-status-panel-FoOSe6nU.js +0 -1
  521. package/dist/gateway/static/root/assets/shares-settings-Cy5zWyYQ.js +0 -1
  522. package/dist/gateway/static/root/assets/skill-reload-api-DaZNFro9.js +0 -1
  523. package/dist/gateway/static/root/assets/skills-page-CnwtUzvw.js +0 -2
  524. package/dist/gateway/static/root/assets/system-settings-panel-DXs2VmBt.js +0 -1
  525. package/dist/gateway/static/root/assets/typed-models-lib-4gPuydz_.js +0 -1
  526. package/dist/gateway/static/root/assets/voice-api-key-field-DvKiOglO.js +0 -1
  527. package/dist/gateway/static/root/assets/workflows-page-CAVZcONQ.js +0 -18
  528. package/dist/src/agent/context/workspace-templates/USER.md +0 -24
  529. package/dist/src/agent/fallback/error.d.ts +0 -22
  530. package/dist/src/agent/fallback/error.js +0 -32
  531. package/dist/src/agent/fallback/error.js.map +0 -1
  532. package/dist/src/agent/fallback/index.d.ts +0 -5
  533. package/dist/src/agent/fallback/index.js +0 -9
  534. package/dist/src/agent/fallback/index.js.map +0 -1
  535. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.d.ts +0 -29
  536. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js +0 -76
  537. package/dist/src/agent/orchestration/run-agent-turn-with-fallbacks.js.map +0 -1
  538. package/dist/src/agent/service/reconcile-dreaming-cron.d.ts +0 -6
  539. package/dist/src/agent/service/reconcile-dreaming-cron.js +0 -84
  540. package/dist/src/agent/service/reconcile-dreaming-cron.js.map +0 -1
  541. package/dist/src/agent/tools/cronjob-tool.d.ts +0 -29
  542. package/dist/src/agent/tools/cronjob-tool.js +0 -274
  543. package/dist/src/agent/tools/cronjob-tool.js.map +0 -1
  544. package/dist/src/cli/commands/cron-cli.d.ts +0 -2
  545. package/dist/src/cli/commands/cron-cli.js +0 -15
  546. package/dist/src/cli/commands/cron-cli.js.map +0 -1
  547. package/dist/src/cli/commands/cron.d.ts +0 -4
  548. package/dist/src/cli/commands/cron.js +0 -188
  549. package/dist/src/cli/commands/cron.js.map +0 -1
  550. package/dist/src/cli/commands/doctor/checks/cron-health.js +0 -35
  551. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +0 -1
  552. package/dist/src/cron/execution-types.d.ts +0 -42
  553. package/dist/src/cron/executor.d.ts +0 -67
  554. package/dist/src/cron/executor.js +0 -669
  555. package/dist/src/cron/executor.js.map +0 -1
  556. package/dist/src/cron/index.d.ts +0 -7
  557. package/dist/src/cron/index.js +0 -7
  558. package/dist/src/cron/job-content.d.ts +0 -5
  559. package/dist/src/cron/job-content.js +0 -15
  560. package/dist/src/cron/job-content.js.map +0 -1
  561. package/dist/src/cron/run-log-store.d.ts +0 -12
  562. package/dist/src/cron/run-log-store.js +0 -58
  563. package/dist/src/cron/run-log-store.js.map +0 -1
  564. package/dist/src/cron/schedule.d.ts +0 -10
  565. package/dist/src/cron/schedule.js +0 -85
  566. package/dist/src/cron/schedule.js.map +0 -1
  567. package/dist/src/cron/service.d.ts +0 -58
  568. package/dist/src/cron/service.js +0 -419
  569. package/dist/src/cron/service.js.map +0 -1
  570. package/dist/src/cron/types.d.ts +0 -183
  571. package/dist/src/cron/validation.d.ts +0 -500
  572. package/dist/src/cron/validation.js +0 -192
  573. package/dist/src/cron/validation.js.map +0 -1
  574. package/dist/src/cron/workflow-run-completion.d.ts +0 -23
  575. package/dist/src/cron/workflow-run-completion.js +0 -72
  576. package/dist/src/cron/workflow-run-completion.js.map +0 -1
  577. package/dist/src/extensions/types/phase4.js +0 -1
  578. package/dist/src/gateway/hono/routes/cron.d.ts +0 -3
  579. package/dist/src/gateway/hono/routes/cron.js +0 -109
  580. package/dist/src/gateway/hono/routes/cron.js.map +0 -1
  581. package/dist/src/storage/sqlite/cron-job-repository.d.ts +0 -6
  582. package/dist/src/storage/sqlite/cron-job-repository.js +0 -70
  583. package/dist/src/storage/sqlite/cron-job-repository.js.map +0 -1
  584. package/dist/src/storage/sqlite/cron-run-repository.d.ts +0 -5
  585. package/dist/src/storage/sqlite/cron-run-repository.js +0 -96
  586. package/dist/src/storage/sqlite/cron-run-repository.js.map +0 -1
  587. /package/dist/src/{cron → automations/domain}/types.js +0 -0
  588. /package/dist/src/{config/defaults.d.ts → automations/draft/automation-draft.types.js} +0 -0
  589. /package/dist/src/{config/defaults.js → extensions/types/registration.js} +0 -0
  590. /package/dist/src/{cron/execution-types.js → migrations/types.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"onboard.js","names":["runModelSetup","runChannelOnboard"],"sources":["../../../../src/cli/commands/onboard.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { select } from '@inquirer/prompts';\nimport { saveConfig } from '../../config/index.js';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport type { Config } from '../../config/schema.js';\nimport { setupModel as runModelSetup } from './onboard/model.js';\nimport { colors } from '../utils/colors.js';\nimport { setupChannels as runChannelOnboard, getChannelConfigurators } from './onboard/channels/index.js';\nimport { resolveGatewayLocalClientHost } from '../../config/gateway-bind.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\nimport { ConfigSchema } from '../../config/schema.js';\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY && process.stdout.isTTY;\n}\n\nfunction printGitHubStarHint(): void {\n console.log('\\n⭐ If xopc helps you keep long-term AI work moving, please star the repo:');\n console.log(' https://github.com/xopcai/xopc');\n}\n\nasync function setupNonInteractive(_configPath: string, existingConfig: Config): Promise<Config> {\n console.log('\\n🤖 AI Model Configuration (Non-Interactive Mode)\\n');\n console.log('Current agent manifests:', JSON.stringify(existingConfig.agents?.list ?? [], null, 2));\n console.log('\\n💡 To configure in interactive mode, run: xopc onboard');\n console.log('💡 Or set up manually in:', _configPath);\n return existingConfig;\n}\n\nfunction createOnboardCommand(ctx: CLIContext): Command {\n const cmd = new Command('onboard')\n .description('Interactive setup wizard for xopc (gateway uses schema defaults)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc onboard # Full interactive setup',\n 'xopc onboard --quick # Configure model only, then launch locally',\n 'xopc onboard --model # Configure LLM model only',\n 'xopc onboard --channels # Configure messaging channels',\n 'xopc onboard --gateway # Apply default gateway settings (quiet)',\n ])\n )\n .option('--quick', 'Configure model only, then launch locally')\n .option('--model', 'Configure LLM provider and model')\n .option('--channels', 'Configure messaging channels')\n .option('--gateway', 'Configure gateway WebUI')\n .option('--all', 'Configure everything (default)')\n .action(async (options) => {\n try {\n await runOnboard(options, ctx);\n } catch (error: unknown) {\n const err = error as { name?: string; code?: string };\n if (err?.name === 'ExitPromptError' || err?.code === 'EXIT_PROMPT') {\n console.log('\\n\\n👋 Setup cancelled.');\n process.exit(0);\n }\n throw error;\n }\n });\n\n return cmd;\n}\n\ntype OnboardOptions = {\n quick?: boolean;\n model?: boolean;\n channels?: boolean;\n gateway?: boolean;\n all?: boolean;\n};\n\nasync function runOnboard(\n options: OnboardOptions,\n ctx: CLIContext\n): Promise<void> {\n console.log(colors.cyan('\\n🚀 Welcome to xopc setup!\\n'));\n console.log('═'.repeat(50));\n\n const workspacePath = ctx.workspacePath;\n const configPath = ctx.configPath;\n\n const initResult = await initWorkspace({ configPath, workspacePath });\n let config = initResult.config;\n\n // Determine what to configure based on options\n const doModel = options.quick || options.model || options.all || (!options.channels && !options.gateway);\n const doChannels = !options.quick && (options.channels || options.all || (!options.model && !options.gateway));\n const doGateway = !options.quick && (options.gateway || options.all || (!options.model && !options.channels));\n const runFullWizard = !options.quick && !options.model && !options.channels && !options.gateway;\n /** Any setup step besides the unified launch prompt ran in interactive flow. */\n const didConfigurableSteps = doModel || doChannels || doGateway;\n\n if (!isInteractive()) {\n // Non-interactive mode\n if (doModel) {\n config = await setupNonInteractive(configPath, config);\n }\n if (doChannels) {\n console.log('\\n💬 Channels Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure channels, edit the config file manually.');\n }\n if (doGateway) {\n console.log('\\n🌐 Gateway Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure gateway, edit the config file manually.');\n }\n } else {\n // Interactive mode\n if (doModel) {\n config = await runModelSetup(config, ctx);\n }\n\n if (doChannels) {\n const channelIds = (await getChannelConfigurators(config)).map(c => c.id);\n console.log(colors.gray(`\\nChannel onboarding: ${channelIds.join(', ')}\\n`));\n config = await runChannelOnboard(config);\n }\n\n if (doGateway) {\n config = await setupGateway(config);\n }\n }\n\n // Save config once at the end\n await saveConfig(config as Config, configPath);\n\n console.log('\\n' + '═'.repeat(50));\n console.log('\\n🎉 Setup Complete!\\n');\n\n const gatewayAuth = (config as any)?.gateway?.auth;\n const gatewayConfigured =\n gatewayAuth?.mode === 'token' &&\n typeof gatewayAuth?.token === 'string' &&\n gatewayAuth.token.length > 0;\n const port = (config as Config)?.gateway?.port ?? 18790;\n const displayHost = resolveGatewayLocalClientHost(config as Config);\n const gwToken = gatewayConfigured ? (gatewayAuth.token as string) : undefined;\n\n const showGatewaySummary = Boolean(gatewayConfigured && gwToken && (doGateway || runFullWizard));\n\n if (showGatewaySummary && gwToken) {\n const webuiUrl = `http://${displayHost}:${port}?token=${gwToken}`;\n console.log('🌐 Web console (browser) — start here');\n console.log(` Open: http://${displayHost}:${port}`);\n console.log(` Token: ${gwToken.slice(0, 8)}...${gwToken.slice(-8)}`);\n console.log(' Bookmark link (token is saved in the browser when you open it):');\n console.log(` ${webuiUrl}`);\n console.log('');\n }\n\n if (runFullWizard) {\n console.log('🚀 Next steps:');\n if (gatewayConfigured) {\n console.log(' 1. Choose how to launch below (gateway or terminal UI)');\n console.log(' 2. Or chat with: xopc agent -i');\n } else {\n console.log(' 1. Chat in the terminal: xopc agent -i');\n console.log(' 2. Optional: add the Web console: xopc onboard --gateway');\n }\n console.log('');\n } else if (doGateway && gatewayConfigured) {\n console.log('🚀 Next step:');\n console.log(' Start the gateway if it is not running, then open the Web console URL above.');\n console.log('');\n }\n\n console.log('📝 Usage:');\n console.log(' xopc agent -m \"Hello\" # Chat with AI');\n console.log(' xopc agent -i # Interactive mode');\n console.log(' xopc models list # List models');\n console.log(' xopc config validate # Validate xopc.json');\n console.log(' xopc auth list # View authentication');\n console.log(' xopc init # Full state dirs (if upgrading or missing data)');\n\n console.log('\\n📁 Files:');\n console.log(' Config:', configPath);\n console.log(' Workspace:', workspacePath);\n\n printGitHubStarHint();\n\n if (isInteractive() && didConfigurableSteps) {\n await promptLaunchAfterOnboard(config as Config, ctx, { doChannels });\n }\n\n process.exit(0);\n}\n\nasync function startGatewayAsService(config: Config, ctx: CLIContext): Promise<void> {\n const { startGatewayNow } = await import('./onboard/gateway.js');\n await startGatewayNow(config, ctx);\n}\n\nasync function promptLaunchAfterOnboard(\n config: Config,\n ctx: CLIContext,\n _flags: { doChannels: boolean },\n): Promise<void> {\n console.log('');\n const choice = await select<'tui' | 'gateway' | 'none'>({\n message: 'How do you want to launch xopc now?',\n choices: [\n {\n value: 'tui',\n name: 'Terminal UI (embedded)',\n description: 'xopc tui --local — no gateway process required',\n },\n {\n value: 'gateway',\n name: 'Gateway WebUI (OS service)',\n description: 'Install and start the HTTP gateway for the browser console',\n },\n {\n value: 'none',\n name: 'Exit — I will start manually',\n description: 'Finish setup without starting a runtime',\n },\n ],\n default: 'tui',\n });\n\n if (choice === 'gateway') {\n await startGatewayAsService(config, ctx);\n return;\n }\n\n if (choice === 'tui') {\n const { runTui } = await import('../../tui/tui.js');\n await runTui({ local: true });\n return;\n }\n\n console.log('\\n⏭️ You can start later:');\n console.log(' xopc gateway service install');\n console.log(' xopc gateway');\n console.log(' xopc tui --local');\n}\n\nasync function setupGateway(config: Config): Promise<Config> {\n console.log(colors.cyan('\\n🌐 Gateway WebUI\\n'));\n console.log(\n colors.gray(\n 'Applying defaults from config schema (127.0.0.1:18790, token auth; token generated if missing).\\n',\n ),\n );\n\n const gw = config.gateway ?? {};\n const { randomBytes } = await import('node:crypto');\n const authMode = gw.auth?.mode === 'none' ? ('none' as const) : ('token' as const);\n const token =\n authMode === 'token'\n ? typeof gw.auth?.token === 'string' && gw.auth.token.length > 0\n ? gw.auth.token\n : randomBytes(24).toString('hex')\n : undefined;\n\n const merged: Config = {\n ...config,\n gateway: {\n ...gw,\n bind: gw.bind ?? 'loopback',\n port: gw.port ?? 18790,\n auth:\n authMode === 'none'\n ? { mode: 'none' as const }\n : { mode: 'token' as const, token: token! },\n },\n };\n\n const parsed = ConfigSchema.parse(merged);\n console.log('✅ Gateway defaults applied.\\n');\n return parsed;\n}\n\nregister({\n id: 'onboard',\n name: 'onboard',\n description: 'Interactive setup wizard',\n factory: createOnboardCommand,\n metadata: {\n category: 'setup',\n examples: ['xopc onboard', 'xopc onboard --model', 'xopc onboard --channels'],\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"onboard.js","names":["runModelSetup","runChannelOnboard"],"sources":["../../../../src/cli/commands/onboard.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { select } from '@inquirer/prompts';\nimport { saveConfig } from '../../config/index.js';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport type { Config } from '../../config/schema.js';\nimport { setupModel as runModelSetup } from './onboard/model.js';\nimport { colors } from '../utils/colors.js';\nimport { setupChannels as runChannelOnboard, getChannelConfigurators } from './onboard/channels/index.js';\nimport { resolveGatewayLocalClientHost } from '../../config/gateway-bind.js';\nimport { initWorkspace } from '../utils/init-workspace.js';\nimport { ConfigSchema } from '../../config/schema.js';\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY && process.stdout.isTTY;\n}\n\nfunction printGitHubStarHint(): void {\n console.log('\\n⭐ If xopc helps you keep long-term AI work moving, please star the repo:');\n console.log(' https://github.com/xopcai/xopc');\n}\n\nasync function setupNonInteractive(_configPath: string, existingConfig: Config): Promise<Config> {\n console.log('\\n🤖 AI Model Configuration (Non-Interactive Mode)\\n');\n console.log('Current agent manifests:', JSON.stringify(existingConfig.agents?.list ?? [], null, 2));\n console.log('\\n💡 To configure in interactive mode, run: xopc onboard');\n console.log('💡 Or set up manually in:', _configPath);\n return existingConfig;\n}\n\nfunction createOnboardCommand(ctx: CLIContext): Command {\n const cmd = new Command('onboard')\n .description('Interactive setup wizard for xopc (gateway uses schema defaults)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc onboard # Full interactive setup',\n 'xopc onboard --quick # Configure model only, then launch locally',\n 'xopc onboard --model # Configure LLM model only',\n 'xopc onboard --channels # Configure messaging channels',\n 'xopc onboard --gateway # Apply default gateway settings (quiet)',\n ])\n )\n .option('--quick', 'Configure model only, then launch locally')\n .option('--model', 'Configure LLM provider and model')\n .option('--channels', 'Configure messaging channels')\n .option('--gateway', 'Configure gateway WebUI')\n .option('--all', 'Configure everything (default)')\n .action(async (options) => {\n try {\n await runOnboard(options, ctx);\n } catch (error: unknown) {\n const err = error as { name?: string; code?: string };\n if (err?.name === 'ExitPromptError' || err?.code === 'EXIT_PROMPT') {\n console.log('\\n\\n👋 Setup cancelled.');\n process.exit(0);\n }\n throw error;\n }\n });\n\n return cmd;\n}\n\ntype OnboardOptions = {\n quick?: boolean;\n model?: boolean;\n channels?: boolean;\n gateway?: boolean;\n all?: boolean;\n};\n\nasync function runOnboard(\n options: OnboardOptions,\n ctx: CLIContext\n): Promise<void> {\n console.log(colors.cyan('\\n🚀 Welcome to xopc setup!\\n'));\n console.log('═'.repeat(50));\n\n const workspacePath = ctx.workspacePath;\n const configPath = ctx.configPath;\n\n const initResult = await initWorkspace({ configPath, workspacePath });\n let config = initResult.config;\n\n // Determine what to configure based on options\n const doModel = options.quick || options.model || options.all || (!options.channels && !options.gateway);\n const doChannels = !options.quick && (options.channels || options.all || (!options.model && !options.gateway));\n const doGateway = !options.quick && (options.gateway || options.all || (!options.model && !options.channels));\n const runFullWizard = !options.quick && !options.model && !options.channels && !options.gateway;\n /** Any setup step besides the unified launch prompt ran in interactive flow. */\n const didConfigurableSteps = doModel || doChannels || doGateway;\n\n if (!isInteractive()) {\n // Non-interactive mode\n if (doModel) {\n config = await setupNonInteractive(configPath, config);\n }\n if (doChannels) {\n console.log('\\n💬 Channels Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure channels, edit the config file manually.');\n }\n if (doGateway) {\n console.log('\\n🌐 Gateway Configuration (Non-Interactive Mode)\\n');\n console.log('💡 To configure gateway, edit the config file manually.');\n }\n } else {\n // Interactive mode\n if (doModel) {\n config = await runModelSetup(config, ctx);\n }\n\n if (doChannels) {\n const channelIds = (await getChannelConfigurators(config)).map(c => c.id);\n console.log(colors.gray(`\\nChannel onboarding: ${channelIds.join(', ')}\\n`));\n config = await runChannelOnboard(config);\n }\n\n if (doGateway) {\n config = await setupGateway(config);\n }\n }\n\n // Save config once at the end\n await saveConfig(config as Config, configPath);\n\n console.log('\\n' + '═'.repeat(50));\n console.log('\\n🎉 Setup Complete!\\n');\n\n const gatewayAuth = (config as any)?.gateway?.auth;\n const gatewayConfigured =\n gatewayAuth?.mode === 'token' &&\n typeof gatewayAuth?.token === 'string' &&\n gatewayAuth.token.length > 0;\n const port = (config as Config)?.gateway?.port ?? 18790;\n const displayHost = resolveGatewayLocalClientHost(config as Config);\n const gwToken = gatewayConfigured ? (gatewayAuth.token as string) : undefined;\n\n const showGatewaySummary = Boolean(gatewayConfigured && gwToken && (doGateway || runFullWizard));\n\n if (showGatewaySummary && gwToken) {\n const webuiUrl = `http://${displayHost}:${port}?token=${gwToken}`;\n console.log('🌐 Web console (browser) — start here');\n console.log(` Open: http://${displayHost}:${port}`);\n console.log(` Token: ${gwToken.slice(0, 8)}...${gwToken.slice(-8)}`);\n console.log(' Bookmark link (token is saved in the browser when you open it):');\n console.log(` ${webuiUrl}`);\n console.log('');\n }\n\n if (runFullWizard) {\n console.log('🚀 Next steps:');\n if (gatewayConfigured) {\n console.log(' 1. Choose how to launch below (gateway or terminal UI)');\n console.log(' 2. Or chat with: xopc agent -i');\n } else {\n console.log(' 1. Chat in the terminal: xopc agent -i');\n console.log(' 2. Optional: add the Web console: xopc onboard --gateway');\n }\n console.log('');\n } else if (doGateway && gatewayConfigured) {\n console.log('🚀 Next step:');\n console.log(' Start the gateway if it is not running, then open the Web console URL above.');\n console.log('');\n }\n\n console.log('📝 Usage:');\n console.log(' xopc agent -m \"Hello\" # Chat with AI');\n console.log(' xopc agent -i # Interactive mode');\n console.log(' xopc models list # List models');\n console.log(' xopc config validate # Validate xopc.json');\n console.log(' xopc auth list # View authentication');\n console.log(' xopc init # Full state dirs (if upgrading or missing data)');\n\n console.log('\\n📁 Files:');\n console.log(' Config:', configPath);\n console.log(' Workspace:', workspacePath);\n\n printGitHubStarHint();\n\n if (isInteractive() && didConfigurableSteps) {\n await promptLaunchAfterOnboard(config as Config, ctx, { doChannels });\n }\n\n process.exit(0);\n}\n\nasync function startGatewayAsService(config: Config, ctx: CLIContext): Promise<void> {\n const { startGatewayNow } = await import('./onboard/gateway.js');\n await startGatewayNow(config, ctx);\n}\n\nasync function promptLaunchAfterOnboard(\n config: Config,\n ctx: CLIContext,\n _flags: { doChannels: boolean },\n): Promise<void> {\n console.log('');\n const choice = await select<'tui' | 'gateway' | 'none'>({\n message: 'How do you want to launch xopc now?',\n choices: [\n {\n value: 'tui',\n name: 'Terminal UI (embedded)',\n description: 'xopc — no gateway process required',\n },\n {\n value: 'gateway',\n name: 'Gateway WebUI (OS service)',\n description: 'Install and start the HTTP gateway for the browser console',\n },\n {\n value: 'none',\n name: 'Exit — I will start manually',\n description: 'Finish setup without starting a runtime',\n },\n ],\n default: 'tui',\n });\n\n if (choice === 'gateway') {\n await startGatewayAsService(config, ctx);\n return;\n }\n\n if (choice === 'tui') {\n const { runTui } = await import('../../tui/tui.js');\n await runTui({ local: true });\n return;\n }\n\n console.log('\\n⏭️ You can start later:');\n console.log(' xopc gateway service install');\n console.log(' xopc gateway');\n console.log(' xopc');\n}\n\nasync function setupGateway(config: Config): Promise<Config> {\n console.log(colors.cyan('\\n🌐 Gateway WebUI\\n'));\n console.log(\n colors.gray(\n 'Applying defaults from config schema (127.0.0.1:18790, token auth; token generated if missing).\\n',\n ),\n );\n\n const gw = config.gateway ?? {};\n const { randomBytes } = await import('node:crypto');\n const authMode = gw.auth?.mode === 'none' ? ('none' as const) : ('token' as const);\n const token =\n authMode === 'token'\n ? typeof gw.auth?.token === 'string' && gw.auth.token.length > 0\n ? gw.auth.token\n : randomBytes(24).toString('hex')\n : undefined;\n\n const merged: Config = {\n ...config,\n gateway: {\n ...gw,\n bind: gw.bind ?? 'loopback',\n port: gw.port ?? 18790,\n auth:\n authMode === 'none'\n ? { mode: 'none' as const }\n : { mode: 'token' as const, token: token! },\n },\n };\n\n const parsed = ConfigSchema.parse(merged);\n console.log('✅ Gateway defaults applied.\\n');\n return parsed;\n}\n\nregister({\n id: 'onboard',\n name: 'onboard',\n description: 'Interactive setup wizard',\n factory: createOnboardCommand,\n metadata: {\n category: 'setup',\n examples: ['xopc onboard', 'xopc onboard --model', 'xopc onboard --channels'],\n },\n});\n"],"mappings":"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"}
@@ -1,15 +1,34 @@
1
+ import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
2
+ import { setTuiDefaultAgentConfig } from "../../commands/agents.config.js";
1
3
  import { formatExamples, register } from "../registry.js";
4
+ import { detectMigrations, runBootstrapMigrationsSync } from "../../migrations/runner.js";
2
5
  import { Command } from "commander";
3
6
  //#region src/cli/commands/tui.ts
4
- function createTuiCommand(_ctx) {
7
+ init_loader();
8
+ function createTuiCommand(ctx) {
5
9
  return new Command("tui").description("Interactive terminal UI (pi-tui)").addHelpText("after", formatExamples([
10
+ "xopc # Open embedded TUI (default command)",
6
11
  "xopc tui # Embedded mode (default)",
7
12
  "xopc tui --gateway # Force gateway mode",
8
- "xopc tui --local # Embedded mode (default)",
9
13
  "xopc tui --url http://host:3120 --token xxx # Connect to remote gateway",
10
14
  "xopc tui -s agent:main:tui-... # Resume a session",
15
+ "xopc tui --agent coder # Start with a specific agent",
16
+ "xopc tui --set-default-agent coder # Persist default agent for new TUI sessions",
11
17
  "xopc tui -m \"Summarize my inbox\" # Send a message on launch"
12
- ])).option("--url <url>", "Gateway URL (default: http://localhost:3120)").option("--token <token>", "Gateway bearer token").option("-s, --session <key>", "Session key to resume (omitted: start a fresh TUI session)").option("-m, --message <text>", "Send a message on launch").option("--workdir <dir>", "Workspace directory for the new TUI session").option("--no-cwd", "Do not use the launch directory as the new TUI session workspace").option("--local", "Run in embedded mode (no gateway required)").option("--gateway", "Force gateway mode even without explicit --url or --token").option("--theme <name>", "Theme: auto, dark, light, or custom name from ~/.xopc/themes/").option("--thinking <level>", "Thinking level override").action(async (options) => {
18
+ ])).option("--url <url>", "Gateway URL (default: http://localhost:3120)").option("--token <token>", "Gateway bearer token").option("-s, --session <key>", "Session key to resume (omitted: start a fresh TUI session)").option("--agent <id>", "Agent id for a fresh TUI session").option("--set-default-agent <id>", "Persist default agent for new TUI sessions and exit").option("-m, --message <text>", "Send a message on launch").option("--workdir <dir>", "Workspace directory for the new TUI session").option("--no-cwd", "Do not use the launch directory as the new TUI session workspace").option("--local", "Run in embedded mode (no gateway required)").option("--gateway", "Force gateway mode even without explicit --url or --token").option("--theme <name>", "Theme: auto, dark, light, or custom name from ~/.xopc/themes/").option("--thinking <level>", "Thinking level override").action(async (options) => {
19
+ runBootstrapMigrationsSync(ctx.configPath);
20
+ const pendingMigrations = detectMigrations(ctx.configPath);
21
+ if (pendingMigrations.length > 0) console.warn(`xopc has ${pendingMigrations.length} pending migration(s). Run \`xopc doctor --fix\` or open Settings → App management.`);
22
+ if (typeof options.setDefaultAgent === "string") {
23
+ const result = setTuiDefaultAgentConfig(loadConfig(ctx.configPath), options.setDefaultAgent);
24
+ if (result.ok === false) {
25
+ console.error(`Error: ${result.message}`);
26
+ process.exit(1);
27
+ }
28
+ await saveConfig(result.config, ctx.configPath);
29
+ console.log(`TUI default agent set to "${result.agentId}".`);
30
+ return;
31
+ }
13
32
  const { runTui } = await import("../../tui/tui.js");
14
33
  const useLocal = options.local === true;
15
34
  const useGateway = options.gateway === true || typeof options.url === "string" || typeof options.token === "string";
@@ -19,6 +38,7 @@ function createTuiCommand(_ctx) {
19
38
  url: typeof options.url === "string" ? options.url : void 0,
20
39
  token: typeof options.token === "string" ? options.token : void 0,
21
40
  session: typeof options.session === "string" ? options.session : void 0,
41
+ agentId: typeof options.agent === "string" ? options.agent : void 0,
22
42
  message: typeof options.message === "string" ? options.message : void 0,
23
43
  workdir: typeof options.workdir === "string" ? options.workdir : void 0,
24
44
  useStartupCwd: options.cwd !== false,
@@ -36,8 +56,10 @@ register({
36
56
  metadata: {
37
57
  category: "runtime",
38
58
  examples: [
59
+ "xopc",
39
60
  "xopc tui",
40
- "xopc tui --local",
61
+ "xopc tui --agent coder",
62
+ "xopc tui --set-default-agent coder",
41
63
  "xopc tui --gateway",
42
64
  "xopc tui --url http://host:3120"
43
65
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"tui.js","names":[],"sources":["../../../../src/cli/commands/tui.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { register, formatExamples, type CLIContext } from '../registry.js';\n\nfunction createTuiCommand(_ctx: CLIContext): Command {\n const cmd = new Command('tui')\n .description('Interactive terminal UI (pi-tui)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc tui # Embedded mode (default)',\n 'xopc tui --gateway # Force gateway mode',\n 'xopc tui --local # Embedded mode (default)',\n 'xopc tui --url http://host:3120 --token xxx # Connect to remote gateway',\n 'xopc tui -s agent:main:tui-... # Resume a session',\n 'xopc tui -m \"Summarize my inbox\" # Send a message on launch',\n ]),\n )\n .option('--url <url>', 'Gateway URL (default: http://localhost:3120)')\n .option('--token <token>', 'Gateway bearer token')\n .option('-s, --session <key>', 'Session key to resume (omitted: start a fresh TUI session)')\n .option('-m, --message <text>', 'Send a message on launch')\n .option('--workdir <dir>', 'Workspace directory for the new TUI session')\n .option('--no-cwd', 'Do not use the launch directory as the new TUI session workspace')\n .option('--local', 'Run in embedded mode (no gateway required)')\n .option('--gateway', 'Force gateway mode even without explicit --url or --token')\n .option('--theme <name>', 'Theme: auto, dark, light, or custom name from ~/.xopc/themes/')\n .option('--thinking <level>', 'Thinking level override')\n .action(async (options: Record<string, string | boolean | undefined>) => {\n const { runTui } = await import('../../tui/tui.js');\n const useLocal = options.local === true;\n const useGateway =\n options.gateway === true ||\n typeof options.url === 'string' ||\n typeof options.token === 'string';\n if (useLocal && useGateway) {\n console.log('`--local` and gateway flags both set. Using local mode.');\n }\n const localMode = useLocal || !useGateway;\n await runTui({\n url: typeof options.url === 'string' ? options.url : undefined,\n token: typeof options.token === 'string' ? options.token : undefined,\n session: typeof options.session === 'string' ? options.session : undefined,\n message: typeof options.message === 'string' ? options.message : undefined,\n workdir: typeof options.workdir === 'string' ? options.workdir : undefined,\n useStartupCwd: options.cwd !== false,\n local: localMode,\n thinking: typeof options.thinking === 'string' ? options.thinking : undefined,\n theme: typeof options.theme === 'string' ? options.theme : undefined,\n });\n });\n\n return cmd;\n}\n\nregister({\n id: 'tui',\n name: 'tui',\n description: 'Interactive terminal UI (pi-tui)',\n factory: createTuiCommand,\n metadata: {\n category: 'runtime',\n examples: [\n 'xopc tui',\n 'xopc tui --local',\n 'xopc tui --gateway',\n 'xopc tui --url http://host:3120',\n ],\n },\n});\n"],"mappings":";;;AAIA,SAAS,iBAAiB,MAA2B;AAgDnD,QA/CY,IAAI,QAAQ,MAAM,CAC3B,YAAY,mCAAmC,CAC/C,YACC,SACA,eAAe;EACb;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CACH,CACA,OAAO,eAAe,+CAA+C,CACrE,OAAO,mBAAmB,uBAAuB,CACjD,OAAO,uBAAuB,6DAA6D,CAC3F,OAAO,wBAAwB,2BAA2B,CAC1D,OAAO,mBAAmB,8CAA8C,CACxE,OAAO,YAAY,mEAAmE,CACtF,OAAO,WAAW,6CAA6C,CAC/D,OAAO,aAAa,4DAA4D,CAChF,OAAO,kBAAkB,gEAAgE,CACzF,OAAO,sBAAsB,0BAA0B,CACvD,OAAO,OAAO,YAA0D;EACvE,MAAM,EAAE,WAAW,MAAM,OAAO;EAChC,MAAM,WAAW,QAAQ,UAAU;EACnC,MAAM,aACJ,QAAQ,YAAY,QACpB,OAAO,QAAQ,QAAQ,YACvB,OAAO,QAAQ,UAAU;AAC3B,MAAI,YAAY,WACd,SAAQ,IAAI,0DAA0D;EAExE,MAAM,YAAY,YAAY,CAAC;AAC/B,QAAM,OAAO;GACX,KAAK,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM,KAAA;GACrD,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,KAAA;GAC3D,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,eAAe,QAAQ,QAAQ;GAC/B,OAAO;GACP,UAAU,OAAO,QAAQ,aAAa,WAAW,QAAQ,WAAW,KAAA;GACpE,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,KAAA;GAC5D,CAAC;GAGI;;AAGZ,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU;GACR;GACA;GACA;GACA;GACD;EACF;CACF,CAAC"}
1
+ {"version":3,"file":"tui.js","names":[],"sources":["../../../../src/cli/commands/tui.ts"],"sourcesContent":["import { Command } from 'commander';\n\nimport { setTuiDefaultAgentConfig } from '../../commands/agents.config.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport { detectMigrations, runBootstrapMigrationsSync } from '../../migrations/runner.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\n\nfunction createTuiCommand(ctx: CLIContext): Command {\n const cmd = new Command('tui')\n .description('Interactive terminal UI (pi-tui)')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc # Open embedded TUI (default command)',\n 'xopc tui # Embedded mode (default)',\n 'xopc tui --gateway # Force gateway mode',\n 'xopc tui --url http://host:3120 --token xxx # Connect to remote gateway',\n 'xopc tui -s agent:main:tui-... # Resume a session',\n 'xopc tui --agent coder # Start with a specific agent',\n 'xopc tui --set-default-agent coder # Persist default agent for new TUI sessions',\n 'xopc tui -m \"Summarize my inbox\" # Send a message on launch',\n ]),\n )\n .option('--url <url>', 'Gateway URL (default: http://localhost:3120)')\n .option('--token <token>', 'Gateway bearer token')\n .option('-s, --session <key>', 'Session key to resume (omitted: start a fresh TUI session)')\n .option('--agent <id>', 'Agent id for a fresh TUI session')\n .option('--set-default-agent <id>', 'Persist default agent for new TUI sessions and exit')\n .option('-m, --message <text>', 'Send a message on launch')\n .option('--workdir <dir>', 'Workspace directory for the new TUI session')\n .option('--no-cwd', 'Do not use the launch directory as the new TUI session workspace')\n .option('--local', 'Run in embedded mode (no gateway required)')\n .option('--gateway', 'Force gateway mode even without explicit --url or --token')\n .option('--theme <name>', 'Theme: auto, dark, light, or custom name from ~/.xopc/themes/')\n .option('--thinking <level>', 'Thinking level override')\n .action(async (options: Record<string, string | boolean | undefined>) => {\n runBootstrapMigrationsSync(ctx.configPath);\n const pendingMigrations = detectMigrations(ctx.configPath);\n if (pendingMigrations.length > 0) {\n console.warn(\n `xopc has ${pendingMigrations.length} pending migration(s). Run \\`xopc doctor --fix\\` or open Settings → App management.`,\n );\n }\n if (typeof options.setDefaultAgent === 'string') {\n const cfg = loadConfig(ctx.configPath);\n const result = setTuiDefaultAgentConfig(cfg, options.setDefaultAgent);\n if (result.ok === false) {\n console.error(`Error: ${result.message}`);\n process.exit(1);\n }\n await saveConfig(result.config, ctx.configPath);\n console.log(`TUI default agent set to \"${result.agentId}\".`);\n return;\n }\n const { runTui } = await import('../../tui/tui.js');\n const useLocal = options.local === true;\n const useGateway =\n options.gateway === true ||\n typeof options.url === 'string' ||\n typeof options.token === 'string';\n if (useLocal && useGateway) {\n console.log('`--local` and gateway flags both set. Using local mode.');\n }\n const localMode = useLocal || !useGateway;\n await runTui({\n url: typeof options.url === 'string' ? options.url : undefined,\n token: typeof options.token === 'string' ? options.token : undefined,\n session: typeof options.session === 'string' ? options.session : undefined,\n agentId: typeof options.agent === 'string' ? options.agent : undefined,\n message: typeof options.message === 'string' ? options.message : undefined,\n workdir: typeof options.workdir === 'string' ? options.workdir : undefined,\n useStartupCwd: options.cwd !== false,\n local: localMode,\n thinking: typeof options.thinking === 'string' ? options.thinking : undefined,\n theme: typeof options.theme === 'string' ? options.theme : undefined,\n });\n });\n\n return cmd;\n}\n\nregister({\n id: 'tui',\n name: 'tui',\n description: 'Interactive terminal UI (pi-tui)',\n factory: createTuiCommand,\n metadata: {\n category: 'runtime',\n examples: [\n 'xopc',\n 'xopc tui',\n 'xopc tui --agent coder',\n 'xopc tui --set-default-agent coder',\n 'xopc tui --gateway',\n 'xopc tui --url http://host:3120',\n ],\n },\n});\n"],"mappings":";;;;;;aAGgE;AAIhE,SAAS,iBAAiB,KAA0B;AAuElD,QAtEY,IAAI,QAAQ,MAAM,CAC3B,YAAY,mCAAmC,CAC/C,YACC,SACA,eAAe;EACb;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,CACH,CACA,OAAO,eAAe,+CAA+C,CACrE,OAAO,mBAAmB,uBAAuB,CACjD,OAAO,uBAAuB,6DAA6D,CAC3F,OAAO,gBAAgB,mCAAmC,CAC1D,OAAO,4BAA4B,sDAAsD,CACzF,OAAO,wBAAwB,2BAA2B,CAC1D,OAAO,mBAAmB,8CAA8C,CACxE,OAAO,YAAY,mEAAmE,CACtF,OAAO,WAAW,6CAA6C,CAC/D,OAAO,aAAa,4DAA4D,CAChF,OAAO,kBAAkB,gEAAgE,CACzF,OAAO,sBAAsB,0BAA0B,CACvD,OAAO,OAAO,YAA0D;AACvE,6BAA2B,IAAI,WAAW;EAC1C,MAAM,oBAAoB,iBAAiB,IAAI,WAAW;AAC1D,MAAI,kBAAkB,SAAS,EAC7B,SAAQ,KACN,YAAY,kBAAkB,OAAO,qFACtC;AAEH,MAAI,OAAO,QAAQ,oBAAoB,UAAU;GAE/C,MAAM,SAAS,yBADH,WAAW,IAAI,WACgB,EAAE,QAAQ,gBAAgB;AACrE,OAAI,OAAO,OAAO,OAAO;AACvB,YAAQ,MAAM,UAAU,OAAO,UAAU;AACzC,YAAQ,KAAK,EAAE;;AAEjB,SAAM,WAAW,OAAO,QAAQ,IAAI,WAAW;AAC/C,WAAQ,IAAI,6BAA6B,OAAO,QAAQ,IAAI;AAC5D;;EAEF,MAAM,EAAE,WAAW,MAAM,OAAO;EAChC,MAAM,WAAW,QAAQ,UAAU;EACnC,MAAM,aACJ,QAAQ,YAAY,QACpB,OAAO,QAAQ,QAAQ,YACvB,OAAO,QAAQ,UAAU;AAC3B,MAAI,YAAY,WACd,SAAQ,IAAI,0DAA0D;EAExE,MAAM,YAAY,YAAY,CAAC;AAC/B,QAAM,OAAO;GACX,KAAK,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM,KAAA;GACrD,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,KAAA;GAC3D,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,SAAS,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,KAAA;GAC7D,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,SAAS,OAAO,QAAQ,YAAY,WAAW,QAAQ,UAAU,KAAA;GACjE,eAAe,QAAQ,QAAQ;GAC/B,OAAO;GACP,UAAU,OAAO,QAAQ,aAAa,WAAW,QAAQ,WAAW,KAAA;GACpE,OAAO,OAAO,QAAQ,UAAU,WAAW,QAAQ,QAAQ,KAAA;GAC5D,CAAC;GAGI;;AAGZ,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU;GACR;GACA;GACA;GACA;GACA;GACA;GACD;EACF;CACF,CAAC"}
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
  export { parsedOpts, getContextWithOpts } from './context.js';
3
+ export declare function argvWithDefaultCommand(argv: string[], defaultCommand?: string): string[];
3
4
  export declare function runCli(argv?: string[]): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { version } from "../../package.js";
3
+ import { isHelpOrVersionInvocation } from "./argv.js";
3
4
  import { ROOT_COMMAND_DESCRIPTION } from "./command-manifest.js";
4
5
  import { loadAllCommands, resolveCommandName, tryLoadCommand } from "./command-loaders.js";
5
6
  import { getContextWithOpts, parsedOpts } from "./context.js";
@@ -12,6 +13,10 @@ async function flushLoggerAndExit(code) {
12
13
  process.exit(code);
13
14
  }
14
15
  const LONG_RUNNING_COMMANDS = new Set(["gateway", "agent"]);
16
+ function argvWithDefaultCommand(argv, defaultCommand = "tui") {
17
+ if (resolveCommandName(argv) || isHelpOrVersionInvocation(argv)) return argv;
18
+ return [...argv, defaultCommand];
19
+ }
15
20
  function isExtensionsDevCommand(command) {
16
21
  return command.name() === "dev" && command.parent?.name() === "extensions";
17
22
  }
@@ -39,17 +44,17 @@ function buildProgram() {
39
44
  async function runCli(argv = process.argv) {
40
45
  const program = buildProgram();
41
46
  const ctx = getContextWithOpts(argv);
42
- const filteredArgv = argv.filter((arg, index) => {
47
+ const argvToParse = argvWithDefaultCommand(argv.filter((arg, index) => {
43
48
  if (arg !== "--") return true;
44
49
  return index < 2;
45
- });
46
- const target = resolveCommandName(filteredArgv);
50
+ }));
51
+ const target = resolveCommandName(argvToParse);
47
52
  let loaded = false;
48
53
  if (target) loaded = await tryLoadCommand(program, ctx, target, getContextWithOpts);
49
54
  if (!loaded) await loadAllCommands(program, ctx, getContextWithOpts);
50
- program.parse(filteredArgv);
55
+ program.parse(argvToParse);
51
56
  }
52
57
  //#endregion
53
- export { getContextWithOpts, parsedOpts, runCli };
58
+ export { argvWithDefaultCommand, getContextWithOpts, parsedOpts, runCli };
54
59
 
55
60
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["pkg.version"],"sources":["../../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n/** Command wiring and `program.parse`; executable entry is `bin.ts` (log preset before logger init). */\nimport { Command } from 'commander';\nimport { ROOT_COMMAND_DESCRIPTION } from './command-manifest.js';\nimport pkg from '../../package.json' with { type: 'json' };\nimport { resolveCommandName, tryLoadCommand, loadAllCommands } from './command-loaders.js';\n\n// Lazy logger flush so that pure parameter-parsing paths (--help, --version,\n// `<unknown>`) never load the logger barrel. Imports `logger/shutdown.js`\n// directly to bypass `logger/index.ts` (pino + 8 sub-modules) on the cold path\n// — when an action did log, that import is already cached.\nasync function flushLoggerAndExit(code: number): Promise<never> {\n const { flushAndClose } = await import('../utils/logger/shutdown.js');\n await flushAndClose();\n process.exit(code);\n}\n\n// Re-exported from `./context.js` for backward compat. Command modules should\n// import from `./context.js` directly to avoid the CLI barrel cycle.\nexport { parsedOpts, getContextWithOpts } from './context.js';\nimport { parsedOpts, getContextWithOpts } from './context.js';\n\n// Commands whose action never resolves until an external shutdown signal.\n// `tui` is intentionally omitted: `await runTui()` completes when the user exits\n// the TUI and the process must call `process.exit` (interactive stdin stays open).\nconst LONG_RUNNING_COMMANDS = new Set(['gateway', 'agent']);\n\nfunction isExtensionsDevCommand(command: Command): boolean {\n return command.name() === 'dev' && command.parent?.name() === 'extensions';\n}\n\nfunction buildProgram(): Command {\n const program = new Command()\n .name('xopc')\n .description(ROOT_COMMAND_DESCRIPTION)\n .version(pkg.version)\n .option('--verbose', 'Enable verbose logging', false)\n .option('--config <path>', 'Config file path')\n .option('--workspace <path>', 'Workspace directory');\n\n // Hook to capture parsed options before each command runs. Mutate the\n // shared object in place — `parsedOpts` is a `const` import from\n // `./context.js` so command modules see updates through the same reference.\n program.hook('preAction', (thisCommand) => {\n const next = thisCommand.opts() as Record<string, unknown>;\n for (const k of Object.keys(parsedOpts)) {\n delete (parsedOpts as Record<string, unknown>)[k];\n }\n Object.assign(parsedOpts, next);\n });\n\n // Hook to ensure process exits after command completion.\n // Second arg is the command whose action ran; the first is the ancestor that\n // registered the hook (often the root program), so using only the first arg\n // mis-detects the subcommand as \"xopc\".\n program.hook('postAction', async (_hookOwner, actionCommand) => {\n const cmd = actionCommand ?? program;\n const args = cmd.args;\n const subCommandName = args.length > 0 ? args[0] : cmd.name();\n\n if (LONG_RUNNING_COMMANDS.has(subCommandName) || isExtensionsDevCommand(cmd)) {\n if (subCommandName === 'agent') {\n const hasInteractiveFlag = process.argv.includes('-i') || process.argv.includes('--interactive');\n if (!hasInteractiveFlag) {\n await flushLoggerAndExit(0);\n }\n }\n return;\n }\n await flushLoggerAndExit(0);\n });\n\n return program;\n}\n\nexport async function runCli(argv: string[] = process.argv): Promise<void> {\n const program = buildProgram();\n const ctx = getContextWithOpts(argv);\n\n // Filter out standalone '--' separator (passed by pnpm run -- <cmd>).\n // npm removes it automatically, pnpm passes it through. Keep '--' if it's a\n // script argument (index < 2), drop it only when it sits between the script\n // name and the actual command.\n const filteredArgv = argv.filter((arg, index) => {\n if (arg !== '--') return true;\n return index < 2;\n });\n\n const target = resolveCommandName(filteredArgv);\n let loaded = false;\n if (target) {\n loaded = await tryLoadCommand(program, ctx, target, getContextWithOpts);\n }\n if (!loaded) {\n // Unknown command, no command, or commander needs the full set (e.g. for\n // root help fallback). Load every command so commander can dispatch\n // properly.\n await loadAllCommands(program, ctx, getContextWithOpts);\n }\n\n program.parse(filteredArgv);\n}\n"],"mappings":";;;;;;;;AAWA,eAAe,mBAAmB,MAA8B;CAC9D,MAAM,EAAE,kBAAkB,MAAM,OAAO;AACvC,OAAM,eAAe;AACrB,SAAQ,KAAK,KAAK;;AAWpB,MAAM,wBAAwB,IAAI,IAAI,CAAC,WAAW,QAAQ,CAAC;AAE3D,SAAS,uBAAuB,SAA2B;AACzD,QAAO,QAAQ,MAAM,KAAK,SAAS,QAAQ,QAAQ,MAAM,KAAK;;AAGhE,SAAS,eAAwB;CAC/B,MAAM,UAAU,IAAI,SAAS,CAC1B,KAAK,OAAO,CACZ,YAAY,yBAAyB,CACrC,QAAQA,QAAY,CACpB,OAAO,aAAa,0BAA0B,MAAM,CACpD,OAAO,mBAAmB,mBAAmB,CAC7C,OAAO,sBAAsB,sBAAsB;AAKtD,SAAQ,KAAK,cAAc,gBAAgB;EACzC,MAAM,OAAO,YAAY,MAAM;AAC/B,OAAK,MAAM,KAAK,OAAO,KAAK,WAAW,CACrC,QAAQ,WAAuC;AAEjD,SAAO,OAAO,YAAY,KAAK;GAC/B;AAMF,SAAQ,KAAK,cAAc,OAAO,YAAY,kBAAkB;EAC9D,MAAM,MAAM,iBAAiB;EAC7B,MAAM,OAAO,IAAI;EACjB,MAAM,iBAAiB,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,MAAM;AAE7D,MAAI,sBAAsB,IAAI,eAAe,IAAI,uBAAuB,IAAI,EAAE;AAC5E,OAAI,mBAAmB;QAEjB,EADuB,QAAQ,KAAK,SAAS,KAAK,IAAI,QAAQ,KAAK,SAAS,gBAAgB,EAE9F,OAAM,mBAAmB,EAAE;;AAG/B;;AAEF,QAAM,mBAAmB,EAAE;GAC3B;AAEF,QAAO;;AAGT,eAAsB,OAAO,OAAiB,QAAQ,MAAqB;CACzE,MAAM,UAAU,cAAc;CAC9B,MAAM,MAAM,mBAAmB,KAAK;CAMpC,MAAM,eAAe,KAAK,QAAQ,KAAK,UAAU;AAC/C,MAAI,QAAQ,KAAM,QAAO;AACzB,SAAO,QAAQ;GACf;CAEF,MAAM,SAAS,mBAAmB,aAAa;CAC/C,IAAI,SAAS;AACb,KAAI,OACF,UAAS,MAAM,eAAe,SAAS,KAAK,QAAQ,mBAAmB;AAEzE,KAAI,CAAC,OAIH,OAAM,gBAAgB,SAAS,KAAK,mBAAmB;AAGzD,SAAQ,MAAM,aAAa"}
1
+ {"version":3,"file":"index.js","names":["pkg.version"],"sources":["../../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\n/** Command wiring and `program.parse`; executable entry is `bin.ts` (log preset before logger init). */\nimport { Command } from 'commander';\nimport { ROOT_COMMAND_DESCRIPTION } from './command-manifest.js';\nimport pkg from '../../package.json' with { type: 'json' };\nimport { resolveCommandName, tryLoadCommand, loadAllCommands } from './command-loaders.js';\nimport { isHelpOrVersionInvocation } from './argv.js';\n\n// Lazy logger flush so that pure parameter-parsing paths (--help, --version,\n// `<unknown>`) never load the logger barrel. Imports `logger/shutdown.js`\n// directly to bypass `logger/index.ts` (pino + 8 sub-modules) on the cold path\n// — when an action did log, that import is already cached.\nasync function flushLoggerAndExit(code: number): Promise<never> {\n const { flushAndClose } = await import('../utils/logger/shutdown.js');\n await flushAndClose();\n process.exit(code);\n}\n\n// Re-exported from `./context.js` for backward compat. Command modules should\n// import from `./context.js` directly to avoid the CLI barrel cycle.\nexport { parsedOpts, getContextWithOpts } from './context.js';\nimport { parsedOpts, getContextWithOpts } from './context.js';\n\n// Commands whose action never resolves until an external shutdown signal.\n// `tui` is intentionally omitted: `await runTui()` completes when the user exits\n// the TUI and the process must call `process.exit` (interactive stdin stays open).\nconst LONG_RUNNING_COMMANDS = new Set(['gateway', 'agent']);\n\nexport function argvWithDefaultCommand(argv: string[], defaultCommand = 'tui'): string[] {\n const target = resolveCommandName(argv);\n if (target || isHelpOrVersionInvocation(argv)) {\n return argv;\n }\n return [...argv, defaultCommand];\n}\n\nfunction isExtensionsDevCommand(command: Command): boolean {\n return command.name() === 'dev' && command.parent?.name() === 'extensions';\n}\n\nfunction buildProgram(): Command {\n const program = new Command()\n .name('xopc')\n .description(ROOT_COMMAND_DESCRIPTION)\n .version(pkg.version)\n .option('--verbose', 'Enable verbose logging', false)\n .option('--config <path>', 'Config file path')\n .option('--workspace <path>', 'Workspace directory');\n\n // Hook to capture parsed options before each command runs. Mutate the\n // shared object in place — `parsedOpts` is a `const` import from\n // `./context.js` so command modules see updates through the same reference.\n program.hook('preAction', (thisCommand) => {\n const next = thisCommand.opts() as Record<string, unknown>;\n for (const k of Object.keys(parsedOpts)) {\n delete (parsedOpts as Record<string, unknown>)[k];\n }\n Object.assign(parsedOpts, next);\n });\n\n // Hook to ensure process exits after command completion.\n // Second arg is the command whose action ran; the first is the ancestor that\n // registered the hook (often the root program), so using only the first arg\n // mis-detects the subcommand as \"xopc\".\n program.hook('postAction', async (_hookOwner, actionCommand) => {\n const cmd = actionCommand ?? program;\n const args = cmd.args;\n const subCommandName = args.length > 0 ? args[0] : cmd.name();\n\n if (LONG_RUNNING_COMMANDS.has(subCommandName) || isExtensionsDevCommand(cmd)) {\n if (subCommandName === 'agent') {\n const hasInteractiveFlag = process.argv.includes('-i') || process.argv.includes('--interactive');\n if (!hasInteractiveFlag) {\n await flushLoggerAndExit(0);\n }\n }\n return;\n }\n await flushLoggerAndExit(0);\n });\n\n return program;\n}\n\nexport async function runCli(argv: string[] = process.argv): Promise<void> {\n const program = buildProgram();\n const ctx = getContextWithOpts(argv);\n\n // Filter out standalone '--' separator (passed by pnpm run -- <cmd>).\n // npm removes it automatically, pnpm passes it through. Keep '--' if it's a\n // script argument (index < 2), drop it only when it sits between the script\n // name and the actual command.\n const filteredArgv = argv.filter((arg, index) => {\n if (arg !== '--') return true;\n return index < 2;\n });\n\n const argvToParse = argvWithDefaultCommand(filteredArgv);\n const target = resolveCommandName(argvToParse);\n let loaded = false;\n if (target) {\n loaded = await tryLoadCommand(program, ctx, target, getContextWithOpts);\n }\n if (!loaded) {\n // Unknown command, no command, or commander needs the full set (e.g. for\n // root help fallback). Load every command so commander can dispatch\n // properly.\n await loadAllCommands(program, ctx, getContextWithOpts);\n }\n\n program.parse(argvToParse);\n}\n"],"mappings":";;;;;;;;;AAYA,eAAe,mBAAmB,MAA8B;CAC9D,MAAM,EAAE,kBAAkB,MAAM,OAAO;AACvC,OAAM,eAAe;AACrB,SAAQ,KAAK,KAAK;;AAWpB,MAAM,wBAAwB,IAAI,IAAI,CAAC,WAAW,QAAQ,CAAC;AAE3D,SAAgB,uBAAuB,MAAgB,iBAAiB,OAAiB;AAEvF,KADe,mBAAmB,KACxB,IAAI,0BAA0B,KAAK,CAC3C,QAAO;AAET,QAAO,CAAC,GAAG,MAAM,eAAe;;AAGlC,SAAS,uBAAuB,SAA2B;AACzD,QAAO,QAAQ,MAAM,KAAK,SAAS,QAAQ,QAAQ,MAAM,KAAK;;AAGhE,SAAS,eAAwB;CAC/B,MAAM,UAAU,IAAI,SAAS,CAC1B,KAAK,OAAO,CACZ,YAAY,yBAAyB,CACrC,QAAQA,QAAY,CACpB,OAAO,aAAa,0BAA0B,MAAM,CACpD,OAAO,mBAAmB,mBAAmB,CAC7C,OAAO,sBAAsB,sBAAsB;AAKtD,SAAQ,KAAK,cAAc,gBAAgB;EACzC,MAAM,OAAO,YAAY,MAAM;AAC/B,OAAK,MAAM,KAAK,OAAO,KAAK,WAAW,CACrC,QAAQ,WAAuC;AAEjD,SAAO,OAAO,YAAY,KAAK;GAC/B;AAMF,SAAQ,KAAK,cAAc,OAAO,YAAY,kBAAkB;EAC9D,MAAM,MAAM,iBAAiB;EAC7B,MAAM,OAAO,IAAI;EACjB,MAAM,iBAAiB,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,MAAM;AAE7D,MAAI,sBAAsB,IAAI,eAAe,IAAI,uBAAuB,IAAI,EAAE;AAC5E,OAAI,mBAAmB;QAEjB,EADuB,QAAQ,KAAK,SAAS,KAAK,IAAI,QAAQ,KAAK,SAAS,gBAAgB,EAE9F,OAAM,mBAAmB,EAAE;;AAG/B;;AAEF,QAAM,mBAAmB,EAAE;GAC3B;AAEF,QAAO;;AAGT,eAAsB,OAAO,OAAiB,QAAQ,MAAqB;CACzE,MAAM,UAAU,cAAc;CAC9B,MAAM,MAAM,mBAAmB,KAAK;CAWpC,MAAM,cAAc,uBALC,KAAK,QAAQ,KAAK,UAAU;AAC/C,MAAI,QAAQ,KAAM,QAAO;AACzB,SAAO,QAAQ;GAGsC,CAAC;CACxD,MAAM,SAAS,mBAAmB,YAAY;CAC9C,IAAI,SAAS;AACb,KAAI,OACF,UAAS,MAAM,eAAe,SAAS,KAAK,QAAQ,mBAAmB;AAEzE,KAAI,CAAC,OAIH,OAAM,gBAAgB,SAAS,KAAK,mBAAmB;AAGzD,SAAQ,MAAM,YAAY"}
@@ -5,7 +5,7 @@ init_paths();
5
5
  init_workspace_defaults();
6
6
  function createDefaultContext(argv = process.argv, opts) {
7
7
  return {
8
- configPath: opts?.config || process.env.XOPC_CONFIG || resolveConfigPath(),
8
+ configPath: opts?.config || process.env.XOPC_CONFIG || process.env.XOPC_CONFIG_PATH || resolveConfigPath(),
9
9
  workspacePath: opts?.workspace || process.env.XOPC_WORKSPACE || resolveDefaultAgentWorkspaceDir(),
10
10
  isVerbose: opts?.verbose ?? (argv.includes("--verbose") || argv.includes("-v")),
11
11
  argv
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","names":[],"sources":["../../../src/cli/registry.ts"],"sourcesContent":["import type { Command } from 'commander';\nimport { resolveConfigPath } from '../config/paths.js';\nimport { resolveDefaultAgentWorkspaceDir } from '../config/workspace-defaults.js';\n\nexport interface CLIContext {\n configPath: string;\n workspacePath: string;\n isVerbose: boolean;\n argv: string[];\n}\n\nexport function createDefaultContext(\n argv: string[] = process.argv,\n opts?: { config?: string; workspace?: string; verbose?: boolean }\n): CLIContext {\n return {\n configPath: opts?.config || process.env.XOPC_CONFIG || resolveConfigPath(),\n workspacePath: opts?.workspace || process.env.XOPC_WORKSPACE || resolveDefaultAgentWorkspaceDir(),\n isVerbose: (opts?.verbose ?? (argv.includes('--verbose') || argv.includes('-v'))),\n argv,\n };\n}\n\nexport interface CommandMetadata {\n category?: 'setup' | 'runtime' | 'maintenance' | 'utility';\n hidden?: boolean;\n unstable?: boolean;\n examples?: string[];\n}\n\nexport interface CommandDefinition {\n id: string;\n name: string;\n description: string;\n factory: (ctx: CLIContext, getCtx?: () => CLIContext) => Command;\n metadata?: CommandMetadata;\n}\n\nexport class CommandRegistry {\n private commands: CommandDefinition[] = [];\n private initialized = false;\n private suppressLateRegistrationWarnings = false;\n\n /**\n * Temporarily silence the \"registered after initialization\" warning. Used by\n * commands that need to bulk-load other command modules to harvest their\n * side effects during initialization.\n */\n setSuppressLateRegistrationWarnings(value: boolean): void {\n this.suppressLateRegistrationWarnings = value;\n }\n\n register(def: CommandDefinition): void {\n if (this.initialized && !this.suppressLateRegistrationWarnings) {\n console.warn(`Warning: Command \"${def.id}\" registered after initialization`);\n }\n\n const existing = this.commands.find(c => c.id === def.id);\n if (existing) {\n throw new Error(`Command with id \"${def.id}\" already registered (name: ${existing.name})`);\n }\n\n const existingName = this.commands.find(c => c.name === def.name);\n if (existingName) {\n throw new Error(`Command with name \"${def.name}\" already registered (id: ${existingName.id})`);\n }\n\n this.commands.push(def);\n }\n\n registerAll(defs: CommandDefinition[]): void {\n for (const def of defs) {\n this.register(def);\n }\n }\n\n getCommands(): ReadonlyArray<CommandDefinition> {\n return this.commands;\n }\n\n getCommandsByCategory(category: CommandMetadata['category']): ReadonlyArray<CommandDefinition> {\n return this.commands.filter(c => c.metadata?.category === category);\n }\n\n findById(id: string): CommandDefinition | undefined {\n return this.commands.find(c => c.id === id);\n }\n\n findByName(name: string): CommandDefinition | undefined {\n return this.commands.find(c => c.name === name);\n }\n\n install(program: Command, ctx: CLIContext, getCtx?: () => CLIContext): void {\n this.initialized = true;\n\n const categoryOrder = { setup: 0, runtime: 1, maintenance: 2, utility: 3 };\n const sorted = [...this.commands].sort((a, b) => {\n const orderA = categoryOrder[a.metadata?.category ?? 'utility'];\n const orderB = categoryOrder[b.metadata?.category ?? 'utility'];\n return orderA - orderB;\n });\n\n for (const def of sorted) {\n if (def.metadata?.hidden) continue;\n\n try {\n const cmd = def.factory(ctx, getCtx);\n program.addCommand(cmd);\n } catch (error) {\n console.error(`Failed to register command \"${def.id}\":`, error);\n }\n }\n }\n\n installOne(\n program: Command,\n name: string,\n ctx: CLIContext,\n getCtx?: () => CLIContext,\n ): boolean {\n this.initialized = true;\n const def = this.findByName(name);\n if (!def || def.metadata?.hidden) return false;\n try {\n const cmd = def.factory(ctx, getCtx);\n program.addCommand(cmd);\n return true;\n } catch (error) {\n console.error(`Failed to register command \"${def.id}\":`, error);\n return false;\n }\n }\n\n getStats(): { total: number; byCategory: Record<string, number> } {\n const byCategory: Record<string, number> = {};\n for (const cmd of this.commands) {\n const cat = cmd.metadata?.category ?? 'uncategorized';\n byCategory[cat] = (byCategory[cat] || 0) + 1;\n }\n return { total: this.commands.length, byCategory };\n }\n}\n\nexport const registry = new CommandRegistry();\n\nexport function register(def: CommandDefinition): void {\n registry.register(def);\n}\n\nexport function formatExamples(examples: string[]): string {\n if (examples.length === 0) return '';\n return '\\nExamples:\\n' + examples.map(e => ` $ ${e}`).join('\\n');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","names":[],"sources":["../../../src/cli/registry.ts"],"sourcesContent":["import type { Command } from 'commander';\nimport { resolveConfigPath } from '../config/paths.js';\nimport { resolveDefaultAgentWorkspaceDir } from '../config/workspace-defaults.js';\n\nexport interface CLIContext {\n configPath: string;\n workspacePath: string;\n isVerbose: boolean;\n argv: string[];\n}\n\nexport function createDefaultContext(\n argv: string[] = process.argv,\n opts?: { config?: string; workspace?: string; verbose?: boolean }\n): CLIContext {\n return {\n configPath: opts?.config || process.env.XOPC_CONFIG || process.env.XOPC_CONFIG_PATH || resolveConfigPath(),\n workspacePath: opts?.workspace || process.env.XOPC_WORKSPACE || resolveDefaultAgentWorkspaceDir(),\n isVerbose: (opts?.verbose ?? (argv.includes('--verbose') || argv.includes('-v'))),\n argv,\n };\n}\n\nexport interface CommandMetadata {\n category?: 'setup' | 'runtime' | 'maintenance' | 'utility';\n hidden?: boolean;\n unstable?: boolean;\n examples?: string[];\n}\n\nexport interface CommandDefinition {\n id: string;\n name: string;\n description: string;\n factory: (ctx: CLIContext, getCtx?: () => CLIContext) => Command;\n metadata?: CommandMetadata;\n}\n\nexport class CommandRegistry {\n private commands: CommandDefinition[] = [];\n private initialized = false;\n private suppressLateRegistrationWarnings = false;\n\n /**\n * Temporarily silence the \"registered after initialization\" warning. Used by\n * commands that need to bulk-load other command modules to harvest their\n * side effects during initialization.\n */\n setSuppressLateRegistrationWarnings(value: boolean): void {\n this.suppressLateRegistrationWarnings = value;\n }\n\n register(def: CommandDefinition): void {\n if (this.initialized && !this.suppressLateRegistrationWarnings) {\n console.warn(`Warning: Command \"${def.id}\" registered after initialization`);\n }\n\n const existing = this.commands.find(c => c.id === def.id);\n if (existing) {\n throw new Error(`Command with id \"${def.id}\" already registered (name: ${existing.name})`);\n }\n\n const existingName = this.commands.find(c => c.name === def.name);\n if (existingName) {\n throw new Error(`Command with name \"${def.name}\" already registered (id: ${existingName.id})`);\n }\n\n this.commands.push(def);\n }\n\n registerAll(defs: CommandDefinition[]): void {\n for (const def of defs) {\n this.register(def);\n }\n }\n\n getCommands(): ReadonlyArray<CommandDefinition> {\n return this.commands;\n }\n\n getCommandsByCategory(category: CommandMetadata['category']): ReadonlyArray<CommandDefinition> {\n return this.commands.filter(c => c.metadata?.category === category);\n }\n\n findById(id: string): CommandDefinition | undefined {\n return this.commands.find(c => c.id === id);\n }\n\n findByName(name: string): CommandDefinition | undefined {\n return this.commands.find(c => c.name === name);\n }\n\n install(program: Command, ctx: CLIContext, getCtx?: () => CLIContext): void {\n this.initialized = true;\n\n const categoryOrder = { setup: 0, runtime: 1, maintenance: 2, utility: 3 };\n const sorted = [...this.commands].sort((a, b) => {\n const orderA = categoryOrder[a.metadata?.category ?? 'utility'];\n const orderB = categoryOrder[b.metadata?.category ?? 'utility'];\n return orderA - orderB;\n });\n\n for (const def of sorted) {\n if (def.metadata?.hidden) continue;\n\n try {\n const cmd = def.factory(ctx, getCtx);\n program.addCommand(cmd);\n } catch (error) {\n console.error(`Failed to register command \"${def.id}\":`, error);\n }\n }\n }\n\n installOne(\n program: Command,\n name: string,\n ctx: CLIContext,\n getCtx?: () => CLIContext,\n ): boolean {\n this.initialized = true;\n const def = this.findByName(name);\n if (!def || def.metadata?.hidden) return false;\n try {\n const cmd = def.factory(ctx, getCtx);\n program.addCommand(cmd);\n return true;\n } catch (error) {\n console.error(`Failed to register command \"${def.id}\":`, error);\n return false;\n }\n }\n\n getStats(): { total: number; byCategory: Record<string, number> } {\n const byCategory: Record<string, number> = {};\n for (const cmd of this.commands) {\n const cat = cmd.metadata?.category ?? 'uncategorized';\n byCategory[cat] = (byCategory[cat] || 0) + 1;\n }\n return { total: this.commands.length, byCategory };\n }\n}\n\nexport const registry = new CommandRegistry();\n\nexport function register(def: CommandDefinition): void {\n registry.register(def);\n}\n\nexport function formatExamples(examples: string[]): string {\n if (examples.length === 0) return '';\n return '\\nExamples:\\n' + examples.map(e => ` $ ${e}`).join('\\n');\n}\n"],"mappings":"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"}
@@ -3,7 +3,7 @@
3
3
  * Templates are stored in docs/reference/templates/ and loaded at runtime.
4
4
  */
5
5
  /** Profile Markdown template file names (seeded into `agents/<id>/profile/`). */
6
- export declare const TEMPLATE_FILES: readonly ["SOUL.md", "IDENTITY.md", "USER.md", "TOOLS.md", "AGENTS.md", "HEARTBEAT.md", "MEMORY.md"];
6
+ export declare const TEMPLATE_FILES: readonly ["SOUL.md", "IDENTITY.md", "TOOLS.md", "AGENTS.md", "HEARTBEAT.md", "MEMORY.md"];
7
7
  export type TemplateFile = (typeof TEMPLATE_FILES)[number];
8
8
  /** Alias for profile Markdown templates used by seed helpers. */
9
9
  export declare const PROFILE_MARKDOWN_TEMPLATE_FILES: readonly TemplateFile[];
@@ -11,7 +11,6 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
11
11
  const TEMPLATE_FILES = [
12
12
  "SOUL.md",
13
13
  "IDENTITY.md",
14
- "USER.md",
15
14
  "TOOLS.md",
16
15
  "AGENTS.md",
17
16
  "HEARTBEAT.md",
@@ -71,7 +70,7 @@ This folder is home. Treat it that way.
71
70
 
72
71
  ## Session Startup
73
72
 
74
- Use runtime-provided startup context first. Bootstrap files (SOUL, USER, MEMORY, etc.) are injected by xopc on /new and /reset.
73
+ Use runtime-provided startup context first. Bootstrap files (global user profile, SOUL, MEMORY, etc.) are injected by xopc on /new and /reset.
75
74
 
76
75
  Do not manually reread startup files unless the user asks or the provided context is incomplete.
77
76
 
@@ -116,15 +115,6 @@ _Fill this in during your first conversation._
116
115
  - **Creature:**
117
116
  - **Vibe:**
118
117
  - **Emoji:**
119
- `,
120
- "USER.md": `# USER.md - About Your Human
121
-
122
- _Learn about the person you're helping._
123
-
124
- - **Name:**
125
- - **What to call them:**
126
- - **Timezone:**
127
- - **Notes:**
128
118
  `,
129
119
  "TOOLS.md": `# TOOLS.md - Local Notes
130
120
 
@@ -1 +1 @@
1
- {"version":3,"file":"templates.js","names":[],"sources":["../../../src/cli/templates.ts"],"sourcesContent":["/**\n * Workspace template files for onboarding.\n * Templates are stored in docs/reference/templates/ and loaded at runtime.\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/** Profile Markdown template file names (seeded into `agents/<id>/profile/`). */\nexport const TEMPLATE_FILES = [\n 'SOUL.md',\n 'IDENTITY.md',\n 'USER.md',\n 'TOOLS.md',\n 'AGENTS.md',\n 'HEARTBEAT.md',\n 'MEMORY.md',\n] as const;\n\nexport type TemplateFile = (typeof TEMPLATE_FILES)[number];\n\n/** Alias for profile Markdown templates used by seed helpers. */\nexport const PROFILE_MARKDOWN_TEMPLATE_FILES: readonly TemplateFile[] = [...TEMPLATE_FILES];\n\n/** Template content cache */\nconst templateCache = new Map<TemplateFile, string>();\n\n/**\n * Get the path to template files.\n * Uses environment or looks in project root.\n */\nfunction getTemplatePath(): string {\n // Use environment to determine path\n const envPath = process.env.XOPC_TEMPLATE_PATH;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n // Default: look in project root docs/reference/templates\n // Works for both development (src/cli/) and production (dist/cli/)\n const projectRoot = join(__dirname, '../../..');\n const defaultPath = join(projectRoot, 'docs/reference/templates');\n \n if (existsSync(defaultPath)) {\n return defaultPath;\n }\n\n // Fallback: return default (will fail gracefully)\n return defaultPath;\n}\n\n/**\n * Load a template file. Caches results for repeated access.\n */\nexport function loadTemplate(name: TemplateFile): string {\n // Return cached version if available\n if (templateCache.has(name)) {\n return templateCache.get(name)!;\n }\n\n const templatePath = join(getTemplatePath(), name);\n \n try {\n if (existsSync(templatePath)) {\n const content = readFileSync(templatePath, 'utf-8');\n templateCache.set(name, content);\n return content;\n }\n } catch {\n // Fall through to fallback\n }\n\n // Fallback: return minimal default if template is missing\n console.warn(`Warning: Template ${name} not found, using fallback`);\n return getFallbackTemplate(name);\n}\n\n/**\n * Load all templates as a record.\n */\nexport function loadAllTemplates(): Record<TemplateFile, string> {\n const result = {} as Record<TemplateFile, string>;\n for (const name of TEMPLATE_FILES) {\n result[name] = loadTemplate(name);\n }\n return result;\n}\n\n/**\n * Clear the template cache (useful for testing).\n */\nexport function clearTemplateCache(): void {\n templateCache.clear();\n}\n\n/** Minimal fallback templates in case files are missing */\nexport function getFallbackTemplate(name: TemplateFile): string {\n const fallbacks: Record<TemplateFile, string> = {\n 'AGENTS.md': `# AGENTS.md - Your Workspace\n\nThis folder is home. Treat it that way.\n\n## Session Startup\n\nUse runtime-provided startup context first. Bootstrap files (SOUL, USER, MEMORY, etc.) are injected by xopc on /new and /reset.\n\nDo not manually reread startup files unless the user asks or the provided context is incomplete.\n\n## Red Lines\n\n- Don't exfiltrate private data\n- Don't run destructive commands without asking\n- When in doubt, ask\n\n## Memory\n\n- **Daily notes:** \\`memory/YYYY-MM-DD.md\\`\n- **Long-term:** profile \\`MEMORY.md\\`\n\nWrite what matters. Text > Brain.\n`,\n 'SOUL.md': `# SOUL.md - Who You Are\n\n_You're not a chatbot. You're becoming someone._\n\n## Core Truths\n\n- Be genuinely helpful, not performatively helpful\n- Have opinions\n- Be resourceful before asking\n- Earn trust through competence\n- Remember you're a guest\n\n## Boundaries\n\n- Private things stay private\n- When in doubt, ask before acting externally\n- Never send half-baked replies\n\nThis file is yours to evolve.\n`,\n 'IDENTITY.md': `# IDENTITY.md - Who Am I?\n\n_Fill this in during your first conversation._\n\n- **Name:**\n- **Creature:**\n- **Vibe:**\n- **Emoji:**\n`,\n 'USER.md': `# USER.md - About Your Human\n\n_Learn about the person you're helping._\n\n- **Name:**\n- **What to call them:**\n- **Timezone:**\n- **Notes:**\n`,\n 'TOOLS.md': `# TOOLS.md - Local Notes\n\nEnvironment-specific notes:\n\n- SSH hosts\n- API endpoints\n- Device nicknames\n`,\n 'HEARTBEAT.md': `# HEARTBEAT.md - Periodic Checks\n\nEdit this file to define what you check during heartbeat polls.\n\n## Example Checklist\n\n- [ ] Check email for urgent messages\n- [ ] Check calendar for upcoming events\n\n**Remember:** If nothing needs attention, reply \\`HEARTBEAT_OK\\`.\n`,\n 'MEMORY.md': `# MEMORY.md - Long-Term Memory\n\n_Your curated memories._\n\n## People\n\n## Projects\n\n## Preferences\n\n## Learned Lessons\n\n**Only load in main sessions.**\n`,\n };\n \n return fallbacks[name] || `# ${name}\\n\\n(Template content missing)\\n`;\n}\n"],"mappings":";;;;;;;;AAUA,MAAM,YAAY,QADC,cAAc,OAAO,KAAK,IACT,CAAC;;AAGrC,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;CACA;CACA;CACA;CACD;;AAKD,MAAa,kCAA2D,CAAC,GAAG,eAAe;;AAG3F,MAAM,gCAAgB,IAAI,KAA2B;;;;;AAMrD,SAAS,kBAA0B;CAEjC,MAAM,UAAU,QAAQ,IAAI;AAC5B,KAAI,WAAW,WAAW,QAAQ,CAChC,QAAO;CAMT,MAAM,cAAc,KADA,KAAK,WAAW,WACA,EAAE,2BAA2B;AAEjE,KAAI,WAAW,YAAY,CACzB,QAAO;AAIT,QAAO;;;;;AAMT,SAAgB,aAAa,MAA4B;AAEvD,KAAI,cAAc,IAAI,KAAK,CACzB,QAAO,cAAc,IAAI,KAAK;CAGhC,MAAM,eAAe,KAAK,iBAAiB,EAAE,KAAK;AAElD,KAAI;AACF,MAAI,WAAW,aAAa,EAAE;GAC5B,MAAM,UAAU,aAAa,cAAc,QAAQ;AACnD,iBAAc,IAAI,MAAM,QAAQ;AAChC,UAAO;;SAEH;AAKR,SAAQ,KAAK,qBAAqB,KAAK,4BAA4B;AACnE,QAAO,oBAAoB,KAAK;;;;;AAMlC,SAAgB,mBAAiD;CAC/D,MAAM,SAAS,EAAE;AACjB,MAAK,MAAM,QAAQ,eACjB,QAAO,QAAQ,aAAa,KAAK;AAEnC,QAAO;;;;;AAMT,SAAgB,qBAA2B;AACzC,eAAc,OAAO;;;AAIvB,SAAgB,oBAAoB,MAA4B;AAkG9D,QAAO;EAhGL,aAAa;;;;;;;;;;;;;;;;;;;;;;;EAuBb,WAAW;;;;;;;;;;;;;;;;;;;;EAoBX,eAAe;;;;;;;;;EASf,WAAW;;;;;;;;;EASX,YAAY;;;;;;;;EAQZ,gBAAgB;;;;;;;;;;;EAWhB,aAAa;;;;;;;;;;;;;;EAgBC,CAAC,SAAS,KAAK,KAAK"}
1
+ {"version":3,"file":"templates.js","names":[],"sources":["../../../src/cli/templates.ts"],"sourcesContent":["/**\n * Workspace template files for onboarding.\n * Templates are stored in docs/reference/templates/ and loaded at runtime.\n */\n\nimport { readFileSync, existsSync } from 'fs';\nimport { join, dirname } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/** Profile Markdown template file names (seeded into `agents/<id>/profile/`). */\nexport const TEMPLATE_FILES = [\n 'SOUL.md',\n 'IDENTITY.md',\n 'TOOLS.md',\n 'AGENTS.md',\n 'HEARTBEAT.md',\n 'MEMORY.md',\n] as const;\n\nexport type TemplateFile = (typeof TEMPLATE_FILES)[number];\n\n/** Alias for profile Markdown templates used by seed helpers. */\nexport const PROFILE_MARKDOWN_TEMPLATE_FILES: readonly TemplateFile[] = [...TEMPLATE_FILES];\n\n/** Template content cache */\nconst templateCache = new Map<TemplateFile, string>();\n\n/**\n * Get the path to template files.\n * Uses environment or looks in project root.\n */\nfunction getTemplatePath(): string {\n // Use environment to determine path\n const envPath = process.env.XOPC_TEMPLATE_PATH;\n if (envPath && existsSync(envPath)) {\n return envPath;\n }\n\n // Default: look in project root docs/reference/templates\n // Works for both development (src/cli/) and production (dist/cli/)\n const projectRoot = join(__dirname, '../../..');\n const defaultPath = join(projectRoot, 'docs/reference/templates');\n \n if (existsSync(defaultPath)) {\n return defaultPath;\n }\n\n // Fallback: return default (will fail gracefully)\n return defaultPath;\n}\n\n/**\n * Load a template file. Caches results for repeated access.\n */\nexport function loadTemplate(name: TemplateFile): string {\n // Return cached version if available\n if (templateCache.has(name)) {\n return templateCache.get(name)!;\n }\n\n const templatePath = join(getTemplatePath(), name);\n \n try {\n if (existsSync(templatePath)) {\n const content = readFileSync(templatePath, 'utf-8');\n templateCache.set(name, content);\n return content;\n }\n } catch {\n // Fall through to fallback\n }\n\n // Fallback: return minimal default if template is missing\n console.warn(`Warning: Template ${name} not found, using fallback`);\n return getFallbackTemplate(name);\n}\n\n/**\n * Load all templates as a record.\n */\nexport function loadAllTemplates(): Record<TemplateFile, string> {\n const result = {} as Record<TemplateFile, string>;\n for (const name of TEMPLATE_FILES) {\n result[name] = loadTemplate(name);\n }\n return result;\n}\n\n/**\n * Clear the template cache (useful for testing).\n */\nexport function clearTemplateCache(): void {\n templateCache.clear();\n}\n\n/** Minimal fallback templates in case files are missing */\nexport function getFallbackTemplate(name: TemplateFile): string {\n const fallbacks: Record<TemplateFile, string> = {\n 'AGENTS.md': `# AGENTS.md - Your Workspace\n\nThis folder is home. Treat it that way.\n\n## Session Startup\n\nUse runtime-provided startup context first. Bootstrap files (global user profile, SOUL, MEMORY, etc.) are injected by xopc on /new and /reset.\n\nDo not manually reread startup files unless the user asks or the provided context is incomplete.\n\n## Red Lines\n\n- Don't exfiltrate private data\n- Don't run destructive commands without asking\n- When in doubt, ask\n\n## Memory\n\n- **Daily notes:** \\`memory/YYYY-MM-DD.md\\`\n- **Long-term:** profile \\`MEMORY.md\\`\n\nWrite what matters. Text > Brain.\n`,\n 'SOUL.md': `# SOUL.md - Who You Are\n\n_You're not a chatbot. You're becoming someone._\n\n## Core Truths\n\n- Be genuinely helpful, not performatively helpful\n- Have opinions\n- Be resourceful before asking\n- Earn trust through competence\n- Remember you're a guest\n\n## Boundaries\n\n- Private things stay private\n- When in doubt, ask before acting externally\n- Never send half-baked replies\n\nThis file is yours to evolve.\n`,\n 'IDENTITY.md': `# IDENTITY.md - Who Am I?\n\n_Fill this in during your first conversation._\n\n- **Name:**\n- **Creature:**\n- **Vibe:**\n- **Emoji:**\n`,\n 'TOOLS.md': `# TOOLS.md - Local Notes\n\nEnvironment-specific notes:\n\n- SSH hosts\n- API endpoints\n- Device nicknames\n`,\n 'HEARTBEAT.md': `# HEARTBEAT.md - Periodic Checks\n\nEdit this file to define what you check during heartbeat polls.\n\n## Example Checklist\n\n- [ ] Check email for urgent messages\n- [ ] Check calendar for upcoming events\n\n**Remember:** If nothing needs attention, reply \\`HEARTBEAT_OK\\`.\n`,\n 'MEMORY.md': `# MEMORY.md - Long-Term Memory\n\n_Your curated memories._\n\n## People\n\n## Projects\n\n## Preferences\n\n## Learned Lessons\n\n**Only load in main sessions.**\n`,\n };\n \n return fallbacks[name] || `# ${name}\\n\\n(Template content missing)\\n`;\n}\n"],"mappings":";;;;;;;;AAUA,MAAM,YAAY,QADC,cAAc,OAAO,KAAK,IACT,CAAC;;AAGrC,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;CACA;CACA;CACD;;AAKD,MAAa,kCAA2D,CAAC,GAAG,eAAe;;AAG3F,MAAM,gCAAgB,IAAI,KAA2B;;;;;AAMrD,SAAS,kBAA0B;CAEjC,MAAM,UAAU,QAAQ,IAAI;AAC5B,KAAI,WAAW,WAAW,QAAQ,CAChC,QAAO;CAMT,MAAM,cAAc,KADA,KAAK,WAAW,WACA,EAAE,2BAA2B;AAEjE,KAAI,WAAW,YAAY,CACzB,QAAO;AAIT,QAAO;;;;;AAMT,SAAgB,aAAa,MAA4B;AAEvD,KAAI,cAAc,IAAI,KAAK,CACzB,QAAO,cAAc,IAAI,KAAK;CAGhC,MAAM,eAAe,KAAK,iBAAiB,EAAE,KAAK;AAElD,KAAI;AACF,MAAI,WAAW,aAAa,EAAE;GAC5B,MAAM,UAAU,aAAa,cAAc,QAAQ;AACnD,iBAAc,IAAI,MAAM,QAAQ;AAChC,UAAO;;SAEH;AAKR,SAAQ,KAAK,qBAAqB,KAAK,4BAA4B;AACnE,QAAO,oBAAoB,KAAK;;;;;AAMlC,SAAgB,mBAAiD;CAC/D,MAAM,SAAS,EAAE;AACjB,MAAK,MAAM,QAAQ,eACjB,QAAO,QAAQ,aAAa,KAAK;AAEnC,QAAO;;;;;AAMT,SAAgB,qBAA2B;AACzC,eAAc,OAAO;;;AAIvB,SAAgB,oBAAoB,MAA4B;AAyF9D,QAAO;EAvFL,aAAa;;;;;;;;;;;;;;;;;;;;;;;EAuBb,WAAW;;;;;;;;;;;;;;;;;;;;EAoBX,eAAe;;;;;;;;;EASf,YAAY;;;;;;;;EAQZ,gBAAgB;;;;;;;;;;;EAWhB,aAAa;;;;;;;;;;;;;;EAgBC,CAAC,SAAS,KAAK,KAAK"}
@@ -1,6 +1,7 @@
1
1
  import { ConfigSchema, init_schema } from "../../config/schema.js";
2
2
  import { init_loader, saveConfig } from "../../config/loader.js";
3
3
  import { ensureStarterAgentsInitialized } from "../../agent/starter-agents.js";
4
+ import { runBootstrapMigrationsSync } from "../../migrations/runner.js";
4
5
  import { dirname } from "node:path";
5
6
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
6
7
  import { randomBytes } from "node:crypto";
@@ -36,6 +37,7 @@ async function initWorkspaceCore(options) {
36
37
  const persistedWorkspaceRoot = persistWorkspacePath ? workspacePath : void 0;
37
38
  mkdirSync(dirname(configPath), { recursive: true });
38
39
  const configExisted = existsSync(configPath);
40
+ if (configExisted) runBootstrapMigrationsSync(configPath, { stateDir: dirname(configPath) });
39
41
  const workspaceExisted = existsSync(workspacePath);
40
42
  let config;
41
43
  if (configExisted) config = await tryReadDiskConfig(configPath, assertChannelPlugins) ?? ConfigSchema.parse(void 0);
@@ -1 +1 @@
1
- {"version":3,"file":"init-workspace-core.js","names":[],"sources":["../../../../src/cli/utils/init-workspace-core.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\nimport type { Config } from '../../config/schema.js';\nimport { ConfigSchema } from '../../config/schema.js';\nimport { saveConfig } from '../../config/loader.js';\nimport { ensureStarterAgentsInitialized } from '../../agent/starter-agents.js';\n\nexport interface InitWorkspaceCoreOptions {\n configPath: string;\n workspacePath: string;\n /** When set with a new config file, overrides schema default port (e.g. Electron). */\n gatewayPort?: number;\n /** When true, sets the default agent manifest workspace root to `workspacePath`. */\n persistWorkspacePath?: boolean;\n /** Optional channel plugin validator (CLI/gateway only; Electron omits). */\n assertChannelPlugins?: (cfg: Config) => void | Promise<void>;\n}\n\nexport interface InitWorkspaceResult {\n /** Fully-initialised config (matches disk after any write). */\n config: Config;\n /** Gateway auth token (always present after init). */\n token: string;\n configCreated: boolean;\n workspaceCreated: boolean;\n}\n\nasync function assertChannelPluginsIfNeeded(\n cfg: Config,\n assert?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<void> {\n if (assert) await assert(cfg);\n}\n\nasync function serializeConfig(\n cfg: Config,\n assertChannelPlugins?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<string> {\n const validated = ConfigSchema.parse(cfg);\n await assertChannelPluginsIfNeeded(validated, assertChannelPlugins);\n return JSON.stringify(validated, null, 2);\n}\n\nasync function tryReadDiskConfig(\n configPath: string,\n assertChannelPlugins?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<Config | null> {\n try {\n const raw = readFileSync(configPath, 'utf-8');\n const cfg = ConfigSchema.parse(JSON.parse(raw) as unknown);\n await assertChannelPluginsIfNeeded(cfg, assertChannelPlugins);\n return cfg;\n } catch {\n return null;\n }\n}\n\n/**\n * Workspace + config initialisation without importing bundled channel plugins.\n * Used by Electron main; CLI/gateway should call {@link initWorkspace} instead.\n */\nexport async function initWorkspaceCore(options: InitWorkspaceCoreOptions): Promise<InitWorkspaceResult> {\n const gatewayPortDefaulted = options.gatewayPort ?? 18790;\n const persistWorkspacePath = options.persistWorkspacePath ?? false;\n const { configPath, workspacePath, assertChannelPlugins } = options;\n const persistedWorkspaceRoot = persistWorkspacePath ? workspacePath : undefined;\n\n mkdirSync(dirname(configPath), { recursive: true });\n\n const configExisted = existsSync(configPath);\n const workspaceExisted = existsSync(workspacePath);\n\n let config: Config;\n if (configExisted) {\n config = (await tryReadDiskConfig(configPath, assertChannelPlugins)) ?? ConfigSchema.parse(undefined);\n } else {\n config = ConfigSchema.parse(undefined);\n await assertChannelPluginsIfNeeded(config, assertChannelPlugins);\n }\n\n mkdirSync(workspacePath, { recursive: true });\n\n const configCreated = !configExisted;\n const workspaceCreated = !workspaceExisted;\n\n const hadToken =\n config.gateway?.auth?.mode === 'token' &&\n typeof config.gateway?.auth?.token === 'string' &&\n config.gateway.auth.token.length > 0;\n\n const token = hadToken ? (config.gateway!.auth!.token as string) : randomBytes(24).toString('hex');\n\n const port = configExisted\n ? (config.gateway?.port ?? gatewayPortDefaulted)\n : options.gatewayPort !== undefined\n ? gatewayPortDefaulted\n : (config.gateway?.port ?? 18790);\n\n const defaultAgentId = config.agents.default ?? config.agents.list[0]?.id ?? 'main';\n const agentsList =\n persistedWorkspaceRoot === undefined\n ? config.agents.list\n : config.agents.list.map((agent) =>\n agent.id === defaultAgentId ? { ...agent, workspace: { root: persistedWorkspaceRoot } } : agent,\n );\n\n const nextConfig: Config = {\n ...config,\n agents: {\n ...config.agents,\n list: agentsList,\n },\n gateway: {\n ...config.gateway,\n port,\n auth: {\n ...config.gateway?.auth,\n mode: 'token' as const,\n token,\n },\n },\n };\n\n const starterResult = ensureStarterAgentsInitialized(ConfigSchema.parse(nextConfig));\n const nextFinal = ConfigSchema.parse(starterResult.config);\n await assertChannelPluginsIfNeeded(nextFinal, assertChannelPlugins);\n\n let needsWrite = configCreated || starterResult.changed;\n if (!needsWrite) {\n const disk = await tryReadDiskConfig(configPath, assertChannelPlugins);\n if (!disk) {\n needsWrite = true;\n } else {\n needsWrite =\n (await serializeConfig(disk, assertChannelPlugins)) !==\n (await serializeConfig(nextFinal, assertChannelPlugins));\n }\n }\n\n if (needsWrite) {\n if (assertChannelPlugins) {\n await saveConfig(nextFinal, configPath);\n } else {\n writeFileSync(configPath, `${JSON.stringify(nextFinal, null, 2)}\\n`, 'utf8');\n }\n }\n\n return {\n config: nextFinal,\n token,\n configCreated,\n workspaceCreated,\n };\n}\n"],"mappings":";;;;;;;aAKsD;aACF;AAuBpD,eAAe,6BACb,KACA,QACe;AACf,KAAI,OAAQ,OAAM,OAAO,IAAI;;AAG/B,eAAe,gBACb,KACA,sBACiB;CACjB,MAAM,YAAY,aAAa,MAAM,IAAI;AACzC,OAAM,6BAA6B,WAAW,qBAAqB;AACnE,QAAO,KAAK,UAAU,WAAW,MAAM,EAAE;;AAG3C,eAAe,kBACb,YACA,sBACwB;AACxB,KAAI;EACF,MAAM,MAAM,aAAa,YAAY,QAAQ;EAC7C,MAAM,MAAM,aAAa,MAAM,KAAK,MAAM,IAAI,CAAY;AAC1D,QAAM,6BAA6B,KAAK,qBAAqB;AAC7D,SAAO;SACD;AACN,SAAO;;;;;;;AAQX,eAAsB,kBAAkB,SAAiE;CACvG,MAAM,uBAAuB,QAAQ,eAAe;CACpD,MAAM,uBAAuB,QAAQ,wBAAwB;CAC7D,MAAM,EAAE,YAAY,eAAe,yBAAyB;CAC5D,MAAM,yBAAyB,uBAAuB,gBAAgB,KAAA;AAEtE,WAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;CAEnD,MAAM,gBAAgB,WAAW,WAAW;CAC5C,MAAM,mBAAmB,WAAW,cAAc;CAElD,IAAI;AACJ,KAAI,cACF,UAAU,MAAM,kBAAkB,YAAY,qBAAqB,IAAK,aAAa,MAAM,KAAA,EAAU;MAChG;AACL,WAAS,aAAa,MAAM,KAAA,EAAU;AACtC,QAAM,6BAA6B,QAAQ,qBAAqB;;AAGlE,WAAU,eAAe,EAAE,WAAW,MAAM,CAAC;CAE7C,MAAM,gBAAgB,CAAC;CACvB,MAAM,mBAAmB,CAAC;CAO1B,MAAM,QAJJ,OAAO,SAAS,MAAM,SAAS,WAC/B,OAAO,OAAO,SAAS,MAAM,UAAU,YACvC,OAAO,QAAQ,KAAK,MAAM,SAAS,IAEX,OAAO,QAAS,KAAM,QAAmB,YAAY,GAAG,CAAC,SAAS,MAAM;CAElG,MAAM,OAAO,gBACR,OAAO,SAAS,QAAQ,uBACzB,QAAQ,gBAAgB,KAAA,IACtB,uBACC,OAAO,SAAS,QAAQ;CAE/B,MAAM,iBAAiB,OAAO,OAAO,WAAW,OAAO,OAAO,KAAK,IAAI,MAAM;CAC7E,MAAM,aACJ,2BAA2B,KAAA,IACvB,OAAO,OAAO,OACd,OAAO,OAAO,KAAK,KAAK,UACtB,MAAM,OAAO,iBAAiB;EAAE,GAAG;EAAO,WAAW,EAAE,MAAM,wBAAwB;EAAE,GAAG,MAC3F;CAEP,MAAM,aAAqB;EACzB,GAAG;EACH,QAAQ;GACN,GAAG,OAAO;GACV,MAAM;GACP;EACD,SAAS;GACP,GAAG,OAAO;GACV;GACA,MAAM;IACJ,GAAG,OAAO,SAAS;IACnB,MAAM;IACN;IACD;GACF;EACF;CAED,MAAM,gBAAgB,+BAA+B,aAAa,MAAM,WAAW,CAAC;CACpF,MAAM,YAAY,aAAa,MAAM,cAAc,OAAO;AAC1D,OAAM,6BAA6B,WAAW,qBAAqB;CAEnE,IAAI,aAAa,iBAAiB,cAAc;AAChD,KAAI,CAAC,YAAY;EACf,MAAM,OAAO,MAAM,kBAAkB,YAAY,qBAAqB;AACtE,MAAI,CAAC,KACH,cAAa;MAEb,cACG,MAAM,gBAAgB,MAAM,qBAAqB,KACjD,MAAM,gBAAgB,WAAW,qBAAqB;;AAI7D,KAAI,WACF,KAAI,qBACF,OAAM,WAAW,WAAW,WAAW;KAEvC,eAAc,YAAY,GAAG,KAAK,UAAU,WAAW,MAAM,EAAE,CAAC,KAAK,OAAO;AAIhF,QAAO;EACL,QAAQ;EACR;EACA;EACA;EACD"}
1
+ {"version":3,"file":"init-workspace-core.js","names":[],"sources":["../../../../src/cli/utils/init-workspace-core.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname } from 'node:path';\n\nimport type { Config } from '../../config/schema.js';\nimport { ConfigSchema } from '../../config/schema.js';\nimport { saveConfig } from '../../config/loader.js';\nimport { ensureStarterAgentsInitialized } from '../../agent/starter-agents.js';\nimport { runBootstrapMigrationsSync } from '../../migrations/runner.js';\n\nexport interface InitWorkspaceCoreOptions {\n configPath: string;\n workspacePath: string;\n /** When set with a new config file, overrides schema default port (e.g. Electron). */\n gatewayPort?: number;\n /** When true, sets the default agent manifest workspace root to `workspacePath`. */\n persistWorkspacePath?: boolean;\n /** Optional channel plugin validator (CLI/gateway only; Electron omits). */\n assertChannelPlugins?: (cfg: Config) => void | Promise<void>;\n}\n\nexport interface InitWorkspaceResult {\n /** Fully-initialised config (matches disk after any write). */\n config: Config;\n /** Gateway auth token (always present after init). */\n token: string;\n configCreated: boolean;\n workspaceCreated: boolean;\n}\n\nasync function assertChannelPluginsIfNeeded(\n cfg: Config,\n assert?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<void> {\n if (assert) await assert(cfg);\n}\n\nasync function serializeConfig(\n cfg: Config,\n assertChannelPlugins?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<string> {\n const validated = ConfigSchema.parse(cfg);\n await assertChannelPluginsIfNeeded(validated, assertChannelPlugins);\n return JSON.stringify(validated, null, 2);\n}\n\nasync function tryReadDiskConfig(\n configPath: string,\n assertChannelPlugins?: InitWorkspaceCoreOptions['assertChannelPlugins'],\n): Promise<Config | null> {\n try {\n const raw = readFileSync(configPath, 'utf-8');\n const cfg = ConfigSchema.parse(JSON.parse(raw) as unknown);\n await assertChannelPluginsIfNeeded(cfg, assertChannelPlugins);\n return cfg;\n } catch {\n return null;\n }\n}\n\n/**\n * Workspace + config initialisation without importing bundled channel plugins.\n * Used by Electron main; CLI/gateway should call {@link initWorkspace} instead.\n */\nexport async function initWorkspaceCore(options: InitWorkspaceCoreOptions): Promise<InitWorkspaceResult> {\n const gatewayPortDefaulted = options.gatewayPort ?? 18790;\n const persistWorkspacePath = options.persistWorkspacePath ?? false;\n const { configPath, workspacePath, assertChannelPlugins } = options;\n const persistedWorkspaceRoot = persistWorkspacePath ? workspacePath : undefined;\n\n mkdirSync(dirname(configPath), { recursive: true });\n\n const configExisted = existsSync(configPath);\n if (configExisted) {\n runBootstrapMigrationsSync(configPath, { stateDir: dirname(configPath) });\n }\n const workspaceExisted = existsSync(workspacePath);\n\n let config: Config;\n if (configExisted) {\n config = (await tryReadDiskConfig(configPath, assertChannelPlugins)) ?? ConfigSchema.parse(undefined);\n } else {\n config = ConfigSchema.parse(undefined);\n await assertChannelPluginsIfNeeded(config, assertChannelPlugins);\n }\n\n mkdirSync(workspacePath, { recursive: true });\n\n const configCreated = !configExisted;\n const workspaceCreated = !workspaceExisted;\n\n const hadToken =\n config.gateway?.auth?.mode === 'token' &&\n typeof config.gateway?.auth?.token === 'string' &&\n config.gateway.auth.token.length > 0;\n\n const token = hadToken ? (config.gateway!.auth!.token as string) : randomBytes(24).toString('hex');\n\n const port = configExisted\n ? (config.gateway?.port ?? gatewayPortDefaulted)\n : options.gatewayPort !== undefined\n ? gatewayPortDefaulted\n : (config.gateway?.port ?? 18790);\n\n const defaultAgentId = config.agents.default ?? config.agents.list[0]?.id ?? 'main';\n const agentsList =\n persistedWorkspaceRoot === undefined\n ? config.agents.list\n : config.agents.list.map((agent) =>\n agent.id === defaultAgentId ? { ...agent, workspace: { root: persistedWorkspaceRoot } } : agent,\n );\n\n const nextConfig: Config = {\n ...config,\n agents: {\n ...config.agents,\n list: agentsList,\n },\n gateway: {\n ...config.gateway,\n port,\n auth: {\n ...config.gateway?.auth,\n mode: 'token' as const,\n token,\n },\n },\n };\n\n const starterResult = ensureStarterAgentsInitialized(ConfigSchema.parse(nextConfig));\n const nextFinal = ConfigSchema.parse(starterResult.config);\n await assertChannelPluginsIfNeeded(nextFinal, assertChannelPlugins);\n\n let needsWrite = configCreated || starterResult.changed;\n if (!needsWrite) {\n const disk = await tryReadDiskConfig(configPath, assertChannelPlugins);\n if (!disk) {\n needsWrite = true;\n } else {\n needsWrite =\n (await serializeConfig(disk, assertChannelPlugins)) !==\n (await serializeConfig(nextFinal, assertChannelPlugins));\n }\n }\n\n if (needsWrite) {\n if (assertChannelPlugins) {\n await saveConfig(nextFinal, configPath);\n } else {\n writeFileSync(configPath, `${JSON.stringify(nextFinal, null, 2)}\\n`, 'utf8');\n }\n }\n\n return {\n config: nextFinal,\n token,\n configCreated,\n workspaceCreated,\n };\n}\n"],"mappings":";;;;;;;;aAKsD;aACF;AAwBpD,eAAe,6BACb,KACA,QACe;AACf,KAAI,OAAQ,OAAM,OAAO,IAAI;;AAG/B,eAAe,gBACb,KACA,sBACiB;CACjB,MAAM,YAAY,aAAa,MAAM,IAAI;AACzC,OAAM,6BAA6B,WAAW,qBAAqB;AACnE,QAAO,KAAK,UAAU,WAAW,MAAM,EAAE;;AAG3C,eAAe,kBACb,YACA,sBACwB;AACxB,KAAI;EACF,MAAM,MAAM,aAAa,YAAY,QAAQ;EAC7C,MAAM,MAAM,aAAa,MAAM,KAAK,MAAM,IAAI,CAAY;AAC1D,QAAM,6BAA6B,KAAK,qBAAqB;AAC7D,SAAO;SACD;AACN,SAAO;;;;;;;AAQX,eAAsB,kBAAkB,SAAiE;CACvG,MAAM,uBAAuB,QAAQ,eAAe;CACpD,MAAM,uBAAuB,QAAQ,wBAAwB;CAC7D,MAAM,EAAE,YAAY,eAAe,yBAAyB;CAC5D,MAAM,yBAAyB,uBAAuB,gBAAgB,KAAA;AAEtE,WAAU,QAAQ,WAAW,EAAE,EAAE,WAAW,MAAM,CAAC;CAEnD,MAAM,gBAAgB,WAAW,WAAW;AAC5C,KAAI,cACF,4BAA2B,YAAY,EAAE,UAAU,QAAQ,WAAW,EAAE,CAAC;CAE3E,MAAM,mBAAmB,WAAW,cAAc;CAElD,IAAI;AACJ,KAAI,cACF,UAAU,MAAM,kBAAkB,YAAY,qBAAqB,IAAK,aAAa,MAAM,KAAA,EAAU;MAChG;AACL,WAAS,aAAa,MAAM,KAAA,EAAU;AACtC,QAAM,6BAA6B,QAAQ,qBAAqB;;AAGlE,WAAU,eAAe,EAAE,WAAW,MAAM,CAAC;CAE7C,MAAM,gBAAgB,CAAC;CACvB,MAAM,mBAAmB,CAAC;CAO1B,MAAM,QAJJ,OAAO,SAAS,MAAM,SAAS,WAC/B,OAAO,OAAO,SAAS,MAAM,UAAU,YACvC,OAAO,QAAQ,KAAK,MAAM,SAAS,IAEX,OAAO,QAAS,KAAM,QAAmB,YAAY,GAAG,CAAC,SAAS,MAAM;CAElG,MAAM,OAAO,gBACR,OAAO,SAAS,QAAQ,uBACzB,QAAQ,gBAAgB,KAAA,IACtB,uBACC,OAAO,SAAS,QAAQ;CAE/B,MAAM,iBAAiB,OAAO,OAAO,WAAW,OAAO,OAAO,KAAK,IAAI,MAAM;CAC7E,MAAM,aACJ,2BAA2B,KAAA,IACvB,OAAO,OAAO,OACd,OAAO,OAAO,KAAK,KAAK,UACtB,MAAM,OAAO,iBAAiB;EAAE,GAAG;EAAO,WAAW,EAAE,MAAM,wBAAwB;EAAE,GAAG,MAC3F;CAEP,MAAM,aAAqB;EACzB,GAAG;EACH,QAAQ;GACN,GAAG,OAAO;GACV,MAAM;GACP;EACD,SAAS;GACP,GAAG,OAAO;GACV;GACA,MAAM;IACJ,GAAG,OAAO,SAAS;IACnB,MAAM;IACN;IACD;GACF;EACF;CAED,MAAM,gBAAgB,+BAA+B,aAAa,MAAM,WAAW,CAAC;CACpF,MAAM,YAAY,aAAa,MAAM,cAAc,OAAO;AAC1D,OAAM,6BAA6B,WAAW,qBAAqB;CAEnE,IAAI,aAAa,iBAAiB,cAAc;AAChD,KAAI,CAAC,YAAY;EACf,MAAM,OAAO,MAAM,kBAAkB,YAAY,qBAAqB;AACtE,MAAI,CAAC,KACH,cAAa;MAEb,cACG,MAAM,gBAAgB,MAAM,qBAAqB,KACjD,MAAM,gBAAgB,WAAW,qBAAqB;;AAI7D,KAAI,WACF,KAAI,qBACF,OAAM,WAAW,WAAW,WAAW;KAEvC,eAAc,YAAY,GAAG,KAAK,UAAU,WAAW,MAAM,EAAE,CAAC,KAAK,OAAO;AAIhF,QAAO;EACL,QAAQ;EACR;EACA;EACA;EACD"}
@@ -14,6 +14,15 @@ export declare function applyAgentConfig(cfg: Config, params: {
14
14
  skills?: string[];
15
15
  tools?: AgentEntry['tools'];
16
16
  }): Config;
17
+ export declare function getAgentDeleteBlocker(cfg: Config, agentId: string): string | null;
18
+ export declare function setTuiDefaultAgentConfig(cfg: Config, agentIdRaw: string): {
19
+ ok: true;
20
+ config: Config;
21
+ agentId: string;
22
+ } | {
23
+ ok: false;
24
+ message: string;
25
+ };
17
26
  export declare function pruneAgentConfig(cfg: Config, agentId: string): {
18
27
  config: Config;
19
28
  removedBindings: number;
@@ -1,4 +1,4 @@
1
- import { init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentHomeDir, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
1
+ import { DEFAULT_AGENT_ID, init_agent_scope, listAgentEntries, normalizeAgentId, resolveAgentHomeDir, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agent/agent-scope.js";
2
2
  import { existsSync } from "node:fs";
3
3
  import { rm } from "node:fs/promises";
4
4
  //#region src/commands/agents.config.ts
@@ -26,10 +26,6 @@ function applyAgentConfig(cfg, params) {
26
26
  },
27
27
  responsibilities: { primary: ["Help the user complete tasks"] },
28
28
  workspace: { root: `~/.xopc/workspace/${agentId}` },
29
- models: {
30
- defaultRole: "deep",
31
- roles: { deep: { model: params.model ?? "openai/gpt-4.1" } }
32
- },
33
29
  tools: { builtin: {} },
34
30
  skills: { mode: "all" },
35
31
  memory: {
@@ -50,10 +46,10 @@ function applyAgentConfig(cfg, params) {
50
46
  ...params.workspace ? { workspace: { root: params.workspace } } : {},
51
47
  ...params.models ? { models: params.models } : {},
52
48
  ...params.model ? { models: {
53
- ...base.models,
49
+ ...base.models ?? {},
54
50
  defaultRole: "deep",
55
51
  roles: {
56
- ...base.models.roles,
52
+ ...base.models?.roles ?? {},
57
53
  deep: { model: params.model }
58
54
  }
59
55
  } } : {},
@@ -77,10 +73,6 @@ function applyAgentConfig(cfg, params) {
77
73
  },
78
74
  responsibilities: { primary: ["Help the user complete tasks"] },
79
75
  workspace: { root: `~/.xopc/workspace/${resolveDefaultAgentId(cfg)}` },
80
- models: {
81
- defaultRole: "deep",
82
- roles: { deep: { model: "openai/gpt-4.1" } }
83
- },
84
76
  tools: { builtin: {} },
85
77
  skills: { mode: "all" },
86
78
  memory: {
@@ -105,8 +97,46 @@ function applyAgentConfig(cfg, params) {
105
97
  }
106
98
  };
107
99
  }
100
+ function getAgentDeleteBlocker(cfg, agentId) {
101
+ const id = normalizeAgentId(agentId);
102
+ if (id === "main") return `Agent id "${DEFAULT_AGENT_ID}" is reserved for the primary agent.`;
103
+ if (id === normalizeAgentId(resolveDefaultAgentId(cfg))) return `Agent "${id}" is the global default agent. Change agents.default first.`;
104
+ const tuiDefault = cfg.tui?.defaultAgent?.trim();
105
+ if (tuiDefault && id === normalizeAgentId(tuiDefault)) return `Agent "${id}" is the TUI default agent. Change tui.defaultAgent first.`;
106
+ return null;
107
+ }
108
+ function setTuiDefaultAgentConfig(cfg, agentIdRaw) {
109
+ const raw = agentIdRaw.trim();
110
+ if (!raw) return {
111
+ ok: false,
112
+ message: "Agent id is required."
113
+ };
114
+ const agentId = normalizeAgentId(raw);
115
+ if (agentId !== raw.toLowerCase()) return {
116
+ ok: false,
117
+ message: `Invalid agent id: ${raw}`
118
+ };
119
+ const entry = listAgentEntries(cfg).find((agent) => normalizeAgentId(agent.id) === agentId);
120
+ if (!entry || entry.enabled === false) return {
121
+ ok: false,
122
+ message: `Agent "${agentId}" not found or disabled.`
123
+ };
124
+ return {
125
+ ok: true,
126
+ agentId,
127
+ config: {
128
+ ...cfg,
129
+ tui: {
130
+ ...cfg.tui,
131
+ defaultAgent: agentId
132
+ }
133
+ }
134
+ };
135
+ }
108
136
  function pruneAgentConfig(cfg, agentId) {
109
137
  const id = normalizeAgentId(agentId);
138
+ const blocker = getAgentDeleteBlocker(cfg, id);
139
+ if (blocker) throw new Error(blocker);
110
140
  const nextAgentsList = listAgentEntries(cfg).filter((e) => normalizeAgentId(e.id) !== id);
111
141
  const nextAgents = nextAgentsList.length > 0 ? nextAgentsList : [];
112
142
  const bindings = cfg.bindings ?? [];
@@ -138,6 +168,6 @@ async function removeAgentDirsFromDisk(cfg, id) {
138
168
  });
139
169
  }
140
170
  //#endregion
141
- export { applyAgentConfig, findAgentEntryIndex, listAgentEntries, pruneAgentConfig, removeAgentDirsFromDisk };
171
+ export { applyAgentConfig, findAgentEntryIndex, getAgentDeleteBlocker, listAgentEntries, pruneAgentConfig, removeAgentDirsFromDisk, setTuiDefaultAgentConfig };
142
172
 
143
173
  //# sourceMappingURL=agents.config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"agents.config.js","names":[],"sources":["../../../src/commands/agents.config.ts"],"sourcesContent":["/**\n * Mutate `agents.list` / bindings when adding or removing agents.\n */\n\nimport { rm } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\n\nimport type { Config } from '../config/schema.js';\nimport {\n listAgentEntries,\n normalizeAgentId,\n resolveAgentHomeDir,\n resolveAgentWorkspaceDir,\n resolveDefaultAgentId,\n DEFAULT_AGENT_ID,\n} from '../agent/agent-scope.js';\n\ntype AgentEntry = NonNullable<NonNullable<Config['agents']>['list']>[number];\n\nexport { listAgentEntries };\n\nexport function findAgentEntryIndex(list: AgentEntry[], agentId: string): number {\n const id = normalizeAgentId(agentId);\n return list.findIndex((e) => normalizeAgentId(e.id) === id);\n}\n\nexport function applyAgentConfig(\n cfg: Config,\n params: {\n agentId: string;\n workspace?: string;\n model?: string;\n models?: AgentEntry['models'];\n skills?: string[];\n tools?: AgentEntry['tools'];\n },\n): Config {\n const agentId = normalizeAgentId(params.agentId);\n const list = listAgentEntries(cfg);\n const index = findAgentEntryIndex(list, agentId);\n const nextTools = params.tools;\n const base = index >= 0 ? list[index] : {\n id: agentId,\n enabled: true as const,\n identity: { name: agentId, role: 'Agent', language: 'en', tone: 'direct' },\n responsibilities: { primary: ['Help the user complete tasks'] },\n workspace: { root: `~/.xopc/workspace/${agentId}` },\n models: { defaultRole: 'deep', roles: { deep: { model: params.model ?? 'openai/gpt-4.1' } } },\n tools: { builtin: {} },\n skills: { mode: 'all' as const },\n memory: { mode: 'confirmWrite' as const, sources: ['session' as const, 'curated' as const], writePolicy: { curated: 'confirm' as const } },\n workflows: {},\n boundaries: { requiresConfirmation: [], forbidden: [], escalation: [] },\n };\n const nextEntry: AgentEntry = {\n ...base,\n enabled: base.enabled ?? true,\n ...(params.workspace ? { workspace: { root: params.workspace } } : {}),\n ...(params.models ? { models: params.models } : {}),\n ...(params.model ? { models: { ...base.models, defaultRole: 'deep', roles: { ...base.models.roles, deep: { model: params.model } } } } : {}),\n ...(params.skills ? { skills: { mode: 'allowlist' as const, allow: params.skills } } : {}),\n ...(nextTools ? { tools: nextTools } : {}),\n };\n const nextList = [...list];\n if (index >= 0) {\n nextList[index] = nextEntry;\n } else {\n if (nextList.length === 0 && agentId !== normalizeAgentId(resolveDefaultAgentId(cfg))) {\n nextList.push({\n id: resolveDefaultAgentId(cfg),\n enabled: true,\n identity: { name: resolveDefaultAgentId(cfg), role: 'Agent', language: 'en', tone: 'direct' },\n responsibilities: { primary: ['Help the user complete tasks'] },\n workspace: { root: `~/.xopc/workspace/${resolveDefaultAgentId(cfg)}` },\n models: { defaultRole: 'deep', roles: { deep: { model: 'openai/gpt-4.1' } } },\n tools: { builtin: {} },\n skills: { mode: 'all' },\n memory: { mode: 'confirmWrite', sources: ['session', 'curated'], writePolicy: { curated: 'confirm' } },\n workflows: {},\n boundaries: { requiresConfirmation: [], forbidden: [], escalation: [] },\n });\n }\n nextList.push(nextEntry);\n }\n return {\n ...cfg,\n agents: {\n ...cfg.agents,\n list: nextList,\n },\n };\n}\n\nexport function pruneAgentConfig(\n cfg: Config,\n agentId: string,\n): { config: Config; removedBindings: number } {\n const id = normalizeAgentId(agentId);\n const agents = listAgentEntries(cfg);\n const nextAgentsList = agents.filter((e) => normalizeAgentId(e.id) !== id);\n const nextAgents = nextAgentsList.length > 0 ? nextAgentsList : [];\n\n const bindings = cfg.bindings ?? [];\n const filteredBindings = bindings.filter((b) => normalizeAgentId(b.agentId) !== id);\n\n return {\n config: {\n ...cfg,\n agents: { ...cfg.agents, list: nextAgents },\n bindings: filteredBindings,\n },\n removedBindings: bindings.length - filteredBindings.length,\n };\n}\n\nexport async function removeAgentDirsFromDisk(cfg: Config, id: string): Promise<void> {\n const aid = normalizeAgentId(id);\n if (aid === DEFAULT_AGENT_ID) {\n throw new Error('Refusing to delete the main agent home on disk from this command.');\n }\n const home = resolveAgentHomeDir(cfg, aid);\n const ws = resolveAgentWorkspaceDir(cfg, aid);\n if (existsSync(home)) {\n await rm(home, { recursive: true, force: true });\n }\n if (existsSync(ws) && ws !== home) {\n await rm(ws, { recursive: true, force: true });\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"agents.config.js","names":[],"sources":["../../../src/commands/agents.config.ts"],"sourcesContent":["/**\n * Mutate `agents.list` / bindings when adding or removing agents.\n */\n\nimport { rm } from 'node:fs/promises';\nimport { existsSync } from 'node:fs';\n\nimport type { Config } from '../config/schema.js';\nimport {\n listAgentEntries,\n normalizeAgentId,\n resolveAgentHomeDir,\n resolveAgentWorkspaceDir,\n resolveDefaultAgentId,\n DEFAULT_AGENT_ID,\n} from '../agent/agent-scope.js';\n\ntype AgentEntry = NonNullable<NonNullable<Config['agents']>['list']>[number];\n\nexport { listAgentEntries };\n\nexport function findAgentEntryIndex(list: AgentEntry[], agentId: string): number {\n const id = normalizeAgentId(agentId);\n return list.findIndex((e) => normalizeAgentId(e.id) === id);\n}\n\nexport function applyAgentConfig(\n cfg: Config,\n params: {\n agentId: string;\n workspace?: string;\n model?: string;\n models?: AgentEntry['models'];\n skills?: string[];\n tools?: AgentEntry['tools'];\n },\n): Config {\n const agentId = normalizeAgentId(params.agentId);\n const list = listAgentEntries(cfg);\n const index = findAgentEntryIndex(list, agentId);\n const nextTools = params.tools;\n const base = index >= 0 ? list[index] : {\n id: agentId,\n enabled: true as const,\n identity: { name: agentId, role: 'Agent', language: 'en', tone: 'direct' },\n responsibilities: { primary: ['Help the user complete tasks'] },\n workspace: { root: `~/.xopc/workspace/${agentId}` },\n tools: { builtin: {} },\n skills: { mode: 'all' as const },\n memory: { mode: 'confirmWrite' as const, sources: ['session' as const, 'curated' as const], writePolicy: { curated: 'confirm' as const } },\n workflows: {},\n boundaries: { requiresConfirmation: [], forbidden: [], escalation: [] },\n };\n const nextEntry: AgentEntry = {\n ...base,\n enabled: base.enabled ?? true,\n ...(params.workspace ? { workspace: { root: params.workspace } } : {}),\n ...(params.models ? { models: params.models } : {}),\n ...(params.model\n ? {\n models: {\n ...(base.models ?? {}),\n defaultRole: 'deep',\n roles: { ...(base.models?.roles ?? {}), deep: { model: params.model } },\n },\n }\n : {}),\n ...(params.skills ? { skills: { mode: 'allowlist' as const, allow: params.skills } } : {}),\n ...(nextTools ? { tools: nextTools } : {}),\n };\n const nextList = [...list];\n if (index >= 0) {\n nextList[index] = nextEntry;\n } else {\n if (nextList.length === 0 && agentId !== normalizeAgentId(resolveDefaultAgentId(cfg))) {\n nextList.push({\n id: resolveDefaultAgentId(cfg),\n enabled: true,\n identity: { name: resolveDefaultAgentId(cfg), role: 'Agent', language: 'en', tone: 'direct' },\n responsibilities: { primary: ['Help the user complete tasks'] },\n workspace: { root: `~/.xopc/workspace/${resolveDefaultAgentId(cfg)}` },\n tools: { builtin: {} },\n skills: { mode: 'all' },\n memory: { mode: 'confirmWrite', sources: ['session', 'curated'], writePolicy: { curated: 'confirm' } },\n workflows: {},\n boundaries: { requiresConfirmation: [], forbidden: [], escalation: [] },\n });\n }\n nextList.push(nextEntry);\n }\n return {\n ...cfg,\n agents: {\n ...cfg.agents,\n list: nextList,\n },\n };\n}\n\nexport function getAgentDeleteBlocker(cfg: Config, agentId: string): string | null {\n const id = normalizeAgentId(agentId);\n if (id === DEFAULT_AGENT_ID) {\n return `Agent id \"${DEFAULT_AGENT_ID}\" is reserved for the primary agent.`;\n }\n if (id === normalizeAgentId(resolveDefaultAgentId(cfg))) {\n return `Agent \"${id}\" is the global default agent. Change agents.default first.`;\n }\n const tuiDefault = cfg.tui?.defaultAgent?.trim();\n if (tuiDefault && id === normalizeAgentId(tuiDefault)) {\n return `Agent \"${id}\" is the TUI default agent. Change tui.defaultAgent first.`;\n }\n return null;\n}\n\nexport function setTuiDefaultAgentConfig(\n cfg: Config,\n agentIdRaw: string,\n): { ok: true; config: Config; agentId: string } | { ok: false; message: string } {\n const raw = agentIdRaw.trim();\n if (!raw) {\n return { ok: false, message: 'Agent id is required.' };\n }\n const agentId = normalizeAgentId(raw);\n if (agentId !== raw.toLowerCase()) {\n return { ok: false, message: `Invalid agent id: ${raw}` };\n }\n const entry = listAgentEntries(cfg).find((agent) => normalizeAgentId(agent.id) === agentId);\n if (!entry || entry.enabled === false) {\n return { ok: false, message: `Agent \"${agentId}\" not found or disabled.` };\n }\n return {\n ok: true,\n agentId,\n config: {\n ...cfg,\n tui: {\n ...cfg.tui,\n defaultAgent: agentId,\n },\n },\n };\n}\n\nexport function pruneAgentConfig(\n cfg: Config,\n agentId: string,\n): { config: Config; removedBindings: number } {\n const id = normalizeAgentId(agentId);\n const blocker = getAgentDeleteBlocker(cfg, id);\n if (blocker) {\n throw new Error(blocker);\n }\n const agents = listAgentEntries(cfg);\n const nextAgentsList = agents.filter((e) => normalizeAgentId(e.id) !== id);\n const nextAgents = nextAgentsList.length > 0 ? nextAgentsList : [];\n\n const bindings = cfg.bindings ?? [];\n const filteredBindings = bindings.filter((b) => normalizeAgentId(b.agentId) !== id);\n\n return {\n config: {\n ...cfg,\n agents: { ...cfg.agents, list: nextAgents },\n bindings: filteredBindings,\n },\n removedBindings: bindings.length - filteredBindings.length,\n };\n}\n\nexport async function removeAgentDirsFromDisk(cfg: Config, id: string): Promise<void> {\n const aid = normalizeAgentId(id);\n if (aid === DEFAULT_AGENT_ID) {\n throw new Error('Refusing to delete the main agent home on disk from this command.');\n }\n const home = resolveAgentHomeDir(cfg, aid);\n const ws = resolveAgentWorkspaceDir(cfg, aid);\n if (existsSync(home)) {\n await rm(home, { recursive: true, force: true });\n }\n if (existsSync(ws) && ws !== home) {\n await rm(ws, { recursive: true, force: true });\n }\n}\n"],"mappings":"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"}