@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.
- package/LICENSE +21 -0
- package/README.md +628 -0
- package/bin/nimbus +38 -0
- package/package.json +80 -0
- package/src/__tests__/app.test.ts +76 -0
- package/src/__tests__/audit.test.ts +877 -0
- package/src/__tests__/circuit-breaker.test.ts +116 -0
- package/src/__tests__/cli-run.test.ts +115 -0
- package/src/__tests__/context-manager.test.ts +502 -0
- package/src/__tests__/context.test.ts +242 -0
- package/src/__tests__/enterprise.test.ts +401 -0
- package/src/__tests__/generator.test.ts +433 -0
- package/src/__tests__/hooks.test.ts +582 -0
- package/src/__tests__/init.test.ts +436 -0
- package/src/__tests__/intent-parser.test.ts +229 -0
- package/src/__tests__/llm-router.test.ts +209 -0
- package/src/__tests__/lsp.test.ts +293 -0
- package/src/__tests__/modes.test.ts +336 -0
- package/src/__tests__/permissions.test.ts +338 -0
- package/src/__tests__/serve.test.ts +275 -0
- package/src/__tests__/sessions.test.ts +227 -0
- package/src/__tests__/sharing.test.ts +288 -0
- package/src/__tests__/snapshots.test.ts +581 -0
- package/src/__tests__/state-db.test.ts +334 -0
- package/src/__tests__/stream-with-tools.test.ts +732 -0
- package/src/__tests__/subagents.test.ts +176 -0
- package/src/__tests__/system-prompt.test.ts +169 -0
- package/src/__tests__/tool-converter.test.ts +256 -0
- package/src/__tests__/tool-schemas.test.ts +397 -0
- package/src/__tests__/tools.test.ts +143 -0
- package/src/__tests__/version.test.ts +49 -0
- package/src/agent/compaction-agent.ts +227 -0
- package/src/agent/context-manager.ts +435 -0
- package/src/agent/context.ts +427 -0
- package/src/agent/deploy-preview.ts +426 -0
- package/src/agent/index.ts +68 -0
- package/src/agent/loop.ts +717 -0
- package/src/agent/modes.ts +429 -0
- package/src/agent/permissions.ts +466 -0
- package/src/agent/subagents/base.ts +116 -0
- package/src/agent/subagents/cost.ts +51 -0
- package/src/agent/subagents/explore.ts +42 -0
- package/src/agent/subagents/general.ts +54 -0
- package/src/agent/subagents/index.ts +102 -0
- package/src/agent/subagents/infra.ts +59 -0
- package/src/agent/subagents/security.ts +69 -0
- package/src/agent/system-prompt.ts +436 -0
- package/src/app.ts +122 -0
- package/src/audit/activity-log.ts +290 -0
- package/src/audit/compliance-checker.ts +540 -0
- package/src/audit/cost-tracker.ts +318 -0
- package/src/audit/index.ts +23 -0
- package/src/audit/security-scanner.ts +596 -0
- package/src/auth/guard.ts +75 -0
- package/src/auth/index.ts +56 -0
- package/src/auth/oauth.ts +455 -0
- package/src/auth/providers.ts +470 -0
- package/src/auth/sso.ts +113 -0
- package/src/auth/store.ts +505 -0
- package/src/auth/types.ts +187 -0
- package/src/build.ts +141 -0
- package/src/cli/index.ts +16 -0
- package/src/cli/init.ts +854 -0
- package/src/cli/openapi-spec.ts +356 -0
- package/src/cli/run.ts +237 -0
- package/src/cli/serve-auth.ts +80 -0
- package/src/cli/serve.ts +462 -0
- package/src/cli/web.ts +67 -0
- package/src/cli.ts +1417 -0
- package/src/clients/core-engine-client.ts +227 -0
- package/src/clients/enterprise-client.ts +334 -0
- package/src/clients/generator-client.ts +351 -0
- package/src/clients/git-client.ts +627 -0
- package/src/clients/github-client.ts +410 -0
- package/src/clients/helm-client.ts +504 -0
- package/src/clients/index.ts +80 -0
- package/src/clients/k8s-client.ts +497 -0
- package/src/clients/llm-client.ts +161 -0
- package/src/clients/rest-client.ts +130 -0
- package/src/clients/service-discovery.ts +33 -0
- package/src/clients/terraform-client.ts +482 -0
- package/src/clients/tools-client.ts +1843 -0
- package/src/clients/ws-client.ts +115 -0
- package/src/commands/analyze/index.ts +352 -0
- package/src/commands/apply/helm.ts +473 -0
- package/src/commands/apply/index.ts +213 -0
- package/src/commands/apply/k8s.ts +454 -0
- package/src/commands/apply/terraform.ts +582 -0
- package/src/commands/ask.ts +167 -0
- package/src/commands/audit/index.ts +238 -0
- package/src/commands/auth-cloud.ts +294 -0
- package/src/commands/auth-list.ts +134 -0
- package/src/commands/auth-profile.ts +121 -0
- package/src/commands/auth-status.ts +141 -0
- package/src/commands/aws/ec2.ts +501 -0
- package/src/commands/aws/iam.ts +397 -0
- package/src/commands/aws/index.ts +133 -0
- package/src/commands/aws/lambda.ts +396 -0
- package/src/commands/aws/rds.ts +439 -0
- package/src/commands/aws/s3.ts +439 -0
- package/src/commands/aws/vpc.ts +393 -0
- package/src/commands/aws-discover.ts +649 -0
- package/src/commands/aws-terraform.ts +805 -0
- package/src/commands/azure/aks.ts +376 -0
- package/src/commands/azure/functions.ts +253 -0
- package/src/commands/azure/index.ts +116 -0
- package/src/commands/azure/storage.ts +478 -0
- package/src/commands/azure/vm.ts +355 -0
- package/src/commands/billing/index.ts +256 -0
- package/src/commands/chat.ts +314 -0
- package/src/commands/config.ts +346 -0
- package/src/commands/cost/cloud-cost-estimator.ts +266 -0
- package/src/commands/cost/estimator.ts +79 -0
- package/src/commands/cost/index.ts +594 -0
- package/src/commands/cost/parsers/terraform.ts +273 -0
- package/src/commands/cost/parsers/types.ts +25 -0
- package/src/commands/cost/pricing/aws.ts +544 -0
- package/src/commands/cost/pricing/azure.ts +499 -0
- package/src/commands/cost/pricing/gcp.ts +396 -0
- package/src/commands/cost/pricing/index.ts +40 -0
- package/src/commands/demo.ts +250 -0
- package/src/commands/doctor.ts +794 -0
- package/src/commands/drift/index.ts +439 -0
- package/src/commands/explain.ts +277 -0
- package/src/commands/feedback.ts +389 -0
- package/src/commands/fix.ts +324 -0
- package/src/commands/fs/index.ts +402 -0
- package/src/commands/gcp/compute.ts +325 -0
- package/src/commands/gcp/functions.ts +271 -0
- package/src/commands/gcp/gke.ts +438 -0
- package/src/commands/gcp/iam.ts +344 -0
- package/src/commands/gcp/index.ts +129 -0
- package/src/commands/gcp/storage.ts +284 -0
- package/src/commands/generate-helm.ts +1249 -0
- package/src/commands/generate-k8s.ts +1560 -0
- package/src/commands/generate-terraform.ts +1460 -0
- package/src/commands/gh/index.ts +863 -0
- package/src/commands/git/index.ts +1343 -0
- package/src/commands/helm/index.ts +1126 -0
- package/src/commands/help.ts +539 -0
- package/src/commands/history.ts +142 -0
- package/src/commands/import.ts +868 -0
- package/src/commands/index.ts +367 -0
- package/src/commands/init.ts +1046 -0
- package/src/commands/k8s/index.ts +1137 -0
- package/src/commands/login.ts +631 -0
- package/src/commands/logout.ts +83 -0
- package/src/commands/onboarding.ts +228 -0
- package/src/commands/plan/display.ts +279 -0
- package/src/commands/plan/index.ts +599 -0
- package/src/commands/preview.ts +452 -0
- package/src/commands/questionnaire.ts +1270 -0
- package/src/commands/resume.ts +55 -0
- package/src/commands/team/index.ts +346 -0
- package/src/commands/template.ts +232 -0
- package/src/commands/tf/index.ts +1034 -0
- package/src/commands/upgrade.ts +550 -0
- package/src/commands/usage/index.ts +134 -0
- package/src/commands/version.ts +170 -0
- package/src/compat/index.ts +2 -0
- package/src/compat/runtime.ts +12 -0
- package/src/compat/sqlite.ts +107 -0
- package/src/config/index.ts +17 -0
- package/src/config/manager.ts +530 -0
- package/src/config/safety-policy.ts +358 -0
- package/src/config/schema.ts +125 -0
- package/src/config/types.ts +527 -0
- package/src/context/context-db.ts +199 -0
- package/src/demo/index.ts +349 -0
- package/src/demo/scenarios/full-journey.ts +229 -0
- package/src/demo/scenarios/getting-started.ts +127 -0
- package/src/demo/scenarios/helm-release.ts +341 -0
- package/src/demo/scenarios/k8s-deployment.ts +194 -0
- package/src/demo/scenarios/terraform-vpc.ts +170 -0
- package/src/demo/types.ts +92 -0
- package/src/engine/cost-estimator.ts +438 -0
- package/src/engine/diagram-generator.ts +256 -0
- package/src/engine/drift-detector.ts +902 -0
- package/src/engine/executor.ts +1035 -0
- package/src/engine/index.ts +76 -0
- package/src/engine/orchestrator.ts +636 -0
- package/src/engine/planner.ts +720 -0
- package/src/engine/safety.ts +743 -0
- package/src/engine/verifier.ts +770 -0
- package/src/enterprise/audit.ts +348 -0
- package/src/enterprise/auth.ts +270 -0
- package/src/enterprise/billing.ts +822 -0
- package/src/enterprise/index.ts +17 -0
- package/src/enterprise/teams.ts +443 -0
- package/src/generator/best-practices.ts +1608 -0
- package/src/generator/helm.ts +630 -0
- package/src/generator/index.ts +37 -0
- package/src/generator/intent-parser.ts +514 -0
- package/src/generator/kubernetes.ts +976 -0
- package/src/generator/terraform.ts +1867 -0
- package/src/history/index.ts +8 -0
- package/src/history/manager.ts +322 -0
- package/src/history/types.ts +34 -0
- package/src/hooks/config.ts +432 -0
- package/src/hooks/engine.ts +391 -0
- package/src/hooks/index.ts +4 -0
- package/src/llm/auth-bridge.ts +198 -0
- package/src/llm/circuit-breaker.ts +140 -0
- package/src/llm/config-loader.ts +201 -0
- package/src/llm/cost-calculator.ts +171 -0
- package/src/llm/index.ts +8 -0
- package/src/llm/model-aliases.ts +115 -0
- package/src/llm/provider-registry.ts +63 -0
- package/src/llm/providers/anthropic.ts +433 -0
- package/src/llm/providers/bedrock.ts +477 -0
- package/src/llm/providers/google.ts +405 -0
- package/src/llm/providers/ollama.ts +767 -0
- package/src/llm/providers/openai-compatible.ts +340 -0
- package/src/llm/providers/openai.ts +328 -0
- package/src/llm/providers/openrouter.ts +338 -0
- package/src/llm/router.ts +1035 -0
- package/src/llm/types.ts +232 -0
- package/src/lsp/client.ts +298 -0
- package/src/lsp/languages.ts +116 -0
- package/src/lsp/manager.ts +278 -0
- package/src/mcp/client.ts +402 -0
- package/src/mcp/index.ts +5 -0
- package/src/mcp/manager.ts +133 -0
- package/src/nimbus.ts +214 -0
- package/src/plugins/index.ts +27 -0
- package/src/plugins/loader.ts +334 -0
- package/src/plugins/manager.ts +376 -0
- package/src/plugins/types.ts +284 -0
- package/src/scanners/cicd-scanner.ts +258 -0
- package/src/scanners/cloud-scanner.ts +466 -0
- package/src/scanners/framework-scanner.ts +469 -0
- package/src/scanners/iac-scanner.ts +388 -0
- package/src/scanners/index.ts +539 -0
- package/src/scanners/language-scanner.ts +276 -0
- package/src/scanners/package-manager-scanner.ts +277 -0
- package/src/scanners/types.ts +172 -0
- package/src/sessions/manager.ts +365 -0
- package/src/sessions/types.ts +44 -0
- package/src/sharing/sync.ts +296 -0
- package/src/sharing/viewer.ts +97 -0
- package/src/snapshots/index.ts +2 -0
- package/src/snapshots/manager.ts +530 -0
- package/src/state/artifacts.ts +147 -0
- package/src/state/audit.ts +137 -0
- package/src/state/billing.ts +240 -0
- package/src/state/checkpoints.ts +117 -0
- package/src/state/config.ts +67 -0
- package/src/state/conversations.ts +14 -0
- package/src/state/credentials.ts +154 -0
- package/src/state/db.ts +58 -0
- package/src/state/index.ts +26 -0
- package/src/state/messages.ts +115 -0
- package/src/state/projects.ts +123 -0
- package/src/state/schema.ts +236 -0
- package/src/state/sessions.ts +147 -0
- package/src/state/teams.ts +200 -0
- package/src/telemetry.ts +108 -0
- package/src/tools/aws-ops.ts +952 -0
- package/src/tools/azure-ops.ts +579 -0
- package/src/tools/file-ops.ts +593 -0
- package/src/tools/gcp-ops.ts +625 -0
- package/src/tools/git-ops.ts +773 -0
- package/src/tools/github-ops.ts +799 -0
- package/src/tools/helm-ops.ts +943 -0
- package/src/tools/index.ts +17 -0
- package/src/tools/k8s-ops.ts +819 -0
- package/src/tools/schemas/converter.ts +184 -0
- package/src/tools/schemas/devops.ts +612 -0
- package/src/tools/schemas/index.ts +73 -0
- package/src/tools/schemas/standard.ts +1144 -0
- package/src/tools/schemas/types.ts +705 -0
- package/src/tools/terraform-ops.ts +862 -0
- package/src/types/ambient.d.ts +193 -0
- package/src/types/config.ts +83 -0
- package/src/types/drift.ts +116 -0
- package/src/types/enterprise.ts +335 -0
- package/src/types/index.ts +20 -0
- package/src/types/plan.ts +44 -0
- package/src/types/request.ts +65 -0
- package/src/types/response.ts +54 -0
- package/src/types/service.ts +51 -0
- package/src/ui/App.tsx +997 -0
- package/src/ui/DeployPreview.tsx +169 -0
- package/src/ui/Header.tsx +68 -0
- package/src/ui/InputBox.tsx +350 -0
- package/src/ui/MessageList.tsx +585 -0
- package/src/ui/PermissionPrompt.tsx +151 -0
- package/src/ui/StatusBar.tsx +158 -0
- package/src/ui/ToolCallDisplay.tsx +409 -0
- package/src/ui/chat-ui.ts +853 -0
- package/src/ui/index.ts +33 -0
- package/src/ui/ink/index.ts +711 -0
- package/src/ui/streaming.ts +176 -0
- package/src/ui/types.ts +57 -0
- package/src/utils/analytics.ts +72 -0
- package/src/utils/cost-warning.ts +27 -0
- package/src/utils/env.ts +46 -0
- package/src/utils/errors.ts +69 -0
- package/src/utils/event-bus.ts +38 -0
- package/src/utils/index.ts +24 -0
- package/src/utils/logger.ts +171 -0
- package/src/utils/rate-limiter.ts +121 -0
- package/src/utils/service-auth.ts +49 -0
- package/src/utils/validation.ts +53 -0
- package/src/version.ts +4 -0
- package/src/watcher/index.ts +163 -0
- package/src/wizard/approval.ts +383 -0
- package/src/wizard/index.ts +25 -0
- package/src/wizard/prompts.ts +338 -0
- package/src/wizard/types.ts +171 -0
- package/src/wizard/ui.ts +556 -0
- package/src/wizard/wizard.ts +304 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Prompt Utilities
|
|
3
|
+
*
|
|
4
|
+
* Provides functions for user input in the CLI wizard
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as readline from 'node:readline';
|
|
8
|
+
import type { SelectConfig, ConfirmConfig, InputConfig } from './types';
|
|
9
|
+
import { ui } from './ui';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Create a readline interface for user input
|
|
13
|
+
*/
|
|
14
|
+
function createReadline(): readline.Interface {
|
|
15
|
+
return readline.createInterface({
|
|
16
|
+
input: process.stdin,
|
|
17
|
+
output: process.stdout,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Prompt for a single selection from options
|
|
23
|
+
*/
|
|
24
|
+
export async function select<T = string>(config: SelectConfig): Promise<T | undefined> {
|
|
25
|
+
return new Promise(resolve => {
|
|
26
|
+
const options = config.options.filter(o => !o.disabled);
|
|
27
|
+
let selectedIndex = 0;
|
|
28
|
+
|
|
29
|
+
// Find default selection
|
|
30
|
+
if (config.defaultValue) {
|
|
31
|
+
const defaultIdx = options.findIndex(o => o.value === config.defaultValue);
|
|
32
|
+
if (defaultIdx >= 0) {
|
|
33
|
+
selectedIndex = defaultIdx;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Display prompt
|
|
38
|
+
ui.print(` ${ui.icons.question} ${config.message}`);
|
|
39
|
+
ui.newLine();
|
|
40
|
+
|
|
41
|
+
// For now, use simple numbered selection (arrow key selection requires raw mode)
|
|
42
|
+
for (let i = 0; i < config.options.length; i++) {
|
|
43
|
+
const opt = config.options[i];
|
|
44
|
+
const num = i + 1;
|
|
45
|
+
let line = ` ${num}. ${opt.label}`;
|
|
46
|
+
|
|
47
|
+
if (opt.disabled) {
|
|
48
|
+
line = ui.dim(`${line} (${opt.disabledReason || 'unavailable'})`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
ui.print(line);
|
|
52
|
+
|
|
53
|
+
if (opt.description) {
|
|
54
|
+
ui.print(ui.dim(` ${opt.description}`));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
ui.newLine();
|
|
59
|
+
|
|
60
|
+
const rl = createReadline();
|
|
61
|
+
const defaultNum = selectedIndex + 1;
|
|
62
|
+
const prompt = config.required
|
|
63
|
+
? ` Enter choice (1-${config.options.length}): `
|
|
64
|
+
: ` Enter choice (1-${config.options.length}) [${defaultNum}]: `;
|
|
65
|
+
|
|
66
|
+
rl.question(prompt, answer => {
|
|
67
|
+
rl.close();
|
|
68
|
+
|
|
69
|
+
const trimmed = answer.trim();
|
|
70
|
+
|
|
71
|
+
// Use default if empty
|
|
72
|
+
if (!trimmed && !config.required) {
|
|
73
|
+
resolve(config.options[selectedIndex].value as T);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Parse number
|
|
78
|
+
const num = parseInt(trimmed, 10);
|
|
79
|
+
if (isNaN(num) || num < 1 || num > config.options.length) {
|
|
80
|
+
ui.error(
|
|
81
|
+
`Invalid selection. Please enter a number between 1 and ${config.options.length}.`
|
|
82
|
+
);
|
|
83
|
+
resolve(undefined);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const selected = config.options[num - 1];
|
|
88
|
+
if (selected.disabled) {
|
|
89
|
+
ui.error(`Option "${selected.label}" is not available.`);
|
|
90
|
+
resolve(undefined);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
ui.newLine();
|
|
95
|
+
ui.print(` ${ui.icons.success} Selected: ${selected.label}`);
|
|
96
|
+
resolve(selected.value as T);
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Prompt for multiple selections from options
|
|
103
|
+
*/
|
|
104
|
+
export async function multiSelect<T = string>(config: SelectConfig): Promise<T[]> {
|
|
105
|
+
return new Promise(resolve => {
|
|
106
|
+
const options = config.options.filter(o => !o.disabled);
|
|
107
|
+
|
|
108
|
+
ui.print(` ${ui.icons.question} ${config.message}`);
|
|
109
|
+
ui.print(ui.dim(' (Enter comma-separated numbers, or "all" for all options)'));
|
|
110
|
+
ui.newLine();
|
|
111
|
+
|
|
112
|
+
// Display options
|
|
113
|
+
for (let i = 0; i < config.options.length; i++) {
|
|
114
|
+
const opt = config.options[i];
|
|
115
|
+
const num = i + 1;
|
|
116
|
+
let line = ` ${num}. ${opt.label}`;
|
|
117
|
+
|
|
118
|
+
if (opt.disabled) {
|
|
119
|
+
line = ui.dim(`${line} (${opt.disabledReason || 'unavailable'})`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
ui.print(line);
|
|
123
|
+
|
|
124
|
+
if (opt.description) {
|
|
125
|
+
ui.print(ui.dim(` ${opt.description}`));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
ui.newLine();
|
|
130
|
+
|
|
131
|
+
const rl = createReadline();
|
|
132
|
+
const prompt = ` Enter choices: `;
|
|
133
|
+
|
|
134
|
+
rl.question(prompt, answer => {
|
|
135
|
+
rl.close();
|
|
136
|
+
|
|
137
|
+
const trimmed = answer.trim().toLowerCase();
|
|
138
|
+
|
|
139
|
+
// Handle "all" selection
|
|
140
|
+
if (trimmed === 'all') {
|
|
141
|
+
const allValues = options.map(o => o.value as T);
|
|
142
|
+
ui.newLine();
|
|
143
|
+
ui.print(` ${ui.icons.success} Selected: All options`);
|
|
144
|
+
resolve(allValues);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Parse comma-separated numbers
|
|
149
|
+
const nums = trimmed.split(',').map(s => parseInt(s.trim(), 10));
|
|
150
|
+
const selected: T[] = [];
|
|
151
|
+
const selectedLabels: string[] = [];
|
|
152
|
+
|
|
153
|
+
for (const num of nums) {
|
|
154
|
+
if (isNaN(num) || num < 1 || num > config.options.length) {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const opt = config.options[num - 1];
|
|
159
|
+
if (!opt.disabled) {
|
|
160
|
+
selected.push(opt.value as T);
|
|
161
|
+
selectedLabels.push(opt.label);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (selected.length === 0 && config.required) {
|
|
166
|
+
ui.error('Please select at least one option.');
|
|
167
|
+
resolve([]);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (config.maxSelections && selected.length > config.maxSelections) {
|
|
172
|
+
ui.error(`Maximum ${config.maxSelections} selections allowed.`);
|
|
173
|
+
resolve([]);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
ui.newLine();
|
|
178
|
+
ui.print(` ${ui.icons.success} Selected: ${selectedLabels.join(', ')}`);
|
|
179
|
+
resolve(selected);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Prompt for confirmation (yes/no)
|
|
186
|
+
*/
|
|
187
|
+
export async function confirm(config: ConfirmConfig): Promise<boolean> {
|
|
188
|
+
return new Promise(resolve => {
|
|
189
|
+
const defaultHint =
|
|
190
|
+
config.defaultValue !== undefined ? (config.defaultValue ? '[Y/n]' : '[y/N]') : '[y/n]';
|
|
191
|
+
|
|
192
|
+
const rl = createReadline();
|
|
193
|
+
const prompt = ` ${ui.icons.question} ${config.message} ${defaultHint} `;
|
|
194
|
+
|
|
195
|
+
rl.question(prompt, answer => {
|
|
196
|
+
rl.close();
|
|
197
|
+
|
|
198
|
+
const trimmed = answer.trim().toLowerCase();
|
|
199
|
+
|
|
200
|
+
// Handle empty input
|
|
201
|
+
if (!trimmed) {
|
|
202
|
+
if (config.defaultValue !== undefined) {
|
|
203
|
+
resolve(config.defaultValue);
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
resolve(false);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Parse answer
|
|
211
|
+
if (trimmed === 'y' || trimmed === 'yes') {
|
|
212
|
+
resolve(true);
|
|
213
|
+
} else if (trimmed === 'n' || trimmed === 'no') {
|
|
214
|
+
resolve(false);
|
|
215
|
+
} else {
|
|
216
|
+
ui.error('Please enter "y" or "n".');
|
|
217
|
+
resolve(config.defaultValue ?? false);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Prompt for text input
|
|
225
|
+
*/
|
|
226
|
+
export async function input(config: InputConfig): Promise<string> {
|
|
227
|
+
return new Promise(resolve => {
|
|
228
|
+
const rl = createReadline();
|
|
229
|
+
|
|
230
|
+
let prompt = ` ${ui.icons.question} ${config.message}`;
|
|
231
|
+
if (config.defaultValue) {
|
|
232
|
+
prompt += ui.dim(` [${config.defaultValue}]`);
|
|
233
|
+
}
|
|
234
|
+
prompt += ': ';
|
|
235
|
+
|
|
236
|
+
rl.question(prompt, answer => {
|
|
237
|
+
rl.close();
|
|
238
|
+
|
|
239
|
+
let value = answer.trim();
|
|
240
|
+
|
|
241
|
+
// Use default if empty
|
|
242
|
+
if (!value && config.defaultValue) {
|
|
243
|
+
value = config.defaultValue;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Transform if specified
|
|
247
|
+
if (config.transform && value) {
|
|
248
|
+
value = config.transform(value);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Validate if specified
|
|
252
|
+
if (config.validate && value) {
|
|
253
|
+
const result = config.validate(value);
|
|
254
|
+
if (result !== true) {
|
|
255
|
+
ui.error(result);
|
|
256
|
+
resolve('');
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
resolve(value);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Prompt for a path input with validation
|
|
268
|
+
*/
|
|
269
|
+
export async function pathInput(message: string, defaultValue?: string): Promise<string> {
|
|
270
|
+
return input({
|
|
271
|
+
message,
|
|
272
|
+
defaultValue,
|
|
273
|
+
validate: value => {
|
|
274
|
+
// Basic path validation
|
|
275
|
+
if (!value) {
|
|
276
|
+
return 'Path is required';
|
|
277
|
+
}
|
|
278
|
+
if (value.includes('\0')) {
|
|
279
|
+
return 'Invalid path';
|
|
280
|
+
}
|
|
281
|
+
return true;
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/**
|
|
287
|
+
* Wait for user to press enter
|
|
288
|
+
*/
|
|
289
|
+
export async function pressEnter(message: string = 'Press Enter to continue...'): Promise<void> {
|
|
290
|
+
return new Promise(resolve => {
|
|
291
|
+
const rl = createReadline();
|
|
292
|
+
rl.question(` ${message}`, () => {
|
|
293
|
+
rl.close();
|
|
294
|
+
resolve();
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Display action options (e.g., for review)
|
|
301
|
+
*/
|
|
302
|
+
export async function actionSelect(
|
|
303
|
+
message: string,
|
|
304
|
+
actions: Array<{ key: string; label: string; description?: string }>
|
|
305
|
+
): Promise<string> {
|
|
306
|
+
return new Promise(resolve => {
|
|
307
|
+
ui.print(` ${message}`);
|
|
308
|
+
ui.newLine();
|
|
309
|
+
|
|
310
|
+
for (const action of actions) {
|
|
311
|
+
ui.print(` [${action.key.toUpperCase()}] ${action.label}`);
|
|
312
|
+
if (action.description) {
|
|
313
|
+
ui.print(ui.dim(` ${action.description}`));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
ui.newLine();
|
|
318
|
+
|
|
319
|
+
const rl = createReadline();
|
|
320
|
+
const validKeys = actions.map(a => a.key.toLowerCase());
|
|
321
|
+
|
|
322
|
+
rl.question(' > ', answer => {
|
|
323
|
+
rl.close();
|
|
324
|
+
|
|
325
|
+
const key = answer.trim().toLowerCase();
|
|
326
|
+
|
|
327
|
+
if (!validKeys.includes(key)) {
|
|
328
|
+
ui.error(
|
|
329
|
+
`Invalid option. Please enter one of: ${actions.map(a => a.key.toUpperCase()).join(', ')}`
|
|
330
|
+
);
|
|
331
|
+
resolve('');
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
resolve(key);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for the Interactive Wizard Framework
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Wizard step types
|
|
6
|
+
export interface WizardStep<TContext = any> {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
execute: (context: TContext) => Promise<StepResult>;
|
|
11
|
+
canSkip?: boolean;
|
|
12
|
+
condition?: (context: TContext) => boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface StepResult {
|
|
16
|
+
success: boolean;
|
|
17
|
+
data?: Record<string, unknown>;
|
|
18
|
+
error?: string;
|
|
19
|
+
nextStep?: string; // Override default next step
|
|
20
|
+
skipRemaining?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Selection types
|
|
24
|
+
export interface SelectOption<T = string> {
|
|
25
|
+
value: T;
|
|
26
|
+
label: string;
|
|
27
|
+
description?: string;
|
|
28
|
+
disabled?: boolean;
|
|
29
|
+
disabledReason?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface SelectConfig {
|
|
33
|
+
message: string;
|
|
34
|
+
options: SelectOption[];
|
|
35
|
+
defaultValue?: string;
|
|
36
|
+
allowMultiple?: boolean;
|
|
37
|
+
required?: boolean;
|
|
38
|
+
maxSelections?: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ConfirmConfig {
|
|
42
|
+
message: string;
|
|
43
|
+
defaultValue?: boolean;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface InputConfig {
|
|
47
|
+
message: string;
|
|
48
|
+
defaultValue?: string;
|
|
49
|
+
placeholder?: string;
|
|
50
|
+
validate?: (value: string) => string | true;
|
|
51
|
+
transform?: (value: string) => string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Progress display types
|
|
55
|
+
export interface ProgressConfig {
|
|
56
|
+
message: string;
|
|
57
|
+
total?: number;
|
|
58
|
+
showPercentage?: boolean;
|
|
59
|
+
showETA?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface SpinnerConfig {
|
|
63
|
+
message: string;
|
|
64
|
+
successMessage?: string;
|
|
65
|
+
failMessage?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Output types
|
|
69
|
+
export interface TableColumn {
|
|
70
|
+
key: string;
|
|
71
|
+
header: string;
|
|
72
|
+
width?: number;
|
|
73
|
+
align?: 'left' | 'center' | 'right';
|
|
74
|
+
formatter?: (value: unknown) => string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface TableConfig {
|
|
78
|
+
columns: TableColumn[];
|
|
79
|
+
data: Record<string, unknown>[];
|
|
80
|
+
title?: string;
|
|
81
|
+
showRowNumbers?: boolean;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Box types for styled output
|
|
85
|
+
export type BoxStyle = 'single' | 'double' | 'rounded' | 'heavy';
|
|
86
|
+
|
|
87
|
+
export interface BoxConfig {
|
|
88
|
+
content: string | string[];
|
|
89
|
+
title?: string;
|
|
90
|
+
style?: BoxStyle;
|
|
91
|
+
padding?: number;
|
|
92
|
+
width?: number;
|
|
93
|
+
borderColor?: string;
|
|
94
|
+
titleColor?: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Diff display types
|
|
98
|
+
export interface DiffLine {
|
|
99
|
+
type: 'unchanged' | 'added' | 'removed' | 'modified';
|
|
100
|
+
content: string;
|
|
101
|
+
lineNumber?: number;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export interface DiffConfig {
|
|
105
|
+
original: string;
|
|
106
|
+
modified: string;
|
|
107
|
+
title?: string;
|
|
108
|
+
contextLines?: number;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Wizard context for terraform generation
|
|
112
|
+
export interface TerraformWizardContext {
|
|
113
|
+
// Provider selection
|
|
114
|
+
provider?: 'aws' | 'gcp' | 'azure';
|
|
115
|
+
|
|
116
|
+
// AWS configuration
|
|
117
|
+
awsProfile?: string;
|
|
118
|
+
awsRegions?: string[];
|
|
119
|
+
awsAccountId?: string;
|
|
120
|
+
awsAccountAlias?: string;
|
|
121
|
+
|
|
122
|
+
// GCP configuration
|
|
123
|
+
gcpProject?: string;
|
|
124
|
+
gcpRegions?: string[];
|
|
125
|
+
|
|
126
|
+
// Azure configuration
|
|
127
|
+
azureSubscription?: string;
|
|
128
|
+
azureResourceGroup?: string;
|
|
129
|
+
|
|
130
|
+
// Discovery options
|
|
131
|
+
servicesToScan?: string[];
|
|
132
|
+
excludeServices?: string[];
|
|
133
|
+
|
|
134
|
+
// Generation options
|
|
135
|
+
outputPath?: string;
|
|
136
|
+
includeImports?: boolean;
|
|
137
|
+
importMethod?: 'blocks' | 'script' | 'both';
|
|
138
|
+
|
|
139
|
+
// Improvements
|
|
140
|
+
enabledCategories?: string[];
|
|
141
|
+
autoApplyLowRisk?: boolean;
|
|
142
|
+
explanationLevel?: 'simple' | 'detailed';
|
|
143
|
+
|
|
144
|
+
// Starter kit
|
|
145
|
+
includeReadme?: boolean;
|
|
146
|
+
includeGitignore?: boolean;
|
|
147
|
+
includeMakefile?: boolean;
|
|
148
|
+
includeGithubActions?: boolean;
|
|
149
|
+
|
|
150
|
+
// State
|
|
151
|
+
discoverySessionId?: string;
|
|
152
|
+
inventory?: any;
|
|
153
|
+
generatedFiles?: any[];
|
|
154
|
+
improvements?: any;
|
|
155
|
+
|
|
156
|
+
// Preferences
|
|
157
|
+
savePreferences?: boolean;
|
|
158
|
+
organizationPolicy?: string;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Wizard events
|
|
162
|
+
export type WizardEvent =
|
|
163
|
+
| { type: 'step:start'; stepId: string }
|
|
164
|
+
| { type: 'step:complete'; stepId: string; result: StepResult }
|
|
165
|
+
| { type: 'step:error'; stepId: string; error: Error }
|
|
166
|
+
| { type: 'wizard:start' }
|
|
167
|
+
| { type: 'wizard:complete'; context: any }
|
|
168
|
+
| { type: 'wizard:cancel' }
|
|
169
|
+
| { type: 'wizard:error'; error: Error };
|
|
170
|
+
|
|
171
|
+
export type WizardEventHandler = (event: WizardEvent) => void;
|