@build-astron-co/nimbus 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/agent/compaction-agent.js +24 -12
- package/dist/src/agent/context-manager.js +2 -1
- package/dist/src/agent/expand-files.js +2 -1
- package/dist/src/agent/loop.js +71 -33
- package/dist/src/agent/permissions.js +4 -2
- package/dist/src/agent/system-prompt.js +34 -17
- package/dist/src/app.js +1 -1
- package/dist/src/auth/keychain.js +8 -4
- package/dist/src/auth/store.js +70 -107
- package/dist/src/cli/init.js +35 -19
- package/dist/src/cli/run.js +18 -10
- package/dist/src/cli/serve.js +4 -2
- package/dist/src/cli.js +52 -11
- package/dist/src/commands/alias.js +5 -3
- package/dist/src/commands/audit/index.js +2 -1
- package/dist/src/commands/aws-terraform.js +36 -18
- package/dist/src/commands/completions.js +1 -1
- package/dist/src/commands/config.js +3 -2
- package/dist/src/commands/connect-github.js +92 -0
- package/dist/src/commands/cost/index.js +3 -2
- package/dist/src/commands/deploy.js +15 -10
- package/dist/src/commands/doctor.js +6 -3
- package/dist/src/commands/drift/index.js +2 -1
- package/dist/src/commands/export.js +5 -3
- package/dist/src/commands/generate-terraform.js +110 -2
- package/dist/src/commands/import.js +3 -3
- package/dist/src/commands/incident.js +10 -5
- package/dist/src/commands/login.js +8 -93
- package/dist/src/commands/logs.js +16 -8
- package/dist/src/commands/onboarding.js +6 -4
- package/dist/src/commands/pipeline.js +6 -3
- package/dist/src/commands/plugin.js +3 -2
- package/dist/src/commands/profile.js +27 -14
- package/dist/src/commands/questionnaire.js +1 -1
- package/dist/src/commands/rollback.js +3 -2
- package/dist/src/commands/rollout.js +5 -3
- package/dist/src/commands/runbook.js +17 -10
- package/dist/src/commands/schedule.js +10 -5
- package/dist/src/commands/status.js +2 -1
- package/dist/src/commands/team-context.js +12 -7
- package/dist/src/commands/template.js +1 -1
- package/dist/src/commands/tf/index.js +6 -3
- package/dist/src/commands/version.js +6 -3
- package/dist/src/commands/watch.js +6 -3
- package/dist/src/compat/sqlite.js +5 -3
- package/dist/src/config/mode-store.js +2 -1
- package/dist/src/config/profiles.js +4 -2
- package/dist/src/config/types.js +2 -1
- package/dist/src/engine/executor.js +8 -4
- package/dist/src/engine/planner.js +9 -5
- package/dist/src/llm/providers/anthropic.js +6 -3
- package/dist/src/llm/providers/ollama.js +1 -1
- package/dist/src/llm/router.js +22 -7
- package/dist/src/sessions/manager.js +6 -3
- package/dist/src/sharing/viewer.js +2 -1
- package/dist/src/tools/file-ops.js +1 -2
- package/dist/src/tools/schemas/devops.js +197 -108
- package/dist/src/tools/schemas/standard.js +1 -1
- package/dist/src/ui/App.js +25 -13
- package/dist/src/ui/FileDiffModal.js +22 -11
- package/dist/src/ui/HelpModal.js +2 -1
- package/dist/src/ui/InputBox.js +6 -3
- package/dist/src/ui/MessageList.js +40 -20
- package/dist/src/ui/TerminalPane.js +2 -1
- package/dist/src/ui/ToolCallDisplay.js +12 -6
- package/dist/src/ui/TreePane.js +2 -1
- package/dist/src/ui/ink/index.js +37 -21
- package/dist/src/watcher/index.js +8 -4
- package/package.json +3 -5
- package/src/__tests__/alias.test.ts +0 -133
- package/src/__tests__/app.test.ts +0 -76
- package/src/__tests__/audit.test.ts +0 -877
- package/src/__tests__/circuit-breaker.test.ts +0 -116
- package/src/__tests__/cli-run.test.ts +0 -351
- package/src/__tests__/compat-sqlite.test.ts +0 -68
- package/src/__tests__/context-manager.test.ts +0 -632
- package/src/__tests__/context.test.ts +0 -242
- package/src/__tests__/devops-terminal-gaps.test.ts +0 -718
- package/src/__tests__/doctor.test.ts +0 -48
- package/src/__tests__/enterprise.test.ts +0 -401
- package/src/__tests__/export.test.ts +0 -236
- package/src/__tests__/gap-11-18-20.test.ts +0 -958
- package/src/__tests__/generator.test.ts +0 -433
- package/src/__tests__/helm-streaming.test.ts +0 -127
- package/src/__tests__/hooks.test.ts +0 -582
- package/src/__tests__/incident.test.ts +0 -179
- package/src/__tests__/init.test.ts +0 -487
- package/src/__tests__/intent-parser.test.ts +0 -229
- package/src/__tests__/llm-router.test.ts +0 -209
- package/src/__tests__/logs.test.ts +0 -107
- package/src/__tests__/loop-errors.test.ts +0 -244
- package/src/__tests__/lsp.test.ts +0 -293
- package/src/__tests__/modes.test.ts +0 -336
- package/src/__tests__/perf-optimizations.test.ts +0 -847
- package/src/__tests__/permissions.test.ts +0 -338
- package/src/__tests__/pipeline.test.ts +0 -50
- package/src/__tests__/polish-phase3.test.ts +0 -340
- package/src/__tests__/profile.test.ts +0 -237
- package/src/__tests__/rollback.test.ts +0 -83
- package/src/__tests__/runbook.test.ts +0 -219
- package/src/__tests__/schedule.test.ts +0 -206
- package/src/__tests__/serve.test.ts +0 -275
- package/src/__tests__/sessions.test.ts +0 -322
- package/src/__tests__/sharing.test.ts +0 -340
- package/src/__tests__/snapshots.test.ts +0 -581
- package/src/__tests__/standalone-migration.test.ts +0 -199
- package/src/__tests__/state-db.test.ts +0 -334
- package/src/__tests__/status.test.ts +0 -158
- package/src/__tests__/stream-with-tools.test.ts +0 -778
- package/src/__tests__/subagents.test.ts +0 -176
- package/src/__tests__/system-prompt.test.ts +0 -248
- package/src/__tests__/terminal-gap-v2.test.ts +0 -395
- package/src/__tests__/terminal-parity.test.ts +0 -393
- package/src/__tests__/tf-apply.test.ts +0 -187
- package/src/__tests__/tool-converter.test.ts +0 -256
- package/src/__tests__/tool-schemas.test.ts +0 -602
- package/src/__tests__/tools.test.ts +0 -144
- package/src/__tests__/version-json.test.ts +0 -184
- package/src/__tests__/version.test.ts +0 -49
- package/src/__tests__/watch.test.ts +0 -129
- package/src/agent/compaction-agent.ts +0 -266
- package/src/agent/context-manager.ts +0 -499
- package/src/agent/context.ts +0 -427
- package/src/agent/deploy-preview.ts +0 -487
- package/src/agent/expand-files.ts +0 -108
- package/src/agent/index.ts +0 -68
- package/src/agent/loop.ts +0 -1998
- package/src/agent/modes.ts +0 -429
- package/src/agent/permissions.ts +0 -513
- package/src/agent/subagents/base.ts +0 -116
- package/src/agent/subagents/cost.ts +0 -51
- package/src/agent/subagents/explore.ts +0 -42
- package/src/agent/subagents/general.ts +0 -54
- package/src/agent/subagents/index.ts +0 -102
- package/src/agent/subagents/infra.ts +0 -59
- package/src/agent/subagents/security.ts +0 -69
- package/src/agent/system-prompt.ts +0 -990
- package/src/app.ts +0 -180
- package/src/audit/activity-log.ts +0 -290
- package/src/audit/compliance-checker.ts +0 -540
- package/src/audit/cost-tracker.ts +0 -318
- package/src/audit/index.ts +0 -23
- package/src/audit/security-scanner.ts +0 -641
- package/src/auth/guard.ts +0 -75
- package/src/auth/index.ts +0 -56
- package/src/auth/keychain.ts +0 -82
- package/src/auth/oauth.ts +0 -465
- package/src/auth/providers.ts +0 -470
- package/src/auth/sso.ts +0 -113
- package/src/auth/store.ts +0 -505
- package/src/auth/types.ts +0 -187
- package/src/build.ts +0 -141
- package/src/cli/index.ts +0 -16
- package/src/cli/init.ts +0 -1227
- package/src/cli/openapi-spec.ts +0 -356
- package/src/cli/run.ts +0 -628
- package/src/cli/serve-auth.ts +0 -80
- package/src/cli/serve.ts +0 -539
- package/src/cli/web.ts +0 -71
- package/src/cli.ts +0 -1728
- package/src/clients/core-engine-client.ts +0 -227
- package/src/clients/enterprise-client.ts +0 -334
- package/src/clients/generator-client.ts +0 -351
- package/src/clients/git-client.ts +0 -627
- package/src/clients/github-client.ts +0 -410
- package/src/clients/helm-client.ts +0 -504
- package/src/clients/index.ts +0 -80
- package/src/clients/k8s-client.ts +0 -497
- package/src/clients/llm-client.ts +0 -161
- package/src/clients/rest-client.ts +0 -130
- package/src/clients/service-discovery.ts +0 -38
- package/src/clients/terraform-client.ts +0 -482
- package/src/clients/tools-client.ts +0 -1843
- package/src/clients/ws-client.ts +0 -115
- package/src/commands/alias.ts +0 -100
- package/src/commands/analyze/index.ts +0 -352
- package/src/commands/apply/helm.ts +0 -473
- package/src/commands/apply/index.ts +0 -213
- package/src/commands/apply/k8s.ts +0 -454
- package/src/commands/apply/terraform.ts +0 -582
- package/src/commands/ask.ts +0 -167
- package/src/commands/audit/index.ts +0 -357
- package/src/commands/auth-cloud.ts +0 -407
- package/src/commands/auth-list.ts +0 -134
- package/src/commands/auth-profile.ts +0 -121
- package/src/commands/auth-refresh.ts +0 -187
- package/src/commands/auth-status.ts +0 -141
- package/src/commands/aws/ec2.ts +0 -501
- package/src/commands/aws/iam.ts +0 -397
- package/src/commands/aws/index.ts +0 -133
- package/src/commands/aws/lambda.ts +0 -396
- package/src/commands/aws/rds.ts +0 -439
- package/src/commands/aws/s3.ts +0 -439
- package/src/commands/aws/vpc.ts +0 -393
- package/src/commands/aws-discover.ts +0 -542
- package/src/commands/aws-terraform.ts +0 -755
- package/src/commands/azure/aks.ts +0 -376
- package/src/commands/azure/functions.ts +0 -253
- package/src/commands/azure/index.ts +0 -116
- package/src/commands/azure/storage.ts +0 -478
- package/src/commands/azure/vm.ts +0 -355
- package/src/commands/billing/index.ts +0 -256
- package/src/commands/chat.ts +0 -320
- package/src/commands/completions.ts +0 -268
- package/src/commands/config.ts +0 -372
- package/src/commands/cost/cloud-cost-estimator.ts +0 -266
- package/src/commands/cost/estimator.ts +0 -79
- package/src/commands/cost/index.ts +0 -810
- package/src/commands/cost/parsers/terraform.ts +0 -273
- package/src/commands/cost/parsers/types.ts +0 -25
- package/src/commands/cost/pricing/aws.ts +0 -544
- package/src/commands/cost/pricing/azure.ts +0 -499
- package/src/commands/cost/pricing/gcp.ts +0 -396
- package/src/commands/cost/pricing/index.ts +0 -40
- package/src/commands/demo.ts +0 -250
- package/src/commands/deploy.ts +0 -260
- package/src/commands/doctor.ts +0 -1386
- package/src/commands/drift/index.ts +0 -787
- package/src/commands/explain.ts +0 -277
- package/src/commands/export.ts +0 -146
- package/src/commands/feedback.ts +0 -389
- package/src/commands/fix.ts +0 -324
- package/src/commands/fs/index.ts +0 -402
- package/src/commands/gcp/compute.ts +0 -325
- package/src/commands/gcp/functions.ts +0 -271
- package/src/commands/gcp/gke.ts +0 -438
- package/src/commands/gcp/iam.ts +0 -344
- package/src/commands/gcp/index.ts +0 -129
- package/src/commands/gcp/storage.ts +0 -284
- package/src/commands/generate-helm.ts +0 -1249
- package/src/commands/generate-k8s.ts +0 -1508
- package/src/commands/generate-terraform.ts +0 -1202
- package/src/commands/gh/index.ts +0 -863
- package/src/commands/git/index.ts +0 -1343
- package/src/commands/helm/index.ts +0 -1126
- package/src/commands/help.ts +0 -715
- package/src/commands/history.ts +0 -149
- package/src/commands/import.ts +0 -868
- package/src/commands/incident.ts +0 -166
- package/src/commands/index.ts +0 -367
- package/src/commands/init.ts +0 -1051
- package/src/commands/k8s/index.ts +0 -1137
- package/src/commands/login.ts +0 -716
- package/src/commands/logout.ts +0 -83
- package/src/commands/logs.ts +0 -167
- package/src/commands/onboarding.ts +0 -405
- package/src/commands/pipeline.ts +0 -186
- package/src/commands/plan/display.ts +0 -279
- package/src/commands/plan/index.ts +0 -599
- package/src/commands/plugin.ts +0 -398
- package/src/commands/preview.ts +0 -452
- package/src/commands/profile.ts +0 -342
- package/src/commands/questionnaire.ts +0 -1172
- package/src/commands/resume.ts +0 -47
- package/src/commands/rollback.ts +0 -315
- package/src/commands/rollout.ts +0 -88
- package/src/commands/runbook.ts +0 -346
- package/src/commands/schedule.ts +0 -236
- package/src/commands/status.ts +0 -252
- package/src/commands/team/index.ts +0 -346
- package/src/commands/team-context.ts +0 -220
- package/src/commands/template.ts +0 -233
- package/src/commands/tf/index.ts +0 -1093
- package/src/commands/upgrade.ts +0 -609
- package/src/commands/usage/index.ts +0 -134
- package/src/commands/version.ts +0 -174
- package/src/commands/watch.ts +0 -153
- package/src/compat/index.ts +0 -2
- package/src/compat/runtime.ts +0 -12
- package/src/compat/sqlite.ts +0 -177
- package/src/config/index.ts +0 -17
- package/src/config/manager.ts +0 -530
- package/src/config/mode-store.ts +0 -62
- package/src/config/profiles.ts +0 -84
- package/src/config/safety-policy.ts +0 -358
- package/src/config/schema.ts +0 -125
- package/src/config/types.ts +0 -609
- package/src/config/workspace-state.ts +0 -53
- package/src/context/context-db.ts +0 -199
- package/src/demo/index.ts +0 -349
- package/src/demo/scenarios/full-journey.ts +0 -229
- package/src/demo/scenarios/getting-started.ts +0 -127
- package/src/demo/scenarios/helm-release.ts +0 -341
- package/src/demo/scenarios/k8s-deployment.ts +0 -194
- package/src/demo/scenarios/terraform-vpc.ts +0 -170
- package/src/demo/types.ts +0 -92
- package/src/engine/cost-estimator.ts +0 -480
- package/src/engine/diagram-generator.ts +0 -256
- package/src/engine/drift-detector.ts +0 -902
- package/src/engine/executor.ts +0 -1066
- package/src/engine/index.ts +0 -76
- package/src/engine/orchestrator.ts +0 -636
- package/src/engine/planner.ts +0 -787
- package/src/engine/safety.ts +0 -743
- package/src/engine/verifier.ts +0 -770
- package/src/enterprise/audit.ts +0 -348
- package/src/enterprise/auth.ts +0 -270
- package/src/enterprise/billing.ts +0 -822
- package/src/enterprise/index.ts +0 -17
- package/src/enterprise/teams.ts +0 -443
- package/src/generator/best-practices.ts +0 -1608
- package/src/generator/helm.ts +0 -630
- package/src/generator/index.ts +0 -37
- package/src/generator/intent-parser.ts +0 -514
- package/src/generator/kubernetes.ts +0 -976
- package/src/generator/terraform.ts +0 -1875
- package/src/history/index.ts +0 -8
- package/src/history/manager.ts +0 -250
- package/src/history/types.ts +0 -34
- package/src/hooks/config.ts +0 -432
- package/src/hooks/engine.ts +0 -392
- package/src/hooks/index.ts +0 -4
- package/src/llm/auth-bridge.ts +0 -198
- package/src/llm/circuit-breaker.ts +0 -140
- package/src/llm/config-loader.ts +0 -201
- package/src/llm/cost-calculator.ts +0 -171
- package/src/llm/index.ts +0 -8
- package/src/llm/model-aliases.ts +0 -115
- package/src/llm/provider-registry.ts +0 -63
- package/src/llm/providers/anthropic.ts +0 -462
- package/src/llm/providers/bedrock.ts +0 -477
- package/src/llm/providers/google.ts +0 -405
- package/src/llm/providers/ollama.ts +0 -767
- package/src/llm/providers/openai-compatible.ts +0 -340
- package/src/llm/providers/openai.ts +0 -328
- package/src/llm/providers/openrouter.ts +0 -338
- package/src/llm/router.ts +0 -1104
- package/src/llm/types.ts +0 -232
- package/src/lsp/client.ts +0 -298
- package/src/lsp/languages.ts +0 -119
- package/src/lsp/manager.ts +0 -294
- package/src/mcp/client.ts +0 -402
- package/src/mcp/index.ts +0 -5
- package/src/mcp/manager.ts +0 -133
- package/src/nimbus.ts +0 -234
- package/src/plugins/index.ts +0 -27
- package/src/plugins/loader.ts +0 -334
- package/src/plugins/manager.ts +0 -376
- package/src/plugins/types.ts +0 -284
- package/src/scanners/cicd-scanner.ts +0 -258
- package/src/scanners/cloud-scanner.ts +0 -466
- package/src/scanners/framework-scanner.ts +0 -469
- package/src/scanners/iac-scanner.ts +0 -388
- package/src/scanners/index.ts +0 -539
- package/src/scanners/language-scanner.ts +0 -276
- package/src/scanners/package-manager-scanner.ts +0 -277
- package/src/scanners/types.ts +0 -172
- package/src/sessions/manager.ts +0 -472
- package/src/sessions/types.ts +0 -44
- package/src/sharing/sync.ts +0 -300
- package/src/sharing/viewer.ts +0 -163
- package/src/snapshots/index.ts +0 -2
- package/src/snapshots/manager.ts +0 -530
- package/src/state/artifacts.ts +0 -147
- package/src/state/audit.ts +0 -137
- package/src/state/billing.ts +0 -240
- package/src/state/checkpoints.ts +0 -117
- package/src/state/config.ts +0 -67
- package/src/state/conversations.ts +0 -14
- package/src/state/credentials.ts +0 -154
- package/src/state/db.ts +0 -58
- package/src/state/index.ts +0 -26
- package/src/state/messages.ts +0 -115
- package/src/state/projects.ts +0 -123
- package/src/state/schema.ts +0 -236
- package/src/state/sessions.ts +0 -147
- package/src/state/teams.ts +0 -200
- package/src/telemetry.ts +0 -108
- package/src/tools/aws-ops.ts +0 -952
- package/src/tools/azure-ops.ts +0 -579
- package/src/tools/file-ops.ts +0 -615
- package/src/tools/gcp-ops.ts +0 -625
- package/src/tools/git-ops.ts +0 -773
- package/src/tools/github-ops.ts +0 -799
- package/src/tools/helm-ops.ts +0 -943
- package/src/tools/index.ts +0 -17
- package/src/tools/k8s-ops.ts +0 -819
- package/src/tools/schemas/converter.ts +0 -184
- package/src/tools/schemas/devops.ts +0 -3502
- package/src/tools/schemas/index.ts +0 -73
- package/src/tools/schemas/standard.ts +0 -1148
- package/src/tools/schemas/types.ts +0 -735
- package/src/tools/spawn-exec.ts +0 -148
- package/src/tools/terraform-ops.ts +0 -862
- package/src/types/ambient.d.ts +0 -193
- package/src/types/config.ts +0 -83
- package/src/types/drift.ts +0 -116
- package/src/types/enterprise.ts +0 -335
- package/src/types/index.ts +0 -20
- package/src/types/plan.ts +0 -44
- package/src/types/request.ts +0 -65
- package/src/types/response.ts +0 -54
- package/src/types/service.ts +0 -51
- package/src/ui/App.tsx +0 -2114
- package/src/ui/DeployPreview.tsx +0 -174
- package/src/ui/FileDiffModal.tsx +0 -162
- package/src/ui/Header.tsx +0 -131
- package/src/ui/HelpModal.tsx +0 -57
- package/src/ui/InputBox.tsx +0 -503
- package/src/ui/MessageList.tsx +0 -1032
- package/src/ui/PermissionPrompt.tsx +0 -163
- package/src/ui/StatusBar.tsx +0 -277
- package/src/ui/TerminalPane.tsx +0 -84
- package/src/ui/ToolCallDisplay.tsx +0 -643
- package/src/ui/TreePane.tsx +0 -132
- package/src/ui/chat-ui.ts +0 -850
- package/src/ui/index.ts +0 -33
- package/src/ui/ink/index.ts +0 -1444
- package/src/ui/streaming.ts +0 -176
- package/src/ui/theme.ts +0 -104
- package/src/ui/types.ts +0 -75
- package/src/utils/analytics.ts +0 -72
- package/src/utils/cost-warning.ts +0 -27
- package/src/utils/env.ts +0 -46
- package/src/utils/errors.ts +0 -69
- package/src/utils/event-bus.ts +0 -38
- package/src/utils/index.ts +0 -24
- package/src/utils/logger.ts +0 -171
- package/src/utils/rate-limiter.ts +0 -121
- package/src/utils/service-auth.ts +0 -49
- package/src/utils/validation.ts +0 -53
- package/src/version.ts +0 -4
- package/src/watcher/index.ts +0 -214
- package/src/wizard/approval.ts +0 -383
- package/src/wizard/index.ts +0 -25
- package/src/wizard/prompts.ts +0 -338
- package/src/wizard/types.ts +0 -172
- package/src/wizard/ui.ts +0 -556
- package/src/wizard/wizard.ts +0 -304
- package/tsconfig.json +0 -24
package/src/clients/ws-client.ts
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { logger } from '../utils';
|
|
2
|
-
|
|
3
|
-
export interface WebSocketClientOptions {
|
|
4
|
-
reconnect?: boolean;
|
|
5
|
-
reconnectInterval?: number;
|
|
6
|
-
maxReconnectAttempts?: number;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* WebSocket Client for streaming communication
|
|
11
|
-
*/
|
|
12
|
-
export class WebSocketClient {
|
|
13
|
-
private url: string;
|
|
14
|
-
private ws: WebSocket | null = null;
|
|
15
|
-
private options: Required<WebSocketClientOptions>;
|
|
16
|
-
private reconnectAttempts = 0;
|
|
17
|
-
private messageHandlers: Set<(data: any) => void> = new Set();
|
|
18
|
-
private errorHandlers: Set<(error: Event) => void> = new Set();
|
|
19
|
-
private closeHandlers: Set<() => void> = new Set();
|
|
20
|
-
|
|
21
|
-
constructor(url: string, options: WebSocketClientOptions = {}) {
|
|
22
|
-
this.url = url;
|
|
23
|
-
this.options = {
|
|
24
|
-
reconnect: options.reconnect ?? true,
|
|
25
|
-
reconnectInterval: options.reconnectInterval ?? 3000,
|
|
26
|
-
maxReconnectAttempts: options.maxReconnectAttempts ?? 5,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
connect(): Promise<void> {
|
|
31
|
-
return new Promise((resolve, reject) => {
|
|
32
|
-
try {
|
|
33
|
-
this.ws = new WebSocket(this.url);
|
|
34
|
-
|
|
35
|
-
this.ws.onopen = () => {
|
|
36
|
-
logger.info(`WebSocket connected to ${this.url}`);
|
|
37
|
-
this.reconnectAttempts = 0;
|
|
38
|
-
resolve();
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
this.ws.onmessage = event => {
|
|
42
|
-
try {
|
|
43
|
-
const data = JSON.parse(event.data);
|
|
44
|
-
this.messageHandlers.forEach(handler => handler(data));
|
|
45
|
-
} catch (error) {
|
|
46
|
-
logger.error('Failed to parse WebSocket message', error);
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
this.ws.onerror = event => {
|
|
51
|
-
logger.error('WebSocket error', event);
|
|
52
|
-
this.errorHandlers.forEach(handler => handler(event));
|
|
53
|
-
reject(event);
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
this.ws.onclose = () => {
|
|
57
|
-
logger.warn(`WebSocket disconnected from ${this.url}`);
|
|
58
|
-
this.closeHandlers.forEach(handler => handler());
|
|
59
|
-
|
|
60
|
-
// Auto-reconnect
|
|
61
|
-
if (
|
|
62
|
-
this.options.reconnect &&
|
|
63
|
-
this.reconnectAttempts < this.options.maxReconnectAttempts
|
|
64
|
-
) {
|
|
65
|
-
this.reconnectAttempts++;
|
|
66
|
-
logger.info(
|
|
67
|
-
`Attempting to reconnect (${this.reconnectAttempts}/${this.options.maxReconnectAttempts})...`
|
|
68
|
-
);
|
|
69
|
-
setTimeout(() => {
|
|
70
|
-
this.connect().catch(() => {
|
|
71
|
-
// Ignore, will retry or give up
|
|
72
|
-
});
|
|
73
|
-
}, this.options.reconnectInterval);
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
} catch (error) {
|
|
77
|
-
reject(error);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
send(data: any): void {
|
|
83
|
-
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
84
|
-
throw new Error('WebSocket is not connected');
|
|
85
|
-
}
|
|
86
|
-
this.ws.send(JSON.stringify(data));
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
onMessage(handler: (data: any) => void): () => void {
|
|
90
|
-
this.messageHandlers.add(handler);
|
|
91
|
-
return () => this.messageHandlers.delete(handler);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
onError(handler: (error: Event) => void): () => void {
|
|
95
|
-
this.errorHandlers.add(handler);
|
|
96
|
-
return () => this.errorHandlers.delete(handler);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
onClose(handler: () => void): () => void {
|
|
100
|
-
this.closeHandlers.add(handler);
|
|
101
|
-
return () => this.closeHandlers.delete(handler);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
close(): void {
|
|
105
|
-
if (this.ws) {
|
|
106
|
-
this.options.reconnect = false; // Prevent auto-reconnect
|
|
107
|
-
this.ws.close();
|
|
108
|
-
this.ws = null;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
isConnected(): boolean {
|
|
113
|
-
return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
|
|
114
|
-
}
|
|
115
|
-
}
|
package/src/commands/alias.ts
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Alias Command — L2
|
|
3
|
-
*
|
|
4
|
-
* Create, list, and remove command aliases stored in ~/.nimbus/aliases.json.
|
|
5
|
-
*
|
|
6
|
-
* Usage:
|
|
7
|
-
* nimbus alias deploy=run --auto-approve "deploy staging"
|
|
8
|
-
* nimbus alias list
|
|
9
|
-
* nimbus alias remove deploy
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import * as fs from 'node:fs';
|
|
13
|
-
import * as path from 'node:path';
|
|
14
|
-
import * as os from 'node:os';
|
|
15
|
-
import { ui } from '../wizard/ui';
|
|
16
|
-
|
|
17
|
-
const ALIASES_FILE = path.join(os.homedir(), '.nimbus', 'aliases.json');
|
|
18
|
-
|
|
19
|
-
function loadAliases(): Record<string, string> {
|
|
20
|
-
try {
|
|
21
|
-
return JSON.parse(fs.readFileSync(ALIASES_FILE, 'utf-8')) as Record<string, string>;
|
|
22
|
-
} catch {
|
|
23
|
-
return {};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function saveAliases(aliases: Record<string, string>): void {
|
|
28
|
-
const dir = path.dirname(ALIASES_FILE);
|
|
29
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
30
|
-
fs.writeFileSync(ALIASES_FILE, JSON.stringify(aliases, null, 2), 'utf-8');
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Resolve the first arg as an alias if one exists.
|
|
35
|
-
* Returns the original args unchanged if no alias matches.
|
|
36
|
-
*/
|
|
37
|
-
export function resolveAlias(args: string[]): string[] {
|
|
38
|
-
if (!args.length) return args;
|
|
39
|
-
const aliases = loadAliases();
|
|
40
|
-
const expanded = aliases[args[0]];
|
|
41
|
-
if (!expanded) return args;
|
|
42
|
-
// Split the alias value on spaces and prepend to remaining args
|
|
43
|
-
return [...expanded.split(' '), ...args.slice(1)];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Alias command handler.
|
|
48
|
-
*/
|
|
49
|
-
export async function aliasCommand(subcommand: string, args: string[]): Promise<void> {
|
|
50
|
-
const aliases = loadAliases();
|
|
51
|
-
|
|
52
|
-
if (subcommand === 'list' || (!subcommand && args.length === 0)) {
|
|
53
|
-
ui.header('Command Aliases');
|
|
54
|
-
const entries = Object.entries(aliases);
|
|
55
|
-
if (entries.length === 0) {
|
|
56
|
-
ui.info('No aliases defined. Create one: nimbus alias <name>=<command>');
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
for (const [name, cmd] of entries) {
|
|
60
|
-
ui.print(` ${ui.color(name, 'green')} = ${cmd}`);
|
|
61
|
-
}
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (subcommand === 'remove' || subcommand === 'rm') {
|
|
66
|
-
const name = args[0];
|
|
67
|
-
if (!name) {
|
|
68
|
-
ui.error('Usage: nimbus alias remove <name>');
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
if (!(name in aliases)) {
|
|
72
|
-
ui.warning(`Alias "${name}" not found`);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
delete aliases[name];
|
|
76
|
-
saveAliases(aliases);
|
|
77
|
-
ui.success(`Removed alias: ${name}`);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
// Create alias: subcommand is "<name>=<rest>" or subcommand is the name and args hold the expansion
|
|
82
|
-
const raw = subcommand + (args.length ? ' ' + args.join(' ') : '');
|
|
83
|
-
const eqIdx = raw.indexOf('=');
|
|
84
|
-
if (eqIdx === -1) {
|
|
85
|
-
ui.error('Usage: nimbus alias <name>=<command> or nimbus alias list or nimbus alias remove <name>');
|
|
86
|
-
process.exit(1);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const name = raw.slice(0, eqIdx).trim();
|
|
90
|
-
const cmd = raw.slice(eqIdx + 1).trim();
|
|
91
|
-
|
|
92
|
-
if (!name || !cmd) {
|
|
93
|
-
ui.error('Alias name and command must not be empty');
|
|
94
|
-
process.exit(1);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
aliases[name] = cmd;
|
|
98
|
-
saveAliases(aliases);
|
|
99
|
-
ui.success(`Alias set: ${ui.color(name, 'green')} = ${cmd}`);
|
|
100
|
-
}
|
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Analyze Command
|
|
3
|
-
* Codebase analysis and refactoring suggestions
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { ui } from '../../wizard/ui';
|
|
7
|
-
import type { AnalyzeOptions, CodeAnalysis, RefactoringSuggestion } from '../../types';
|
|
8
|
-
import * as fs from 'node:fs';
|
|
9
|
-
import * as path from 'node:path';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Parse analyze options
|
|
13
|
-
*/
|
|
14
|
-
export function parseAnalyzeOptions(args: string[]): AnalyzeOptions {
|
|
15
|
-
const options: AnalyzeOptions = {
|
|
16
|
-
type: 'all',
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
for (let i = 0; i < args.length; i++) {
|
|
20
|
-
const arg = args[i];
|
|
21
|
-
if (arg === '--type' && args[i + 1]) {
|
|
22
|
-
options.type = args[++i] as AnalyzeOptions['type'];
|
|
23
|
-
} else if (arg === '--path' && args[i + 1]) {
|
|
24
|
-
options.path = args[++i];
|
|
25
|
-
} else if (arg === '--json') {
|
|
26
|
-
options.json = true;
|
|
27
|
-
} else if (arg === '--security') {
|
|
28
|
-
// Shortcut for --type security
|
|
29
|
-
options.type = 'security';
|
|
30
|
-
} else if (arg === '--compliance' && args[i + 1]) {
|
|
31
|
-
// Set compliance standard (soc2, hipaa, pci)
|
|
32
|
-
options.type = 'security';
|
|
33
|
-
(options as any).compliance = args[++i];
|
|
34
|
-
} else if (!arg.startsWith('-') && !options.path) {
|
|
35
|
-
options.path = arg;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return options;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Get files to analyze
|
|
44
|
-
*/
|
|
45
|
-
function getFilesToAnalyze(basePath: string, extensions: string[]): string[] {
|
|
46
|
-
const files: string[] = [];
|
|
47
|
-
|
|
48
|
-
function walk(dir: string) {
|
|
49
|
-
try {
|
|
50
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
51
|
-
|
|
52
|
-
for (const entry of entries) {
|
|
53
|
-
const fullPath = path.join(dir, entry.name);
|
|
54
|
-
|
|
55
|
-
// Skip node_modules, .git, etc.
|
|
56
|
-
if (entry.isDirectory()) {
|
|
57
|
-
if (!['node_modules', '.git', 'dist', 'build', 'coverage'].includes(entry.name)) {
|
|
58
|
-
walk(fullPath);
|
|
59
|
-
}
|
|
60
|
-
} else if (entry.isFile()) {
|
|
61
|
-
const ext = path.extname(entry.name);
|
|
62
|
-
if (extensions.includes(ext)) {
|
|
63
|
-
files.push(fullPath);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
} catch {
|
|
68
|
-
// Ignore permission errors
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
walk(basePath);
|
|
73
|
-
return files;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Analyze a single file for potential improvements
|
|
78
|
-
*/
|
|
79
|
-
function analyzeFile(filePath: string, type: AnalyzeOptions['type']): RefactoringSuggestion[] {
|
|
80
|
-
const suggestions: RefactoringSuggestion[] = [];
|
|
81
|
-
|
|
82
|
-
try {
|
|
83
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
84
|
-
const lines = content.split('\n');
|
|
85
|
-
const relativePath = path.relative(process.cwd(), filePath);
|
|
86
|
-
|
|
87
|
-
// Simple pattern-based analysis
|
|
88
|
-
lines.forEach((line, index) => {
|
|
89
|
-
const lineNum = index + 1;
|
|
90
|
-
|
|
91
|
-
// Complexity: Long lines
|
|
92
|
-
if (type === 'all' || type === 'refactor') {
|
|
93
|
-
if (line.length > 120) {
|
|
94
|
-
suggestions.push({
|
|
95
|
-
file: relativePath,
|
|
96
|
-
line: lineNum,
|
|
97
|
-
type: 'style',
|
|
98
|
-
severity: 'info',
|
|
99
|
-
explanation: `Line exceeds 120 characters (${line.length}). Consider breaking it up.`,
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Nested callbacks (callback hell indicator)
|
|
104
|
-
const nestedCallbacks = (line.match(/\)\s*=>\s*\{/g) || []).length;
|
|
105
|
-
if (nestedCallbacks >= 2) {
|
|
106
|
-
suggestions.push({
|
|
107
|
-
file: relativePath,
|
|
108
|
-
line: lineNum,
|
|
109
|
-
type: 'complexity',
|
|
110
|
-
severity: 'warning',
|
|
111
|
-
explanation:
|
|
112
|
-
'Multiple nested arrow functions detected. Consider extracting to named functions.',
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// TODO/FIXME comments
|
|
117
|
-
if (/\/\/\s*(TODO|FIXME|HACK|XXX)/i.test(line)) {
|
|
118
|
-
suggestions.push({
|
|
119
|
-
file: relativePath,
|
|
120
|
-
line: lineNum,
|
|
121
|
-
type: 'style',
|
|
122
|
-
severity: 'info',
|
|
123
|
-
explanation: 'TODO/FIXME comment found. Consider addressing or tracking this.',
|
|
124
|
-
});
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Security checks
|
|
129
|
-
if (type === 'all' || type === 'security') {
|
|
130
|
-
// Hardcoded secrets patterns (variable names or quoted strings)
|
|
131
|
-
if (/\b(?:password|secret|api[_-]?key|token)\b\s*[:=]/i.test(line)) {
|
|
132
|
-
suggestions.push({
|
|
133
|
-
file: relativePath,
|
|
134
|
-
line: lineNum,
|
|
135
|
-
type: 'security',
|
|
136
|
-
severity: 'error',
|
|
137
|
-
explanation:
|
|
138
|
-
'Potential hardcoded credential detected. Use environment variables instead.',
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
// eval() usage
|
|
143
|
-
if (/\beval\s*\(/.test(line)) {
|
|
144
|
-
suggestions.push({
|
|
145
|
-
file: relativePath,
|
|
146
|
-
line: lineNum,
|
|
147
|
-
type: 'security',
|
|
148
|
-
severity: 'error',
|
|
149
|
-
explanation: 'eval() usage detected. This can lead to code injection vulnerabilities.',
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// SQL injection potential
|
|
154
|
-
if (/\$\{.*\}.*(?:SELECT|INSERT|UPDATE|DELETE|FROM|WHERE)/i.test(line)) {
|
|
155
|
-
suggestions.push({
|
|
156
|
-
file: relativePath,
|
|
157
|
-
line: lineNum,
|
|
158
|
-
type: 'security',
|
|
159
|
-
severity: 'warning',
|
|
160
|
-
explanation:
|
|
161
|
-
'Potential SQL injection. Use parameterized queries instead of string interpolation.',
|
|
162
|
-
});
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Documentation checks
|
|
167
|
-
if (type === 'all' || type === 'docs') {
|
|
168
|
-
// Functions without JSDoc
|
|
169
|
-
if (/^(?:export\s+)?(?:async\s+)?function\s+\w+/.test(line)) {
|
|
170
|
-
const prevLine = index > 0 ? lines[index - 1] : '';
|
|
171
|
-
if (!/\*\/\s*$/.test(prevLine)) {
|
|
172
|
-
suggestions.push({
|
|
173
|
-
file: relativePath,
|
|
174
|
-
line: lineNum,
|
|
175
|
-
type: 'style',
|
|
176
|
-
severity: 'info',
|
|
177
|
-
explanation: 'Function lacks JSDoc documentation.',
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
// File-level checks
|
|
185
|
-
if (type === 'all' || type === 'refactor') {
|
|
186
|
-
// Large file
|
|
187
|
-
if (lines.length > 500) {
|
|
188
|
-
suggestions.push({
|
|
189
|
-
file: relativePath,
|
|
190
|
-
line: 1,
|
|
191
|
-
type: 'complexity',
|
|
192
|
-
severity: 'warning',
|
|
193
|
-
explanation: `File has ${lines.length} lines. Consider splitting into smaller modules.`,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
} catch {
|
|
198
|
-
// Skip files we can't read
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
return suggestions;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Display severity with color
|
|
206
|
-
*/
|
|
207
|
-
function formatSeverity(severity: RefactoringSuggestion['severity']): string {
|
|
208
|
-
switch (severity) {
|
|
209
|
-
case 'error':
|
|
210
|
-
return ui.color('ERROR', 'red');
|
|
211
|
-
case 'warning':
|
|
212
|
-
return ui.color('WARN', 'yellow');
|
|
213
|
-
case 'info':
|
|
214
|
-
default:
|
|
215
|
-
return ui.color('INFO', 'blue');
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Analyze command
|
|
221
|
-
*/
|
|
222
|
-
export async function analyzeCommand(options: AnalyzeOptions): Promise<void> {
|
|
223
|
-
const targetPath = options.path || process.cwd();
|
|
224
|
-
|
|
225
|
-
if (!fs.existsSync(targetPath)) {
|
|
226
|
-
ui.error(`Path not found: ${targetPath}`);
|
|
227
|
-
return;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
ui.header('Nimbus Analyze', targetPath);
|
|
231
|
-
ui.startSpinner({ message: 'Analyzing codebase...' });
|
|
232
|
-
|
|
233
|
-
// Get files to analyze
|
|
234
|
-
const extensions = ['.ts', '.tsx', '.js', '.jsx', '.mjs'];
|
|
235
|
-
const files = getFilesToAnalyze(targetPath, extensions);
|
|
236
|
-
|
|
237
|
-
if (files.length === 0) {
|
|
238
|
-
ui.stopSpinnerSuccess('No files found to analyze');
|
|
239
|
-
return;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// Analyze files
|
|
243
|
-
const allSuggestions: RefactoringSuggestion[] = [];
|
|
244
|
-
|
|
245
|
-
for (const file of files) {
|
|
246
|
-
const suggestions = analyzeFile(file, options.type);
|
|
247
|
-
allSuggestions.push(...suggestions);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
ui.stopSpinnerSuccess(`Analyzed ${files.length} files`);
|
|
251
|
-
|
|
252
|
-
// Track analysis completion
|
|
253
|
-
try {
|
|
254
|
-
const { trackEvent } = await import('../../telemetry');
|
|
255
|
-
trackEvent('analysis_completed', {
|
|
256
|
-
filesAnalyzed: files.length,
|
|
257
|
-
suggestionsCount: allSuggestions.length,
|
|
258
|
-
});
|
|
259
|
-
} catch {
|
|
260
|
-
/* telemetry failure is non-critical */
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Build analysis result
|
|
264
|
-
const byType: Record<string, number> = {};
|
|
265
|
-
const bySeverity: Record<string, number> = {};
|
|
266
|
-
|
|
267
|
-
for (const s of allSuggestions) {
|
|
268
|
-
byType[s.type] = (byType[s.type] || 0) + 1;
|
|
269
|
-
bySeverity[s.severity] = (bySeverity[s.severity] || 0) + 1;
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const analysis: CodeAnalysis = {
|
|
273
|
-
path: targetPath,
|
|
274
|
-
analyzedAt: new Date().toISOString(),
|
|
275
|
-
summary: {
|
|
276
|
-
filesAnalyzed: files.length,
|
|
277
|
-
suggestionsCount: allSuggestions.length,
|
|
278
|
-
byType,
|
|
279
|
-
bySeverity,
|
|
280
|
-
},
|
|
281
|
-
suggestions: allSuggestions,
|
|
282
|
-
};
|
|
283
|
-
|
|
284
|
-
if (options.json) {
|
|
285
|
-
console.log(JSON.stringify(analysis, null, 2));
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// Display results
|
|
290
|
-
ui.newLine();
|
|
291
|
-
ui.section('Summary');
|
|
292
|
-
ui.print(` Files analyzed: ${analysis.summary.filesAnalyzed}`);
|
|
293
|
-
ui.print(` Total suggestions: ${analysis.summary.suggestionsCount}`);
|
|
294
|
-
|
|
295
|
-
if (analysis.summary.suggestionsCount > 0) {
|
|
296
|
-
ui.newLine();
|
|
297
|
-
ui.print(' By severity:');
|
|
298
|
-
if (bySeverity.error) {
|
|
299
|
-
ui.print(` ${ui.color('Errors:', 'red')} ${bySeverity.error}`);
|
|
300
|
-
}
|
|
301
|
-
if (bySeverity.warning) {
|
|
302
|
-
ui.print(` ${ui.color('Warnings:', 'yellow')} ${bySeverity.warning}`);
|
|
303
|
-
}
|
|
304
|
-
if (bySeverity.info) {
|
|
305
|
-
ui.print(` ${ui.color('Info:', 'blue')} ${bySeverity.info}`);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
ui.newLine();
|
|
309
|
-
ui.print(' By type:');
|
|
310
|
-
for (const [type, count] of Object.entries(byType)) {
|
|
311
|
-
ui.print(` ${type}: ${count}`);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Show top suggestions
|
|
316
|
-
if (allSuggestions.length > 0) {
|
|
317
|
-
ui.section('Suggestions');
|
|
318
|
-
|
|
319
|
-
// Sort by severity (error > warning > info)
|
|
320
|
-
const sorted = allSuggestions.sort((a, b) => {
|
|
321
|
-
const order = { error: 0, warning: 1, info: 2 };
|
|
322
|
-
return order[a.severity] - order[b.severity];
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
// Show top 20
|
|
326
|
-
const toShow = sorted.slice(0, 20);
|
|
327
|
-
|
|
328
|
-
for (const suggestion of toShow) {
|
|
329
|
-
ui.newLine();
|
|
330
|
-
ui.print(` ${formatSeverity(suggestion.severity)} ${suggestion.file}:${suggestion.line}`);
|
|
331
|
-
ui.print(` ${ui.dim(suggestion.type)}: ${suggestion.explanation}`);
|
|
332
|
-
|
|
333
|
-
if (suggestion.diff) {
|
|
334
|
-
ui.sideBySideDiff({
|
|
335
|
-
original: suggestion.original || '',
|
|
336
|
-
modified: suggestion.suggested || '',
|
|
337
|
-
});
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (allSuggestions.length > 20) {
|
|
342
|
-
ui.newLine();
|
|
343
|
-
ui.dim(` ... and ${allSuggestions.length - 20} more suggestions`);
|
|
344
|
-
ui.dim(` Use --json for full output`);
|
|
345
|
-
}
|
|
346
|
-
} else {
|
|
347
|
-
ui.newLine();
|
|
348
|
-
ui.success('No issues found!');
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
ui.newLine();
|
|
352
|
-
}
|