vigthoria-cli 1.13.20 → 1.13.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/completions/_vigthoria +49 -0
  2. package/completions/vigthoria.bash +6 -0
  3. package/completions/vigthoria.fish +41 -0
  4. package/dist/commands/auth.d.ts +1 -0
  5. package/dist/commands/auth.js +63 -128
  6. package/dist/commands/background.d.ts +0 -2
  7. package/dist/commands/background.js +26 -34
  8. package/dist/commands/bridge.js +45 -41
  9. package/dist/commands/cancel.d.ts +1 -0
  10. package/dist/commands/cancel.js +22 -16
  11. package/dist/commands/chat.d.ts +3 -42
  12. package/dist/commands/chat.js +378 -1123
  13. package/dist/commands/coding-registration.d.ts +4 -0
  14. package/dist/commands/coding-registration.js +24 -0
  15. package/dist/commands/config.js +23 -29
  16. package/dist/commands/conversation-registration.d.ts +4 -0
  17. package/dist/commands/conversation-registration.js +122 -0
  18. package/dist/commands/deploy.d.ts +8 -2
  19. package/dist/commands/deploy.js +92 -90
  20. package/dist/commands/device.d.ts +1 -2
  21. package/dist/commands/device.js +37 -21
  22. package/dist/commands/doctor-registration.d.ts +4 -0
  23. package/dist/commands/doctor-registration.js +207 -0
  24. package/dist/commands/edit.js +22 -33
  25. package/dist/commands/explain.js +7 -10
  26. package/dist/commands/fork.d.ts +1 -2
  27. package/dist/commands/fork.js +72 -22
  28. package/dist/commands/game.d.ts +1 -1
  29. package/dist/commands/game.js +17 -6
  30. package/dist/commands/generate.js +7 -9
  31. package/dist/commands/history.js +11 -7
  32. package/dist/commands/hub.d.ts +2 -2
  33. package/dist/commands/hub.js +34 -35
  34. package/dist/commands/legion.d.ts +0 -1
  35. package/dist/commands/legion.js +62 -79
  36. package/dist/commands/music.d.ts +1 -2
  37. package/dist/commands/music.js +62 -27
  38. package/dist/commands/platform-registration.d.ts +4 -0
  39. package/dist/commands/platform-registration.js +45 -0
  40. package/dist/commands/preview.d.ts +0 -1
  41. package/dist/commands/preview.js +82 -35
  42. package/dist/commands/product-run-registration.d.ts +4 -0
  43. package/dist/commands/product-run-registration.js +490 -0
  44. package/dist/commands/replay.d.ts +1 -2
  45. package/dist/commands/replay.js +15 -11
  46. package/dist/commands/repo.d.ts +14 -7
  47. package/dist/commands/repo.js +244 -198
  48. package/dist/commands/review.js +9 -12
  49. package/dist/commands/security.d.ts +1 -2
  50. package/dist/commands/security.js +12 -6
  51. package/dist/commands/update-registration.d.ts +3 -0
  52. package/dist/commands/update-registration.js +368 -0
  53. package/dist/commands/v4-registration.d.ts +4 -0
  54. package/dist/commands/v4-registration.js +24 -0
  55. package/dist/commands/v4.d.ts +1 -1
  56. package/dist/commands/v4.js +46 -8
  57. package/dist/commands/wallet.d.ts +1 -3
  58. package/dist/commands/wallet.js +18 -45
  59. package/dist/commands/workflow.d.ts +2 -0
  60. package/dist/commands/workflow.js +52 -39
  61. package/dist/index.js +124 -1589
  62. package/dist/utils/agent-stream-state.d.ts +27 -0
  63. package/dist/utils/agent-stream-state.js +93 -0
  64. package/dist/utils/agentRoute.d.ts +2 -1
  65. package/dist/utils/agentRoute.js +22 -9
  66. package/dist/utils/agentRunOutcome.d.ts +16 -0
  67. package/dist/utils/agentRunOutcome.js +37 -2
  68. package/dist/utils/api-client-factory.d.ts +8 -0
  69. package/dist/utils/api-client-factory.js +8 -0
  70. package/dist/utils/api.d.ts +44 -266
  71. package/dist/utils/api.js +647 -3180
  72. package/dist/utils/auth-session.d.ts +41 -0
  73. package/dist/utils/auth-session.js +224 -0
  74. package/dist/utils/brain-hub-client.d.ts +0 -4
  75. package/dist/utils/brain-hub-client.js +6 -3
  76. package/dist/utils/bridge-client.js +2 -0
  77. package/dist/utils/capability-health-service.d.ts +48 -0
  78. package/dist/utils/capability-health-service.js +64 -0
  79. package/dist/utils/chat-prompt-policy.d.ts +18 -0
  80. package/dist/utils/chat-prompt-policy.js +61 -0
  81. package/dist/utils/chat-tool-call-parser.d.ts +11 -0
  82. package/dist/utils/chat-tool-call-parser.js +71 -0
  83. package/dist/utils/cli-state.d.ts +22 -4
  84. package/dist/utils/cli-state.js +105 -47
  85. package/dist/utils/code-operations-service.d.ts +104 -0
  86. package/dist/utils/code-operations-service.js +837 -0
  87. package/dist/utils/codebase-indexer.d.ts +1 -0
  88. package/dist/utils/codebase-indexer.js +28 -8
  89. package/dist/utils/command-contract.d.ts +61 -0
  90. package/dist/utils/command-contract.js +149 -0
  91. package/dist/utils/command-policy.d.ts +10 -0
  92. package/dist/utils/command-policy.js +54 -0
  93. package/dist/utils/config.d.ts +13 -5
  94. package/dist/utils/config.js +220 -94
  95. package/dist/utils/context-ranker.js +11 -2
  96. package/dist/utils/context-state.d.ts +39 -0
  97. package/dist/utils/context-state.js +52 -0
  98. package/dist/utils/deckEvents.d.ts +0 -5
  99. package/dist/utils/deckEvents.js +3 -2
  100. package/dist/utils/desktop-bridge-client.js +2 -0
  101. package/dist/utils/direct-output-policy.d.ts +3 -0
  102. package/dist/utils/direct-output-policy.js +76 -0
  103. package/dist/utils/durable-json.d.ts +57 -0
  104. package/dist/utils/durable-json.js +319 -0
  105. package/dist/utils/fastAgentRouter.d.ts +5 -6
  106. package/dist/utils/fastAgentRouter.js +17 -25
  107. package/dist/utils/files.js +21 -13
  108. package/dist/utils/frontend-preview-service.d.ts +76 -0
  109. package/dist/utils/frontend-preview-service.js +482 -0
  110. package/dist/utils/goaEvents.d.ts +0 -4
  111. package/dist/utils/goaEvents.js +5 -2
  112. package/dist/utils/logger.d.ts +2 -1
  113. package/dist/utils/logger.js +27 -20
  114. package/dist/utils/mcp-context-client.d.ts +24 -0
  115. package/dist/utils/mcp-context-client.js +58 -0
  116. package/dist/utils/model-governance.d.ts +18 -0
  117. package/dist/utils/model-governance.js +75 -0
  118. package/dist/utils/model-transport-service.d.ts +44 -0
  119. package/dist/utils/model-transport-service.js +111 -0
  120. package/dist/utils/mutation-journal.d.ts +42 -0
  121. package/dist/utils/mutation-journal.js +387 -0
  122. package/dist/utils/network-policy.d.ts +24 -0
  123. package/dist/utils/network-policy.js +202 -0
  124. package/dist/utils/operator-client.d.ts +45 -0
  125. package/dist/utils/operator-client.js +159 -0
  126. package/dist/utils/post-write-validator.js +7 -9
  127. package/dist/utils/preview-screenshot-adapter.d.ts +15 -0
  128. package/dist/utils/preview-screenshot-adapter.js +51 -0
  129. package/dist/utils/process-policy.d.ts +23 -0
  130. package/dist/utils/process-policy.js +284 -0
  131. package/dist/utils/project-memory.d.ts +13 -3
  132. package/dist/utils/project-memory.js +70 -17
  133. package/dist/utils/prompt-workspace-resolver.d.ts +14 -0
  134. package/dist/utils/prompt-workspace-resolver.js +64 -0
  135. package/dist/utils/release-install.d.ts +11 -0
  136. package/dist/utils/release-install.js +155 -0
  137. package/dist/utils/release-policy.d.ts +64 -0
  138. package/dist/utils/release-policy.js +293 -0
  139. package/dist/utils/requestIntent.js +22 -3
  140. package/dist/utils/runtime-capability.d.ts +8 -0
  141. package/dist/utils/runtime-capability.js +16 -0
  142. package/dist/utils/runtime-temp.d.ts +76 -0
  143. package/dist/utils/runtime-temp.js +492 -0
  144. package/dist/utils/secret-policy.d.ts +20 -0
  145. package/dist/utils/secret-policy.js +160 -0
  146. package/dist/utils/session.d.ts +17 -3
  147. package/dist/utils/session.js +354 -110
  148. package/dist/utils/tool-approval-service.d.ts +17 -0
  149. package/dist/utils/tool-approval-service.js +78 -0
  150. package/dist/utils/tool-capability-providers.d.ts +57 -0
  151. package/dist/utils/tool-capability-providers.js +57 -0
  152. package/dist/utils/tools.d.ts +2 -23
  153. package/dist/utils/tools.js +226 -512
  154. package/dist/utils/update-policy.d.ts +18 -0
  155. package/dist/utils/update-policy.js +137 -0
  156. package/dist/utils/v3-agent-client.d.ts +40 -0
  157. package/dist/utils/v3-agent-client.js +165 -0
  158. package/dist/utils/v3-workspace-service.d.ts +28 -0
  159. package/dist/utils/v3-workspace-service.js +279 -0
  160. package/dist/utils/vigflow-client.d.ts +95 -0
  161. package/dist/utils/vigflow-client.js +105 -0
  162. package/dist/utils/workspace-boundary.d.ts +45 -0
  163. package/dist/utils/workspace-boundary.js +377 -0
  164. package/dist/utils/workspace-brain-service.d.ts +2 -0
  165. package/dist/utils/workspace-brain-service.js +11 -1
  166. package/dist/utils/workspace-cache.js +37 -15
  167. package/dist/utils/workspace-stream.js +35 -10
  168. package/install.ps1 +115 -142
  169. package/install.sh +112 -81
  170. package/package.json +43 -9
  171. package/release-policy.json +43 -0
  172. package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
  173. package/scripts/release/generate-completions.mjs +24 -0
  174. package/scripts/release/install-release.mjs +10 -0
  175. package/scripts/release/publish-cli-release.mjs +116 -0
  176. package/scripts/release/publish-cli-release.sh +2 -70
  177. package/scripts/release/resolve-release-manifest.mjs +26 -0
  178. package/scripts/release/test-balanced-model-live.sh +45 -0
  179. package/scripts/release/validate-live-service-gates.sh +93 -0
  180. package/scripts/release/validate-no-go-gates.sh +145 -174
  181. package/scripts/release/verify-runtime-consistency.mjs +4 -1
  182. package/dist/commands/index.d.ts +0 -12
  183. package/dist/commands/index.js +0 -194
  184. package/dist/commands/update.d.ts +0 -9
  185. package/dist/commands/update.js +0 -301
  186. package/dist/utils/templateInstantPath.d.ts +0 -18
  187. package/dist/utils/templateInstantPath.js +0 -228
