@build-astron-co/nimbus 0.2.0

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 (313) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +628 -0
  3. package/bin/nimbus +38 -0
  4. package/package.json +80 -0
  5. package/src/__tests__/app.test.ts +76 -0
  6. package/src/__tests__/audit.test.ts +877 -0
  7. package/src/__tests__/circuit-breaker.test.ts +116 -0
  8. package/src/__tests__/cli-run.test.ts +115 -0
  9. package/src/__tests__/context-manager.test.ts +502 -0
  10. package/src/__tests__/context.test.ts +242 -0
  11. package/src/__tests__/enterprise.test.ts +401 -0
  12. package/src/__tests__/generator.test.ts +433 -0
  13. package/src/__tests__/hooks.test.ts +582 -0
  14. package/src/__tests__/init.test.ts +436 -0
  15. package/src/__tests__/intent-parser.test.ts +229 -0
  16. package/src/__tests__/llm-router.test.ts +209 -0
  17. package/src/__tests__/lsp.test.ts +293 -0
  18. package/src/__tests__/modes.test.ts +336 -0
  19. package/src/__tests__/permissions.test.ts +338 -0
  20. package/src/__tests__/serve.test.ts +275 -0
  21. package/src/__tests__/sessions.test.ts +227 -0
  22. package/src/__tests__/sharing.test.ts +288 -0
  23. package/src/__tests__/snapshots.test.ts +581 -0
  24. package/src/__tests__/state-db.test.ts +334 -0
  25. package/src/__tests__/stream-with-tools.test.ts +732 -0
  26. package/src/__tests__/subagents.test.ts +176 -0
  27. package/src/__tests__/system-prompt.test.ts +169 -0
  28. package/src/__tests__/tool-converter.test.ts +256 -0
  29. package/src/__tests__/tool-schemas.test.ts +397 -0
  30. package/src/__tests__/tools.test.ts +143 -0
  31. package/src/__tests__/version.test.ts +49 -0
  32. package/src/agent/compaction-agent.ts +227 -0
  33. package/src/agent/context-manager.ts +435 -0
  34. package/src/agent/context.ts +427 -0
  35. package/src/agent/deploy-preview.ts +426 -0
  36. package/src/agent/index.ts +68 -0
  37. package/src/agent/loop.ts +717 -0
  38. package/src/agent/modes.ts +429 -0
  39. package/src/agent/permissions.ts +466 -0
  40. package/src/agent/subagents/base.ts +116 -0
  41. package/src/agent/subagents/cost.ts +51 -0
  42. package/src/agent/subagents/explore.ts +42 -0
  43. package/src/agent/subagents/general.ts +54 -0
  44. package/src/agent/subagents/index.ts +102 -0
  45. package/src/agent/subagents/infra.ts +59 -0
  46. package/src/agent/subagents/security.ts +69 -0
  47. package/src/agent/system-prompt.ts +436 -0
  48. package/src/app.ts +122 -0
  49. package/src/audit/activity-log.ts +290 -0
  50. package/src/audit/compliance-checker.ts +540 -0
  51. package/src/audit/cost-tracker.ts +318 -0
  52. package/src/audit/index.ts +23 -0
  53. package/src/audit/security-scanner.ts +596 -0
  54. package/src/auth/guard.ts +75 -0
  55. package/src/auth/index.ts +56 -0
  56. package/src/auth/oauth.ts +455 -0
  57. package/src/auth/providers.ts +470 -0
  58. package/src/auth/sso.ts +113 -0
  59. package/src/auth/store.ts +505 -0
  60. package/src/auth/types.ts +187 -0
  61. package/src/build.ts +141 -0
  62. package/src/cli/index.ts +16 -0
  63. package/src/cli/init.ts +854 -0
  64. package/src/cli/openapi-spec.ts +356 -0
  65. package/src/cli/run.ts +237 -0
  66. package/src/cli/serve-auth.ts +80 -0
  67. package/src/cli/serve.ts +462 -0
  68. package/src/cli/web.ts +67 -0
  69. package/src/cli.ts +1417 -0
  70. package/src/clients/core-engine-client.ts +227 -0
  71. package/src/clients/enterprise-client.ts +334 -0
  72. package/src/clients/generator-client.ts +351 -0
  73. package/src/clients/git-client.ts +627 -0
  74. package/src/clients/github-client.ts +410 -0
  75. package/src/clients/helm-client.ts +504 -0
  76. package/src/clients/index.ts +80 -0
  77. package/src/clients/k8s-client.ts +497 -0
  78. package/src/clients/llm-client.ts +161 -0
  79. package/src/clients/rest-client.ts +130 -0
  80. package/src/clients/service-discovery.ts +33 -0
  81. package/src/clients/terraform-client.ts +482 -0
  82. package/src/clients/tools-client.ts +1843 -0
  83. package/src/clients/ws-client.ts +115 -0
  84. package/src/commands/analyze/index.ts +352 -0
  85. package/src/commands/apply/helm.ts +473 -0
  86. package/src/commands/apply/index.ts +213 -0
  87. package/src/commands/apply/k8s.ts +454 -0
  88. package/src/commands/apply/terraform.ts +582 -0
  89. package/src/commands/ask.ts +167 -0
  90. package/src/commands/audit/index.ts +238 -0
  91. package/src/commands/auth-cloud.ts +294 -0
  92. package/src/commands/auth-list.ts +134 -0
  93. package/src/commands/auth-profile.ts +121 -0
  94. package/src/commands/auth-status.ts +141 -0
  95. package/src/commands/aws/ec2.ts +501 -0
  96. package/src/commands/aws/iam.ts +397 -0
  97. package/src/commands/aws/index.ts +133 -0
  98. package/src/commands/aws/lambda.ts +396 -0
  99. package/src/commands/aws/rds.ts +439 -0
  100. package/src/commands/aws/s3.ts +439 -0
  101. package/src/commands/aws/vpc.ts +393 -0
  102. package/src/commands/aws-discover.ts +649 -0
  103. package/src/commands/aws-terraform.ts +805 -0
  104. package/src/commands/azure/aks.ts +376 -0
  105. package/src/commands/azure/functions.ts +253 -0
  106. package/src/commands/azure/index.ts +116 -0
  107. package/src/commands/azure/storage.ts +478 -0
  108. package/src/commands/azure/vm.ts +355 -0
  109. package/src/commands/billing/index.ts +256 -0
  110. package/src/commands/chat.ts +314 -0
  111. package/src/commands/config.ts +346 -0
  112. package/src/commands/cost/cloud-cost-estimator.ts +266 -0
  113. package/src/commands/cost/estimator.ts +79 -0
  114. package/src/commands/cost/index.ts +594 -0
  115. package/src/commands/cost/parsers/terraform.ts +273 -0
  116. package/src/commands/cost/parsers/types.ts +25 -0
  117. package/src/commands/cost/pricing/aws.ts +544 -0
  118. package/src/commands/cost/pricing/azure.ts +499 -0
  119. package/src/commands/cost/pricing/gcp.ts +396 -0
  120. package/src/commands/cost/pricing/index.ts +40 -0
  121. package/src/commands/demo.ts +250 -0
  122. package/src/commands/doctor.ts +794 -0
  123. package/src/commands/drift/index.ts +439 -0
  124. package/src/commands/explain.ts +277 -0
  125. package/src/commands/feedback.ts +389 -0
  126. package/src/commands/fix.ts +324 -0
  127. package/src/commands/fs/index.ts +402 -0
  128. package/src/commands/gcp/compute.ts +325 -0
  129. package/src/commands/gcp/functions.ts +271 -0
  130. package/src/commands/gcp/gke.ts +438 -0
  131. package/src/commands/gcp/iam.ts +344 -0
  132. package/src/commands/gcp/index.ts +129 -0
  133. package/src/commands/gcp/storage.ts +284 -0
  134. package/src/commands/generate-helm.ts +1249 -0
  135. package/src/commands/generate-k8s.ts +1560 -0
  136. package/src/commands/generate-terraform.ts +1460 -0
  137. package/src/commands/gh/index.ts +863 -0
  138. package/src/commands/git/index.ts +1343 -0
  139. package/src/commands/helm/index.ts +1126 -0
  140. package/src/commands/help.ts +539 -0
  141. package/src/commands/history.ts +142 -0
  142. package/src/commands/import.ts +868 -0
  143. package/src/commands/index.ts +367 -0
  144. package/src/commands/init.ts +1046 -0
  145. package/src/commands/k8s/index.ts +1137 -0
  146. package/src/commands/login.ts +631 -0
  147. package/src/commands/logout.ts +83 -0
  148. package/src/commands/onboarding.ts +228 -0
  149. package/src/commands/plan/display.ts +279 -0
  150. package/src/commands/plan/index.ts +599 -0
  151. package/src/commands/preview.ts +452 -0
  152. package/src/commands/questionnaire.ts +1270 -0
  153. package/src/commands/resume.ts +55 -0
  154. package/src/commands/team/index.ts +346 -0
  155. package/src/commands/template.ts +232 -0
  156. package/src/commands/tf/index.ts +1034 -0
  157. package/src/commands/upgrade.ts +550 -0
  158. package/src/commands/usage/index.ts +134 -0
  159. package/src/commands/version.ts +170 -0
  160. package/src/compat/index.ts +2 -0
  161. package/src/compat/runtime.ts +12 -0
  162. package/src/compat/sqlite.ts +107 -0
  163. package/src/config/index.ts +17 -0
  164. package/src/config/manager.ts +530 -0
  165. package/src/config/safety-policy.ts +358 -0
  166. package/src/config/schema.ts +125 -0
  167. package/src/config/types.ts +527 -0
  168. package/src/context/context-db.ts +199 -0
  169. package/src/demo/index.ts +349 -0
  170. package/src/demo/scenarios/full-journey.ts +229 -0
  171. package/src/demo/scenarios/getting-started.ts +127 -0
  172. package/src/demo/scenarios/helm-release.ts +341 -0
  173. package/src/demo/scenarios/k8s-deployment.ts +194 -0
  174. package/src/demo/scenarios/terraform-vpc.ts +170 -0
  175. package/src/demo/types.ts +92 -0
  176. package/src/engine/cost-estimator.ts +438 -0
  177. package/src/engine/diagram-generator.ts +256 -0
  178. package/src/engine/drift-detector.ts +902 -0
  179. package/src/engine/executor.ts +1035 -0
  180. package/src/engine/index.ts +76 -0
  181. package/src/engine/orchestrator.ts +636 -0
  182. package/src/engine/planner.ts +720 -0
  183. package/src/engine/safety.ts +743 -0
  184. package/src/engine/verifier.ts +770 -0
  185. package/src/enterprise/audit.ts +348 -0
  186. package/src/enterprise/auth.ts +270 -0
  187. package/src/enterprise/billing.ts +822 -0
  188. package/src/enterprise/index.ts +17 -0
  189. package/src/enterprise/teams.ts +443 -0
  190. package/src/generator/best-practices.ts +1608 -0
  191. package/src/generator/helm.ts +630 -0
  192. package/src/generator/index.ts +37 -0
  193. package/src/generator/intent-parser.ts +514 -0
  194. package/src/generator/kubernetes.ts +976 -0
  195. package/src/generator/terraform.ts +1867 -0
  196. package/src/history/index.ts +8 -0
  197. package/src/history/manager.ts +322 -0
  198. package/src/history/types.ts +34 -0
  199. package/src/hooks/config.ts +432 -0
  200. package/src/hooks/engine.ts +391 -0
  201. package/src/hooks/index.ts +4 -0
  202. package/src/llm/auth-bridge.ts +198 -0
  203. package/src/llm/circuit-breaker.ts +140 -0
  204. package/src/llm/config-loader.ts +201 -0
  205. package/src/llm/cost-calculator.ts +171 -0
  206. package/src/llm/index.ts +8 -0
  207. package/src/llm/model-aliases.ts +115 -0
  208. package/src/llm/provider-registry.ts +63 -0
  209. package/src/llm/providers/anthropic.ts +433 -0
  210. package/src/llm/providers/bedrock.ts +477 -0
  211. package/src/llm/providers/google.ts +405 -0
  212. package/src/llm/providers/ollama.ts +767 -0
  213. package/src/llm/providers/openai-compatible.ts +340 -0
  214. package/src/llm/providers/openai.ts +328 -0
  215. package/src/llm/providers/openrouter.ts +338 -0
  216. package/src/llm/router.ts +1035 -0
  217. package/src/llm/types.ts +232 -0
  218. package/src/lsp/client.ts +298 -0
  219. package/src/lsp/languages.ts +116 -0
  220. package/src/lsp/manager.ts +278 -0
  221. package/src/mcp/client.ts +402 -0
  222. package/src/mcp/index.ts +5 -0
  223. package/src/mcp/manager.ts +133 -0
  224. package/src/nimbus.ts +214 -0
  225. package/src/plugins/index.ts +27 -0
  226. package/src/plugins/loader.ts +334 -0
  227. package/src/plugins/manager.ts +376 -0
  228. package/src/plugins/types.ts +284 -0
  229. package/src/scanners/cicd-scanner.ts +258 -0
  230. package/src/scanners/cloud-scanner.ts +466 -0
  231. package/src/scanners/framework-scanner.ts +469 -0
  232. package/src/scanners/iac-scanner.ts +388 -0
  233. package/src/scanners/index.ts +539 -0
  234. package/src/scanners/language-scanner.ts +276 -0
  235. package/src/scanners/package-manager-scanner.ts +277 -0
  236. package/src/scanners/types.ts +172 -0
  237. package/src/sessions/manager.ts +365 -0
  238. package/src/sessions/types.ts +44 -0
  239. package/src/sharing/sync.ts +296 -0
  240. package/src/sharing/viewer.ts +97 -0
  241. package/src/snapshots/index.ts +2 -0
  242. package/src/snapshots/manager.ts +530 -0
  243. package/src/state/artifacts.ts +147 -0
  244. package/src/state/audit.ts +137 -0
  245. package/src/state/billing.ts +240 -0
  246. package/src/state/checkpoints.ts +117 -0
  247. package/src/state/config.ts +67 -0
  248. package/src/state/conversations.ts +14 -0
  249. package/src/state/credentials.ts +154 -0
  250. package/src/state/db.ts +58 -0
  251. package/src/state/index.ts +26 -0
  252. package/src/state/messages.ts +115 -0
  253. package/src/state/projects.ts +123 -0
  254. package/src/state/schema.ts +236 -0
  255. package/src/state/sessions.ts +147 -0
  256. package/src/state/teams.ts +200 -0
  257. package/src/telemetry.ts +108 -0
  258. package/src/tools/aws-ops.ts +952 -0
  259. package/src/tools/azure-ops.ts +579 -0
  260. package/src/tools/file-ops.ts +593 -0
  261. package/src/tools/gcp-ops.ts +625 -0
  262. package/src/tools/git-ops.ts +773 -0
  263. package/src/tools/github-ops.ts +799 -0
  264. package/src/tools/helm-ops.ts +943 -0
  265. package/src/tools/index.ts +17 -0
  266. package/src/tools/k8s-ops.ts +819 -0
  267. package/src/tools/schemas/converter.ts +184 -0
  268. package/src/tools/schemas/devops.ts +612 -0
  269. package/src/tools/schemas/index.ts +73 -0
  270. package/src/tools/schemas/standard.ts +1144 -0
  271. package/src/tools/schemas/types.ts +705 -0
  272. package/src/tools/terraform-ops.ts +862 -0
  273. package/src/types/ambient.d.ts +193 -0
  274. package/src/types/config.ts +83 -0
  275. package/src/types/drift.ts +116 -0
  276. package/src/types/enterprise.ts +335 -0
  277. package/src/types/index.ts +20 -0
  278. package/src/types/plan.ts +44 -0
  279. package/src/types/request.ts +65 -0
  280. package/src/types/response.ts +54 -0
  281. package/src/types/service.ts +51 -0
  282. package/src/ui/App.tsx +997 -0
  283. package/src/ui/DeployPreview.tsx +169 -0
  284. package/src/ui/Header.tsx +68 -0
  285. package/src/ui/InputBox.tsx +350 -0
  286. package/src/ui/MessageList.tsx +585 -0
  287. package/src/ui/PermissionPrompt.tsx +151 -0
  288. package/src/ui/StatusBar.tsx +158 -0
  289. package/src/ui/ToolCallDisplay.tsx +409 -0
  290. package/src/ui/chat-ui.ts +853 -0
  291. package/src/ui/index.ts +33 -0
  292. package/src/ui/ink/index.ts +711 -0
  293. package/src/ui/streaming.ts +176 -0
  294. package/src/ui/types.ts +57 -0
  295. package/src/utils/analytics.ts +72 -0
  296. package/src/utils/cost-warning.ts +27 -0
  297. package/src/utils/env.ts +46 -0
  298. package/src/utils/errors.ts +69 -0
  299. package/src/utils/event-bus.ts +38 -0
  300. package/src/utils/index.ts +24 -0
  301. package/src/utils/logger.ts +171 -0
  302. package/src/utils/rate-limiter.ts +121 -0
  303. package/src/utils/service-auth.ts +49 -0
  304. package/src/utils/validation.ts +53 -0
  305. package/src/version.ts +4 -0
  306. package/src/watcher/index.ts +163 -0
  307. package/src/wizard/approval.ts +383 -0
  308. package/src/wizard/index.ts +25 -0
  309. package/src/wizard/prompts.ts +338 -0
  310. package/src/wizard/types.ts +171 -0
  311. package/src/wizard/ui.ts +556 -0
  312. package/src/wizard/wizard.ts +304 -0
  313. package/tsconfig.json +24 -0
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Auth List Command
3
+ *
4
+ * Display all available providers and their configuration status
5
+ *
6
+ * Usage: nimbus auth list
7
+ */
8
+
9
+ import { logger } from '../utils';
10
+ import { ui } from '../wizard';
11
+ import { authStore, AuthStore, getProviderNames, getProviderInfo } from '../auth';
12
+
13
+ /**
14
+ * Command options
15
+ */
16
+ export interface AuthListOptions {
17
+ json?: boolean;
18
+ }
19
+
20
+ /**
21
+ * Run the auth list command
22
+ */
23
+ export async function authListCommand(options: AuthListOptions = {}): Promise<void> {
24
+ logger.info('Listing auth providers');
25
+
26
+ const providerNames = getProviderNames();
27
+ const status = authStore.getStatus();
28
+ const configuredProviders = new Set(status.providers.map(p => p.name));
29
+
30
+ // Build provider data
31
+ const providerData = providerNames.map(name => {
32
+ const info = getProviderInfo(name);
33
+ const credential = authStore.getProvider(name);
34
+ const isConfigured = configuredProviders.has(name);
35
+ const isDefault = status.defaultProvider === name;
36
+
37
+ return {
38
+ name,
39
+ displayName: info.displayName,
40
+ description: info.description,
41
+ isConfigured,
42
+ isDefault,
43
+ model: credential?.model || info.models.find(m => m.isDefault)?.id || info.models[0].id,
44
+ apiKey: credential?.apiKey,
45
+ baseUrl: credential?.baseUrl,
46
+ requiresApiKey: info.requiresApiKey,
47
+ apiKeyUrl: info.apiKeyUrl,
48
+ };
49
+ });
50
+
51
+ // JSON output mode
52
+ if (options.json) {
53
+ const safeOutput = providerData.map(p => ({
54
+ name: p.name,
55
+ displayName: p.displayName,
56
+ description: p.description,
57
+ isConfigured: p.isConfigured,
58
+ isDefault: p.isDefault,
59
+ model: p.model,
60
+ apiKey: p.apiKey ? AuthStore.maskApiKey(p.apiKey) : null,
61
+ baseUrl: p.baseUrl,
62
+ requiresApiKey: p.requiresApiKey,
63
+ }));
64
+
65
+ // Output sanitized JSON (API keys are already masked above)
66
+ ui.print(JSON.stringify(safeOutput, null, 2));
67
+ return;
68
+ }
69
+
70
+ // Human-readable table output
71
+ ui.newLine();
72
+ ui.section('LLM Providers');
73
+
74
+ // Build table data
75
+ const tableData: Array<Record<string, string>> = [];
76
+
77
+ for (const provider of providerData) {
78
+ const statusIcon = provider.isConfigured ? ui.color('✓', 'green') : ui.dim('—');
79
+ const statusText = provider.isConfigured ? 'Configured' : 'Not configured';
80
+
81
+ let apiKeyDisplay: string;
82
+ if (provider.isConfigured && provider.apiKey) {
83
+ apiKeyDisplay = AuthStore.maskApiKey(provider.apiKey);
84
+ } else if (!provider.requiresApiKey) {
85
+ apiKeyDisplay = ui.dim('(not needed)');
86
+ } else if (provider.isConfigured) {
87
+ apiKeyDisplay = ui.dim('(from env)');
88
+ } else {
89
+ apiKeyDisplay = ui.dim('—');
90
+ }
91
+
92
+ const modelDisplay = provider.isConfigured ? provider.model : ui.dim(provider.model);
93
+ const defaultDisplay = provider.isDefault ? ui.color('★', 'yellow') : '';
94
+
95
+ tableData.push({
96
+ provider: `${statusIcon} ${provider.displayName}`,
97
+ status: statusText,
98
+ apiKey: apiKeyDisplay,
99
+ model: modelDisplay,
100
+ default: defaultDisplay,
101
+ });
102
+ }
103
+
104
+ // Display table
105
+ ui.table({
106
+ columns: [
107
+ { key: 'provider', header: 'Provider', width: 25 },
108
+ { key: 'status', header: 'Status', width: 15 },
109
+ { key: 'apiKey', header: 'API Key', width: 20 },
110
+ { key: 'model', header: 'Model', width: 30 },
111
+ { key: 'default', header: 'Default', width: 8 },
112
+ ],
113
+ data: tableData,
114
+ });
115
+
116
+ ui.newLine();
117
+
118
+ // Show hints for unconfigured providers
119
+ const unconfigured = providerData.filter(p => !p.isConfigured);
120
+ if (unconfigured.length > 0) {
121
+ ui.print(ui.dim('To configure a provider, run `nimbus login`'));
122
+ ui.newLine();
123
+
124
+ ui.print(ui.dim('API key URLs:'));
125
+ for (const provider of unconfigured) {
126
+ if (provider.apiKeyUrl) {
127
+ ui.print(ui.dim(` ${provider.displayName}: ${provider.apiKeyUrl}`));
128
+ }
129
+ }
130
+ ui.newLine();
131
+ }
132
+ }
133
+
134
+ export default authListCommand;
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Auth Profile Commands
3
+ *
4
+ * CLI commands for managing authentication profiles and switching providers
5
+ */
6
+
7
+ import { AuthStore } from '../auth/store';
8
+ import { ui } from '../wizard/ui';
9
+
10
+ /**
11
+ * List all configured providers
12
+ */
13
+ async function authProfileListCommand(): Promise<void> {
14
+ ui.header('Auth Profiles');
15
+
16
+ const authStore = new AuthStore();
17
+ const status = authStore.getStatus();
18
+
19
+ if (!status.hasProviders) {
20
+ ui.warning('No providers configured. Run "nimbus login" to set up authentication.');
21
+ return;
22
+ }
23
+
24
+ ui.table({
25
+ columns: [
26
+ { key: 'name', header: 'Provider' },
27
+ { key: 'model', header: 'Model' },
28
+ { key: 'default', header: 'Default' },
29
+ { key: 'validatedAt', header: 'Validated' },
30
+ ],
31
+ data: status.providers.map(p => ({
32
+ name: p.name,
33
+ model: p.model || '-',
34
+ default: p.isDefault ? 'Yes' : '',
35
+ validatedAt: p.validatedAt ? new Date(p.validatedAt).toLocaleDateString() : '-',
36
+ })),
37
+ });
38
+ }
39
+
40
+ /**
41
+ * Show the current default provider
42
+ */
43
+ async function authProfileShowCommand(): Promise<void> {
44
+ ui.header('Current Auth Profile');
45
+
46
+ const authStore = new AuthStore();
47
+ const defaultProvider = authStore.getDefaultProvider();
48
+
49
+ if (!defaultProvider) {
50
+ ui.warning('No default provider set. Run "nimbus login" to configure.');
51
+ return;
52
+ }
53
+
54
+ const status = authStore.getStatus();
55
+ const providerInfo = status.providers.find(p => p.name === defaultProvider);
56
+
57
+ ui.print(` ${ui.color('Provider:', 'cyan')} ${defaultProvider}`);
58
+ if (providerInfo) {
59
+ ui.print(` ${ui.color('Model:', 'cyan')} ${providerInfo.model || '-'}`);
60
+ ui.print(
61
+ ` ${ui.color('Validated:', 'cyan')} ${providerInfo.validatedAt ? new Date(providerInfo.validatedAt).toLocaleDateString() : '-'}`
62
+ );
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Switch the default provider
68
+ */
69
+ async function authProfileSwitchCommand(provider: string): Promise<void> {
70
+ ui.header(`Switch Auth Profile`);
71
+
72
+ const authStore = new AuthStore();
73
+
74
+ try {
75
+ authStore.setDefaultProvider(provider as any);
76
+ ui.success(`Default provider switched to "${provider}"`);
77
+ ui.info(`Persisted to ${authStore.getAuthPath()}`);
78
+ } catch (error: any) {
79
+ ui.error(error.message);
80
+ ui.info('Available providers:');
81
+ const status = authStore.getStatus();
82
+ status.providers.forEach(p => {
83
+ ui.print(` - ${p.name}${p.isDefault ? ' (current default)' : ''}`);
84
+ });
85
+ }
86
+ }
87
+
88
+ /**
89
+ * Main auth-profile command router
90
+ */
91
+ export async function authProfileCommand(subcommand: string, args: string[]): Promise<void> {
92
+ const positionalArgs: string[] = [];
93
+
94
+ for (let i = 0; i < args.length; i++) {
95
+ const arg = args[i];
96
+ if (!arg.startsWith('-')) {
97
+ positionalArgs.push(arg);
98
+ }
99
+ }
100
+
101
+ switch (subcommand) {
102
+ case 'list':
103
+ case 'ls':
104
+ await authProfileListCommand();
105
+ break;
106
+ case 'show':
107
+ await authProfileShowCommand();
108
+ break;
109
+ case 'switch':
110
+ if (positionalArgs.length < 1) {
111
+ ui.error('Usage: nimbus auth-profile switch <provider>');
112
+ ui.info('Example: nimbus auth-profile switch openai');
113
+ return;
114
+ }
115
+ await authProfileSwitchCommand(positionalArgs[0]);
116
+ break;
117
+ default:
118
+ ui.error(`Unknown auth-profile subcommand: ${subcommand || '(none)'}`);
119
+ ui.info('Available commands: list, show, switch <provider>');
120
+ }
121
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Auth Status Command
3
+ *
4
+ * Display current authentication status
5
+ *
6
+ * Usage: nimbus auth status
7
+ */
8
+
9
+ import { logger } from '../utils';
10
+ import { ui } from '../wizard';
11
+ import { authStore, AuthStore, getProviderInfo } from '../auth';
12
+
13
+ /**
14
+ * Command options
15
+ */
16
+ export interface AuthStatusOptions {
17
+ json?: boolean;
18
+ }
19
+
20
+ /**
21
+ * Run the auth status command
22
+ */
23
+ export async function authStatusCommand(options: AuthStatusOptions = {}): Promise<void> {
24
+ logger.info('Checking auth status');
25
+
26
+ const status = authStore.getStatus();
27
+
28
+ // JSON output mode
29
+ if (options.json) {
30
+ // Build safe JSON output (no raw API keys)
31
+ const safeOutput = {
32
+ isConfigured: status.isConfigured,
33
+ identity: status.identity
34
+ ? {
35
+ provider: status.identity.provider,
36
+ username: status.identity.username,
37
+ name: status.identity.name,
38
+ authenticatedAt: status.identity.authenticatedAt,
39
+ }
40
+ : null,
41
+ providers: status.providers.map(p => ({
42
+ name: p.name,
43
+ model: p.model,
44
+ isDefault: p.isDefault,
45
+ validatedAt: p.validatedAt,
46
+ })),
47
+ defaultProvider: status.defaultProvider,
48
+ };
49
+
50
+ // Output sanitized JSON (no sensitive data included)
51
+ ui.print(JSON.stringify(safeOutput, null, 2));
52
+ return;
53
+ }
54
+
55
+ // Human-readable output
56
+ ui.newLine();
57
+ ui.section('Authentication Status');
58
+
59
+ // Overall status
60
+ if (status.isConfigured) {
61
+ ui.success('Nimbus is configured and ready to use');
62
+ } else {
63
+ ui.warning('Nimbus is not configured. Run `nimbus login` to get started.');
64
+ }
65
+ ui.newLine();
66
+
67
+ // Identity section
68
+ ui.print(ui.bold('Identity'));
69
+
70
+ if (status.identity) {
71
+ const identity = status.identity;
72
+ ui.print(` Provider: GitHub`);
73
+ ui.print(` Username: ${identity.username}`);
74
+ if (identity.name) {
75
+ ui.print(` Name: ${identity.name}`);
76
+ }
77
+ ui.print(` Signed in: ${formatDate(identity.authenticatedAt)}`);
78
+ } else {
79
+ ui.print(ui.dim(' Not signed in'));
80
+ ui.print(ui.dim(' Run `nimbus login` to sign in with GitHub'));
81
+ }
82
+ ui.newLine();
83
+
84
+ // Providers section
85
+ ui.print(ui.bold('LLM Providers'));
86
+
87
+ if (status.providers.length > 0) {
88
+ for (const provider of status.providers) {
89
+ const info = getProviderInfo(provider.name);
90
+ const defaultMarker = provider.isDefault ? ui.color(' (default)', 'green') : '';
91
+
92
+ ui.print(` ${info.displayName}${defaultMarker}`);
93
+ ui.print(` Model: ${provider.model}`);
94
+
95
+ // Get the actual credential to show masked key
96
+ const credential = authStore.getProvider(provider.name);
97
+ if (credential?.apiKey) {
98
+ ui.print(` API Key: ${AuthStore.maskApiKey(credential.apiKey)}`);
99
+ } else if (!info.requiresApiKey) {
100
+ ui.print(` API Key: ${ui.dim('(not required)')}`);
101
+ } else {
102
+ ui.print(` API Key: ${ui.dim('(from environment)')}`);
103
+ }
104
+
105
+ if (credential?.baseUrl) {
106
+ ui.print(` Base URL: ${credential.baseUrl}`);
107
+ }
108
+
109
+ if (provider.validatedAt) {
110
+ ui.print(` Validated: ${formatDate(provider.validatedAt)}`);
111
+ }
112
+ ui.newLine();
113
+ }
114
+ } else {
115
+ ui.print(ui.dim(' No providers configured'));
116
+ ui.print(ui.dim(' Run `nimbus login` to configure LLM providers'));
117
+ ui.newLine();
118
+ }
119
+
120
+ // Auth file location
121
+ ui.print(ui.dim(`Config: ${authStore.getAuthPath()}`));
122
+ ui.newLine();
123
+ }
124
+
125
+ /**
126
+ * Format ISO date string for display
127
+ */
128
+ function formatDate(isoString: string): string {
129
+ try {
130
+ const date = new Date(isoString);
131
+ // Check if date is valid (NaN check)
132
+ if (isNaN(date.getTime())) {
133
+ return isoString;
134
+ }
135
+ return date.toLocaleString();
136
+ } catch {
137
+ return isoString;
138
+ }
139
+ }
140
+
141
+ export default authStatusCommand;