@xopcai/xopc 0.0.88 → 0.0.89

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 (301) hide show
  1. package/README.md +8 -1
  2. package/README.zh-CN.md +8 -1
  3. package/dist/browser-ext/manifest.json +1 -1
  4. package/dist/extensions/feishu/src/outbound/media-load.js +1 -1
  5. package/dist/extensions/feishu/src/workflow-progress.js +1 -1
  6. package/dist/extensions/telegram/src/plugin.js +1 -1
  7. package/dist/extensions/telegram/src/routing-integration.js +2 -2
  8. package/dist/extensions/telegram/src/workflow-progress.js +1 -1
  9. package/dist/extensions/telegram/xopc.extension.json +1 -1
  10. package/dist/extensions/weixin/src/api/api.js +2 -2
  11. package/dist/extensions/weixin/src/auth/accounts.js +1 -1
  12. package/dist/extensions/weixin/src/cdn/upload.js +1 -1
  13. package/dist/extensions/weixin/src/media/data-url.js +1 -1
  14. package/dist/extensions/weixin/src/messaging/debug-mode.js +1 -1
  15. package/dist/extensions/weixin/src/messaging/inbound.js +1 -1
  16. package/dist/extensions/weixin/src/messaging/process-message.js +1 -1
  17. package/dist/extensions/weixin/src/plugin.js +1 -1
  18. package/dist/extensions/weixin/src/storage/sync-buf.js +1 -1
  19. package/dist/extensions/weixin/src/workflow-progress.js +1 -1
  20. package/dist/gateway/static/root/assets/agents-B6PJB07W.js +222 -0
  21. package/dist/gateway/static/root/assets/apps-page-BOr0B1wv.js +1 -0
  22. package/dist/gateway/static/root/assets/channels-settings-BelUKggl.js +1 -0
  23. package/dist/gateway/static/root/assets/{channels-status-swr-DIsl75Y3.js → channels-status-swr-DaHGkRF1.js} +1 -1
  24. package/dist/gateway/static/root/assets/cron-api-CjOg-BIj.js +1 -0
  25. package/dist/gateway/static/root/assets/cron-page-DhoZmZXb.js +1 -0
  26. package/dist/gateway/static/root/assets/{dist-CJwfHYvT.js → dist-6LecgDx5.js} +1 -1
  27. package/dist/gateway/static/root/assets/{extension-debug-page-BVJohZoZ.js → extension-debug-page-CtuKJ9tE.js} +1 -1
  28. package/dist/gateway/static/root/assets/{extension-page-BT2tmElC.js → extension-page-ykzjOkR5.js} +1 -1
  29. package/dist/gateway/static/root/assets/{extension-settings-page-BSS47c2j.js → extension-settings-page-Ce2qrdpO.js} +1 -1
  30. package/dist/gateway/static/root/assets/{fetch-BaFNUtkE.js → fetch-C9FFJjuH.js} +1 -1
  31. package/dist/gateway/static/root/assets/{field-primitives-QwYEq6Hz.js → field-primitives-BFcrNeTU.js} +1 -1
  32. package/dist/gateway/static/root/assets/{heartbeat-config-api-BVSidEDJ.js → heartbeat-config-api-CEg4Vr9R.js} +1 -1
  33. package/dist/gateway/static/root/assets/{index-qNrVJp-y.js → index-CZfy9oxs.js} +97 -97
  34. package/dist/gateway/static/root/assets/index-CiN1cQiQ.css +1 -0
  35. package/dist/gateway/static/root/assets/logs-page-BwWLfqvd.js +1 -0
  36. package/dist/gateway/static/root/assets/sessions-page-DV5WN8uk.js +1 -0
  37. package/dist/gateway/static/root/assets/{settings-form-section-B8N3A3Zo.js → settings-form-section-BqdzA28u.js} +1 -1
  38. package/dist/gateway/static/root/assets/settings-page-CfOBRbPX.js +3 -0
  39. package/dist/gateway/static/root/assets/{share-preview-page-Q7KqkO-u.js → share-preview-page-Di5Bzh4g.js} +1 -1
  40. package/dist/gateway/static/root/assets/skills-page-D0H5Kaxg.js +2 -0
  41. package/dist/gateway/static/root/assets/{theme-store-BbRc5ugR.js → theme-store-CNqbmTNV.js} +1 -1
  42. package/dist/gateway/static/root/assets/url-aYn-Rj1C.js +7 -0
  43. package/dist/gateway/static/root/assets/{utils-CxDGduqK.js → utils-BWm2tG2w.js} +1 -1
  44. package/dist/gateway/static/root/assets/{voice-api-key-field-CTyHz7L_.js → voice-api-key-field-X2UfnHeq.js} +1 -1
  45. package/dist/gateway/static/root/assets/workflows-page-BOPpO3NG.js +27 -0
  46. package/dist/gateway/static/root/index.html +5 -6
  47. package/dist/package.js +1 -1
  48. package/dist/src/agent/agent-manager.d.ts +2 -0
  49. package/dist/src/agent/agent-manager.js +8 -7
  50. package/dist/src/agent/agent-manager.js.map +1 -1
  51. package/dist/src/agent/agent-scope.js +1 -1
  52. package/dist/src/agent/bootstrap/load-bootstrap-files.js +1 -1
  53. package/dist/src/agent/context/workspace-seed.js +2 -2
  54. package/dist/src/agent/goals/goal-run-store.js +4 -4
  55. package/dist/src/agent/goals/persistent-goal-service.js +1 -1
  56. package/dist/src/agent/goals/post-turn.js +2 -2
  57. package/dist/src/agent/image/load-image-media.js +2 -2
  58. package/dist/src/agent/ipc/bus.js +1 -1
  59. package/dist/src/agent/ipc/inbox.js +2 -2
  60. package/dist/src/agent/ipc/socket.js +1 -1
  61. package/dist/src/agent/mcp/bundle-mcp-materialize.js +1 -1
  62. package/dist/src/agent/mcp/bundle-mcp-runtime.js +1 -1
  63. package/dist/src/agent/mcp/mcp-transport-config.js +1 -1
  64. package/dist/src/agent/mcp/mcp-transport.js +1 -1
  65. package/dist/src/agent/memory/builtin-memory-store.js +1 -1
  66. package/dist/src/agent/memory/dreaming/deep-promotion.js +1 -1
  67. package/dist/src/agent/memory/dreaming/events.js +1 -1
  68. package/dist/src/agent/memory/dreaming/last-run.js +1 -1
  69. package/dist/src/agent/memory/dreaming/light-sweep.js +1 -1
  70. package/dist/src/agent/memory/dreaming/preview.js +1 -1
  71. package/dist/src/agent/memory/dreaming/rem-patterns.js +1 -1
  72. package/dist/src/agent/memory/dreaming/short-term-store.js +1 -1
  73. package/dist/src/agent/memory/dreaming/utils.js +1 -1
  74. package/dist/src/agent/memory/plugin-discovery.js +1 -1
  75. package/dist/src/agent/models/manager.js +1 -1
  76. package/dist/src/agent/prompt/service-prompt-builder.js +2 -2
  77. package/dist/src/agent/reply/post-compaction-context.js +1 -1
  78. package/dist/src/agent/reply/workspace-boundary-read.js +1 -1
  79. package/dist/src/agent/sandbox/path-policy.js +2 -2
  80. package/dist/src/agent/service/build-direct-message-content.js +1 -1
  81. package/dist/src/agent/service.js +6 -5
  82. package/dist/src/agent/service.js.map +1 -1
  83. package/dist/src/agent/service.types.d.ts +3 -1
  84. package/dist/src/agent/session/session-inspector.js +1 -1
  85. package/dist/src/agent/skills/config.js +1 -1
  86. package/dist/src/agent/skills/hub-hash.js +2 -2
  87. package/dist/src/agent/skills/hub-lock.js +1 -1
  88. package/dist/src/agent/skills/hub-pull.js +2 -2
  89. package/dist/src/agent/skills/index.js +1 -1
  90. package/dist/src/agent/skills/managed-store.js +1 -1
  91. package/dist/src/agent/skills/scanner.js +1 -1
  92. package/dist/src/agent/skills/skill-manage-ops.js +1 -1
  93. package/dist/src/agent/skills/skill-manager.js +1 -1
  94. package/dist/src/agent/tools/cronjob-tool.js +2 -1
  95. package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
  96. package/dist/src/agent/tools/dreaming-tool.js +1 -1
  97. package/dist/src/agent/tools/factory.d.ts +3 -0
  98. package/dist/src/agent/tools/factory.js +3 -24
  99. package/dist/src/agent/tools/factory.js.map +1 -1
  100. package/dist/src/agent/tools/image-generate-tool.js +1 -1
  101. package/dist/src/agent/tools/send-media.js +1 -1
  102. package/dist/src/agent/tools/skill-manage-tool.js +1 -1
  103. package/dist/src/agent/tools/workflow-tool.d.ts +6 -28
  104. package/dist/src/agent/tools/workflow-tool.js +61 -261
  105. package/dist/src/agent/tools/workflow-tool.js.map +1 -1
  106. package/dist/src/agent/tools/write.js +1 -1
  107. package/dist/src/agent/workflow/catalog.js +1 -1
  108. package/dist/src/agent/workflow/workflow-child-tools.d.ts +4 -0
  109. package/dist/src/agent/workflow/workflow-child-tools.js +21 -0
  110. package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -0
  111. package/dist/src/auth/credentials.d.ts +14 -2
  112. package/dist/src/auth/credentials.js +40 -15
  113. package/dist/src/auth/credentials.js.map +1 -1
  114. package/dist/src/auth/oauth/types.d.ts +16 -0
  115. package/dist/src/auth/profiles/store.js +1 -1
  116. package/dist/src/auth/sync-provider-auth.js +1 -1
  117. package/dist/src/browser/cache-dir-policy.js +1 -1
  118. package/dist/src/browser/cdp-local-launcher.js +2 -2
  119. package/dist/src/browser/providers/browser-ext-install.js +3 -3
  120. package/dist/src/browser/providers/cloakbrowser.js +4 -4
  121. package/dist/src/browser/providers/playwright-doctor.js +1 -1
  122. package/dist/src/browser/stealth.js +1 -1
  123. package/dist/src/channels/attachments/inbound-persist.js +1 -1
  124. package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
  125. package/dist/src/channels/outbound/persist-store.js +1 -1
  126. package/dist/src/channels/pairing/allow-from-file.js +1 -1
  127. package/dist/src/channels/pairing/pairing-store.js +2 -2
  128. package/dist/src/chat-commands/builtins/config.js +2 -2
  129. package/dist/src/chat-commands/context.js +1 -1
  130. package/dist/src/cli/commands/auth.js +6 -0
  131. package/dist/src/cli/commands/auth.js.map +1 -1
  132. package/dist/src/cli/commands/config.js +1 -1
  133. package/dist/src/cli/commands/doctor/checks/config-health.js +1 -1
  134. package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
  135. package/dist/src/cli/commands/doctor/checks/session-integrity.js +1 -1
  136. package/dist/src/cli/commands/doctor/checks/state-integrity.js +1 -1
  137. package/dist/src/cli/commands/doctor/checks/workspace-status.js +1 -1
  138. package/dist/src/cli/commands/extension-dev.js +1 -1
  139. package/dist/src/cli/commands/extension-marketplace.js +1 -1
  140. package/dist/src/cli/commands/extension-pack.js +1 -1
  141. package/dist/src/cli/commands/gateway/lifecycle.js +1 -1
  142. package/dist/src/cli/commands/gateway/logs.js +1 -1
  143. package/dist/src/cli/commands/image.js +1 -1
  144. package/dist/src/cli/commands/init.js +4 -4
  145. package/dist/src/cli/commands/onboard/model.js +6 -0
  146. package/dist/src/cli/commands/onboard/model.js.map +1 -1
  147. package/dist/src/cli/commands/onboard.js +1 -1
  148. package/dist/src/cli/utils/init-workspace-core.js +2 -2
  149. package/dist/src/config/agent-profile.js +1 -1
  150. package/dist/src/config/agent-typed-models.js +1 -1
  151. package/dist/src/config/gateway-bind.js +1 -1
  152. package/dist/src/config/index.js +5 -5
  153. package/dist/src/config/loader.js +2 -2
  154. package/dist/src/config/models-json.js +2 -2
  155. package/dist/src/config/paths-state.js +1 -1
  156. package/dist/src/config/profile.js +2 -2
  157. package/dist/src/config/workspace-path.js +1 -1
  158. package/dist/src/cron/executor.d.ts +2 -0
  159. package/dist/src/cron/executor.js +61 -7
  160. package/dist/src/cron/executor.js.map +1 -1
  161. package/dist/src/cron/job-content.js +2 -1
  162. package/dist/src/cron/job-content.js.map +1 -1
  163. package/dist/src/cron/persistence.js +1 -1
  164. package/dist/src/cron/run-log-store.js +1 -1
  165. package/dist/src/cron/types.d.ts +21 -1
  166. package/dist/src/cron/validation.d.ts +76 -0
  167. package/dist/src/cron/validation.js +26 -1
  168. package/dist/src/cron/validation.js.map +1 -1
  169. package/dist/src/daemon/constants.js +1 -1
  170. package/dist/src/daemon/install-plan.js +2 -2
  171. package/dist/src/daemon/launchd.js +2 -2
  172. package/dist/src/daemon/schtasks.js +2 -2
  173. package/dist/src/daemon/systemd.js +2 -2
  174. package/dist/src/extensions/bundle-mcp.js +1 -1
  175. package/dist/src/extensions/discover-extensions.js +1 -1
  176. package/dist/src/extensions/health.js +1 -1
  177. package/dist/src/extensions/loader.js +1 -1
  178. package/dist/src/extensions/lockfile.js +2 -2
  179. package/dist/src/gateway/agents-admin.js +3 -3
  180. package/dist/src/gateway/file-path-classifier.js +2 -2
  181. package/dist/src/gateway/gateway-workflow-host.types.d.ts +17 -0
  182. package/dist/src/gateway/gateway-workflow-host.types.js +1 -0
  183. package/dist/src/gateway/hono/lib/config-payload.js +1 -1
  184. package/dist/src/gateway/hono/lib/extension-store.js +2 -2
  185. package/dist/src/gateway/hono/lib/static-ui.js +2 -2
  186. package/dist/src/gateway/hono/oauth-async.js +40 -15
  187. package/dist/src/gateway/hono/oauth-async.js.map +1 -1
  188. package/dist/src/gateway/hono/oauth.js +31 -6
  189. package/dist/src/gateway/hono/oauth.js.map +1 -1
  190. package/dist/src/gateway/hono/routes/agents.js +1 -1
  191. package/dist/src/gateway/hono/routes/auth-registry-extensions.js +1 -1
  192. package/dist/src/gateway/hono/routes/config-patch/misc.js +1 -1
  193. package/dist/src/gateway/hono/routes/dreaming.js +1 -1
  194. package/dist/src/gateway/hono/routes/host-fs.js +2 -2
  195. package/dist/src/gateway/hono/routes/models.js +12 -6
  196. package/dist/src/gateway/hono/routes/models.js.map +1 -1
  197. package/dist/src/gateway/hono/routes/shares.js +1 -1
  198. package/dist/src/gateway/hono/routes/workflows.js +69 -190
  199. package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
  200. package/dist/src/gateway/hono/routes/workspace.js +4 -4
  201. package/dist/src/gateway/lock.js +3 -3
  202. package/dist/src/gateway/ports.js +1 -1
  203. package/dist/src/gateway/service/agent-runner.js +2 -2
  204. package/dist/src/gateway/service/marketplace-service.js +2 -2
  205. package/dist/src/gateway/service.d.ts +5 -0
  206. package/dist/src/gateway/service.js +23 -3
  207. package/dist/src/gateway/service.js.map +1 -1
  208. package/dist/src/gateway/workspace-fs-file-list.js +1 -1
  209. package/dist/src/infra/restart.js +2 -2
  210. package/dist/src/infra/update-check.js +1 -1
  211. package/dist/src/infra/update-global.js +1 -1
  212. package/dist/src/infra/update-lock.js +3 -3
  213. package/dist/src/infra/update-runner.js +1 -1
  214. package/dist/src/infra/update-startup.js +2 -2
  215. package/dist/src/infra/write-file-atomic.js +2 -2
  216. package/dist/src/providers/auth-runtime/auth-profile-store.js +1 -1
  217. package/dist/src/providers/index.d.ts +8 -0
  218. package/dist/src/providers/index.js +53 -14
  219. package/dist/src/providers/index.js.map +1 -1
  220. package/dist/src/providers/model-registry.js +1 -1
  221. package/dist/src/session/config-store.js +2 -2
  222. package/dist/src/session/init-session-turn.js +2 -2
  223. package/dist/src/session/parity/jsonl-transcript-io.js +2 -2
  224. package/dist/src/session/parity/sessions-json-file.js +1 -1
  225. package/dist/src/session/parity/transcript-file-lock.js +2 -2
  226. package/dist/src/session/parity/transcript-paths.js +1 -1
  227. package/dist/src/session/resolve-session.js +4 -4
  228. package/dist/src/session/search-index-cache.js +1 -1
  229. package/dist/src/session/search-index.js +1 -1
  230. package/dist/src/session/session-title.js +2 -2
  231. package/dist/src/session/store.js +5 -5
  232. package/dist/src/share/share-auto.js +2 -2
  233. package/dist/src/share/share-store.js +3 -3
  234. package/dist/src/share/share-thumbnail.js +2 -2
  235. package/dist/src/share/share-zip.js +1 -1
  236. package/dist/src/share/site-share-config.d.ts +3 -2
  237. package/dist/src/share/site-share-config.js.map +1 -1
  238. package/dist/src/share/site-share-store.js +3 -3
  239. package/dist/src/share/site-static-serve.js +1 -1
  240. package/dist/src/tui/clipboard-image.js +3 -3
  241. package/dist/src/tui/theme-manager.js +1 -1
  242. package/dist/src/tui/tui-keybindings-file.js +1 -1
  243. package/dist/src/tui/tui-scoped-models.js +2 -2
  244. package/dist/src/tui/tui-settings.js +1 -1
  245. package/dist/src/tui/tui.js +3 -3
  246. package/dist/src/tunnel/frpc-binary.js +3 -3
  247. package/dist/src/tunnel/frpc-config.js +1 -1
  248. package/dist/src/tunnel/frpc-extract.js +1 -1
  249. package/dist/src/tunnel/tunnel-state.js +1 -1
  250. package/dist/src/utils/logger/audit.js +1 -1
  251. package/dist/src/utils/logger/log-store.js +1 -1
  252. package/dist/src/utils/logger/rotation.js +1 -1
  253. package/dist/src/voice/tts/audio.js +1 -1
  254. package/dist/src/voice/tts/providers/edge-speech.js +2 -2
  255. package/dist/src/workflows/domain/command.d.ts +2 -1
  256. package/dist/src/workflows/domain/definition-utils.d.ts +14 -0
  257. package/dist/src/workflows/domain/definition-utils.js +50 -0
  258. package/dist/src/workflows/domain/definition-utils.js.map +1 -0
  259. package/dist/src/workflows/domain/index.d.ts +2 -0
  260. package/dist/src/workflows/domain/index.js +3 -1
  261. package/dist/src/workflows/domain/run.d.ts +57 -0
  262. package/dist/src/workflows/domain/run.js.map +1 -1
  263. package/dist/src/workflows/domain/validation.d.ts +19 -0
  264. package/dist/src/workflows/domain/validation.js +66 -0
  265. package/dist/src/workflows/domain/validation.js.map +1 -0
  266. package/dist/src/workflows/engine/workflow-engine.d.ts +2 -1
  267. package/dist/src/workflows/engine/workflow-engine.js +1 -0
  268. package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
  269. package/dist/src/workflows/index.d.ts +4 -0
  270. package/dist/src/workflows/index.js +9 -2
  271. package/dist/src/workflows/service/run-view-to-snapshot.d.ts +4 -0
  272. package/dist/src/workflows/service/run-view-to-snapshot.js +61 -0
  273. package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -0
  274. package/dist/src/workflows/service/workflow-run-service.d.ts +36 -0
  275. package/dist/src/workflows/service/workflow-run-service.js +279 -0
  276. package/dist/src/workflows/service/workflow-run-service.js.map +1 -0
  277. package/dist/src/workflows/service/workflow-run-service.types.d.ts +47 -0
  278. package/dist/src/workflows/service/workflow-run-service.types.js +1 -0
  279. package/dist/src/workflows/service/workflow-session-bridge.d.ts +29 -0
  280. package/dist/src/workflows/service/workflow-session-bridge.js +177 -0
  281. package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -0
  282. package/dist/src/workflows/service/workflow-session-key.d.ts +3 -0
  283. package/dist/src/workflows/service/workflow-session-key.js +21 -0
  284. package/dist/src/workflows/service/workflow-session-key.js.map +1 -0
  285. package/dist/src/workflows/store/event-store.js +1 -1
  286. package/dist/src/workflows/store/run-store.js +2 -1
  287. package/dist/src/workflows/store/run-store.js.map +1 -1
  288. package/package.json +1 -1
  289. package/dist/gateway/static/root/assets/agents-CRxETUZx.js +0 -222
  290. package/dist/gateway/static/root/assets/apps-page-wKWf3l57.js +0 -1
  291. package/dist/gateway/static/root/assets/channels-settings-DDbqVNkx.js +0 -1
  292. package/dist/gateway/static/root/assets/copy-SxMW6Xpc.js +0 -1
  293. package/dist/gateway/static/root/assets/cron-api-N9hvuRrn.js +0 -1
  294. package/dist/gateway/static/root/assets/cron-page-tlNGNxhP.js +0 -1
  295. package/dist/gateway/static/root/assets/index-CqZzHNEg.css +0 -1
  296. package/dist/gateway/static/root/assets/logs-page-DDonPVLn.js +0 -1
  297. package/dist/gateway/static/root/assets/sessions-page-DKt-Wmib.js +0 -1
  298. package/dist/gateway/static/root/assets/settings-page-DcJjvvw4.js +0 -3
  299. package/dist/gateway/static/root/assets/skills-page-DuJ4BTO3.js +0 -2
  300. package/dist/gateway/static/root/assets/url-D6jvVYIA.js +0 -7
  301. package/dist/gateway/static/root/assets/workflows-page-GacJ41Fv.js +0 -27
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","names":[],"sources":["../../../src/auth/credentials.ts"],"sourcesContent":["import { readFile, mkdir } from 'fs/promises';\nimport { writeTextAtomic } from '../infra/write-file-atomic.js';\nimport { join, dirname } from 'path';\nimport { createLogger } from '../utils/logger.js';\nimport { getApiKeyFromEnv } from '../providers/env-keys.js';\nimport {\n resolveCredentialsDir,\n resolveAuthProfilesPath,\n resolveAgentAuthProfilesPath,\n resolveOAuthPath,\n} from '../config/paths.js';\nimport type { Config } from '../config/schema.js';\n\nconst log = createLogger('Credentials');\n\n// ============================================\n// Types\n// ============================================\n\nexport type CredentialType = 'api_key' | 'oauth';\n\nexport interface ApiKeyProfile {\n type: 'api_key';\n provider: string;\n profileName?: string;\n envVar?: string | null;\n key: string | null;\n}\n\nexport interface OAuthToken {\n type: 'oauth';\n provider: string;\n access: string;\n refresh?: string;\n expiresAt?: number;\n scope?: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport type CredentialProfile = ApiKeyProfile;\n\nexport interface AuthProfilesFile {\n version: number;\n profiles: Record<string, ApiKeyProfile>;\n}\n\n// ============================================\n// Credential Resolver\n// ============================================\n\nexport interface CredentialResolverOptions {\n stateDir?: string;\n /** When set, per-agent auth profiles are read from `resolveAgentAuthProfilesPath(appConfig, agentId)`. */\n agentId?: string;\n /** Required when `agentId` is set. */\n appConfig?: Config;\n}\n\nexport class CredentialResolver {\n private readonly credentialsDir: string;\n private readonly agentId?: string;\n private readonly appConfig?: Config;\n\n constructor(options: CredentialResolverOptions = {}) {\n this.credentialsDir = options.stateDir\n ? join(options.stateDir, 'credentials')\n : resolveCredentialsDir();\n this.agentId = options.agentId;\n this.appConfig = options.appConfig;\n if (this.agentId && !this.appConfig) {\n throw new Error('CredentialResolver: appConfig is required when agentId is set');\n }\n }\n\n /**\n * Resolve API key for a provider\n * Priority: Agent private > Global > OAuth > Environment\n */\n async resolveApiKey(provider: string): Promise<string | null> {\n const normalizedProvider = provider.toLowerCase();\n\n // 1. Try agent private credentials\n if (this.agentId) {\n const agentKey = await this.loadFromAgentCredentials(normalizedProvider);\n if (agentKey) {\n log.debug({ provider, source: 'agent' }, 'Resolved API key from agent credentials');\n return agentKey;\n }\n }\n\n // 2. Try global credentials\n const globalKey = await this.loadFromGlobalCredentials(normalizedProvider);\n if (globalKey) {\n log.debug({ provider, source: 'global' }, 'Resolved API key from global credentials');\n return globalKey;\n }\n\n // 3. Try OAuth token (convert to Bearer)\n const oauthToken = await this.loadOAuthToken(normalizedProvider);\n if (oauthToken) {\n log.debug({ provider, source: 'oauth' }, 'Resolved API key from OAuth token');\n return oauthToken.access;\n }\n\n // 4. Environment variables (see `src/providers/env-keys.ts`)\n const envKey = getApiKeyFromEnv(normalizedProvider);\n if (envKey) {\n log.debug({ provider, source: 'env' }, 'Resolved API key from environment');\n return envKey;\n }\n\n log.debug({ provider }, 'No API key found');\n return null;\n }\n\n /**\n * Check if a provider has credentials configured\n */\n async hasCredentials(provider: string): Promise<boolean> {\n const key = await this.resolveApiKey(provider);\n return key !== null;\n }\n\n /**\n * Which step in {@link resolveApiKey} would supply the key (no secret material).\n */\n async resolveApiKeySource(\n provider: string,\n ): Promise<'agent' | 'global' | 'oauth' | 'env' | null> {\n const normalizedProvider = provider.toLowerCase();\n\n if (this.agentId) {\n const agentKey = await this.loadFromAgentCredentials(normalizedProvider);\n if (agentKey) return 'agent';\n }\n\n const globalKey = await this.loadFromGlobalCredentials(normalizedProvider);\n if (globalKey) return 'global';\n\n const oauthToken = await this.loadOAuthToken(normalizedProvider);\n if (oauthToken) return 'oauth';\n\n if (getApiKeyFromEnv(normalizedProvider)) return 'env';\n\n return null;\n }\n\n /**\n * List all available credential profiles\n */\n async listProfiles(): Promise<Array<ApiKeyProfile & { id: string; source: 'agent' | 'global' }>> {\n const profiles: Array<ApiKeyProfile & { id: string; source: 'agent' | 'global' }> = [];\n\n // Global profiles\n const globalProfiles = await this.loadAuthProfilesFile();\n for (const [id, profile] of Object.entries(globalProfiles.profiles)) {\n profiles.push({ ...profile, id, source: 'global' });\n }\n\n // Agent private profiles\n if (this.agentId) {\n const agentProfiles = await this.loadAgentAuthProfilesFile();\n for (const [id, profile] of Object.entries(agentProfiles.profiles)) {\n profiles.push({ ...profile, id, source: 'agent' });\n }\n }\n\n return profiles;\n }\n\n /**\n * Plaintext API key from global auth profiles only (no env/oauth fallback).\n * Used by the gateway console reveal endpoint.\n */\n async revealGatewayStoredApiKey(provider: string): Promise<string | null> {\n const normalizedProvider = provider.toLowerCase();\n const profiles = await this.loadAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, normalizedProvider);\n const key = profile?.key?.trim();\n return key || null;\n }\n\n /**\n * Save an API key profile\n */\n async saveApiKey(\n provider: string,\n key: string,\n options: {\n profileName?: string;\n envVar?: string | null;\n agentPrivate?: boolean;\n } = {}\n ): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const profileId = options.profileName\n ? `${normalizedProvider}:${options.profileName}`\n : `${normalizedProvider}:default`;\n\n const profile: ApiKeyProfile = {\n type: 'api_key',\n provider: normalizedProvider,\n profileName: options.profileName,\n envVar: options.envVar ?? null,\n key,\n };\n\n if (options.agentPrivate && this.agentId) {\n await this.saveAgentAuthProfile(profileId, profile);\n } else {\n await this.saveGlobalAuthProfile(profileId, profile);\n }\n\n log.info({ provider, profileId, agentPrivate: options.agentPrivate }, 'Saved API key');\n }\n\n /**\n * Delete a credential profile\n */\n async deleteProfile(profileId: string, options: { agentPrivate?: boolean } = {}): Promise<void> {\n if (options.agentPrivate && this.agentId) {\n await this.deleteAgentAuthProfile(profileId);\n } else {\n await this.deleteGlobalAuthProfile(profileId);\n }\n\n log.info({ profileId, agentPrivate: options.agentPrivate }, 'Deleted credential profile');\n }\n\n /**\n * Load OAuth token for a provider\n */\n async loadOAuthToken(provider: string): Promise<OAuthToken | null> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n\n try {\n const content = await readFile(oauthPath, 'utf-8');\n const token = JSON.parse(content) as OAuthToken;\n\n // Check if token is expired\n if (token.expiresAt && token.expiresAt < Date.now()) {\n log.warn({ provider, expiresAt: token.expiresAt }, 'OAuth token is expired');\n // TODO: Implement token refresh\n return null;\n }\n\n return token;\n } catch {\n return null;\n }\n }\n\n /**\n * Save OAuth token for a provider\n */\n async saveOAuthToken(provider: string, token: Omit<OAuthToken, 'type' | 'provider' | 'updatedAt'>): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n\n await mkdir(dirname(oauthPath), { recursive: true });\n\n const fullToken: OAuthToken = {\n ...token,\n type: 'oauth',\n provider: normalizedProvider,\n updatedAt: new Date().toISOString(),\n };\n\n await writeTextAtomic(oauthPath, JSON.stringify(fullToken, null, 2));\n log.info({ provider }, 'Saved OAuth token');\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private async loadFromAgentCredentials(provider: string): Promise<string | null> {\n if (!this.agentId) return null;\n\n const profiles = await this.loadAgentAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, provider);\n\n if (!profile) return null;\n if (profile.envVar) return this.loadFromEnv(profile.envVar) ?? profile.key;\n return profile.key;\n }\n\n private async loadFromGlobalCredentials(provider: string): Promise<string | null> {\n const profiles = await this.loadAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, provider);\n\n if (!profile) return null;\n if (profile.envVar) return this.loadFromEnv(profile.envVar) ?? profile.key;\n return profile.key;\n }\n\n private loadFromEnv(envVarName: string): string | null {\n return process.env[envVarName] || null;\n }\n\n private findProfileForProvider(\n file: AuthProfilesFile,\n provider: string\n ): ApiKeyProfile | null {\n const normalizedProvider = provider.toLowerCase();\n\n // Look for exact match first\n for (const [, profile] of Object.entries(file.profiles)) {\n if (profile.provider === normalizedProvider) {\n return profile;\n }\n }\n\n return null;\n }\n\n private async loadAuthProfilesFile(): Promise<AuthProfilesFile> {\n const path = resolveAuthProfilesPath();\n\n try {\n const content = await readFile(path, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n profiles: data.profiles || {},\n };\n } catch {\n return { version: 2, profiles: {} };\n }\n }\n\n private async loadAgentAuthProfilesFile(): Promise<AuthProfilesFile> {\n if (!this.agentId || !this.appConfig) return { version: 2, profiles: {} };\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n\n try {\n const content = await readFile(path, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n profiles: data.profiles || {},\n };\n } catch {\n return { version: 2, profiles: {} };\n }\n }\n\n private async saveGlobalAuthProfile(profileId: string, profile: ApiKeyProfile): Promise<void> {\n const path = resolveAuthProfilesPath();\n await mkdir(dirname(path), { recursive: true });\n\n const file = await this.loadAuthProfilesFile();\n file.profiles[profileId] = profile;\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async saveAgentAuthProfile(profileId: string, profile: ApiKeyProfile): Promise<void> {\n if (!this.agentId || !this.appConfig) throw new Error('Agent ID and appConfig required for agent-private profiles');\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n await mkdir(dirname(path), { recursive: true });\n\n const file = await this.loadAgentAuthProfilesFile();\n file.profiles[profileId] = profile;\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async deleteGlobalAuthProfile(profileId: string): Promise<void> {\n const path = resolveAuthProfilesPath();\n const file = await this.loadAuthProfilesFile();\n\n delete file.profiles[profileId];\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async deleteAgentAuthProfile(profileId: string): Promise<void> {\n if (!this.agentId || !this.appConfig) throw new Error('Agent ID and appConfig required for agent-private profiles');\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n const file = await this.loadAgentAuthProfilesFile();\n\n delete file.profiles[profileId];\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nlet defaultResolver: CredentialResolver | null = null;\n\nexport function getCredentialResolver(options?: CredentialResolverOptions): CredentialResolver {\n if (!defaultResolver || options) {\n return new CredentialResolver(options);\n }\n return defaultResolver;\n}\n\nexport async function resolveApiKey(provider: string, options?: CredentialResolverOptions): Promise<string | null> {\n const resolver = getCredentialResolver(options);\n return resolver.resolveApiKey(provider);\n}\n\nexport async function hasCredentials(provider: string, options?: CredentialResolverOptions): Promise<boolean> {\n const resolver = getCredentialResolver(options);\n return resolver.hasCredentials(provider);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"credentials.js","names":[],"sources":["../../../src/auth/credentials.ts"],"sourcesContent":["import { readFile, mkdir, rm } from 'fs/promises';\nimport { writeTextAtomic } from '../infra/write-file-atomic.js';\nimport { join, dirname } from 'path';\nimport { createLogger } from '../utils/logger.js';\nimport { getApiKeyFromEnv } from '../providers/env-keys.js';\nimport {\n resolveCredentialsDir,\n resolveAuthProfilesPath,\n resolveAgentAuthProfilesPath,\n resolveOAuthPath,\n} from '../config/paths.js';\nimport type { Config } from '../config/schema.js';\n\nconst log = createLogger('Credentials');\n\n// ============================================\n// Types\n// ============================================\n\nexport type CredentialType = 'api_key' | 'oauth';\n\nexport interface ApiKeyProfile {\n type: 'api_key';\n provider: string;\n profileName?: string;\n envVar?: string | null;\n key: string | null;\n}\n\nexport interface OAuthToken {\n type: 'oauth';\n provider: string;\n access: string;\n refresh?: string;\n expiresAt?: number;\n scope?: string[];\n createdAt: string;\n updatedAt: string;\n}\n\nexport type CredentialProfile = ApiKeyProfile;\n\nexport interface AuthProfilesFile {\n version: number;\n profiles: Record<string, ApiKeyProfile>;\n}\n\n// ============================================\n// Credential Resolver\n// ============================================\n\nexport interface CredentialResolverOptions {\n stateDir?: string;\n /** When set, per-agent auth profiles are read from `resolveAgentAuthProfilesPath(appConfig, agentId)`. */\n agentId?: string;\n /** Required when `agentId` is set. */\n appConfig?: Config;\n}\n\nexport class CredentialResolver {\n private readonly credentialsDir: string;\n private readonly agentId?: string;\n private readonly appConfig?: Config;\n\n constructor(options: CredentialResolverOptions = {}) {\n this.credentialsDir = options.stateDir\n ? join(options.stateDir, 'credentials')\n : resolveCredentialsDir();\n this.agentId = options.agentId;\n this.appConfig = options.appConfig;\n if (this.agentId && !this.appConfig) {\n throw new Error('CredentialResolver: appConfig is required when agentId is set');\n }\n }\n\n /**\n * Resolve API key for a provider\n * Priority: Agent private > Global > OAuth > Environment\n */\n async resolveApiKey(provider: string): Promise<string | null> {\n const normalizedProvider = provider.toLowerCase();\n\n // 1. Try agent private credentials\n if (this.agentId) {\n const agentKey = await this.loadFromAgentCredentials(normalizedProvider);\n if (agentKey) {\n log.debug({ provider, source: 'agent' }, 'Resolved API key from agent credentials');\n return agentKey;\n }\n }\n\n // 2. Try global credentials\n const globalKey = await this.loadFromGlobalCredentials(normalizedProvider);\n if (globalKey) {\n log.debug({ provider, source: 'global' }, 'Resolved API key from global credentials');\n return globalKey;\n }\n\n // 3. Try OAuth token (convert to Bearer)\n const oauthToken = await this.loadOAuthToken(normalizedProvider);\n if (oauthToken) {\n log.debug({ provider, source: 'oauth' }, 'Resolved API key from OAuth token');\n return oauthToken.access;\n }\n\n // 4. Environment variables (see `src/providers/env-keys.ts`)\n const envKey = getApiKeyFromEnv(normalizedProvider);\n if (envKey) {\n log.debug({ provider, source: 'env' }, 'Resolved API key from environment');\n return envKey;\n }\n\n log.debug({ provider }, 'No API key found');\n return null;\n }\n\n /**\n * Check if a provider has credentials configured\n */\n async hasCredentials(provider: string): Promise<boolean> {\n const key = await this.resolveApiKey(provider);\n return key !== null;\n }\n\n /**\n * Which step in {@link resolveApiKey} would supply the key (no secret material).\n */\n async resolveApiKeySource(\n provider: string,\n ): Promise<'agent' | 'global' | 'oauth' | 'env' | null> {\n const normalizedProvider = provider.toLowerCase();\n\n if (this.agentId) {\n const agentKey = await this.loadFromAgentCredentials(normalizedProvider);\n if (agentKey) return 'agent';\n }\n\n const globalKey = await this.loadFromGlobalCredentials(normalizedProvider);\n if (globalKey) return 'global';\n\n const oauthToken = await this.loadOAuthToken(normalizedProvider);\n if (oauthToken) return 'oauth';\n\n if (getApiKeyFromEnv(normalizedProvider)) return 'env';\n\n return null;\n }\n\n /**\n * List all available credential profiles\n */\n async listProfiles(): Promise<Array<ApiKeyProfile & { id: string; source: 'agent' | 'global' }>> {\n const profiles: Array<ApiKeyProfile & { id: string; source: 'agent' | 'global' }> = [];\n\n // Global profiles\n const globalProfiles = await this.loadAuthProfilesFile();\n for (const [id, profile] of Object.entries(globalProfiles.profiles)) {\n profiles.push({ ...profile, id, source: 'global' });\n }\n\n // Agent private profiles\n if (this.agentId) {\n const agentProfiles = await this.loadAgentAuthProfilesFile();\n for (const [id, profile] of Object.entries(agentProfiles.profiles)) {\n profiles.push({ ...profile, id, source: 'agent' });\n }\n }\n\n return profiles;\n }\n\n /**\n * Plaintext API key from global auth profiles only (no env/oauth fallback).\n * Used by the gateway console reveal endpoint.\n */\n async revealGatewayStoredApiKey(provider: string): Promise<string | null> {\n const normalizedProvider = provider.toLowerCase();\n const profiles = await this.loadAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, normalizedProvider);\n const key = profile?.key?.trim();\n return key || null;\n }\n\n /**\n * Save an API key profile\n */\n async saveApiKey(\n provider: string,\n key: string,\n options: {\n profileName?: string;\n envVar?: string | null;\n agentPrivate?: boolean;\n } = {}\n ): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const profileId = options.profileName\n ? `${normalizedProvider}:${options.profileName}`\n : `${normalizedProvider}:default`;\n\n const profile: ApiKeyProfile = {\n type: 'api_key',\n provider: normalizedProvider,\n profileName: options.profileName,\n envVar: options.envVar ?? null,\n key,\n };\n\n if (options.agentPrivate && this.agentId) {\n await this.saveAgentAuthProfile(profileId, profile);\n } else {\n await this.saveGlobalAuthProfile(profileId, profile);\n }\n\n log.info({ provider, profileId, agentPrivate: options.agentPrivate }, 'Saved API key');\n }\n\n /**\n * Delete a credential profile\n */\n async deleteProfile(profileId: string, options: { agentPrivate?: boolean } = {}): Promise<void> {\n if (options.agentPrivate && this.agentId) {\n await this.deleteAgentAuthProfile(profileId);\n } else {\n await this.deleteGlobalAuthProfile(profileId);\n }\n\n log.info({ profileId, agentPrivate: options.agentPrivate }, 'Deleted credential profile');\n }\n\n /**\n * Load OAuth token for a provider.\n */\n async loadOAuthToken(provider: string): Promise<OAuthToken | null> {\n const token = await this.loadOAuthTokenRecord(provider);\n if (!token) return null;\n\n if (token.expiresAt && token.expiresAt < Date.now()) {\n log.warn({ provider, expiresAt: token.expiresAt }, 'OAuth token is expired');\n return null;\n }\n\n return token;\n }\n\n /**\n * Load the raw OAuth token record, including expired tokens for status UIs.\n */\n async loadOAuthTokenRecord(provider: string): Promise<OAuthToken | null> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n\n try {\n const content = await readFile(oauthPath, 'utf-8');\n const token = JSON.parse(content) as OAuthToken;\n return token.provider === normalizedProvider ? token : null;\n } catch {\n return null;\n }\n }\n\n /**\n * Save OAuth token for a provider.\n */\n async saveOAuthToken(provider: string, token: Omit<OAuthToken, 'type' | 'provider' | 'updatedAt'>): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n\n await mkdir(dirname(oauthPath), { recursive: true });\n\n const fullToken: OAuthToken = {\n ...token,\n type: 'oauth',\n provider: normalizedProvider,\n updatedAt: new Date().toISOString(),\n };\n\n await writeTextAtomic(oauthPath, JSON.stringify(fullToken, null, 2));\n log.info({ provider: normalizedProvider }, 'Saved OAuth token');\n }\n\n /**\n * Delete the OAuth token persisted for a provider.\n */\n async deleteOAuthToken(provider: string): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n const oauthPath = resolveOAuthPath(normalizedProvider);\n await rm(oauthPath, { force: true });\n log.info({ provider: normalizedProvider }, 'Deleted OAuth token');\n }\n\n /**\n * Disconnect the default credential for a provider from local storage.\n */\n async deleteProviderCredential(provider: string): Promise<void> {\n const normalizedProvider = provider.toLowerCase();\n await this.deleteProfile(`${normalizedProvider}:default`);\n await this.deleteOAuthToken(normalizedProvider);\n }\n\n // ============================================\n // Private Methods\n // ============================================\n\n private async loadFromAgentCredentials(provider: string): Promise<string | null> {\n if (!this.agentId) return null;\n\n const profiles = await this.loadAgentAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, provider);\n\n if (!profile) return null;\n if (profile.envVar) return this.loadFromEnv(profile.envVar) ?? profile.key;\n return profile.key;\n }\n\n private async loadFromGlobalCredentials(provider: string): Promise<string | null> {\n const profiles = await this.loadAuthProfilesFile();\n const profile = this.findProfileForProvider(profiles, provider);\n\n if (!profile) return null;\n if (profile.envVar) return this.loadFromEnv(profile.envVar) ?? profile.key;\n return profile.key;\n }\n\n private loadFromEnv(envVarName: string): string | null {\n return process.env[envVarName] || null;\n }\n\n private findProfileForProvider(\n file: AuthProfilesFile,\n provider: string\n ): ApiKeyProfile | null {\n const normalizedProvider = provider.toLowerCase();\n\n // Look for exact match first\n for (const [, profile] of Object.entries(file.profiles)) {\n if (profile.provider === normalizedProvider) {\n return profile;\n }\n }\n\n return null;\n }\n\n private async loadAuthProfilesFile(): Promise<AuthProfilesFile> {\n const path = resolveAuthProfilesPath();\n\n try {\n const content = await readFile(path, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n profiles: data.profiles || {},\n };\n } catch {\n return { version: 2, profiles: {} };\n }\n }\n\n private async loadAgentAuthProfilesFile(): Promise<AuthProfilesFile> {\n if (!this.agentId || !this.appConfig) return { version: 2, profiles: {} };\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n\n try {\n const content = await readFile(path, 'utf-8');\n const data = JSON.parse(content);\n return {\n version: data.version || 1,\n profiles: data.profiles || {},\n };\n } catch {\n return { version: 2, profiles: {} };\n }\n }\n\n private async saveGlobalAuthProfile(profileId: string, profile: ApiKeyProfile): Promise<void> {\n const path = resolveAuthProfilesPath();\n await mkdir(dirname(path), { recursive: true });\n\n const file = await this.loadAuthProfilesFile();\n file.profiles[profileId] = profile;\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async saveAgentAuthProfile(profileId: string, profile: ApiKeyProfile): Promise<void> {\n if (!this.agentId || !this.appConfig) throw new Error('Agent ID and appConfig required for agent-private profiles');\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n await mkdir(dirname(path), { recursive: true });\n\n const file = await this.loadAgentAuthProfilesFile();\n file.profiles[profileId] = profile;\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async deleteGlobalAuthProfile(profileId: string): Promise<void> {\n const path = resolveAuthProfilesPath();\n const file = await this.loadAuthProfilesFile();\n\n delete file.profiles[profileId];\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n\n private async deleteAgentAuthProfile(profileId: string): Promise<void> {\n if (!this.agentId || !this.appConfig) throw new Error('Agent ID and appConfig required for agent-private profiles');\n\n const path = resolveAgentAuthProfilesPath(this.appConfig, this.agentId);\n const file = await this.loadAgentAuthProfilesFile();\n\n delete file.profiles[profileId];\n\n await writeTextAtomic(path, JSON.stringify(file, null, 2));\n }\n}\n\n// ============================================\n// Convenience Functions\n// ============================================\n\nlet defaultResolver: CredentialResolver | null = null;\n\nexport function getCredentialResolver(options?: CredentialResolverOptions): CredentialResolver {\n if (!defaultResolver || options) {\n return new CredentialResolver(options);\n }\n return defaultResolver;\n}\n\nexport async function resolveApiKey(provider: string, options?: CredentialResolverOptions): Promise<string | null> {\n const resolver = getCredentialResolver(options);\n return resolver.resolveApiKey(provider);\n}\n\nexport async function hasCredentials(provider: string, options?: CredentialResolverOptions): Promise<boolean> {\n const resolver = getCredentialResolver(options);\n return resolver.hasCredentials(provider);\n}\n"],"mappings":"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"}
@@ -19,11 +19,27 @@ export type OAuthAuthInfo = {
19
19
  url: string;
20
20
  instructions?: string;
21
21
  };
