@xopcai/xopc 0.0.6 → 0.0.11

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 (412) hide show
  1. package/dist/extensions/weixin/src/api/api.js +1 -1
  2. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  3. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  4. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  5. package/dist/gateway/static/root/assets/{agents-B6s2BvpH.js → agents-BdC4Y-HX.js} +2 -2
  6. package/dist/gateway/static/root/assets/agents-BdC4Y-HX.js.map +1 -0
  7. package/dist/gateway/static/root/assets/{apps-page-BtsZ5ZPx.js → apps-page-C-oaSHkm.js} +2 -2
  8. package/dist/gateway/static/root/assets/{apps-page-BtsZ5ZPx.js.map → apps-page-C-oaSHkm.js.map} +1 -1
  9. package/dist/gateway/static/root/assets/attachment-load-BDDlItdE.js +1 -0
  10. package/dist/gateway/static/root/assets/{channels-settings-BUfWBEVU.js → channels-settings-BqEUppPO.js} +2 -2
  11. package/dist/gateway/static/root/assets/{channels-settings-BUfWBEVU.js.map → channels-settings-BqEUppPO.js.map} +1 -1
  12. package/dist/gateway/static/root/assets/{chat-agents-api-BR30M2YQ.js → chat-agents-api-BhqjQ7iL.js} +2 -2
  13. package/dist/gateway/static/root/assets/{chat-agents-api-BR30M2YQ.js.map → chat-agents-api-BhqjQ7iL.js.map} +1 -1
  14. package/dist/gateway/static/root/assets/{cron-page-CMTx0Mjz.js → cron-page-Cli49RKR.js} +2 -2
  15. package/dist/gateway/static/root/assets/{cron-page-CMTx0Mjz.js.map → cron-page-Cli49RKR.js.map} +1 -1
  16. package/dist/gateway/static/root/assets/{cron-utils-BJma9IcD.js → cron-utils-Dkj-Ldpf.js} +2 -2
  17. package/dist/gateway/static/root/assets/{cron-utils-BJma9IcD.js.map → cron-utils-Dkj-Ldpf.js.map} +1 -1
  18. package/dist/gateway/static/root/assets/electron-env-BDtJw9AY.js +2 -0
  19. package/dist/gateway/static/root/assets/electron-env-BDtJw9AY.js.map +1 -0
  20. package/dist/gateway/static/root/assets/{extension-debug-page-BCVoNSo6.js → extension-debug-page-BMcZlaxF.js} +2 -2
  21. package/dist/gateway/static/root/assets/{extension-debug-page-BCVoNSo6.js.map → extension-debug-page-BMcZlaxF.js.map} +1 -1
  22. package/dist/gateway/static/root/assets/{extension-iframe-host-PWB-Pw2d.js → extension-iframe-host-D5HEF0KR.js} +2 -2
  23. package/dist/gateway/static/root/assets/{extension-iframe-host-PWB-Pw2d.js.map → extension-iframe-host-D5HEF0KR.js.map} +1 -1
  24. package/dist/gateway/static/root/assets/{extension-page-D2tTklsD.js → extension-page-CXdCSSPl.js} +2 -2
  25. package/dist/gateway/static/root/assets/{extension-page-D2tTklsD.js.map → extension-page-CXdCSSPl.js.map} +1 -1
  26. package/dist/gateway/static/root/assets/{extension-provider-BpHodVRj.js → extension-provider-DZCZgQE2.js} +2 -2
  27. package/dist/gateway/static/root/assets/{extension-provider-BpHodVRj.js.map → extension-provider-DZCZgQE2.js.map} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-settings-page-BEu6Xw1Z.js → extension-settings-page-CX6STpx3.js} +2 -2
  29. package/dist/gateway/static/root/assets/{extension-settings-page-BEu6Xw1Z.js.map → extension-settings-page-CX6STpx3.js.map} +1 -1
  30. package/dist/gateway/static/root/assets/{gateway-config-swr-C7ZFPhNj.js → gateway-config-swr-Cph02QZn.js} +2 -2
  31. package/dist/gateway/static/root/assets/{gateway-config-swr-C7ZFPhNj.js.map → gateway-config-swr-Cph02QZn.js.map} +1 -1
  32. package/dist/gateway/static/root/assets/index-Bty3m0mS.css +2 -0
  33. package/dist/gateway/static/root/assets/index-iTUyfzNr.js +16 -0
  34. package/dist/gateway/static/root/assets/index-iTUyfzNr.js.map +1 -0
  35. package/dist/gateway/static/root/assets/{logs-page-BpsxYdcL.js → logs-page-B9O5l3I8.js} +2 -2
  36. package/dist/gateway/static/root/assets/{logs-page-BpsxYdcL.js.map → logs-page-B9O5l3I8.js.map} +1 -1
  37. package/dist/gateway/static/root/assets/{model-selector-BiiDq8Pk.js → model-selector-BLiY_O25.js} +2 -2
  38. package/dist/gateway/static/root/assets/{model-selector-BiiDq8Pk.js.map → model-selector-BLiY_O25.js.map} +1 -1
  39. package/dist/gateway/static/root/assets/navigation-DB9S-C6S.js +2 -0
  40. package/dist/gateway/static/root/assets/navigation-DB9S-C6S.js.map +1 -0
  41. package/dist/gateway/static/root/assets/page-header-store-BFpnFTed.js +2 -0
  42. package/dist/gateway/static/root/assets/{page-header-store-HcRZK5CZ.js.map → page-header-store-BFpnFTed.js.map} +1 -1
  43. package/dist/gateway/static/root/assets/{session-api-DxNaAkmX.js → session-api-DEhQXWJg.js} +2 -2
  44. package/dist/gateway/static/root/assets/{session-api-DxNaAkmX.js.map → session-api-DEhQXWJg.js.map} +1 -1
  45. package/dist/gateway/static/root/assets/{session-working-directory-control-CDH-Wk4E.js → session-working-directory-control-DKOtWs3-.js} +3 -3
  46. package/dist/gateway/static/root/assets/{session-working-directory-control-CDH-Wk4E.js.map → session-working-directory-control-DKOtWs3-.js.map} +1 -1
  47. package/dist/gateway/static/root/assets/{sessions-page-5PK75r1n.js → sessions-page-BYlWP1ep.js} +2 -2
  48. package/dist/gateway/static/root/assets/{sessions-page-5PK75r1n.js.map → sessions-page-BYlWP1ep.js.map} +1 -1
  49. package/dist/gateway/static/root/assets/settings-page-oCnIavdg.js +2 -0
  50. package/dist/gateway/static/root/assets/settings-page-oCnIavdg.js.map +1 -0
  51. package/dist/gateway/static/root/assets/{skill-api-CxbNlOD_.js → skill-api-DWrn8Az0.js} +2 -2
  52. package/dist/gateway/static/root/assets/{skill-api-CxbNlOD_.js.map → skill-api-DWrn8Az0.js.map} +1 -1
  53. package/dist/gateway/static/root/assets/{skills-page-Dd8ZzYJb.js → skills-page-C59WQpM1.js} +2 -2
  54. package/dist/gateway/static/root/assets/{skills-page-Dd8ZzYJb.js.map → skills-page-C59WQpM1.js.map} +1 -1
  55. package/dist/gateway/static/root/assets/{theme-store-CPTH77BE.js → theme-store-CywXkKml.js} +2 -2
  56. package/dist/gateway/static/root/assets/{theme-store-CPTH77BE.js.map → theme-store-CywXkKml.js.map} +1 -1
  57. package/dist/gateway/static/root/assets/url-D7yWllI8.js +2 -0
  58. package/dist/gateway/static/root/assets/url-D7yWllI8.js.map +1 -0
  59. package/dist/gateway/static/root/assets/{useTranslation-BEUWOMuh.js → useTranslation-CACj0DBJ.js} +2 -2
  60. package/dist/gateway/static/root/assets/{useTranslation-BEUWOMuh.js.map → useTranslation-CACj0DBJ.js.map} +1 -1
  61. package/dist/gateway/static/root/index.html +16 -16
  62. package/dist/package.js +1 -1
  63. package/dist/src/agent/agent-manager.d.ts +1 -0
  64. package/dist/src/agent/agent-manager.js +17 -9
  65. package/dist/src/agent/agent-manager.js.map +1 -1
  66. package/dist/src/agent/background-review/run-background-review.js +2 -0
  67. package/dist/src/agent/background-review/run-background-review.js.map +1 -1
  68. package/dist/src/agent/child-agent-factory.js +2 -0
  69. package/dist/src/agent/child-agent-factory.js.map +1 -1
  70. package/dist/src/agent/context/expand-at-file-mentions.d.ts +4 -0
  71. package/dist/src/agent/context/expand-at-file-mentions.js +69 -0
  72. package/dist/src/agent/context/expand-at-file-mentions.js.map +1 -0
  73. package/dist/src/agent/context/workspace-seed.js +1 -1
  74. package/dist/src/agent/image/index.d.ts +0 -1
  75. package/dist/src/agent/image/index.js +1 -2
  76. package/dist/src/agent/image/understanding/pi-ai-provider.js.map +1 -1
  77. package/dist/src/agent/ipc/inbox.js +1 -1
  78. package/dist/src/agent/ipc/socket.js +1 -1
  79. package/dist/src/agent/memory/compaction.d.ts +1 -1
  80. package/dist/src/agent/memory/compaction.js +38 -11
  81. package/dist/src/agent/memory/compaction.js.map +1 -1
  82. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  83. package/dist/src/agent/messaging/command-handler.d.ts +13 -0
  84. package/dist/src/agent/messaging/command-handler.js +14 -2
  85. package/dist/src/agent/messaging/command-handler.js.map +1 -1
  86. package/dist/src/agent/orchestration/agent-orchestrator.js +6 -1
  87. package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
  88. package/dist/src/agent/service.d.ts +16 -1
  89. package/dist/src/agent/service.js +175 -17
  90. package/dist/src/agent/service.js.map +1 -1
  91. package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
  92. package/dist/src/agent/skills/hub-hash.js +1 -1
  93. package/dist/src/agent/skills/hub-pull.js +1 -1
  94. package/dist/src/agent/skills/scanner.js +1 -1
  95. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  96. package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
  97. package/dist/src/agent/tools/browser/tools.js +2 -2
  98. package/dist/src/agent/tools/browser/tools.js.map +1 -1
  99. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  100. package/dist/src/agent/tools/image-tool.js +2 -2
  101. package/dist/src/agent/tools/image-tool.js.map +1 -1
  102. package/dist/src/agent/tools/index.d.ts +1 -1
  103. package/dist/src/agent/tools/index.js +2 -2
  104. package/dist/src/agent/tools/read.d.ts +0 -2
  105. package/dist/src/agent/tools/read.js +1 -3
  106. package/dist/src/agent/tools/read.js.map +1 -1
  107. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  108. package/dist/src/agent/tools/write.js +1 -1
  109. package/dist/src/auth/credentials.js +2 -2
  110. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  111. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  112. package/dist/src/channels/index.d.ts +1 -1
  113. package/dist/src/channels/index.js +2 -2
  114. package/dist/src/channels/pipeline.d.ts +8 -1
  115. package/dist/src/channels/pipeline.js +49 -4
  116. package/dist/src/channels/pipeline.js.map +1 -1
  117. package/dist/src/channels/plugin-types.d.ts +14 -0
  118. package/dist/src/chat-commands/builtins/config.d.ts +4 -0
  119. package/dist/src/chat-commands/builtins/config.js +197 -0
  120. package/dist/src/chat-commands/builtins/config.js.map +1 -0
  121. package/dist/src/chat-commands/builtins/context.d.ts +4 -0
  122. package/dist/src/chat-commands/builtins/context.js +44 -0
  123. package/dist/src/chat-commands/builtins/context.js.map +1 -0
  124. package/dist/src/chat-commands/builtins/session.js +111 -0
  125. package/dist/src/chat-commands/builtins/session.js.map +1 -1
  126. package/dist/src/chat-commands/builtins/thinking.js +49 -21
  127. package/dist/src/chat-commands/builtins/thinking.js.map +1 -1
  128. package/dist/src/chat-commands/config-paths.d.ts +10 -0
  129. package/dist/src/chat-commands/config-paths.js +45 -0
  130. package/dist/src/chat-commands/config-paths.js.map +1 -0
  131. package/dist/src/chat-commands/config-value.d.ts +12 -0
  132. package/dist/src/chat-commands/config-value.js +53 -0
  133. package/dist/src/chat-commands/config-value.js.map +1 -0
  134. package/dist/src/chat-commands/context.d.ts +24 -1
  135. package/dist/src/chat-commands/context.js +41 -0
  136. package/dist/src/chat-commands/context.js.map +1 -1
  137. package/dist/src/chat-commands/index.d.ts +2 -0
  138. package/dist/src/chat-commands/index.js +5 -1
  139. package/dist/src/chat-commands/index.js.map +1 -1
  140. package/dist/src/chat-commands/types.d.ts +33 -1
  141. package/dist/src/cli/commands/agent/interactive.js +1 -1
  142. package/dist/src/cli/commands/agent/interactive.js.map +1 -1
  143. package/dist/src/cli/commands/agent.js +21 -9
  144. package/dist/src/cli/commands/agent.js.map +1 -1
  145. package/dist/src/cli/commands/auth.js.map +1 -1
  146. package/dist/src/cli/commands/doctor/checks/channel-config.d.ts +2 -0
  147. package/dist/src/cli/commands/doctor/checks/channel-config.js +113 -0
  148. package/dist/src/cli/commands/doctor/checks/channel-config.js.map +1 -0
  149. package/dist/src/cli/commands/doctor/checks/channel-plugins.d.ts +2 -0
  150. package/dist/src/cli/commands/doctor/checks/channel-plugins.js +47 -0
  151. package/dist/src/cli/commands/doctor/checks/channel-plugins.js.map +1 -0
  152. package/dist/src/cli/commands/doctor/checks/config-health.d.ts +2 -0
  153. package/dist/src/cli/commands/doctor/checks/config-health.js +82 -0
  154. package/dist/src/cli/commands/doctor/checks/config-health.js.map +1 -0
  155. package/dist/src/cli/commands/doctor/checks/cron-health.d.ts +2 -0
  156. package/dist/src/cli/commands/doctor/checks/cron-health.js +116 -0
  157. package/dist/src/cli/commands/doctor/checks/cron-health.js.map +1 -0
  158. package/dist/src/cli/commands/doctor/checks/gateway-health.d.ts +2 -0
  159. package/dist/src/cli/commands/doctor/checks/gateway-health.js +64 -0
  160. package/dist/src/cli/commands/doctor/checks/gateway-health.js.map +1 -0
  161. package/dist/src/cli/commands/doctor/checks/gateway-service.d.ts +2 -0
  162. package/dist/src/cli/commands/doctor/checks/gateway-service.js +64 -0
  163. package/dist/src/cli/commands/doctor/checks/gateway-service.js.map +1 -0
  164. package/dist/src/cli/commands/doctor/checks/node-version.d.ts +2 -0
  165. package/dist/src/cli/commands/doctor/checks/node-version.js +33 -0
  166. package/dist/src/cli/commands/doctor/checks/node-version.js.map +1 -0
  167. package/dist/src/cli/commands/doctor/checks/provider-auth.d.ts +2 -0
  168. package/dist/src/cli/commands/doctor/checks/provider-auth.js +91 -0
  169. package/dist/src/cli/commands/doctor/checks/provider-auth.js.map +1 -0
  170. package/dist/src/cli/commands/doctor/checks/security-audit.d.ts +2 -0
  171. package/dist/src/cli/commands/doctor/checks/security-audit.js +85 -0
  172. package/dist/src/cli/commands/doctor/checks/security-audit.js.map +1 -0
  173. package/dist/src/cli/commands/doctor/checks/session-integrity.d.ts +2 -0
  174. package/dist/src/cli/commands/doctor/checks/session-integrity.js +118 -0
  175. package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -0
  176. package/dist/src/cli/commands/doctor/checks/state-integrity.d.ts +2 -0
  177. package/dist/src/cli/commands/doctor/checks/state-integrity.js +99 -0
  178. package/dist/src/cli/commands/doctor/checks/state-integrity.js.map +1 -0
  179. package/dist/src/cli/commands/doctor/checks/version-check.d.ts +2 -0
  180. package/dist/src/cli/commands/doctor/checks/version-check.js +71 -0
  181. package/dist/src/cli/commands/doctor/checks/version-check.js.map +1 -0
  182. package/dist/src/cli/commands/doctor/checks/workspace-status.d.ts +2 -0
  183. package/dist/src/cli/commands/doctor/checks/workspace-status.js +73 -0
  184. package/dist/src/cli/commands/doctor/checks/workspace-status.js.map +1 -0
  185. package/dist/src/cli/commands/doctor/flow.d.ts +9 -0
  186. package/dist/src/cli/commands/doctor/flow.js +51 -0
  187. package/dist/src/cli/commands/doctor/flow.js.map +1 -0
  188. package/dist/src/cli/commands/doctor/format.d.ts +6 -0
  189. package/dist/src/cli/commands/doctor/format.js +61 -0
  190. package/dist/src/cli/commands/doctor/format.js.map +1 -0
  191. package/dist/src/cli/commands/doctor/index.js +44 -0
  192. package/dist/src/cli/commands/doctor/index.js.map +1 -0
  193. package/dist/src/cli/commands/doctor/types.d.ts +20 -0
  194. package/dist/src/cli/commands/doctor/types.js +1 -0
  195. package/dist/src/cli/commands/extension.js +10 -0
  196. package/dist/src/cli/commands/extension.js.map +1 -1
  197. package/dist/src/cli/commands/init.js +1 -2
  198. package/dist/src/cli/commands/init.js.map +1 -1
  199. package/dist/src/cli/commands/session/utils.js.map +1 -1
  200. package/dist/src/cli/commands/update.d.ts +1 -0
  201. package/dist/src/cli/commands/update.js +171 -0
  202. package/dist/src/cli/commands/update.js.map +1 -0
  203. package/dist/src/cli/index.d.ts +2 -2
  204. package/dist/src/cli/index.js +4 -2
  205. package/dist/src/cli/index.js.map +1 -1
  206. package/dist/src/cli/utils/init-workspace.js +1 -1
  207. package/dist/src/config/index.d.ts +1 -0
  208. package/dist/src/config/index.js +4 -3
  209. package/dist/src/config/index.js.map +1 -1
  210. package/dist/src/config/loader.js +1 -1
  211. package/dist/src/config/models-json.d.ts +15 -15
  212. package/dist/src/config/paths.js.map +1 -1
  213. package/dist/src/config/profile.js +1 -1
  214. package/dist/src/config/runtime-overrides.d.ts +8 -0
  215. package/dist/src/config/runtime-overrides.js +40 -0
  216. package/dist/src/config/runtime-overrides.js.map +1 -0
  217. package/dist/src/config/schema.d.ts +34 -104
  218. package/dist/src/config/schema.js +18 -39
  219. package/dist/src/config/schema.js.map +1 -1
  220. package/dist/src/cron/persistence.js +1 -1
  221. package/dist/src/cron/run-log-store.js +1 -1
  222. package/dist/src/daemon/launchd.js +2 -2
  223. package/dist/src/daemon/launchd.js.map +1 -1
  224. package/dist/src/daemon/systemd.js +2 -2
  225. package/dist/src/daemon/systemd.js.map +1 -1
  226. package/dist/src/extensions/health.js +1 -1
  227. package/dist/src/extensions/loader.d.ts +1 -1
  228. package/dist/src/extensions/loader.js +5 -8
  229. package/dist/src/extensions/loader.js.map +1 -1
  230. package/dist/src/extensions/lockfile.js +1 -1
  231. package/dist/src/extensions/sdk/index.js +6 -1
  232. package/dist/src/extensions/sdk/index.js.map +1 -0
  233. package/dist/src/gateway/agents-admin.js +1 -1
  234. package/dist/src/gateway/agents-admin.js.map +1 -1
  235. package/dist/src/gateway/hono/lib/static-ui.js +1 -1
  236. package/dist/src/gateway/hono/oauth.js +1 -1
  237. package/dist/src/gateway/hono/routes/config.js +1 -1
  238. package/dist/src/gateway/hono/routes/doctor.d.ts +3 -0
  239. package/dist/src/gateway/hono/routes/doctor.js +35 -0
  240. package/dist/src/gateway/hono/routes/doctor.js.map +1 -0
  241. package/dist/src/gateway/hono/routes/index.js +4 -0
  242. package/dist/src/gateway/hono/routes/index.js.map +1 -1
  243. package/dist/src/gateway/hono/routes/models.js +64 -11
  244. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  245. package/dist/src/gateway/hono/routes/public-gateway.js +10 -0
  246. package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
  247. package/dist/src/gateway/hono/routes/update.d.ts +3 -0
  248. package/dist/src/gateway/hono/routes/update.js +141 -0
  249. package/dist/src/gateway/hono/routes/update.js.map +1 -0
  250. package/dist/src/gateway/hono/routes/workspace.js +82 -2
  251. package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
  252. package/dist/src/gateway/lock.js +1 -1
  253. package/dist/src/gateway/ports.js +98 -3
  254. package/dist/src/gateway/ports.js.map +1 -1
  255. package/dist/src/gateway/service.d.ts +1 -4
  256. package/dist/src/gateway/service.js +13 -20
  257. package/dist/src/gateway/service.js.map +1 -1
  258. package/dist/src/gateway/workspace-fs-file-list.d.ts +5 -0
  259. package/dist/src/gateway/workspace-fs-file-list.js +56 -0
  260. package/dist/src/gateway/workspace-fs-file-list.js.map +1 -0
  261. package/dist/src/gateway/workspace-heartbeat-path.js +1 -1
  262. package/dist/src/gateway/workspace-ripgrep.d.ts +5 -0
  263. package/dist/src/gateway/workspace-ripgrep.js +88 -4
  264. package/dist/src/gateway/workspace-ripgrep.js.map +1 -1
  265. package/dist/src/infra/update-channels.d.ts +14 -0
  266. package/dist/src/infra/update-channels.js +30 -0
  267. package/dist/src/infra/update-channels.js.map +1 -0
  268. package/dist/src/infra/update-check.d.ts +53 -0
  269. package/dist/src/infra/update-check.js +155 -0
  270. package/dist/src/infra/update-check.js.map +1 -0
  271. package/dist/src/infra/update-runner.d.ts +18 -0
  272. package/dist/src/infra/update-runner.js +112 -0
  273. package/dist/src/infra/update-runner.js.map +1 -0
  274. package/dist/src/infra/update-startup.d.ts +20 -0
  275. package/dist/src/infra/update-startup.js +246 -0
  276. package/dist/src/infra/update-startup.js.map +1 -0
  277. package/dist/src/providers/extension-stream-bridge.d.ts +3 -0
  278. package/dist/src/providers/extension-stream-bridge.js +239 -0
  279. package/dist/src/providers/extension-stream-bridge.js.map +1 -0
  280. package/dist/src/providers/index.d.ts +7 -2
  281. package/dist/src/providers/index.js +77 -14
  282. package/dist/src/providers/index.js.map +1 -1
  283. package/dist/src/providers/model-registry.js +1 -1
  284. package/dist/src/providers/plugin-registry.js +92 -87
  285. package/dist/src/providers/plugin-registry.js.map +1 -1
  286. package/dist/src/routing/bindings.js +1 -1
  287. package/dist/src/routing/index.d.ts +1 -1
  288. package/dist/src/routing/index.js +2 -2
  289. package/dist/src/routing/index.js.map +1 -1
  290. package/dist/src/routing/resolve-route.js +1 -1
  291. package/dist/src/routing/session-key.d.ts +0 -5
  292. package/dist/src/routing/session-key.js +1 -27
  293. package/dist/src/routing/session-key.js.map +1 -1
  294. package/dist/src/session/chat-export.d.ts +5 -0
  295. package/dist/src/session/chat-export.js +35 -0
  296. package/dist/src/session/chat-export.js.map +1 -0
  297. package/dist/src/session/config-store.js +1 -1
  298. package/dist/src/session/manager.d.ts +1 -1
  299. package/dist/src/session/manager.js +2 -2
  300. package/dist/src/session/manager.js.map +1 -1
  301. package/dist/src/session/store.d.ts +1 -1
  302. package/dist/src/session/store.js +3 -7
  303. package/dist/src/session/store.js.map +1 -1
  304. package/dist/src/session/types.d.ts +0 -10
  305. package/dist/src/session/types.js.map +1 -1
  306. package/dist/src/utils/logger/audit.js +1 -1
  307. package/dist/src/utils/logger/log-store.js +1 -1
  308. package/dist/src/utils/logger/rotation.js +1 -1
  309. package/dist/src/voice/tts/audio.js +1 -1
  310. package/package.json +2 -2
  311. package/dist/gateway/static/root/assets/agents-B6s2BvpH.js.map +0 -1
  312. package/dist/gateway/static/root/assets/attachment-load-6pRlDPZ8.js +0 -1
  313. package/dist/gateway/static/root/assets/index-DBZ5eXW5.js +0 -16
  314. package/dist/gateway/static/root/assets/index-DBZ5eXW5.js.map +0 -1
  315. package/dist/gateway/static/root/assets/index-KsVMH-Jo.css +0 -2
  316. package/dist/gateway/static/root/assets/navigation-BpLKd2Ca.js +0 -2
  317. package/dist/gateway/static/root/assets/navigation-BpLKd2Ca.js.map +0 -1
  318. package/dist/gateway/static/root/assets/page-header-store-HcRZK5CZ.js +0 -2
  319. package/dist/gateway/static/root/assets/preference-select-fields-B4AJBqUY.js +0 -2
  320. package/dist/gateway/static/root/assets/preference-select-fields-B4AJBqUY.js.map +0 -1
  321. package/dist/gateway/static/root/assets/settings-page-BvSj0JqX.js +0 -2
  322. package/dist/gateway/static/root/assets/settings-page-BvSj0JqX.js.map +0 -1
  323. package/dist/gateway/static/root/assets/url-QmwQTJ-j.js +0 -2
  324. package/dist/gateway/static/root/assets/url-QmwQTJ-j.js.map +0 -1
  325. package/dist/src/acp/commands.d.ts +0 -11
  326. package/dist/src/acp/commands.js +0 -17
  327. package/dist/src/acp/commands.js.map +0 -1
  328. package/dist/src/acp/control-plane/identity-reconcile.d.ts +0 -36
  329. package/dist/src/acp/control-plane/identity-reconcile.js +0 -124
  330. package/dist/src/acp/control-plane/identity-reconcile.js.map +0 -1
  331. package/dist/src/acp/control-plane/index.d.ts +0 -10
  332. package/dist/src/acp/control-plane/index.js +0 -6
  333. package/dist/src/acp/control-plane/manager.d.ts +0 -86
  334. package/dist/src/acp/control-plane/manager.js +0 -502
  335. package/dist/src/acp/control-plane/manager.js.map +0 -1
  336. package/dist/src/acp/control-plane/manager.types.d.ts +0 -125
  337. package/dist/src/acp/control-plane/manager.types.js +0 -14
  338. package/dist/src/acp/control-plane/manager.types.js.map +0 -1
  339. package/dist/src/acp/control-plane/manager.utils.d.ts +0 -29
  340. package/dist/src/acp/control-plane/manager.utils.js +0 -46
  341. package/dist/src/acp/control-plane/manager.utils.js.map +0 -1
  342. package/dist/src/acp/control-plane/runtime-cache-manager.d.ts +0 -49
  343. package/dist/src/acp/control-plane/runtime-cache-manager.js +0 -155
  344. package/dist/src/acp/control-plane/runtime-cache-manager.js.map +0 -1
  345. package/dist/src/acp/control-plane/runtime-cache.d.ts +0 -45
  346. package/dist/src/acp/control-plane/runtime-cache.js +0 -58
  347. package/dist/src/acp/control-plane/runtime-cache.js.map +0 -1
  348. package/dist/src/acp/control-plane/runtime-options.d.ts +0 -30
  349. package/dist/src/acp/control-plane/runtime-options.js +0 -92
  350. package/dist/src/acp/control-plane/runtime-options.js.map +0 -1
  351. package/dist/src/acp/control-plane/session-actor-queue.d.ts +0 -22
  352. package/dist/src/acp/control-plane/session-actor-queue.js +0 -70
  353. package/dist/src/acp/control-plane/session-actor-queue.js.map +0 -1
  354. package/dist/src/acp/control-plane/session-lifecycle-manager.d.ts +0 -59
  355. package/dist/src/acp/control-plane/session-lifecycle-manager.js +0 -209
  356. package/dist/src/acp/control-plane/session-lifecycle-manager.js.map +0 -1
  357. package/dist/src/acp/control-plane/session-store.d.ts +0 -39
  358. package/dist/src/acp/control-plane/session-store.js +0 -149
  359. package/dist/src/acp/control-plane/session-store.js.map +0 -1
  360. package/dist/src/acp/control-plane/turn-manager.d.ts +0 -40
  361. package/dist/src/acp/control-plane/turn-manager.js +0 -134
  362. package/dist/src/acp/control-plane/turn-manager.js.map +0 -1
  363. package/dist/src/acp/event-mapper.d.ts +0 -48
  364. package/dist/src/acp/event-mapper.js +0 -94
  365. package/dist/src/acp/event-mapper.js.map +0 -1
  366. package/dist/src/acp/index.d.ts +0 -10
  367. package/dist/src/acp/index.js +0 -5
  368. package/dist/src/acp/meta.d.ts +0 -15
  369. package/dist/src/acp/meta.js +0 -36
  370. package/dist/src/acp/meta.js.map +0 -1
  371. package/dist/src/acp/routing-integration.d.ts +0 -37
  372. package/dist/src/acp/routing-integration.js +0 -58
  373. package/dist/src/acp/routing-integration.js.map +0 -1
  374. package/dist/src/acp/runtime/backends/index.d.ts +0 -4
  375. package/dist/src/acp/runtime/backends/index.js +0 -2
  376. package/dist/src/acp/runtime/backends/local.d.ts +0 -136
  377. package/dist/src/acp/runtime/backends/local.js +0 -603
  378. package/dist/src/acp/runtime/backends/local.js.map +0 -1
  379. package/dist/src/acp/runtime/error-text.d.ts +0 -16
  380. package/dist/src/acp/runtime/error-text.js +0 -40
  381. package/dist/src/acp/runtime/error-text.js.map +0 -1
  382. package/dist/src/acp/runtime/errors.d.ts +0 -31
  383. package/dist/src/acp/runtime/errors.js +0 -47
  384. package/dist/src/acp/runtime/errors.js.map +0 -1
  385. package/dist/src/acp/runtime/index.d.ts +0 -7
  386. package/dist/src/acp/runtime/index.js +0 -4
  387. package/dist/src/acp/runtime/registry.d.ts +0 -35
  388. package/dist/src/acp/runtime/registry.js +0 -85
  389. package/dist/src/acp/runtime/registry.js.map +0 -1
  390. package/dist/src/acp/runtime/session-identity.d.ts +0 -35
  391. package/dist/src/acp/runtime/session-identity.js +0 -134
  392. package/dist/src/acp/runtime/session-identity.js.map +0 -1
  393. package/dist/src/acp/runtime/types.d.ts +0 -214
  394. package/dist/src/acp/secret-file.d.ts +0 -7
  395. package/dist/src/acp/secret-file.js +0 -19
  396. package/dist/src/acp/secret-file.js.map +0 -1
  397. package/dist/src/acp/server.d.ts +0 -48
  398. package/dist/src/acp/server.js +0 -300
  399. package/dist/src/acp/server.js.map +0 -1
  400. package/dist/src/acp/session.d.ts +0 -29
  401. package/dist/src/acp/session.js +0 -30
  402. package/dist/src/acp/session.js.map +0 -1
  403. package/dist/src/acp/types.d.ts +0 -39
  404. package/dist/src/acp/types.js +0 -13
  405. package/dist/src/acp/types.js.map +0 -1
  406. package/dist/src/agent/image/describe-images.d.ts +0 -18
  407. package/dist/src/agent/image/describe-images.js +0 -19
  408. package/dist/src/agent/image/describe-images.js.map +0 -1
  409. package/dist/src/cli/commands/acp.d.ts +0 -4
  410. package/dist/src/cli/commands/acp.js +0 -200
  411. package/dist/src/cli/commands/acp.js.map +0 -1
  412. /package/dist/src/{acp/runtime/types.js → cli/commands/doctor/index.d.ts} +0 -0