@@ -0,0 +1,49 @@
1
+ #compdef vigthoria vig vigthoria-chat
2
+ # Generated from contracts/phase-0/command-manifest.json; do not edit.
3
+ _vigthoria() {
4
+ local -a commands
5
+ commands=(
6
+ 'agent:Start agentic mode - AI can read/write files, run commands'
7
+ 'auth:Manage Vigthoria CLI authentication'
8
+ 'background:Run and manage detached Vigthoria Agent jobs'
9
+ 'bridge:Inspect local DevTools Bridge availability for browser debugging tasks'
10
+ 'cancel:Cancel an in-flight V3 agent run (by context_id), or use --all to cancel every active run'
11
+ 'chat:Start interactive chat with Vigthoria AI'
12
+ 'chat-resume:Resume the latest chat session for the current or specified project'
13
+ 'commands:List every CLI command grouped by command family'
14
+ 'config:Configure Vigthoria CLI settings'
15
+ 'deploy:Deploy and host your project on Vigthoria infrastructure'
16
+ 'device:Android Developer Bridge commands via local ADB'
17
+ 'devtools:DevTools Bridge commands for browser debugging'
18
+ 'doctor:Run local Vigthoria CLI diagnostics (no network calls unless --check-api)'
19
+ 'edit:Edit a file with AI assistance'
20
+ 'explain:Explain code in a file'
21
+ 'fix:Fix issues in a file'
22
+ 'fork:Fork from an existing V3 agent run with new instructions'
23
+ 'game:Create, run, and validate Babylon/VGE game projects'
24
+ 'generate:Generate code from description'
25
+ 'history:List recent V3 agent runs'
26
+ 'hub:Discover, search, and activate Vigthoria API modules'
27
+ 'hyper-loop:Hyper Loop Legion orchestrator commands'
28
+ 'init:Initialize Vigthoria in current project'
29
+ 'legion:Run parallel tasks via Hyper Loop Legion orchestrator'
30
+ 'login:Login to Vigthoria Coder (prompts for credentials when run without flags)'
31
+ 'logout:Logout from Vigthoria Coder'
32
+ 'menu:Open the interactive command-family menu'
33
+ 'music:Generate songs with Vigthoria Music AI / ACE-Step'
34
+ 'operator:Start BMAD operator mode for infrastructure and system workflows'
35
+ 'preview:Preview project locally with visual diffs and proof validation'
36
+ 'replay:Replay events from a V3 agent run step-by-step'
37
+ 'repo:Push and pull projects to/from your Vigthoria Community Repository'
38
+ 'review:Review code quality'
39
+ 'security:Run security scans, scores, and fix plans via Vigthoria MCP security tools'
40
+ 'status:Show authentication and subscription status'
41
+ 'update:Check for updates and upgrade Vigthoria CLI. Default manifest: https://extension.vigthoria.io/downloads/manifest.json'
42
+ 'v4:Launch Vigthoria V4 Operating Agent (DeerFlow 2.0 harness)'
43
+ 'v4-menu:Internal: interactive V3/V4 agent + provider picker used by the V4 Operating Agent launcher'
44
+ 'wallet:Inspect monetary Vigthoria Credits used for Cloud, API, Video, and other PAYG services'
45
+ 'workflow:List, instantiate, and run repeatable VigFlow workflows'
46
+ )
47
+ _describe 'command' commands
48
+ }
49
+ _vigthoria "$@"
@@ -0,0 +1,6 @@
1
+ # Generated from contracts/phase-0/command-manifest.json; do not edit.
2
+ _vigthoria_completions() {
3
+ local cur="${COMP_WORDS[COMP_CWORD]}"
4
+ COMPREPLY=( $(compgen -W 'agent auth background bridge cancel chat chat-resume commands config deploy device devtools doctor edit explain fix fork game generate history hub hyper-loop init legion login logout menu music operator preview replay repo review security status update v4 v4-menu wallet workflow' -- "$cur") )
5
+ }
6
+ complete -F _vigthoria_completions vigthoria vig vigthoria-chat
@@ -0,0 +1,41 @@
1
+ # Generated from contracts/phase-0/command-manifest.json; do not edit.
2
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'agent' -d 'Start agentic mode - AI can read/write files, run commands'
3
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'auth' -d 'Manage Vigthoria CLI authentication'
4
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'background' -d 'Run and manage detached Vigthoria Agent jobs'
5
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'bridge' -d 'Inspect local DevTools Bridge availability for browser debugging tasks'
6
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'cancel' -d 'Cancel an in-flight V3 agent run (by context_id), or use --all to cancel every active run'
7
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'chat' -d 'Start interactive chat with Vigthoria AI'
8
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'chat-resume' -d 'Resume the latest chat session for the current or specified project'
9
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'commands' -d 'List every CLI command grouped by command family'
10
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'config' -d 'Configure Vigthoria CLI settings'
11
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'deploy' -d 'Deploy and host your project on Vigthoria infrastructure'
12
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'device' -d 'Android Developer Bridge commands via local ADB'
13
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'devtools' -d 'DevTools Bridge commands for browser debugging'
14
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'doctor' -d 'Run local Vigthoria CLI diagnostics (no network calls unless --check-api)'
15
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'edit' -d 'Edit a file with AI assistance'
16
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'explain' -d 'Explain code in a file'
17
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'fix' -d 'Fix issues in a file'
18
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'fork' -d 'Fork from an existing V3 agent run with new instructions'
19
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'game' -d 'Create, run, and validate Babylon/VGE game projects'
20
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'generate' -d 'Generate code from description'
21
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'history' -d 'List recent V3 agent runs'
22
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'hub' -d 'Discover, search, and activate Vigthoria API modules'
23
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'hyper-loop' -d 'Hyper Loop Legion orchestrator commands'
24
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'init' -d 'Initialize Vigthoria in current project'
25
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'legion' -d 'Run parallel tasks via Hyper Loop Legion orchestrator'
26
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'login' -d 'Login to Vigthoria Coder (prompts for credentials when run without flags)'
27
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'logout' -d 'Logout from Vigthoria Coder'
28
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'menu' -d 'Open the interactive command-family menu'
29
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'music' -d 'Generate songs with Vigthoria Music AI / ACE-Step'
30
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'operator' -d 'Start BMAD operator mode for infrastructure and system workflows'
31
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'preview' -d 'Preview project locally with visual diffs and proof validation'
32
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'replay' -d 'Replay events from a V3 agent run step-by-step'
33
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'repo' -d 'Push and pull projects to/from your Vigthoria Community Repository'
34
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'review' -d 'Review code quality'
35
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'security' -d 'Run security scans, scores, and fix plans via Vigthoria MCP security tools'
36
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'status' -d 'Show authentication and subscription status'
37
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'update' -d 'Check for updates and upgrade Vigthoria CLI. Default manifest: https://extension.vigthoria.io/downloads/manifest.json'
38
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'v4' -d 'Launch Vigthoria V4 Operating Agent (DeerFlow 2.0 harness)'
39
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'v4-menu' -d 'Internal: interactive V3/V4 agent + provider picker used by the V4 Operating Agent launcher'
40
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'wallet' -d 'Inspect monetary Vigthoria Credits used for Cloud, API, Video, and other PAYG services'
41
+ complete -c vigthoria -c vig -c vigthoria-chat -n '__fish_use_subcommand' -a 'workflow' -d 'List, instantiate, and run repeatable VigFlow workflows'
@@ -2,6 +2,7 @@ import { Command } from 'commander';
2
2
  export interface AuthConfig {
3
3
  apiUrl: string;
4
4
  token?: string;
5
+ refreshToken?: string;
5
6
  v3ServiceKey?: string;
6
7
  user?: {
7
8
  id?: string;
@@ -1,13 +1,11 @@
1
1
  import chalk from 'chalk';
2
- import { chmodSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'fs';
3
- import { homedir } from 'os';
4
- import path from 'path';
5
2
  import readline from 'readline';
6
3
  import { Config } from '../utils/config.js';
7
4
  import { clearGatewayPreflightCache } from '../utils/cli-state.js';
5
+ import { AuthSessionService } from '../utils/auth-session.js';
6
+ import { assertTrustedEndpoint, guardedFetch } from '../utils/network-policy.js';
7
+ import { CliCommandError, commandFailure } from '../utils/command-contract.js';
8
8
  const DEFAULT_API_URL = 'https://coder.vigthoria.io';
9
- const CONFIG_DIR = path.join(homedir(), '.vigthoria');
10
- const CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');
11
9
  const KNOWN_AUTH_BASE_URLS = ['https://coder.vigthoria.io'];
12
10
  class HttpError extends Error {
13
11
  status;
@@ -27,68 +25,13 @@ function uniqueStrings(values) {
27
25
  return [...new Set(values.filter(Boolean))];
28
26
  }
29
27
  function getApiUrl() {
30
- return trimTrailingSlash(process.env.VIGTHORIA_API_URL || DEFAULT_API_URL);
31
- }
32
- function derivePeerHost(baseUrl) {
33
- if (baseUrl.includes('://api.vigthoria.io')) {
34
- return baseUrl.replace('://api.vigthoria.io', '://coder.vigthoria.io');
35
- }
36
- if (baseUrl.includes('://coder.vigthoria.io')) {
37
- return baseUrl.replace('://coder.vigthoria.io', '://api.vigthoria.io');
38
- }
39
- return undefined;
28
+ const configured = trimTrailingSlash(process.env.VIGTHORIA_API_URL || DEFAULT_API_URL);
29
+ return trimTrailingSlash(assertTrustedEndpoint(configured, { audience: 'coder', credentialBearing: true, ignoreOffline: true }).toString());
40
30
  }
41
31
  function getAuthBaseCandidates(seedBaseUrl) {
42
32
  const seed = trimTrailingSlash(seedBaseUrl || getApiUrl());
43
- const peer = derivePeerHost(seed);
44
- return uniqueStrings([seed, ...(peer ? [peer] : []), ...KNOWN_AUTH_BASE_URLS]).map(trimTrailingSlash);
45
- }
46
- function ensureConfigDir() {
47
- if (!existsSync(CONFIG_DIR)) {
48
- mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
49
- }
50
- try {
51
- chmodSync(CONFIG_DIR, 0o700);
52
- }
53
- catch {
54
- // Best-effort on non-POSIX filesystems.
55
- }
56
- }
57
- function syncSharedConfig(config) {
58
- try {
59
- const shared = new Config();
60
- shared.set('apiUrl', trimTrailingSlash(config.apiUrl || getApiUrl()));
61
- if (config.token) {
62
- shared.set('authToken', config.token);
63
- }
64
- if (config.user?.id) {
65
- shared.set('userId', String(config.user.id));
66
- }
67
- if (config.user?.email) {
68
- shared.set('email', String(config.user.email));
69
- }
70
- // Always overwrite (never conditionally skip) so a fresh login can never
71
- // leave a stale/rotated key behind from a prior session — a falsy value
72
- // here explicitly clears the cache, forcing ensureV3ServiceKey() to fetch
73
- // a real one on next use instead of silently trusting stale state.
74
- shared.set('v3ServiceKey', config.v3ServiceKey || null);
75
- }
76
- catch {
77
- // Keep legacy auth flow working even if shared config write fails.
78
- }
79
- }
80
- function clearSharedConfigAuth() {
81
- try {
82
- const shared = new Config();
83
- shared.set('authToken', null);
84
- shared.set('refreshToken', null);
85
- shared.set('userId', null);
86
- shared.set('email', null);
87
- shared.set('v3ServiceKey', null);
88
- }
89
- catch {
90
- // Ignore shared config clear failures during logout.
91
- }
33
+ return uniqueStrings([seed, ...KNOWN_AUTH_BASE_URLS])
34
+ .map((candidate) => trimTrailingSlash(assertTrustedEndpoint(candidate, { audience: 'coder', credentialBearing: true, ignoreOffline: true }).toString()));
92
35
  }
93
36
  function humanMessage(error) {
94
37
  const raw = error instanceof Error ? error.message : String(error);
@@ -128,16 +71,17 @@ function extractAuthUser(payload, fallbackEmail) {
128
71
  return fallbackEmail ? { email: fallbackEmail } : undefined;
129
72
  }
130
73
  export function loadAuthConfig() {
131
- if (!existsSync(CONFIG_FILE)) {
132
- return { apiUrl: getApiUrl() };
133
- }
134
74
  try {
135
- const parsed = JSON.parse(readFileSync(CONFIG_FILE, 'utf8'));
75
+ const shared = new Config();
136
76
  return {
137
- apiUrl: trimTrailingSlash(parsed.apiUrl || getApiUrl()),
138
- token: parsed.token || parsed.authToken,
139
- v3ServiceKey: typeof parsed.v3ServiceKey === 'string' ? parsed.v3ServiceKey : undefined,
140
- user: parsed.user,
77
+ apiUrl: trimTrailingSlash(String(shared.get('apiUrl') || getApiUrl())),
78
+ token: shared.get('authToken') || undefined,
79
+ refreshToken: shared.get('refreshToken') || undefined,
80
+ v3ServiceKey: shared.get('v3ServiceKey') || undefined,
81
+ user: {
82
+ id: shared.get('userId') || undefined,
83
+ email: shared.get('email') || undefined,
84
+ },
141
85
  };
142
86
  }
143
87
  catch (error) {
@@ -146,25 +90,23 @@ export function loadAuthConfig() {
146
90
  }
147
91
  }
148
92
  export function saveAuthConfig(config) {
149
- ensureConfigDir();
150
- writeFileSync(CONFIG_FILE, `${JSON.stringify(config, null, 2)}\n`, 'utf8');
151
- try {
152
- chmodSync(CONFIG_FILE, 0o600);
153
- }
154
- catch {
155
- // Best-effort on non-POSIX filesystems.
156
- }
157
- syncSharedConfig(config);
93
+ if (!config.token)
94
+ throw new Error('Cannot persist an authentication record without a token.');
95
+ const shared = new Config();
96
+ shared.setAuth({
97
+ token: config.token,
98
+ refreshToken: config.refreshToken,
99
+ userId: config.user?.id,
100
+ email: config.user?.email,
101
+ apiUrl: trimTrailingSlash(config.apiUrl || getApiUrl()),
102
+ v3ServiceKey: config.v3ServiceKey || null,
103
+ });
158
104
  // A fresh login must never be blocked by a stale cached gateway-preflight
159
105
  // failure from a prior (invalid) session.
160
106
  clearGatewayPreflightCache();
161
107
  }
162
108
  export function clearAuthConfig() {
163
- if (existsSync(CONFIG_FILE)) {
164
- rmSync(CONFIG_FILE, { force: true });
165
- }
166
- clearSharedConfigAuth();
167
- clearGatewayPreflightCache();
109
+ new AuthSessionService(new Config()).clearLocalCredentials();
168
110
  }
169
111
  export function getAuthToken() {
170
112
  return process.env.VIGTHORIA_TOKEN || loadAuthConfig().token;
@@ -176,7 +118,7 @@ async function requestJson(url, init) {
176
118
  const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
177
119
  let response;
178
120
  try {
179
- response = await fetch(url, {
121
+ response = await guardedFetch(url, {
180
122
  ...init,
181
123
  signal: controller.signal,
182
124
  headers: {
@@ -184,7 +126,7 @@ async function requestJson(url, init) {
184
126
  'content-type': 'application/json',
185
127
  ...(init.headers || {}),
186
128
  },
187
- });
129
+ }, { audience: 'coder' });
188
130
  }
189
131
  catch (error) {
190
132
  const name = error?.name;
@@ -277,12 +219,6 @@ async function ask(question, hidden = false) {
277
219
  rl.close();
278
220
  }
279
221
  }
280
- function markSuccessExit() {
281
- process.exitCode = 0;
282
- }
283
- function markErrorExit() {
284
- process.exitCode = 1;
285
- }
286
222
  export async function login(email, password) {
287
223
  try {
288
224
  const resolvedEmail = (email || '').trim();
@@ -315,15 +251,22 @@ export async function login(email, password) {
315
251
  }
316
252
  const normalizedBase = trimTrailingSlash(base);
317
253
  const v3ServiceKey = await fetchV3ServiceKey(normalizedBase, token);
254
+ const identity = extractAuthUser(result, resolvedEmail);
255
+ const refreshToken = result.tokens?.refresh_token || undefined;
256
+ await new AuthSessionService(new Config()).validateAndPersistToken(token, {
257
+ apiUrl: normalizedBase,
258
+ refreshToken,
259
+ identity: { userId: identity?.id, email: identity?.email },
260
+ v3ServiceKey: v3ServiceKey || null,
261
+ });
318
262
  const config = {
319
263
  apiUrl: normalizedBase,
320
264
  token,
321
- user: extractAuthUser(result, resolvedEmail),
265
+ ...(refreshToken ? { refreshToken } : {}),
266
+ user: identity,
322
267
  ...(v3ServiceKey ? { v3ServiceKey } : {}),
323
268
  success: true,
324
269
  };
325
- saveAuthConfig(config);
326
- markSuccessExit();
327
270
  return config;
328
271
  }
329
272
  catch (error) {
@@ -339,8 +282,12 @@ export async function login(email, password) {
339
282
  }
340
283
  catch (error) {
341
284
  const message = humanMessage(error);
342
- markErrorExit();
343
- throw new Error(message);
285
+ if (error instanceof HttpError && error.code === 'SUBSCRIPTION_REQUIRED') {
286
+ throw new CliCommandError(message, {
287
+ code: 'SUBSCRIPTION_REQUIRED', category: 'authorization', status: error.status, cause: error,
288
+ });
289
+ }
290
+ throw commandFailure(error, { code: 'LOGIN_FAILED', category: 'authentication', message });
344
291
  }
345
292
  }
346
293
  export async function logout() {
@@ -372,7 +319,6 @@ export async function logout() {
372
319
  }
373
320
  }
374
321
  clearAuthConfig();
375
- process.exitCode = 0;
376
322
  }
377
323
  export async function whoami() {
378
324
  const config = loadAuthConfig();
@@ -424,32 +370,33 @@ export async function whoami() {
424
370
  }
425
371
  export async function doctor() {
426
372
  const config = loadAuthConfig();
373
+ const shared = new Config();
427
374
  const report = {
428
375
  nodeVersion: process.version,
429
376
  platform: process.platform,
430
377
  arch: process.arch,
431
- configFile: CONFIG_FILE,
378
+ configFile: shared.getConfigPath(),
432
379
  loggedIn: Boolean(config.token),
433
380
  apiUrl: config.apiUrl,
434
381
  };
435
- process.exitCode = 0;
436
382
  return report;
437
383
  }
438
384
  export async function handleLogin(options = {}) {
439
385
  try {
440
386
  if (options.token) {
387
+ const apiUrl = getApiUrl();
388
+ const v3ServiceKey = await fetchV3ServiceKey(apiUrl, options.token);
389
+ await new AuthSessionService(new Config()).validateAndPersistToken(options.token, {
390
+ apiUrl,
391
+ v3ServiceKey: v3ServiceKey || null,
392
+ });
441
393
  const config = {
442
- apiUrl: getApiUrl(),
394
+ apiUrl,
443
395
  token: options.token,
396
+ ...(v3ServiceKey ? { v3ServiceKey } : {}),
444
397
  success: true,
445
398
  };
446
- const v3ServiceKey = await fetchV3ServiceKey(config.apiUrl, options.token);
447
- if (v3ServiceKey) {
448
- config.v3ServiceKey = v3ServiceKey;
449
- }
450
- saveAuthConfig(config);
451
399
  console.log(chalk.green('Logged in successfully with API token.'));
452
- process.exitCode = 0;
453
400
  return config;
454
401
  }
455
402
  let email = options.email?.trim();
@@ -502,24 +449,19 @@ export async function handleLogin(options = {}) {
502
449
  }
503
450
  catch { /* non-fatal */ }
504
451
  console.log(`API: ${config.apiUrl}`);
505
- process.exitCode = 0;
506
452
  return config;
507
453
  }
508
454
  catch (error) {
509
- console.error(chalk.red(`Login failed: ${humanMessage(error)}`));
510
- process.exitCode = 1;
511
- return undefined;
455
+ throw commandFailure(error, { code: 'LOGIN_FAILED', category: 'authentication', message: humanMessage(error) });
512
456
  }
513
457
  }
514
458
  export async function handleLogout(_options) {
515
459
  try {
516
460
  await logout();
517
461
  console.log(chalk.green('Logged out successfully.'));
518
- process.exitCode = 0;
519
462
  }
520
463
  catch (error) {
521
- console.error(chalk.red(`Logout failed: ${humanMessage(error)}`));
522
- process.exitCode = 1;
464
+ throw commandFailure(error, { code: 'LOGOUT_FAILED', message: humanMessage(error) });
523
465
  }
524
466
  }
525
467
  export async function statusAction() {
@@ -532,7 +474,6 @@ export async function statusAction() {
532
474
  const effectiveToken = sharedToken || legacyConfig.token || '';
533
475
  if (!effectiveToken) {
534
476
  console.log(chalk.yellow('Not logged in.'));
535
- process.exitCode = 0;
536
477
  return;
537
478
  }
538
479
  const authProbeHeaders = {
@@ -550,10 +491,9 @@ export async function statusAction() {
550
491
  // Network failures should not force logout status.
551
492
  }
552
493
  if (!authLooksValid) {
553
- console.log(chalk.yellow('Not logged in. Session expired or invalid.'));
554
- console.log(chalk.gray('Run: vigthoria login'));
555
- process.exitCode = 1;
556
- return;
494
+ throw new CliCommandError('Not logged in. Session expired or invalid. Run: vigthoria login', {
495
+ code: 'AUTH_SESSION_INVALID', category: 'authentication',
496
+ });
557
497
  }
558
498
  let user = legacyConfig.user;
559
499
  try {
@@ -595,11 +535,9 @@ export async function statusAction() {
595
535
  console.log(`Coder API: ${coderStatus}`);
596
536
  console.log(`Models API: ${modelsStatus}`);
597
537
  console.log(`API: ${effectiveApiUrl}`);
598
- process.exitCode = 0;
599
538
  }
600
539
  catch (error) {
601
- console.error(chalk.red(`Unable to read status: ${humanMessage(error)}`));
602
- process.exitCode = 1;
540
+ throw commandFailure(error, { code: 'AUTH_STATUS_FAILED', message: humanMessage(error) });
603
541
  }
604
542
  }
605
543
  export function registerAuthCommands(program) {
@@ -628,16 +566,13 @@ export function registerAuthCommands(program) {
628
566
  const user = await whoami();
629
567
  if (!user) {
630
568
  console.log(chalk.yellow('Not logged in.'));
631
- process.exitCode = 0;
632
569
  return;
633
570
  }
634
571
  console.log(chalk.green('Logged in.'));
635
572
  console.log(user.email || user.name || user.id || 'Authenticated user');
636
- process.exitCode = 0;
637
573
  }
638
574
  catch (error) {
639
- console.error(chalk.red(`Unable to fetch account: ${humanMessage(error)}`));
640
- process.exitCode = 1;
575
+ throw commandFailure(error, { code: 'AUTH_WHOAMI_FAILED', message: humanMessage(error) });
641
576
  }
642
577
  });
643
578
  }
@@ -8,8 +8,6 @@ interface BackgroundOptions {
8
8
  model?: string;
9
9
  }
10
10
  export declare class BackgroundCommand {
11
- private config;
12
- private logger;
13
11
  private api;
14
12
  constructor(config: Config, logger: Logger);
15
13
  start(promptParts: string[], options?: BackgroundOptions): Promise<void>;