22
+ export type OAuthDeviceCodeInfo = {
23
+ userCode: string;
24
+ verificationUri: string;
25
+ intervalSeconds?: number;
26
+ expiresInSeconds?: number;
27
+ };
28
+ export type OAuthSelectOption = {
29
+ id: string;
30
+ label: string;
31
+ };
32
+ export type OAuthSelectPrompt = {
33
+ message: string;
34
+ options: OAuthSelectOption[];
35
+ };
22
36
  export interface OAuthLoginCallbacks {
23
37
  onAuth: (info: OAuthAuthInfo) => void;
38
+ onDeviceCode: (info: OAuthDeviceCodeInfo) => void;
24
39
  onPrompt: (prompt: OAuthPrompt) => Promise<string>;
25
40
  onProgress?: (message: string) => void;
26
41
  onManualCodeInput?: () => Promise<string>;
42
+ onSelect: (prompt: OAuthSelectPrompt) => Promise<string | undefined>;
27
43
  signal?: AbortSignal;
28
44
  }
29
45
  export interface OAuthProviderInterface {
@@ -1,6 +1,6 @@
1
1
  import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
2
- import { chmodSync, existsSync, mkdirSync, readFileSync } from "node:fs";
3
2
  import path from "node:path";
3
+ import { chmodSync, existsSync, mkdirSync, readFileSync } from "node:fs";
4
4
  import { homedir } from "os";
5
5
  //#region src/auth/profiles/store.ts
6
6
  /**
@@ -1,7 +1,7 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
+ import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
2
3
  import { init_paths, resolveAgentAuthProfilesPath, resolveAuthProfilesPath, resolveOAuthPath } from "../config/paths.js";
3
4
  import { init_loader, loadConfig } from "../config/loader.js";
4
- import { getDefaultAgentId, init_resolve_route } from "../routing/resolve-route.js";
5
5
  import { existsSync, readFileSync } from "node:fs";
6
6
  //#region src/auth/sync-provider-auth.ts
7
7
  /**
@@ -1,6 +1,6 @@
1
1
  import { __esmMin } from "../../_virtual/_rolldown/runtime.js";
2
- import { isAbsolute, relative, resolve, sep } from "node:path";
3
2
  import { homedir } from "node:os";
3
+ import { isAbsolute, relative, resolve, sep } from "node:path";
4
4
  //#region src/browser/cache-dir-policy.ts
5
5
  function expandHome(input) {
6
6
  if (input === "~") return homedir();
@@ -2,10 +2,10 @@ import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
3
  import { loadPlaywrightCoreModule } from "./providers/playwright-doctor.js";
4
4
  import { pickFreePort } from "./free-port.js";
5
+ import { homedir, platform } from "node:os";
6
+ import { join } from "node:path";
5
7
  import { existsSync } from "node:fs";
6
8
  import { mkdir, rm } from "node:fs/promises";
7
- import { join } from "node:path";
8
- import { homedir, platform } from "node:os";
9
9
  import { spawn } from "node:child_process";
10
10
  //#region src/browser/cdp-local-launcher.ts
11
11
  /**
@@ -1,13 +1,13 @@
1
1
  import { PACKAGE_VERSION, init_package_version } from "../../package-version.js";
2
- import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
2
+ import { assertCacheDir, init_cache_dir_policy } from "../cache-dir-policy.js";
3
3
  import { createLogger } from "../../utils/logger/index.js";
4
4
  import { init_logger } from "../../utils/logger.js";
5
5
  import { init_paths, resolveBinDir } from "../../config/paths.js";
6
- import { assertCacheDir, init_cache_dir_policy } from "../cache-dir-policy.js";
6
+ import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
7
7
  import { resolvePackageRoot } from "../../infra/update-check.js";
8
+ import { dirname, join } from "node:path";
8
9
  import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
9
10
  import { readFile, readdir, rm } from "node:fs/promises";
10
- import { dirname, join } from "node:path";
11
11
  import { spawn } from "node:child_process";
12
12
  import { fileURLToPath } from "node:url";
13
13
  //#region src/browser/providers/browser-ext-install.ts
@@ -1,15 +1,15 @@
1
+ import { assertCacheDir, expandHome, init_cache_dir_policy } from "../cache-dir-policy.js";
1
2
  import { createLogger } from "../../utils/logger/index.js";
2
3
  import { init_logger } from "../../utils/logger.js";
3
4
  import { init_paths, resolveBinDir } from "../../config/paths.js";
4
- import { assertCacheDir, expandHome, init_cache_dir_policy } from "../cache-dir-policy.js";
5
5
  import { loadPlaywrightCoreModule } from "./playwright-doctor.js";
6
6
  import { WEBDRIVER_OVERRIDE_SCRIPT, buildStealthArgs, filterCloakBrowserExtraArgs, generateFingerprintSeed, makeExecutable, removeQuarantineAttr } from "../stealth.js";
7
7
  import { pickFreePort } from "../free-port.js";
8
- import { createHash } from "node:crypto";
8
+ import { arch, platform, tmpdir } from "node:os";
9
+ import { join, resolve } from "node:path";
9
10
  import { createReadStream, createWriteStream } from "node:fs";
11
+ import { createHash } from "node:crypto";
10
12
  import { mkdir, mkdtemp, rm, stat } from "node:fs/promises";
11
- import { join, resolve } from "node:path";
12
- import { arch, platform, tmpdir } from "node:os";
13
13
  import { spawn } from "node:child_process";
14
14
  import { Readable, Transform } from "node:stream";
15
15
  import AdmZip from "adm-zip";
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
+ import { dirname, join } from "node:path";
2
3
  import { existsSync } from "node:fs";
3
4
  import { stat } from "node:fs/promises";
4
- import { dirname, join } from "node:path";
5
5
  import { fileURLToPath } from "node:url";
6
6
  //#region src/browser/providers/playwright-doctor.ts
7
7
  /** Root directory of the `playwright-core` package (Electron extraResources or node_modules). */
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../utils/logger/index.js";
2
2
  import { init_logger } from "../utils/logger.js";
3
- import { chmod, stat } from "node:fs/promises";
4
3
  import { platform } from "node:os";
4
+ import { chmod, stat } from "node:fs/promises";
5
5
  import { exec } from "node:child_process";
6
6
  import { promisify } from "node:util";
7
7
  //#region src/browser/stealth.ts
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { mkdir, writeFile } from "fs/promises";
4
3
  import { join, resolve } from "path";
4
+ import { mkdir, writeFile } from "fs/promises";
5
5
  import { randomBytes } from "crypto";
6
6
  //#region src/channels/attachments/inbound-persist.ts
7
7
  /**
@@ -1,7 +1,7 @@
1
1
  import { createLogger } from "../../utils/logger/index.js";
2
2
  import { init_logger } from "../../utils/logger.js";
3
- import { mkdir, writeFile } from "fs/promises";
4
3
  import { join, resolve } from "path";
4
+ import { mkdir, writeFile } from "fs/promises";
5
5
  import { randomBytes } from "crypto";
6
6
  //#region src/channels/attachments/outbound-tts-persist.ts
7
7
  /**
@@ -1,7 +1,7 @@
1
1
  import { init_write_file_atomic, writeTextAtomicSync } from "../../infra/write-file-atomic.js";
2
- import { randomUUID } from "node:crypto";
3
2
  import { join } from "path";
4
3
  import { existsSync, mkdirSync, readFileSync } from "fs";
4
+ import { randomUUID } from "node:crypto";
5
5
  //#region src/channels/outbound/persist-store.ts
6
6
  /**
7
7
  * Durable outbound queue (crash recovery): JSON file under agent internal dir.
@@ -1,5 +1,5 @@
1
- import fs from "node:fs";
2
1
  import path from "node:path";
2
+ import fs from "node:fs";
3
3
  //#region src/channels/pairing/allow-from-file.ts
4
4
  function readAllowFromFile(filePath) {
5
5
  try {
@@ -1,8 +1,8 @@
1
1
  import { appendAllowFromIdSync } from "./allow-from-file.js";
2
2
  import "./pairing-constants.js";
3
- import crypto from "node:crypto";
4
- import fs from "node:fs";
5
3
  import path from "node:path";
4
+ import fs from "node:fs";
5
+ import crypto from "node:crypto";
6
6
  //#region src/channels/pairing/pairing-store.ts
7
7
  const PAIRING_CODE_LENGTH = 8;
8
8
  const PAIRING_CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
@@ -1,9 +1,9 @@
1
+ import { ConfigSchema, init_schema } from "../../config/schema.js";
2
+ import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
1
3
  import { createLogger } from "../../utils/logger/index.js";
2
4
  import { init_logger } from "../../utils/logger.js";
3
5
  import { init_paths, resolveConfigPath } from "../../config/paths.js";
4
- import { ConfigSchema, init_schema } from "../../config/schema.js";
5
6
  import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
6
- import { init_session_key, parseSessionKey } from "../../routing/session-key.js";
7
7
  import { commandRegistry } from "../registry.js";
8
8
  import { resolveAllowlistMatchSimple } from "../../channels/security.js";
9
9
  import { parseConfigValue } from "../config-value.js";
@@ -4,8 +4,8 @@ import { init_loader, saveConfig } from "../config/loader.js";
4
4
  import { effectiveWorkspacePathForSession } from "../session/session-workspace.js";
5
5
  import { getRoutingInfo, getSessionDisplayName } from "./session-key.js";
6
6
  import { wrapMarkdownExportAsHtml } from "../session/chat-export.js";
7
- import { mkdir, writeFile } from "fs/promises";
8
7
  import { join } from "path";
8
+ import { mkdir, writeFile } from "fs/promises";
9
9
  //#region src/chat-commands/context.ts
10
10
  init_logger();
11
11
  init_loader();
@@ -86,12 +86,18 @@ function createAuthCommand(_ctx) {
86
86
  if (info.instructions) console.log("\n" + info.instructions);
87
87
  console.log("\n");
88
88
  },
89
+ onDeviceCode: (info) => {
90
+ console.log(`\nOpen ${info.verificationUri} and enter code ${info.userCode}\n`);
91
+ },
89
92
  onPrompt: async (prompt) => {
90
93
  const { input } = await import("@inquirer/prompts");
91
94
  return input({ message: prompt.message });
92
95
  },
93
96
  onProgress: (message) => {
94
97
  log.info(message);
98
+ },
99
+ onSelect: async (prompt) => {
100
+ return prompt.options.find((option) => option.id === "browser")?.id ?? prompt.options[0]?.id;
95
101
  }
96
102
  };
97
103
  try {
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","names":[],"sources":["../../../../src/cli/commands/auth.ts"],"sourcesContent":["/**\n * Auth Command\n * \n * Manage authentication credentials (API keys, OAuth tokens, Auth Profiles).\n */\n\nimport { Command } from 'commander';\nimport { type OAuthLoginCallbacks } from '../../auth/index.js';\nimport {\n\tlistProfilesForProvider,\n\tlistAllProfiles,\n\tupsertAuthProfile,\n\tremoveAuthProfile,\n\ttype AuthProfileCredential,\n} from '../../auth/profiles/index.js';\nimport { getAllProviders } from '../../providers/index.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { colors, colorizeStatus } from '../utils/colors.js';\nimport { getOAuthProvider, getSupportedOAuthProviders } from '../utils/oauth-providers.js';\n\nconst log = createLogger('AuthCommand');\n\nfunction createAuthCommand(_ctx: CLIContext): Command {\n\tconst cmd = new Command('auth')\n\t\t.description('Manage authentication credentials')\n\t\t.addHelpText(\n\t\t\t'after',\n\t\t\tformatExamples([\n\t\t\t\t'xopc auth list',\n\t\t\t\t'xopc auth set openai sk-xxx',\n\t\t\t\t'xopc auth set anthropic sk-ant-api-xxx',\n\t\t\t\t'xopc auth login anthropic',\n\t\t\t\t'xopc auth login kimi-coding',\n\t\t\t\t'xopc auth logout anthropic',\n\t\t\t\t'xopc auth remove anthropic',\n\t\t\t\t'xopc auth profiles list',\n\t\t\t])\n\t\t);\n\n\t// List command - shows auth profiles\n\tcmd\n\t\t.command('list')\n\t\t.description('List all configured authentication credentials')\n\t\t.action(() => {\n\t\t\tlistAuthProfiles();\n\t\t});\n\n\t// Set command\n\tcmd\n\t\t.command('set <provider> <key>')\n\t\t.description('Set API key for a provider')\n\t\t.option('-p, --profile <profileId>', 'Profile ID (default: provider:default)')\n\t\t.action((provider: string, key: string, options: { profile?: string }) => {\n\t\t\tconst profileId = options.profile || `${provider}:default`;\n\t\t\t\n\t\t\tconst credential: AuthProfileCredential = {\n\t\t\t\ttype: 'api_key',\n\t\t\t\tprovider,\n\t\t\t\tkey,\n\t\t\t};\n\t\t\t\n\t\t\tupsertAuthProfile({ profileId, credential });\n\t\t\tlog.info(`API key set for ${provider} (profile: ${profileId})`);\n\t\t});\n\n\t// Get command\n\tcmd\n\t\t.command('get <provider>')\n\t\t.description('Get API key for a provider (shows masked)')\n\t\t.option('-p, --profile <profileId>', 'Profile ID')\n\t\t.action(async (provider: string, _options: { profile?: string }) => {\n\t\t\tconst profiles = listProfilesForProvider(provider);\n\t\t\t\n\t\t\tif (profiles.length === 0) {\n\t\t\t\tlog.error(`No credentials found for provider: ${provider}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tfor (const profile of profiles) {\n\t\t\t\tconst _masked = '****';\n\t\t\t\tconst status = colorizeStatus(profile.hasKey);\n\t\t\t\tconsole.log(`\\nProvider: ${provider}`);\n\t\t\t\tconsole.log(`Profile: ${profile.profileId}`);\n\t\t\t\tconsole.log(`Type: ${profile.type}`);\n\t\t\t\tconsole.log(`Status: ${status} ${profile.hasKey ? 'Configured' : 'Missing'}`);\n\t\t\t\tif (profile.expires) {\n\t\t\t\t\tconst expDate = new Date(profile.expires);\n\t\t\t\t\tconsole.log(`Expires: ${expDate.toLocaleString()}`);\n\t\t\t\t}\n\t\t\t\tconsole.log('');\n\t\t\t}\n\t\t});\n\n\t// Remove command\n\tcmd\n\t\t.command('remove <provider>')\n\t\t.description('Remove authentication for a provider')\n\t\t.option('-p, --profile <profileId>', 'Profile ID to remove')\n\t\t.action((provider: string, options: { profile?: string }) => {\n\t\t\tif (options.profile) {\n\t\t\t\tconst removed = removeAuthProfile(options.profile);\n\t\t\t\tif (removed) {\n\t\t\t\t\tlog.info(`Profile removed: ${options.profile}`);\n\t\t\t\t} else {\n\t\t\t\t\tlog.warn(`Profile not found: ${options.profile}`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// Remove all profiles for provider\n\t\t\tconst profiles = listProfilesForProvider(provider);\n\t\t\tfor (const profile of profiles) {\n\t\t\t\tremoveAuthProfile(profile.profileId);\n\t\t\t}\n\t\t\tlog.info(`All profiles removed for provider: ${provider}`);\n\t\t});\n\n\t// Login command (OAuth)\n\tcmd\n\t\t.command('login <provider>')\n\t\t.description('Login to a provider using OAuth')\n\t\t.option('-p, --profile <profileId>', 'Profile ID (default: provider:default)')\n\t\t.action(async (provider: string, options: { profile?: string }) => {\n\t\t\tconst oauthConfig = getOAuthProvider(provider);\n\t\t\t\n\t\t\tif (!oauthConfig) {\n\t\t\t\tlog.error(`OAuth not supported for provider: ${provider}`);\n\t\t\t\tlog.info(`Supported OAuth providers: ${getSupportedOAuthProviders().join(', ')}`);\n\t\t\t\tlog.info('Alternatively, set an API key: xopc auth set <provider> <key>');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tlog.info(`Starting ${oauthConfig.displayName} OAuth login...`);\n\t\t\t\n\t\t\tconst callbacks: OAuthLoginCallbacks = {\n\t\t\t\tonAuth: (info) => {\n\t\t\t\t\tconsole.log('\\n' + oauthConfig.urlPrompt);\n\t\t\t\t\tconsole.log(info.url);\n\t\t\t\t\tif (info.instructions) {\n\t\t\t\t\t\tconsole.log('\\n' + info.instructions);\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log('\\n');\n\t\t\t\t},\n\t\t\t\tonPrompt: async (prompt) => {\n\t\t\t\t\tconst { input } = await import('@inquirer/prompts');\n\t\t\t\t\treturn input({ message: prompt.message });\n\t\t\t\t},\n\t\t\t\tonProgress: (message) => {\n\t\t\t\t\tlog.info(message);\n\t\t\t\t},\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\tconst creds = await oauthConfig.provider.login(callbacks);\n\t\t\t\tconst profileId = options.profile || oauthConfig.profileId;\n\t\t\t\tupsertAuthProfile({\n\t\t\t\t\tprofileId,\n\t\t\t\t\tcredential: {\n\t\t\t\t\t\ttype: 'oauth',\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\t...creds,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tlog.info(`✅ OAuth login successful! Profile: ${profileId}`);\n\t\t\t} catch (error) {\n\t\t\t\tlog.error(`OAuth login failed: ${error}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t});\n\n\t// Logout command\n\tcmd\n\t\t.command('logout <provider>')\n\t\t.description('Logout from a provider (remove credentials)')\n\t\t.option('-p, --profile <profileId>', 'Profile ID to remove')\n\t\t.action((provider: string, options: { profile?: string }) => {\n\t\t\tif (options.profile) {\n\t\t\t\tconst removed = removeAuthProfile(options.profile);\n\t\t\t\tif (removed) {\n\t\t\t\t\tlog.info(`Logged out: ${options.profile}`);\n\t\t\t\t} else {\n\t\t\t\t\tlog.warn(`Profile not found: ${options.profile}`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// Remove all profiles for provider\n\t\t\tconst profiles = listProfilesForProvider(provider);\n\t\t\tif (profiles.length === 0) {\n\t\t\t\tlog.warn(`No profiles found for provider: ${provider}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tfor (const profile of profiles) {\n\t\t\t\tremoveAuthProfile(profile.profileId);\n\t\t\t}\n\t\t\tlog.info(`Logged out from provider: ${provider}`);\n\t\t});\n\n\t// Profiles subcommand\n\tconst profilesCmd = cmd\n\t\t.command('profiles')\n\t\t.description('Manage auth profiles');\n\n\tprofilesCmd\n\t\t.command('list')\n\t\t.description('List all auth profiles')\n\t\t.action(() => {\n\t\t\tlistAuthProfiles();\n\t\t});\n\n\tprofilesCmd\n\t\t.command('add')\n\t\t.description('Add a new auth profile')\n\t\t.requiredOption('-p, --profile <profileId>', 'Profile ID (e.g., openai:work)')\n\t\t.requiredOption('-t, --type <type>', 'Credential type (api_key, token, oauth)')\n\t\t.option('-k, --key <key>', 'API key (for api_key type)')\n\t\t.option('-e, --email <email>', 'Email associated with the credential')\n\t\t.action((options) => {\n\t\t\tconst { profile, type, key, email } = options;\n\t\t\t\n\t\t\tlet credential: AuthProfileCredential;\n\t\t\t\n\t\t\tif (type === 'api_key') {\n\t\t\t\tif (!key) {\n\t\t\t\t\tlog.error('API key required for api_key type');\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tcredential = { type: 'api_key', provider: profile.split(':')[0], key, email };\n\t\t\t} else if (type === 'token') {\n\t\t\t\tif (!key) {\n\t\t\t\t\tlog.error('Token required for token type');\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tcredential = { type: 'token', provider: profile.split(':')[0], token: key, email };\n\t\t\t} else {\n\t\t\t\tlog.error('OAuth credentials must be added via \"xopc auth login\"');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\t\n\t\t\tupsertAuthProfile({ profileId: profile, credential });\n\t\t\tlog.info(`Profile added: ${profile}`);\n\t\t});\n\n\t// Clear command\n\tcmd\n\t\t.command('clear')\n\t\t.description('Clear all authentication credentials')\n\t\t.action(() => {\n\t\t\tconst profiles = listAllProfiles();\n\t\t\tfor (const profile of profiles) {\n\t\t\t\tremoveAuthProfile(profile.profileId);\n\t\t\t}\n\t\t\t\n\t\t\tlog.info('All authentication credentials cleared.');\n\t\t});\n\n\t// Providers command - show supported providers\n\tcmd\n\t\t.command('providers')\n\t\t.description('List supported providers and their auth methods')\n\t\t.action(() => {\n\t\t\tconsole.log('\\nSupported providers:\\n');\n\t\t\t\n\t\t\t// Built-in providers from pi-ai\n\t\t\tconst providers = getAllProviders();\n\t\t\t\n\t\t\tfor (const id of providers) {\n\t\t\t\tconsole.log(` ${id}`);\n\t\t\t}\n\t\t\t\n\t\t\tconsole.log('\\nSet API key: xopc auth set <provider> <key>');\n\t\t\tconsole.log('Environment variables: PROVIDER_API_KEY\\n');\n\t\t});\n\n\treturn cmd;\n}\n\nfunction listAuthProfiles(): void {\n\tconst profiles = listAllProfiles();\n\t\n\tif (profiles.length === 0) {\n\t\tlog.info('No auth profiles configured.');\n\t\tlog.info('Set an API key: xopc auth set <provider> <key>');\n\t\tlog.info('Or login with OAuth: xopc auth login <provider>');\n\t\treturn;\n\t}\n\n\tconsole.log('\\nAuth profiles:\\n');\n\tfor (const profile of profiles) {\n\t\tconst typeColor = profile.type === 'oauth' ? colors.yellow :\n\t\t\tprofile.type === 'token' ? colors.cyan : colors.blue;\n\t\tconst status = colorizeStatus(profile.hasKey);\n\t\t\n\t\tconsole.log(` ${profile.profileId}`);\n\t\tconsole.log(` Type: ${typeColor(profile.type)}`);\n\t\tconsole.log(` Status: ${status} ${profile.hasKey ? 'Configured' : 'Missing'}`);\n\t\tif (profile.email) {\n\t\t\tconsole.log(` Email: ${profile.email}`);\n\t\t}\n\t\tif (profile.expires) {\n\t\t\tconst expDate = new Date(profile.expires);\n\t\t\tconst isExpired = Date.now() >= profile.expires;\n\t\t\tconsole.log(` Expires: ${isExpired ? colors.red('') : ''}${expDate.toLocaleString()}`);\n\t\t}\n\t\tconsole.log('');\n\t}\n}\n\n// Register the command\nregister({\n\tid: 'auth',\n\tname: 'auth',\n\tdescription: 'Manage authentication credentials',\n\tfactory: createAuthCommand,\n\tmetadata: { \n\t\tcategory: 'setup',\n\t\texamples: [\n\t\t\t'xopc auth list',\n\t\t\t'xopc auth providers',\n\t\t\t'xopc auth set openai sk-xxx',\n\t\t\t'xopc auth login anthropic',\n\t\t\t'xopc auth login kimi-coding',\n\t\t\t'xopc auth profiles list',\n\t\t],\n\t},\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","names":[],"sources":["../../../../src/cli/commands/auth.ts"],"sourcesContent":["/**\n * Auth Command\n * \n * Manage authentication credentials (API keys, OAuth tokens, Auth Profiles).\n */\n\nimport { Command } from 'commander';\nimport { type OAuthLoginCallbacks } from '../../auth/index.js';\nimport {\n\tlistProfilesForProvider,\n\tlistAllProfiles,\n\tupsertAuthProfile,\n\tremoveAuthProfile,\n\ttype AuthProfileCredential,\n} from '../../auth/profiles/index.js';\nimport { getAllProviders } from '../../providers/index.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { colors, colorizeStatus } from '../utils/colors.js';\nimport { getOAuthProvider, getSupportedOAuthProviders } from '../utils/oauth-providers.js';\n\nconst log = createLogger('AuthCommand');\n\nfunction createAuthCommand(_ctx: CLIContext): Command {\n\tconst cmd = new Command('auth')\n\t\t.description('Manage authentication credentials')\n\t\t.addHelpText(\n\t\t\t'after',\n\t\t\tformatExamples([\n\t\t\t\t'xopc auth list',\n\t\t\t\t'xopc auth set openai sk-xxx',\n\t\t\t\t'xopc auth set anthropic sk-ant-api-xxx',\n\t\t\t\t'xopc auth login anthropic',\n\t\t\t\t'xopc auth login kimi-coding',\n\t\t\t\t'xopc auth logout anthropic',\n\t\t\t\t'xopc auth remove anthropic',\n\t\t\t\t'xopc auth profiles list',\n\t\t\t])\n\t\t);\n\n\t// List command - shows auth profiles\n\tcmd\n\t\t.command('list')\n\t\t.description('List all configured authentication credentials')\n\t\t.action(() => {\n\t\t\tlistAuthProfiles();\n\t\t});\n\n\t// Set command\n\tcmd\n\t\t.command('set <provider> <key>')\n\t\t.description('Set API key for a provider')\n\t\t.option('-p, --profile <profileId>', 'Profile ID (default: provider:default)')\n\t\t.action((provider: string, key: string, options: { profile?: string }) => {\n\t\t\tconst profileId = options.profile || `${provider}:default`;\n\t\t\t\n\t\t\tconst credential: AuthProfileCredential = {\n\t\t\t\ttype: 'api_key',\n\t\t\t\tprovider,\n\t\t\t\tkey,\n\t\t\t};\n\t\t\t\n\t\t\tupsertAuthProfile({ profileId, credential });\n\t\t\tlog.info(`API key set for ${provider} (profile: ${profileId})`);\n\t\t});\n\n\t// Get command\n\tcmd\n\t\t.command('get <provider>')\n\t\t.description('Get API key for a provider (shows masked)')\n\t\t.option('-p, --profile <profileId>', 'Profile ID')\n\t\t.action(async (provider: string, _options: { profile?: string }) => {\n\t\t\tconst profiles = listProfilesForProvider(provider);\n\t\t\t\n\t\t\tif (profiles.length === 0) {\n\t\t\t\tlog.error(`No credentials found for provider: ${provider}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tfor (const profile of profiles) {\n\t\t\t\tconst _masked = '****';\n\t\t\t\tconst status = colorizeStatus(profile.hasKey);\n\t\t\t\tconsole.log(`\\nProvider: ${provider}`);\n\t\t\t\tconsole.log(`Profile: ${profile.profileId}`);\n\t\t\t\tconsole.log(`Type: ${profile.type}`);\n\t\t\t\tconsole.log(`Status: ${status} ${profile.hasKey ? 'Configured' : 'Missing'}`);\n\t\t\t\tif (profile.expires) {\n\t\t\t\t\tconst expDate = new Date(profile.expires);\n\t\t\t\t\tconsole.log(`Expires: ${expDate.toLocaleString()}`);\n\t\t\t\t}\n\t\t\t\tconsole.log('');\n\t\t\t}\n\t\t});\n\n\t// Remove command\n\tcmd\n\t\t.command('remove <provider>')\n\t\t.description('Remove authentication for a provider')\n\t\t.option('-p, --profile <profileId>', 'Profile ID to remove')\n\t\t.action((provider: string, options: { profile?: string }) => {\n\t\t\tif (options.profile) {\n\t\t\t\tconst removed = removeAuthProfile(options.profile);\n\t\t\t\tif (removed) {\n\t\t\t\t\tlog.info(`Profile removed: ${options.profile}`);\n\t\t\t\t} else {\n\t\t\t\t\tlog.warn(`Profile not found: ${options.profile}`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// Remove all profiles for provider\n\t\t\tconst profiles = listProfilesForProvider(provider);\n\t\t\tfor (const profile of profiles) {\n\t\t\t\tremoveAuthProfile(profile.profileId);\n\t\t\t}\n\t\t\tlog.info(`All profiles removed for provider: ${provider}`);\n\t\t});\n\n\t// Login command (OAuth)\n\tcmd\n\t\t.command('login <provider>')\n\t\t.description('Login to a provider using OAuth')\n\t\t.option('-p, --profile <profileId>', 'Profile ID (default: provider:default)')\n\t\t.action(async (provider: string, options: { profile?: string }) => {\n\t\t\tconst oauthConfig = getOAuthProvider(provider);\n\t\t\t\n\t\t\tif (!oauthConfig) {\n\t\t\t\tlog.error(`OAuth not supported for provider: ${provider}`);\n\t\t\t\tlog.info(`Supported OAuth providers: ${getSupportedOAuthProviders().join(', ')}`);\n\t\t\t\tlog.info('Alternatively, set an API key: xopc auth set <provider> <key>');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\n\t\t\tlog.info(`Starting ${oauthConfig.displayName} OAuth login...`);\n\t\t\t\n\t\t\tconst callbacks: OAuthLoginCallbacks = {\n\t\t\t\tonAuth: (info) => {\n\t\t\t\t\tconsole.log('\\n' + oauthConfig.urlPrompt);\n\t\t\t\t\tconsole.log(info.url);\n\t\t\t\t\tif (info.instructions) {\n\t\t\t\t\t\tconsole.log('\\n' + info.instructions);\n\t\t\t\t\t}\n\t\t\t\t\tconsole.log('\\n');\n\t\t\t\t},\n\t\t\t\tonDeviceCode: (info) => {\n\t\t\t\t\tconsole.log(`\\nOpen ${info.verificationUri} and enter code ${info.userCode}\\n`);\n\t\t\t\t},\n\t\t\t\tonPrompt: async (prompt) => {\n\t\t\t\t\tconst { input } = await import('@inquirer/prompts');\n\t\t\t\t\treturn input({ message: prompt.message });\n\t\t\t\t},\n\t\t\t\tonProgress: (message) => {\n\t\t\t\t\tlog.info(message);\n\t\t\t\t},\n\t\t\t\tonSelect: async (prompt) => {\n\t\t\t\t\tconst browserOption = prompt.options.find((option) => option.id === 'browser');\n\t\t\t\t\treturn browserOption?.id ?? prompt.options[0]?.id;\n\t\t\t\t},\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\tconst creds = await oauthConfig.provider.login(callbacks);\n\t\t\t\tconst profileId = options.profile || oauthConfig.profileId;\n\t\t\t\tupsertAuthProfile({\n\t\t\t\t\tprofileId,\n\t\t\t\t\tcredential: {\n\t\t\t\t\t\ttype: 'oauth',\n\t\t\t\t\t\tprovider,\n\t\t\t\t\t\t...creds,\n\t\t\t\t\t},\n\t\t\t\t});\n\t\t\t\tlog.info(`✅ OAuth login successful! Profile: ${profileId}`);\n\t\t\t} catch (error) {\n\t\t\t\tlog.error(`OAuth login failed: ${error}`);\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t});\n\n\t// Logout command\n\tcmd\n\t\t.command('logout <provider>')\n\t\t.description('Logout from a provider (remove credentials)')\n\t\t.option('-p, --profile <profileId>', 'Profile ID to remove')\n\t\t.action((provider: string, options: { profile?: string }) => {\n\t\t\tif (options.profile) {\n\t\t\t\tconst removed = removeAuthProfile(options.profile);\n\t\t\t\tif (removed) {\n\t\t\t\t\tlog.info(`Logged out: ${options.profile}`);\n\t\t\t\t} else {\n\t\t\t\t\tlog.warn(`Profile not found: ${options.profile}`);\n\t\t\t\t}\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\t// Remove all profiles for provider\n\t\t\tconst profiles = listProfilesForProvider(provider);\n\t\t\tif (profiles.length === 0) {\n\t\t\t\tlog.warn(`No profiles found for provider: ${provider}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\t\n\t\t\tfor (const profile of profiles) {\n\t\t\t\tremoveAuthProfile(profile.profileId);\n\t\t\t}\n\t\t\tlog.info(`Logged out from provider: ${provider}`);\n\t\t});\n\n\t// Profiles subcommand\n\tconst profilesCmd = cmd\n\t\t.command('profiles')\n\t\t.description('Manage auth profiles');\n\n\tprofilesCmd\n\t\t.command('list')\n\t\t.description('List all auth profiles')\n\t\t.action(() => {\n\t\t\tlistAuthProfiles();\n\t\t});\n\n\tprofilesCmd\n\t\t.command('add')\n\t\t.description('Add a new auth profile')\n\t\t.requiredOption('-p, --profile <profileId>', 'Profile ID (e.g., openai:work)')\n\t\t.requiredOption('-t, --type <type>', 'Credential type (api_key, token, oauth)')\n\t\t.option('-k, --key <key>', 'API key (for api_key type)')\n\t\t.option('-e, --email <email>', 'Email associated with the credential')\n\t\t.action((options) => {\n\t\t\tconst { profile, type, key, email } = options;\n\t\t\t\n\t\t\tlet credential: AuthProfileCredential;\n\t\t\t\n\t\t\tif (type === 'api_key') {\n\t\t\t\tif (!key) {\n\t\t\t\t\tlog.error('API key required for api_key type');\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tcredential = { type: 'api_key', provider: profile.split(':')[0], key, email };\n\t\t\t} else if (type === 'token') {\n\t\t\t\tif (!key) {\n\t\t\t\t\tlog.error('Token required for token type');\n\t\t\t\t\tprocess.exit(1);\n\t\t\t\t}\n\t\t\t\tcredential = { type: 'token', provider: profile.split(':')[0], token: key, email };\n\t\t\t} else {\n\t\t\t\tlog.error('OAuth credentials must be added via \"xopc auth login\"');\n\t\t\t\tprocess.exit(1);\n\t\t\t}\n\t\t\t\n\t\t\tupsertAuthProfile({ profileId: profile, credential });\n\t\t\tlog.info(`Profile added: ${profile}`);\n\t\t});\n\n\t// Clear command\n\tcmd\n\t\t.command('clear')\n\t\t.description('Clear all authentication credentials')\n\t\t.action(() => {\n\t\t\tconst profiles = listAllProfiles();\n\t\t\tfor (const profile of profiles) {\n\t\t\t\tremoveAuthProfile(profile.profileId);\n\t\t\t}\n\t\t\t\n\t\t\tlog.info('All authentication credentials cleared.');\n\t\t});\n\n\t// Providers command - show supported providers\n\tcmd\n\t\t.command('providers')\n\t\t.description('List supported providers and their auth methods')\n\t\t.action(() => {\n\t\t\tconsole.log('\\nSupported providers:\\n');\n\t\t\t\n\t\t\t// Built-in providers from pi-ai\n\t\t\tconst providers = getAllProviders();\n\t\t\t\n\t\t\tfor (const id of providers) {\n\t\t\t\tconsole.log(` ${id}`);\n\t\t\t}\n\t\t\t\n\t\t\tconsole.log('\\nSet API key: xopc auth set <provider> <key>');\n\t\t\tconsole.log('Environment variables: PROVIDER_API_KEY\\n');\n\t\t});\n\n\treturn cmd;\n}\n\nfunction listAuthProfiles(): void {\n\tconst profiles = listAllProfiles();\n\t\n\tif (profiles.length === 0) {\n\t\tlog.info('No auth profiles configured.');\n\t\tlog.info('Set an API key: xopc auth set <provider> <key>');\n\t\tlog.info('Or login with OAuth: xopc auth login <provider>');\n\t\treturn;\n\t}\n\n\tconsole.log('\\nAuth profiles:\\n');\n\tfor (const profile of profiles) {\n\t\tconst typeColor = profile.type === 'oauth' ? colors.yellow :\n\t\t\tprofile.type === 'token' ? colors.cyan : colors.blue;\n\t\tconst status = colorizeStatus(profile.hasKey);\n\t\t\n\t\tconsole.log(` ${profile.profileId}`);\n\t\tconsole.log(` Type: ${typeColor(profile.type)}`);\n\t\tconsole.log(` Status: ${status} ${profile.hasKey ? 'Configured' : 'Missing'}`);\n\t\tif (profile.email) {\n\t\t\tconsole.log(` Email: ${profile.email}`);\n\t\t}\n\t\tif (profile.expires) {\n\t\t\tconst expDate = new Date(profile.expires);\n\t\t\tconst isExpired = Date.now() >= profile.expires;\n\t\t\tconsole.log(` Expires: ${isExpired ? colors.red('') : ''}${expDate.toLocaleString()}`);\n\t\t}\n\t\tconsole.log('');\n\t}\n}\n\n// Register the command\nregister({\n\tid: 'auth',\n\tname: 'auth',\n\tdescription: 'Manage authentication credentials',\n\tfactory: createAuthCommand,\n\tmetadata: { \n\t\tcategory: 'setup',\n\t\texamples: [\n\t\t\t'xopc auth list',\n\t\t\t'xopc auth providers',\n\t\t\t'xopc auth set openai sk-xxx',\n\t\t\t'xopc auth login anthropic',\n\t\t\t'xopc auth login kimi-coding',\n\t\t\t'xopc auth profiles list',\n\t\t],\n\t},\n});\n"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
2
1
  import { ConfigSchema, init_schema } from "../../config/schema.js";
2
+ import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
3
3
  import { resolveGatewayLocalClientHost } from "../../config/gateway-bind.js";
4
4
  import { formatExamples, register } from "../registry.js";
5
5
  import { existsSync, readFileSync } from "fs";
@@ -1,7 +1,7 @@
1
1
  import { ConfigSchema, init_schema } from "../../../../config/schema.js";
2
2
  import { init_loader, loadConfig, saveConfig } from "../../../../config/loader.js";
3
- import { existsSync, mkdirSync, readFileSync } from "node:fs";
4
3
  import { dirname } from "node:path";
4
+ import { existsSync, mkdirSync, readFileSync } from "node:fs";
5
5
  //#region src/cli/commands/doctor/checks/config-health.ts
6
6
  init_loader();
7
7
  init_schema();
@@ -1,6 +1,6 @@
1
- import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
2
1
  import { getAgentDefaultModelRef, init_schema, parseModelRef } from "../../../../config/schema.js";
3
2
  import { init_loader, loadConfig } from "../../../../config/loader.js";
3
+ import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
4
4
  import { existsSync } from "node:fs";
5
5
  //#region src/cli/commands/doctor/checks/provider-auth.ts
6
6
  init_loader();
@@ -2,8 +2,8 @@ import { init_agent_scope, resolveDefaultAgentId } from "../../../../agent/agent
2
2
  import { init_transcript_paths, resolveSessionFilePath } from "../../../../session/parity/transcript-paths.js";
3
3
  import { FILENAMES, init_paths, resolveSessionsDir } from "../../../../config/paths.js";
4
4
  import { init_loader, loadConfig } from "../../../../config/loader.js";
5
- import { existsSync, readFileSync } from "node:fs";
6
5
  import { join } from "node:path";
6
+ import { existsSync, readFileSync } from "node:fs";
7
7
  //#region src/cli/commands/doctor/checks/session-integrity.ts
8
8
  init_agent_scope();
9
9
  init_loader();
@@ -1,5 +1,5 @@
1
- import { accessSync, chmodSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
2
1
  import { join } from "node:path";
2
+ import { accessSync, chmodSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
3
3
  //#region src/cli/commands/doctor/checks/state-integrity.ts
4
4
  function isWritable(dir) {
5
5
  try {
@@ -1,8 +1,8 @@
1
1
  import { init_agent_scope, resolveAgentProfileDir, resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../../../../agent/agent-scope.js";
2
2
  import { WORKSPACE_FILES, init_paths } from "../../../../config/paths.js";
3
3
  import { init_loader, loadConfig } from "../../../../config/loader.js";
4
- import { existsSync } from "node:fs";
5
4
  import { join } from "node:path";
5
+ import { existsSync } from "node:fs";
6
6
  //#region src/cli/commands/doctor/checks/workspace-status.ts
7
7
  init_agent_scope();
8
8
  init_loader();
@@ -12,8 +12,8 @@ import { runGatewayLoop } from "../../gateway/run-loop.js";
12
12
  import "../../gateway/index.js";
13
13
  import { colors } from "../utils/colors.js";
14
14
  import { initWorkspace } from "../utils/init-workspace.js";
15
- import { existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, watch } from "node:fs";
16
15
  import { join, resolve } from "node:path";
16
+ import { existsSync, mkdirSync, readFileSync, symlinkSync, unlinkSync, watch } from "node:fs";
17
17
  import { Command } from "commander";
18
18
  //#region src/cli/commands/extension-dev.ts
19
19
  init_loader();
@@ -7,8 +7,8 @@ import { installExtensionFromStoreZip, installFromLocal, installFromNpm, peekExt
7
7
  import { fetchRegistry, findExtension, getExtensionMarketplaceStoreBaseUrl, listExtensions, searchExtensions } from "../../extensions/marketplace.js";
8
8
  import { downloadExtensionStoreZipBuffer, resolveExtensionZipDownloadUrl, resolveExtensionsStoreBaseUrl } from "../../agent/skills/marketplace/adapters/store/store-api-client.js";
9
9
  import { colors } from "../utils/colors.js";
10
- import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
11
10
  import { join, resolve } from "node:path";
11
+ import { existsSync, readFileSync, rmSync, statSync } from "node:fs";
12
12
  import { execSync } from "node:child_process";
13
13
  import { Command } from "commander";
14
14
  import semver from "semver";
@@ -4,8 +4,8 @@ import { init_logger } from "../../utils/logger.js";
4
4
  import { normalizeExtensionManifest } from "../../extensions/normalize-manifest.js";
5
5
  import { checkEngineCompatibility } from "../../extensions/engine-check.js";
6
6
  import { colors } from "../utils/colors.js";
7
- import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
8
7
  import { isAbsolute, join, resolve } from "node:path";
8
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, statSync } from "node:fs";
9
9
  import { execSync } from "node:child_process";
10
10
  import { Command } from "commander";
11
11
  //#region src/cli/commands/extension-pack.ts
@@ -1,8 +1,8 @@
1
1
  import { init_paths, resolveConfigPath } from "../../../config/paths.js";
2
2
  import { loadConfig } from "../../../config/loader.js";
3
3
  import "../../../config/index.js";
4
- import { isRestartEnabled } from "../../../config/commands.flags.js";
5
4
  import { resolveGatewayService } from "../../../daemon/service.js";
5
+ import { isRestartEnabled } from "../../../config/commands.flags.js";
6
6
  import { authorizeGatewaySigusr1Restart, writeGatewayRestartIntentSync } from "../../../infra/restart.js";
7
7
  import { findVerifiedGatewayListenerPidsOnPortSync, formatGatewayPidList, signalVerifiedGatewayPidSync } from "../../../infra/gateway-processes.js";
8
8
  import { runServiceRestart, runServiceStop } from "./lifecycle-core.js";
@@ -1,7 +1,7 @@
1
1
  import { getContextWithOpts } from "../../context.js";
2
+ import path from "node:path";
2
3
  import { existsSync, statSync, watch } from "node:fs";
3
4
  import { readFile } from "node:fs/promises";
4
- import path from "node:path";
5
5
  import { Command } from "commander";
6
6
  //#region src/cli/commands/gateway/logs.ts
7
7
  function parseLineCount(value) {
@@ -8,8 +8,8 @@ import { formatExamples, register } from "../registry.js";
8
8
  import { getContextWithOpts } from "../context.js";
9
9
  import "../../agent/image/index.js";
10
10
  import { colors } from "../utils/colors.js";
11
- import { mkdir, writeFile } from "node:fs/promises";
12
11
  import { join, resolve } from "node:path";
12
+ import { mkdir, writeFile } from "node:fs/promises";
13
13
  import { Command } from "commander";
14
14
  //#region src/cli/commands/image.ts
15
15
  init_loader();
@@ -1,14 +1,14 @@
1
- import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
2
- import { createLogger } from "../../utils/logger/index.js";
3
- import { init_logger } from "../../utils/logger.js";
4
1
  import { resolveStateDir } from "../../config/paths-state.js";
5
2
  import { resolveAgentWorkspaceDir } from "../../agent/agent-scope.js";
3
+ import { createLogger } from "../../utils/logger/index.js";
4
+ import { init_logger } from "../../utils/logger.js";
6
5
  import { WORKSPACE_FILES, init_paths, resolveAgentDir, resolveAgentHomeDir, resolveAgentMetadataPath, resolveAgentProfileDir, resolveBinDir, resolveConfigPath, resolveCredentialsDir, resolveCronDir, resolveExtensionsDir, resolveInboxDir, resolveInboxPendingDir, resolveInboxProcessedDir, resolveLogsDir, resolveSessionsDir, resolveSkillsDir, resolveToolsDir, resolveWorkspaceStateDir, resolveWorkspaceStatePath } from "../../config/paths.js";
6
+ import { init_write_file_atomic, writeTextAtomic } from "../../infra/write-file-atomic.js";
7
7
  import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
8
8
  import { formatExamples, register } from "../registry.js";
9
- import { mkdir, writeFile } from "fs/promises";
10
9
  import { join } from "path";
11
10
  import { existsSync } from "fs";
11
+ import { mkdir, writeFile } from "fs/promises";
12
12
  import { Command } from "commander";
13
13
  //#region src/cli/commands/init.ts
14
14
  init_write_file_atomic();
@@ -38,11 +38,17 @@ async function doOAuthLogin(provider) {
38
38
  if (info.instructions) console.log("\n" + info.instructions);
39
39
  console.log("\n");
40
40
  },
41
+ onDeviceCode: (info) => {
42
+ console.log(`\nOpen ${info.verificationUri} and enter code ${info.userCode}\n`);
43
+ },
41
44
  onPrompt: async (prompt) => {
42
45
  return input({ message: prompt.message });
43
46
  },
44
47
  onProgress: (message) => {
45
48
  console.log(" →", message);
49
+ },
50
+ onSelect: async (prompt) => {
51
+ return prompt.options.find((option) => option.id === "browser")?.id ?? prompt.options[0]?.id;
46
52
  }
47
53
  };
48
54
  try {