@@ -0,0 +1,64 @@
1
+ import { init_loader, loadConfig } from "../../../../config/loader.js";
2
+ import { resolveGatewayService } from "../../../../daemon/service.js";
3
+ import { existsSync } from "node:fs";
4
+ //#region src/cli/commands/doctor/checks/gateway-service.ts
5
+ init_loader();
6
+ async function checkGatewayService(ctx) {
7
+ if (!existsSync(ctx.configPath)) return {
8
+ id: "gateway-service",
9
+ label: "Gateway service",
10
+ status: "skip",
11
+ message: "No config file; skipped.",
12
+ hints: []
13
+ };
14
+ try {
15
+ loadConfig(ctx.configPath);
16
+ } catch {
17
+ return {
18
+ id: "gateway-service",
19
+ label: "Gateway service",
20
+ status: "skip",
21
+ message: "Config could not be loaded; skipped.",
22
+ hints: []
23
+ };
24
+ }
25
+ let service;
26
+ try {
27
+ service = await resolveGatewayService();
28
+ } catch (e) {
29
+ return {
30
+ id: "gateway-service",
31
+ label: "Gateway service",
32
+ status: "skip",
33
+ message: `Service backend unavailable: ${e instanceof Error ? e.message : String(e)}`,
34
+ hints: []
35
+ };
36
+ }
37
+ const env = { ...process.env };
38
+ if (!await service.isLoaded({ env })) return {
39
+ id: "gateway-service",
40
+ label: "Gateway service",
41
+ status: "warn",
42
+ message: "Gateway is not installed as a system service.",
43
+ hints: ["Install: xopc gateway install (or your platform equivalent)"]
44
+ };
45
+ const runtime = await service.getRuntime({ env });
46
+ if (runtime.status === "running" && runtime.pid) return {
47
+ id: "gateway-service",
48
+ label: "Gateway service",
49
+ status: "pass",
50
+ message: `Gateway service is running (PID ${runtime.pid}).`,
51
+ hints: [service.label]
52
+ };
53
+ return {
54
+ id: "gateway-service",
55
+ label: "Gateway service",
56
+ status: "warn",
57
+ message: `Gateway service is installed but not running (status: ${runtime.status}).`,
58
+ hints: ["Start: xopc gateway start"]
59
+ };
60
+ }
61
+ //#endregion
62
+ export { checkGatewayService };
63
+
64
+ //# sourceMappingURL=gateway-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gateway-service.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/gateway-service.ts"],"sourcesContent":["import { loadConfig } from '../../../../config/loader.js';\nimport { existsSync } from 'node:fs';\nimport { resolveGatewayService } from '../../../../daemon/service.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nexport async function checkGatewayService(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n try {\n loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n let service;\n try {\n service = await resolveGatewayService();\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'skip',\n message: `Service backend unavailable: ${msg}`,\n hints: [],\n };\n }\n\n const env: Record<string, string | undefined> = { ...process.env };\n const loaded = await service.isLoaded({ env });\n if (!loaded) {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'warn',\n message: 'Gateway is not installed as a system service.',\n hints: ['Install: xopc gateway install (or your platform equivalent)'],\n };\n }\n\n const runtime = await service.getRuntime({ env });\n if (runtime.status === 'running' && runtime.pid) {\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'pass',\n message: `Gateway service is running (PID ${runtime.pid}).`,\n hints: [service.label],\n };\n }\n\n return {\n id: 'gateway-service',\n label: 'Gateway service',\n status: 'warn',\n message: `Gateway service is installed but not running (status: ${runtime.status}).`,\n hints: ['Start: xopc gateway start'],\n };\n}\n"],"mappings":";;;;aAA0D;AAK1D,eAAsB,oBAAoB,KAA0C;AAClF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAGH,KAAI;AACF,aAAW,IAAI,WAAW;SACpB;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,IAAI;AACJ,KAAI;AACF,YAAU,MAAM,uBAAuB;UAChC,GAAG;AAEV,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS,gCALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;GAMpD,OAAO,EAAE;GACV;;CAGH,MAAM,MAA0C,EAAE,GAAG,QAAQ,KAAK;AAElE,KAAI,CADW,MAAM,QAAQ,SAAS,EAAE,KAAK,CAAC,CAE5C,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,8DAA8D;EACvE;CAGH,MAAM,UAAU,MAAM,QAAQ,WAAW,EAAE,KAAK,CAAC;AACjD,KAAI,QAAQ,WAAW,aAAa,QAAQ,IAC1C,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,mCAAmC,QAAQ,IAAI;EACxD,OAAO,CAAC,QAAQ,MAAM;EACvB;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,yDAAyD,QAAQ,OAAO;EACjF,OAAO,CAAC,4BAA4B;EACrC"}
@@ -0,0 +1,2 @@
1
+ import type { CheckResult, DoctorContext } from '../types.js';
2
+ export declare function checkNodeVersion(_ctx: DoctorContext): Promise<CheckResult>;
@@ -0,0 +1,33 @@
1
+ //#region src/cli/commands/doctor/checks/node-version.ts
2
+ function parseNodeMajorVersion() {
3
+ const match = process.version.match(/^v(\d+)/);
4
+ return match ? parseInt(match[1], 10) : 0;
5
+ }
6
+ async function checkNodeVersion(_ctx) {
7
+ const major = parseNodeMajorVersion();
8
+ if (major === 0) return {
9
+ id: "node-version",
10
+ label: "Node.js",
11
+ status: "warn",
12
+ message: "Could not parse Node.js version.",
13
+ hints: [`process.version=${process.version}`]
14
+ };
15
+ if (major < 22) return {
16
+ id: "node-version",
17
+ label: "Node.js",
18
+ status: "fail",
19
+ message: `Node ${major} is below the required minimum (22).`,
20
+ hints: ["Install Node.js 22+ from https://nodejs.org/"]
21
+ };
22
+ return {
23
+ id: "node-version",
24
+ label: "Node.js",
25
+ status: "pass",
26
+ message: `Node.js ${process.version} meets the project requirement (>= 22).`,
27
+ hints: []
28
+ };
29
+ }
30
+ //#endregion
31
+ export { checkNodeVersion };
32
+
33
+ //# sourceMappingURL=node-version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-version.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/node-version.ts"],"sourcesContent":["import type { CheckResult, DoctorContext } from '../types.js';\n\nfunction parseNodeMajorVersion(): number {\n const match = process.version.match(/^v(\\d+)/);\n return match ? parseInt(match[1]!, 10) : 0;\n}\n\nexport async function checkNodeVersion(_ctx: DoctorContext): Promise<CheckResult> {\n const major = parseNodeMajorVersion();\n if (major === 0) {\n return {\n id: 'node-version',\n label: 'Node.js',\n status: 'warn',\n message: 'Could not parse Node.js version.',\n hints: [`process.version=${process.version}`],\n };\n }\n if (major < 22) {\n return {\n id: 'node-version',\n label: 'Node.js',\n status: 'fail',\n message: `Node ${major} is below the required minimum (22).`,\n hints: ['Install Node.js 22+ from https://nodejs.org/'],\n };\n }\n return {\n id: 'node-version',\n label: 'Node.js',\n status: 'pass',\n message: `Node.js ${process.version} meets the project requirement (>= 22).`,\n hints: [],\n };\n}\n"],"mappings":";AAEA,SAAS,wBAAgC;CACvC,MAAM,QAAQ,QAAQ,QAAQ,MAAM,UAAU;AAC9C,QAAO,QAAQ,SAAS,MAAM,IAAK,GAAG,GAAG;;AAG3C,eAAsB,iBAAiB,MAA2C;CAChF,MAAM,QAAQ,uBAAuB;AACrC,KAAI,UAAU,EACZ,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,mBAAmB,QAAQ,UAAU;EAC9C;AAEH,KAAI,QAAQ,GACV,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,QAAQ,MAAM;EACvB,OAAO,CAAC,+CAA+C;EACxD;AAEH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,WAAW,QAAQ,QAAQ;EACpC,OAAO,EAAE;EACV"}
@@ -0,0 +1,2 @@
1
+ import type { CheckResult, DoctorContext } from '../types.js';
2
+ export declare function checkProviderAuth(ctx: DoctorContext): Promise<CheckResult>;
@@ -0,0 +1,91 @@
1
+ import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
2
+ import { getAgentDefaultModelRef, init_schema, parseModelRef } from "../../../../config/schema.js";
3
+ import { init_loader, loadConfig } from "../../../../config/loader.js";
4
+ import { existsSync } from "node:fs";
5
+ //#region src/cli/commands/doctor/checks/provider-auth.ts
6
+ init_loader();
7
+ init_schema();
8
+ init_env_keys();
9
+ function collectProviderIdsFromConfig(cfg) {
10
+ const ids = /* @__PURE__ */ new Set();
11
+ const addRef = (ref) => {
12
+ if (!ref?.trim()) return;
13
+ const parsed = parseModelRef(ref.trim());
14
+ if (parsed) ids.add(parsed.provider.toLowerCase());
15
+ };
16
+ addRef(getAgentDefaultModelRef(cfg));
17
+ const raw = cfg.agents?.defaults?.model;
18
+ if (raw && typeof raw === "object" && "fallbacks" in raw && Array.isArray(raw.fallbacks)) for (const f of raw.fallbacks) addRef(typeof f === "string" ? f : void 0);
19
+ const list = cfg.agents?.list;
20
+ if (Array.isArray(list)) for (const e of list) {
21
+ const m = e?.model;
22
+ if (typeof m === "string") addRef(m);
23
+ else if (m && typeof m === "object" && "primary" in m) {
24
+ addRef(typeof m.primary === "string" ? m.primary : void 0);
25
+ const fb = m.fallbacks;
26
+ if (Array.isArray(fb)) for (const f of fb) addRef(f);
27
+ }
28
+ }
29
+ const img = cfg.agents?.defaults?.imageModel;
30
+ if (typeof img === "string") addRef(img);
31
+ else if (img && typeof img === "object" && "primary" in img) addRef(typeof img.primary === "string" ? img.primary : void 0);
32
+ const ss = cfg.agents?.defaults?.sessionSearch?.summaryModel;
33
+ if (typeof ss === "string") addRef(ss);
34
+ return ids;
35
+ }
36
+ function anyProviderEnvPresent() {
37
+ for (const vars of Object.values(PROVIDER_ENV_MAP)) for (const v of vars) if (process.env[v]?.trim()) return true;
38
+ for (const [k, val] of Object.entries(process.env)) {
39
+ if (!val?.trim()) continue;
40
+ if (k.endsWith("_API_KEY") || k.endsWith("_TOKEN")) return true;
41
+ }
42
+ return false;
43
+ }
44
+ async function checkProviderAuth(ctx) {
45
+ if (!existsSync(ctx.configPath)) return {
46
+ id: "provider-auth",
47
+ label: "Provider auth",
48
+ status: "skip",
49
+ message: "No config file; skipped.",
50
+ hints: []
51
+ };
52
+ let cfg;
53
+ try {
54
+ cfg = loadConfig(ctx.configPath);
55
+ } catch {
56
+ return {
57
+ id: "provider-auth",
58
+ label: "Provider auth",
59
+ status: "skip",
60
+ message: "Config could not be loaded; skipped.",
61
+ hints: []
62
+ };
63
+ }
64
+ const fromConfig = collectProviderIdsFromConfig(cfg);
65
+ const checkIds = fromConfig.size > 0 ? [...fromConfig] : Object.keys(PROVIDER_ENV_MAP);
66
+ for (const id of checkIds) if (getApiKeyFromEnv(id)?.trim()) return {
67
+ id: "provider-auth",
68
+ label: "Provider auth",
69
+ status: "pass",
70
+ message: "At least one LLM provider API key is available.",
71
+ hints: []
72
+ };
73
+ if (anyProviderEnvPresent()) return {
74
+ id: "provider-auth",
75
+ label: "Provider auth",
76
+ status: "pass",
77
+ message: "Environment contains provider credentials.",
78
+ hints: []
79
+ };
80
+ return {
81
+ id: "provider-auth",
82
+ label: "Provider auth",
83
+ status: "warn",
84
+ message: "No API keys detected for configured providers.",
85
+ hints: ["Set keys via: xopc auth set <provider> <key>", "Or export the provider env vars from the pi-ai docs."]
86
+ };
87
+ }
88
+ //#endregion
89
+ export { checkProviderAuth };
90
+
91
+ //# sourceMappingURL=provider-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider-auth.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/provider-auth.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport { parseModelRef, getAgentDefaultModelRef } from '../../../../config/schema.js';\nimport { getApiKeyFromEnv, PROVIDER_ENV_MAP } from '../../../../providers/env-keys.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction collectProviderIdsFromConfig(cfg: Config): Set<string> {\n const ids = new Set<string>();\n\n const addRef = (ref: string | undefined) => {\n if (!ref?.trim()) return;\n const parsed = parseModelRef(ref.trim());\n if (parsed) ids.add(parsed.provider.toLowerCase());\n };\n\n addRef(getAgentDefaultModelRef(cfg));\n\n const raw = cfg.agents?.defaults?.model;\n if (raw && typeof raw === 'object' && 'fallbacks' in raw && Array.isArray(raw.fallbacks)) {\n for (const f of raw.fallbacks) {\n addRef(typeof f === 'string' ? f : undefined);\n }\n }\n\n const list = cfg.agents?.list;\n if (Array.isArray(list)) {\n for (const e of list) {\n const m = e?.model;\n if (typeof m === 'string') addRef(m);\n else if (m && typeof m === 'object' && 'primary' in m) {\n addRef(typeof m.primary === 'string' ? m.primary : undefined);\n const fb = (m as { fallbacks?: string[] }).fallbacks;\n if (Array.isArray(fb)) {\n for (const f of fb) addRef(f);\n }\n }\n }\n }\n\n const img = cfg.agents?.defaults?.imageModel;\n if (typeof img === 'string') addRef(img);\n else if (img && typeof img === 'object' && 'primary' in img) {\n addRef(typeof img.primary === 'string' ? img.primary : undefined);\n }\n\n const ss = cfg.agents?.defaults?.sessionSearch?.summaryModel;\n if (typeof ss === 'string') addRef(ss);\n\n return ids;\n}\n\nfunction anyProviderEnvPresent(): boolean {\n for (const vars of Object.values(PROVIDER_ENV_MAP)) {\n for (const v of vars) {\n if (process.env[v]?.trim()) return true;\n }\n }\n for (const [k, val] of Object.entries(process.env)) {\n if (!val?.trim()) continue;\n if (k.endsWith('_API_KEY') || k.endsWith('_TOKEN')) return true;\n }\n return false;\n}\n\nexport async function checkProviderAuth(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'provider-auth',\n label: 'Provider auth',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'provider-auth',\n label: 'Provider auth',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const fromConfig = collectProviderIdsFromConfig(cfg);\n const checkIds = fromConfig.size > 0 ? [...fromConfig] : Object.keys(PROVIDER_ENV_MAP);\n\n for (const id of checkIds) {\n const key = getApiKeyFromEnv(id);\n if (key?.trim()) {\n return {\n id: 'provider-auth',\n label: 'Provider auth',\n status: 'pass',\n message: 'At least one LLM provider API key is available.',\n hints: [],\n };\n }\n }\n\n if (anyProviderEnvPresent()) {\n return {\n id: 'provider-auth',\n label: 'Provider auth',\n status: 'pass',\n message: 'Environment contains provider credentials.',\n hints: [],\n };\n }\n\n return {\n id: 'provider-auth',\n label: 'Provider auth',\n status: 'warn',\n message: 'No API keys detected for configured providers.',\n hints: ['Set keys via: xopc auth set <provider> <key>', 'Or export the provider env vars from the pi-ai docs.'],\n };\n}\n"],"mappings":";;;;;aAE0D;aAE4B;eACC;AAGvF,SAAS,6BAA6B,KAA0B;CAC9D,MAAM,sBAAM,IAAI,KAAa;CAE7B,MAAM,UAAU,QAA4B;AAC1C,MAAI,CAAC,KAAK,MAAM,CAAE;EAClB,MAAM,SAAS,cAAc,IAAI,MAAM,CAAC;AACxC,MAAI,OAAQ,KAAI,IAAI,OAAO,SAAS,aAAa,CAAC;;AAGpD,QAAO,wBAAwB,IAAI,CAAC;CAEpC,MAAM,MAAM,IAAI,QAAQ,UAAU;AAClC,KAAI,OAAO,OAAO,QAAQ,YAAY,eAAe,OAAO,MAAM,QAAQ,IAAI,UAAU,CACtF,MAAK,MAAM,KAAK,IAAI,UAClB,QAAO,OAAO,MAAM,WAAW,IAAI,KAAA,EAAU;CAIjD,MAAM,OAAO,IAAI,QAAQ;AACzB,KAAI,MAAM,QAAQ,KAAK,CACrB,MAAK,MAAM,KAAK,MAAM;EACpB,MAAM,IAAI,GAAG;AACb,MAAI,OAAO,MAAM,SAAU,QAAO,EAAE;WAC3B,KAAK,OAAO,MAAM,YAAY,aAAa,GAAG;AACrD,UAAO,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU,KAAA,EAAU;GAC7D,MAAM,KAAM,EAA+B;AAC3C,OAAI,MAAM,QAAQ,GAAG,CACnB,MAAK,MAAM,KAAK,GAAI,QAAO,EAAE;;;CAMrC,MAAM,MAAM,IAAI,QAAQ,UAAU;AAClC,KAAI,OAAO,QAAQ,SAAU,QAAO,IAAI;UAC/B,OAAO,OAAO,QAAQ,YAAY,aAAa,IACtD,QAAO,OAAO,IAAI,YAAY,WAAW,IAAI,UAAU,KAAA,EAAU;CAGnE,MAAM,KAAK,IAAI,QAAQ,UAAU,eAAe;AAChD,KAAI,OAAO,OAAO,SAAU,QAAO,GAAG;AAEtC,QAAO;;AAGT,SAAS,wBAAiC;AACxC,MAAK,MAAM,QAAQ,OAAO,OAAO,iBAAiB,CAChD,MAAK,MAAM,KAAK,KACd,KAAI,QAAQ,IAAI,IAAI,MAAM,CAAE,QAAO;AAGvC,MAAK,MAAM,CAAC,GAAG,QAAQ,OAAO,QAAQ,QAAQ,IAAI,EAAE;AAClD,MAAI,CAAC,KAAK,MAAM,CAAE;AAClB,MAAI,EAAE,SAAS,WAAW,IAAI,EAAE,SAAS,SAAS,CAAE,QAAO;;AAE7D,QAAO;;AAGT,eAAsB,kBAAkB,KAA0C;AAChF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,aAAa,6BAA6B,IAAI;CACpD,MAAM,WAAW,WAAW,OAAO,IAAI,CAAC,GAAG,WAAW,GAAG,OAAO,KAAK,iBAAiB;AAEtF,MAAK,MAAM,MAAM,SAEf,KADY,iBAAiB,GAAG,EACvB,MAAM,CACb,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAIL,KAAI,uBAAuB,CACzB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,gDAAgD,uDAAuD;EAChH"}
@@ -0,0 +1,2 @@
1
+ import type { CheckResult, DoctorContext } from '../types.js';
2
+ export declare function checkSecurityAudit(ctx: DoctorContext): Promise<CheckResult>;
@@ -0,0 +1,85 @@
1
+ import { init_loader, loadConfig } from "../../../../config/loader.js";
2
+ import { existsSync, statSync } from "node:fs";
3
+ //#region src/cli/commands/doctor/checks/security-audit.ts
4
+ init_loader();
5
+ function isLoopbackHost(host) {
6
+ const normalized = host.trim().toLowerCase();
7
+ return normalized === "127.0.0.1" || normalized === "localhost" || normalized === "::1" || normalized === "0:0:0:0:0:0:0:1";
8
+ }
9
+ function isAllInterfaces(host) {
10
+ const n = host.trim();
11
+ return n === "0.0.0.0" || n === "::" || n === "*";
12
+ }
13
+ async function checkSecurityAudit(ctx) {
14
+ if (!existsSync(ctx.configPath)) return {
15
+ id: "security-audit",
16
+ label: "Security",
17
+ status: "skip",
18
+ message: "No config file; skipped.",
19
+ hints: []
20
+ };
21
+ let cfg;
22
+ try {
23
+ cfg = loadConfig(ctx.configPath);
24
+ } catch {
25
+ return {
26
+ id: "security-audit",
27
+ label: "Security",
28
+ status: "skip",
29
+ message: "Config could not be loaded; skipped.",
30
+ hints: []
31
+ };
32
+ }
33
+ const hints = [];
34
+ const host = cfg.gateway?.host?.trim() || "127.0.0.1";
35
+ const auth = cfg.gateway?.auth;
36
+ const mode = auth?.mode ?? "token";
37
+ const token = auth?.token?.trim() ?? "";
38
+ if (isAllInterfaces(host) && (mode === "none" || !token)) return {
39
+ id: "security-audit",
40
+ label: "Security",
41
+ status: "fail",
42
+ message: "Gateway is bound to all interfaces without token authentication (critical).",
43
+ hints: ["Set gateway.host to 127.0.0.1 or enable gateway.auth (token).", "Do not expose an unauthenticated gateway on the network."]
44
+ };
45
+ if (isAllInterfaces(host) && mode !== "none" && token) hints.push("Listening on all network interfaces; prefer 127.0.0.1 or firewall rules if the token could leak.");
46
+ if (!isLoopbackHost(host) && !isAllInterfaces(host)) {
47
+ if (mode === "none" || !token) return {
48
+ id: "security-audit",
49
+ label: "Security",
50
+ status: "fail",
51
+ message: "Gateway is reachable on a non-loopback address without authentication.",
52
+ hints: ["Use gateway.auth.mode \"token\" and set gateway.auth.token, or bind to loopback only."]
53
+ };
54
+ hints.push("Non-loopback bind is safer with a strong token and firewall rules.");
55
+ }
56
+ if (isLoopbackHost(host) && (mode === "none" || !token)) return {
57
+ id: "security-audit",
58
+ label: "Security",
59
+ status: "warn",
60
+ message: "Gateway has no token auth (loopback only).",
61
+ hints: ["Consider gateway.auth.token for defense in depth."]
62
+ };
63
+ if (token.length > 0 && token.length < 16) hints.push("Auth token is shorter than 16 characters; use a longer random token.");
64
+ if (process.platform !== "win32") try {
65
+ if (statSync(ctx.configPath).mode & 63) hints.push("Config file is group/world-readable; consider chmod 600 (contains secrets).");
66
+ } catch {}
67
+ if (hints.length > 0) return {
68
+ id: "security-audit",
69
+ label: "Security",
70
+ status: "warn",
71
+ message: "Non-critical security recommendations.",
72
+ hints
73
+ };
74
+ return {
75
+ id: "security-audit",
76
+ label: "Security",
77
+ status: "pass",
78
+ message: "No critical gateway exposure issues detected.",
79
+ hints: []
80
+ };
81
+ }
82
+ //#endregion
83
+ export { checkSecurityAudit };
84
+
85
+ //# sourceMappingURL=security-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-audit.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/security-audit.ts"],"sourcesContent":["import { existsSync, statSync } from 'node:fs';\n\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction isLoopbackHost(host: string): boolean {\n const normalized = host.trim().toLowerCase();\n return (\n normalized === '127.0.0.1' ||\n normalized === 'localhost' ||\n normalized === '::1' ||\n normalized === '0:0:0:0:0:0:0:1'\n );\n}\n\nfunction isAllInterfaces(host: string): boolean {\n const n = host.trim();\n return n === '0.0.0.0' || n === '::' || n === '*';\n}\n\nexport async function checkSecurityAudit(ctx: DoctorContext): Promise<CheckResult> {\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'security-audit',\n label: 'Security',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let cfg: Config;\n try {\n cfg = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'security-audit',\n label: 'Security',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const hints: string[] = [];\n const host = cfg.gateway?.host?.trim() || '127.0.0.1';\n const auth = cfg.gateway?.auth;\n const mode = auth?.mode ?? 'token';\n const token = auth?.token?.trim() ?? '';\n\n if (isAllInterfaces(host) && (mode === 'none' || !token)) {\n return {\n id: 'security-audit',\n label: 'Security',\n status: 'fail',\n message: 'Gateway is bound to all interfaces without token authentication (critical).',\n hints: [\n 'Set gateway.host to 127.0.0.1 or enable gateway.auth (token).',\n 'Do not expose an unauthenticated gateway on the network.',\n ],\n };\n }\n\n if (isAllInterfaces(host) && mode !== 'none' && token) {\n hints.push('Listening on all network interfaces; prefer 127.0.0.1 or firewall rules if the token could leak.');\n }\n\n if (!isLoopbackHost(host) && !isAllInterfaces(host)) {\n if (mode === 'none' || !token) {\n return {\n id: 'security-audit',\n label: 'Security',\n status: 'fail',\n message: 'Gateway is reachable on a non-loopback address without authentication.',\n hints: ['Use gateway.auth.mode \"token\" and set gateway.auth.token, or bind to loopback only.'],\n };\n }\n hints.push('Non-loopback bind is safer with a strong token and firewall rules.');\n }\n\n if (isLoopbackHost(host) && (mode === 'none' || !token)) {\n return {\n id: 'security-audit',\n label: 'Security',\n status: 'warn',\n message: 'Gateway has no token auth (loopback only).',\n hints: ['Consider gateway.auth.token for defense in depth.'],\n };\n }\n\n if (token.length > 0 && token.length < 16) {\n hints.push('Auth token is shorter than 16 characters; use a longer random token.');\n }\n\n if (process.platform !== 'win32') {\n try {\n const st = statSync(ctx.configPath);\n const perms = st.mode & 0o777;\n if (perms & 0o077) {\n hints.push('Config file is group/world-readable; consider chmod 600 (contains secrets).');\n }\n } catch {\n /* ignore */\n }\n }\n\n if (hints.length > 0) {\n return {\n id: 'security-audit',\n label: 'Security',\n status: 'warn',\n message: 'Non-critical security recommendations.',\n hints,\n };\n }\n\n return {\n id: 'security-audit',\n label: 'Security',\n status: 'pass',\n message: 'No critical gateway exposure issues detected.',\n hints: [],\n };\n}\n"],"mappings":";;;aAE0D;AAI1D,SAAS,eAAe,MAAuB;CAC7C,MAAM,aAAa,KAAK,MAAM,CAAC,aAAa;AAC5C,QACE,eAAe,eACf,eAAe,eACf,eAAe,SACf,eAAe;;AAInB,SAAS,gBAAgB,MAAuB;CAC9C,MAAM,IAAI,KAAK,MAAM;AACrB,QAAO,MAAM,aAAa,MAAM,QAAQ,MAAM;;AAGhD,eAAsB,mBAAmB,KAA0C;AACjF,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,QAAM,WAAW,IAAI,WAAW;SAC1B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,QAAkB,EAAE;CAC1B,MAAM,OAAO,IAAI,SAAS,MAAM,MAAM,IAAI;CAC1C,MAAM,OAAO,IAAI,SAAS;CAC1B,MAAM,OAAO,MAAM,QAAQ;CAC3B,MAAM,QAAQ,MAAM,OAAO,MAAM,IAAI;AAErC,KAAI,gBAAgB,KAAK,KAAK,SAAS,UAAU,CAAC,OAChD,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CACL,iEACA,2DACD;EACF;AAGH,KAAI,gBAAgB,KAAK,IAAI,SAAS,UAAU,MAC9C,OAAM,KAAK,mGAAmG;AAGhH,KAAI,CAAC,eAAe,KAAK,IAAI,CAAC,gBAAgB,KAAK,EAAE;AACnD,MAAI,SAAS,UAAU,CAAC,MACtB,QAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,wFAAsF;GAC/F;AAEH,QAAM,KAAK,qEAAqE;;AAGlF,KAAI,eAAe,KAAK,KAAK,SAAS,UAAU,CAAC,OAC/C,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,oDAAoD;EAC7D;AAGH,KAAI,MAAM,SAAS,KAAK,MAAM,SAAS,GACrC,OAAM,KAAK,uEAAuE;AAGpF,KAAI,QAAQ,aAAa,QACvB,KAAI;AAGF,MAFW,SAAS,IAAI,WAAW,CAClB,OAAA,GAEf,OAAM,KAAK,8EAA8E;SAErF;AAKV,KAAI,MAAM,SAAS,EACjB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT;EACD;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV"}
@@ -0,0 +1,2 @@
1
+ import type { CheckResult, DoctorContext } from '../types.js';
2
+ export declare function checkSessionIntegrity(ctx: DoctorContext): Promise<CheckResult>;
@@ -0,0 +1,118 @@
1
+ import { init_agent_scope, resolveDefaultAgentId } from "../../../../agent/agent-scope.js";
2
+ import { init_paths, resolveSessionsDir, resolveSessionsIndexPath } from "../../../../config/paths.js";
3
+ import { init_loader, loadConfig } from "../../../../config/loader.js";
4
+ import { resolveSessionShardRelativePath } from "../../../../session/shard-path.js";
5
+ import { join } from "node:path";
6
+ import { existsSync, readFileSync, readdirSync } from "node:fs";
7
+ //#region src/cli/commands/doctor/checks/session-integrity.ts
8
+ init_agent_scope();
9
+ init_loader();
10
+ init_paths();
11
+ function sanitizeSessionKeyToFileStem(key) {
12
+ return key.replace(/[^a-zA-Z0-9_-]/g, "_");
13
+ }
14
+ function findSessionFileInDir(baseDir, safeStem) {
15
+ if (!existsSync(baseDir)) return false;
16
+ const entries = readdirSync(baseDir, { withFileTypes: true });
17
+ for (const entry of entries) {
18
+ if (entry.isFile() && entry.name === `${safeStem}.json`) return true;
19
+ if (entry.isDirectory() && entry.name !== "archive") {
20
+ if (findSessionFileInDir(join(baseDir, entry.name), safeStem)) return true;
21
+ }
22
+ }
23
+ return false;
24
+ }
25
+ function transcriptExists(sessionsDir, key) {
26
+ const safeStem = sanitizeSessionKeyToFileStem(key);
27
+ if (existsSync(join(sessionsDir, resolveSessionShardRelativePath(key), `${safeStem}.json`))) return true;
28
+ return findSessionFileInDir(sessionsDir, safeStem);
29
+ }
30
+ async function checkSessionIntegrity(ctx) {
31
+ if (!ctx.options.deep) return {
32
+ id: "session-integrity",
33
+ label: "Sessions",
34
+ status: "skip",
35
+ message: "Deep mode off; session scan skipped.",
36
+ hints: ["Run: xopc doctor --deep"]
37
+ };
38
+ if (!existsSync(ctx.configPath)) return {
39
+ id: "session-integrity",
40
+ label: "Sessions",
41
+ status: "skip",
42
+ message: "No config file; skipped.",
43
+ hints: []
44
+ };
45
+ let config;
46
+ try {
47
+ config = loadConfig(ctx.configPath);
48
+ } catch {
49
+ return {
50
+ id: "session-integrity",
51
+ label: "Sessions",
52
+ status: "skip",
53
+ message: "Config could not be loaded; skipped.",
54
+ hints: []
55
+ };
56
+ }
57
+ const agentId = resolveDefaultAgentId(config);
58
+ const indexPath = resolveSessionsIndexPath(config, agentId);
59
+ const sessionsDir = resolveSessionsDir(config, agentId);
60
+ if (!existsSync(sessionsDir)) return {
61
+ id: "session-integrity",
62
+ label: "Sessions",
63
+ status: "warn",
64
+ message: "Sessions directory is missing.",
65
+ hints: [sessionsDir]
66
+ };
67
+ if (!existsSync(indexPath)) return {
68
+ id: "session-integrity",
69
+ label: "Sessions",
70
+ status: "warn",
71
+ message: "Session index file is missing.",
72
+ hints: [indexPath]
73
+ };
74
+ let index;
75
+ try {
76
+ index = JSON.parse(readFileSync(indexPath, "utf-8"));
77
+ } catch {
78
+ return {
79
+ id: "session-integrity",
80
+ label: "Sessions",
81
+ status: "warn",
82
+ message: "Session index is not valid JSON.",
83
+ hints: [indexPath]
84
+ };
85
+ }
86
+ const sample = [...Array.isArray(index.sessions) ? index.sessions : []].sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()).slice(0, 20);
87
+ if (sample.length === 0) return {
88
+ id: "session-integrity",
89
+ label: "Sessions",
90
+ status: "pass",
91
+ message: "Session index is valid; no sessions to sample.",
92
+ hints: []
93
+ };
94
+ const missing = [];
95
+ for (const s of sample) {
96
+ const key = s.key?.trim();
97
+ if (!key) continue;
98
+ if (!transcriptExists(sessionsDir, key)) missing.push(key);
99
+ }
100
+ if (missing.length > 0) return {
101
+ id: "session-integrity",
102
+ label: "Sessions",
103
+ status: "warn",
104
+ message: `${missing.length} of ${sample.length} sampled session transcripts are missing on disk.`,
105
+ hints: missing.slice(0, 5).map((k) => `Missing transcript for: ${k}`)
106
+ };
107
+ return {
108
+ id: "session-integrity",
109
+ label: "Sessions",
110
+ status: "pass",
111
+ message: `Sampled ${sample.length} recent session(s); transcript files are present.`,
112
+ hints: []
113
+ };
114
+ }
115
+ //#endregion
116
+ export { checkSessionIntegrity };
117
+
118
+ //# sourceMappingURL=session-integrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-integrity.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/session-integrity.ts"],"sourcesContent":["import { existsSync, readFileSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { resolveDefaultAgentId } from '../../../../agent/agent-scope.js';\nimport { loadConfig } from '../../../../config/loader.js';\nimport { resolveSessionsDir, resolveSessionsIndexPath } from '../../../../config/paths.js';\nimport { resolveSessionShardRelativePath } from '../../../../session/shard-path.js';\nimport type { SessionIndex, SessionMetadata } from '../../../../session/types.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction sanitizeSessionKeyToFileStem(key: string): string {\n return key.replace(/[^a-zA-Z0-9_-]/g, '_');\n}\n\nfunction findSessionFileInDir(baseDir: string, safeStem: string): boolean {\n if (!existsSync(baseDir)) return false;\n const entries = readdirSync(baseDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isFile() && entry.name === `${safeStem}.json`) return true;\n if (entry.isDirectory() && entry.name !== 'archive') {\n if (findSessionFileInDir(join(baseDir, entry.name), safeStem)) return true;\n }\n }\n return false;\n}\n\nfunction transcriptExists(sessionsDir: string, key: string): boolean {\n const safeStem = sanitizeSessionKeyToFileStem(key);\n const shard = resolveSessionShardRelativePath(key);\n const primary = join(sessionsDir, shard, `${safeStem}.json`);\n if (existsSync(primary)) return true;\n return findSessionFileInDir(sessionsDir, safeStem);\n}\n\nexport async function checkSessionIntegrity(ctx: DoctorContext): Promise<CheckResult> {\n if (!ctx.options.deep) {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'skip',\n message: 'Deep mode off; session scan skipped.',\n hints: ['Run: xopc doctor --deep'],\n };\n }\n\n if (!existsSync(ctx.configPath)) {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'skip',\n message: 'No config file; skipped.',\n hints: [],\n };\n }\n\n let config;\n try {\n config = loadConfig(ctx.configPath);\n } catch {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'skip',\n message: 'Config could not be loaded; skipped.',\n hints: [],\n };\n }\n\n const agentId = resolveDefaultAgentId(config);\n const indexPath = resolveSessionsIndexPath(config, agentId);\n const sessionsDir = resolveSessionsDir(config, agentId);\n\n if (!existsSync(sessionsDir)) {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'warn',\n message: 'Sessions directory is missing.',\n hints: [sessionsDir],\n };\n }\n\n if (!existsSync(indexPath)) {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'warn',\n message: 'Session index file is missing.',\n hints: [indexPath],\n };\n }\n\n let index: SessionIndex;\n try {\n index = JSON.parse(readFileSync(indexPath, 'utf-8')) as SessionIndex;\n } catch {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'warn',\n message: 'Session index is not valid JSON.',\n hints: [indexPath],\n };\n }\n\n const sessions: SessionMetadata[] = Array.isArray(index.sessions) ? index.sessions : [];\n const sorted = [...sessions].sort(\n (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime(),\n );\n const sample = sorted.slice(0, 20);\n if (sample.length === 0) {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'pass',\n message: 'Session index is valid; no sessions to sample.',\n hints: [],\n };\n }\n\n const missing: string[] = [];\n for (const s of sample) {\n const key = s.key?.trim();\n if (!key) continue;\n if (!transcriptExists(sessionsDir, key)) {\n missing.push(key);\n }\n }\n\n if (missing.length > 0) {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'warn',\n message: `${missing.length} of ${sample.length} sampled session transcripts are missing on disk.`,\n hints: missing.slice(0, 5).map((k) => `Missing transcript for: ${k}`),\n };\n }\n\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'pass',\n message: `Sampled ${sample.length} recent session(s); transcript files are present.`,\n hints: [],\n };\n}\n"],"mappings":";;;;;;;kBAGyE;aACf;YACiC;AAK3F,SAAS,6BAA6B,KAAqB;AACzD,QAAO,IAAI,QAAQ,mBAAmB,IAAI;;AAG5C,SAAS,qBAAqB,SAAiB,UAA2B;AACxE,KAAI,CAAC,WAAW,QAAQ,CAAE,QAAO;CACjC,MAAM,UAAU,YAAY,SAAS,EAAE,eAAe,MAAM,CAAC;AAC7D,MAAK,MAAM,SAAS,SAAS;AAC3B,MAAI,MAAM,QAAQ,IAAI,MAAM,SAAS,GAAG,SAAS,OAAQ,QAAO;AAChE,MAAI,MAAM,aAAa,IAAI,MAAM,SAAS;OACpC,qBAAqB,KAAK,SAAS,MAAM,KAAK,EAAE,SAAS,CAAE,QAAO;;;AAG1E,QAAO;;AAGT,SAAS,iBAAiB,aAAqB,KAAsB;CACnE,MAAM,WAAW,6BAA6B,IAAI;AAGlD,KAAI,WADY,KAAK,aADP,gCAAgC,IAAI,EACT,GAAG,SAAS,OAAO,CACrC,CAAE,QAAO;AAChC,QAAO,qBAAqB,aAAa,SAAS;;AAGpD,eAAsB,sBAAsB,KAA0C;AACpF,KAAI,CAAC,IAAI,QAAQ,KACf,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,0BAA0B;EACnC;AAGH,KAAI,CAAC,WAAW,IAAI,WAAW,CAC7B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,IAAI;AACJ,KAAI;AACF,WAAS,WAAW,IAAI,WAAW;SAC7B;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,EAAE;GACV;;CAGH,MAAM,UAAU,sBAAsB,OAAO;CAC7C,MAAM,YAAY,yBAAyB,QAAQ,QAAQ;CAC3D,MAAM,cAAc,mBAAmB,QAAQ,QAAQ;AAEvD,KAAI,CAAC,WAAW,YAAY,CAC1B,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,YAAY;EACrB;AAGH,KAAI,CAAC,WAAW,UAAU,CACxB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,UAAU;EACnB;CAGH,IAAI;AACJ,KAAI;AACF,UAAQ,KAAK,MAAM,aAAa,WAAW,QAAQ,CAAC;SAC9C;AACN,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO,CAAC,UAAU;GACnB;;CAOH,MAAM,SAHS,CAAC,GADoB,MAAM,QAAQ,MAAM,SAAS,GAAG,MAAM,WAAW,EAAE,CAC3D,CAAC,MAC1B,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,CAC5E,CACqB,MAAM,GAAG,GAAG;AAClC,KAAI,OAAO,WAAW,EACpB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,EAAE;EACV;CAGH,MAAM,UAAoB,EAAE;AAC5B,MAAK,MAAM,KAAK,QAAQ;EACtB,MAAM,MAAM,EAAE,KAAK,MAAM;AACzB,MAAI,CAAC,IAAK;AACV,MAAI,CAAC,iBAAiB,aAAa,IAAI,CACrC,SAAQ,KAAK,IAAI;;AAIrB,KAAI,QAAQ,SAAS,EACnB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,GAAG,QAAQ,OAAO,MAAM,OAAO,OAAO;EAC/C,OAAO,QAAQ,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM,2BAA2B,IAAI;EACtE;AAGH,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS,WAAW,OAAO,OAAO;EAClC,OAAO,EAAE;EACV"}
@@ -0,0 +1,2 @@
1
+ import type { CheckResult, DoctorContext } from '../types.js';
2
+ export declare function checkStateIntegrity(ctx: DoctorContext): Promise<CheckResult>;
@@ -0,0 +1,99 @@
1
+ import { join } from "node:path";
2
+ import { accessSync, chmodSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
3
+ //#region src/cli/commands/doctor/checks/state-integrity.ts
4
+ function isWritable(dir) {
5
+ try {
6
+ accessSync(dir, constants.W_OK);
7
+ return true;
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ async function checkStateIntegrity(ctx) {
13
+ const root = ctx.stateDir;
14
+ const hints = [];
15
+ if (!existsSync(root)) {
16
+ if (ctx.options.fix) try {
17
+ mkdirSync(root, {
18
+ recursive: true,
19
+ mode: 448
20
+ });
21
+ if (process.platform !== "win32") chmodSync(root, 448);
22
+ return {
23
+ id: "state-integrity",
24
+ label: "State directory",
25
+ status: "pass",
26
+ message: "Created state directory with safe permissions.",
27
+ hints: [root],
28
+ fixed: true
29
+ };
30
+ } catch (e) {
31
+ return {
32
+ id: "state-integrity",
33
+ label: "State directory",
34
+ status: "fail",
35
+ message: `State directory missing and could not create: ${e instanceof Error ? e.message : String(e)}`,
36
+ hints: [root]
37
+ };
38
+ }
39
+ return {
40
+ id: "state-integrity",
41
+ label: "State directory",
42
+ status: "fail",
43
+ message: "State directory does not exist.",
44
+ hints: [
45
+ `Expected: ${root}`,
46
+ "Run: xopc init",
47
+ "Or: xopc doctor --fix"
48
+ ]
49
+ };
50
+ }
51
+ if (!isWritable(root)) return {
52
+ id: "state-integrity",
53
+ label: "State directory",
54
+ status: "fail",
55
+ message: "State directory is not writable.",
56
+ hints: [root]
57
+ };
58
+ if (process.platform !== "win32") try {
59
+ if ((statSync(root).mode & 511) !== 448) {
60
+ if (ctx.options.fix) {
61
+ chmodSync(root, 448);
62
+ return {
63
+ id: "state-integrity",
64
+ label: "State directory",
65
+ status: "pass",
66
+ message: "State directory permissions set to 700.",
67
+ hints: [root],
68
+ fixed: true
69
+ };
70
+ }
71
+ return {
72
+ id: "state-integrity",
73
+ label: "State directory",
74
+ status: "warn",
75
+ message: "State directory permissions are not 700 (recommended for privacy).",
76
+ hints: [root, "Run: xopc doctor --fix"]
77
+ };
78
+ }
79
+ } catch {}
80
+ const agentsDir = join(root, "agents");
81
+ if (!existsSync(agentsDir) && ctx.options.fix) try {
82
+ mkdirSync(agentsDir, {
83
+ recursive: true,
84
+ mode: 448
85
+ });
86
+ hints.push(`Created: ${agentsDir}`);
87
+ } catch {}
88
+ return {
89
+ id: "state-integrity",
90
+ label: "State directory",
91
+ status: "pass",
92
+ message: "State directory exists and is usable.",
93
+ hints: hints.length ? hints : [root]
94
+ };
95
+ }
96
+ //#endregion
97
+ export { checkStateIntegrity };
98
+
99
+ //# sourceMappingURL=state-integrity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"state-integrity.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/state-integrity.ts"],"sourcesContent":["import { existsSync, mkdirSync, chmodSync, accessSync, constants, statSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport type { CheckResult, DoctorContext } from '../types.js';\n\nfunction isWritable(dir: string): boolean {\n try {\n accessSync(dir, constants.W_OK);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function checkStateIntegrity(ctx: DoctorContext): Promise<CheckResult> {\n const root = ctx.stateDir;\n const hints: string[] = [];\n\n if (!existsSync(root)) {\n if (ctx.options.fix) {\n try {\n mkdirSync(root, { recursive: true, mode: 0o700 });\n if (process.platform !== 'win32') {\n chmodSync(root, 0o700);\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'Created state directory with safe permissions.',\n hints: [root],\n fixed: true,\n };\n } catch (e) {\n const msg = e instanceof Error ? e.message : String(e);\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: `State directory missing and could not create: ${msg}`,\n hints: [root],\n };\n }\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: 'State directory does not exist.',\n hints: [`Expected: ${root}`, 'Run: xopc init', 'Or: xopc doctor --fix'],\n };\n }\n\n if (!isWritable(root)) {\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'fail',\n message: 'State directory is not writable.',\n hints: [root],\n };\n }\n\n if (process.platform !== 'win32') {\n try {\n const mode = statSync(root).mode & 0o777;\n if (mode !== 0o700) {\n if (ctx.options.fix) {\n chmodSync(root, 0o700);\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'State directory permissions set to 700.',\n hints: [root],\n fixed: true,\n };\n }\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'warn',\n message: 'State directory permissions are not 700 (recommended for privacy).',\n hints: [root, 'Run: xopc doctor --fix'],\n };\n }\n } catch {\n /* ignore stat errors */\n }\n }\n\n const agentsDir = join(root, 'agents');\n if (!existsSync(agentsDir) && ctx.options.fix) {\n try {\n mkdirSync(agentsDir, { recursive: true, mode: 0o700 });\n hints.push(`Created: ${agentsDir}`);\n } catch {\n /* best-effort */\n }\n }\n\n return {\n id: 'state-integrity',\n label: 'State directory',\n status: 'pass',\n message: 'State directory exists and is usable.',\n hints: hints.length ? hints : [root],\n };\n}\n"],"mappings":";;;AAKA,SAAS,WAAW,KAAsB;AACxC,KAAI;AACF,aAAW,KAAK,UAAU,KAAK;AAC/B,SAAO;SACD;AACN,SAAO;;;AAIX,eAAsB,oBAAoB,KAA0C;CAClF,MAAM,OAAO,IAAI;CACjB,MAAM,QAAkB,EAAE;AAE1B,KAAI,CAAC,WAAW,KAAK,EAAE;AACrB,MAAI,IAAI,QAAQ,IACd,KAAI;AACF,aAAU,MAAM;IAAE,WAAW;IAAM,MAAM;IAAO,CAAC;AACjD,OAAI,QAAQ,aAAa,QACvB,WAAU,MAAM,IAAM;AAExB,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,KAAK;IACb,OAAO;IACR;WACM,GAAG;AAEV,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS,iDALC,aAAa,QAAQ,EAAE,UAAU,OAAO,EAAE;IAMpD,OAAO,CAAC,KAAK;IACd;;AAGL,SAAO;GACL,IAAI;GACJ,OAAO;GACP,QAAQ;GACR,SAAS;GACT,OAAO;IAAC,aAAa;IAAQ;IAAkB;IAAwB;GACxE;;AAGH,KAAI,CAAC,WAAW,KAAK,CACnB,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,CAAC,KAAK;EACd;AAGH,KAAI,QAAQ,aAAa,QACvB,KAAI;AAEF,OADa,SAAS,KAAK,CAAC,OAAO,SACtB,KAAO;AAClB,OAAI,IAAI,QAAQ,KAAK;AACnB,cAAU,MAAM,IAAM;AACtB,WAAO;KACL,IAAI;KACJ,OAAO;KACP,QAAQ;KACR,SAAS;KACT,OAAO,CAAC,KAAK;KACb,OAAO;KACR;;AAEH,UAAO;IACL,IAAI;IACJ,OAAO;IACP,QAAQ;IACR,SAAS;IACT,OAAO,CAAC,MAAM,yBAAyB;IACxC;;SAEG;CAKV,MAAM,YAAY,KAAK,MAAM,SAAS;AACtC,KAAI,CAAC,WAAW,UAAU,IAAI,IAAI,QAAQ,IACxC,KAAI;AACF,YAAU,WAAW;GAAE,WAAW;GAAM,MAAM;GAAO,CAAC;AACtD,QAAM,KAAK,YAAY,YAAY;SAC7B;AAKV,QAAO;EACL,IAAI;EACJ,OAAO;EACP,QAAQ;EACR,SAAS;EACT,OAAO,MAAM,SAAS,QAAQ,CAAC,KAAK;EACrC"}
@@ -0,0 +1,2 @@
1
+ import type { CheckResult, DoctorContext } from '../types.js';
2
+ export declare function checkVersionUpdate(_ctx: DoctorContext): Promise<CheckResult>;