@vibecheckai/cli 3.4.0 → 3.5.1
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/bin/registry.js +154 -338
- package/bin/runners/context/generators/mcp.js +13 -15
- package/bin/runners/context/proof-context.js +1 -248
- package/bin/runners/lib/analysis-core.js +180 -198
- package/bin/runners/lib/analyzers.js +223 -1669
- package/bin/runners/lib/cli-output.js +210 -242
- package/bin/runners/lib/detectors-v2.js +785 -547
- package/bin/runners/lib/entitlements-v2.js +458 -96
- package/bin/runners/lib/error-handler.js +9 -16
- package/bin/runners/lib/global-flags.js +0 -37
- package/bin/runners/lib/route-truth.js +322 -1167
- package/bin/runners/lib/scan-output.js +469 -448
- package/bin/runners/lib/ship-output.js +27 -280
- package/bin/runners/lib/terminal-ui.js +733 -231
- package/bin/runners/lib/truth.js +321 -1004
- package/bin/runners/lib/unified-output.js +158 -162
- package/bin/runners/lib/upsell.js +204 -104
- package/bin/runners/runAllowlist.js +324 -0
- package/bin/runners/runAuth.js +95 -324
- package/bin/runners/runCheckpoint.js +21 -39
- package/bin/runners/runContext.js +24 -136
- package/bin/runners/runDoctor.js +67 -115
- package/bin/runners/runEvidencePack.js +219 -0
- package/bin/runners/runFix.js +5 -6
- package/bin/runners/runGuard.js +118 -212
- package/bin/runners/runInit.js +2 -14
- package/bin/runners/runInstall.js +281 -0
- package/bin/runners/runLabs.js +341 -0
- package/bin/runners/runMcp.js +52 -130
- package/bin/runners/runPolish.js +20 -43
- package/bin/runners/runProve.js +3 -13
- package/bin/runners/runReality.js +0 -14
- package/bin/runners/runReport.js +2 -3
- package/bin/runners/runScan.js +44 -511
- package/bin/runners/runShip.js +14 -28
- package/bin/runners/runValidate.js +2 -19
- package/bin/runners/runWatch.js +54 -118
- package/bin/vibecheck.js +41 -148
- package/mcp-server/ARCHITECTURE.md +339 -0
- package/mcp-server/__tests__/cache.test.ts +313 -0
- package/mcp-server/__tests__/executor.test.ts +239 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.cache/webpack/cache.pack +1 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.next/server/chunk.js +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.turbo/cache.json +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/.venv/lib/env.py +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/dist/bundle.js +3 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/package.json +5 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/src/app.ts +5 -0
- package/mcp-server/__tests__/fixtures/exclusion-test/venv/lib/config.py +4 -0
- package/mcp-server/__tests__/ids.test.ts +345 -0
- package/mcp-server/__tests__/integration/tools.test.ts +410 -0
- package/mcp-server/__tests__/registry.test.ts +365 -0
- package/mcp-server/__tests__/sandbox.test.ts +323 -0
- package/mcp-server/__tests__/schemas.test.ts +372 -0
- package/mcp-server/benchmarks/run-benchmarks.ts +304 -0
- package/mcp-server/examples/doctor.request.json +14 -0
- package/mcp-server/examples/doctor.response.json +53 -0
- package/mcp-server/examples/error.response.json +15 -0
- package/mcp-server/examples/scan.request.json +14 -0
- package/mcp-server/examples/scan.response.json +108 -0
- package/mcp-server/handlers/tool-handler.ts +671 -0
- package/mcp-server/index-v3.ts +293 -0
- package/mcp-server/index.js +1072 -1573
- package/mcp-server/index.old.js +4137 -0
- package/mcp-server/lib/cache.ts +341 -0
- package/mcp-server/lib/errors.ts +346 -0
- package/mcp-server/lib/executor.ts +792 -0
- package/mcp-server/lib/ids.ts +238 -0
- package/mcp-server/lib/logger.ts +368 -0
- package/mcp-server/lib/metrics.ts +365 -0
- package/mcp-server/lib/sandbox.ts +337 -0
- package/mcp-server/lib/validator.ts +229 -0
- package/mcp-server/package-lock.json +165 -0
- package/mcp-server/package.json +32 -7
- package/mcp-server/premium-tools.js +2 -2
- package/mcp-server/registry/tools.json +476 -0
- package/mcp-server/schemas/error-envelope.schema.json +125 -0
- package/mcp-server/schemas/finding.schema.json +167 -0
- package/mcp-server/schemas/report-artifact.schema.json +88 -0
- package/mcp-server/schemas/run-request.schema.json +75 -0
- package/mcp-server/schemas/verdict.schema.json +168 -0
- package/mcp-server/tier-auth.d.ts +71 -0
- package/mcp-server/tier-auth.js +371 -183
- package/mcp-server/truth-context.js +90 -131
- package/mcp-server/truth-firewall-tools.js +1000 -1611
- package/mcp-server/tsconfig.json +34 -0
- package/mcp-server/vibecheck-tools.js +2 -2
- package/mcp-server/vitest.config.ts +16 -0
- package/package.json +3 -4
- package/bin/runners/lib/agent-firewall/ai/false-positive-analyzer.js +0 -474
- package/bin/runners/lib/agent-firewall/change-packet/builder.js +0 -488
- package/bin/runners/lib/agent-firewall/change-packet/schema.json +0 -228
- package/bin/runners/lib/agent-firewall/change-packet/store.js +0 -200
- package/bin/runners/lib/agent-firewall/claims/claim-types.js +0 -21
- package/bin/runners/lib/agent-firewall/claims/extractor.js +0 -303
- package/bin/runners/lib/agent-firewall/claims/patterns.js +0 -24
- package/bin/runners/lib/agent-firewall/critic/index.js +0 -151
- package/bin/runners/lib/agent-firewall/critic/judge.js +0 -432
- package/bin/runners/lib/agent-firewall/critic/prompts.js +0 -305
- package/bin/runners/lib/agent-firewall/evidence/auth-evidence.js +0 -88
- package/bin/runners/lib/agent-firewall/evidence/contract-evidence.js +0 -75
- package/bin/runners/lib/agent-firewall/evidence/env-evidence.js +0 -127
- package/bin/runners/lib/agent-firewall/evidence/resolver.js +0 -102
- package/bin/runners/lib/agent-firewall/evidence/route-evidence.js +0 -213
- package/bin/runners/lib/agent-firewall/evidence/side-effect-evidence.js +0 -145
- package/bin/runners/lib/agent-firewall/fs-hook/daemon.js +0 -19
- package/bin/runners/lib/agent-firewall/fs-hook/installer.js +0 -87
- package/bin/runners/lib/agent-firewall/fs-hook/watcher.js +0 -184
- package/bin/runners/lib/agent-firewall/git-hook/pre-commit.js +0 -163
- package/bin/runners/lib/agent-firewall/ide-extension/cursor.js +0 -107
- package/bin/runners/lib/agent-firewall/ide-extension/vscode.js +0 -68
- package/bin/runners/lib/agent-firewall/ide-extension/windsurf.js +0 -66
- package/bin/runners/lib/agent-firewall/interceptor/base.js +0 -304
- package/bin/runners/lib/agent-firewall/interceptor/cursor.js +0 -35
- package/bin/runners/lib/agent-firewall/interceptor/vscode.js +0 -35
- package/bin/runners/lib/agent-firewall/interceptor/windsurf.js +0 -34
- package/bin/runners/lib/agent-firewall/lawbook/distributor.js +0 -465
- package/bin/runners/lib/agent-firewall/lawbook/evaluator.js +0 -604
- package/bin/runners/lib/agent-firewall/lawbook/index.js +0 -304
- package/bin/runners/lib/agent-firewall/lawbook/registry.js +0 -514
- package/bin/runners/lib/agent-firewall/lawbook/schema.js +0 -420
- package/bin/runners/lib/agent-firewall/logger.js +0 -141
- package/bin/runners/lib/agent-firewall/policy/default-policy.json +0 -90
- package/bin/runners/lib/agent-firewall/policy/engine.js +0 -103
- package/bin/runners/lib/agent-firewall/policy/loader.js +0 -451
- package/bin/runners/lib/agent-firewall/policy/rules/auth-drift.js +0 -50
- package/bin/runners/lib/agent-firewall/policy/rules/contract-drift.js +0 -50
- package/bin/runners/lib/agent-firewall/policy/rules/fake-success.js +0 -86
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-env.js +0 -162
- package/bin/runners/lib/agent-firewall/policy/rules/ghost-route.js +0 -189
- package/bin/runners/lib/agent-firewall/policy/rules/scope.js +0 -93
- package/bin/runners/lib/agent-firewall/policy/rules/unsafe-side-effect.js +0 -57
- package/bin/runners/lib/agent-firewall/policy/schema.json +0 -183
- package/bin/runners/lib/agent-firewall/policy/verdict.js +0 -54
- package/bin/runners/lib/agent-firewall/proposal/extractor.js +0 -394
- package/bin/runners/lib/agent-firewall/proposal/index.js +0 -212
- package/bin/runners/lib/agent-firewall/proposal/schema.js +0 -251
- package/bin/runners/lib/agent-firewall/proposal/validator.js +0 -386
- package/bin/runners/lib/agent-firewall/reality/index.js +0 -332
- package/bin/runners/lib/agent-firewall/reality/state.js +0 -625
- package/bin/runners/lib/agent-firewall/reality/watcher.js +0 -322
- package/bin/runners/lib/agent-firewall/risk/index.js +0 -173
- package/bin/runners/lib/agent-firewall/risk/scorer.js +0 -328
- package/bin/runners/lib/agent-firewall/risk/thresholds.js +0 -321
- package/bin/runners/lib/agent-firewall/risk/vectors.js +0 -421
- package/bin/runners/lib/agent-firewall/simulator/diff-simulator.js +0 -472
- package/bin/runners/lib/agent-firewall/simulator/import-resolver.js +0 -346
- package/bin/runners/lib/agent-firewall/simulator/index.js +0 -181
- package/bin/runners/lib/agent-firewall/simulator/route-validator.js +0 -380
- package/bin/runners/lib/agent-firewall/time-machine/incident-correlator.js +0 -661
- package/bin/runners/lib/agent-firewall/time-machine/index.js +0 -267
- package/bin/runners/lib/agent-firewall/time-machine/replay-engine.js +0 -436
- package/bin/runners/lib/agent-firewall/time-machine/state-reconstructor.js +0 -490
- package/bin/runners/lib/agent-firewall/time-machine/timeline-builder.js +0 -530
- package/bin/runners/lib/agent-firewall/truthpack/index.js +0 -67
- package/bin/runners/lib/agent-firewall/truthpack/loader.js +0 -137
- package/bin/runners/lib/agent-firewall/unblock/planner.js +0 -337
- package/bin/runners/lib/agent-firewall/utils/ignore-checker.js +0 -118
- package/bin/runners/lib/api-client.js +0 -269
- package/bin/runners/lib/authority-badge.js +0 -425
- package/bin/runners/lib/engines/accessibility-engine.js +0 -190
- package/bin/runners/lib/engines/api-consistency-engine.js +0 -162
- package/bin/runners/lib/engines/ast-cache.js +0 -99
- package/bin/runners/lib/engines/code-quality-engine.js +0 -255
- package/bin/runners/lib/engines/console-logs-engine.js +0 -115
- package/bin/runners/lib/engines/cross-file-analysis-engine.js +0 -268
- package/bin/runners/lib/engines/dead-code-engine.js +0 -198
- package/bin/runners/lib/engines/deprecated-api-engine.js +0 -226
- package/bin/runners/lib/engines/empty-catch-engine.js +0 -150
- package/bin/runners/lib/engines/file-filter.js +0 -131
- package/bin/runners/lib/engines/hardcoded-secrets-engine.js +0 -251
- package/bin/runners/lib/engines/mock-data-engine.js +0 -272
- package/bin/runners/lib/engines/parallel-processor.js +0 -71
- package/bin/runners/lib/engines/performance-issues-engine.js +0 -265
- package/bin/runners/lib/engines/security-vulnerabilities-engine.js +0 -243
- package/bin/runners/lib/engines/todo-fixme-engine.js +0 -115
- package/bin/runners/lib/engines/type-aware-engine.js +0 -152
- package/bin/runners/lib/engines/unsafe-regex-engine.js +0 -225
- package/bin/runners/lib/engines/vibecheck-engines/README.md +0 -53
- package/bin/runners/lib/engines/vibecheck-engines/index.js +0 -15
- package/bin/runners/lib/engines/vibecheck-engines/lib/ast-cache.js +0 -164
- package/bin/runners/lib/engines/vibecheck-engines/lib/code-quality-engine.js +0 -291
- package/bin/runners/lib/engines/vibecheck-engines/lib/console-logs-engine.js +0 -83
- package/bin/runners/lib/engines/vibecheck-engines/lib/dead-code-engine.js +0 -198
- package/bin/runners/lib/engines/vibecheck-engines/lib/deprecated-api-engine.js +0 -275
- package/bin/runners/lib/engines/vibecheck-engines/lib/empty-catch-engine.js +0 -167
- package/bin/runners/lib/engines/vibecheck-engines/lib/file-filter.js +0 -217
- package/bin/runners/lib/engines/vibecheck-engines/lib/hardcoded-secrets-engine.js +0 -139
- package/bin/runners/lib/engines/vibecheck-engines/lib/mock-data-engine.js +0 -140
- package/bin/runners/lib/engines/vibecheck-engines/lib/parallel-processor.js +0 -164
- package/bin/runners/lib/engines/vibecheck-engines/lib/performance-issues-engine.js +0 -234
- package/bin/runners/lib/engines/vibecheck-engines/lib/type-aware-engine.js +0 -217
- package/bin/runners/lib/engines/vibecheck-engines/lib/unsafe-regex-engine.js +0 -78
- package/bin/runners/lib/engines/vibecheck-engines/package.json +0 -13
- package/bin/runners/lib/exit-codes.js +0 -275
- package/bin/runners/lib/fingerprint.js +0 -377
- package/bin/runners/lib/help-formatter.js +0 -413
- package/bin/runners/lib/logger.js +0 -38
- package/bin/runners/lib/ship-output-enterprise.js +0 -239
- package/bin/runners/lib/unified-cli-output.js +0 -604
- package/bin/runners/runAgent.d.ts +0 -5
- package/bin/runners/runAgent.js +0 -161
- package/bin/runners/runApprove.js +0 -1200
- package/bin/runners/runClassify.js +0 -859
- package/bin/runners/runContext.d.ts +0 -4
- package/bin/runners/runFirewall.d.ts +0 -5
- package/bin/runners/runFirewall.js +0 -134
- package/bin/runners/runFirewallHook.d.ts +0 -5
- package/bin/runners/runFirewallHook.js +0 -56
- package/bin/runners/runPolish.d.ts +0 -4
- package/bin/runners/runProof.zip +0 -0
- package/bin/runners/runTruth.d.ts +0 -5
- package/bin/runners/runTruth.js +0 -101
- package/mcp-server/HARDENING_SUMMARY.md +0 -299
- package/mcp-server/agent-firewall-interceptor.js +0 -500
- package/mcp-server/authority-tools.js +0 -569
- package/mcp-server/conductor/conflict-resolver.js +0 -588
- package/mcp-server/conductor/execution-planner.js +0 -544
- package/mcp-server/conductor/index.js +0 -377
- package/mcp-server/conductor/lock-manager.js +0 -615
- package/mcp-server/conductor/request-queue.js +0 -550
- package/mcp-server/conductor/session-manager.js +0 -500
- package/mcp-server/conductor/tools.js +0 -510
- package/mcp-server/lib/api-client.cjs +0 -13
- package/mcp-server/lib/logger.cjs +0 -30
- package/mcp-server/logger.js +0 -173
- package/mcp-server/tools-v3.js +0 -706
- package/mcp-server/vibecheck-mcp-server-3.2.0.tgz +0 -0
|
@@ -0,0 +1,792 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI/Core Execution Layer
|
|
3
|
+
*
|
|
4
|
+
* Thin wrapper around CLI commands with:
|
|
5
|
+
* - Timeout handling
|
|
6
|
+
* - Cancellation support
|
|
7
|
+
* - Output parsing
|
|
8
|
+
* - Error normalization
|
|
9
|
+
*
|
|
10
|
+
* CRITICAL: Windows-safe. No shell=true. Args array only.
|
|
11
|
+
* Zero Unix shell assumptions (no head/grep/sed/awk).
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { spawn, ChildProcess, spawnSync } from 'child_process';
|
|
15
|
+
import { join, dirname, resolve } from 'path';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
import { existsSync } from 'fs';
|
|
18
|
+
import { Errors, ErrorCode, VibecheckError, createErrorEnvelope, createSuccessEnvelope } from './errors.js';
|
|
19
|
+
import { createSandbox } from './sandbox.js';
|
|
20
|
+
import { getLogger } from './logger.js';
|
|
21
|
+
import { getGlobalCache } from './cache.js';
|
|
22
|
+
import { getMetricsCollector } from './metrics.js';
|
|
23
|
+
import { generateRequestId } from './ids.js';
|
|
24
|
+
|
|
25
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* CLI subcommands allowed - must be in registry
|
|
29
|
+
*/
|
|
30
|
+
const ALLOWED_SUBCOMMANDS = new Set([
|
|
31
|
+
'doctor', 'init', 'scan', 'ship', 'prove', 'reality',
|
|
32
|
+
'fix', 'guard', 'ctx', 'report', 'polish', 'status',
|
|
33
|
+
'share', 'badge', 'context', 'verify', 'gate',
|
|
34
|
+
]);
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Default timeouts per tool (in ms)
|
|
38
|
+
*/
|
|
39
|
+
const DEFAULT_TIMEOUTS: Record<string, number> = {
|
|
40
|
+
doctor: 30000,
|
|
41
|
+
init: 60000,
|
|
42
|
+
scan: 120000,
|
|
43
|
+
ship: 90000,
|
|
44
|
+
prove: 600000,
|
|
45
|
+
reality: 300000,
|
|
46
|
+
fix: 300000,
|
|
47
|
+
guard: 60000,
|
|
48
|
+
ctx: 90000,
|
|
49
|
+
report: 60000,
|
|
50
|
+
polish: 60000,
|
|
51
|
+
status: 10000,
|
|
52
|
+
share: 30000,
|
|
53
|
+
badge: 10000,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Execution options
|
|
58
|
+
*/
|
|
59
|
+
export interface ExecuteOptions {
|
|
60
|
+
projectPath: string;
|
|
61
|
+
timeout?: number;
|
|
62
|
+
cacheMode?: 'auto' | 'force' | 'skip';
|
|
63
|
+
cacheMaxAge?: number;
|
|
64
|
+
requestId?: string;
|
|
65
|
+
signal?: AbortSignal;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Execution result
|
|
70
|
+
*/
|
|
71
|
+
export interface ExecuteResult<T> {
|
|
72
|
+
ok: boolean;
|
|
73
|
+
data?: T;
|
|
74
|
+
error?: {
|
|
75
|
+
code: ErrorCode;
|
|
76
|
+
message: string;
|
|
77
|
+
};
|
|
78
|
+
cached?: boolean;
|
|
79
|
+
durationMs: number;
|
|
80
|
+
exitCode?: number;
|
|
81
|
+
stdout?: string;
|
|
82
|
+
stderr?: string;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Active processes for cancellation
|
|
87
|
+
*/
|
|
88
|
+
const activeProcesses = new Map<string, ChildProcess>();
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Concurrency control
|
|
92
|
+
*/
|
|
93
|
+
const workspaceLocks = new Map<string, number>();
|
|
94
|
+
const MAX_CONCURRENT_PER_WORKSPACE = 2;
|
|
95
|
+
const MAX_CONCURRENT_GLOBAL = 6;
|
|
96
|
+
let globalConcurrentCount = 0;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Get CLI binary path
|
|
100
|
+
*
|
|
101
|
+
* Searches multiple locations for the vibecheck CLI.
|
|
102
|
+
* Windows-safe: uses spawnSync with args array, no shell interpolation.
|
|
103
|
+
*/
|
|
104
|
+
function getCliBinPath(): string {
|
|
105
|
+
// Try multiple locations
|
|
106
|
+
const possiblePaths = [
|
|
107
|
+
join(__dirname, '..', '..', 'bin', 'vibecheck.js'),
|
|
108
|
+
join(__dirname, '..', '..', 'packages', 'cli', 'bin', 'vibecheck.js'),
|
|
109
|
+
join(__dirname, '..', '..', 'packages', 'cli', 'dist', 'standalone.js'),
|
|
110
|
+
join(__dirname, '..', '..', 'node_modules', '@vibecheckai', 'cli', 'bin', 'vibecheck.js'),
|
|
111
|
+
join(__dirname, '..', 'node_modules', '.bin', 'vibecheck'),
|
|
112
|
+
];
|
|
113
|
+
|
|
114
|
+
for (const binPath of possiblePaths) {
|
|
115
|
+
const resolvedPath = resolve(binPath);
|
|
116
|
+
if (existsSync(resolvedPath)) {
|
|
117
|
+
// Verify it works - use args array, NOT shell string
|
|
118
|
+
try {
|
|
119
|
+
const result = spawnSync('node', [resolvedPath, '--version'], {
|
|
120
|
+
encoding: 'utf-8',
|
|
121
|
+
timeout: 5000,
|
|
122
|
+
shell: false, // CRITICAL: No shell
|
|
123
|
+
windowsHide: true,
|
|
124
|
+
});
|
|
125
|
+
if (result.status === 0) {
|
|
126
|
+
return resolvedPath;
|
|
127
|
+
}
|
|
128
|
+
} catch {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Try global vibecheck
|
|
135
|
+
try {
|
|
136
|
+
const result = spawnSync(process.platform === 'win32' ? 'where' : 'which', ['vibecheck'], {
|
|
137
|
+
encoding: 'utf-8',
|
|
138
|
+
timeout: 5000,
|
|
139
|
+
shell: false,
|
|
140
|
+
windowsHide: true,
|
|
141
|
+
});
|
|
142
|
+
if (result.status === 0 && result.stdout) {
|
|
143
|
+
return result.stdout.trim().split('\n')[0];
|
|
144
|
+
}
|
|
145
|
+
} catch {
|
|
146
|
+
// Not found globally
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
throw new VibecheckError(
|
|
150
|
+
ErrorCode.DEPENDENCY_MISSING,
|
|
151
|
+
'vibecheck CLI not found. Run: npm install -g @vibecheckai/cli',
|
|
152
|
+
{ userAction: 'Install the vibecheck CLI globally or in your project' }
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Check if subcommand is allowed
|
|
158
|
+
*/
|
|
159
|
+
function validateSubcommand(command: string): void {
|
|
160
|
+
if (!ALLOWED_SUBCOMMANDS.has(command)) {
|
|
161
|
+
throw new VibecheckError(
|
|
162
|
+
ErrorCode.INVALID_INPUT,
|
|
163
|
+
`Unknown CLI subcommand: ${command}. Allowed: ${[...ALLOWED_SUBCOMMANDS].join(', ')}`,
|
|
164
|
+
{ userAction: 'Use a valid vibecheck subcommand' }
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Acquire concurrency slot
|
|
171
|
+
*/
|
|
172
|
+
async function acquireConcurrencySlot(workspace: string): Promise<void> {
|
|
173
|
+
// Check global limit
|
|
174
|
+
if (globalConcurrentCount >= MAX_CONCURRENT_GLOBAL) {
|
|
175
|
+
throw new VibecheckError(
|
|
176
|
+
ErrorCode.RATE_LIMITED,
|
|
177
|
+
`Global concurrency limit reached (${MAX_CONCURRENT_GLOBAL})`,
|
|
178
|
+
{ retryable: true, retryAfterMs: 1000 }
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Check workspace limit
|
|
183
|
+
const workspaceCount = workspaceLocks.get(workspace) ?? 0;
|
|
184
|
+
if (workspaceCount >= MAX_CONCURRENT_PER_WORKSPACE) {
|
|
185
|
+
throw new VibecheckError(
|
|
186
|
+
ErrorCode.RATE_LIMITED,
|
|
187
|
+
`Workspace concurrency limit reached (${MAX_CONCURRENT_PER_WORKSPACE})`,
|
|
188
|
+
{ retryable: true, retryAfterMs: 1000 }
|
|
189
|
+
);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Acquire slot
|
|
193
|
+
globalConcurrentCount++;
|
|
194
|
+
workspaceLocks.set(workspace, workspaceCount + 1);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Release concurrency slot
|
|
199
|
+
*/
|
|
200
|
+
function releaseConcurrencySlot(workspace: string): void {
|
|
201
|
+
globalConcurrentCount = Math.max(0, globalConcurrentCount - 1);
|
|
202
|
+
const workspaceCount = workspaceLocks.get(workspace) ?? 0;
|
|
203
|
+
if (workspaceCount <= 1) {
|
|
204
|
+
workspaceLocks.delete(workspace);
|
|
205
|
+
} else {
|
|
206
|
+
workspaceLocks.set(workspace, workspaceCount - 1);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Parse JSON from CLI output
|
|
212
|
+
*
|
|
213
|
+
* CLI output may contain ANSI codes, warnings, or other non-JSON lines.
|
|
214
|
+
* We extract the JSON object/array from the output.
|
|
215
|
+
*/
|
|
216
|
+
function parseJsonOutput<T>(stdout: string): T | null {
|
|
217
|
+
// Try direct parse first
|
|
218
|
+
try {
|
|
219
|
+
return JSON.parse(stdout) as T;
|
|
220
|
+
} catch {
|
|
221
|
+
// Try to extract JSON from output
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Find JSON object or array
|
|
225
|
+
const jsonMatch = stdout.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
|
|
226
|
+
if (jsonMatch) {
|
|
227
|
+
try {
|
|
228
|
+
return JSON.parse(jsonMatch[1]) as T;
|
|
229
|
+
} catch {
|
|
230
|
+
// Parse failed
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Execute a CLI command
|
|
239
|
+
*
|
|
240
|
+
* CRITICAL: Uses spawn with args array. No shell=true. Windows-safe.
|
|
241
|
+
*/
|
|
242
|
+
export async function executeCli<T>(
|
|
243
|
+
command: string,
|
|
244
|
+
args: string[],
|
|
245
|
+
options: ExecuteOptions
|
|
246
|
+
): Promise<ExecuteResult<T>> {
|
|
247
|
+
const logger = getLogger();
|
|
248
|
+
const metrics = getMetricsCollector();
|
|
249
|
+
const startTime = Date.now();
|
|
250
|
+
const requestId = options.requestId ?? generateRequestId();
|
|
251
|
+
|
|
252
|
+
// Validate subcommand
|
|
253
|
+
try {
|
|
254
|
+
validateSubcommand(command);
|
|
255
|
+
} catch (e) {
|
|
256
|
+
return {
|
|
257
|
+
ok: false,
|
|
258
|
+
error: { code: ErrorCode.INVALID_INPUT, message: (e as Error).message },
|
|
259
|
+
durationMs: Date.now() - startTime,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Validate project path
|
|
264
|
+
const sandbox = createSandbox({ workspace: options.projectPath });
|
|
265
|
+
const validation = sandbox.validate(options.projectPath);
|
|
266
|
+
if (!validation.allowed) {
|
|
267
|
+
return {
|
|
268
|
+
ok: false,
|
|
269
|
+
error: { code: ErrorCode.PATH_OUTSIDE_SANDBOX, message: validation.reason! },
|
|
270
|
+
durationMs: Date.now() - startTime,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Check cache
|
|
275
|
+
const cache = getGlobalCache();
|
|
276
|
+
const cacheKey = cache.generateKey(command, options.projectPath, { args });
|
|
277
|
+
|
|
278
|
+
if (options.cacheMode !== 'skip') {
|
|
279
|
+
const cached = cache.get<T>(cacheKey);
|
|
280
|
+
if (cached.cached) {
|
|
281
|
+
const maxAge = (options.cacheMaxAge ?? 300) * 1000;
|
|
282
|
+
if (cached.age < maxAge) {
|
|
283
|
+
logger.debug('Cache hit', { command, cacheAge: cached.age });
|
|
284
|
+
metrics.recordToolExecution(`vibecheck.${command}`, Date.now() - startTime, true, true);
|
|
285
|
+
return {
|
|
286
|
+
ok: true,
|
|
287
|
+
data: cached.data,
|
|
288
|
+
cached: true,
|
|
289
|
+
durationMs: Date.now() - startTime,
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Acquire concurrency slot
|
|
296
|
+
try {
|
|
297
|
+
await acquireConcurrencySlot(options.projectPath);
|
|
298
|
+
} catch (e) {
|
|
299
|
+
return {
|
|
300
|
+
ok: false,
|
|
301
|
+
error: { code: ErrorCode.RATE_LIMITED, message: (e as Error).message },
|
|
302
|
+
durationMs: Date.now() - startTime,
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Build command
|
|
307
|
+
let binPath: string;
|
|
308
|
+
try {
|
|
309
|
+
binPath = getCliBinPath();
|
|
310
|
+
} catch (e) {
|
|
311
|
+
releaseConcurrencySlot(options.projectPath);
|
|
312
|
+
return {
|
|
313
|
+
ok: false,
|
|
314
|
+
error: { code: ErrorCode.DEPENDENCY_MISSING, message: (e as Error).message },
|
|
315
|
+
durationMs: Date.now() - startTime,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Build full args array - args array ONLY, no shell string interpolation
|
|
320
|
+
const fullArgs = [binPath, command, '--json', ...args];
|
|
321
|
+
const timeout = options.timeout ?? DEFAULT_TIMEOUTS[command] ?? 120000;
|
|
322
|
+
|
|
323
|
+
logger.info('Executing CLI', { command, args, timeout, requestId });
|
|
324
|
+
|
|
325
|
+
return new Promise((resolve) => {
|
|
326
|
+
let stdout = '';
|
|
327
|
+
let stderr = '';
|
|
328
|
+
let completed = false;
|
|
329
|
+
let timeoutId: NodeJS.Timeout | undefined;
|
|
330
|
+
|
|
331
|
+
// Spawn process - CRITICAL: shell: false (default, but explicit)
|
|
332
|
+
const child = spawn('node', fullArgs, {
|
|
333
|
+
cwd: options.projectPath,
|
|
334
|
+
env: {
|
|
335
|
+
...process.env,
|
|
336
|
+
VIBECHECK_SKIP_AUTH: '1',
|
|
337
|
+
VIBECHECK_JSON_OUTPUT: '1',
|
|
338
|
+
VIBECHECK_REQUEST_ID: requestId,
|
|
339
|
+
// Don't pass through potentially dangerous vars
|
|
340
|
+
VIBECHECK_DANGEROUS: undefined,
|
|
341
|
+
},
|
|
342
|
+
shell: false, // CRITICAL: No shell
|
|
343
|
+
windowsHide: true,
|
|
344
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Track for cancellation
|
|
348
|
+
activeProcesses.set(requestId, child);
|
|
349
|
+
|
|
350
|
+
// Handle abort signal
|
|
351
|
+
if (options.signal) {
|
|
352
|
+
options.signal.addEventListener('abort', () => {
|
|
353
|
+
if (!completed) {
|
|
354
|
+
child.kill('SIGTERM');
|
|
355
|
+
completed = true;
|
|
356
|
+
activeProcesses.delete(requestId);
|
|
357
|
+
releaseConcurrencySlot(options.projectPath);
|
|
358
|
+
clearTimeout(timeoutId);
|
|
359
|
+
|
|
360
|
+
metrics.recordToolExecution(`vibecheck.${command}`, Date.now() - startTime, false, false);
|
|
361
|
+
resolve({
|
|
362
|
+
ok: false,
|
|
363
|
+
error: { code: ErrorCode.CANCELLED, message: 'Operation cancelled' },
|
|
364
|
+
durationMs: Date.now() - startTime,
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
// Collect output
|
|
371
|
+
child.stdout?.on('data', (data: Buffer) => {
|
|
372
|
+
stdout += data.toString();
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
child.stderr?.on('data', (data: Buffer) => {
|
|
376
|
+
stderr += data.toString();
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
// Handle timeout
|
|
380
|
+
timeoutId = setTimeout(() => {
|
|
381
|
+
if (!completed) {
|
|
382
|
+
child.kill('SIGTERM');
|
|
383
|
+
// Give process time to cleanup
|
|
384
|
+
setTimeout(() => {
|
|
385
|
+
if (!completed) {
|
|
386
|
+
child.kill('SIGKILL');
|
|
387
|
+
}
|
|
388
|
+
}, 1000);
|
|
389
|
+
|
|
390
|
+
completed = true;
|
|
391
|
+
activeProcesses.delete(requestId);
|
|
392
|
+
releaseConcurrencySlot(options.projectPath);
|
|
393
|
+
|
|
394
|
+
metrics.recordToolExecution(`vibecheck.${command}`, Date.now() - startTime, false, false);
|
|
395
|
+
resolve({
|
|
396
|
+
ok: false,
|
|
397
|
+
error: { code: ErrorCode.TIMEOUT, message: `Timeout after ${timeout}ms` },
|
|
398
|
+
durationMs: Date.now() - startTime,
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}, timeout);
|
|
402
|
+
|
|
403
|
+
// Handle completion
|
|
404
|
+
child.on('close', (code: number | null) => {
|
|
405
|
+
clearTimeout(timeoutId);
|
|
406
|
+
if (completed) return;
|
|
407
|
+
completed = true;
|
|
408
|
+
activeProcesses.delete(requestId);
|
|
409
|
+
releaseConcurrencySlot(options.projectPath);
|
|
410
|
+
|
|
411
|
+
const durationMs = Date.now() - startTime;
|
|
412
|
+
|
|
413
|
+
// Try to parse JSON output
|
|
414
|
+
const data = parseJsonOutput<T>(stdout);
|
|
415
|
+
|
|
416
|
+
if (code === 0 && data !== null) {
|
|
417
|
+
// Success
|
|
418
|
+
if (options.cacheMode !== 'skip') {
|
|
419
|
+
cache.set(cacheKey, data, { ttl: options.cacheMaxAge ?? 300 });
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
logger.info('CLI completed', { command, code, durationMs });
|
|
423
|
+
metrics.recordToolExecution(`vibecheck.${command}`, durationMs, true, false);
|
|
424
|
+
|
|
425
|
+
resolve({
|
|
426
|
+
ok: true,
|
|
427
|
+
data,
|
|
428
|
+
durationMs,
|
|
429
|
+
cached: false,
|
|
430
|
+
exitCode: code,
|
|
431
|
+
stdout,
|
|
432
|
+
stderr,
|
|
433
|
+
});
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (code === 0 && data === null) {
|
|
438
|
+
// Success but no JSON output - return raw output
|
|
439
|
+
logger.info('CLI completed (no JSON)', { command, code, durationMs });
|
|
440
|
+
metrics.recordToolExecution(`vibecheck.${command}`, durationMs, true, false);
|
|
441
|
+
|
|
442
|
+
resolve({
|
|
443
|
+
ok: true,
|
|
444
|
+
data: { output: stdout, exitCode: code } as unknown as T,
|
|
445
|
+
durationMs,
|
|
446
|
+
cached: false,
|
|
447
|
+
exitCode: code ?? undefined,
|
|
448
|
+
stdout,
|
|
449
|
+
stderr,
|
|
450
|
+
});
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
// Non-zero exit
|
|
455
|
+
logger.warn('CLI failed', { command, code, stderr, durationMs });
|
|
456
|
+
metrics.recordToolExecution(`vibecheck.${command}`, durationMs, false, false);
|
|
457
|
+
|
|
458
|
+
resolve({
|
|
459
|
+
ok: false,
|
|
460
|
+
error: {
|
|
461
|
+
code: ErrorCode.CLI_ERROR,
|
|
462
|
+
message: stderr || stdout || `CLI exited with code ${code}`,
|
|
463
|
+
},
|
|
464
|
+
durationMs,
|
|
465
|
+
exitCode: code ?? undefined,
|
|
466
|
+
stdout,
|
|
467
|
+
stderr,
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
child.on('error', (err: Error) => {
|
|
472
|
+
clearTimeout(timeoutId);
|
|
473
|
+
if (completed) return;
|
|
474
|
+
completed = true;
|
|
475
|
+
activeProcesses.delete(requestId);
|
|
476
|
+
releaseConcurrencySlot(options.projectPath);
|
|
477
|
+
|
|
478
|
+
logger.error('CLI error', err);
|
|
479
|
+
metrics.recordToolExecution(`vibecheck.${command}`, Date.now() - startTime, false, false);
|
|
480
|
+
|
|
481
|
+
resolve({
|
|
482
|
+
ok: false,
|
|
483
|
+
error: { code: ErrorCode.CLI_ERROR, message: err.message },
|
|
484
|
+
durationMs: Date.now() - startTime,
|
|
485
|
+
});
|
|
486
|
+
});
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Execute CLI synchronously (for simple commands)
|
|
492
|
+
*
|
|
493
|
+
* CRITICAL: Uses spawnSync with args array. No shell. Windows-safe.
|
|
494
|
+
*/
|
|
495
|
+
export function executeCliSync<T>(
|
|
496
|
+
command: string,
|
|
497
|
+
args: string[],
|
|
498
|
+
options: ExecuteOptions
|
|
499
|
+
): ExecuteResult<T> {
|
|
500
|
+
const startTime = Date.now();
|
|
501
|
+
|
|
502
|
+
// Validate subcommand
|
|
503
|
+
try {
|
|
504
|
+
validateSubcommand(command);
|
|
505
|
+
} catch (e) {
|
|
506
|
+
return {
|
|
507
|
+
ok: false,
|
|
508
|
+
error: { code: ErrorCode.INVALID_INPUT, message: (e as Error).message },
|
|
509
|
+
durationMs: Date.now() - startTime,
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
// Validate project path
|
|
514
|
+
const sandbox = createSandbox({ workspace: options.projectPath });
|
|
515
|
+
const validation = sandbox.validate(options.projectPath);
|
|
516
|
+
if (!validation.allowed) {
|
|
517
|
+
return {
|
|
518
|
+
ok: false,
|
|
519
|
+
error: { code: ErrorCode.PATH_OUTSIDE_SANDBOX, message: validation.reason! },
|
|
520
|
+
durationMs: Date.now() - startTime,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
let binPath: string;
|
|
525
|
+
try {
|
|
526
|
+
binPath = getCliBinPath();
|
|
527
|
+
} catch (e) {
|
|
528
|
+
return {
|
|
529
|
+
ok: false,
|
|
530
|
+
error: { code: ErrorCode.DEPENDENCY_MISSING, message: (e as Error).message },
|
|
531
|
+
durationMs: Date.now() - startTime,
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const fullArgs = [binPath, command, '--json', ...args];
|
|
536
|
+
|
|
537
|
+
try {
|
|
538
|
+
// CRITICAL: shell: false, args array
|
|
539
|
+
const result = spawnSync('node', fullArgs, {
|
|
540
|
+
cwd: options.projectPath,
|
|
541
|
+
encoding: 'utf-8',
|
|
542
|
+
timeout: options.timeout ?? DEFAULT_TIMEOUTS[command] ?? 120000,
|
|
543
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
544
|
+
shell: false, // CRITICAL: No shell
|
|
545
|
+
windowsHide: true,
|
|
546
|
+
env: {
|
|
547
|
+
...process.env,
|
|
548
|
+
VIBECHECK_SKIP_AUTH: '1',
|
|
549
|
+
VIBECHECK_JSON_OUTPUT: '1',
|
|
550
|
+
},
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
const durationMs = Date.now() - startTime;
|
|
554
|
+
|
|
555
|
+
if (result.error) {
|
|
556
|
+
return {
|
|
557
|
+
ok: false,
|
|
558
|
+
error: { code: ErrorCode.CLI_ERROR, message: result.error.message },
|
|
559
|
+
durationMs,
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
const stdout = result.stdout ?? '';
|
|
564
|
+
const data = parseJsonOutput<T>(stdout);
|
|
565
|
+
|
|
566
|
+
if (result.status === 0 && data !== null) {
|
|
567
|
+
return { ok: true, data, durationMs, exitCode: result.status };
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
if (result.status === 0) {
|
|
571
|
+
return {
|
|
572
|
+
ok: true,
|
|
573
|
+
data: { output: stdout } as unknown as T,
|
|
574
|
+
durationMs,
|
|
575
|
+
exitCode: result.status,
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
return {
|
|
580
|
+
ok: false,
|
|
581
|
+
error: {
|
|
582
|
+
code: ErrorCode.CLI_ERROR,
|
|
583
|
+
message: result.stderr || stdout || `CLI exited with code ${result.status}`,
|
|
584
|
+
},
|
|
585
|
+
durationMs,
|
|
586
|
+
exitCode: result.status ?? undefined,
|
|
587
|
+
};
|
|
588
|
+
} catch (err) {
|
|
589
|
+
const error = err as { message?: string; status?: number };
|
|
590
|
+
return {
|
|
591
|
+
ok: false,
|
|
592
|
+
error: {
|
|
593
|
+
code: ErrorCode.CLI_ERROR,
|
|
594
|
+
message: error.message || 'CLI execution failed',
|
|
595
|
+
},
|
|
596
|
+
durationMs: Date.now() - startTime,
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Cancel a running command
|
|
603
|
+
*/
|
|
604
|
+
export function cancelExecution(requestId: string): boolean {
|
|
605
|
+
const child = activeProcesses.get(requestId);
|
|
606
|
+
if (child) {
|
|
607
|
+
child.kill('SIGTERM');
|
|
608
|
+
activeProcesses.delete(requestId);
|
|
609
|
+
return true;
|
|
610
|
+
}
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/**
|
|
615
|
+
* Get count of active executions
|
|
616
|
+
*/
|
|
617
|
+
export function getActiveExecutionCount(): number {
|
|
618
|
+
return activeProcesses.size;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Get concurrency stats
|
|
623
|
+
*/
|
|
624
|
+
export function getConcurrencyStats(): {
|
|
625
|
+
global: number;
|
|
626
|
+
maxGlobal: number;
|
|
627
|
+
workspaces: Record<string, number>;
|
|
628
|
+
maxPerWorkspace: number;
|
|
629
|
+
} {
|
|
630
|
+
const workspaces: Record<string, number> = {};
|
|
631
|
+
for (const [key, value] of workspaceLocks.entries()) {
|
|
632
|
+
workspaces[key] = value;
|
|
633
|
+
}
|
|
634
|
+
return {
|
|
635
|
+
global: globalConcurrentCount,
|
|
636
|
+
maxGlobal: MAX_CONCURRENT_GLOBAL,
|
|
637
|
+
workspaces,
|
|
638
|
+
maxPerWorkspace: MAX_CONCURRENT_PER_WORKSPACE,
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
/**
|
|
643
|
+
* Tool-specific executors
|
|
644
|
+
*/
|
|
645
|
+
export const ToolExecutors = {
|
|
646
|
+
async doctor(options: ExecuteOptions) {
|
|
647
|
+
return executeCli('doctor', [], options);
|
|
648
|
+
},
|
|
649
|
+
|
|
650
|
+
async scan(options: ExecuteOptions & { profile?: string; since?: string; baseline?: string }) {
|
|
651
|
+
const args: string[] = [];
|
|
652
|
+
if (options.profile) args.push(`--profile=${options.profile}`);
|
|
653
|
+
if (options.since) args.push(`--since=${options.since}`);
|
|
654
|
+
if (options.baseline) args.push(`--baseline=${options.baseline}`);
|
|
655
|
+
return executeCli('scan', args, options);
|
|
656
|
+
},
|
|
657
|
+
|
|
658
|
+
async ship(options: ExecuteOptions & { strict?: boolean; mockproof?: boolean; ci?: boolean }) {
|
|
659
|
+
const args: string[] = [];
|
|
660
|
+
if (options.strict) args.push('--strict');
|
|
661
|
+
if (options.mockproof !== false) args.push('--mockproof');
|
|
662
|
+
if (options.ci) args.push('--ci');
|
|
663
|
+
return executeCli('ship', args, options);
|
|
664
|
+
},
|
|
665
|
+
|
|
666
|
+
async prove(options: ExecuteOptions & {
|
|
667
|
+
url?: string;
|
|
668
|
+
auth?: string;
|
|
669
|
+
storageState?: string;
|
|
670
|
+
maxFixRounds?: number;
|
|
671
|
+
skipReality?: boolean;
|
|
672
|
+
skipFix?: boolean;
|
|
673
|
+
}) {
|
|
674
|
+
const args: string[] = [];
|
|
675
|
+
if (options.url) args.push(`--url=${options.url}`);
|
|
676
|
+
if (options.auth) args.push(`--auth=${options.auth}`);
|
|
677
|
+
if (options.storageState) args.push(`--storage-state=${options.storageState}`);
|
|
678
|
+
if (options.maxFixRounds) args.push(`--max-fix-rounds=${options.maxFixRounds}`);
|
|
679
|
+
if (options.skipReality) args.push('--skip-reality');
|
|
680
|
+
if (options.skipFix) args.push('--skip-fix');
|
|
681
|
+
return executeCli('prove', args, { ...options, timeout: options.timeout ?? 600000 });
|
|
682
|
+
},
|
|
683
|
+
|
|
684
|
+
async reality(options: ExecuteOptions & {
|
|
685
|
+
url: string;
|
|
686
|
+
auth?: string;
|
|
687
|
+
verifyAuth?: boolean;
|
|
688
|
+
storageState?: string;
|
|
689
|
+
maxPages?: number;
|
|
690
|
+
headed?: boolean;
|
|
691
|
+
recordVideo?: boolean;
|
|
692
|
+
recordTrace?: boolean;
|
|
693
|
+
}) {
|
|
694
|
+
const args: string[] = [`--url=${options.url}`];
|
|
695
|
+
if (options.auth) args.push(`--auth=${options.auth}`);
|
|
696
|
+
if (options.verifyAuth) args.push('--verify-auth');
|
|
697
|
+
if (options.storageState) args.push(`--storage-state=${options.storageState}`);
|
|
698
|
+
if (options.maxPages) args.push(`--max-pages=${options.maxPages}`);
|
|
699
|
+
if (options.headed) args.push('--headed');
|
|
700
|
+
if (options.recordVideo) args.push('--record-video');
|
|
701
|
+
if (options.recordTrace) args.push('--record-trace');
|
|
702
|
+
return executeCli('reality', args, { ...options, timeout: options.timeout ?? 300000 });
|
|
703
|
+
},
|
|
704
|
+
|
|
705
|
+
async fix(options: ExecuteOptions & {
|
|
706
|
+
apply?: boolean;
|
|
707
|
+
promptOnly?: boolean;
|
|
708
|
+
autopilot?: boolean;
|
|
709
|
+
maxMissions?: number;
|
|
710
|
+
}) {
|
|
711
|
+
const args: string[] = [];
|
|
712
|
+
if (options.apply) args.push('--apply');
|
|
713
|
+
if (options.promptOnly) args.push('--prompt-only');
|
|
714
|
+
if (options.autopilot) args.push('--autopilot');
|
|
715
|
+
if (options.maxMissions) args.push(`--max-missions=${options.maxMissions}`);
|
|
716
|
+
return executeCli('fix', args, { ...options, timeout: options.timeout ?? 300000 });
|
|
717
|
+
},
|
|
718
|
+
|
|
719
|
+
async guard(options: ExecuteOptions & {
|
|
720
|
+
claims?: boolean;
|
|
721
|
+
hallucinations?: boolean;
|
|
722
|
+
prompts?: boolean;
|
|
723
|
+
strict?: boolean;
|
|
724
|
+
}) {
|
|
725
|
+
const args: string[] = [];
|
|
726
|
+
if (options.claims) args.push('--claims');
|
|
727
|
+
if (options.hallucinations) args.push('--hallucinations');
|
|
728
|
+
if (options.prompts) args.push('--prompts');
|
|
729
|
+
if (options.strict) args.push('--strict');
|
|
730
|
+
return executeCli('guard', args, options);
|
|
731
|
+
},
|
|
732
|
+
|
|
733
|
+
async ctx(options: ExecuteOptions & { snapshot?: boolean; sync?: boolean }) {
|
|
734
|
+
const args: string[] = [];
|
|
735
|
+
if (options.snapshot) args.push('--snapshot');
|
|
736
|
+
if (options.sync) args.push('--sync');
|
|
737
|
+
return executeCli('ctx', args, options);
|
|
738
|
+
},
|
|
739
|
+
|
|
740
|
+
async report(options: ExecuteOptions & {
|
|
741
|
+
type?: string;
|
|
742
|
+
format?: string;
|
|
743
|
+
output?: string;
|
|
744
|
+
maxFindings?: number;
|
|
745
|
+
}) {
|
|
746
|
+
const args: string[] = [];
|
|
747
|
+
if (options.type) args.push(`--type=${options.type}`);
|
|
748
|
+
if (options.format) args.push(`--format=${options.format}`);
|
|
749
|
+
if (options.output) args.push(`--output=${options.output}`);
|
|
750
|
+
if (options.maxFindings) args.push(`--max-findings=${options.maxFindings}`);
|
|
751
|
+
return executeCli('report', args, options);
|
|
752
|
+
},
|
|
753
|
+
|
|
754
|
+
async polish(options: ExecuteOptions & { category?: string; fix?: boolean }) {
|
|
755
|
+
const args: string[] = [];
|
|
756
|
+
if (options.category) args.push(`--category=${options.category}`);
|
|
757
|
+
if (options.fix) args.push('--fix');
|
|
758
|
+
return executeCli('polish', args, options);
|
|
759
|
+
},
|
|
760
|
+
|
|
761
|
+
async status(options: ExecuteOptions) {
|
|
762
|
+
return executeCli('status', [], { ...options, timeout: options.timeout ?? 10000 });
|
|
763
|
+
},
|
|
764
|
+
|
|
765
|
+
async share(options: ExecuteOptions & { missionDir?: string }) {
|
|
766
|
+
const args: string[] = [];
|
|
767
|
+
if (options.missionDir) args.push(`--mission-dir=${options.missionDir}`);
|
|
768
|
+
return executeCli('share', args, options);
|
|
769
|
+
},
|
|
770
|
+
|
|
771
|
+
async badge(options: ExecuteOptions & { format?: string; style?: string }) {
|
|
772
|
+
const args: string[] = [];
|
|
773
|
+
if (options.format) args.push(`--format=${options.format}`);
|
|
774
|
+
if (options.style) args.push(`--style=${options.style}`);
|
|
775
|
+
return executeCli('badge', args, { ...options, timeout: options.timeout ?? 10000 });
|
|
776
|
+
},
|
|
777
|
+
|
|
778
|
+
async init(options: ExecuteOptions & { force?: boolean }) {
|
|
779
|
+
const args: string[] = [];
|
|
780
|
+
if (options.force) args.push('--force');
|
|
781
|
+
return executeCli('init', args, options);
|
|
782
|
+
},
|
|
783
|
+
};
|
|
784
|
+
|
|
785
|
+
export default {
|
|
786
|
+
executeCli,
|
|
787
|
+
executeCliSync,
|
|
788
|
+
cancelExecution,
|
|
789
|
+
getActiveExecutionCount,
|
|
790
|
+
getConcurrencyStats,
|
|
791
|
+
ToolExecutors,
|
|
792
|
+
};
|