@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,539 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Project Scanners
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates all project scanners to build a complete project context
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import { execSync } from 'child_process';
|
|
10
|
+
import type {
|
|
11
|
+
ProjectContext,
|
|
12
|
+
ProjectType,
|
|
13
|
+
ScanOptions,
|
|
14
|
+
AggregateScanResult,
|
|
15
|
+
LanguageInfo,
|
|
16
|
+
FrameworkInfo,
|
|
17
|
+
PackageManagerInfo,
|
|
18
|
+
IaCInfo,
|
|
19
|
+
CICDInfo,
|
|
20
|
+
CloudInfo,
|
|
21
|
+
GitInfo,
|
|
22
|
+
} from './types';
|
|
23
|
+
|
|
24
|
+
import { createLanguageScanner, type LanguageScanner } from './language-scanner';
|
|
25
|
+
import { createFrameworkScanner, type FrameworkScanner } from './framework-scanner';
|
|
26
|
+
import { createPackageManagerScanner, type PackageManagerScanner } from './package-manager-scanner';
|
|
27
|
+
import { createIaCScanner, type IaCScanner } from './iac-scanner';
|
|
28
|
+
import { createCICDScanner, type CICDScanner } from './cicd-scanner';
|
|
29
|
+
import { createCloudScanner, type CloudScanner } from './cloud-scanner';
|
|
30
|
+
|
|
31
|
+
// Re-export types
|
|
32
|
+
export * from './types';
|
|
33
|
+
|
|
34
|
+
// Re-export scanners
|
|
35
|
+
export { LanguageScanner, createLanguageScanner } from './language-scanner';
|
|
36
|
+
export { FrameworkScanner, createFrameworkScanner } from './framework-scanner';
|
|
37
|
+
export { PackageManagerScanner, createPackageManagerScanner } from './package-manager-scanner';
|
|
38
|
+
export { IaCScanner, createIaCScanner } from './iac-scanner';
|
|
39
|
+
export { CICDScanner, createCICDScanner } from './cicd-scanner';
|
|
40
|
+
export { CloudScanner, createCloudScanner } from './cloud-scanner';
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Default scan options
|
|
44
|
+
*/
|
|
45
|
+
const DEFAULT_SCAN_OPTIONS: ScanOptions = {
|
|
46
|
+
depth: 'standard',
|
|
47
|
+
maxFiles: 1000,
|
|
48
|
+
includeHidden: false,
|
|
49
|
+
instructions: '',
|
|
50
|
+
maxDepth: 10,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Project Scanner Orchestrator
|
|
55
|
+
*
|
|
56
|
+
* Coordinates all individual scanners to build a complete project context
|
|
57
|
+
*/
|
|
58
|
+
export class ProjectScanner {
|
|
59
|
+
private languageScanner: LanguageScanner;
|
|
60
|
+
private frameworkScanner: FrameworkScanner;
|
|
61
|
+
private packageManagerScanner: PackageManagerScanner;
|
|
62
|
+
private iacScanner: IaCScanner;
|
|
63
|
+
private cicdScanner: CICDScanner;
|
|
64
|
+
private cloudScanner: CloudScanner;
|
|
65
|
+
|
|
66
|
+
constructor() {
|
|
67
|
+
this.languageScanner = createLanguageScanner();
|
|
68
|
+
this.frameworkScanner = createFrameworkScanner();
|
|
69
|
+
this.packageManagerScanner = createPackageManagerScanner();
|
|
70
|
+
this.iacScanner = createIaCScanner();
|
|
71
|
+
this.cicdScanner = createCICDScanner();
|
|
72
|
+
this.cloudScanner = createCloudScanner();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Scan a project directory and return complete context
|
|
77
|
+
*/
|
|
78
|
+
async scan(cwd: string, options: Partial<ScanOptions> = {}): Promise<ProjectContext> {
|
|
79
|
+
const opts = { ...DEFAULT_SCAN_OPTIONS, ...options };
|
|
80
|
+
|
|
81
|
+
// Run all scanners in parallel
|
|
82
|
+
const [
|
|
83
|
+
languageResult,
|
|
84
|
+
frameworkResult,
|
|
85
|
+
packageManagerResult,
|
|
86
|
+
iacResult,
|
|
87
|
+
cicdResult,
|
|
88
|
+
cloudResult,
|
|
89
|
+
gitInfo,
|
|
90
|
+
] = await Promise.all([
|
|
91
|
+
this.languageScanner.scan(cwd, opts),
|
|
92
|
+
this.frameworkScanner.scan(cwd, opts),
|
|
93
|
+
this.packageManagerScanner.scan(cwd, opts),
|
|
94
|
+
this.iacScanner.scan(cwd, opts),
|
|
95
|
+
this.cicdScanner.scan(cwd, opts),
|
|
96
|
+
this.cloudScanner.scan(cwd, opts),
|
|
97
|
+
this.getGitInfo(cwd),
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
// Extract detailed results
|
|
101
|
+
const languages = languageResult.details.languages as LanguageInfo[];
|
|
102
|
+
const frameworks = frameworkResult.details.frameworks as FrameworkInfo[];
|
|
103
|
+
const packageManagers = packageManagerResult.details.packageManagers as PackageManagerInfo[];
|
|
104
|
+
const iac = iacResult.details.iac as IaCInfo[];
|
|
105
|
+
const cicd = cicdResult.details.cicd as CICDInfo[];
|
|
106
|
+
const cloud = cloudResult.details.cloud as CloudInfo[];
|
|
107
|
+
|
|
108
|
+
// Get file lists
|
|
109
|
+
const terraformFiles = await this.iacScanner.getTerraformFiles(cwd);
|
|
110
|
+
const kubernetesFiles = await this.iacScanner.getKubernetesFiles(cwd);
|
|
111
|
+
const dockerFiles = await this.iacScanner.getDockerFiles(cwd);
|
|
112
|
+
const cicdFiles = await this.cicdScanner.getCICDFiles(cwd);
|
|
113
|
+
|
|
114
|
+
// Determine project type
|
|
115
|
+
const projectType = this.determineProjectType({
|
|
116
|
+
languages,
|
|
117
|
+
frameworks,
|
|
118
|
+
packageManagers,
|
|
119
|
+
iac,
|
|
120
|
+
cicd,
|
|
121
|
+
cloud,
|
|
122
|
+
git: gitInfo,
|
|
123
|
+
projectType: 'unknown',
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
// Get primary CI/CD platform
|
|
127
|
+
const primaryCICD = await this.cicdScanner.getPrimaryCICDPlatform(cwd);
|
|
128
|
+
|
|
129
|
+
// Build project context
|
|
130
|
+
const context: ProjectContext = {
|
|
131
|
+
project: {
|
|
132
|
+
name: this.getProjectName(cwd),
|
|
133
|
+
path: cwd,
|
|
134
|
+
detected_at: new Date().toISOString(),
|
|
135
|
+
},
|
|
136
|
+
structure: {
|
|
137
|
+
type: projectType,
|
|
138
|
+
languages: languages.map(l => ({
|
|
139
|
+
name: l.name,
|
|
140
|
+
version: l.version,
|
|
141
|
+
confidence: l.confidence,
|
|
142
|
+
files: l.files,
|
|
143
|
+
})),
|
|
144
|
+
frameworks: frameworks.map(f => ({
|
|
145
|
+
name: f.name,
|
|
146
|
+
version: f.version,
|
|
147
|
+
confidence: f.confidence,
|
|
148
|
+
language: f.language,
|
|
149
|
+
})),
|
|
150
|
+
packageManagers: packageManagers.map(pm => ({
|
|
151
|
+
name: pm.name,
|
|
152
|
+
lockFile: pm.lockFile,
|
|
153
|
+
confidence: pm.confidence,
|
|
154
|
+
})),
|
|
155
|
+
},
|
|
156
|
+
files: {
|
|
157
|
+
terraform: terraformFiles,
|
|
158
|
+
kubernetes: kubernetesFiles,
|
|
159
|
+
docker: dockerFiles,
|
|
160
|
+
cicd: cicdFiles,
|
|
161
|
+
},
|
|
162
|
+
git: gitInfo,
|
|
163
|
+
cicd: {
|
|
164
|
+
platform: primaryCICD,
|
|
165
|
+
workflows: cicdFiles,
|
|
166
|
+
},
|
|
167
|
+
cloud: {
|
|
168
|
+
providers: cloud.map(c => c.provider),
|
|
169
|
+
regions: [...new Set(cloud.flatMap(c => c.regions))],
|
|
170
|
+
},
|
|
171
|
+
instructions: opts.instructions || '',
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return context;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Run a quick scan (config files only)
|
|
179
|
+
*/
|
|
180
|
+
async quickScan(cwd: string): Promise<AggregateScanResult> {
|
|
181
|
+
const [
|
|
182
|
+
languageResult,
|
|
183
|
+
frameworkResult,
|
|
184
|
+
packageManagerResult,
|
|
185
|
+
iacResult,
|
|
186
|
+
cicdResult,
|
|
187
|
+
cloudResult,
|
|
188
|
+
gitInfo,
|
|
189
|
+
] = await Promise.all([
|
|
190
|
+
this.languageScanner.scan(cwd),
|
|
191
|
+
this.frameworkScanner.scan(cwd),
|
|
192
|
+
this.packageManagerScanner.scan(cwd),
|
|
193
|
+
this.iacScanner.scan(cwd),
|
|
194
|
+
this.cicdScanner.scan(cwd),
|
|
195
|
+
this.cloudScanner.scan(cwd),
|
|
196
|
+
this.getGitInfo(cwd),
|
|
197
|
+
]);
|
|
198
|
+
|
|
199
|
+
const result: AggregateScanResult = {
|
|
200
|
+
languages: languageResult.details.languages as LanguageInfo[],
|
|
201
|
+
frameworks: frameworkResult.details.frameworks as FrameworkInfo[],
|
|
202
|
+
packageManagers: packageManagerResult.details.packageManagers as PackageManagerInfo[],
|
|
203
|
+
iac: iacResult.details.iac as IaCInfo[],
|
|
204
|
+
cicd: cicdResult.details.cicd as CICDInfo[],
|
|
205
|
+
cloud: cloudResult.details.cloud as CloudInfo[],
|
|
206
|
+
git: gitInfo,
|
|
207
|
+
projectType: 'unknown',
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
result.projectType = this.determineProjectType(result);
|
|
211
|
+
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Get git repository information
|
|
217
|
+
*/
|
|
218
|
+
private async getGitInfo(cwd: string): Promise<GitInfo> {
|
|
219
|
+
const gitDir = path.join(cwd, '.git');
|
|
220
|
+
const isRepo = fs.existsSync(gitDir);
|
|
221
|
+
|
|
222
|
+
if (!isRepo) {
|
|
223
|
+
return {
|
|
224
|
+
isRepo: false,
|
|
225
|
+
remote: null,
|
|
226
|
+
branch: '',
|
|
227
|
+
hasUncommittedChanges: false,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
let remote: string | null = null;
|
|
232
|
+
let branch = '';
|
|
233
|
+
let hasUncommittedChanges = false;
|
|
234
|
+
|
|
235
|
+
try {
|
|
236
|
+
// Get remote URL
|
|
237
|
+
remote = execSync('git remote get-url origin', { cwd, encoding: 'utf-8' }).trim();
|
|
238
|
+
} catch {
|
|
239
|
+
remote = null;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
try {
|
|
243
|
+
// Get current branch
|
|
244
|
+
branch = execSync('git rev-parse --abbrev-ref HEAD', { cwd, encoding: 'utf-8' }).trim();
|
|
245
|
+
} catch {
|
|
246
|
+
branch = 'unknown';
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
try {
|
|
250
|
+
// Check for uncommitted changes
|
|
251
|
+
const status = execSync('git status --porcelain', { cwd, encoding: 'utf-8' }).trim();
|
|
252
|
+
hasUncommittedChanges = status.length > 0;
|
|
253
|
+
} catch {
|
|
254
|
+
hasUncommittedChanges = false;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
isRepo,
|
|
259
|
+
remote,
|
|
260
|
+
branch,
|
|
261
|
+
hasUncommittedChanges,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Get project name from package.json or directory name
|
|
267
|
+
*/
|
|
268
|
+
private getProjectName(cwd: string): string {
|
|
269
|
+
// Try package.json
|
|
270
|
+
const packageJsonPath = path.join(cwd, 'package.json');
|
|
271
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
272
|
+
try {
|
|
273
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'));
|
|
274
|
+
if (packageJson.name) {
|
|
275
|
+
return packageJson.name;
|
|
276
|
+
}
|
|
277
|
+
} catch {
|
|
278
|
+
// Ignore parse errors
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Try pyproject.toml
|
|
283
|
+
const pyprojectPath = path.join(cwd, 'pyproject.toml');
|
|
284
|
+
if (fs.existsSync(pyprojectPath)) {
|
|
285
|
+
try {
|
|
286
|
+
const content = fs.readFileSync(pyprojectPath, 'utf-8');
|
|
287
|
+
const match = content.match(/name\s*=\s*["']([^"']+)["']/);
|
|
288
|
+
if (match) {
|
|
289
|
+
return match[1];
|
|
290
|
+
}
|
|
291
|
+
} catch {
|
|
292
|
+
// Ignore parse errors
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Try Cargo.toml
|
|
297
|
+
const cargoPath = path.join(cwd, 'Cargo.toml');
|
|
298
|
+
if (fs.existsSync(cargoPath)) {
|
|
299
|
+
try {
|
|
300
|
+
const content = fs.readFileSync(cargoPath, 'utf-8');
|
|
301
|
+
const match = content.match(/name\s*=\s*["']([^"']+)["']/);
|
|
302
|
+
if (match) {
|
|
303
|
+
return match[1];
|
|
304
|
+
}
|
|
305
|
+
} catch {
|
|
306
|
+
// Ignore parse errors
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Fall back to directory name
|
|
311
|
+
return path.basename(cwd);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Determine project type based on scan results
|
|
316
|
+
*/
|
|
317
|
+
private determineProjectType(result: AggregateScanResult): ProjectType {
|
|
318
|
+
const { languages, frameworks, iac, cloud: _cloud } = result;
|
|
319
|
+
|
|
320
|
+
// Check for monorepo indicators
|
|
321
|
+
const isMonorepo = this.isMonorepo(languages, frameworks);
|
|
322
|
+
if (isMonorepo) {
|
|
323
|
+
return 'monorepo';
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Check for infrastructure-only project
|
|
327
|
+
if (iac.length > 0 && languages.length === 0) {
|
|
328
|
+
return 'infrastructure';
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Check for mobile frameworks
|
|
332
|
+
const mobileFrameworks = ['react-native', 'flutter', 'expo'];
|
|
333
|
+
if (frameworks.some(f => mobileFrameworks.includes(f.name))) {
|
|
334
|
+
return 'mobile';
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Check for CLI indicators
|
|
338
|
+
const cliIndicators = ['commander', 'yargs', 'oclif', 'clap', 'cobra', 'click', 'typer'];
|
|
339
|
+
if (frameworks.some(f => cliIndicators.includes(f.name))) {
|
|
340
|
+
return 'cli';
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Check for fullstack
|
|
344
|
+
const frontendFrameworks = [
|
|
345
|
+
'next.js',
|
|
346
|
+
'nuxt',
|
|
347
|
+
'remix',
|
|
348
|
+
'angular',
|
|
349
|
+
'vue',
|
|
350
|
+
'react',
|
|
351
|
+
'svelte',
|
|
352
|
+
'astro',
|
|
353
|
+
];
|
|
354
|
+
const backendFrameworks = [
|
|
355
|
+
'express',
|
|
356
|
+
'fastify',
|
|
357
|
+
'nestjs',
|
|
358
|
+
'django',
|
|
359
|
+
'fastapi',
|
|
360
|
+
'flask',
|
|
361
|
+
'spring-boot',
|
|
362
|
+
'gin',
|
|
363
|
+
'actix-web',
|
|
364
|
+
];
|
|
365
|
+
|
|
366
|
+
const hasFrontend = frameworks.some(f => frontendFrameworks.includes(f.name));
|
|
367
|
+
const hasBackend = frameworks.some(f => backendFrameworks.includes(f.name));
|
|
368
|
+
|
|
369
|
+
if (hasFrontend && hasBackend) {
|
|
370
|
+
return 'fullstack';
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (hasFrontend) {
|
|
374
|
+
return 'frontend';
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if (hasBackend) {
|
|
378
|
+
return 'backend';
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Check for library indicators
|
|
382
|
+
if (this.isLibrary(languages)) {
|
|
383
|
+
return 'library';
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return 'unknown';
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Check if project is a monorepo
|
|
391
|
+
*/
|
|
392
|
+
private isMonorepo(languages: LanguageInfo[], _frameworks: FrameworkInfo[]): boolean {
|
|
393
|
+
// Check for monorepo tools
|
|
394
|
+
const _monorepoTools = ['lerna', 'nx', 'turborepo', 'rush', 'pnpm-workspace'];
|
|
395
|
+
// This would need to be detected from package.json or config files
|
|
396
|
+
// For now, check if multiple languages with high confidence
|
|
397
|
+
const highConfidenceLanguages = languages.filter(l => l.confidence === 'high');
|
|
398
|
+
return highConfidenceLanguages.length >= 3;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Check if project is a library
|
|
403
|
+
*/
|
|
404
|
+
private isLibrary(languages: LanguageInfo[]): boolean {
|
|
405
|
+
// Libraries typically have specific config files
|
|
406
|
+
// This is a simplified heuristic
|
|
407
|
+
return languages.some(l =>
|
|
408
|
+
l.files.some(
|
|
409
|
+
f => f.includes('.gemspec') || f.includes('setup.py') || f.includes('Cargo.toml')
|
|
410
|
+
)
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Generate project.yaml content from project context
|
|
417
|
+
*/
|
|
418
|
+
export function generateProjectYaml(context: ProjectContext): string {
|
|
419
|
+
const lines: string[] = [];
|
|
420
|
+
|
|
421
|
+
// Project section
|
|
422
|
+
lines.push('project:');
|
|
423
|
+
lines.push(` name: ${context.project.name}`);
|
|
424
|
+
lines.push(` detected_at: ${context.project.detected_at}`);
|
|
425
|
+
lines.push('');
|
|
426
|
+
|
|
427
|
+
// Structure section
|
|
428
|
+
lines.push('structure:');
|
|
429
|
+
lines.push(` type: ${context.structure.type}`);
|
|
430
|
+
|
|
431
|
+
if (context.structure.languages.length > 0) {
|
|
432
|
+
lines.push(' languages:');
|
|
433
|
+
for (const lang of context.structure.languages) {
|
|
434
|
+
if (lang.version) {
|
|
435
|
+
lines.push(` - name: ${lang.name}`);
|
|
436
|
+
lines.push(` version: "${lang.version}"`);
|
|
437
|
+
} else {
|
|
438
|
+
lines.push(` - name: ${lang.name}`);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (context.structure.frameworks.length > 0) {
|
|
444
|
+
lines.push(' frameworks:');
|
|
445
|
+
for (const fw of context.structure.frameworks) {
|
|
446
|
+
lines.push(` - name: ${fw.name}`);
|
|
447
|
+
if (fw.version) {
|
|
448
|
+
lines.push(` version: "${fw.version}"`);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (context.structure.packageManagers.length > 0) {
|
|
454
|
+
lines.push(
|
|
455
|
+
` packageManagers: [${context.structure.packageManagers.map(pm => pm.name).join(', ')}]`
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
lines.push('');
|
|
460
|
+
|
|
461
|
+
// Files section
|
|
462
|
+
lines.push('files:');
|
|
463
|
+
if (context.files.terraform.length > 0) {
|
|
464
|
+
lines.push(` terraform: ["${context.files.terraform.slice(0, 10).join('", "')}"]`);
|
|
465
|
+
} else {
|
|
466
|
+
lines.push(' terraform: []');
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
if (context.files.kubernetes.length > 0) {
|
|
470
|
+
lines.push(` kubernetes: ["${context.files.kubernetes.slice(0, 10).join('", "')}"]`);
|
|
471
|
+
} else {
|
|
472
|
+
lines.push(' kubernetes: []');
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
if (context.files.docker.length > 0) {
|
|
476
|
+
lines.push(` docker: ["${context.files.docker.slice(0, 10).join('", "')}"]`);
|
|
477
|
+
} else {
|
|
478
|
+
lines.push(' docker: []');
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
if (context.files.cicd.length > 0) {
|
|
482
|
+
lines.push(` cicd: ["${context.files.cicd.slice(0, 10).join('", "')}"]`);
|
|
483
|
+
} else {
|
|
484
|
+
lines.push(' cicd: []');
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
lines.push('');
|
|
488
|
+
|
|
489
|
+
// Git section
|
|
490
|
+
lines.push('git:');
|
|
491
|
+
lines.push(` remote: ${context.git.remote || 'null'}`);
|
|
492
|
+
lines.push(` branch: ${context.git.branch}`);
|
|
493
|
+
lines.push(` isRepo: ${context.git.isRepo}`);
|
|
494
|
+
lines.push('');
|
|
495
|
+
|
|
496
|
+
// CI/CD section
|
|
497
|
+
lines.push('cicd:');
|
|
498
|
+
lines.push(` platform: ${context.cicd.platform || 'null'}`);
|
|
499
|
+
if (context.cicd.workflows.length > 0) {
|
|
500
|
+
lines.push(` workflows: ["${context.cicd.workflows.slice(0, 10).join('", "')}"]`);
|
|
501
|
+
} else {
|
|
502
|
+
lines.push(' workflows: []');
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
lines.push('');
|
|
506
|
+
|
|
507
|
+
// Cloud section
|
|
508
|
+
lines.push('cloud:');
|
|
509
|
+
if (context.cloud.providers.length > 0) {
|
|
510
|
+
lines.push(` providers: [${context.cloud.providers.join(', ')}]`);
|
|
511
|
+
} else {
|
|
512
|
+
lines.push(' providers: []');
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (context.cloud.regions.length > 0) {
|
|
516
|
+
lines.push(` regions: [${context.cloud.regions.join(', ')}]`);
|
|
517
|
+
} else {
|
|
518
|
+
lines.push(' regions: []');
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Instructions section (if provided)
|
|
522
|
+
if (context.instructions) {
|
|
523
|
+
lines.push('');
|
|
524
|
+
lines.push('# Custom project instructions');
|
|
525
|
+
lines.push(`instructions: |`);
|
|
526
|
+
for (const line of context.instructions.split('\n')) {
|
|
527
|
+
lines.push(` ${line}`);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
return `${lines.join('\n')}\n`;
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Create project scanner instance
|
|
536
|
+
*/
|
|
537
|
+
export function createProjectScanner(): ProjectScanner {
|
|
538
|
+
return new ProjectScanner();
|
|
539
|
+
}
|