@ttfw/envoi 1.0.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/README.md +238 -0
- package/dist/commands/app.d.ts +2 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +31 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/autonomy.d.ts +6 -0
- package/dist/commands/autonomy.d.ts.map +1 -0
- package/dist/commands/autonomy.js +89 -0
- package/dist/commands/autonomy.js.map +1 -0
- package/dist/commands/builder.d.ts +13 -0
- package/dist/commands/builder.d.ts.map +1 -0
- package/dist/commands/builder.js +142 -0
- package/dist/commands/builder.js.map +1 -0
- package/dist/commands/idea.d.ts +12 -0
- package/dist/commands/idea.d.ts.map +1 -0
- package/dist/commands/idea.js +79 -0
- package/dist/commands/idea.js.map +1 -0
- package/dist/commands/init.d.ts +18 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +423 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/mode.d.ts +13 -0
- package/dist/commands/mode.d.ts.map +1 -0
- package/dist/commands/mode.js +96 -0
- package/dist/commands/mode.js.map +1 -0
- package/dist/commands/onboard.d.ts +37 -0
- package/dist/commands/onboard.d.ts.map +1 -0
- package/dist/commands/onboard.js +743 -0
- package/dist/commands/onboard.js.map +1 -0
- package/dist/commands/pr-note.d.ts +8 -0
- package/dist/commands/pr-note.d.ts.map +1 -0
- package/dist/commands/pr-note.js +27 -0
- package/dist/commands/pr-note.js.map +1 -0
- package/dist/commands/undo.d.ts +7 -0
- package/dist/commands/undo.d.ts.map +1 -0
- package/dist/commands/undo.js +59 -0
- package/dist/commands/undo.js.map +1 -0
- package/dist/commands/update.d.ts +24 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +248 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/constants/report_codes.d.ts +29 -0
- package/dist/constants/report_codes.d.ts.map +1 -0
- package/dist/constants/report_codes.js +69 -0
- package/dist/constants/report_codes.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +675 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/autonomy.d.ts +16 -0
- package/dist/lib/autonomy.d.ts.map +1 -0
- package/dist/lib/autonomy.js +38 -0
- package/dist/lib/autonomy.js.map +1 -0
- package/dist/lib/blocked.d.ts +87 -0
- package/dist/lib/blocked.d.ts.map +1 -0
- package/dist/lib/blocked.js +134 -0
- package/dist/lib/blocked.js.map +1 -0
- package/dist/lib/branding.d.ts +13 -0
- package/dist/lib/branding.d.ts.map +1 -0
- package/dist/lib/branding.js +19 -0
- package/dist/lib/branding.js.map +1 -0
- package/dist/lib/claude.d.ts +42 -0
- package/dist/lib/claude.d.ts.map +1 -0
- package/dist/lib/claude.js +291 -0
- package/dist/lib/claude.js.map +1 -0
- package/dist/lib/config.d.ts +71 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +410 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/diff.d.ts +150 -0
- package/dist/lib/diff.d.ts.map +1 -0
- package/dist/lib/diff.js +257 -0
- package/dist/lib/diff.js.map +1 -0
- package/dist/lib/doctor.d.ts +67 -0
- package/dist/lib/doctor.d.ts.map +1 -0
- package/dist/lib/doctor.js +211 -0
- package/dist/lib/doctor.js.map +1 -0
- package/dist/lib/fingerprint.d.ts +27 -0
- package/dist/lib/fingerprint.d.ts.map +1 -0
- package/dist/lib/fingerprint.js +116 -0
- package/dist/lib/fingerprint.js.map +1 -0
- package/dist/lib/fs.d.ts +93 -0
- package/dist/lib/fs.d.ts.map +1 -0
- package/dist/lib/fs.js +179 -0
- package/dist/lib/fs.js.map +1 -0
- package/dist/lib/git.d.ts +177 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +355 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/git_branching.d.ts +84 -0
- package/dist/lib/git_branching.d.ts.map +1 -0
- package/dist/lib/git_branching.js +327 -0
- package/dist/lib/git_branching.js.map +1 -0
- package/dist/lib/gitignore.d.ts +26 -0
- package/dist/lib/gitignore.d.ts.map +1 -0
- package/dist/lib/gitignore.js +119 -0
- package/dist/lib/gitignore.js.map +1 -0
- package/dist/lib/guardrails.d.ts +232 -0
- package/dist/lib/guardrails.d.ts.map +1 -0
- package/dist/lib/guardrails.js +323 -0
- package/dist/lib/guardrails.js.map +1 -0
- package/dist/lib/history.d.ts +110 -0
- package/dist/lib/history.d.ts.map +1 -0
- package/dist/lib/history.js +236 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/index.d.ts +29 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +29 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/json-extract.d.ts +42 -0
- package/dist/lib/json-extract.d.ts.map +1 -0
- package/dist/lib/json-extract.js +201 -0
- package/dist/lib/json-extract.js.map +1 -0
- package/dist/lib/judge.d.ts +237 -0
- package/dist/lib/judge.d.ts.map +1 -0
- package/dist/lib/judge.js +501 -0
- package/dist/lib/judge.js.map +1 -0
- package/dist/lib/lock.d.ts +79 -0
- package/dist/lib/lock.d.ts.map +1 -0
- package/dist/lib/lock.js +254 -0
- package/dist/lib/lock.js.map +1 -0
- package/dist/lib/migration.d.ts +9 -0
- package/dist/lib/migration.d.ts.map +1 -0
- package/dist/lib/migration.js +74 -0
- package/dist/lib/migration.js.map +1 -0
- package/dist/lib/paths.d.ts +18 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +27 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/preflight.d.ts +33 -0
- package/dist/lib/preflight.d.ts.map +1 -0
- package/dist/lib/preflight.js +177 -0
- package/dist/lib/preflight.js.map +1 -0
- package/dist/lib/prompt_budget.d.ts +18 -0
- package/dist/lib/prompt_budget.d.ts.map +1 -0
- package/dist/lib/prompt_budget.js +36 -0
- package/dist/lib/prompt_budget.js.map +1 -0
- package/dist/lib/report.d.ts +102 -0
- package/dist/lib/report.d.ts.map +1 -0
- package/dist/lib/report.js +347 -0
- package/dist/lib/report.js.map +1 -0
- package/dist/lib/reviewer-flow.d.ts +80 -0
- package/dist/lib/reviewer-flow.d.ts.map +1 -0
- package/dist/lib/reviewer-flow.js +138 -0
- package/dist/lib/reviewer-flow.js.map +1 -0
- package/dist/lib/reviewer.d.ts +53 -0
- package/dist/lib/reviewer.d.ts.map +1 -0
- package/dist/lib/reviewer.js +199 -0
- package/dist/lib/reviewer.js.map +1 -0
- package/dist/lib/risk.d.ts +127 -0
- package/dist/lib/risk.d.ts.map +1 -0
- package/dist/lib/risk.js +192 -0
- package/dist/lib/risk.js.map +1 -0
- package/dist/lib/rollback.d.ts +143 -0
- package/dist/lib/rollback.d.ts.map +1 -0
- package/dist/lib/rollback.js +244 -0
- package/dist/lib/rollback.js.map +1 -0
- package/dist/lib/schema.d.ts +47 -0
- package/dist/lib/schema.d.ts.map +1 -0
- package/dist/lib/schema.js +91 -0
- package/dist/lib/schema.js.map +1 -0
- package/dist/lib/scope.d.ts +89 -0
- package/dist/lib/scope.d.ts.map +1 -0
- package/dist/lib/scope.js +135 -0
- package/dist/lib/scope.js.map +1 -0
- package/dist/lib/self_update.d.ts +13 -0
- package/dist/lib/self_update.d.ts.map +1 -0
- package/dist/lib/self_update.js +172 -0
- package/dist/lib/self_update.js.map +1 -0
- package/dist/lib/state.d.ts +143 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +258 -0
- package/dist/lib/state.js.map +1 -0
- package/dist/lib/tick.d.ts +310 -0
- package/dist/lib/tick.d.ts.map +1 -0
- package/dist/lib/tick.js +424 -0
- package/dist/lib/tick.js.map +1 -0
- package/dist/lib/transport.d.ts +145 -0
- package/dist/lib/transport.d.ts.map +1 -0
- package/dist/lib/transport.js +237 -0
- package/dist/lib/transport.js.map +1 -0
- package/dist/lib/verdict_labels.d.ts +5 -0
- package/dist/lib/verdict_labels.d.ts.map +1 -0
- package/dist/lib/verdict_labels.js +25 -0
- package/dist/lib/verdict_labels.js.map +1 -0
- package/dist/lib/verify-safety.d.ts +63 -0
- package/dist/lib/verify-safety.d.ts.map +1 -0
- package/dist/lib/verify-safety.js +123 -0
- package/dist/lib/verify-safety.js.map +1 -0
- package/dist/lib/verify.d.ts +139 -0
- package/dist/lib/verify.d.ts.map +1 -0
- package/dist/lib/verify.js +311 -0
- package/dist/lib/verify.js.map +1 -0
- package/dist/lib/workspace_state.d.ts +79 -0
- package/dist/lib/workspace_state.d.ts.map +1 -0
- package/dist/lib/workspace_state.js +283 -0
- package/dist/lib/workspace_state.js.map +1 -0
- package/dist/runner/builder.d.ts +58 -0
- package/dist/runner/builder.d.ts.map +1 -0
- package/dist/runner/builder.js +775 -0
- package/dist/runner/builder.js.map +1 -0
- package/dist/runner/builder_parse.d.ts +37 -0
- package/dist/runner/builder_parse.d.ts.map +1 -0
- package/dist/runner/builder_parse.js +76 -0
- package/dist/runner/builder_parse.js.map +1 -0
- package/dist/runner/index.d.ts +9 -0
- package/dist/runner/index.d.ts.map +1 -0
- package/dist/runner/index.js +7 -0
- package/dist/runner/index.js.map +1 -0
- package/dist/runner/loop.d.ts +51 -0
- package/dist/runner/loop.d.ts.map +1 -0
- package/dist/runner/loop.js +221 -0
- package/dist/runner/loop.js.map +1 -0
- package/dist/runner/orchestrator.d.ts +67 -0
- package/dist/runner/orchestrator.d.ts.map +1 -0
- package/dist/runner/orchestrator.js +376 -0
- package/dist/runner/orchestrator.js.map +1 -0
- package/dist/runner/tick.d.ts +10 -0
- package/dist/runner/tick.d.ts.map +1 -0
- package/dist/runner/tick.js +1639 -0
- package/dist/runner/tick.js.map +1 -0
- package/dist/types/blocked.d.ts +52 -0
- package/dist/types/blocked.d.ts.map +1 -0
- package/dist/types/blocked.js +8 -0
- package/dist/types/blocked.js.map +1 -0
- package/dist/types/builder.d.ts +25 -0
- package/dist/types/builder.d.ts.map +1 -0
- package/dist/types/builder.js +7 -0
- package/dist/types/builder.js.map +1 -0
- package/dist/types/claude.d.ts +86 -0
- package/dist/types/claude.d.ts.map +1 -0
- package/dist/types/claude.js +48 -0
- package/dist/types/claude.js.map +1 -0
- package/dist/types/config.d.ts +384 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +7 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/lock.d.ts +21 -0
- package/dist/types/lock.d.ts.map +1 -0
- package/dist/types/lock.js +8 -0
- package/dist/types/lock.js.map +1 -0
- package/dist/types/preflight.d.ts +49 -0
- package/dist/types/preflight.d.ts.map +1 -0
- package/dist/types/preflight.js +8 -0
- package/dist/types/preflight.js.map +1 -0
- package/dist/types/report.d.ts +161 -0
- package/dist/types/report.d.ts.map +1 -0
- package/dist/types/report.js +8 -0
- package/dist/types/report.js.map +1 -0
- package/dist/types/reviewer.d.ts +66 -0
- package/dist/types/reviewer.d.ts.map +1 -0
- package/dist/types/reviewer.js +5 -0
- package/dist/types/reviewer.js.map +1 -0
- package/dist/types/state.d.ts +124 -0
- package/dist/types/state.d.ts.map +1 -0
- package/dist/types/state.js +20 -0
- package/dist/types/state.js.map +1 -0
- package/dist/types/task.d.ts +117 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +7 -0
- package/dist/types/task.js.map +1 -0
- package/dist/types/workspace_state.d.ts +125 -0
- package/dist/types/workspace_state.d.ts.map +1 -0
- package/dist/types/workspace_state.js +10 -0
- package/dist/types/workspace_state.js.map +1 -0
- package/envoi.config.json +191 -0
- package/package.json +52 -0
- package/relais/prompts/.gitkeep +0 -0
- package/relais/prompts/builder.system.txt +13 -0
- package/relais/prompts/builder.user.txt +15 -0
- package/relais/prompts/orchestrator.system.txt +37 -0
- package/relais/prompts/orchestrator.user.txt +34 -0
- package/relais/prompts/reviewer.system.txt +33 -0
- package/relais/prompts/reviewer.user.txt +35 -0
- package/relais/schemas/.gitkeep +0 -0
- package/relais/schemas/builder_result.schema.json +29 -0
- package/relais/schemas/report.schema.json +195 -0
- package/relais/schemas/reviewer_result.schema.json +70 -0
- package/relais/schemas/task.schema.json +155 -0
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transport layer utilities for Claude invocations.
|
|
3
|
+
*
|
|
4
|
+
* Provides stall detection and timeout wrapper for reliable
|
|
5
|
+
* handling of connection issues, timeouts, and transport failures.
|
|
6
|
+
*/
|
|
7
|
+
import { ClaudeError } from '../types/claude.js';
|
|
8
|
+
import { invokeClaudeCode } from './claude.js';
|
|
9
|
+
/**
|
|
10
|
+
* Maximum length for raw_error in TransportStallError.
|
|
11
|
+
* Truncates error messages to prevent excessive memory usage.
|
|
12
|
+
*/
|
|
13
|
+
const MAX_RAW_ERROR_LENGTH = 500;
|
|
14
|
+
/**
|
|
15
|
+
* Patterns that indicate a transport stall.
|
|
16
|
+
*/
|
|
17
|
+
const STALL_PATTERNS = [
|
|
18
|
+
'Connection stalled',
|
|
19
|
+
'streamFromAgentBackend',
|
|
20
|
+
'ECONNRESET',
|
|
21
|
+
'ETIMEDOUT',
|
|
22
|
+
'socket hang up',
|
|
23
|
+
];
|
|
24
|
+
/**
|
|
25
|
+
* Detects transport stall patterns in error output.
|
|
26
|
+
*
|
|
27
|
+
* Checks for known patterns that indicate connection issues:
|
|
28
|
+
* - "Connection stalled" - Cursor/CLI connection issue
|
|
29
|
+
* - "streamFromAgentBackend" - Backend stream failure
|
|
30
|
+
* - "ECONNRESET" - Connection reset by peer
|
|
31
|
+
* - "ETIMEDOUT" - Connection timeout
|
|
32
|
+
* - "socket hang up" - Socket disconnection
|
|
33
|
+
*
|
|
34
|
+
* Also extracts Request ID if present for debugging.
|
|
35
|
+
*
|
|
36
|
+
* @param error - Error message or stderr output to analyze
|
|
37
|
+
* @returns Detection result with stalled flag and optional request_id
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const result = isTransportStall('Connection stalled. Request ID: abc123');
|
|
42
|
+
* // result.stalled === true
|
|
43
|
+
* // result.request_id === 'abc123'
|
|
44
|
+
* ```
|
|
45
|
+
*/
|
|
46
|
+
export function isTransportStall(error) {
|
|
47
|
+
if (!error) {
|
|
48
|
+
return { stalled: false, request_id: null, matched_pattern: null };
|
|
49
|
+
}
|
|
50
|
+
// Check for stall patterns
|
|
51
|
+
let matchedPattern = null;
|
|
52
|
+
for (const pattern of STALL_PATTERNS) {
|
|
53
|
+
if (error.includes(pattern)) {
|
|
54
|
+
matchedPattern = pattern;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Extract Request ID if present
|
|
59
|
+
// Common formats: "Request ID: xxx", "request_id: xxx", "requestId: xxx"
|
|
60
|
+
let requestId = null;
|
|
61
|
+
const requestIdMatch = error.match(/[Rr]equest[_\s]?[Ii][Dd][:\s]+([a-zA-Z0-9_-]+)/);
|
|
62
|
+
if (requestIdMatch) {
|
|
63
|
+
requestId = requestIdMatch[1];
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
stalled: matchedPattern !== null,
|
|
67
|
+
request_id: requestId,
|
|
68
|
+
matched_pattern: matchedPattern,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Creates a TransportStallError from error information.
|
|
73
|
+
*
|
|
74
|
+
* @param stage - The stage where the stall occurred (ORCHESTRATE or BUILD)
|
|
75
|
+
* @param rawError - The raw error message
|
|
76
|
+
* @param requestId - Optional request ID extracted from error
|
|
77
|
+
* @returns Structured TransportStallError
|
|
78
|
+
*/
|
|
79
|
+
export function createTransportStallError(stage, rawError, requestId = null) {
|
|
80
|
+
// Truncate raw_error to prevent excessive length
|
|
81
|
+
const truncatedError = rawError.length > MAX_RAW_ERROR_LENGTH
|
|
82
|
+
? rawError.substring(0, MAX_RAW_ERROR_LENGTH) + '...'
|
|
83
|
+
: rawError;
|
|
84
|
+
return {
|
|
85
|
+
kind: 'transport_stalled',
|
|
86
|
+
stage,
|
|
87
|
+
request_id: requestId,
|
|
88
|
+
raw_error: truncatedError,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Invokes Claude Code CLI with stall detection.
|
|
93
|
+
*
|
|
94
|
+
* Wraps the standard invokeClaudeCode function and:
|
|
95
|
+
* 1. Catches timeout errors and converts to TransportStallError
|
|
96
|
+
* 2. Detects stall patterns in error output
|
|
97
|
+
* 3. Returns structured error for transport failures
|
|
98
|
+
*
|
|
99
|
+
* @param config - Claude Code CLI configuration
|
|
100
|
+
* @param invocation - Invocation parameters
|
|
101
|
+
* @param stage - The stage (ORCHESTRATE or BUILD) for error context
|
|
102
|
+
* @returns InvokeResult with either response or stall error
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```typescript
|
|
106
|
+
* const result = await invokeWithStallDetection(config, invocation, 'BUILD');
|
|
107
|
+
* if (result.ok) {
|
|
108
|
+
* console.log('Success:', result.response.result);
|
|
109
|
+
* } else {
|
|
110
|
+
* console.log('Stall:', result.error.raw_error);
|
|
111
|
+
* }
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
export async function invokeWithStallDetection(config, invocation, stage) {
|
|
115
|
+
try {
|
|
116
|
+
const response = await invokeClaudeCode(config, invocation);
|
|
117
|
+
return { ok: true, response };
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
// Handle ClaudeError (timeout, process errors, etc.)
|
|
121
|
+
if (error instanceof ClaudeError) {
|
|
122
|
+
const errorMessage = error.message + (error.stderr ? `\n${error.stderr}` : '');
|
|
123
|
+
// Check if this is a timeout (exit code 124 is standard timeout)
|
|
124
|
+
const isTimeout = error.exitCode === 124 || error.message.includes('timed out');
|
|
125
|
+
// Check for stall patterns
|
|
126
|
+
const stallCheck = isTransportStall(errorMessage);
|
|
127
|
+
// If timeout or stall pattern detected, return TransportStallError
|
|
128
|
+
if (isTimeout || stallCheck.stalled) {
|
|
129
|
+
return {
|
|
130
|
+
ok: false,
|
|
131
|
+
error: createTransportStallError(stage, errorMessage, stallCheck.request_id),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
// For other ClaudeErrors, re-throw (not a transport stall)
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
// For unexpected errors, check if they contain stall patterns
|
|
138
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
139
|
+
const stallCheck = isTransportStall(errorMessage);
|
|
140
|
+
if (stallCheck.stalled) {
|
|
141
|
+
return {
|
|
142
|
+
ok: false,
|
|
143
|
+
error: createTransportStallError(stage, errorMessage, stallCheck.request_id),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// Re-throw non-transport errors
|
|
147
|
+
throw error;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Normalizes any error type into a consistent format for stall detection.
|
|
152
|
+
*
|
|
153
|
+
* Handles:
|
|
154
|
+
* - ClaudeError: extracts message + stderr, checks for timeout
|
|
155
|
+
* - Error: extracts message
|
|
156
|
+
* - string: wraps in Error
|
|
157
|
+
* - unknown: converts to string and wraps in Error
|
|
158
|
+
*
|
|
159
|
+
* @param error - Any error type (ClaudeError, Error, string, unknown)
|
|
160
|
+
* @param stage - The stage where the error occurred (ORCHESTRATE or BUILD)
|
|
161
|
+
* @returns Normalized error with stall detection result
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* ```typescript
|
|
165
|
+
* try {
|
|
166
|
+
* await invokeClaudeCode(config, invocation);
|
|
167
|
+
* } catch (error) {
|
|
168
|
+
* const normalized = normalizeTransportError(error, 'BUILD');
|
|
169
|
+
* if (normalized.isStall) {
|
|
170
|
+
* handleStall(normalized.stallError);
|
|
171
|
+
* } else {
|
|
172
|
+
* throw normalized.originalError;
|
|
173
|
+
* }
|
|
174
|
+
* }
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
/**
|
|
178
|
+
* Type guard to check if an error is a TransportStallError.
|
|
179
|
+
*
|
|
180
|
+
* @param error - Any value to check
|
|
181
|
+
* @returns True if the error is a TransportStallError
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```typescript
|
|
185
|
+
* const result = await invokeWithStallDetection(config, invocation, 'BUILD');
|
|
186
|
+
* if (!result.ok && isTransportStallError(result.error)) {
|
|
187
|
+
* console.log('Stage:', result.error.stage);
|
|
188
|
+
* console.log('Request ID:', result.error.request_id);
|
|
189
|
+
* }
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
export function isTransportStallError(error) {
|
|
193
|
+
if (typeof error !== 'object' || error === null) {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
const obj = error;
|
|
197
|
+
return (obj.kind === 'transport_stalled' &&
|
|
198
|
+
(obj.stage === 'ORCHESTRATE' || obj.stage === 'BUILD') &&
|
|
199
|
+
(typeof obj.request_id === 'string' || obj.request_id === null) &&
|
|
200
|
+
typeof obj.raw_error === 'string');
|
|
201
|
+
}
|
|
202
|
+
export function normalizeTransportError(error, stage) {
|
|
203
|
+
let message;
|
|
204
|
+
let originalError;
|
|
205
|
+
let isTimeout = false;
|
|
206
|
+
// Handle different error types
|
|
207
|
+
if (error instanceof ClaudeError) {
|
|
208
|
+
message = error.message + (error.stderr ? `\n${error.stderr}` : '');
|
|
209
|
+
originalError = error;
|
|
210
|
+
isTimeout = error.exitCode === 124 || error.message.includes('timed out');
|
|
211
|
+
}
|
|
212
|
+
else if (error instanceof Error) {
|
|
213
|
+
message = error.message;
|
|
214
|
+
originalError = error;
|
|
215
|
+
}
|
|
216
|
+
else if (typeof error === 'string') {
|
|
217
|
+
message = error;
|
|
218
|
+
originalError = new Error(error);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
message = String(error);
|
|
222
|
+
originalError = new Error(message);
|
|
223
|
+
}
|
|
224
|
+
// Check for stall patterns
|
|
225
|
+
const stallCheck = isTransportStall(message);
|
|
226
|
+
// Determine if this is a stall
|
|
227
|
+
const isStall = isTimeout || stallCheck.stalled;
|
|
228
|
+
return {
|
|
229
|
+
isStall,
|
|
230
|
+
stallError: isStall
|
|
231
|
+
? createTransportStallError(stage, message, stallCheck.request_id)
|
|
232
|
+
: null,
|
|
233
|
+
originalError,
|
|
234
|
+
message,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/lib/transport.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Verdict } from '../types/report.js';
|
|
2
|
+
export type DisplayState = 'CLEARED' | 'STANDBY' | 'BLOCKED' | 'OUT_OF_BOUNDS' | 'LIMIT_HIT' | 'ROLLED_BACK';
|
|
3
|
+
export declare function toDisplayState(verdict: Verdict, code: string): DisplayState;
|
|
4
|
+
export declare function formatDisplayState(verdict: Verdict, code: string): string;
|
|
5
|
+
//# sourceMappingURL=verdict_labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verdict_labels.d.ts","sourceRoot":"","sources":["../../src/lib/verdict_labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,MAAM,YAAY,GACpB,SAAS,GACT,SAAS,GACT,SAAS,GACT,eAAe,GACf,WAAW,GACX,aAAa,CAAC;AAclB,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,YAAY,CAO3E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAEzE"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
function isOutOfBounds(code) {
|
|
2
|
+
return (code.startsWith('STOP_SCOPE_VIOLATION') ||
|
|
3
|
+
code === 'STOP_RUNNER_OWNED_MUTATION' ||
|
|
4
|
+
code === 'STOP_LOCKFILE_CHANGE_FORBIDDEN');
|
|
5
|
+
}
|
|
6
|
+
function isLimitHit(code) {
|
|
7
|
+
return code === 'STOP_DIFF_TOO_LARGE' || code.startsWith('BLOCKED_BUDGET_');
|
|
8
|
+
}
|
|
9
|
+
export function toDisplayState(verdict, code) {
|
|
10
|
+
if (code === 'SUCCESS' || verdict === 'success')
|
|
11
|
+
return 'CLEARED';
|
|
12
|
+
if (isOutOfBounds(code))
|
|
13
|
+
return 'OUT_OF_BOUNDS';
|
|
14
|
+
if (isLimitHit(code))
|
|
15
|
+
return 'LIMIT_HIT';
|
|
16
|
+
if (code === 'STOP_INTERRUPTED' || verdict === 'stop')
|
|
17
|
+
return 'STANDBY';
|
|
18
|
+
if (code.startsWith('BLOCKED_') || verdict === 'blocked')
|
|
19
|
+
return 'BLOCKED';
|
|
20
|
+
return 'STANDBY';
|
|
21
|
+
}
|
|
22
|
+
export function formatDisplayState(verdict, code) {
|
|
23
|
+
return `${toDisplayState(verdict, code)} (${code})`;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=verdict_labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verdict_labels.js","sourceRoot":"","sources":["../../src/lib/verdict_labels.ts"],"names":[],"mappings":"AAUA,SAAS,aAAa,CAAC,IAAY;IACjC,OAAO,CACL,IAAI,CAAC,UAAU,CAAC,sBAAsB,CAAC;QACvC,IAAI,KAAK,4BAA4B;QACrC,IAAI,KAAK,gCAAgC,CAC1C,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI,KAAK,qBAAqB,IAAI,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,IAAY;IAC3D,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAClE,IAAI,aAAa,CAAC,IAAI,CAAC;QAAE,OAAO,eAAe,CAAC;IAChD,IAAI,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,WAAW,CAAC;IACzC,IAAI,IAAI,KAAK,kBAAkB,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,SAAS,CAAC;IACxE,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IAC3E,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,OAAgB,EAAE,IAAY;IAC/D,OAAO,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,IAAI,GAAG,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verification parameter safety validation module.
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to validate verification parameters against security constraints
|
|
5
|
+
* to prevent shell injection and other security issues.
|
|
6
|
+
*/
|
|
7
|
+
import type { VerificationConfig } from '../types/config.js';
|
|
8
|
+
/**
|
|
9
|
+
* Result of parameter validation.
|
|
10
|
+
*/
|
|
11
|
+
export interface ParamValidationResult {
|
|
12
|
+
/** True if the parameter(s) are valid */
|
|
13
|
+
ok: boolean;
|
|
14
|
+
/** Stop code to use if validation fails */
|
|
15
|
+
stopCode: 'STOP_VERIFY_TAINTED' | null;
|
|
16
|
+
/** Name of the invalid parameter (if any) */
|
|
17
|
+
invalidParam: string | null;
|
|
18
|
+
/** Reason for validation failure */
|
|
19
|
+
reason: string | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Validates a single verification parameter against security constraints.
|
|
23
|
+
*
|
|
24
|
+
* Checks for:
|
|
25
|
+
* - Length exceeding max_param_len
|
|
26
|
+
* - Whitespace (if reject_whitespace_in_params is true)
|
|
27
|
+
* - Path traversal '..' (if reject_dotdot is true)
|
|
28
|
+
* - Shell metacharacters (using reject_metachars_regex)
|
|
29
|
+
*
|
|
30
|
+
* @param param - The parameter value to validate
|
|
31
|
+
* @param config - Verification configuration with validation rules
|
|
32
|
+
* @returns ParamValidationResult with ok=true if valid, or failure details
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* const result = validateVerifyParam('my-value', config);
|
|
37
|
+
* if (!result.ok) {
|
|
38
|
+
* console.error(`Invalid param: ${result.reason}`);
|
|
39
|
+
* }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function validateVerifyParam(param: string, config: VerificationConfig): ParamValidationResult;
|
|
43
|
+
/**
|
|
44
|
+
* Validates all parameters in a record, returning the first failure.
|
|
45
|
+
*
|
|
46
|
+
* Validates each parameter value in the params object against the security
|
|
47
|
+
* constraints defined in the verification config. Returns the first validation
|
|
48
|
+
* failure encountered, or success if all parameters are valid.
|
|
49
|
+
*
|
|
50
|
+
* @param params - Record mapping parameter names to string values
|
|
51
|
+
* @param config - Verification configuration with validation rules
|
|
52
|
+
* @returns ParamValidationResult with ok=true if all params valid, or first failure details
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```typescript
|
|
56
|
+
* const result = validateAllParams({ pkg: 'my-package', env: 'prod' }, config);
|
|
57
|
+
* if (!result.ok) {
|
|
58
|
+
* console.error(`Invalid param '${result.invalidParam}': ${result.reason}`);
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function validateAllParams(params: Record<string, string>, config: VerificationConfig): ParamValidationResult;
|
|
63
|
+
//# sourceMappingURL=verify-safety.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-safety.d.ts","sourceRoot":"","sources":["../../src/lib/verify-safety.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAE7D;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,yCAAyC;IACzC,EAAE,EAAE,OAAO,CAAC;IACZ,2CAA2C;IAC3C,QAAQ,EAAE,qBAAqB,GAAG,IAAI,CAAC;IACvC,6CAA6C;IAC7C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,oCAAoC;IACpC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,kBAAkB,GACzB,qBAAqB,CA4DvB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,MAAM,EAAE,kBAAkB,GACzB,qBAAqB,CAkBvB"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verification parameter safety validation module.
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to validate verification parameters against security constraints
|
|
5
|
+
* to prevent shell injection and other security issues.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Validates a single verification parameter against security constraints.
|
|
9
|
+
*
|
|
10
|
+
* Checks for:
|
|
11
|
+
* - Length exceeding max_param_len
|
|
12
|
+
* - Whitespace (if reject_whitespace_in_params is true)
|
|
13
|
+
* - Path traversal '..' (if reject_dotdot is true)
|
|
14
|
+
* - Shell metacharacters (using reject_metachars_regex)
|
|
15
|
+
*
|
|
16
|
+
* @param param - The parameter value to validate
|
|
17
|
+
* @param config - Verification configuration with validation rules
|
|
18
|
+
* @returns ParamValidationResult with ok=true if valid, or failure details
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const result = validateVerifyParam('my-value', config);
|
|
23
|
+
* if (!result.ok) {
|
|
24
|
+
* console.error(`Invalid param: ${result.reason}`);
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export function validateVerifyParam(param, config) {
|
|
29
|
+
// Check length
|
|
30
|
+
if (param.length > config.max_param_len) {
|
|
31
|
+
return {
|
|
32
|
+
ok: false,
|
|
33
|
+
stopCode: 'STOP_VERIFY_TAINTED',
|
|
34
|
+
invalidParam: null,
|
|
35
|
+
reason: `Parameter length ${param.length} exceeds maximum ${config.max_param_len}`,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// Check for whitespace if enabled
|
|
39
|
+
if (config.reject_whitespace_in_params && /\s/.test(param)) {
|
|
40
|
+
return {
|
|
41
|
+
ok: false,
|
|
42
|
+
stopCode: 'STOP_VERIFY_TAINTED',
|
|
43
|
+
invalidParam: null,
|
|
44
|
+
reason: 'Parameter contains whitespace',
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
// Check for path traversal '..' if enabled
|
|
48
|
+
if (config.reject_dotdot && param.includes('..')) {
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
stopCode: 'STOP_VERIFY_TAINTED',
|
|
52
|
+
invalidParam: null,
|
|
53
|
+
reason: "Parameter contains '..' path traversal",
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Check for shell metacharacters
|
|
57
|
+
try {
|
|
58
|
+
const metacharRegex = new RegExp(config.reject_metachars_regex);
|
|
59
|
+
if (metacharRegex.test(param)) {
|
|
60
|
+
return {
|
|
61
|
+
ok: false,
|
|
62
|
+
stopCode: 'STOP_VERIFY_TAINTED',
|
|
63
|
+
invalidParam: null,
|
|
64
|
+
reason: `Parameter matches metacharacter regex: ${config.reject_metachars_regex}`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
// If regex is invalid, treat as validation failure
|
|
70
|
+
// This shouldn't happen with valid config, but be defensive
|
|
71
|
+
return {
|
|
72
|
+
ok: false,
|
|
73
|
+
stopCode: 'STOP_VERIFY_TAINTED',
|
|
74
|
+
invalidParam: null,
|
|
75
|
+
reason: `Invalid metacharacter regex in config: ${error instanceof Error ? error.message : String(error)}`,
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
// All checks passed
|
|
79
|
+
return {
|
|
80
|
+
ok: true,
|
|
81
|
+
stopCode: null,
|
|
82
|
+
invalidParam: null,
|
|
83
|
+
reason: null,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Validates all parameters in a record, returning the first failure.
|
|
88
|
+
*
|
|
89
|
+
* Validates each parameter value in the params object against the security
|
|
90
|
+
* constraints defined in the verification config. Returns the first validation
|
|
91
|
+
* failure encountered, or success if all parameters are valid.
|
|
92
|
+
*
|
|
93
|
+
* @param params - Record mapping parameter names to string values
|
|
94
|
+
* @param config - Verification configuration with validation rules
|
|
95
|
+
* @returns ParamValidationResult with ok=true if all params valid, or first failure details
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```typescript
|
|
99
|
+
* const result = validateAllParams({ pkg: 'my-package', env: 'prod' }, config);
|
|
100
|
+
* if (!result.ok) {
|
|
101
|
+
* console.error(`Invalid param '${result.invalidParam}': ${result.reason}`);
|
|
102
|
+
* }
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
export function validateAllParams(params, config) {
|
|
106
|
+
for (const [paramName, paramValue] of Object.entries(params)) {
|
|
107
|
+
const result = validateVerifyParam(paramValue, config);
|
|
108
|
+
if (!result.ok) {
|
|
109
|
+
return {
|
|
110
|
+
...result,
|
|
111
|
+
invalidParam: paramName,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// All parameters are valid
|
|
116
|
+
return {
|
|
117
|
+
ok: true,
|
|
118
|
+
stopCode: null,
|
|
119
|
+
invalidParam: null,
|
|
120
|
+
reason: null,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=verify-safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify-safety.js","sourceRoot":"","sources":["../../src/lib/verify-safety.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAkBH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,mBAAmB,CACjC,KAAa,EACb,MAA0B;IAE1B,eAAe;IACf,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;QACxC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,QAAQ,EAAE,qBAAqB;YAC/B,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,oBAAoB,KAAK,CAAC,MAAM,oBAAoB,MAAM,CAAC,aAAa,EAAE;SACnF,CAAC;IACJ,CAAC;IAED,kCAAkC;IAClC,IAAI,MAAM,CAAC,2BAA2B,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,QAAQ,EAAE,qBAAqB;YAC/B,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,+BAA+B;SACxC,CAAC;IACJ,CAAC;IAED,2CAA2C;IAC3C,IAAI,MAAM,CAAC,aAAa,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACjD,OAAO;YACL,EAAE,EAAE,KAAK;YACT,QAAQ,EAAE,qBAAqB;YAC/B,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,wCAAwC;SACjD,CAAC;IACJ,CAAC;IAED,iCAAiC;IACjC,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC;QAChE,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9B,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,QAAQ,EAAE,qBAAqB;gBAC/B,YAAY,EAAE,IAAI;gBAClB,MAAM,EAAE,0CAA0C,MAAM,CAAC,sBAAsB,EAAE;aAClF,CAAC;QACJ,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,mDAAmD;QACnD,4DAA4D;QAC5D,OAAO;YACL,EAAE,EAAE,KAAK;YACT,QAAQ,EAAE,qBAAqB;YAC/B,YAAY,EAAE,IAAI;YAClB,MAAM,EAAE,0CAA0C,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;SAC3G,CAAC;IACJ,CAAC;IAED,oBAAoB;IACpB,OAAO;QACL,EAAE,EAAE,IAAI;QACR,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,MAAM,EAAE,IAAI;KACb,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAA8B,EAC9B,MAA0B;IAE1B,KAAK,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,mBAAmB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACf,OAAO;gBACL,GAAG,MAAM;gBACT,YAAY,EAAE,SAAS;aACxB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,OAAO;QACL,EAAE,EAAE,IAAI;QACR,QAAQ,EAAE,IAAI;QACd,YAAY,EAAE,IAAI;QAClB,MAAM,EAAE,IAAI;KACb,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verification command execution module.
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to execute verification commands safely using argv arrays
|
|
5
|
+
* (no shell) with parameter interpolation and timeout handling.
|
|
6
|
+
*/
|
|
7
|
+
import type { VerificationTemplate, VerificationConfig } from '../types/config.js';
|
|
8
|
+
import type { Task } from '../types/task.js';
|
|
9
|
+
/**
|
|
10
|
+
* Result of a single verification command execution.
|
|
11
|
+
*/
|
|
12
|
+
export interface VerificationRun {
|
|
13
|
+
/** ID of the verification template */
|
|
14
|
+
template_id: string;
|
|
15
|
+
/** Process exit code */
|
|
16
|
+
exit_code: number;
|
|
17
|
+
/** Captured stdout */
|
|
18
|
+
stdout: string;
|
|
19
|
+
/** Captured stderr */
|
|
20
|
+
stderr: string;
|
|
21
|
+
/** Execution time in milliseconds */
|
|
22
|
+
duration_ms: number;
|
|
23
|
+
/** Whether the command succeeded (exit_code === 0) */
|
|
24
|
+
success: boolean;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Validation error for a single parameter.
|
|
28
|
+
*/
|
|
29
|
+
export interface ParamValidationError {
|
|
30
|
+
/** Name of the parameter */
|
|
31
|
+
param_name: string;
|
|
32
|
+
/** The invalid value */
|
|
33
|
+
value: string;
|
|
34
|
+
/** Reason for failure: too_long, whitespace, dotdot, or metachar */
|
|
35
|
+
reason: 'too_long' | 'whitespace' | 'dotdot' | 'metachar';
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Result of parameter validation.
|
|
39
|
+
*/
|
|
40
|
+
export interface ParamValidationResult {
|
|
41
|
+
/** True if all parameters are valid */
|
|
42
|
+
ok: boolean;
|
|
43
|
+
/** List of validation failures */
|
|
44
|
+
errors: ParamValidationError[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Validates a single parameter value against security constraints.
|
|
48
|
+
*
|
|
49
|
+
* Checks for:
|
|
50
|
+
* - Length exceeding max_param_len
|
|
51
|
+
* - Whitespace (if reject_whitespace_in_params is true)
|
|
52
|
+
* - Path traversal '..' (if reject_dotdot is true)
|
|
53
|
+
* - Shell metacharacters (using reject_metachars_regex)
|
|
54
|
+
*
|
|
55
|
+
* @param paramName - Name of the parameter being validated
|
|
56
|
+
* @param value - The parameter value to validate (converted to string)
|
|
57
|
+
* @param config - Verification configuration with validation rules
|
|
58
|
+
* @returns ParamValidationError if validation fails, null if valid
|
|
59
|
+
*/
|
|
60
|
+
export declare function validateParam(paramName: string, value: string | number | boolean | null, config: VerificationConfig): ParamValidationError | null;
|
|
61
|
+
/**
|
|
62
|
+
* Validates all verification parameters for a task.
|
|
63
|
+
*
|
|
64
|
+
* Validates all parameters in task.verification.params against the security
|
|
65
|
+
* constraints defined in the verification config.
|
|
66
|
+
*
|
|
67
|
+
* @param task - Task containing verification configuration and parameters
|
|
68
|
+
* @param config - Verification configuration with validation rules
|
|
69
|
+
* @returns ParamValidationResult with ok=true if all params valid, errors otherwise
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const result = validateVerificationParams(task, config.verification);
|
|
74
|
+
* if (!result.ok) {
|
|
75
|
+
* // Handle validation errors
|
|
76
|
+
* console.error('Invalid parameters:', result.errors);
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*/
|
|
80
|
+
export declare function validateVerificationParams(task: Task, config: VerificationConfig): ParamValidationResult;
|
|
81
|
+
/**
|
|
82
|
+
* Interpolates parameter placeholders in command arguments.
|
|
83
|
+
*
|
|
84
|
+
* Replaces {{param_name}} placeholders with values from the params object.
|
|
85
|
+
*
|
|
86
|
+
* @param args - Array of command arguments that may contain {{param}} placeholders
|
|
87
|
+
* @param params - Object mapping parameter names to values
|
|
88
|
+
* @returns Array of arguments with placeholders replaced
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* interpolateArgs(['--filter', '{{pkg}}'], { pkg: 'my-package' })
|
|
93
|
+
* // Returns: ['--filter', 'my-package']
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function interpolateArgs(args: string[], params: Record<string, string | number | boolean | null>): string[];
|
|
97
|
+
/**
|
|
98
|
+
* Executes a single verification command.
|
|
99
|
+
*
|
|
100
|
+
* Runs the command using spawn with shell:false for security. Captures stdout
|
|
101
|
+
* and stderr, enforces timeout, and returns execution results.
|
|
102
|
+
*
|
|
103
|
+
* @param template - Verification template containing cmd and args
|
|
104
|
+
* @param params - Parameters for template argument interpolation
|
|
105
|
+
* @param timeoutMs - Timeout in milliseconds (0 means no timeout)
|
|
106
|
+
* @returns Promise resolving to VerificationRun result
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```typescript
|
|
110
|
+
* const result = await executeVerification(
|
|
111
|
+
* { id: 'lint', cmd: 'pnpm', args: ['-w', 'lint'] },
|
|
112
|
+
* {},
|
|
113
|
+
* 90000
|
|
114
|
+
* );
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
export declare function executeVerification(template: VerificationTemplate, params: Record<string, string | number | boolean | null>, timeoutMs: number): Promise<VerificationRun>;
|
|
118
|
+
/**
|
|
119
|
+
* Runs verification commands for a task.
|
|
120
|
+
*
|
|
121
|
+
* Executes fast verifications first, then slow verifications. Each verification
|
|
122
|
+
* uses the appropriate timeout from config. Parameters are taken from the task's
|
|
123
|
+
* verification.params object, keyed by template ID.
|
|
124
|
+
*
|
|
125
|
+
* @param templates - Map of template ID to VerificationTemplate
|
|
126
|
+
* @param task - Task containing verification configuration
|
|
127
|
+
* @param config - Verification configuration with timeouts
|
|
128
|
+
* @returns Promise resolving to array of VerificationRun results
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* const templates = new Map([
|
|
133
|
+
* ['lint', { id: 'lint', cmd: 'pnpm', args: ['-w', 'lint'] }]
|
|
134
|
+
* ]);
|
|
135
|
+
* const runs = await runVerifications(templates, task, config.verification);
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export declare function runVerifications(templates: Map<string, VerificationTemplate>, task: Task, config: VerificationConfig): Promise<VerificationRun[]>;
|
|
139
|
+
//# sourceMappingURL=verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/lib/verify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,IAAI,EAAoB,MAAM,kBAAkB,CAAC;AAE/D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,wBAAwB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,oEAAoE;IACpE,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,QAAQ,GAAG,UAAU,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,uCAAuC;IACvC,EAAE,EAAE,OAAO,CAAC;IACZ,kCAAkC;IAClC,MAAM,EAAE,oBAAoB,EAAE,CAAC;CAChC;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,EACvC,MAAM,EAAE,kBAAkB,GACzB,oBAAoB,GAAG,IAAI,CAuD7B;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,kBAAkB,GACzB,qBAAqB,CAuBvB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,GACvD,MAAM,EAAE,CAcV;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mBAAmB,CACvC,QAAQ,EAAE,oBAAoB,EAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC,EACxD,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAgH1B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,EAC5C,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,eAAe,EAAE,CAAC,CAsC5B"}
|