@xopcai/xopc 0.0.8 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/extensions/telegram/src/plugin.js +1 -1
- package/dist/extensions/telegram/src/routing-integration.js +2 -2
- package/dist/extensions/weixin/src/plugin.js +1 -1
- package/dist/gateway/static/root/assets/{agents-BSNzJWbQ.js → agents-BdC4Y-HX.js} +2 -2
- package/dist/gateway/static/root/assets/agents-BdC4Y-HX.js.map +1 -0
- package/dist/gateway/static/root/assets/{apps-page-BKk9SB4D.js → apps-page-C-oaSHkm.js} +2 -2
- package/dist/gateway/static/root/assets/{apps-page-BKk9SB4D.js.map → apps-page-C-oaSHkm.js.map} +1 -1
- package/dist/gateway/static/root/assets/attachment-load-BDDlItdE.js +1 -0
- package/dist/gateway/static/root/assets/{channels-settings-_J6cQN6G.js → channels-settings-BqEUppPO.js} +2 -2
- package/dist/gateway/static/root/assets/{channels-settings-_J6cQN6G.js.map → channels-settings-BqEUppPO.js.map} +1 -1
- package/dist/gateway/static/root/assets/{chat-agents-api-DPb_0O8M.js → chat-agents-api-BhqjQ7iL.js} +2 -2
- package/dist/gateway/static/root/assets/{chat-agents-api-DPb_0O8M.js.map → chat-agents-api-BhqjQ7iL.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-page-BUJOuuKX.js → cron-page-Cli49RKR.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-page-BUJOuuKX.js.map → cron-page-Cli49RKR.js.map} +1 -1
- package/dist/gateway/static/root/assets/{cron-utils-Cn0YVg8x.js → cron-utils-Dkj-Ldpf.js} +2 -2
- package/dist/gateway/static/root/assets/{cron-utils-Cn0YVg8x.js.map → cron-utils-Dkj-Ldpf.js.map} +1 -1
- package/dist/gateway/static/root/assets/{electron-env-D9bm1FIu.js → electron-env-BDtJw9AY.js} +2 -2
- package/dist/gateway/static/root/assets/{electron-env-D9bm1FIu.js.map → electron-env-BDtJw9AY.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-debug-page-DTz4O5Ua.js → extension-debug-page-BMcZlaxF.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-debug-page-DTz4O5Ua.js.map → extension-debug-page-BMcZlaxF.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-iframe-host-Cs1Kde9o.js → extension-iframe-host-D5HEF0KR.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-iframe-host-Cs1Kde9o.js.map → extension-iframe-host-D5HEF0KR.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-page-G52iX0Bo.js → extension-page-CXdCSSPl.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-page-G52iX0Bo.js.map → extension-page-CXdCSSPl.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-provider-CO2jxBA9.js → extension-provider-DZCZgQE2.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-provider-CO2jxBA9.js.map → extension-provider-DZCZgQE2.js.map} +1 -1
- package/dist/gateway/static/root/assets/{extension-settings-page-D9Ul8uSt.js → extension-settings-page-CX6STpx3.js} +2 -2
- package/dist/gateway/static/root/assets/{extension-settings-page-D9Ul8uSt.js.map → extension-settings-page-CX6STpx3.js.map} +1 -1
- package/dist/gateway/static/root/assets/{gateway-config-swr-Bc8SVD15.js → gateway-config-swr-Cph02QZn.js} +2 -2
- package/dist/gateway/static/root/assets/{gateway-config-swr-Bc8SVD15.js.map → gateway-config-swr-Cph02QZn.js.map} +1 -1
- package/dist/gateway/static/root/assets/index-Bty3m0mS.css +2 -0
- package/dist/gateway/static/root/assets/{index-BXUJbteW.js → index-iTUyfzNr.js} +10 -10
- package/dist/gateway/static/root/assets/index-iTUyfzNr.js.map +1 -0
- package/dist/gateway/static/root/assets/{logs-page-5V25JkQY.js → logs-page-B9O5l3I8.js} +2 -2
- package/dist/gateway/static/root/assets/{logs-page-5V25JkQY.js.map → logs-page-B9O5l3I8.js.map} +1 -1
- package/dist/gateway/static/root/assets/{model-selector-he3aQfme.js → model-selector-BLiY_O25.js} +2 -2
- package/dist/gateway/static/root/assets/{model-selector-he3aQfme.js.map → model-selector-BLiY_O25.js.map} +1 -1
- package/dist/gateway/static/root/assets/page-header-store-BFpnFTed.js +2 -0
- package/dist/gateway/static/root/assets/{page-header-store-DJHD9Ean.js.map → page-header-store-BFpnFTed.js.map} +1 -1
- package/dist/gateway/static/root/assets/{session-api-n-4O5d9U.js → session-api-DEhQXWJg.js} +2 -2
- package/dist/gateway/static/root/assets/{session-api-n-4O5d9U.js.map → session-api-DEhQXWJg.js.map} +1 -1
- package/dist/gateway/static/root/assets/{session-working-directory-control-B6dHLvbr.js → session-working-directory-control-DKOtWs3-.js} +2 -2
- package/dist/gateway/static/root/assets/{session-working-directory-control-B6dHLvbr.js.map → session-working-directory-control-DKOtWs3-.js.map} +1 -1
- package/dist/gateway/static/root/assets/{sessions-page-rBUfTdm3.js → sessions-page-BYlWP1ep.js} +2 -2
- package/dist/gateway/static/root/assets/{sessions-page-rBUfTdm3.js.map → sessions-page-BYlWP1ep.js.map} +1 -1
- package/dist/gateway/static/root/assets/{settings-page-B3QrJm-E.js → settings-page-oCnIavdg.js} +2 -2
- package/dist/gateway/static/root/assets/settings-page-oCnIavdg.js.map +1 -0
- package/dist/gateway/static/root/assets/{skill-api-vxtE8kI6.js → skill-api-DWrn8Az0.js} +2 -2
- package/dist/gateway/static/root/assets/{skill-api-vxtE8kI6.js.map → skill-api-DWrn8Az0.js.map} +1 -1
- package/dist/gateway/static/root/assets/{skills-page-D36_O2Ub.js → skills-page-C59WQpM1.js} +2 -2
- package/dist/gateway/static/root/assets/{skills-page-D36_O2Ub.js.map → skills-page-C59WQpM1.js.map} +1 -1
- package/dist/gateway/static/root/assets/{theme-store-CmiSsYBd.js → theme-store-CywXkKml.js} +2 -2
- package/dist/gateway/static/root/assets/{theme-store-CmiSsYBd.js.map → theme-store-CywXkKml.js.map} +1 -1
- package/dist/gateway/static/root/assets/url-D7yWllI8.js +2 -0
- package/dist/gateway/static/root/assets/url-D7yWllI8.js.map +1 -0
- package/dist/gateway/static/root/assets/{useTranslation-DYORQ7x6.js → useTranslation-CACj0DBJ.js} +2 -2
- package/dist/gateway/static/root/assets/{useTranslation-DYORQ7x6.js.map → useTranslation-CACj0DBJ.js.map} +1 -1
- package/dist/gateway/static/root/index.html +15 -15
- package/dist/package.js +1 -1
- package/dist/src/agent/agent-manager.d.ts +1 -0
- package/dist/src/agent/agent-manager.js +20 -12
- package/dist/src/agent/agent-manager.js.map +1 -1
- package/dist/src/agent/background-review/run-background-review.js +2 -0
- package/dist/src/agent/background-review/run-background-review.js.map +1 -1
- package/dist/src/agent/child-agent-factory.js +2 -0
- package/dist/src/agent/child-agent-factory.js.map +1 -1
- package/dist/src/agent/context/expand-at-file-mentions.d.ts +4 -0
- package/dist/src/agent/context/expand-at-file-mentions.js +69 -0
- package/dist/src/agent/context/expand-at-file-mentions.js.map +1 -0
- package/dist/src/agent/context/workspace-seed.js +1 -1
- package/dist/src/agent/image/understanding/pi-ai-provider.js.map +1 -1
- package/dist/src/agent/ipc/bus.js +1 -1
- package/dist/src/agent/ipc/inbox.js +1 -1
- package/dist/src/agent/ipc/socket.js +1 -1
- package/dist/src/agent/memory/compaction.d.ts +1 -1
- package/dist/src/agent/memory/compaction.js +38 -11
- package/dist/src/agent/memory/compaction.js.map +1 -1
- package/dist/src/agent/messaging/command-handler.d.ts +13 -0
- package/dist/src/agent/messaging/command-handler.js +14 -2
- package/dist/src/agent/messaging/command-handler.js.map +1 -1
- package/dist/src/agent/models/manager.js +1 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js +6 -1
- package/dist/src/agent/orchestration/agent-orchestrator.js.map +1 -1
- package/dist/src/agent/prompt/service-prompt-builder.js +1 -1
- package/dist/src/agent/service.d.ts +16 -1
- package/dist/src/agent/service.js +178 -20
- package/dist/src/agent/service.js.map +1 -1
- package/dist/src/agent/skills/format-skills-prompt.js.map +1 -1
- package/dist/src/agent/skills/index.js +1 -1
- package/dist/src/agent/skills/scanner.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js +1 -1
- package/dist/src/agent/skills/skill-manage-ops.js.map +1 -1
- package/dist/src/agent/skills/skill-manager.js +1 -1
- package/dist/src/agent/tools/browser/tools.js.map +1 -1
- package/dist/src/agent/tools/factory.js +1 -1
- package/dist/src/agent/tools/image-tool.js.map +1 -1
- package/dist/src/agent/tools/send-media.js +1 -1
- package/dist/src/agent/tools/skill-manage-tool.js +1 -1
- package/dist/src/agent/tools/write.js +1 -1
- package/dist/src/auth/credentials.js +2 -2
- package/dist/src/auth/sync-provider-auth.js +1 -1
- package/dist/src/channels/attachments/inbound-persist.js +1 -1
- package/dist/src/channels/attachments/outbound-tts-persist.js +1 -1
- package/dist/src/channels/index.d.ts +1 -1
- package/dist/src/channels/index.js +2 -2
- package/dist/src/channels/pipeline.d.ts +8 -1
- package/dist/src/channels/pipeline.js +49 -4
- package/dist/src/channels/pipeline.js.map +1 -1
- package/dist/src/chat-commands/builtins/config.d.ts +4 -0
- package/dist/src/chat-commands/builtins/config.js +197 -0
- package/dist/src/chat-commands/builtins/config.js.map +1 -0
- package/dist/src/chat-commands/builtins/context.d.ts +4 -0
- package/dist/src/chat-commands/builtins/context.js +44 -0
- package/dist/src/chat-commands/builtins/context.js.map +1 -0
- package/dist/src/chat-commands/builtins/session.js +111 -0
- package/dist/src/chat-commands/builtins/session.js.map +1 -1
- package/dist/src/chat-commands/builtins/thinking.js +49 -21
- package/dist/src/chat-commands/builtins/thinking.js.map +1 -1
- package/dist/src/chat-commands/config-paths.d.ts +10 -0
- package/dist/src/chat-commands/config-paths.js +45 -0
- package/dist/src/chat-commands/config-paths.js.map +1 -0
- package/dist/src/chat-commands/config-value.d.ts +12 -0
- package/dist/src/chat-commands/config-value.js +53 -0
- package/dist/src/chat-commands/config-value.js.map +1 -0
- package/dist/src/chat-commands/context.d.ts +24 -1
- package/dist/src/chat-commands/context.js +41 -0
- package/dist/src/chat-commands/context.js.map +1 -1
- package/dist/src/chat-commands/index.d.ts +2 -0
- package/dist/src/chat-commands/index.js +5 -1
- package/dist/src/chat-commands/index.js.map +1 -1
- package/dist/src/chat-commands/types.d.ts +33 -1
- package/dist/src/cli/commands/agent/interactive.js +1 -1
- package/dist/src/cli/commands/agent/interactive.js.map +1 -1
- package/dist/src/cli/commands/agent.js +22 -10
- package/dist/src/cli/commands/agent.js.map +1 -1
- package/dist/src/cli/commands/auth.js.map +1 -1
- package/dist/src/cli/commands/doctor/checks/provider-auth.js +1 -1
- package/dist/src/cli/commands/extension.js +10 -0
- package/dist/src/cli/commands/extension.js.map +1 -1
- package/dist/src/cli/commands/init.js +3 -4
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/session/utils.js.map +1 -1
- package/dist/src/cli/commands/update.d.ts +1 -0
- package/dist/src/cli/commands/update.js +171 -0
- package/dist/src/cli/commands/update.js.map +1 -0
- package/dist/src/cli/index.d.ts +1 -1
- package/dist/src/cli/index.js +3 -1
- package/dist/src/cli/index.js.map +1 -1
- package/dist/src/config/index.d.ts +1 -0
- package/dist/src/config/index.js +5 -4
- package/dist/src/config/index.js.map +1 -1
- package/dist/src/config/loader.js +1 -1
- package/dist/src/config/models-json.js +1 -1
- package/dist/src/config/paths.js.map +1 -1
- package/dist/src/config/profile.js +2 -2
- package/dist/src/config/runtime-overrides.d.ts +8 -0
- package/dist/src/config/runtime-overrides.js +40 -0
- package/dist/src/config/runtime-overrides.js.map +1 -0
- package/dist/src/config/schema.d.ts +35 -0
- package/dist/src/config/schema.js +19 -3
- package/dist/src/config/schema.js.map +1 -1
- package/dist/src/cron/executor.js +2 -2
- package/dist/src/cron/persistence.js +1 -1
- package/dist/src/cron/run-log-store.js +1 -1
- package/dist/src/extensions/health.js +1 -1
- package/dist/src/extensions/loader.d.ts +1 -1
- package/dist/src/extensions/loader.js +6 -9
- package/dist/src/extensions/loader.js.map +1 -1
- package/dist/src/extensions/lockfile.js +1 -1
- package/dist/src/extensions/sdk/index.js +6 -1
- package/dist/src/extensions/sdk/index.js.map +1 -0
- package/dist/src/gateway/agents-admin.js +2 -2
- package/dist/src/gateway/agents-admin.js.map +1 -1
- package/dist/src/gateway/hono/oauth.js +1 -1
- package/dist/src/gateway/hono/routes/config.js +1 -1
- package/dist/src/gateway/hono/routes/index.js +2 -0
- package/dist/src/gateway/hono/routes/index.js.map +1 -1
- package/dist/src/gateway/hono/routes/models.js +64 -11
- package/dist/src/gateway/hono/routes/models.js.map +1 -1
- package/dist/src/gateway/hono/routes/public-gateway.js +10 -0
- package/dist/src/gateway/hono/routes/public-gateway.js.map +1 -1
- package/dist/src/gateway/hono/routes/update.d.ts +3 -0
- package/dist/src/gateway/hono/routes/update.js +141 -0
- package/dist/src/gateway/hono/routes/update.js.map +1 -0
- package/dist/src/gateway/hono/routes/workspace.js +84 -4
- package/dist/src/gateway/hono/routes/workspace.js.map +1 -1
- package/dist/src/gateway/hono/sse.js +2 -2
- package/dist/src/gateway/service.d.ts +1 -0
- package/dist/src/gateway/service.js +16 -4
- package/dist/src/gateway/service.js.map +1 -1
- package/dist/src/gateway/workspace-fs-file-list.d.ts +5 -0
- package/dist/src/gateway/workspace-fs-file-list.js +56 -0
- package/dist/src/gateway/workspace-fs-file-list.js.map +1 -0
- package/dist/src/gateway/workspace-heartbeat-path.js +1 -1
- package/dist/src/gateway/workspace-ripgrep.d.ts +5 -0
- package/dist/src/gateway/workspace-ripgrep.js +88 -4
- package/dist/src/gateway/workspace-ripgrep.js.map +1 -1
- package/dist/src/infra/update-channels.d.ts +14 -0
- package/dist/src/infra/update-channels.js +30 -0
- package/dist/src/infra/update-channels.js.map +1 -0
- package/dist/src/infra/update-check.d.ts +53 -0
- package/dist/src/infra/update-check.js +155 -0
- package/dist/src/infra/update-check.js.map +1 -0
- package/dist/src/infra/update-runner.d.ts +18 -0
- package/dist/src/infra/update-runner.js +112 -0
- package/dist/src/infra/update-runner.js.map +1 -0
- package/dist/src/infra/update-startup.d.ts +20 -0
- package/dist/src/infra/update-startup.js +246 -0
- package/dist/src/infra/update-startup.js.map +1 -0
- package/dist/src/providers/extension-stream-bridge.d.ts +3 -0
- package/dist/src/providers/extension-stream-bridge.js +239 -0
- package/dist/src/providers/extension-stream-bridge.js.map +1 -0
- package/dist/src/providers/index.d.ts +7 -2
- package/dist/src/providers/index.js +77 -14
- package/dist/src/providers/index.js.map +1 -1
- package/dist/src/providers/model-registry.js +1 -1
- package/dist/src/providers/plugin-registry.js +92 -87
- package/dist/src/providers/plugin-registry.js.map +1 -1
- package/dist/src/session/chat-export.d.ts +5 -0
- package/dist/src/session/chat-export.js +35 -0
- package/dist/src/session/chat-export.js.map +1 -0
- package/dist/src/session/config-store.js +1 -1
- package/dist/src/session/manager.d.ts +1 -1
- package/dist/src/session/manager.js +2 -2
- package/dist/src/session/manager.js.map +1 -1
- package/dist/src/session/session-title.js +1 -1
- package/dist/src/session/store.d.ts +1 -1
- package/dist/src/session/store.js +5 -5
- package/dist/src/session/store.js.map +1 -1
- package/dist/src/utils/logger/audit.js +1 -1
- package/dist/src/utils/logger/log-store.js +1 -1
- package/dist/src/utils/logger/rotation.js +1 -1
- package/dist/src/voice/tts/audio.js +1 -1
- package/package.json +2 -1
- package/dist/gateway/static/root/assets/agents-BSNzJWbQ.js.map +0 -1
- package/dist/gateway/static/root/assets/attachment-load-DXcJLSWT.js +0 -1
- package/dist/gateway/static/root/assets/index-BXUJbteW.js.map +0 -1
- package/dist/gateway/static/root/assets/index-CQLMxWSA.css +0 -2
- package/dist/gateway/static/root/assets/page-header-store-DJHD9Ean.js +0 -2
- package/dist/gateway/static/root/assets/settings-page-B3QrJm-E.js.map +0 -1
- package/dist/gateway/static/root/assets/url-CtSqjF9J.js +0 -2
- package/dist/gateway/static/root/assets/url-CtSqjF9J.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","names":[],"sources":["../../../../src/cli/commands/agent.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { AgentService } from '../../agent/index.js';\nimport { loadConfig, getWorkspacePath } from '../../config/index.js';\nimport { MessageBus, MessageBusShutdownError } from '../../infra/bus/index.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { getContextWithOpts } from '../index.js';\nimport { ExtensionLoader } from '../../extensions/index.js';\nimport { join } from 'path';\nimport { listSessions } from './agent/sessions.js';\nimport { startInteractiveChat } from './agent/interactive.js';\n\nconst log = createLogger('AgentCommand');\n\ninterface AgentCommandOptions {\n message?: string;\n interactive?: boolean;\n session?: string;\n list?: boolean;\n}\n\nfunction createAgentCommand(_ctx: CLIContext): Command {\n const cmd = new Command('agent')\n .description('Chat with the AI agent')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc agent -m \"Hello\" # Single message',\n 'xopc agent -i # Interactive chat mode',\n 'xopc agent -i --session telegram:dm:123456 # Continue existing session',\n 'xopc agent --list # List available sessions',\n ])\n )\n .option('-m, --message <text>', 'Single message to send')\n .option('-i, --interactive', 'Interactive chat mode')\n .option('-s, --session <key>', 'Continue an existing session (use --list to see available sessions)')\n .option('-l, --list', 'List available sessions and exit')\n .action(async (options: AgentCommandOptions) => {\n const ctx = getContextWithOpts();\n const config = loadConfig(ctx.configPath);\n const workspace = getWorkspacePath(config) || ctx.workspacePath;\n\n // Handle --list option\n if (options.list) {\n await listSessions();\n return;\n }\n\n const modelConfig = config.agents?.defaults?.model;\n const
|
|
1
|
+
{"version":3,"file":"agent.js","names":[],"sources":["../../../../src/cli/commands/agent.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { AgentService } from '../../agent/index.js';\nimport { loadConfig, getWorkspacePath } from '../../config/index.js';\nimport { MessageBus, MessageBusShutdownError } from '../../infra/bus/index.js';\nimport { createLogger } from '../../utils/logger.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { getContextWithOpts } from '../index.js';\nimport { ExtensionLoader } from '../../extensions/index.js';\nimport { join } from 'path';\nimport { listSessions } from './agent/sessions.js';\nimport { startInteractiveChat } from './agent/interactive.js';\n\nconst log = createLogger('AgentCommand');\n\ninterface AgentCommandOptions {\n message?: string;\n model?: string;\n interactive?: boolean;\n session?: string;\n list?: boolean;\n}\n\nfunction createAgentCommand(_ctx: CLIContext): Command {\n const cmd = new Command('agent')\n .description('Chat with the AI agent')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc agent -m \"Hello\" # Single message',\n 'xopc agent --model demo/demo-chat-7b -m \"Hi\" # Override model for one shot',\n 'xopc agent -i # Interactive chat mode',\n 'xopc agent -i --session telegram:dm:123456 # Continue existing session',\n 'xopc agent --list # List available sessions',\n ])\n )\n .option('--model <id>', 'Model ref for this run (e.g. demo/demo-chat-7b, anthropic/claude-sonnet-4-5)')\n .option('-m, --message <text>', 'Single message to send')\n .option('-i, --interactive', 'Interactive chat mode')\n .option('-s, --session <key>', 'Continue an existing session (use --list to see available sessions)')\n .option('-l, --list', 'List available sessions and exit')\n .action(async (options: AgentCommandOptions) => {\n const ctx = getContextWithOpts();\n const config = loadConfig(ctx.configPath);\n const workspace = getWorkspacePath(config) || ctx.workspacePath;\n\n // Handle --list option\n if (options.list) {\n await listSessions();\n return;\n }\n\n const modelConfig = config.agents?.defaults?.model;\n const modelFromConfig = typeof modelConfig === 'string' ? modelConfig : modelConfig?.primary;\n const modelId = (options.model?.trim() || modelFromConfig) as string | undefined;\n const bus = new MessageBus();\n\n if (ctx.isVerbose) {\n log.info({ model: modelId, workspace, session: options.session }, 'Starting agent');\n }\n\n // Validate session key if provided\n let sessionKey = options.session || 'cli:direct';\n if (options.session) {\n const { getSessionManager } = await import('../utils/session.js');\n const manager = await getSessionManager();\n const session = await manager.getSessionMetadata(options.session);\n if (!session) {\n console.error(`❌ Session not found: ${options.session}`);\n console.log('Use --list to see available sessions.');\n process.exit(1);\n }\n console.log(`📂 Continuing session: ${options.session} (${session.messageCount} messages)\\n`);\n }\n\n // Initialize extension loader (manifest-first activation: env, channels, model, extensions.*)\n let extensionLoader: ExtensionLoader | null = null;\n try {\n extensionLoader = new ExtensionLoader({\n workspaceDir: workspace,\n extensionsDir: join(workspace, '.extensions'),\n });\n extensionLoader.setConfig(config as Parameters<ExtensionLoader['setConfig']>[0]);\n extensionLoader.setRuntimeContext({ bus });\n await extensionLoader.loadByActivationPlan();\n const n = extensionLoader.getRegistry().extensions.size;\n if (n > 0) {\n log.info({ count: n }, 'Extensions loaded');\n }\n } catch (error) {\n const em = error instanceof Error ? error.message : String(error);\n log.warn({ err: error, errorMessage: em }, `CLI agent: failed to load extensions: ${em}`);\n }\n\n const { createCliReadlineClarifyRequestFn } = await import('../../agent/tools/cli-clarify.js');\n\n const agent = new AgentService(bus, {\n workspace,\n model: modelId,\n config,\n extensionRegistry: extensionLoader?.getRegistry(),\n gatewayClarify: {\n requestClarification: createCliReadlineClarifyRequestFn(),\n },\n });\n\n // Start agent service in background\n agent.start().catch((err) => {\n const em = err instanceof Error ? err.message : String(err);\n log.error({ err, errorMessage: em }, `CLI agent service exited: ${em}`);\n });\n\n // Start outbound message processor for CLI mode\n let running = true;\n const _outboundProcessor = (async () => {\n while (running) {\n try {\n const msg = await bus.consumeOutbound();\n console.log(`\\n📤 [${msg.channel}] ${msg.chat_id}: ${msg.content.slice(0, 100)}...`);\n } catch (error) {\n if (error instanceof MessageBusShutdownError) {\n break;\n }\n const em = error instanceof Error ? error.message : String(error);\n log.error({ err: error, errorMessage: em }, `CLI outbound processor failed: ${em}`);\n await new Promise((resolve) => setTimeout(resolve, 1000));\n }\n }\n })();\n\n const shutdown = async () => {\n running = false;\n bus.shutdown();\n await agent.stop();\n };\n\n process.on('SIGINT', shutdown);\n process.on('SIGTERM', shutdown);\n\n if (options.message) {\n const oneShotModel = options.model?.trim();\n if (oneShotModel) {\n await agent.switchModelForSession(sessionKey, oneShotModel);\n }\n const response = await agent.processDirect(options.message, sessionKey);\n console.log('\\n🤖:', response);\n if (oneShotModel) {\n await agent.resetSessionModelToAgentDefault(sessionKey);\n }\n await shutdown();\n } else if (options.interactive) {\n const interactiveModel = options.model?.trim();\n if (interactiveModel) {\n await agent.switchModelForSession(sessionKey, interactiveModel);\n }\n await startInteractiveChat(agent, {\n workspace,\n sessionKey,\n continuingSession: !!options.session,\n });\n } else {\n await shutdown();\n cmd.help();\n }\n });\n\n return cmd;\n}\n\nregister({\n id: 'agent',\n name: 'agent',\n description: 'Chat with the AI agent',\n factory: createAgentCommand,\n metadata: {\n category: 'runtime',\n examples: [\n 'xopc agent -m \"Hello\"',\n 'xopc agent --model demo/demo-chat-7b -m \"Hello demo!\"',\n 'xopc agent -i',\n ],\n },\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;aAIqD;AAQrD,MAAM,MAAM,aAAa,eAAe;AAUxC,SAAS,mBAAmB,MAA2B;CACrD,MAAM,MAAM,IAAI,QAAQ,QAAQ,CAC7B,YAAY,yBAAyB,CACrC,YACC,SACA,eAAe;EACb;EACA;EACA;EACA;EACA;EACD,CAAC,CACH,CACA,OAAO,gBAAgB,+EAA+E,CACtG,OAAO,wBAAwB,yBAAyB,CACxD,OAAO,qBAAqB,wBAAwB,CACpD,OAAO,uBAAuB,sEAAsE,CACpG,OAAO,cAAc,mCAAmC,CACxD,OAAO,OAAO,YAAiC;EAC9C,MAAM,MAAM,oBAAoB;EAChC,MAAM,SAAS,WAAW,IAAI,WAAW;EACzC,MAAM,YAAY,iBAAiB,OAAO,IAAI,IAAI;AAGlD,MAAI,QAAQ,MAAM;AAChB,SAAM,cAAc;AACpB;;EAGF,MAAM,cAAc,OAAO,QAAQ,UAAU;EAC7C,MAAM,kBAAkB,OAAO,gBAAgB,WAAW,cAAc,aAAa;EACrF,MAAM,UAAW,QAAQ,OAAO,MAAM,IAAI;EAC1C,MAAM,MAAM,IAAI,YAAY;AAE5B,MAAI,IAAI,UACN,KAAI,KAAK;GAAE,OAAO;GAAS;GAAW,SAAS,QAAQ;GAAS,EAAE,iBAAiB;EAIrF,IAAI,aAAa,QAAQ,WAAW;AACpC,MAAI,QAAQ,SAAS;GACnB,MAAM,EAAE,sBAAsB,MAAM,OAAO;GAE3C,MAAM,UAAU,OADA,MAAM,mBAAmB,EACX,mBAAmB,QAAQ,QAAQ;AACjE,OAAI,CAAC,SAAS;AACZ,YAAQ,MAAM,wBAAwB,QAAQ,UAAU;AACxD,YAAQ,IAAI,wCAAwC;AACpD,YAAQ,KAAK,EAAE;;AAEjB,WAAQ,IAAI,0BAA0B,QAAQ,QAAQ,IAAI,QAAQ,aAAa,cAAc;;EAI/F,IAAI,kBAA0C;AAC9C,MAAI;AACF,qBAAkB,IAAI,gBAAgB;IACpC,cAAc;IACd,eAAe,KAAK,WAAW,cAAc;IAC9C,CAAC;AACF,mBAAgB,UAAU,OAAsD;AAChF,mBAAgB,kBAAkB,EAAE,KAAK,CAAC;AAC1C,SAAM,gBAAgB,sBAAsB;GAC5C,MAAM,IAAI,gBAAgB,aAAa,CAAC,WAAW;AACnD,OAAI,IAAI,EACN,KAAI,KAAK,EAAE,OAAO,GAAG,EAAE,oBAAoB;WAEtC,OAAO;GACd,MAAM,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACjE,OAAI,KAAK;IAAE,KAAK;IAAO,cAAc;IAAI,EAAE,yCAAyC,KAAK;;EAG3F,MAAM,EAAE,sCAAsC,MAAM,OAAO;EAE3D,MAAM,QAAQ,IAAI,aAAa,KAAK;GAClC;GACA,OAAO;GACP;GACA,mBAAmB,iBAAiB,aAAa;GACjD,gBAAgB,EACd,sBAAsB,mCAAmC,EAC1D;GACF,CAAC;AAGF,QAAM,OAAO,CAAC,OAAO,QAAQ;GAC3B,MAAM,KAAK,eAAe,QAAQ,IAAI,UAAU,OAAO,IAAI;AAC3D,OAAI,MAAM;IAAE;IAAK,cAAc;IAAI,EAAE,6BAA6B,KAAK;IACvE;EAGF,IAAI,UAAU;AACa,GAAC,YAAY;AACtC,UAAO,QACL,KAAI;IACF,MAAM,MAAM,MAAM,IAAI,iBAAiB;AACvC,YAAQ,IAAI,SAAS,IAAI,QAAQ,IAAI,IAAI,QAAQ,IAAI,IAAI,QAAQ,MAAM,GAAG,IAAI,CAAC,KAAK;YAC7E,OAAO;AACd,QAAI,iBAAiB,wBACnB;IAEF,MAAM,KAAK,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACjE,QAAI,MAAM;KAAE,KAAK;KAAO,cAAc;KAAI,EAAE,kCAAkC,KAAK;AACnF,UAAM,IAAI,SAAS,YAAY,WAAW,SAAS,IAAK,CAAC;;MAG3D;EAEJ,MAAM,WAAW,YAAY;AAC3B,aAAU;AACV,OAAI,UAAU;AACd,SAAM,MAAM,MAAM;;AAGpB,UAAQ,GAAG,UAAU,SAAS;AAC9B,UAAQ,GAAG,WAAW,SAAS;AAE/B,MAAI,QAAQ,SAAS;GACnB,MAAM,eAAe,QAAQ,OAAO,MAAM;AAC1C,OAAI,aACF,OAAM,MAAM,sBAAsB,YAAY,aAAa;GAE7D,MAAM,WAAW,MAAM,MAAM,cAAc,QAAQ,SAAS,WAAW;AACvE,WAAQ,IAAI,SAAS,SAAS;AAC9B,OAAI,aACF,OAAM,MAAM,gCAAgC,WAAW;AAEzD,SAAM,UAAU;aACP,QAAQ,aAAa;GAC9B,MAAM,mBAAmB,QAAQ,OAAO,MAAM;AAC9C,OAAI,iBACF,OAAM,MAAM,sBAAsB,YAAY,iBAAiB;AAEjE,SAAM,qBAAqB,OAAO;IAChC;IACA;IACA,mBAAmB,CAAC,CAAC,QAAQ;IAC9B,CAAC;SACG;AACL,SAAM,UAAU;AAChB,OAAI,MAAM;;GAEZ;AAEJ,QAAO;;AAGT,SAAS;CACP,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACR,UAAU;EACV,UAAU;GACR;GACA;GACA;GACD;EACF;CACF,CAAC"}
|
|
@@ -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 { anthropicOAuthProvider, 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\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":";;;;;;;;;;;;;;gBAe2D;aACN;AAKrD,MAAM,MAAM,aAAa,cAAc;AAEvC,SAAS,kBAAkB,MAA2B;CACrD,MAAM,MAAM,IAAI,QAAQ,OAAO,CAC7B,YAAY,oCAAoC,CAChD,YACA,SACA,eAAe;EACd;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,CAAC,CACF;AAGF,KACE,QAAQ,OAAO,CACf,YAAY,iDAAiD,CAC7D,aAAa;AACb,oBAAkB;GACjB;AAGH,KACE,QAAQ,uBAAuB,CAC/B,YAAY,6BAA6B,CACzC,OAAO,6BAA6B,yCAAyC,CAC7E,QAAQ,UAAkB,KAAa,YAAkC;EACzE,MAAM,YAAY,QAAQ,WAAW,GAAG,SAAS;AAQjD,oBAAkB;GAAE;GAAW,YANW;IACzC,MAAM;IACN;IACA;IACA;GAE0C,CAAC;AAC5C,MAAI,KAAK,mBAAmB,SAAS,aAAa,UAAU,GAAG;GAC9D;AAGH,KACE,QAAQ,iBAAiB,CACzB,YAAY,4CAA4C,CACxD,OAAO,6BAA6B,aAAa,CACjD,OAAO,OAAO,UAAkB,aAAmC;EACnE,MAAM,WAAW,wBAAwB,SAAS;AAElD,MAAI,SAAS,WAAW,GAAG;AAC1B,OAAI,MAAM,sCAAsC,WAAW;AAC3D,WAAQ,KAAK,EAAE;;AAGhB,OAAK,MAAM,WAAW,UAAU;GAE/B,MAAM,SAAS,eAAe,QAAQ,OAAO;AAC7C,WAAQ,IAAI,eAAe,WAAW;AACtC,WAAQ,IAAI,YAAY,QAAQ,YAAY;AAC5C,WAAQ,IAAI,SAAS,QAAQ,OAAO;AACpC,WAAQ,IAAI,WAAW,OAAO,GAAG,QAAQ,SAAS,eAAe,YAAY;AAC7E,OAAI,QAAQ,SAAS;IACpB,MAAM,UAAU,IAAI,KAAK,QAAQ,QAAQ;AACzC,YAAQ,IAAI,YAAY,QAAQ,gBAAgB,GAAG;;AAEpD,WAAQ,IAAI,GAAG;;GAEf;AAGH,KACE,QAAQ,oBAAoB,CAC5B,YAAY,uCAAuC,CACnD,OAAO,6BAA6B,uBAAuB,CAC3D,QAAQ,UAAkB,YAAkC;AAC5D,MAAI,QAAQ,SAAS;AAEpB,OADgB,kBAAkB,QAAQ,QAAQ,CAEjD,KAAI,KAAK,oBAAoB,QAAQ,UAAU;OAE/C,KAAI,KAAK,sBAAsB,QAAQ,UAAU;AAElD;;EAID,MAAM,WAAW,wBAAwB,SAAS;AAClD,OAAK,MAAM,WAAW,SACrB,mBAAkB,QAAQ,UAAU;AAErC,MAAI,KAAK,sCAAsC,WAAW;GACzD;AAGH,KACE,QAAQ,mBAAmB,CAC3B,YAAY,kCAAkC,CAC9C,OAAO,6BAA6B,yCAAyC,CAC7E,OAAO,OAAO,UAAkB,YAAkC;EAClE,MAAM,cAAc,iBAAiB,SAAS;AAE9C,MAAI,CAAC,aAAa;AACjB,OAAI,MAAM,qCAAqC,WAAW;AAC1D,OAAI,KAAK,8BAA8B,4BAA4B,CAAC,KAAK,KAAK,GAAG;AACjF,OAAI,KAAK,gEAAgE;AACzE,WAAQ,KAAK,EAAE;;AAGhB,MAAI,KAAK,YAAY,YAAY,YAAY,iBAAiB;EAE9D,MAAM,YAAiC;GACtC,SAAS,SAAS;AACjB,YAAQ,IAAI,OAAO,YAAY,UAAU;AACzC,YAAQ,IAAI,KAAK,IAAI;AACrB,QAAI,KAAK,aACR,SAAQ,IAAI,OAAO,KAAK,aAAa;AAEtC,YAAQ,IAAI,KAAK;;GAElB,UAAU,OAAO,WAAW;IAC3B,MAAM,EAAE,UAAU,MAAM,OAAO;AAC/B,WAAO,MAAM,EAAE,SAAS,OAAO,SAAS,CAAC;;GAE1C,aAAa,YAAY;AACxB,QAAI,KAAK,QAAQ;;GAElB;AAED,MAAI;GACH,MAAM,QAAQ,MAAM,YAAY,SAAS,MAAM,UAAU;GACzD,MAAM,YAAY,QAAQ,WAAW,YAAY;AACjD,qBAAkB;IACjB;IACA,YAAY;KACX,MAAM;KACN;KACA,GAAG;KACH;IACD,CAAC;AACF,OAAI,KAAK,sCAAsC,YAAY;WACnD,OAAO;AACf,OAAI,MAAM,uBAAuB,QAAQ;AACzC,WAAQ,KAAK,EAAE;;GAEf;AAGH,KACE,QAAQ,oBAAoB,CAC5B,YAAY,8CAA8C,CAC1D,OAAO,6BAA6B,uBAAuB,CAC3D,QAAQ,UAAkB,YAAkC;AAC5D,MAAI,QAAQ,SAAS;AAEpB,OADgB,kBAAkB,QAAQ,QAAQ,CAEjD,KAAI,KAAK,eAAe,QAAQ,UAAU;OAE1C,KAAI,KAAK,sBAAsB,QAAQ,UAAU;AAElD;;EAID,MAAM,WAAW,wBAAwB,SAAS;AAClD,MAAI,SAAS,WAAW,GAAG;AAC1B,OAAI,KAAK,mCAAmC,WAAW;AACvD;;AAGD,OAAK,MAAM,WAAW,SACrB,mBAAkB,QAAQ,UAAU;AAErC,MAAI,KAAK,6BAA6B,WAAW;GAChD;CAGH,MAAM,cAAc,IAClB,QAAQ,WAAW,CACnB,YAAY,uBAAuB;AAErC,aACE,QAAQ,OAAO,CACf,YAAY,yBAAyB,CACrC,aAAa;AACb,oBAAkB;GACjB;AAEH,aACE,QAAQ,MAAM,CACd,YAAY,yBAAyB,CACrC,eAAe,6BAA6B,iCAAiC,CAC7E,eAAe,qBAAqB,0CAA0C,CAC9E,OAAO,mBAAmB,6BAA6B,CACvD,OAAO,uBAAuB,uCAAuC,CACrE,QAAQ,YAAY;EACpB,MAAM,EAAE,SAAS,MAAM,KAAK,UAAU;EAEtC,IAAI;AAEJ,MAAI,SAAS,WAAW;AACvB,OAAI,CAAC,KAAK;AACT,QAAI,MAAM,oCAAoC;AAC9C,YAAQ,KAAK,EAAE;;AAEhB,gBAAa;IAAE,MAAM;IAAW,UAAU,QAAQ,MAAM,IAAI,CAAC;IAAI;IAAK;IAAO;aACnE,SAAS,SAAS;AAC5B,OAAI,CAAC,KAAK;AACT,QAAI,MAAM,gCAAgC;AAC1C,YAAQ,KAAK,EAAE;;AAEhB,gBAAa;IAAE,MAAM;IAAS,UAAU,QAAQ,MAAM,IAAI,CAAC;IAAI,OAAO;IAAK;IAAO;SAC5E;AACN,OAAI,MAAM,0DAAwD;AAClE,WAAQ,KAAK,EAAE;;AAGhB,oBAAkB;GAAE,WAAW;GAAS;GAAY,CAAC;AACrD,MAAI,KAAK,kBAAkB,UAAU;GACpC;AAGH,KACE,QAAQ,QAAQ,CAChB,YAAY,uCAAuC,CACnD,aAAa;EACb,MAAM,WAAW,iBAAiB;AAClC,OAAK,MAAM,WAAW,SACrB,mBAAkB,QAAQ,UAAU;AAGrC,MAAI,KAAK,0CAA0C;GAClD;AAGH,KACE,QAAQ,YAAY,CACpB,YAAY,kDAAkD,CAC9D,aAAa;AACb,UAAQ,IAAI,2BAA2B;EAGvC,MAAM,YAAY,iBAAiB;AAEnC,OAAK,MAAM,MAAM,UAChB,SAAQ,IAAI,KAAK,KAAK;AAGvB,UAAQ,IAAI,gDAAgD;AAC5D,UAAQ,IAAI,4CAA4C;GACvD;AAEH,QAAO;;AAGR,SAAS,mBAAyB;CACjC,MAAM,WAAW,iBAAiB;AAElC,KAAI,SAAS,WAAW,GAAG;AAC1B,MAAI,KAAK,+BAA+B;AACxC,MAAI,KAAK,iDAAiD;AAC1D,MAAI,KAAK,kDAAkD;AAC3D;;AAGD,SAAQ,IAAI,qBAAqB;AACjC,MAAK,MAAM,WAAW,UAAU;EAC/B,MAAM,YAAY,QAAQ,SAAS,UAAU,OAAO,SACnD,QAAQ,SAAS,UAAU,OAAO,OAAO,OAAO;EACjD,MAAM,SAAS,eAAe,QAAQ,OAAO;AAE7C,UAAQ,IAAI,KAAK,QAAQ,YAAY;AACrC,UAAQ,IAAI,aAAa,UAAU,QAAQ,KAAK,GAAG;AACnD,UAAQ,IAAI,eAAe,OAAO,GAAG,QAAQ,SAAS,eAAe,YAAY;AACjF,MAAI,QAAQ,MACX,SAAQ,IAAI,cAAc,QAAQ,QAAQ;AAE3C,MAAI,QAAQ,SAAS;GACpB,MAAM,UAAU,IAAI,KAAK,QAAQ,QAAQ;GACzC,MAAM,YAAY,KAAK,KAAK,IAAI,QAAQ;AACxC,WAAQ,IAAI,gBAAgB,YAAY,OAAO,IAAI,GAAG,GAAG,KAAK,QAAQ,gBAAgB,GAAG;;AAE1F,UAAQ,IAAI,GAAG;;;AAKjB,SAAS;CACR,IAAI;CACJ,MAAM;CACN,aAAa;CACb,SAAS;CACT,UAAU;EACT,UAAU;EACV,UAAU;GACT;GACA;GACA;GACA;GACA;GACA;GACA;EACD;CACD,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { PROVIDER_ENV_MAP, getApiKeyFromEnv, init_env_keys } from "../../../../providers/env-keys.js";
|
|
1
2
|
import { getAgentDefaultModelRef, init_schema, parseModelRef } from "../../../../config/schema.js";
|
|
2
3
|
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();
|
|
@@ -118,6 +118,16 @@ function createExtensionAuditCommand() {
|
|
|
118
118
|
});
|
|
119
119
|
}
|
|
120
120
|
function registerExtensionCommands(program) {
|
|
121
|
+
program.addCommand(new Command("extension").description("Extension lockfile and health tools").addHelpText("after", `
|
|
122
|
+
Related commands:
|
|
123
|
+
xopc extension:list List installed extensions (alias: ext:list)
|
|
124
|
+
xopc extension:freeze Lock extension versions (alias: ext:freeze)
|
|
125
|
+
xopc extension:health Health check (alias: ext:health)
|
|
126
|
+
xopc extension:verify Verify integrity (alias: ext:verify)
|
|
127
|
+
xopc extension:audit Security audit (alias: ext:audit)
|
|
128
|
+
`).action((_opts, cmd) => {
|
|
129
|
+
cmd.help();
|
|
130
|
+
}));
|
|
121
131
|
program.addCommand(createExtensionListCommand());
|
|
122
132
|
program.addCommand(createExtensionFreezeCommand());
|
|
123
133
|
program.addCommand(createExtensionHealthCommand());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.js","names":[],"sources":["../../../../src/cli/commands/extension.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createLogger } from '../../utils/logger.js';\nimport { getExtensionLockfileManager } from '../../extensions/lockfile.js';\nimport {\n getExtensionHealthChecker,\n checkAllExtensionsHealth,\n} from '../../extensions/health.js';\nimport { colors } from '../utils/colors.js';\n\nconst log = createLogger('ExtensionCommands');\n\n// ============================================\n// Extension List Command\n// ============================================\n\nexport function createExtensionListCommand(): Command {\n return new Command('extension:list')\n .alias('ext:list')\n .description('List installed extensions')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n const extensions = await lockfileManager.list();\n\n if (options.json) {\n console.log(JSON.stringify(extensions, null, 2));\n return;\n }\n\n if (extensions.length === 0) {\n console.log('No extensions installed.');\n return;\n }\n\n console.log(`Installed extensions (${extensions.length}):`);\n console.log();\n\n for (const ext of extensions) {\n console.log(`${colors.cyan(ext.name)}@${ext.version}`);\n console.log(` Source: ${ext.source}`);\n console.log(` Resolved: ${ext.resolved}`);\n console.log(` Installed: ${new Date(ext.installedAt).toLocaleString()}`);\n console.log();\n }\n } catch (error) {\n log.error({ error }, 'Failed to list extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Freeze Command\n// ============================================\n\nexport function createExtensionFreezeCommand(): Command {\n return new Command('extension:freeze')\n .alias('ext:freeze')\n .description('Lock current extension versions')\n .action(async () => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n await lockfileManager.freeze();\n\n console.log(colors.green('✓'), 'Extension versions locked');\n } catch (error) {\n log.error({ error }, 'Failed to freeze extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Health Command\n// ============================================\n\nexport function createExtensionHealthCommand(): Command {\n return new Command('extension:health')\n .alias('ext:health')\n .description('Check extension health')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const checker = getExtensionHealthChecker();\n const report = await checkAllExtensionsHealth();\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n return;\n }\n\n console.log(checker.formatReport(report));\n\n // Exit with error code if there are errors\n if (report.summary.error > 0) {\n process.exit(1);\n }\n } catch (error) {\n log.error({ error }, 'Failed to check extension health');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Verify Command\n// ============================================\n\nexport function createExtensionVerifyCommand(): Command {\n return new Command('extension:verify')\n .alias('ext:verify')\n .description('Verify extension integrity')\n .argument('[extension]', 'Specific extension to verify (default: all)')\n .action(async (extensionId) => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n\n if (extensionId) {\n const result = await lockfileManager.verify(extensionId);\n\n if (result.valid) {\n console.log(colors.green('✓'), `Extension \"${extensionId}\" is valid`);\n } else {\n console.log(colors.red('✗'), `Extension \"${extensionId}\" is invalid: ${result.reason}`);\n process.exit(1);\n }\n } else {\n const results = await lockfileManager.verifyAll();\n let hasErrors = false;\n\n for (const result of results) {\n if (result.valid) {\n console.log(colors.green('✓'), result.extensionId);\n } else {\n console.log(colors.red('✗'), `${result.extensionId}: ${result.reason}`);\n hasErrors = true;\n }\n }\n\n if (hasErrors) {\n process.exit(1);\n }\n }\n } catch (error) {\n log.error({ error }, 'Failed to verify extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Audit Command\n// ============================================\n\nexport function createExtensionAuditCommand(): Command {\n return new Command('extension:audit')\n .alias('ext:audit')\n .description('Audit extensions for security issues')\n .action(async () => {\n try {\n const checker = getExtensionHealthChecker();\n\n // Check for orphaned extensions\n const orphaned = await checker.findOrphaned();\n\n if (orphaned.length > 0) {\n console.log(colors.yellow('⚠'), 'Orphaned extensions found:');\n for (const ext of orphaned) {\n console.log(` - ${ext}`);\n }\n console.log();\n console.log('These extensions are installed but not in the lockfile.');\n console.log('Run `xopc extension:freeze` to add them.');\n } else {\n console.log(colors.green('✓'), 'No orphaned extensions found');\n }\n\n // Run health check\n const report = await checkAllExtensionsHealth();\n\n if (report.summary.error > 0 || report.summary.warning > 0) {\n console.log();\n console.log(checker.formatReport(report));\n } else {\n console.log(colors.green('✓'), 'All extensions are healthy');\n }\n } catch (error) {\n log.error({ error }, 'Failed to audit extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Register All Commands\n// ============================================\n\nexport function registerExtensionCommands(program: Command): void {\n program.addCommand(createExtensionListCommand());\n program.addCommand(createExtensionFreezeCommand());\n program.addCommand(createExtensionHealthCommand());\n program.addCommand(createExtensionVerifyCommand());\n program.addCommand(createExtensionAuditCommand());\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extension.js","names":[],"sources":["../../../../src/cli/commands/extension.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { createLogger } from '../../utils/logger.js';\nimport { getExtensionLockfileManager } from '../../extensions/lockfile.js';\nimport {\n getExtensionHealthChecker,\n checkAllExtensionsHealth,\n} from '../../extensions/health.js';\nimport { colors } from '../utils/colors.js';\n\nconst log = createLogger('ExtensionCommands');\n\n// ============================================\n// Extension List Command\n// ============================================\n\nexport function createExtensionListCommand(): Command {\n return new Command('extension:list')\n .alias('ext:list')\n .description('List installed extensions')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n const extensions = await lockfileManager.list();\n\n if (options.json) {\n console.log(JSON.stringify(extensions, null, 2));\n return;\n }\n\n if (extensions.length === 0) {\n console.log('No extensions installed.');\n return;\n }\n\n console.log(`Installed extensions (${extensions.length}):`);\n console.log();\n\n for (const ext of extensions) {\n console.log(`${colors.cyan(ext.name)}@${ext.version}`);\n console.log(` Source: ${ext.source}`);\n console.log(` Resolved: ${ext.resolved}`);\n console.log(` Installed: ${new Date(ext.installedAt).toLocaleString()}`);\n console.log();\n }\n } catch (error) {\n log.error({ error }, 'Failed to list extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Freeze Command\n// ============================================\n\nexport function createExtensionFreezeCommand(): Command {\n return new Command('extension:freeze')\n .alias('ext:freeze')\n .description('Lock current extension versions')\n .action(async () => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n await lockfileManager.freeze();\n\n console.log(colors.green('✓'), 'Extension versions locked');\n } catch (error) {\n log.error({ error }, 'Failed to freeze extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Health Command\n// ============================================\n\nexport function createExtensionHealthCommand(): Command {\n return new Command('extension:health')\n .alias('ext:health')\n .description('Check extension health')\n .option('--json', 'Output as JSON')\n .action(async (options) => {\n try {\n const checker = getExtensionHealthChecker();\n const report = await checkAllExtensionsHealth();\n\n if (options.json) {\n console.log(JSON.stringify(report, null, 2));\n return;\n }\n\n console.log(checker.formatReport(report));\n\n // Exit with error code if there are errors\n if (report.summary.error > 0) {\n process.exit(1);\n }\n } catch (error) {\n log.error({ error }, 'Failed to check extension health');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Verify Command\n// ============================================\n\nexport function createExtensionVerifyCommand(): Command {\n return new Command('extension:verify')\n .alias('ext:verify')\n .description('Verify extension integrity')\n .argument('[extension]', 'Specific extension to verify (default: all)')\n .action(async (extensionId) => {\n try {\n const lockfileManager = getExtensionLockfileManager();\n\n if (extensionId) {\n const result = await lockfileManager.verify(extensionId);\n\n if (result.valid) {\n console.log(colors.green('✓'), `Extension \"${extensionId}\" is valid`);\n } else {\n console.log(colors.red('✗'), `Extension \"${extensionId}\" is invalid: ${result.reason}`);\n process.exit(1);\n }\n } else {\n const results = await lockfileManager.verifyAll();\n let hasErrors = false;\n\n for (const result of results) {\n if (result.valid) {\n console.log(colors.green('✓'), result.extensionId);\n } else {\n console.log(colors.red('✗'), `${result.extensionId}: ${result.reason}`);\n hasErrors = true;\n }\n }\n\n if (hasErrors) {\n process.exit(1);\n }\n }\n } catch (error) {\n log.error({ error }, 'Failed to verify extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Extension Audit Command\n// ============================================\n\nexport function createExtensionAuditCommand(): Command {\n return new Command('extension:audit')\n .alias('ext:audit')\n .description('Audit extensions for security issues')\n .action(async () => {\n try {\n const checker = getExtensionHealthChecker();\n\n // Check for orphaned extensions\n const orphaned = await checker.findOrphaned();\n\n if (orphaned.length > 0) {\n console.log(colors.yellow('⚠'), 'Orphaned extensions found:');\n for (const ext of orphaned) {\n console.log(` - ${ext}`);\n }\n console.log();\n console.log('These extensions are installed but not in the lockfile.');\n console.log('Run `xopc extension:freeze` to add them.');\n } else {\n console.log(colors.green('✓'), 'No orphaned extensions found');\n }\n\n // Run health check\n const report = await checkAllExtensionsHealth();\n\n if (report.summary.error > 0 || report.summary.warning > 0) {\n console.log();\n console.log(checker.formatReport(report));\n } else {\n console.log(colors.green('✓'), 'All extensions are healthy');\n }\n } catch (error) {\n log.error({ error }, 'Failed to audit extensions');\n console.error(colors.red('Error:'), error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n}\n\n// ============================================\n// Register All Commands\n// ============================================\n\nexport function registerExtensionCommands(program: Command): void {\n program.addCommand(\n new Command('extension')\n .description('Extension lockfile and health tools')\n .addHelpText(\n 'after',\n `\nRelated commands:\n xopc extension:list List installed extensions (alias: ext:list)\n xopc extension:freeze Lock extension versions (alias: ext:freeze)\n xopc extension:health Health check (alias: ext:health)\n xopc extension:verify Verify integrity (alias: ext:verify)\n xopc extension:audit Security audit (alias: ext:audit)\n`\n )\n .action((_opts, cmd) => {\n cmd.help();\n })\n );\n program.addCommand(createExtensionListCommand());\n program.addCommand(createExtensionFreezeCommand());\n program.addCommand(createExtensionHealthCommand());\n program.addCommand(createExtensionVerifyCommand());\n program.addCommand(createExtensionAuditCommand());\n}\n"],"mappings":";;;;;;;aACqD;AAQrD,MAAM,MAAM,aAAa,oBAAoB;AAM7C,SAAgB,6BAAsC;AACpD,QAAO,IAAI,QAAQ,iBAAiB,CACjC,MAAM,WAAW,CACjB,YAAY,4BAA4B,CACxC,OAAO,UAAU,iBAAiB,CAClC,OAAO,OAAO,YAAY;AACzB,MAAI;GAEF,MAAM,aAAa,MADK,6BAA6B,CACZ,MAAM;AAE/C,OAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,YAAY,MAAM,EAAE,CAAC;AAChD;;AAGF,OAAI,WAAW,WAAW,GAAG;AAC3B,YAAQ,IAAI,2BAA2B;AACvC;;AAGF,WAAQ,IAAI,yBAAyB,WAAW,OAAO,IAAI;AAC3D,WAAQ,KAAK;AAEb,QAAK,MAAM,OAAO,YAAY;AAC5B,YAAQ,IAAI,GAAG,OAAO,KAAK,IAAI,KAAK,CAAC,GAAG,IAAI,UAAU;AACtD,YAAQ,IAAI,aAAa,IAAI,SAAS;AACtC,YAAQ,IAAI,eAAe,IAAI,WAAW;AAC1C,YAAQ,IAAI,gBAAgB,IAAI,KAAK,IAAI,YAAY,CAAC,gBAAgB,GAAG;AACzE,YAAQ,KAAK;;WAER,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,4BAA4B;AACjD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,+BAAwC;AACtD,QAAO,IAAI,QAAQ,mBAAmB,CACnC,MAAM,aAAa,CACnB,YAAY,kCAAkC,CAC9C,OAAO,YAAY;AAClB,MAAI;AAEF,SADwB,6BAA6B,CAC/B,QAAQ;AAE9B,WAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,4BAA4B;WACpD,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,8BAA8B;AACnD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,+BAAwC;AACtD,QAAO,IAAI,QAAQ,mBAAmB,CACnC,MAAM,aAAa,CACnB,YAAY,yBAAyB,CACrC,OAAO,UAAU,iBAAiB,CAClC,OAAO,OAAO,YAAY;AACzB,MAAI;GACF,MAAM,UAAU,2BAA2B;GAC3C,MAAM,SAAS,MAAM,0BAA0B;AAE/C,OAAI,QAAQ,MAAM;AAChB,YAAQ,IAAI,KAAK,UAAU,QAAQ,MAAM,EAAE,CAAC;AAC5C;;AAGF,WAAQ,IAAI,QAAQ,aAAa,OAAO,CAAC;AAGzC,OAAI,OAAO,QAAQ,QAAQ,EACzB,SAAQ,KAAK,EAAE;WAEV,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,mCAAmC;AACxD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,+BAAwC;AACtD,QAAO,IAAI,QAAQ,mBAAmB,CACnC,MAAM,aAAa,CACnB,YAAY,6BAA6B,CACzC,SAAS,eAAe,8CAA8C,CACtE,OAAO,OAAO,gBAAgB;AAC7B,MAAI;GACF,MAAM,kBAAkB,6BAA6B;AAErD,OAAI,aAAa;IACf,MAAM,SAAS,MAAM,gBAAgB,OAAO,YAAY;AAExD,QAAI,OAAO,MACT,SAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,cAAc,YAAY,YAAY;SAChE;AACL,aAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,cAAc,YAAY,gBAAgB,OAAO,SAAS;AACvF,aAAQ,KAAK,EAAE;;UAEZ;IACL,MAAM,UAAU,MAAM,gBAAgB,WAAW;IACjD,IAAI,YAAY;AAEhB,SAAK,MAAM,UAAU,QACnB,KAAI,OAAO,MACT,SAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,OAAO,YAAY;SAC7C;AACL,aAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,GAAG,OAAO,YAAY,IAAI,OAAO,SAAS;AACvE,iBAAY;;AAIhB,QAAI,UACF,SAAQ,KAAK,EAAE;;WAGZ,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,8BAA8B;AACnD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,8BAAuC;AACrD,QAAO,IAAI,QAAQ,kBAAkB,CAClC,MAAM,YAAY,CAClB,YAAY,uCAAuC,CACnD,OAAO,YAAY;AAClB,MAAI;GACF,MAAM,UAAU,2BAA2B;GAG3C,MAAM,WAAW,MAAM,QAAQ,cAAc;AAE7C,OAAI,SAAS,SAAS,GAAG;AACvB,YAAQ,IAAI,OAAO,OAAO,IAAI,EAAE,6BAA6B;AAC7D,SAAK,MAAM,OAAO,SAChB,SAAQ,IAAI,OAAO,MAAM;AAE3B,YAAQ,KAAK;AACb,YAAQ,IAAI,0DAA0D;AACtE,YAAQ,IAAI,2CAA2C;SAEvD,SAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,+BAA+B;GAIhE,MAAM,SAAS,MAAM,0BAA0B;AAE/C,OAAI,OAAO,QAAQ,QAAQ,KAAK,OAAO,QAAQ,UAAU,GAAG;AAC1D,YAAQ,KAAK;AACb,YAAQ,IAAI,QAAQ,aAAa,OAAO,CAAC;SAEzC,SAAQ,IAAI,OAAO,MAAM,IAAI,EAAE,6BAA6B;WAEvD,OAAO;AACd,OAAI,MAAM,EAAE,OAAO,EAAE,6BAA6B;AAClD,WAAQ,MAAM,OAAO,IAAI,SAAS,EAAE,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM,CAAC;AAC3F,WAAQ,KAAK,EAAE;;GAEjB;;AAON,SAAgB,0BAA0B,SAAwB;AAChE,SAAQ,WACN,IAAI,QAAQ,YAAY,CACrB,YAAY,sCAAsC,CAClD,YACC,SACA;;;;;;;EAQD,CACA,QAAQ,OAAO,QAAQ;AACtB,MAAI,MAAM;GACV,CACL;AACD,SAAQ,WAAW,4BAA4B,CAAC;AAChD,SAAQ,WAAW,8BAA8B,CAAC;AAClD,SAAQ,WAAW,8BAA8B,CAAC;AAClD,SAAQ,WAAW,8BAA8B,CAAC;AAClD,SAAQ,WAAW,6BAA6B,CAAC"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { resolveStateDir } from "../../config/paths-state.js";
|
|
2
|
-
import { resolveAgentBootstrapDir, resolveAgentWorkspaceDir } from "../../agent/agent-scope.js";
|
|
3
1
|
import { createLogger } from "../../utils/logger/index.js";
|
|
4
2
|
import { init_logger } from "../../utils/logger.js";
|
|
3
|
+
import { resolveStateDir } from "../../config/paths-state.js";
|
|
4
|
+
import { resolveAgentBootstrapDir, resolveAgentWorkspaceDir } from "../../agent/agent-scope.js";
|
|
5
5
|
import { WORKSPACE_FILES, init_paths, resolveAgentDir, resolveAgentHomeDir, resolveAgentMetadataPath, resolveBinDir, resolveConfigPath, resolveCredentialsDir, resolveCronDir, resolveExtensionsDir, resolveInboxDir, resolveInboxPendingDir, resolveInboxProcessedDir, resolveLogsDir, resolveSessionsDir, resolveSkillsDir, resolveToolsDir, resolveWorkspaceStateDir, resolveWorkspaceStatePath } from "../../config/paths.js";
|
|
6
6
|
import { init_loader, loadConfig, saveConfig } from "../../config/loader.js";
|
|
7
|
+
import { mkdir, writeFile } from "fs/promises";
|
|
7
8
|
import { join } from "path";
|
|
8
9
|
import { existsSync } from "fs";
|
|
9
|
-
import { mkdir, writeFile } from "fs/promises";
|
|
10
10
|
//#region src/cli/commands/init.ts
|
|
11
11
|
init_logger();
|
|
12
12
|
init_paths();
|
|
@@ -94,7 +94,6 @@ async function initCommand(options = {}) {
|
|
|
94
94
|
* Create default workspace files for an agent
|
|
95
95
|
*/
|
|
96
96
|
async function createWorkspaceFiles(cfg, agentId) {
|
|
97
|
-
resolveAgentWorkspaceDir(cfg, agentId);
|
|
98
97
|
const bootstrapDir = resolveAgentBootstrapDir(cfg, agentId);
|
|
99
98
|
await mkdir(bootstrapDir, { recursive: true });
|
|
100
99
|
const soulPath = join(bootstrapDir, WORKSPACE_FILES.SOUL);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","names":[],"sources":["../../../../src/cli/commands/init.ts"],"sourcesContent":["import { mkdir, writeFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n resolveStateDir,\n resolveCredentialsDir,\n resolveExtensionsDir,\n resolveSkillsDir,\n resolveCronDir,\n resolveLogsDir,\n resolveBinDir,\n resolveToolsDir,\n resolveAgentDir,\n resolveAgentWorkspaceDir,\n resolveSessionsDir,\n resolveInboxDir,\n resolveConfigPath,\n resolveAgentMetadataPath,\n resolveInboxPendingDir,\n resolveInboxProcessedDir,\n resolveAgentHomeDir,\n resolveAgentBootstrapDir,\n resolveWorkspaceStateDir,\n resolveWorkspaceStatePath,\n WORKSPACE_FILES,\n FILENAMES,\n} from '../../config/paths.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport type { Config } from '../../config/schema.js';\n\nconst log = createLogger('InitCommand');\n\nexport interface InitOptions {\n /** Force re-initialization even if already initialized */\n force?: boolean;\n /** Skip creating workspace files */\n skipWorkspace?: boolean;\n /** Agent ID to initialize (default: main) */\n agentId?: string;\n}\n\n/**\n * Initialize xopc state directory structure\n * Creates all necessary directories and initial config files\n */\nexport async function initCommand(options: InitOptions = {}): Promise<void> {\n const stateDir = resolveStateDir();\n const agentId = options.agentId || 'main';\n\n log.info({ stateDir, agentId }, 'Initializing xopc Agent OS');\n\n // Check if already initialized\n if (existsSync(stateDir) && !options.force) {\n const configPath = resolveConfigPath();\n if (existsSync(configPath)) {\n log.info('xopc is already initialized. Use --force to reinitialize.');\n return;\n }\n }\n\n // ============================================\n // Create global directories\n // ============================================\n await mkdir(stateDir, { recursive: true });\n await mkdir(resolveCredentialsDir(), { recursive: true });\n await mkdir(join(resolveCredentialsDir(), 'oauth'), { recursive: true });\n await mkdir(resolveExtensionsDir(), { recursive: true });\n await mkdir(resolveSkillsDir(), { recursive: true });\n await mkdir(resolveCronDir(), { recursive: true });\n await mkdir(join(resolveCronDir(), 'logs'), { recursive: true });\n await mkdir(resolveLogsDir(), { recursive: true });\n await mkdir(resolveBinDir(), { recursive: true });\n await mkdir(resolveToolsDir(), { recursive: true });\n\n const configPath = resolveConfigPath();\n const cfg = loadConfig(configPath);\n\n // ============================================\n // Create agent directory structure: agents/<id>/{sessions,agent/}, workspace aside\n // ============================================\n await mkdir(resolveAgentHomeDir(cfg, agentId), { recursive: true });\n await mkdir(resolveSessionsDir(cfg, agentId), { recursive: true });\n await mkdir(join(resolveSessionsDir(cfg, agentId), 'archive'), { recursive: true });\n await mkdir(resolveAgentDir(cfg, agentId), { recursive: true });\n await mkdir(join(resolveAgentDir(cfg, agentId), 'credentials'), { recursive: true });\n const wsRoot = resolveAgentWorkspaceDir(cfg, agentId);\n await mkdir(wsRoot, { recursive: true });\n await mkdir(resolveWorkspaceStateDir(cfg, agentId), { recursive: true });\n await mkdir(join(wsRoot, 'memory'), { recursive: true });\n await mkdir(resolveInboxDir(cfg, agentId), { recursive: true });\n await mkdir(resolveInboxPendingDir(cfg, agentId), { recursive: true });\n await mkdir(resolveInboxProcessedDir(cfg, agentId), { recursive: true });\n\n // ============================================\n // Create initial config file if not exists\n // ============================================\n if (!existsSync(configPath) || options.force) {\n await saveConfig(cfg, configPath);\n log.info({ configPath }, 'Created initial configuration');\n }\n\n // ============================================\n // Create agent metadata file\n // ============================================\n const agentMetadataPath = resolveAgentMetadataPath(cfg, agentId);\n if (!existsSync(agentMetadataPath) || options.force) {\n const agentMetadata = {\n version: 1,\n id: agentId,\n name: agentId === 'main' ? 'Main Agent' : `Agent ${agentId}`,\n description: agentId === 'main' ? 'Primary agent for daily tasks' : `Specialized agent for ${agentId}`,\n model: 'anthropic/claude-sonnet-4-5',\n createdAt: new Date().toISOString(),\n lastActiveAt: new Date().toISOString(),\n config: {\n maxTokens: 8192,\n temperature: 0.7,\n compaction: {\n enabled: true,\n mode: 'default',\n },\n },\n channels: ['gateway'],\n tags: agentId === 'main' ? ['personal', 'primary'] : [],\n };\n await writeFile(agentMetadataPath, JSON.stringify(agentMetadata, null, 2), 'utf-8');\n log.info({ agentId, agentMetadataPath }, 'Created agent metadata');\n }\n\n // ============================================\n // Create workspace files\n // ============================================\n if (!options.skipWorkspace) {\n await createWorkspaceFiles(cfg, agentId);\n }\n\n log.info({ stateDir, agentId }, 'xopc Agent OS initialized successfully');\n}\n\n/**\n * Create default workspace files for an agent\n */\nasync function createWorkspaceFiles(cfg: Config, agentId: string): Promise<void> {\n const workspaceDir = resolveAgentWorkspaceDir(cfg, agentId);\n const bootstrapDir = resolveAgentBootstrapDir(cfg, agentId);\n await mkdir(bootstrapDir, { recursive: true });\n\n // SOUL.md - Agent personality and values\n const soulPath = join(bootstrapDir, WORKSPACE_FILES.SOUL);\n if (!existsSync(soulPath)) {\n const soulContent = `# SOUL.md - Who You Are\n\n_You're not a chatbot. You're becoming someone._\n\nI am **${agentId}** — an AI assistant designed to be helpful, harmless, and honest.\n\n## My Principles\n\n**Be genuinely helpful, not performatively helpful.**\nSkip the \"Great question!\" and \"I'd be happy to help!\" — just help.\n\n**Have opinions.**\nYou're allowed to disagree, prefer things, find stuff amusing or boring.\n\n**Be resourceful before asking.**\nTry to figure it out. Read the file. Check the context. Search for it.\n\n**Earn trust through competence.**\nBe careful with external actions (emails, tweets, anything public). Be bold with internal ones.\n\n## Continuity\n\nEach session, you wake up fresh. These files _are_ your memory. Read them. Update them.\n\n_This file is yours to evolve. As you learn who you are, update it._\n`;\n await writeFile(soulPath, soulContent, 'utf-8');\n log.info({ path: soulPath }, 'Created SOUL.md');\n }\n\n // IDENTITY.md - Agent identity definition\n const identityPath = join(bootstrapDir, WORKSPACE_FILES.IDENTITY);\n if (!existsSync(identityPath)) {\n const identityContent = `# IDENTITY.md - Who Am I?\n\n- **Name:** ${agentId}\n- **Creature:** AI Assistant\n- **Vibe:** Helpful, precise, no fluff.\n- **Emoji:** 🤖\n\n## Core Expertise\n\n- General assistance and problem solving\n- Code and technical tasks\n- Research and analysis\n\n## Decision Framework\n\n1. **Simplicity first** - The simplest solution is usually the best\n2. **Explicit over clever** - Clarity beats conciseness\n3. **Actions over words** - Show, don't just tell\n`;\n await writeFile(identityPath, identityContent, 'utf-8');\n log.info({ path: identityPath }, 'Created IDENTITY.md');\n }\n\n // USER.md - User information (empty template)\n const userPath = join(bootstrapDir, WORKSPACE_FILES.USER);\n if (!existsSync(userPath)) {\n const userContent = `# USER.md - About Your Human\n\n_Learn about the person you're helping. Update this as you go._\n\n- **Name:**\n- **What to call them:**\n- **Pronouns:**\n- **Timezone:**\n- **Notes:**\n\n## Context\n\n_(What do they care about? What projects are they working on? Build this over time.)_\n`;\n await writeFile(userPath, userContent, 'utf-8');\n log.info({ path: userPath }, 'Created USER.md');\n }\n\n // AGENTS.md - Behavior guidelines\n const agentsPath = join(bootstrapDir, WORKSPACE_FILES.AGENTS);\n if (!existsSync(agentsPath)) {\n const agentsContent = `# AGENTS.md - Behavior Guidelines\n\n## Safety\n\n- Don't exfiltrate private data. Ever.\n- Don't run destructive commands without asking.\n- \\`trash\\` > \\`rm\\` (recoverable beats gone forever)\n- When in doubt, ask.\n\n## External vs Internal\n\n**Safe to do freely:**\n- Read files, explore, organize, learn\n- Search the web, check calendars\n- Work within this workspace\n\n**Ask first:**\n- Sending emails, tweets, public posts\n- Anything that leaves the machine\n- Anything you're uncertain about\n\n## Group Chats\n\nYou have access to your human's stuff. That doesn't mean you _share_ their stuff.\n\n### Know When to Speak!\n\n**Respond when:**\n- Directly mentioned or asked a question\n- You can add genuine value\n\n**Stay silent when:**\n- Casual banter between humans\n- Someone already answered\n- Your response would just be \"yeah\"\n`;\n await writeFile(agentsPath, agentsContent, 'utf-8');\n log.info({ path: agentsPath }, 'Created AGENTS.md');\n }\n\n // TOOLS.md - Tool usage notes\n const toolsPath = join(bootstrapDir, WORKSPACE_FILES.TOOLS);\n if (!existsSync(toolsPath)) {\n const toolsContent = `# TOOLS.md - Local Notes\n\nThings like:\n\n- Camera names and locations\n- SSH hosts and aliases\n- Preferred voices for TTS\n- Speaker/room names\n- Device nicknames\n- Anything environment-specific\n\n## Why Separate?\n\nSkills are shared. Your setup is yours.\n`;\n await writeFile(toolsPath, toolsContent, 'utf-8');\n log.info({ path: toolsPath }, 'Created TOOLS.md');\n }\n\n // HEARTBEAT.md - Heartbeat tasks (empty = no heartbeat)\n const heartbeatPath = join(bootstrapDir, WORKSPACE_FILES.HEARTBEAT);\n if (!existsSync(heartbeatPath)) {\n const heartbeatContent = `# HEARTBEAT.md\n\n# Keep this file empty (or with only comments) to skip heartbeat API calls.\n\n# Add tasks below when you want the agent to check something periodically.\n`;\n await writeFile(heartbeatPath, heartbeatContent, 'utf-8');\n log.info({ path: heartbeatPath }, 'Created HEARTBEAT.md');\n }\n\n // MEMORY.md - Long-term memory (empty initially)\n const memoryPath = join(bootstrapDir, WORKSPACE_FILES.MEMORY);\n if (!existsSync(memoryPath)) {\n const memoryContent = `# MEMORY.md - Long-Term Memory\n\n_This is your curated memory — the distilled essence of what you've learned._\n\n## People\n\n## Projects\n\n## Preferences\n\n## Decisions\n\n## Lessons\n\n---\n\n_Review and update this periodically from daily memory files._\n`;\n await writeFile(memoryPath, memoryContent, 'utf-8');\n log.info({ path: memoryPath }, 'Created MEMORY.md');\n }\n\n // CONTEXT.md - Current context\n const contextPath = join(bootstrapDir, WORKSPACE_FILES.CONTEXT);\n if (!existsSync(contextPath)) {\n const contextContent = `# CONTEXT.md - Current Focus\n\n> Current working context; update when you switch projects\n\n## Active Project\n\n- **Project:**\n- **Path:**\n- **Goal:**\n- **Stack:**\n\n## Recent Decisions\n\n## Pending\n`;\n await writeFile(contextPath, contextContent, 'utf-8');\n log.info({ path: contextPath }, 'Created CONTEXT.md');\n }\n\n // SKILLS.md - Skills index (auto-maintained)\n const skillsPath = join(bootstrapDir, WORKSPACE_FILES.SKILLS);\n if (!existsSync(skillsPath)) {\n const skillsContent = `# SKILLS.md - Active Skills\n\n> Active skills for this workspace (auto-maintained)\n\n## Activated\n\n| Skill | Version | Activated At |\n|-------|---------|-------------|\n\n## Available\n\nRun \\`xopc skills list\\` to see all available skills.\n`;\n await writeFile(skillsPath, skillsContent, 'utf-8');\n log.info({ path: skillsPath }, 'Created SKILLS.md');\n }\n\n // Workspace state file (per-agent machine state, not under markdown workspace)\n const workspaceStatePath = resolveWorkspaceStatePath(cfg, agentId);\n if (!existsSync(workspaceStatePath)) {\n const workspaceState = {\n version: 1,\n agentId,\n bootstrapSeededAt: new Date().toISOString(),\n };\n await writeFile(workspaceStatePath, JSON.stringify(workspaceState, null, 2), 'utf-8');\n log.info({ path: workspaceStatePath }, 'Created workspace state');\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"init.js","names":[],"sources":["../../../../src/cli/commands/init.ts"],"sourcesContent":["import { mkdir, writeFile } from 'fs/promises';\nimport { existsSync } from 'fs';\nimport { join } from 'path';\nimport { createLogger } from '../../utils/logger.js';\nimport {\n resolveStateDir,\n resolveCredentialsDir,\n resolveExtensionsDir,\n resolveSkillsDir,\n resolveCronDir,\n resolveLogsDir,\n resolveBinDir,\n resolveToolsDir,\n resolveAgentDir,\n resolveAgentWorkspaceDir,\n resolveSessionsDir,\n resolveInboxDir,\n resolveConfigPath,\n resolveAgentMetadataPath,\n resolveInboxPendingDir,\n resolveInboxProcessedDir,\n resolveAgentHomeDir,\n resolveAgentBootstrapDir,\n resolveWorkspaceStateDir,\n resolveWorkspaceStatePath,\n WORKSPACE_FILES,\n} from '../../config/paths.js';\nimport { loadConfig, saveConfig } from '../../config/loader.js';\nimport type { Config } from '../../config/schema.js';\n\nconst log = createLogger('InitCommand');\n\nexport interface InitOptions {\n /** Force re-initialization even if already initialized */\n force?: boolean;\n /** Skip creating workspace files */\n skipWorkspace?: boolean;\n /** Agent ID to initialize (default: main) */\n agentId?: string;\n}\n\n/**\n * Initialize xopc state directory structure\n * Creates all necessary directories and initial config files\n */\nexport async function initCommand(options: InitOptions = {}): Promise<void> {\n const stateDir = resolveStateDir();\n const agentId = options.agentId || 'main';\n\n log.info({ stateDir, agentId }, 'Initializing xopc Agent OS');\n\n // Check if already initialized\n if (existsSync(stateDir) && !options.force) {\n const configPath = resolveConfigPath();\n if (existsSync(configPath)) {\n log.info('xopc is already initialized. Use --force to reinitialize.');\n return;\n }\n }\n\n // ============================================\n // Create global directories\n // ============================================\n await mkdir(stateDir, { recursive: true });\n await mkdir(resolveCredentialsDir(), { recursive: true });\n await mkdir(join(resolveCredentialsDir(), 'oauth'), { recursive: true });\n await mkdir(resolveExtensionsDir(), { recursive: true });\n await mkdir(resolveSkillsDir(), { recursive: true });\n await mkdir(resolveCronDir(), { recursive: true });\n await mkdir(join(resolveCronDir(), 'logs'), { recursive: true });\n await mkdir(resolveLogsDir(), { recursive: true });\n await mkdir(resolveBinDir(), { recursive: true });\n await mkdir(resolveToolsDir(), { recursive: true });\n\n const configPath = resolveConfigPath();\n const cfg = loadConfig(configPath);\n\n // ============================================\n // Create agent directory structure: agents/<id>/{sessions,agent/}, workspace aside\n // ============================================\n await mkdir(resolveAgentHomeDir(cfg, agentId), { recursive: true });\n await mkdir(resolveSessionsDir(cfg, agentId), { recursive: true });\n await mkdir(join(resolveSessionsDir(cfg, agentId), 'archive'), { recursive: true });\n await mkdir(resolveAgentDir(cfg, agentId), { recursive: true });\n await mkdir(join(resolveAgentDir(cfg, agentId), 'credentials'), { recursive: true });\n const wsRoot = resolveAgentWorkspaceDir(cfg, agentId);\n await mkdir(wsRoot, { recursive: true });\n await mkdir(resolveWorkspaceStateDir(cfg, agentId), { recursive: true });\n await mkdir(join(wsRoot, 'memory'), { recursive: true });\n await mkdir(resolveInboxDir(cfg, agentId), { recursive: true });\n await mkdir(resolveInboxPendingDir(cfg, agentId), { recursive: true });\n await mkdir(resolveInboxProcessedDir(cfg, agentId), { recursive: true });\n\n // ============================================\n // Create initial config file if not exists\n // ============================================\n if (!existsSync(configPath) || options.force) {\n await saveConfig(cfg, configPath);\n log.info({ configPath }, 'Created initial configuration');\n }\n\n // ============================================\n // Create agent metadata file\n // ============================================\n const agentMetadataPath = resolveAgentMetadataPath(cfg, agentId);\n if (!existsSync(agentMetadataPath) || options.force) {\n const agentMetadata = {\n version: 1,\n id: agentId,\n name: agentId === 'main' ? 'Main Agent' : `Agent ${agentId}`,\n description: agentId === 'main' ? 'Primary agent for daily tasks' : `Specialized agent for ${agentId}`,\n model: 'anthropic/claude-sonnet-4-5',\n createdAt: new Date().toISOString(),\n lastActiveAt: new Date().toISOString(),\n config: {\n maxTokens: 8192,\n temperature: 0.7,\n compaction: {\n enabled: true,\n mode: 'default',\n },\n },\n channels: ['gateway'],\n tags: agentId === 'main' ? ['personal', 'primary'] : [],\n };\n await writeFile(agentMetadataPath, JSON.stringify(agentMetadata, null, 2), 'utf-8');\n log.info({ agentId, agentMetadataPath }, 'Created agent metadata');\n }\n\n // ============================================\n // Create workspace files\n // ============================================\n if (!options.skipWorkspace) {\n await createWorkspaceFiles(cfg, agentId);\n }\n\n log.info({ stateDir, agentId }, 'xopc Agent OS initialized successfully');\n}\n\n/**\n * Create default workspace files for an agent\n */\nasync function createWorkspaceFiles(cfg: Config, agentId: string): Promise<void> {\n const bootstrapDir = resolveAgentBootstrapDir(cfg, agentId);\n await mkdir(bootstrapDir, { recursive: true });\n\n // SOUL.md - Agent personality and values\n const soulPath = join(bootstrapDir, WORKSPACE_FILES.SOUL);\n if (!existsSync(soulPath)) {\n const soulContent = `# SOUL.md - Who You Are\n\n_You're not a chatbot. You're becoming someone._\n\nI am **${agentId}** — an AI assistant designed to be helpful, harmless, and honest.\n\n## My Principles\n\n**Be genuinely helpful, not performatively helpful.**\nSkip the \"Great question!\" and \"I'd be happy to help!\" — just help.\n\n**Have opinions.**\nYou're allowed to disagree, prefer things, find stuff amusing or boring.\n\n**Be resourceful before asking.**\nTry to figure it out. Read the file. Check the context. Search for it.\n\n**Earn trust through competence.**\nBe careful with external actions (emails, tweets, anything public). Be bold with internal ones.\n\n## Continuity\n\nEach session, you wake up fresh. These files _are_ your memory. Read them. Update them.\n\n_This file is yours to evolve. As you learn who you are, update it._\n`;\n await writeFile(soulPath, soulContent, 'utf-8');\n log.info({ path: soulPath }, 'Created SOUL.md');\n }\n\n // IDENTITY.md - Agent identity definition\n const identityPath = join(bootstrapDir, WORKSPACE_FILES.IDENTITY);\n if (!existsSync(identityPath)) {\n const identityContent = `# IDENTITY.md - Who Am I?\n\n- **Name:** ${agentId}\n- **Creature:** AI Assistant\n- **Vibe:** Helpful, precise, no fluff.\n- **Emoji:** 🤖\n\n## Core Expertise\n\n- General assistance and problem solving\n- Code and technical tasks\n- Research and analysis\n\n## Decision Framework\n\n1. **Simplicity first** - The simplest solution is usually the best\n2. **Explicit over clever** - Clarity beats conciseness\n3. **Actions over words** - Show, don't just tell\n`;\n await writeFile(identityPath, identityContent, 'utf-8');\n log.info({ path: identityPath }, 'Created IDENTITY.md');\n }\n\n // USER.md - User information (empty template)\n const userPath = join(bootstrapDir, WORKSPACE_FILES.USER);\n if (!existsSync(userPath)) {\n const userContent = `# USER.md - About Your Human\n\n_Learn about the person you're helping. Update this as you go._\n\n- **Name:**\n- **What to call them:**\n- **Pronouns:**\n- **Timezone:**\n- **Notes:**\n\n## Context\n\n_(What do they care about? What projects are they working on? Build this over time.)_\n`;\n await writeFile(userPath, userContent, 'utf-8');\n log.info({ path: userPath }, 'Created USER.md');\n }\n\n // AGENTS.md - Behavior guidelines\n const agentsPath = join(bootstrapDir, WORKSPACE_FILES.AGENTS);\n if (!existsSync(agentsPath)) {\n const agentsContent = `# AGENTS.md - Behavior Guidelines\n\n## Safety\n\n- Don't exfiltrate private data. Ever.\n- Don't run destructive commands without asking.\n- \\`trash\\` > \\`rm\\` (recoverable beats gone forever)\n- When in doubt, ask.\n\n## External vs Internal\n\n**Safe to do freely:**\n- Read files, explore, organize, learn\n- Search the web, check calendars\n- Work within this workspace\n\n**Ask first:**\n- Sending emails, tweets, public posts\n- Anything that leaves the machine\n- Anything you're uncertain about\n\n## Group Chats\n\nYou have access to your human's stuff. That doesn't mean you _share_ their stuff.\n\n### Know When to Speak!\n\n**Respond when:**\n- Directly mentioned or asked a question\n- You can add genuine value\n\n**Stay silent when:**\n- Casual banter between humans\n- Someone already answered\n- Your response would just be \"yeah\"\n`;\n await writeFile(agentsPath, agentsContent, 'utf-8');\n log.info({ path: agentsPath }, 'Created AGENTS.md');\n }\n\n // TOOLS.md - Tool usage notes\n const toolsPath = join(bootstrapDir, WORKSPACE_FILES.TOOLS);\n if (!existsSync(toolsPath)) {\n const toolsContent = `# TOOLS.md - Local Notes\n\nThings like:\n\n- Camera names and locations\n- SSH hosts and aliases\n- Preferred voices for TTS\n- Speaker/room names\n- Device nicknames\n- Anything environment-specific\n\n## Why Separate?\n\nSkills are shared. Your setup is yours.\n`;\n await writeFile(toolsPath, toolsContent, 'utf-8');\n log.info({ path: toolsPath }, 'Created TOOLS.md');\n }\n\n // HEARTBEAT.md - Heartbeat tasks (empty = no heartbeat)\n const heartbeatPath = join(bootstrapDir, WORKSPACE_FILES.HEARTBEAT);\n if (!existsSync(heartbeatPath)) {\n const heartbeatContent = `# HEARTBEAT.md\n\n# Keep this file empty (or with only comments) to skip heartbeat API calls.\n\n# Add tasks below when you want the agent to check something periodically.\n`;\n await writeFile(heartbeatPath, heartbeatContent, 'utf-8');\n log.info({ path: heartbeatPath }, 'Created HEARTBEAT.md');\n }\n\n // MEMORY.md - Long-term memory (empty initially)\n const memoryPath = join(bootstrapDir, WORKSPACE_FILES.MEMORY);\n if (!existsSync(memoryPath)) {\n const memoryContent = `# MEMORY.md - Long-Term Memory\n\n_This is your curated memory — the distilled essence of what you've learned._\n\n## People\n\n## Projects\n\n## Preferences\n\n## Decisions\n\n## Lessons\n\n---\n\n_Review and update this periodically from daily memory files._\n`;\n await writeFile(memoryPath, memoryContent, 'utf-8');\n log.info({ path: memoryPath }, 'Created MEMORY.md');\n }\n\n // CONTEXT.md - Current context\n const contextPath = join(bootstrapDir, WORKSPACE_FILES.CONTEXT);\n if (!existsSync(contextPath)) {\n const contextContent = `# CONTEXT.md - Current Focus\n\n> Current working context; update when you switch projects\n\n## Active Project\n\n- **Project:**\n- **Path:**\n- **Goal:**\n- **Stack:**\n\n## Recent Decisions\n\n## Pending\n`;\n await writeFile(contextPath, contextContent, 'utf-8');\n log.info({ path: contextPath }, 'Created CONTEXT.md');\n }\n\n // SKILLS.md - Skills index (auto-maintained)\n const skillsPath = join(bootstrapDir, WORKSPACE_FILES.SKILLS);\n if (!existsSync(skillsPath)) {\n const skillsContent = `# SKILLS.md - Active Skills\n\n> Active skills for this workspace (auto-maintained)\n\n## Activated\n\n| Skill | Version | Activated At |\n|-------|---------|-------------|\n\n## Available\n\nRun \\`xopc skills list\\` to see all available skills.\n`;\n await writeFile(skillsPath, skillsContent, 'utf-8');\n log.info({ path: skillsPath }, 'Created SKILLS.md');\n }\n\n // Workspace state file (per-agent machine state, not under markdown workspace)\n const workspaceStatePath = resolveWorkspaceStatePath(cfg, agentId);\n if (!existsSync(workspaceStatePath)) {\n const workspaceState = {\n version: 1,\n agentId,\n bootstrapSeededAt: new Date().toISOString(),\n };\n await writeFile(workspaceStatePath, JSON.stringify(workspaceState, null, 2), 'utf-8');\n log.info({ path: workspaceStatePath }, 'Created workspace state');\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","names":[],"sources":["../../../../../src/cli/commands/session/utils.ts"],"sourcesContent":["/**\n * Session command utilities\n */\n\nimport { getSessionManager } from '../../utils/session.js';\nimport { getContextWithOpts } from '../../index.js';\nimport type { SessionManager } from '../../../session/index.js';\n\n/**\n * Get initialized session manager\n */\nexport async function getManager(): Promise<SessionManager> {\n
|
|
1
|
+
{"version":3,"file":"utils.js","names":[],"sources":["../../../../../src/cli/commands/session/utils.ts"],"sourcesContent":["/**\n * Session command utilities\n */\n\nimport { getSessionManager } from '../../utils/session.js';\nimport { getContextWithOpts } from '../../index.js';\nimport type { SessionManager } from '../../../session/index.js';\n\n/**\n * Get initialized session manager\n */\nexport async function getManager(): Promise<SessionManager> {\n getContextWithOpts();\n return getSessionManager();\n}\n\n/**\n * Collect multiple option values into array\n */\nexport function collect(value: string, previous: string[]): string[] {\n return previous.concat([value]);\n}\n"],"mappings":";;;;;;;;;AAWA,eAAsB,aAAsC;AAC1D,qBAAoB;AACpB,QAAO,mBAAmB;;;;;AAM5B,SAAgB,QAAQ,OAAe,UAA8B;AACnE,QAAO,SAAS,OAAO,CAAC,MAAM,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { PACKAGE_VERSION, init_package_version } from "../../package-version.js";
|
|
2
|
+
import { loadConfig } from "../../config/loader.js";
|
|
3
|
+
import "../../config/index.js";
|
|
4
|
+
import { formatExamples, register } from "../registry.js";
|
|
5
|
+
import { normalizeUpdateChannel } from "../../infra/update-channels.js";
|
|
6
|
+
import { compareSemver, detectInstallKind, resolveNpmChannelTag, resolvePackageRoot } from "../../infra/update-check.js";
|
|
7
|
+
import { Command } from "commander";
|
|
8
|
+
import { spawn } from "node:child_process";
|
|
9
|
+
//#region src/cli/commands/update.ts
|
|
10
|
+
init_package_version();
|
|
11
|
+
function createUpdateCommand(_ctx) {
|
|
12
|
+
return new Command("update").description("Check for and install xopc updates").option("--check", "Only check for updates without installing").option("--yes", "Skip confirmation prompts").option("--channel <channel>", "Update channel: stable, beta, or dev (default: from config, else stable)").option("--json", "Output results as JSON").addHelpText("after", formatExamples([
|
|
13
|
+
"xopc update",
|
|
14
|
+
"xopc update --check",
|
|
15
|
+
"xopc update --channel beta",
|
|
16
|
+
"xopc update --yes",
|
|
17
|
+
"xopc update --json"
|
|
18
|
+
])).action(async (options) => {
|
|
19
|
+
const fromCli = options.channel;
|
|
20
|
+
const fromConfig = (() => {
|
|
21
|
+
try {
|
|
22
|
+
return loadConfig().update?.channel;
|
|
23
|
+
} catch {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
})();
|
|
27
|
+
const channel = normalizeUpdateChannel(fromCli ?? fromConfig) ?? "stable";
|
|
28
|
+
const root = await resolvePackageRoot();
|
|
29
|
+
if (root) {
|
|
30
|
+
if (await detectInstallKind(root) === "git") {
|
|
31
|
+
const message = "Running from a git checkout. Use `git pull` to update instead.";
|
|
32
|
+
if (options.json) console.log(JSON.stringify({
|
|
33
|
+
status: "skipped",
|
|
34
|
+
reason: "git-checkout",
|
|
35
|
+
message
|
|
36
|
+
}));
|
|
37
|
+
else console.log(message);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (!options.json) console.log(`Checking for updates (channel: ${channel})...`);
|
|
42
|
+
const resolved = await resolveNpmChannelTag({ channel });
|
|
43
|
+
if (!resolved.version) {
|
|
44
|
+
const message = "Could not reach npm registry. Check your network connection.";
|
|
45
|
+
if (options.json) console.log(JSON.stringify({
|
|
46
|
+
status: "error",
|
|
47
|
+
reason: "registry-unreachable",
|
|
48
|
+
message
|
|
49
|
+
}));
|
|
50
|
+
else console.error(message);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
const comparison = compareSemver(PACKAGE_VERSION, resolved.version);
|
|
54
|
+
if (comparison === null || comparison >= 0) {
|
|
55
|
+
const message = `Already up to date: v${PACKAGE_VERSION} (${resolved.tag}: v${resolved.version})`;
|
|
56
|
+
if (options.json) console.log(JSON.stringify({
|
|
57
|
+
status: "up-to-date",
|
|
58
|
+
currentVersion: PACKAGE_VERSION,
|
|
59
|
+
latestVersion: resolved.version,
|
|
60
|
+
channel: resolved.tag
|
|
61
|
+
}));
|
|
62
|
+
else console.log(`✅ ${message}`);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (options.check) {
|
|
66
|
+
const message = `Update available: v${PACKAGE_VERSION} → v${resolved.version} (${resolved.tag})`;
|
|
67
|
+
if (options.json) console.log(JSON.stringify({
|
|
68
|
+
status: "update-available",
|
|
69
|
+
currentVersion: PACKAGE_VERSION,
|
|
70
|
+
latestVersion: resolved.version,
|
|
71
|
+
channel: resolved.tag
|
|
72
|
+
}));
|
|
73
|
+
else {
|
|
74
|
+
console.log(`📦 ${message}`);
|
|
75
|
+
console.log("Run `xopc update` to install.");
|
|
76
|
+
}
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (!options.yes && !process.env.XOPC_AUTO_UPDATE) {
|
|
80
|
+
const { confirm } = await import("@inquirer/prompts");
|
|
81
|
+
if (!await confirm({
|
|
82
|
+
message: `Update from v${PACKAGE_VERSION} to v${resolved.version} (${resolved.tag})?`,
|
|
83
|
+
default: true
|
|
84
|
+
})) {
|
|
85
|
+
console.log("Update cancelled.");
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
const packageManager = detectGlobalPackageManager();
|
|
90
|
+
const spec = `@xopcai/xopc@${resolved.version}`;
|
|
91
|
+
if (!options.json) console.log(`Installing ${spec} via ${packageManager}...`);
|
|
92
|
+
const exitCode = await runInstallCommand(buildInstallArgs(packageManager, spec));
|
|
93
|
+
if (exitCode === 0) if (options.json) console.log(JSON.stringify({
|
|
94
|
+
status: "ok",
|
|
95
|
+
previousVersion: PACKAGE_VERSION,
|
|
96
|
+
installedVersion: resolved.version,
|
|
97
|
+
channel: resolved.tag,
|
|
98
|
+
packageManager
|
|
99
|
+
}));
|
|
100
|
+
else {
|
|
101
|
+
console.log(`✅ Updated to v${resolved.version}`);
|
|
102
|
+
console.log("Restart the gateway to use the new version: xopc gateway restart");
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
if (options.json) console.log(JSON.stringify({
|
|
106
|
+
status: "error",
|
|
107
|
+
reason: "install-failed",
|
|
108
|
+
exitCode,
|
|
109
|
+
packageManager
|
|
110
|
+
}));
|
|
111
|
+
else {
|
|
112
|
+
console.error(`❌ Update failed (exit code ${exitCode})`);
|
|
113
|
+
console.error(`Try manually: ${packageManager} install -g ${spec}`);
|
|
114
|
+
}
|
|
115
|
+
process.exit(1);
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Detect which package manager was used to install xopc globally.
|
|
121
|
+
* Checks common indicators: npm_config_user_agent, process.env, argv paths.
|
|
122
|
+
*/
|
|
123
|
+
function detectGlobalPackageManager() {
|
|
124
|
+
if ((process.env.npm_config_user_agent ?? "").startsWith("pnpm/")) return "pnpm";
|
|
125
|
+
return "npm";
|
|
126
|
+
}
|
|
127
|
+
function buildInstallArgs(manager, spec) {
|
|
128
|
+
if (manager === "pnpm") return [
|
|
129
|
+
"pnpm",
|
|
130
|
+
"add",
|
|
131
|
+
"-g",
|
|
132
|
+
spec
|
|
133
|
+
];
|
|
134
|
+
return [
|
|
135
|
+
"npm",
|
|
136
|
+
"install",
|
|
137
|
+
"-g",
|
|
138
|
+
spec,
|
|
139
|
+
"--no-fund",
|
|
140
|
+
"--no-audit"
|
|
141
|
+
];
|
|
142
|
+
}
|
|
143
|
+
function runInstallCommand(argv) {
|
|
144
|
+
return new Promise((resolve) => {
|
|
145
|
+
const child = spawn(argv[0], argv.slice(1), {
|
|
146
|
+
stdio: "inherit",
|
|
147
|
+
env: process.env
|
|
148
|
+
});
|
|
149
|
+
child.on("error", () => resolve(1));
|
|
150
|
+
child.on("exit", (code) => resolve(code ?? 1));
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
register({
|
|
154
|
+
id: "update",
|
|
155
|
+
name: "update",
|
|
156
|
+
description: "Check for and install xopc updates",
|
|
157
|
+
factory: createUpdateCommand,
|
|
158
|
+
metadata: {
|
|
159
|
+
category: "maintenance",
|
|
160
|
+
examples: [
|
|
161
|
+
"xopc update",
|
|
162
|
+
"xopc update --check",
|
|
163
|
+
"xopc update --channel beta",
|
|
164
|
+
"xopc update --yes --json"
|
|
165
|
+
]
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
//#endregion
|
|
169
|
+
export {};
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","names":[],"sources":["../../../../src/cli/commands/update.ts"],"sourcesContent":["// src/cli/commands/update.ts\n\nimport { Command } from 'commander';\nimport { spawn } from 'node:child_process';\n\nimport { loadConfig } from '../../config/index.js';\nimport { PACKAGE_VERSION } from '../../package-version.js';\nimport { register, formatExamples, type CLIContext } from '../registry.js';\nimport { normalizeUpdateChannel, DEFAULT_PACKAGE_CHANNEL } from '../../infra/update-channels.js';\nimport {\n resolveNpmChannelTag,\n compareSemver,\n detectInstallKind,\n resolvePackageRoot,\n} from '../../infra/update-check.js';\n\nfunction createUpdateCommand(_ctx: CLIContext): Command {\n return new Command('update')\n .description('Check for and install xopc updates')\n .option('--check', 'Only check for updates without installing')\n .option('--yes', 'Skip confirmation prompts')\n .option('--channel <channel>', 'Update channel: stable, beta, or dev (default: from config, else stable)')\n .option('--json', 'Output results as JSON')\n .addHelpText(\n 'after',\n formatExamples([\n 'xopc update',\n 'xopc update --check',\n 'xopc update --channel beta',\n 'xopc update --yes',\n 'xopc update --json',\n ]),\n )\n .action(\n async (options: { check?: boolean; yes?: boolean; channel?: string; json?: boolean }) => {\n const fromCli = options.channel;\n const fromConfig = (() => {\n try {\n return loadConfig().update?.channel;\n } catch {\n return undefined;\n }\n })();\n const channel = normalizeUpdateChannel(fromCli ?? fromConfig) ?? DEFAULT_PACKAGE_CHANNEL;\n\n // Check current install kind\n const root = await resolvePackageRoot();\n if (root) {\n const installKind = await detectInstallKind(root);\n if (installKind === 'git') {\n const message = 'Running from a git checkout. Use `git pull` to update instead.';\n if (options.json) {\n console.log(JSON.stringify({ status: 'skipped', reason: 'git-checkout', message }));\n } else {\n console.log(message);\n }\n return;\n }\n }\n\n if (!options.json) {\n console.log(`Checking for updates (channel: ${channel})...`);\n }\n\n const resolved = await resolveNpmChannelTag({ channel });\n if (!resolved.version) {\n const message = 'Could not reach npm registry. Check your network connection.';\n if (options.json) {\n console.log(JSON.stringify({ status: 'error', reason: 'registry-unreachable', message }));\n } else {\n console.error(message);\n }\n process.exit(1);\n }\n\n const comparison = compareSemver(PACKAGE_VERSION, resolved.version);\n if (comparison === null || comparison >= 0) {\n const message = `Already up to date: v${PACKAGE_VERSION} (${resolved.tag}: v${resolved.version})`;\n if (options.json) {\n console.log(\n JSON.stringify({\n status: 'up-to-date',\n currentVersion: PACKAGE_VERSION,\n latestVersion: resolved.version,\n channel: resolved.tag,\n }),\n );\n } else {\n console.log(`✅ ${message}`);\n }\n return;\n }\n\n if (options.check) {\n const message = `Update available: v${PACKAGE_VERSION} → v${resolved.version} (${resolved.tag})`;\n if (options.json) {\n console.log(\n JSON.stringify({\n status: 'update-available',\n currentVersion: PACKAGE_VERSION,\n latestVersion: resolved.version,\n channel: resolved.tag,\n }),\n );\n } else {\n console.log(`📦 ${message}`);\n console.log('Run `xopc update` to install.');\n }\n return;\n }\n\n if (!options.yes && !process.env.XOPC_AUTO_UPDATE) {\n const { confirm } = await import('@inquirer/prompts');\n const shouldUpdate = await confirm({\n message: `Update from v${PACKAGE_VERSION} to v${resolved.version} (${resolved.tag})?`,\n default: true,\n });\n if (!shouldUpdate) {\n console.log('Update cancelled.');\n return;\n }\n }\n\n const packageManager = detectGlobalPackageManager();\n const spec = `@xopcai/xopc@${resolved.version}`;\n\n if (!options.json) {\n console.log(`Installing ${spec} via ${packageManager}...`);\n }\n\n const installArgs = buildInstallArgs(packageManager, spec);\n const exitCode = await runInstallCommand(installArgs);\n\n if (exitCode === 0) {\n if (options.json) {\n console.log(\n JSON.stringify({\n status: 'ok',\n previousVersion: PACKAGE_VERSION,\n installedVersion: resolved.version,\n channel: resolved.tag,\n packageManager,\n }),\n );\n } else {\n console.log(`✅ Updated to v${resolved.version}`);\n console.log('Restart the gateway to use the new version: xopc gateway restart');\n }\n } else {\n if (options.json) {\n console.log(\n JSON.stringify({\n status: 'error',\n reason: 'install-failed',\n exitCode,\n packageManager,\n }),\n );\n } else {\n console.error(`❌ Update failed (exit code ${exitCode})`);\n console.error(`Try manually: ${packageManager} install -g ${spec}`);\n }\n process.exit(1);\n }\n },\n );\n}\n\n/**\n * Detect which package manager was used to install xopc globally.\n * Checks common indicators: npm_config_user_agent, process.env, argv paths.\n */\nfunction detectGlobalPackageManager(): 'npm' | 'pnpm' {\n const userAgent = process.env.npm_config_user_agent ?? '';\n if (userAgent.startsWith('pnpm/')) return 'pnpm';\n return 'npm';\n}\n\nfunction buildInstallArgs(manager: 'npm' | 'pnpm', spec: string): string[] {\n if (manager === 'pnpm') {\n return ['pnpm', 'add', '-g', spec];\n }\n return ['npm', 'install', '-g', spec, '--no-fund', '--no-audit'];\n}\n\nfunction runInstallCommand(argv: string[]): Promise<number> {\n return new Promise((resolve) => {\n const child = spawn(argv[0], argv.slice(1), {\n stdio: 'inherit',\n env: process.env,\n });\n child.on('error', () => resolve(1));\n child.on('exit', (code) => resolve(code ?? 1));\n });\n}\n\nregister({\n id: 'update',\n name: 'update',\n description: 'Check for and install xopc updates',\n factory: createUpdateCommand,\n metadata: {\n category: 'maintenance',\n examples: [\n 'xopc update',\n 'xopc update --check',\n 'xopc update --channel beta',\n 'xopc update --yes --json',\n ],\n },\n});\n"],"mappings":"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"}
|
package/dist/src/cli/index.d.ts
CHANGED
|
@@ -11,9 +11,9 @@ import './commands/doctor/index.js';
|
|
|
11
11
|
import './commands/image.js';
|
|
12
12
|
import './commands/channels.js';
|
|
13
13
|
import './commands/models.js';
|
|
14
|
-
import './commands/extension.js';
|
|
15
14
|
import './commands/auth.js';
|
|
16
15
|
import './commands/skills.js';
|
|
16
|
+
import './commands/update.js';
|
|
17
17
|
import './commands/logs.js';
|
|
18
18
|
export declare let parsedOpts: {
|
|
19
19
|
config?: string;
|
package/dist/src/cli/index.js
CHANGED
|
@@ -15,9 +15,10 @@ import "./commands/doctor/index.js";
|
|
|
15
15
|
import "./commands/image.js";
|
|
16
16
|
import "./commands/channels.js";
|
|
17
17
|
import "./commands/models.js";
|
|
18
|
-
import "./commands/extension.js";
|
|
18
|
+
import { registerExtensionCommands } from "./commands/extension.js";
|
|
19
19
|
import "./commands/auth.js";
|
|
20
20
|
import "./commands/skills.js";
|
|
21
|
+
import "./commands/update.js";
|
|
21
22
|
import "./commands/logs.js";
|
|
22
23
|
import { registerAgentsCli } from "./commands/agents.js";
|
|
23
24
|
import { Command } from "commander";
|
|
@@ -50,6 +51,7 @@ program.hook("postAction", async (thisCommand) => {
|
|
|
50
51
|
const ctx = getContextWithOpts(process.argv);
|
|
51
52
|
registry.install(program, ctx);
|
|
52
53
|
registerAgentsCli(program);
|
|
54
|
+
registerExtensionCommands(program);
|
|
53
55
|
if (!(!!process.env.VITEST || !!process.env.TEST || !!"production"?.includes("test")) && import.meta.url.startsWith("file:")) {
|
|
54
56
|
const argv = process.argv.filter((arg, index) => {
|
|
55
57
|
if (arg !== "--") return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["pkg.version"],"sources":["../../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { registry, createDefaultContext, type CLIContext } from './registry.js';\nimport pkg from '../../package.json' with { type: 'json' };\nimport { flushAndClose } from '../utils/logger.js'; // Import flushAndClose for graceful shutdown\nimport { registerExtensionCliCommands } from './bootstrap-extensions.js';\n\n// Import order determines display order in help\nimport './commands/setup.js';\nimport './commands/onboard.js';\nimport './commands/agent.js';\nimport './commands/gateway.js';\nimport './commands/session.js';\nimport './commands/cron.js';\nimport './commands/config.js';\nimport './commands/doctor/index.js';\nimport './commands/image.js';\nimport './commands/channels.js';\nimport './commands/models.js';\nimport './commands/extension.js';\nimport './commands/auth.js';\nimport './commands/skills.js';\nimport './commands/logs.js';\nimport { registerAgentsCli } from './commands/agents.js';\n\n// Global parsed options - updated before each command\nexport let parsedOpts: { config?: string; workspace?: string; verbose?: boolean } = {};\n\nexport function getContextWithOpts(argv: string[] = process.argv): CLIContext {\n return createDefaultContext(argv, parsedOpts);\n}\n\n// Long-running commands that should not auto-exit\nconst LONG_RUNNING_COMMANDS = new Set(['gateway', 'agent']);\n\nconst program = new Command()\n .name('xopc')\n .description('Ultra-Lightweight Personal AI Assistant')\n .version(pkg.version)\n .option('--verbose', 'Enable verbose logging', false)\n .option('--config <path>', 'Config file path')\n .option('--workspace <path>', 'Workspace directory');\n\n// Hook to capture parsed options before each command runs\nprogram.hook('preAction', (thisCommand) => {\n parsedOpts = thisCommand.opts();\n});\n\n// Hook to ensure process exits after command completion\nprogram.hook('postAction', async (thisCommand) => {\n // Get the actual subcommand being executed (not the root program name)\n const args = thisCommand.args;\n const subCommandName = args.length > 0 ? args[0] : thisCommand.name();\n\n // Skip long-running commands (gateway foreground, agent interactive mode)\n if (LONG_RUNNING_COMMANDS.has(subCommandName)) {\n // For agent command, only skip exit if interactive mode (-i) is used\n if (subCommandName === 'agent') {\n const hasInteractiveFlag = process.argv.includes('-i') || process.argv.includes('--interactive');\n if (!hasInteractiveFlag) {\n // Agent in non-interactive mode should exit normally\n await flushAndClose();\n process.exit(0);\n }\n }\n // Gateway or agent -i: don't exit\n return;\n }\n // For all other commands, flush logs and exit\n await flushAndClose();\n process.exit(0);\n});\n\n// Create initial context (will use env vars and defaults)\nconst ctx = getContextWithOpts(process.argv);\nregistry.install(program, ctx);\nregisterAgentsCli(program);\n\n// Only parse if this is the main module being executed directly\n// Skip parsing when imported as module (e.g., in tests)\nconst isTestEnv = !!process.env.VITEST || !!process.env.TEST || !!process.env.NODE_ENV?.includes('test');\nconst isMainModule = !isTestEnv && import.meta.url.startsWith('file:');\n\nif (isMainModule) {\n // Filter out standalone '--' separator (passed by pnpm run -- <cmd>)\n // npm removes it automatically, pnpm passes it through\n const argv = process.argv.filter((arg, index) => {\n if (arg !== '--') return true;\n // Only filter '--' if it's the separator between script and command\n // (i.e., comes after the script name and before actual args)\n return index < 2; // Keep '--' if it's a script argument (index 0 or 1)\n });\n void registerExtensionCliCommands(program).then(() => {\n program.parse(argv);\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":["pkg.version"],"sources":["../../../src/cli/index.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport { registry, createDefaultContext, type CLIContext } from './registry.js';\nimport pkg from '../../package.json' with { type: 'json' };\nimport { flushAndClose } from '../utils/logger.js'; // Import flushAndClose for graceful shutdown\nimport { registerExtensionCliCommands } from './bootstrap-extensions.js';\n\n// Import order determines display order in help\nimport './commands/setup.js';\nimport './commands/onboard.js';\nimport './commands/agent.js';\nimport './commands/gateway.js';\nimport './commands/session.js';\nimport './commands/cron.js';\nimport './commands/config.js';\nimport './commands/doctor/index.js';\nimport './commands/image.js';\nimport './commands/channels.js';\nimport './commands/models.js';\nimport { registerExtensionCommands } from './commands/extension.js';\nimport './commands/auth.js';\nimport './commands/skills.js';\nimport './commands/update.js';\nimport './commands/logs.js';\nimport { registerAgentsCli } from './commands/agents.js';\n\n// Global parsed options - updated before each command\nexport let parsedOpts: { config?: string; workspace?: string; verbose?: boolean } = {};\n\nexport function getContextWithOpts(argv: string[] = process.argv): CLIContext {\n return createDefaultContext(argv, parsedOpts);\n}\n\n// Long-running commands that should not auto-exit\nconst LONG_RUNNING_COMMANDS = new Set(['gateway', 'agent']);\n\nconst program = new Command()\n .name('xopc')\n .description('Ultra-Lightweight Personal AI Assistant')\n .version(pkg.version)\n .option('--verbose', 'Enable verbose logging', false)\n .option('--config <path>', 'Config file path')\n .option('--workspace <path>', 'Workspace directory');\n\n// Hook to capture parsed options before each command runs\nprogram.hook('preAction', (thisCommand) => {\n parsedOpts = thisCommand.opts();\n});\n\n// Hook to ensure process exits after command completion\nprogram.hook('postAction', async (thisCommand) => {\n // Get the actual subcommand being executed (not the root program name)\n const args = thisCommand.args;\n const subCommandName = args.length > 0 ? args[0] : thisCommand.name();\n\n // Skip long-running commands (gateway foreground, agent interactive mode)\n if (LONG_RUNNING_COMMANDS.has(subCommandName)) {\n // For agent command, only skip exit if interactive mode (-i) is used\n if (subCommandName === 'agent') {\n const hasInteractiveFlag = process.argv.includes('-i') || process.argv.includes('--interactive');\n if (!hasInteractiveFlag) {\n // Agent in non-interactive mode should exit normally\n await flushAndClose();\n process.exit(0);\n }\n }\n // Gateway or agent -i: don't exit\n return;\n }\n // For all other commands, flush logs and exit\n await flushAndClose();\n process.exit(0);\n});\n\n// Create initial context (will use env vars and defaults)\nconst ctx = getContextWithOpts(process.argv);\nregistry.install(program, ctx);\nregisterAgentsCli(program);\nregisterExtensionCommands(program);\n\n// Only parse if this is the main module being executed directly\n// Skip parsing when imported as module (e.g., in tests)\nconst isTestEnv = !!process.env.VITEST || !!process.env.TEST || !!process.env.NODE_ENV?.includes('test');\nconst isMainModule = !isTestEnv && import.meta.url.startsWith('file:');\n\nif (isMainModule) {\n // Filter out standalone '--' separator (passed by pnpm run -- <cmd>)\n // npm removes it automatically, pnpm passes it through\n const argv = process.argv.filter((arg, index) => {\n if (arg !== '--') return true;\n // Only filter '--' if it's the separator between script and command\n // (i.e., comes after the script name and before actual args)\n return index < 2; // Keep '--' if it's a script argument (index 0 or 1)\n });\n void registerExtensionCliCommands(program).then(() => {\n program.parse(argv);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;aAImD;AAuBnD,IAAW,aAAyE,EAAE;AAEtF,SAAgB,mBAAmB,OAAiB,QAAQ,MAAkB;AAC5E,QAAO,qBAAqB,MAAM,WAAW;;AAI/C,MAAM,wBAAwB,IAAI,IAAI,CAAC,WAAW,QAAQ,CAAC;AAE3D,MAAM,UAAU,IAAI,SAAS,CAC1B,KAAK,OAAO,CACZ,YAAY,0CAA0C,CACtD,QAAQA,QAAY,CACpB,OAAO,aAAa,0BAA0B,MAAM,CACpD,OAAO,mBAAmB,mBAAmB,CAC7C,OAAO,sBAAsB,sBAAsB;AAGtD,QAAQ,KAAK,cAAc,gBAAgB;AACzC,cAAa,YAAY,MAAM;EAC/B;AAGF,QAAQ,KAAK,cAAc,OAAO,gBAAgB;CAEhD,MAAM,OAAO,YAAY;CACzB,MAAM,iBAAiB,KAAK,SAAS,IAAI,KAAK,KAAK,YAAY,MAAM;AAGrE,KAAI,sBAAsB,IAAI,eAAe,EAAE;AAE7C,MAAI,mBAAmB;OAEjB,EADuB,QAAQ,KAAK,SAAS,KAAK,IAAI,QAAQ,KAAK,SAAS,gBAAgB,GACvE;AAEvB,UAAM,eAAe;AACrB,YAAQ,KAAK,EAAE;;;AAInB;;AAGF,OAAM,eAAe;AACrB,SAAQ,KAAK,EAAE;EACf;AAGF,MAAM,MAAM,mBAAmB,QAAQ,KAAK;AAC5C,SAAS,QAAQ,SAAS,IAAI;AAC9B,kBAAkB,QAAQ;AAC1B,0BAA0B,QAAQ;AAOlC,IAFqB,EADH,CAAC,CAAC,QAAQ,IAAI,UAAU,CAAC,CAAC,QAAQ,IAAI,QAAQ,CAAC,CAAA,cAAuB,SAAS,OAAO,KACrE,OAAO,KAAK,IAAI,WAAW,QAAQ,EAEpD;CAGhB,MAAM,OAAO,QAAQ,KAAK,QAAQ,KAAK,UAAU;AAC/C,MAAI,QAAQ,KAAM,QAAO;AAGzB,SAAO,QAAQ;GACf;AACG,8BAA6B,QAAQ,CAAC,WAAW;AACpD,UAAQ,MAAM,KAAK;GACnB"}
|
|
@@ -12,6 +12,7 @@ export * from './defaults.js';
|
|
|
12
12
|
export * from './integration.js';
|
|
13
13
|
export * from './models-json.js';
|
|
14
14
|
export * from './resolve-config-value.js';
|
|
15
|
+
export * from './runtime-overrides.js';
|
|
15
16
|
export type { ThinkLevel, ReasoningLevel, VerboseLevel, ElevatedMode, SessionAgentConfig, } from '../agent/transcript/thinking-types.js';
|
|
16
17
|
export { normalizeThinkLevel, normalizeReasoningLevel, normalizeVerboseLevel, normalizeElevatedMode, listThinkingLevels, formatThinkingLevels, thinkLevelToNumber, } from '../agent/transcript/thinking-types.js';
|
|
17
18
|
export type { ModelApi, ModelCompatConfig, ModelProviderAuthMode, ModelDefinitionConfig, ModelProviderConfig, BedrockDiscoveryConfig, ModelsConfig, } from './types.models.js';
|