@xopcai/xopc 0.0.88 → 0.0.90
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.
- package/README.md +8 -1
- package/README.zh-CN.md +8 -1
- package/dist/browser-ext/manifest.json +1 -1
- package/dist/extensions/telegram/xopc.extension.json +1 -1
- package/dist/gateway/static/root/assets/agents-cPvvYLXo.js +222 -0
- package/dist/gateway/static/root/assets/apps-page-Bk1_P5FJ.js +1 -0
- package/dist/gateway/static/root/assets/channels-settings-CZoeQwHz.js +1 -0
- package/dist/gateway/static/root/assets/{channels-status-swr-DIsl75Y3.js → channels-status-swr-BrtH2VzC.js} +1 -1
- package/dist/gateway/static/root/assets/circle-check-C23XjkUj.js +1 -0
- package/dist/gateway/static/root/assets/cron-api-CyqbgfHM.js +1 -0
- package/dist/gateway/static/root/assets/cron-dreaming-jobs-Ip703-qM.js +2 -0
- package/dist/gateway/static/root/assets/cron-page-BpLdiQN8.js +1 -0
- package/dist/gateway/static/root/assets/dist-BpAiK86n.js +1 -0
- package/dist/gateway/static/root/assets/{extension-debug-page-BVJohZoZ.js → extension-debug-page-D6Ak0STa.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-BT2tmElC.js → extension-page-Q0P3d6DW.js} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-BSS47c2j.js → extension-settings-page-CL55LwU_.js} +1 -1
- package/dist/gateway/static/root/assets/eye-DAfL1U7M.js +1 -0
- package/dist/gateway/static/root/assets/{fetch-BaFNUtkE.js → fetch-Dqa9iTWl.js} +1 -1
- package/dist/gateway/static/root/assets/{field-primitives-QwYEq6Hz.js → field-primitives-HUR6JElP.js} +1 -1
- package/dist/gateway/static/root/assets/{heartbeat-config-api-BVSidEDJ.js → heartbeat-config-api-DusckjUX.js} +1 -1
- package/dist/gateway/static/root/assets/{index-qNrVJp-y.js → index-BYcGfwcE.js} +97 -97
- package/dist/gateway/static/root/assets/index-V7MQ7834.css +1 -0
- package/dist/gateway/static/root/assets/{logs-page-DDonPVLn.js → logs-page-_HcZ2fgK.js} +1 -1
- package/dist/gateway/static/root/assets/sessions-page-iezSMjho.js +1 -0
- package/dist/gateway/static/root/assets/{settings-form-section-B8N3A3Zo.js → settings-form-section-a0qGVOlr.js} +1 -1
- package/dist/gateway/static/root/assets/settings-page-C9_nYQwM.js +3 -0
- package/dist/gateway/static/root/assets/{share-preview-page-Q7KqkO-u.js → share-preview-page-DExl7CJy.js} +1 -1
- package/dist/gateway/static/root/assets/skills-page-BlgGD93t.js +2 -0
- package/dist/gateway/static/root/assets/{theme-store-BbRc5ugR.js → theme-store-C0Ehmdo5.js} +1 -1
- package/dist/gateway/static/root/assets/url-fxyYANfA.js +3 -0
- package/dist/gateway/static/root/assets/{utils-CxDGduqK.js → utils-DRQryzdn.js} +1 -1
- package/dist/gateway/static/root/assets/voice-api-key-field-D0viACE2.js +1 -0
- package/dist/gateway/static/root/assets/workflow-page.utils-DnG8JBhV.js +1 -0
- package/dist/gateway/static/root/assets/workflows-page-BvMobnJP.js +27 -0
- package/dist/gateway/static/root/index.html +7 -6
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +2 -0
- package/dist/src/agent/agent-manager.js +1 -0
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/service.js +2 -1
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/service.types.d.ts +3 -1
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js +20 -18
- package/dist/src/agent/skills/marketplace/adapters/skillhub/adapter.js.map +1 -1
- package/dist/src/agent/tools/cronjob-tool.d.ts +6 -0
- package/dist/src/agent/tools/cronjob-tool.js +76 -10
- package/dist/src/agent/tools/cronjob-tool.js.map +1 -1
- package/dist/src/agent/tools/edit.d.ts +5 -1
- package/dist/src/agent/tools/edit.js +7 -5
- package/dist/src/agent/tools/edit.js.map +1 -1
- package/dist/src/agent/tools/factory.d.ts +3 -0
- package/dist/src/agent/tools/factory.js +4 -25
- package/dist/src/agent/tools/factory.js.map +1 -1
- package/dist/src/agent/tools/workflow-tool.d.ts +6 -28
- package/dist/src/agent/tools/workflow-tool.js +60 -260
- package/dist/src/agent/tools/workflow-tool.js.map +1 -1
- package/dist/src/agent/tools/write.d.ts +5 -1
- package/dist/src/agent/tools/write.js +7 -5
- package/dist/src/agent/tools/write.js.map +1 -1
- package/dist/src/agent/workflow/agent-progress.js +2 -0
- package/dist/src/agent/workflow/agent-progress.js.map +1 -1
- package/dist/src/agent/workflow/builtins/client-proposal.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/client-proposal.js +155 -0
- package/dist/src/agent/workflow/builtins/client-proposal.js.map +1 -0
- package/dist/src/agent/workflow/builtins/competitor-scan.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/competitor-scan.js +150 -0
- package/dist/src/agent/workflow/builtins/competitor-scan.js.map +1 -0
- package/dist/src/agent/workflow/builtins/content-draft.d.ts +13 -0
- package/dist/src/agent/workflow/builtins/content-draft.js +146 -0
- package/dist/src/agent/workflow/builtins/content-draft.js.map +1 -0
- package/dist/src/agent/workflow/builtins/content-repurpose.d.ts +11 -0
- package/dist/src/agent/workflow/builtins/content-repurpose.js +137 -0
- package/dist/src/agent/workflow/builtins/content-repurpose.js.map +1 -0
- package/dist/src/agent/workflow/builtins/decision-compare.d.ts +13 -0
- package/dist/src/agent/workflow/builtins/decision-compare.js +173 -0
- package/dist/src/agent/workflow/builtins/decision-compare.js.map +1 -0
- package/dist/src/agent/workflow/builtins/inbox-triage.d.ts +11 -0
- package/dist/src/agent/workflow/builtins/inbox-triage.js +148 -0
- package/dist/src/agent/workflow/builtins/inbox-triage.js.map +1 -0
- package/dist/src/agent/workflow/builtins/index.d.ts +10 -1
- package/dist/src/agent/workflow/builtins/index.js +46 -1
- package/dist/src/agent/workflow/builtins/index.js.map +1 -1
- package/dist/src/agent/workflow/builtins/meeting-prep.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/meeting-prep.js +144 -0
- package/dist/src/agent/workflow/builtins/meeting-prep.js.map +1 -0
- package/dist/src/agent/workflow/builtins/offer-design.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/offer-design.js +161 -0
- package/dist/src/agent/workflow/builtins/offer-design.js.map +1 -0
- package/dist/src/agent/workflow/builtins/weekly-review.d.ts +12 -0
- package/dist/src/agent/workflow/builtins/weekly-review.js +131 -0
- package/dist/src/agent/workflow/builtins/weekly-review.js.map +1 -0
- package/dist/src/agent/workflow/step-labels.js +2 -2
- package/dist/src/agent/workflow/step-labels.js.map +1 -1
- package/dist/src/agent/workflow/subagent-runner.js +3 -1
- package/dist/src/agent/workflow/subagent-runner.js.map +1 -1
- package/dist/src/agent/workflow/types.d.ts +4 -0
- package/dist/src/agent/workflow/workflow-child-tools.d.ts +4 -0
- package/dist/src/agent/workflow/workflow-child-tools.js +21 -0
- package/dist/src/agent/workflow/workflow-child-tools.js.map +1 -0
- package/dist/src/auth/credentials.d.ts +14 -2
- package/dist/src/auth/credentials.js +38 -13
- package/dist/src/auth/credentials.js.map +1 -1
- package/dist/src/auth/oauth/types.d.ts +16 -0
- package/dist/src/chat-commands/agent-edit.d.ts +4 -0
- package/dist/src/chat-commands/agent-edit.js +136 -0
- package/dist/src/chat-commands/agent-edit.js.map +1 -0
- package/dist/src/chat-commands/index.d.ts +1 -0
- package/dist/src/chat-commands/index.js +3 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/cli/bin.js +2 -0
- package/dist/src/cli/bin.js.map +1 -1
- package/dist/src/cli/commands/auth.js +6 -0
- package/dist/src/cli/commands/auth.js.map +1 -1
- package/dist/src/cli/commands/cron.js +42 -3
- package/dist/src/cli/commands/cron.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/session-integrity.js +79 -56
- package/dist/src/cli/commands/doctor/checks/session-integrity.js.map +1 -1
- package/dist/src/cli/commands/onboard/model.js +6 -0
- package/dist/src/cli/commands/onboard/model.js.map +1 -1
- package/dist/src/cli/commands/update.js +86 -79
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/commands/agents.config.d.ts +3 -2
- package/dist/src/commands/agents.config.js +5 -2
- package/dist/src/commands/agents.config.js.map +1 -1
- package/dist/src/config/agent-typed-models.d.ts +2 -7
- package/dist/src/config/agent-typed-models.js +3 -14
- package/dist/src/config/agent-typed-models.js.map +1 -1
- package/dist/src/config/localized-text.d.ts +6 -0
- package/dist/src/config/localized-text.js +42 -0
- package/dist/src/config/localized-text.js.map +1 -0
- package/dist/src/config/models-json.d.ts +6 -6
- package/dist/src/config/schema.d.ts +6 -21
- package/dist/src/config/schema.js +4 -4
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/cron/executor.d.ts +4 -0
- package/dist/src/cron/executor.js +169 -5
- package/dist/src/cron/executor.js.map +1 -1
- package/dist/src/cron/job-content.js +2 -1
- package/dist/src/cron/job-content.js.map +1 -1
- package/dist/src/cron/types.d.ts +28 -1
- package/dist/src/cron/validation.d.ts +80 -0
- package/dist/src/cron/validation.js +30 -4
- package/dist/src/cron/validation.js.map +1 -1
- package/dist/src/cron/workflow-run-completion.d.ts +23 -0
- package/dist/src/cron/workflow-run-completion.js +72 -0
- package/dist/src/cron/workflow-run-completion.js.map +1 -0
- package/dist/src/extensions/update.d.ts +51 -0
- package/dist/src/extensions/update.js +260 -0
- package/dist/src/extensions/update.js.map +1 -0
- package/dist/src/gateway/agents-admin.d.ts +15 -8
- package/dist/src/gateway/agents-admin.js +77 -28
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/gateway-workflow-host.types.d.ts +17 -0
- package/dist/src/gateway/gateway-workflow-host.types.js +1 -0
- package/dist/src/gateway/heartbeat/service.js +1 -1
- package/dist/src/gateway/hono/lib/config-payload.d.ts +5 -0
- package/dist/src/gateway/hono/lib/config-payload.js +2 -1
- package/dist/src/gateway/hono/lib/config-payload.js.map +1 -1
- package/dist/src/gateway/hono/middleware/auth.d.ts +2 -0
- package/dist/src/gateway/hono/middleware/auth.js +12 -7
- package/dist/src/gateway/hono/middleware/auth.js.map +1 -1
- package/dist/src/gateway/hono/oauth-async.js +40 -15
- package/dist/src/gateway/hono/oauth-async.js.map +1 -1
- package/dist/src/gateway/hono/oauth.js +31 -6
- package/dist/src/gateway/hono/oauth.js.map +1 -1
- package/dist/src/gateway/hono/routes/agents.js +55 -12
- package/dist/src/gateway/hono/routes/agents.js.map +1 -1
- package/dist/src/gateway/hono/routes/config-patch/agents.js +1 -1
- package/dist/src/gateway/hono/routes/models.js +11 -5
- package/dist/src/gateway/hono/routes/models.js.map +1 -1
- package/dist/src/gateway/hono/routes/update.js +55 -107
- package/dist/src/gateway/hono/routes/update.js.map +1 -1
- package/dist/src/gateway/hono/routes/workflows.js +72 -191
- package/dist/src/gateway/hono/routes/workflows.js.map +1 -1
- package/dist/src/gateway/server.js +2 -0
- package/dist/src/gateway/server.js.map +1 -1
- package/dist/src/gateway/service.d.ts +5 -0
- package/dist/src/gateway/service.js +24 -3
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/heartbeat/index.js +1 -1
- package/dist/src/infra/brew.d.ts +4 -0
- package/dist/src/infra/brew.js +20 -0
- package/dist/src/infra/brew.js.map +1 -0
- package/dist/src/infra/package-json.d.ts +2 -0
- package/dist/src/infra/package-json.js +23 -0
- package/dist/src/infra/package-json.js.map +1 -0
- package/dist/src/infra/package-update-steps.d.ts +35 -0
- package/dist/src/infra/package-update-steps.js +304 -0
- package/dist/src/infra/package-update-steps.js.map +1 -0
- package/dist/src/infra/path-env.d.ts +11 -0
- package/dist/src/infra/path-env.js +90 -0
- package/dist/src/infra/path-env.js.map +1 -0
- package/dist/src/infra/path-prepend.d.ts +7 -0
- package/dist/src/infra/path-prepend.js +44 -0
- package/dist/src/infra/path-prepend.js.map +1 -0
- package/dist/src/infra/stable-node-path.d.ts +2 -0
- package/dist/src/infra/stable-node-path.js +28 -0
- package/dist/src/infra/stable-node-path.js.map +1 -0
- package/dist/src/infra/update-global.d.ts +30 -23
- package/dist/src/infra/update-global.js +113 -64
- package/dist/src/infra/update-global.js.map +1 -1
- package/dist/src/infra/update-log.d.ts +1 -0
- package/dist/src/infra/update-log.js +12 -0
- package/dist/src/infra/update-log.js.map +1 -0
- package/dist/src/infra/update-restart.d.ts +20 -0
- package/dist/src/infra/update-restart.js +165 -0
- package/dist/src/infra/update-restart.js.map +1 -0
- package/dist/src/infra/update-runner.d.ts +89 -1
- package/dist/src/infra/update-runner.js +604 -173
- package/dist/src/infra/update-runner.js.map +1 -1
- package/dist/src/infra/update-startup.d.ts +3 -0
- package/dist/src/infra/update-startup.js +8 -4
- package/dist/src/infra/update-startup.js.map +1 -1
- package/dist/src/providers/index.d.ts +8 -0
- package/dist/src/providers/index.js +51 -12
- package/dist/src/providers/index.js.map +1 -1
- package/dist/src/routing/resolve-route.d.ts +3 -1
- package/dist/src/routing/resolve-route.js.map +1 -1
- package/dist/src/session/store.d.ts +5 -3
- package/dist/src/session/store.js +66 -20
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/share/site-share-config.d.ts +3 -2
- package/dist/src/share/site-share-config.js.map +1 -1
- package/dist/src/utils/logger/stats.d.ts +1 -1
- package/dist/src/workflows/domain/command.d.ts +2 -1
- package/dist/src/workflows/domain/definition-utils.d.ts +14 -0
- package/dist/src/workflows/domain/definition-utils.js +50 -0
- package/dist/src/workflows/domain/definition-utils.js.map +1 -0
- package/dist/src/workflows/domain/event.d.ts +3 -0
- package/dist/src/workflows/domain/index.d.ts +2 -0
- package/dist/src/workflows/domain/index.js +3 -1
- package/dist/src/workflows/domain/run.d.ts +60 -0
- package/dist/src/workflows/domain/run.js.map +1 -1
- package/dist/src/workflows/domain/validation.d.ts +19 -0
- package/dist/src/workflows/domain/validation.js +66 -0
- package/dist/src/workflows/domain/validation.js.map +1 -0
- package/dist/src/workflows/engine/projector.js +17 -0
- package/dist/src/workflows/engine/projector.js.map +1 -1
- package/dist/src/workflows/engine/workflow-engine.d.ts +2 -1
- package/dist/src/workflows/engine/workflow-engine.js +128 -0
- package/dist/src/workflows/engine/workflow-engine.js.map +1 -1
- package/dist/src/workflows/index.d.ts +4 -0
- package/dist/src/workflows/index.js +9 -2
- package/dist/src/workflows/service/run-view-to-snapshot.d.ts +4 -0
- package/dist/src/workflows/service/run-view-to-snapshot.js +63 -0
- package/dist/src/workflows/service/run-view-to-snapshot.js.map +1 -0
- package/dist/src/workflows/service/workflow-run-service.d.ts +37 -0
- package/dist/src/workflows/service/workflow-run-service.js +282 -0
- package/dist/src/workflows/service/workflow-run-service.js.map +1 -0
- package/dist/src/workflows/service/workflow-run-service.types.d.ts +47 -0
- package/dist/src/workflows/service/workflow-run-service.types.js +1 -0
- package/dist/src/workflows/service/workflow-session-bridge.d.ts +29 -0
- package/dist/src/workflows/service/workflow-session-bridge.js +177 -0
- package/dist/src/workflows/service/workflow-session-bridge.js.map +1 -0
- package/dist/src/workflows/service/workflow-session-key.d.ts +3 -0
- package/dist/src/workflows/service/workflow-session-key.js +21 -0
- package/dist/src/workflows/service/workflow-session-key.js.map +1 -0
- package/dist/src/workflows/store/run-store.js +1 -0
- package/dist/src/workflows/store/run-store.js.map +1 -1
- package/package.json +1 -1
- package/dist/gateway/static/root/assets/agents-CRxETUZx.js +0 -222
- package/dist/gateway/static/root/assets/apps-page-wKWf3l57.js +0 -1
- package/dist/gateway/static/root/assets/channels-settings-DDbqVNkx.js +0 -1
- package/dist/gateway/static/root/assets/copy-SxMW6Xpc.js +0 -1
- package/dist/gateway/static/root/assets/cron-api-N9hvuRrn.js +0 -1
- package/dist/gateway/static/root/assets/cron-dreaming-jobs-DueM3rBz.js +0 -2
- package/dist/gateway/static/root/assets/cron-page-tlNGNxhP.js +0 -1
- package/dist/gateway/static/root/assets/dist-CJwfHYvT.js +0 -1
- package/dist/gateway/static/root/assets/index-CqZzHNEg.css +0 -1
- package/dist/gateway/static/root/assets/sessions-page-DKt-Wmib.js +0 -1
- package/dist/gateway/static/root/assets/settings-page-DcJjvvw4.js +0 -3
- package/dist/gateway/static/root/assets/skills-page-DuJ4BTO3.js +0 -2
- package/dist/gateway/static/root/assets/url-D6jvVYIA.js +0 -7
- package/dist/gateway/static/root/assets/voice-api-key-field-CTyHz7L_.js +0 -1
- package/dist/gateway/static/root/assets/workflows-page-GacJ41Fv.js +0 -27
package/dist/src/cli/bin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bin.js","names":["pkg.version"],"sources":["../../../src/cli/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry: log-level preset must run before any module that initializes the logger.\n * (Bundlers may reorder imports in `index.ts`; this file stays dependency-minimal.)\n */\nimport './cli-log-level-preset.js';\n\nimport pkg from '../../package.json' with { type: 'json' };\nimport { formatRootHelp } from './command-manifest.js';\n\nfunction printRootHelp(): void {\n console.log(formatRootHelp());\n}\n\nconst rootArgs = process.argv.slice(2).filter((arg) => arg !== '--');\nif (rootArgs.length === 1 && (rootArgs[0] === '--version' || rootArgs[0] === '-V')) {\n console.log(pkg.version);\n process.exit(0);\n}\nif (rootArgs.length === 1 && (rootArgs[0] === '--help' || rootArgs[0] === '-h' || rootArgs[0] === 'help')) {\n printRootHelp();\n process.exit(0);\n}\n\nconst filteredArgv = process.argv.filter((arg, index) => {\n if (arg !== '--') return true;\n return index < 2;\n});\n\nconst { tryRunGatewayRunFastPath } = await import('./gateway-run-fast-path.js');\nif (await tryRunGatewayRunFastPath(filteredArgv)) {\n process.exit(typeof process.exitCode === 'number' ? process.exitCode : 0);\n}\n\nconst { runCli } = await import('./index.js');\nawait runCli(process.argv);\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"bin.js","names":["pkg.version"],"sources":["../../../src/cli/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * CLI entry: log-level preset must run before any module that initializes the logger.\n * (Bundlers may reorder imports in `index.ts`; this file stays dependency-minimal.)\n */\nimport './cli-log-level-preset.js';\n\nimport pkg from '../../package.json' with { type: 'json' };\nimport { ensureXopcCliOnPath } from '../infra/path-env.js';\nimport { formatRootHelp } from './command-manifest.js';\n\nensureXopcCliOnPath();\n\nfunction printRootHelp(): void {\n console.log(formatRootHelp());\n}\n\nconst rootArgs = process.argv.slice(2).filter((arg) => arg !== '--');\nif (rootArgs.length === 1 && (rootArgs[0] === '--version' || rootArgs[0] === '-V')) {\n console.log(pkg.version);\n process.exit(0);\n}\nif (rootArgs.length === 1 && (rootArgs[0] === '--help' || rootArgs[0] === '-h' || rootArgs[0] === 'help')) {\n printRootHelp();\n process.exit(0);\n}\n\nconst filteredArgv = process.argv.filter((arg, index) => {\n if (arg !== '--') return true;\n return index < 2;\n});\n\nconst { tryRunGatewayRunFastPath } = await import('./gateway-run-fast-path.js');\nif (await tryRunGatewayRunFastPath(filteredArgv)) {\n process.exit(typeof process.exitCode === 'number' ? process.exitCode : 0);\n}\n\nconst { runCli } = await import('./index.js');\nawait runCli(process.argv);\n"],"mappings":";;;;;;AAWA,qBAAqB;AAErB,SAAS,gBAAsB;AAC7B,SAAQ,IAAI,gBAAgB,CAAC;;AAG/B,MAAM,WAAW,QAAQ,KAAK,MAAM,EAAE,CAAC,QAAQ,QAAQ,QAAQ,KAAK;AACpE,IAAI,SAAS,WAAW,MAAM,SAAS,OAAO,eAAe,SAAS,OAAO,OAAO;AAClF,SAAQ,IAAIA,QAAY;AACxB,SAAQ,KAAK,EAAE;;AAEjB,IAAI,SAAS,WAAW,MAAM,SAAS,OAAO,YAAY,SAAS,OAAO,QAAQ,SAAS,OAAO,SAAS;AACzG,gBAAe;AACf,SAAQ,KAAK,EAAE;;AAGjB,MAAM,eAAe,QAAQ,KAAK,QAAQ,KAAK,UAAU;AACvD,KAAI,QAAQ,KAAM,QAAO;AACzB,QAAO,QAAQ;EACf;AAEF,MAAM,EAAE,6BAA6B,MAAM,OAAO;AAClD,IAAI,MAAM,yBAAyB,aAAa,CAC9C,SAAQ,KAAK,OAAO,QAAQ,aAAa,WAAW,QAAQ,WAAW,EAAE;AAG3E,MAAM,EAAE,WAAW,MAAM,OAAO;AAChC,MAAM,OAAO,QAAQ,KAAK"}
|
|
@@ -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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"}
|
|
@@ -6,6 +6,7 @@ function createCronCommand(_ctx) {
|
|
|
6
6
|
const cmd = new Command("cron").description("Manage scheduled tasks").addHelpText("after", formatExamples([
|
|
7
7
|
"xopc cron list # List all tasks",
|
|
8
8
|
"xopc cron add --schedule \"0 9 * * *\" --message \"Good morning\"",
|
|
9
|
+
"xopc cron add --schedule \"0 17 * * 5\" --workflow weekly_review --goal \"Weekly review\"",
|
|
9
10
|
"xopc cron enable <job-id> # Enable a task",
|
|
10
11
|
"xopc cron disable <job-id> # Disable a task",
|
|
11
12
|
"xopc cron run <job-id> # Run a task now",
|
|
@@ -29,12 +30,49 @@ function createCronCommand(_ctx) {
|
|
|
29
30
|
}
|
|
30
31
|
});
|
|
31
32
|
}));
|
|
32
|
-
cmd.addCommand(new Command("add").description("Add a scheduled task").option("--name <text>", "Task name").option("--schedule <cron>", "Cron expression (e.g., \"0 9 * * *\")").option("--message <text>", "Message to send").action(async (options) => {
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
cmd.addCommand(new Command("add").description("Add a scheduled task").option("--name <text>", "Task name").option("--schedule <cron>", "Cron expression (e.g., \"0 9 * * *\")").option("--message <text>", "Message to send (system event)").option("--workflow <id>", "Workflow definition id (direct workflow run)").option("--goal <text>", "Optional workflow goal").option("--input-json <json>", "Workflow input payload as JSON object").option("--agent-id <id>", "Agent profile for workflow or isolated jobs").option("--no-wait", "Start workflow and return without waiting for completion").option("--channel <name>", "Delivery channel (e.g. telegram)").option("--to <chatId>", "Delivery recipient chat id").action(async (options) => {
|
|
34
|
+
const hasWorkflow = Boolean(options.workflow?.trim());
|
|
35
|
+
const hasMessage = Boolean(options.message?.trim());
|
|
36
|
+
if (!options.schedule || !hasWorkflow && !hasMessage || hasWorkflow && hasMessage) {
|
|
37
|
+
console.error("Error: --schedule is required; provide exactly one of --message or --workflow");
|
|
35
38
|
process.exit(1);
|
|
36
39
|
}
|
|
37
40
|
await withCronService(async (cronService) => {
|
|
41
|
+
if (hasWorkflow) {
|
|
42
|
+
const { DEFAULT_WORKFLOW_CRON_WAIT_MS } = await import("../../cron/workflow-run-completion.js");
|
|
43
|
+
let inputEnvelope;
|
|
44
|
+
if (options.inputJson) try {
|
|
45
|
+
inputEnvelope = { payload: JSON.parse(options.inputJson) };
|
|
46
|
+
} catch {
|
|
47
|
+
console.error("Error: --input-json must be valid JSON");
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
const agentId = options.agentId?.trim() || void 0;
|
|
51
|
+
const delivery = options.channel?.trim() && options.to?.trim() ? {
|
|
52
|
+
mode: "direct",
|
|
53
|
+
channel: options.channel.trim(),
|
|
54
|
+
to: options.to.trim()
|
|
55
|
+
} : void 0;
|
|
56
|
+
const result = await cronService.addJob(options.schedule, {
|
|
57
|
+
name: options.name,
|
|
58
|
+
sessionTarget: "isolated",
|
|
59
|
+
timeout: DEFAULT_WORKFLOW_CRON_WAIT_MS,
|
|
60
|
+
...agentId ? { agentId } : {},
|
|
61
|
+
delivery,
|
|
62
|
+
payload: {
|
|
63
|
+
kind: "workflowRun",
|
|
64
|
+
definitionId: options.workflow.trim(),
|
|
65
|
+
...options.goal?.trim() ? { goal: options.goal.trim() } : {},
|
|
66
|
+
...inputEnvelope ? { inputEnvelope } : {},
|
|
67
|
+
...agentId ? { agentId } : {},
|
|
68
|
+
...options.noWait ? { waitForCompletion: false } : {}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
console.log(`✅ Added workflow job ${result.id}`);
|
|
72
|
+
console.log(` Schedule: ${result.schedule}`);
|
|
73
|
+
console.log(` Workflow: ${options.workflow.trim()}`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
38
76
|
const result = await cronService.addJob(options.schedule, {
|
|
39
77
|
name: options.name,
|
|
40
78
|
payload: {
|
|
@@ -99,6 +137,7 @@ register({
|
|
|
99
137
|
examples: [
|
|
100
138
|
"xopc cron list",
|
|
101
139
|
"xopc cron add --schedule \"0 9 * * *\" --message \"Hello\"",
|
|
140
|
+
"xopc cron add --schedule \"0 17 * * 5\" --workflow weekly_review",
|
|
102
141
|
"xopc cron enable abc12345",
|
|
103
142
|
"xopc cron run abc12345"
|
|
104
143
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cron.js","names":[],"sources":["../../../../src/cli/commands/cron.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport { withCronService } from './cron-cli.js';\n\nfunction createCronCommand(_ctx: CLIContext): Command {\n const cmd = new Command('cron')\n .description('Manage scheduled tasks')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc cron list # List all tasks',\n 'xopc cron add --schedule \"0 9 * * *\" --message \"Good morning\"',\n 'xopc cron enable <job-id> # Enable a task',\n 'xopc cron disable <job-id> # Disable a task',\n 'xopc cron run <job-id> # Run a task now',\n 'xopc cron remove <job-id> # Remove a task',\n ]),\n );\n\n cmd.addCommand(\n new Command('list')\n .description('List all scheduled tasks')\n .action(async () => {\n await withCronService(async (cronService) => {\n const jobs = await cronService.listJobs();\n\n if (jobs.length === 0) {\n console.log('No scheduled tasks.');\n return;\n }\n\n console.log('Scheduled Tasks:\\n');\n const { getCronPayloadText } = await import('../../cron/job-content.js');\n for (const job of jobs) {\n const state = job.enabled ? 'enabled ' : 'disabled';\n console.log(` ${job.id} [${state}] - ${job.schedule}`);\n console.log(` ${getCronPayloadText({ payload: job.payload })}`);\n console.log(` Next: ${job.next_run || 'N/A'}`);\n console.log();\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('add')\n .description('Add a scheduled task')\n .option('--name <text>', 'Task name')\n .option('--schedule <cron>', 'Cron expression (e.g., \"0 9 * * *\")')\n .option('--message <text>', 'Message to send')\n .action(async (options) => {\n if (!options.schedule || !options.message) {\n console.error('Error: --schedule and --message are required');\n process.exit(1);\n }\n\n await withCronService(async (cronService) => {\n const result = await cronService.addJob(options.schedule, {\n name: options.name,\n payload: { kind: 'systemEvent', text: options.message },\n });\n\n console.log(`✅ Added job ${result.id}`);\n console.log(` Schedule: ${result.schedule}`);\n });\n }),\n );\n\n cmd.addCommand(\n new Command('remove')\n .description('Remove a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.removeJob(id);\n if (success) {\n console.log(`✅ Removed job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('enable')\n .description('Enable a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.toggleJob(id, true);\n if (success) {\n console.log(`✅ Enabled job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('disable')\n .description('Disable a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.toggleJob(id, false);\n if (success) {\n console.log(`✅ Disabled job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n const runNowAction = async (id: string) => {\n await withCronService(async (cronService) => {\n try {\n await cronService.runJobNow(id);\n console.log(`✅ Triggered job ${id}`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(message);\n process.exit(1);\n }\n });\n };\n\n cmd.addCommand(\n new Command('run')\n .description('Run a scheduled task immediately')\n .argument('<id>', 'Job ID')\n .action(runNowAction),\n );\n\n cmd.addCommand(\n new Command('trigger')\n .description('Alias for `cron run`')\n .argument('<id>', 'Job ID')\n .action(runNowAction),\n );\n\n return cmd;\n}\n\nregister({\n id: 'cron',\n name: 'cron',\n description: 'Manage scheduled tasks',\n factory: createCronCommand,\n metadata: {\n category: 'utility',\n examples: [\n 'xopc cron list',\n 'xopc cron add --schedule \"0 9 * * *\" --message \"Hello\"',\n 'xopc cron enable abc12345',\n 'xopc cron run abc12345',\n ],\n },\n});\n\nexport { createCronCommand };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cron.js","names":[],"sources":["../../../../src/cli/commands/cron.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { register, formatExamples } from '../registry.js';\nimport type { CLIContext } from '../registry.js';\nimport { withCronService } from './cron-cli.js';\n\nfunction createCronCommand(_ctx: CLIContext): Command {\n const cmd = new Command('cron')\n .description('Manage scheduled tasks')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc cron list # List all tasks',\n 'xopc cron add --schedule \"0 9 * * *\" --message \"Good morning\"',\n 'xopc cron add --schedule \"0 17 * * 5\" --workflow weekly_review --goal \"Weekly review\"',\n 'xopc cron enable <job-id> # Enable a task',\n 'xopc cron disable <job-id> # Disable a task',\n 'xopc cron run <job-id> # Run a task now',\n 'xopc cron remove <job-id> # Remove a task',\n ]),\n );\n\n cmd.addCommand(\n new Command('list')\n .description('List all scheduled tasks')\n .action(async () => {\n await withCronService(async (cronService) => {\n const jobs = await cronService.listJobs();\n\n if (jobs.length === 0) {\n console.log('No scheduled tasks.');\n return;\n }\n\n console.log('Scheduled Tasks:\\n');\n const { getCronPayloadText } = await import('../../cron/job-content.js');\n for (const job of jobs) {\n const state = job.enabled ? 'enabled ' : 'disabled';\n console.log(` ${job.id} [${state}] - ${job.schedule}`);\n console.log(` ${getCronPayloadText({ payload: job.payload })}`);\n console.log(` Next: ${job.next_run || 'N/A'}`);\n console.log();\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('add')\n .description('Add a scheduled task')\n .option('--name <text>', 'Task name')\n .option('--schedule <cron>', 'Cron expression (e.g., \"0 9 * * *\")')\n .option('--message <text>', 'Message to send (system event)')\n .option('--workflow <id>', 'Workflow definition id (direct workflow run)')\n .option('--goal <text>', 'Optional workflow goal')\n .option('--input-json <json>', 'Workflow input payload as JSON object')\n .option('--agent-id <id>', 'Agent profile for workflow or isolated jobs')\n .option('--no-wait', 'Start workflow and return without waiting for completion')\n .option('--channel <name>', 'Delivery channel (e.g. telegram)')\n .option('--to <chatId>', 'Delivery recipient chat id')\n .action(async (options) => {\n const hasWorkflow = Boolean(options.workflow?.trim());\n const hasMessage = Boolean(options.message?.trim());\n if (!options.schedule || (!hasWorkflow && !hasMessage) || (hasWorkflow && hasMessage)) {\n console.error(\n 'Error: --schedule is required; provide exactly one of --message or --workflow',\n );\n process.exit(1);\n }\n\n await withCronService(async (cronService) => {\n if (hasWorkflow) {\n const { DEFAULT_WORKFLOW_CRON_WAIT_MS } = await import(\n '../../cron/workflow-run-completion.js'\n );\n let inputEnvelope: { payload: unknown } | undefined;\n if (options.inputJson) {\n try {\n inputEnvelope = { payload: JSON.parse(options.inputJson) as unknown };\n } catch {\n console.error('Error: --input-json must be valid JSON');\n process.exit(1);\n }\n }\n const agentId = options.agentId?.trim() || undefined;\n const delivery =\n options.channel?.trim() && options.to?.trim()\n ? {\n mode: 'direct' as const,\n channel: options.channel.trim(),\n to: options.to.trim(),\n }\n : undefined;\n const result = await cronService.addJob(options.schedule, {\n name: options.name,\n sessionTarget: 'isolated',\n timeout: DEFAULT_WORKFLOW_CRON_WAIT_MS,\n ...(agentId ? { agentId } : {}),\n delivery,\n payload: {\n kind: 'workflowRun',\n definitionId: options.workflow.trim(),\n ...(options.goal?.trim() ? { goal: options.goal.trim() } : {}),\n ...(inputEnvelope ? { inputEnvelope } : {}),\n ...(agentId ? { agentId } : {}),\n ...(options.noWait ? { waitForCompletion: false } : {}),\n },\n });\n console.log(`✅ Added workflow job ${result.id}`);\n console.log(` Schedule: ${result.schedule}`);\n console.log(` Workflow: ${options.workflow.trim()}`);\n return;\n }\n\n const result = await cronService.addJob(options.schedule, {\n name: options.name,\n payload: { kind: 'systemEvent', text: options.message },\n });\n\n console.log(`✅ Added job ${result.id}`);\n console.log(` Schedule: ${result.schedule}`);\n });\n }),\n );\n\n cmd.addCommand(\n new Command('remove')\n .description('Remove a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.removeJob(id);\n if (success) {\n console.log(`✅ Removed job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('enable')\n .description('Enable a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.toggleJob(id, true);\n if (success) {\n console.log(`✅ Enabled job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n cmd.addCommand(\n new Command('disable')\n .description('Disable a scheduled task')\n .argument('<id>', 'Job ID')\n .action(async (id) => {\n await withCronService(async (cronService) => {\n const success = await cronService.toggleJob(id, false);\n if (success) {\n console.log(`✅ Disabled job ${id}`);\n } else {\n console.error(`Job ${id} not found`);\n process.exit(1);\n }\n });\n }),\n );\n\n const runNowAction = async (id: string) => {\n await withCronService(async (cronService) => {\n try {\n await cronService.runJobNow(id);\n console.log(`✅ Triggered job ${id}`);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n console.error(message);\n process.exit(1);\n }\n });\n };\n\n cmd.addCommand(\n new Command('run')\n .description('Run a scheduled task immediately')\n .argument('<id>', 'Job ID')\n .action(runNowAction),\n );\n\n cmd.addCommand(\n new Command('trigger')\n .description('Alias for `cron run`')\n .argument('<id>', 'Job ID')\n .action(runNowAction),\n );\n\n return cmd;\n}\n\nregister({\n id: 'cron',\n name: 'cron',\n description: 'Manage scheduled tasks',\n factory: createCronCommand,\n metadata: {\n category: 'utility',\n examples: [\n 'xopc cron list',\n 'xopc cron add --schedule \"0 9 * * *\" --message \"Hello\"',\n 'xopc cron add --schedule \"0 17 * * 5\" --workflow weekly_review',\n 'xopc cron enable abc12345',\n 'xopc cron run abc12345',\n ],\n },\n});\n\nexport { createCronCommand };\n"],"mappings":"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"}
|
|
@@ -1,14 +1,42 @@
|
|
|
1
|
-
import { init_agent_scope, resolveDefaultAgentId } from "../../../../agent/agent-scope.js";
|
|
1
|
+
import { init_agent_scope, listAgentEntries, resolveDefaultAgentId } from "../../../../agent/agent-scope.js";
|
|
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 {
|
|
6
|
-
import {
|
|
5
|
+
import { init_session_key, parseSessionKey } from "../../../../routing/session-key.js";
|
|
6
|
+
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
7
|
+
import { basename, join } from "node:path";
|
|
7
8
|
//#region src/cli/commands/doctor/checks/session-integrity.ts
|
|
8
9
|
init_agent_scope();
|
|
9
10
|
init_loader();
|
|
10
11
|
init_paths();
|
|
12
|
+
init_session_key();
|
|
11
13
|
init_transcript_paths();
|
|
14
|
+
function discoverSessionMapLocations(config, stateDir) {
|
|
15
|
+
const agentIds = new Set([resolveDefaultAgentId(config), ...listAgentEntries(config).map((agent) => agent.id)]);
|
|
16
|
+
const agentsRoot = join(stateDir, "agents");
|
|
17
|
+
if (existsSync(agentsRoot)) {
|
|
18
|
+
for (const entry of readdirSync(agentsRoot, { withFileTypes: true })) if (entry.isDirectory()) agentIds.add(entry.name);
|
|
19
|
+
}
|
|
20
|
+
const seenMapPaths = /* @__PURE__ */ new Set();
|
|
21
|
+
const locations = [];
|
|
22
|
+
for (const agentId of agentIds) {
|
|
23
|
+
const sessionsDir = resolveSessionsDir(config, agentId);
|
|
24
|
+
const mapPath = join(sessionsDir, FILENAMES.SESSIONS_MAP);
|
|
25
|
+
if (seenMapPaths.has(mapPath)) continue;
|
|
26
|
+
seenMapPaths.add(mapPath);
|
|
27
|
+
locations.push({
|
|
28
|
+
agentId,
|
|
29
|
+
sessionsDir,
|
|
30
|
+
mapPath
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
return locations;
|
|
34
|
+
}
|
|
35
|
+
function readSessionMap(mapPath) {
|
|
36
|
+
const parsed = JSON.parse(readFileSync(mapPath, "utf-8"));
|
|
37
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("invalid sessions map");
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
12
40
|
async function checkSessionIntegrity(ctx) {
|
|
13
41
|
if (!ctx.options.deep) return {
|
|
14
42
|
id: "session-integrity",
|
|
@@ -36,73 +64,68 @@ async function checkSessionIntegrity(ctx) {
|
|
|
36
64
|
hints: []
|
|
37
65
|
};
|
|
38
66
|
}
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
id: "session-integrity",
|
|
51
|
-
label: "Sessions",
|
|
52
|
-
status: "warn",
|
|
53
|
-
message: "`sessions.json` is missing.",
|
|
54
|
-
hints: [mapPath]
|
|
55
|
-
};
|
|
56
|
-
let map;
|
|
57
|
-
try {
|
|
58
|
-
const parsed = JSON.parse(readFileSync(mapPath, "utf-8"));
|
|
59
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("invalid");
|
|
60
|
-
map = parsed;
|
|
61
|
-
} catch {
|
|
62
|
-
return {
|
|
63
|
-
id: "session-integrity",
|
|
64
|
-
label: "Sessions",
|
|
65
|
-
status: "warn",
|
|
66
|
-
message: "`sessions.json` is not valid JSON.",
|
|
67
|
-
hints: [mapPath]
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
const sample = [...Object.keys(map)].sort((a, b) => {
|
|
71
|
-
const ta = map[a]?.updatedAt ?? 0;
|
|
72
|
-
return (map[b]?.updatedAt ?? 0) - ta;
|
|
73
|
-
}).slice(0, 20);
|
|
74
|
-
if (sample.length === 0) return {
|
|
75
|
-
id: "session-integrity",
|
|
76
|
-
label: "Sessions",
|
|
77
|
-
status: "pass",
|
|
78
|
-
message: "`sessions.json` is valid; no sessions to sample.",
|
|
79
|
-
hints: []
|
|
80
|
-
};
|
|
81
|
-
const missing = [];
|
|
82
|
-
for (const sessionKey of sample) {
|
|
83
|
-
const entry = map[sessionKey];
|
|
84
|
-
if (!entry?.sessionId) {
|
|
85
|
-
missing.push(sessionKey);
|
|
67
|
+
const locations = discoverSessionMapLocations(config, ctx.stateDir);
|
|
68
|
+
const missingMaps = [];
|
|
69
|
+
const invalidMaps = [];
|
|
70
|
+
const missingTranscripts = [];
|
|
71
|
+
const agentMismatches = [];
|
|
72
|
+
const orphanTranscripts = [];
|
|
73
|
+
let sessionCount = 0;
|
|
74
|
+
for (const location of locations) {
|
|
75
|
+
if (!existsSync(location.sessionsDir)) continue;
|
|
76
|
+
if (!existsSync(location.mapPath)) {
|
|
77
|
+
missingMaps.push(location.mapPath);
|
|
86
78
|
continue;
|
|
87
79
|
}
|
|
80
|
+
let map;
|
|
88
81
|
try {
|
|
89
|
-
|
|
82
|
+
map = readSessionMap(location.mapPath);
|
|
90
83
|
} catch {
|
|
91
|
-
|
|
84
|
+
invalidMaps.push(location.mapPath);
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const referencedTranscriptFiles = /* @__PURE__ */ new Set();
|
|
88
|
+
for (const [sessionKey, entry] of Object.entries(map)) {
|
|
89
|
+
sessionCount++;
|
|
90
|
+
const parsed = parseSessionKey(sessionKey);
|
|
91
|
+
if (parsed && parsed.agentId !== location.agentId) agentMismatches.push(`${sessionKey} in agent ${location.agentId}`);
|
|
92
|
+
if (!entry?.sessionId) {
|
|
93
|
+
missingTranscripts.push(sessionKey);
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const transcriptPath = resolveSessionFilePath(entry.sessionId, entry, { sessionsDir: location.sessionsDir });
|
|
98
|
+
referencedTranscriptFiles.add(basename(transcriptPath));
|
|
99
|
+
if (!existsSync(transcriptPath)) missingTranscripts.push(sessionKey);
|
|
100
|
+
} catch {
|
|
101
|
+
missingTranscripts.push(sessionKey);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
for (const file of readdirSync(location.sessionsDir, { withFileTypes: true })) {
|
|
105
|
+
if (!file.isFile() || !file.name.endsWith(".jsonl") || file.name.includes(".checkpoint.")) continue;
|
|
106
|
+
if (!referencedTranscriptFiles.has(file.name)) orphanTranscripts.push(join(location.sessionsDir, file.name));
|
|
92
107
|
}
|
|
93
108
|
}
|
|
94
|
-
|
|
109
|
+
const hints = [
|
|
110
|
+
...missingMaps.slice(0, 3).map((path) => `Missing sessions.json: ${path}`),
|
|
111
|
+
...invalidMaps.slice(0, 3).map((path) => `Invalid sessions.json: ${path}`),
|
|
112
|
+
...agentMismatches.slice(0, 3).map((item) => `Session key agent mismatch: ${item}`),
|
|
113
|
+
...missingTranscripts.slice(0, 3).map((key) => `Missing transcript for: ${key}`),
|
|
114
|
+
...orphanTranscripts.slice(0, 3).map((path) => `Orphan transcript: ${path}`)
|
|
115
|
+
];
|
|
116
|
+
const warningCount = missingMaps.length + invalidMaps.length + missingTranscripts.length + agentMismatches.length + orphanTranscripts.length;
|
|
117
|
+
if (warningCount > 0) return {
|
|
95
118
|
id: "session-integrity",
|
|
96
119
|
label: "Sessions",
|
|
97
120
|
status: "warn",
|
|
98
|
-
message:
|
|
99
|
-
hints
|
|
121
|
+
message: `Scanned ${locations.length} agent session dir(s), ${sessionCount} session(s); found ${warningCount} issue(s).`,
|
|
122
|
+
hints
|
|
100
123
|
};
|
|
101
124
|
return {
|
|
102
125
|
id: "session-integrity",
|
|
103
126
|
label: "Sessions",
|
|
104
127
|
status: "pass",
|
|
105
|
-
message: `
|
|
128
|
+
message: `Scanned ${locations.length} agent session dir(s), ${sessionCount} session(s); session maps and JSONL transcripts are consistent.`,
|
|
106
129
|
hints: []
|
|
107
130
|
};
|
|
108
131
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-integrity.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/session-integrity.ts"],"sourcesContent":["import { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\n\nimport { resolveDefaultAgentId } from '../../../../agent/agent-scope.js';\nimport { loadConfig } from '../../../../config/loader.js';\nimport { FILENAMES, resolveSessionsDir } from '../../../../config/paths.js';\nimport { resolveSessionFilePath } from '../../../../session/parity/transcript-paths.js';\nimport type { XopcSessionDiskEntry } from '../../../../session/parity/xopc-session-disk-entry.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\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
|
|
1
|
+
{"version":3,"file":"session-integrity.js","names":[],"sources":["../../../../../../src/cli/commands/doctor/checks/session-integrity.ts"],"sourcesContent":["import { existsSync, readdirSync, readFileSync } from 'node:fs';\nimport { basename, join } from 'node:path';\n\nimport { listAgentEntries, resolveDefaultAgentId } from '../../../../agent/agent-scope.js';\nimport { loadConfig } from '../../../../config/loader.js';\nimport type { Config } from '../../../../config/schema.js';\nimport { FILENAMES, resolveSessionsDir } from '../../../../config/paths.js';\nimport { parseSessionKey } from '../../../../routing/session-key.js';\nimport { resolveSessionFilePath } from '../../../../session/parity/transcript-paths.js';\nimport type { XopcSessionDiskEntry } from '../../../../session/parity/xopc-session-disk-entry.js';\nimport type { CheckResult, DoctorContext } from '../types.js';\n\ninterface SessionMapLocation {\n agentId: string;\n sessionsDir: string;\n mapPath: string;\n}\n\nfunction discoverSessionMapLocations(config: Config, stateDir: string): SessionMapLocation[] {\n const agentIds = new Set<string>([\n resolveDefaultAgentId(config),\n ...listAgentEntries(config).map((agent) => agent.id),\n ]);\n\n const agentsRoot = join(stateDir, 'agents');\n if (existsSync(agentsRoot)) {\n for (const entry of readdirSync(agentsRoot, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n agentIds.add(entry.name);\n }\n }\n }\n\n const seenMapPaths = new Set<string>();\n const locations: SessionMapLocation[] = [];\n for (const agentId of agentIds) {\n const sessionsDir = resolveSessionsDir(config, agentId);\n const mapPath = join(sessionsDir, FILENAMES.SESSIONS_MAP);\n if (seenMapPaths.has(mapPath)) {\n continue;\n }\n seenMapPaths.add(mapPath);\n locations.push({ agentId, sessionsDir, mapPath });\n }\n return locations;\n}\n\nfunction readSessionMap(mapPath: string): Record<string, XopcSessionDiskEntry> {\n const parsed = JSON.parse(readFileSync(mapPath, 'utf-8')) as unknown;\n if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {\n throw new Error('invalid sessions map');\n }\n return parsed as Record<string, XopcSessionDiskEntry>;\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: 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 locations = discoverSessionMapLocations(config, ctx.stateDir);\n const missingMaps: string[] = [];\n const invalidMaps: string[] = [];\n const missingTranscripts: string[] = [];\n const agentMismatches: string[] = [];\n const orphanTranscripts: string[] = [];\n let sessionCount = 0;\n\n for (const location of locations) {\n if (!existsSync(location.sessionsDir)) {\n continue;\n }\n if (!existsSync(location.mapPath)) {\n missingMaps.push(location.mapPath);\n continue;\n }\n\n let map: Record<string, XopcSessionDiskEntry>;\n try {\n map = readSessionMap(location.mapPath);\n } catch {\n invalidMaps.push(location.mapPath);\n continue;\n }\n\n const referencedTranscriptFiles = new Set<string>();\n for (const [sessionKey, entry] of Object.entries(map)) {\n sessionCount++;\n const parsed = parseSessionKey(sessionKey);\n if (parsed && parsed.agentId !== location.agentId) {\n agentMismatches.push(`${sessionKey} in agent ${location.agentId}`);\n }\n if (!entry?.sessionId) {\n missingTranscripts.push(sessionKey);\n continue;\n }\n try {\n const transcriptPath = resolveSessionFilePath(entry.sessionId, entry, { sessionsDir: location.sessionsDir });\n referencedTranscriptFiles.add(basename(transcriptPath));\n if (!existsSync(transcriptPath)) {\n missingTranscripts.push(sessionKey);\n }\n } catch {\n missingTranscripts.push(sessionKey);\n }\n }\n\n for (const file of readdirSync(location.sessionsDir, { withFileTypes: true })) {\n if (!file.isFile() || !file.name.endsWith('.jsonl') || file.name.includes('.checkpoint.')) {\n continue;\n }\n if (!referencedTranscriptFiles.has(file.name)) {\n orphanTranscripts.push(join(location.sessionsDir, file.name));\n }\n }\n }\n\n const hints = [\n ...missingMaps.slice(0, 3).map((path) => `Missing sessions.json: ${path}`),\n ...invalidMaps.slice(0, 3).map((path) => `Invalid sessions.json: ${path}`),\n ...agentMismatches.slice(0, 3).map((item) => `Session key agent mismatch: ${item}`),\n ...missingTranscripts.slice(0, 3).map((key) => `Missing transcript for: ${key}`),\n ...orphanTranscripts.slice(0, 3).map((path) => `Orphan transcript: ${path}`),\n ];\n\n const warningCount =\n missingMaps.length + invalidMaps.length + missingTranscripts.length + agentMismatches.length + orphanTranscripts.length;\n\n if (warningCount > 0) {\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'warn',\n message: `Scanned ${locations.length} agent session dir(s), ${sessionCount} session(s); found ${warningCount} issue(s).`,\n hints,\n };\n }\n\n return {\n id: 'session-integrity',\n label: 'Sessions',\n status: 'pass',\n message: `Scanned ${locations.length} agent session dir(s), ${sessionCount} session(s); session maps and JSONL transcripts are consistent.`,\n hints: [],\n };\n}\n"],"mappings":"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"}
|
|
@@ -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 {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model.js","names":[],"sources":["../../../../../src/cli/commands/onboard/model.ts"],"sourcesContent":["/**\n * Model Configuration for Onboarding\n */\n\nimport { input, select, confirm } from '@inquirer/prompts';\nimport type { Config } from '../../../config/schema.js';\nimport type { CLIContext } from '../../registry.js';\nimport { colors } from '../../utils/colors.js';\nimport {\n getModelsByProvider,\n getSortedProviders,\n getProviderDisplayName,\n providerSupportsOAuth,\n providerSupportsApiKey,\n} from '../../../providers/index.js';\nimport { listProfilesForProvider } from '../../../auth/profiles/index.js';\nimport { upsertAuthProfile } from '../../../auth/profiles/index.js';\nimport { getOAuthProvider } from '../../utils/oauth-providers.js';\nimport type { OAuthLoginCallbacks } from '../../../auth/index.js';\nimport { CredentialResolver } from '../../../auth/credentials.js';\nimport { getApiKeyFromEnv } from '../../../providers/env-keys.js';\n\n/**\n * Get available models for a provider\n */\nasync function getModelsForProvider(provider: string): Promise<{ value: string; name: string }[]> {\n const models = getModelsByProvider(provider);\n return models.map((m) => ({\n value: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n }));\n}\n\n/**\n * Perform OAuth login for a provider\n */\nasync function doOAuthLogin(provider: string): Promise<boolean> {\n const config = getOAuthProvider(provider);\n if (!config) {\n console.error(`OAuth not supported for provider: ${provider}`);\n return false;\n }\n\n console.log(`\\n🔐 Starting ${config.displayName} OAuth login...`);\n\n const callbacks: OAuthLoginCallbacks = {\n onAuth: (info) => {\n console.log(`\\n${config.urlPrompt}`);\n console.log(info.url);\n if (info.instructions) {\n console.log('\\n' + info.instructions);\n }\n console.log('\\n');\n },\n onPrompt: async (prompt) => {\n return input({ message: prompt.message });\n },\n onProgress: (message) => {\n console.log(' →', message);\n },\n };\n\n try {\n const creds = await config.provider.login(callbacks);\n upsertAuthProfile({\n profileId: config.profileId,\n credential: {\n type: 'oauth',\n provider,\n ...creds,\n },\n });\n return true;\n } catch (error) {\n console.error('❌ OAuth login failed:', error);\n return false;\n }\n}\n\n/**\n * Configure AI model provider and model\n */\nexport async function setupModel(\n existingConfig: Config | null,\n ctx: CLIContext\n): Promise<Config> {\n console.log('\\n🤖 Step: AI Model\\n');\n\n const config = existingConfig || ({} as Config);\n const currentModelConfig = config?.agents?.defaults?.model;\n const currentModel =\n typeof currentModelConfig === 'string' ? currentModelConfig : currentModelConfig?.primary;\n\n if (currentModel) {\n console.log('Current model:', currentModel);\n const keepCurrent = await confirm({\n message: 'Keep using this model?',\n default: true,\n });\n if (keepCurrent) {\n console.log('✅ Keeping:', currentModel);\n return config;\n }\n }\n\n // Get sorted providers with metadata\n const sortedProviders = getSortedProviders();\n\n const choices = sortedProviders.map((p) => ({\n value: p,\n name: getProviderDisplayName(p),\n }));\n\n const provider = await select({\n message: 'Select provider:',\n choices,\n });\n\n const providerName = getProviderDisplayName(provider);\n\n // Check if provider has existing profiles\n const existingProfiles = listProfilesForProvider(provider);\n if (existingProfiles.length > 0) {\n console.log(`\\n${colors.green('✓')} Found existing credentials for ${providerName}`);\n const useExisting = await confirm({\n message: 'Use existing credentials?',\n default: true,\n });\n\n if (useExisting) {\n // Get available models\n const modelChoices = await getModelsForProvider(provider);\n if (modelChoices.length === 0) {\n console.log(`\\n⚠️ No models found for ${providerName}. Please check your credentials.`);\n } else {\n const model = await select({\n message: 'Select model:',\n choices: modelChoices,\n });\n\n config.agents = config.agents || {};\n config.agents.defaults = config.agents.defaults || {\n workspace: ctx.workspacePath,\n model: { primary: model, fallbacks: [] },\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n };\n config.agents.defaults.model = { primary: model, fallbacks: [] };\n config.agents.defaults.workspace = ctx.workspacePath;\n\n console.log('\\n✅ Model configured:', model);\n return config;\n }\n }\n }\n\n let apiKey: string | undefined;\n let useOAuth = false;\n\n apiKey = getApiKeyFromEnv(provider);\n if (apiKey) {\n console.log(`\\n${colors.green('✓')} Found API key for ${providerName} in environment`);\n }\n\n if (!apiKey) {\n // Check auth support from metadata\n const supportsOAuth = providerSupportsOAuth(provider);\n const supportsApiKey = providerSupportsApiKey(provider);\n const isOAuthOnly = supportsOAuth && !supportsApiKey;\n\n if (isOAuthOnly) {\n // OAuth only - no choice\n const success = await doOAuthLogin(provider);\n if (success) {\n useOAuth = true;\n console.log('\\n✅ OAuth login successful!');\n } else {\n console.error('\\n❌ OAuth login failed. This provider requires OAuth.');\n return config;\n }\n } else if (supportsOAuth && supportsApiKey) {\n // Dual auth - let user choose\n const authMethod = await select({\n message: `How would you like to authenticate with ${providerName}?`,\n choices: [\n { value: 'api_key', name: 'API Key (enter manually)' },\n { value: 'oauth', name: 'OAuth Login (browser-based)' },\n ],\n });\n\n if (authMethod === 'oauth') {\n const success = await doOAuthLogin(provider);\n if (success) {\n useOAuth = true;\n console.log('\\n✅ OAuth login successful!');\n } else {\n console.log('\\n⚠️ OAuth login failed. Please enter API key manually.');\n apiKey = await input({\n message: `API Key for ${providerName}:`,\n validate: (v: string) => v.length > 0 || 'Required',\n });\n useOAuth = false;\n }\n } else {\n apiKey = await input({\n message: `API Key for ${providerName}:`,\n validate: (v: string) => v.length > 0 || 'Required',\n });\n }\n } else {\n // API key only\n apiKey = await input({\n message: `API Key for ${providerName}:`,\n validate: (v: string) => v.length > 0 || 'Required',\n });\n }\n }\n\n // Get available models\n const modelChoices = await getModelsForProvider(provider);\n if (modelChoices.length === 0) {\n console.log(`\\n⚠️ No built-in models found for ${providerName}.`);\n console.log(' You can still use custom model names.');\n const model = await input({\n message: 'Model name:',\n validate: (v: string) => v.length > 0 || 'Required',\n });\n\n // Store API key in new credential system\n if (apiKey) {\n const resolver = new CredentialResolver();\n await resolver.saveApiKey(provider, apiKey, { profileName: 'default' });\n }\n\n config.agents = config.agents || {};\n config.agents.defaults = config.agents.defaults || {\n workspace: ctx.workspacePath,\n model: { primary: `${provider}/${model}`, fallbacks: [] },\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n };\n config.agents.defaults.model = { primary: `${provider}/${model}`, fallbacks: [] };\n config.agents.defaults.workspace = ctx.workspacePath;\n\n console.log('\\n✅ Model configured:', `${provider}/${model}`);\n return config;\n }\n\n console.log(`\\n📋 Available models for ${providerName}:`);\n const model = await select({\n message: 'Select model:',\n choices: modelChoices,\n });\n\n // Store in new credential system\n if (!useOAuth && apiKey) {\n const resolver = new CredentialResolver();\n await resolver.saveApiKey(provider, apiKey, { profileName: 'default' });\n }\n\n config.agents = config.agents || {};\n config.agents.defaults = config.agents.defaults || {\n workspace: ctx.workspacePath,\n model: { primary: model, fallbacks: [] },\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n };\n config.agents.defaults.model = { primary: model, fallbacks: [] };\n config.agents.defaults.workspace = ctx.workspacePath;\n\n console.log('\\n✅ Model configured:', model);\n return config;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"model.js","names":[],"sources":["../../../../../src/cli/commands/onboard/model.ts"],"sourcesContent":["/**\n * Model Configuration for Onboarding\n */\n\nimport { input, select, confirm } from '@inquirer/prompts';\nimport type { Config } from '../../../config/schema.js';\nimport type { CLIContext } from '../../registry.js';\nimport { colors } from '../../utils/colors.js';\nimport {\n getModelsByProvider,\n getSortedProviders,\n getProviderDisplayName,\n providerSupportsOAuth,\n providerSupportsApiKey,\n} from '../../../providers/index.js';\nimport { listProfilesForProvider } from '../../../auth/profiles/index.js';\nimport { upsertAuthProfile } from '../../../auth/profiles/index.js';\nimport { getOAuthProvider } from '../../utils/oauth-providers.js';\nimport type { OAuthLoginCallbacks } from '../../../auth/index.js';\nimport { CredentialResolver } from '../../../auth/credentials.js';\nimport { getApiKeyFromEnv } from '../../../providers/env-keys.js';\n\n/**\n * Get available models for a provider\n */\nasync function getModelsForProvider(provider: string): Promise<{ value: string; name: string }[]> {\n const models = getModelsByProvider(provider);\n return models.map((m) => ({\n value: `${m.provider}/${m.id}`,\n name: m.name || m.id,\n }));\n}\n\n/**\n * Perform OAuth login for a provider\n */\nasync function doOAuthLogin(provider: string): Promise<boolean> {\n const config = getOAuthProvider(provider);\n if (!config) {\n console.error(`OAuth not supported for provider: ${provider}`);\n return false;\n }\n\n console.log(`\\n🔐 Starting ${config.displayName} OAuth login...`);\n\n const callbacks: OAuthLoginCallbacks = {\n onAuth: (info) => {\n console.log(`\\n${config.urlPrompt}`);\n console.log(info.url);\n if (info.instructions) {\n console.log('\\n' + info.instructions);\n }\n console.log('\\n');\n },\n onDeviceCode: (info) => {\n console.log(`\\nOpen ${info.verificationUri} and enter code ${info.userCode}\\n`);\n },\n onPrompt: async (prompt) => {\n return input({ message: prompt.message });\n },\n onProgress: (message) => {\n console.log(' →', message);\n },\n onSelect: async (prompt) => {\n const browserOption = prompt.options.find((option) => option.id === 'browser');\n return browserOption?.id ?? prompt.options[0]?.id;\n },\n };\n\n try {\n const creds = await config.provider.login(callbacks);\n upsertAuthProfile({\n profileId: config.profileId,\n credential: {\n type: 'oauth',\n provider,\n ...creds,\n },\n });\n return true;\n } catch (error) {\n console.error('❌ OAuth login failed:', error);\n return false;\n }\n}\n\n/**\n * Configure AI model provider and model\n */\nexport async function setupModel(\n existingConfig: Config | null,\n ctx: CLIContext\n): Promise<Config> {\n console.log('\\n🤖 Step: AI Model\\n');\n\n const config = existingConfig || ({} as Config);\n const currentModelConfig = config?.agents?.defaults?.model;\n const currentModel =\n typeof currentModelConfig === 'string' ? currentModelConfig : currentModelConfig?.primary;\n\n if (currentModel) {\n console.log('Current model:', currentModel);\n const keepCurrent = await confirm({\n message: 'Keep using this model?',\n default: true,\n });\n if (keepCurrent) {\n console.log('✅ Keeping:', currentModel);\n return config;\n }\n }\n\n // Get sorted providers with metadata\n const sortedProviders = getSortedProviders();\n\n const choices = sortedProviders.map((p) => ({\n value: p,\n name: getProviderDisplayName(p),\n }));\n\n const provider = await select({\n message: 'Select provider:',\n choices,\n });\n\n const providerName = getProviderDisplayName(provider);\n\n // Check if provider has existing profiles\n const existingProfiles = listProfilesForProvider(provider);\n if (existingProfiles.length > 0) {\n console.log(`\\n${colors.green('✓')} Found existing credentials for ${providerName}`);\n const useExisting = await confirm({\n message: 'Use existing credentials?',\n default: true,\n });\n\n if (useExisting) {\n // Get available models\n const modelChoices = await getModelsForProvider(provider);\n if (modelChoices.length === 0) {\n console.log(`\\n⚠️ No models found for ${providerName}. Please check your credentials.`);\n } else {\n const model = await select({\n message: 'Select model:',\n choices: modelChoices,\n });\n\n config.agents = config.agents || {};\n config.agents.defaults = config.agents.defaults || {\n workspace: ctx.workspacePath,\n model: { primary: model, fallbacks: [] },\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n };\n config.agents.defaults.model = { primary: model, fallbacks: [] };\n config.agents.defaults.workspace = ctx.workspacePath;\n\n console.log('\\n✅ Model configured:', model);\n return config;\n }\n }\n }\n\n let apiKey: string | undefined;\n let useOAuth = false;\n\n apiKey = getApiKeyFromEnv(provider);\n if (apiKey) {\n console.log(`\\n${colors.green('✓')} Found API key for ${providerName} in environment`);\n }\n\n if (!apiKey) {\n // Check auth support from metadata\n const supportsOAuth = providerSupportsOAuth(provider);\n const supportsApiKey = providerSupportsApiKey(provider);\n const isOAuthOnly = supportsOAuth && !supportsApiKey;\n\n if (isOAuthOnly) {\n // OAuth only - no choice\n const success = await doOAuthLogin(provider);\n if (success) {\n useOAuth = true;\n console.log('\\n✅ OAuth login successful!');\n } else {\n console.error('\\n❌ OAuth login failed. This provider requires OAuth.');\n return config;\n }\n } else if (supportsOAuth && supportsApiKey) {\n // Dual auth - let user choose\n const authMethod = await select({\n message: `How would you like to authenticate with ${providerName}?`,\n choices: [\n { value: 'api_key', name: 'API Key (enter manually)' },\n { value: 'oauth', name: 'OAuth Login (browser-based)' },\n ],\n });\n\n if (authMethod === 'oauth') {\n const success = await doOAuthLogin(provider);\n if (success) {\n useOAuth = true;\n console.log('\\n✅ OAuth login successful!');\n } else {\n console.log('\\n⚠️ OAuth login failed. Please enter API key manually.');\n apiKey = await input({\n message: `API Key for ${providerName}:`,\n validate: (v: string) => v.length > 0 || 'Required',\n });\n useOAuth = false;\n }\n } else {\n apiKey = await input({\n message: `API Key for ${providerName}:`,\n validate: (v: string) => v.length > 0 || 'Required',\n });\n }\n } else {\n // API key only\n apiKey = await input({\n message: `API Key for ${providerName}:`,\n validate: (v: string) => v.length > 0 || 'Required',\n });\n }\n }\n\n // Get available models\n const modelChoices = await getModelsForProvider(provider);\n if (modelChoices.length === 0) {\n console.log(`\\n⚠️ No built-in models found for ${providerName}.`);\n console.log(' You can still use custom model names.');\n const model = await input({\n message: 'Model name:',\n validate: (v: string) => v.length > 0 || 'Required',\n });\n\n // Store API key in new credential system\n if (apiKey) {\n const resolver = new CredentialResolver();\n await resolver.saveApiKey(provider, apiKey, { profileName: 'default' });\n }\n\n config.agents = config.agents || {};\n config.agents.defaults = config.agents.defaults || {\n workspace: ctx.workspacePath,\n model: { primary: `${provider}/${model}`, fallbacks: [] },\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n };\n config.agents.defaults.model = { primary: `${provider}/${model}`, fallbacks: [] };\n config.agents.defaults.workspace = ctx.workspacePath;\n\n console.log('\\n✅ Model configured:', `${provider}/${model}`);\n return config;\n }\n\n console.log(`\\n📋 Available models for ${providerName}:`);\n const model = await select({\n message: 'Select model:',\n choices: modelChoices,\n });\n\n // Store in new credential system\n if (!useOAuth && apiKey) {\n const resolver = new CredentialResolver();\n await resolver.saveApiKey(provider, apiKey, { profileName: 'default' });\n }\n\n config.agents = config.agents || {};\n config.agents.defaults = config.agents.defaults || {\n workspace: ctx.workspacePath,\n model: { primary: model, fallbacks: [] },\n maxTokens: 8192,\n temperature: 0.7,\n maxToolIterations: 20,\n maxRequestsPerTurn: 50,\n maxToolFailuresPerTurn: 3,\n };\n config.agents.defaults.model = { primary: model, fallbacks: [] };\n config.agents.defaults.workspace = ctx.workspacePath;\n\n console.log('\\n✅ Model configured:', model);\n return config;\n}\n"],"mappings":"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"}
|