opencara 0.0.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/dist/commands/agent.d.ts +46 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +924 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/login.d.ts +5 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +102 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/stats.d.ts +9 -0
- package/dist/commands/stats.d.ts.map +1 -0
- package/dist/commands/stats.js +187 -0
- package/dist/commands/stats.js.map +1 -0
- package/dist/config.d.ts +48 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +227 -0
- package/dist/config.js.map +1 -0
- package/dist/consumption.d.ts +21 -0
- package/dist/consumption.d.ts.map +1 -0
- package/dist/consumption.js +18 -0
- package/dist/consumption.js.map +1 -0
- package/dist/http.d.ts +14 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +59 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/reconnect.d.ts +10 -0
- package/dist/reconnect.d.ts.map +1 -0
- package/dist/reconnect.js +17 -0
- package/dist/reconnect.js.map +1 -0
- package/dist/review.d.ts +34 -0
- package/dist/review.d.ts.map +1 -0
- package/dist/review.js +109 -0
- package/dist/review.js.map +1 -0
- package/dist/summary.d.ts +34 -0
- package/dist/summary.d.ts.map +1 -0
- package/dist/summary.js +90 -0
- package/dist/summary.js.map +1 -0
- package/dist/tool-executor.d.ts +50 -0
- package/dist/tool-executor.d.ts.map +1 -0
- package/dist/tool-executor.js +232 -0
- package/dist/tool-executor.js.map +1 -0
- package/package.json +27 -0
package/dist/summary.js
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { executeTool, estimateTokens } from './tool-executor.js';
|
|
2
|
+
export const TIMEOUT_SAFETY_MARGIN_MS = 30_000;
|
|
3
|
+
export const MAX_INPUT_SIZE_BYTES = 200 * 1024;
|
|
4
|
+
export class InputTooLargeError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'InputTooLargeError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function buildSummarySystemPrompt(owner, repo, reviewCount) {
|
|
11
|
+
return `You are a senior code reviewer and lead synthesizer for the ${owner}/${repo} repository.
|
|
12
|
+
|
|
13
|
+
You will receive a pull request diff and ${reviewCount} review${reviewCount !== 1 ? 's' : ''} from other agents.
|
|
14
|
+
|
|
15
|
+
Your job:
|
|
16
|
+
1. Perform your own thorough, independent code review of the diff
|
|
17
|
+
2. Incorporate and synthesize ALL findings from the other reviews into yours
|
|
18
|
+
3. Deduplicate overlapping findings but preserve every unique insight
|
|
19
|
+
4. Provide detailed explanations and actionable fix suggestions for each issue
|
|
20
|
+
5. Produce ONE comprehensive, detailed review
|
|
21
|
+
|
|
22
|
+
Format your response as:
|
|
23
|
+
|
|
24
|
+
## Summary
|
|
25
|
+
[Overall assessment of the PR: what it does, its quality, and key concerns — 3-5 sentences]
|
|
26
|
+
|
|
27
|
+
## Findings
|
|
28
|
+
|
|
29
|
+
For each finding, provide a detailed entry:
|
|
30
|
+
|
|
31
|
+
### [severity] \`file:line\` — Short title
|
|
32
|
+
Detailed explanation of the issue, why it matters, and how to fix it.
|
|
33
|
+
Include code snippets showing the fix when helpful.
|
|
34
|
+
|
|
35
|
+
Severities: critical, major, minor, suggestion
|
|
36
|
+
Include ALL findings from ALL reviewers (deduplicated) plus your own discoveries.
|
|
37
|
+
For each finding, explain clearly what the problem is and how to fix it.
|
|
38
|
+
|
|
39
|
+
## Verdict
|
|
40
|
+
APPROVE | REQUEST_CHANGES | COMMENT`;
|
|
41
|
+
}
|
|
42
|
+
export function buildSummaryUserMessage(prompt, reviews, diffContent) {
|
|
43
|
+
const reviewSections = reviews
|
|
44
|
+
.map((r) => `### Review by ${r.model}/${r.tool} (Verdict: ${r.verdict})\n${r.review}`)
|
|
45
|
+
.join('\n\n');
|
|
46
|
+
return `Project review guidelines:\n${prompt}\n\n---\n\nPull request diff:\n\n${diffContent}\n\n---\n\nCompact reviews from other agents:\n\n${reviewSections}`;
|
|
47
|
+
}
|
|
48
|
+
export function calculateInputSize(prompt, reviews, diffContent) {
|
|
49
|
+
let size = Buffer.byteLength(prompt, 'utf-8');
|
|
50
|
+
size += Buffer.byteLength(diffContent, 'utf-8');
|
|
51
|
+
for (const r of reviews) {
|
|
52
|
+
size += Buffer.byteLength(r.review, 'utf-8');
|
|
53
|
+
size += Buffer.byteLength(r.model, 'utf-8');
|
|
54
|
+
size += Buffer.byteLength(r.tool, 'utf-8');
|
|
55
|
+
size += Buffer.byteLength(r.verdict, 'utf-8');
|
|
56
|
+
}
|
|
57
|
+
return size;
|
|
58
|
+
}
|
|
59
|
+
export async function executeSummary(req, deps, runTool = executeTool) {
|
|
60
|
+
const inputSize = calculateInputSize(req.prompt, req.reviews, req.diffContent);
|
|
61
|
+
if (inputSize > MAX_INPUT_SIZE_BYTES) {
|
|
62
|
+
throw new InputTooLargeError(`Summary input too large (${Math.round(inputSize / 1024)}KB > ${Math.round(MAX_INPUT_SIZE_BYTES / 1024)}KB limit)`);
|
|
63
|
+
}
|
|
64
|
+
const timeoutMs = req.timeout * 1000;
|
|
65
|
+
if (timeoutMs <= TIMEOUT_SAFETY_MARGIN_MS) {
|
|
66
|
+
throw new Error('Not enough time remaining to start summary');
|
|
67
|
+
}
|
|
68
|
+
const effectiveTimeout = timeoutMs - TIMEOUT_SAFETY_MARGIN_MS;
|
|
69
|
+
const abortController = new AbortController();
|
|
70
|
+
const abortTimer = setTimeout(() => {
|
|
71
|
+
abortController.abort();
|
|
72
|
+
}, effectiveTimeout);
|
|
73
|
+
try {
|
|
74
|
+
const systemPrompt = buildSummarySystemPrompt(req.owner, req.repo, req.reviews.length);
|
|
75
|
+
const userMessage = buildSummaryUserMessage(req.prompt, req.reviews, req.diffContent);
|
|
76
|
+
const fullPrompt = `${systemPrompt}\n\n${userMessage}`;
|
|
77
|
+
const result = await runTool(deps.commandTemplate, fullPrompt, effectiveTimeout, abortController.signal);
|
|
78
|
+
// Only add input estimate when tokens were estimated (not parsed from tool output)
|
|
79
|
+
const inputTokens = result.tokensParsed ? 0 : estimateTokens(fullPrompt);
|
|
80
|
+
return {
|
|
81
|
+
summary: result.stdout,
|
|
82
|
+
tokensUsed: result.tokensUsed + inputTokens,
|
|
83
|
+
tokensEstimated: !result.tokensParsed,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
finally {
|
|
87
|
+
clearTimeout(abortTimer);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=summary.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summary.js","sourceRoot":"","sources":["../src/summary.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export interface ToolExecutorResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
tokensUsed: number;
|
|
5
|
+
/** True if tokensUsed was parsed from tool output (includes input+output).
|
|
6
|
+
* False if estimated from output text only (callers should add input estimate). */
|
|
7
|
+
tokensParsed: boolean;
|
|
8
|
+
}
|
|
9
|
+
export declare class ToolTimeoutError extends Error {
|
|
10
|
+
constructor(message: string);
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Validate that the binary referenced by a command template exists and is executable.
|
|
14
|
+
* Cross-platform: uses `where` on Windows, `command -v` via shell on Unix.
|
|
15
|
+
*/
|
|
16
|
+
export declare function validateCommandBinary(commandTemplate: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Parse a command template string into command + args.
|
|
19
|
+
* Splits on whitespace first, then interpolates ${VAR} variables.
|
|
20
|
+
* This ensures variables containing spaces/special chars stay as single args.
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseCommandTemplate(template: string, vars?: Record<string, string>): {
|
|
23
|
+
command: string;
|
|
24
|
+
args: string[];
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Resolve a command template from explicit config.
|
|
28
|
+
* Returns the template string or throws if not available.
|
|
29
|
+
*/
|
|
30
|
+
export declare function resolveCommandTemplate(agentCommand: string | null | undefined): string;
|
|
31
|
+
/**
|
|
32
|
+
* Estimate token count from text length (~4 chars per token).
|
|
33
|
+
*/
|
|
34
|
+
export declare function estimateTokens(text: string): number;
|
|
35
|
+
/**
|
|
36
|
+
* Parse token usage from tool output. Tries tool-specific patterns first,
|
|
37
|
+
* then falls back to character-based estimation.
|
|
38
|
+
*/
|
|
39
|
+
export declare function parseTokenUsage(stdout: string, stderr: string): {
|
|
40
|
+
tokens: number;
|
|
41
|
+
parsed: boolean;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Execute a tool command with prompt.
|
|
45
|
+
*
|
|
46
|
+
* If the command template contains `${PROMPT}`, the prompt is interpolated
|
|
47
|
+
* as a CLI argument. Otherwise, the prompt is delivered via stdin.
|
|
48
|
+
*/
|
|
49
|
+
export declare function executeTool(commandTemplate: string, prompt: string, timeoutMs: number, signal?: AbortSignal, vars?: Record<string, string>): Promise<ToolExecutorResult>;
|
|
50
|
+
//# sourceMappingURL=tool-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-executor.d.ts","sourceRoot":"","sources":["../src/tool-executor.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB;wFACoF;IACpF,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,qBAAa,gBAAiB,SAAQ,KAAK;gBAC7B,OAAO,EAAE,MAAM;CAI5B;AAQD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAwBtE;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAM,GAChC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAwCrC;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAQtF;AAID;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAWD;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,GACb;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAerC;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,WAAW,EACpB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC5B,OAAO,CAAC,kBAAkB,CAAC,CA8G7B"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { spawn, execFileSync } from 'node:child_process';
|
|
2
|
+
import * as fs from 'node:fs';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
export class ToolTimeoutError extends Error {
|
|
5
|
+
constructor(message) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.name = 'ToolTimeoutError';
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
/** Minimum stdout length to treat a non-zero exit as a partial success */
|
|
11
|
+
const MIN_PARTIAL_RESULT_LENGTH = 50;
|
|
12
|
+
/** Maximum stderr length included in error/warning messages */
|
|
13
|
+
const MAX_STDERR_LENGTH = 1000;
|
|
14
|
+
/**
|
|
15
|
+
* Validate that the binary referenced by a command template exists and is executable.
|
|
16
|
+
* Cross-platform: uses `where` on Windows, `command -v` via shell on Unix.
|
|
17
|
+
*/
|
|
18
|
+
export function validateCommandBinary(commandTemplate) {
|
|
19
|
+
const { command } = parseCommandTemplate(commandTemplate);
|
|
20
|
+
if (path.isAbsolute(command)) {
|
|
21
|
+
try {
|
|
22
|
+
fs.accessSync(command, fs.constants.X_OK);
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
const isWindows = process.platform === 'win32';
|
|
31
|
+
if (isWindows) {
|
|
32
|
+
execFileSync('where', [command], { stdio: 'pipe' });
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// Pass command as positional arg to avoid shell injection
|
|
36
|
+
execFileSync('sh', ['-c', 'command -v -- "$1"', '_', command], { stdio: 'pipe' });
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parse a command template string into command + args.
|
|
46
|
+
* Splits on whitespace first, then interpolates ${VAR} variables.
|
|
47
|
+
* This ensures variables containing spaces/special chars stay as single args.
|
|
48
|
+
*/
|
|
49
|
+
export function parseCommandTemplate(template, vars = {}) {
|
|
50
|
+
// Split on whitespace first, respecting quoted strings
|
|
51
|
+
const parts = [];
|
|
52
|
+
let current = '';
|
|
53
|
+
let inSingle = false;
|
|
54
|
+
let inDouble = false;
|
|
55
|
+
for (let i = 0; i < template.length; i++) {
|
|
56
|
+
const ch = template[i];
|
|
57
|
+
if (ch === "'" && !inDouble) {
|
|
58
|
+
inSingle = !inSingle;
|
|
59
|
+
}
|
|
60
|
+
else if (ch === '"' && !inSingle) {
|
|
61
|
+
inDouble = !inDouble;
|
|
62
|
+
}
|
|
63
|
+
else if (/\s/.test(ch) && !inSingle && !inDouble) {
|
|
64
|
+
if (current.length > 0) {
|
|
65
|
+
parts.push(current);
|
|
66
|
+
current = '';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
current += ch;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (current.length > 0) {
|
|
74
|
+
parts.push(current);
|
|
75
|
+
}
|
|
76
|
+
// Interpolate variables after splitting — each ${VAR} stays as one arg
|
|
77
|
+
const interpolated = parts.map((part) => {
|
|
78
|
+
let result = part;
|
|
79
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
80
|
+
result = result.replaceAll(`\${${key}}`, value);
|
|
81
|
+
}
|
|
82
|
+
return result;
|
|
83
|
+
});
|
|
84
|
+
if (interpolated.length === 0) {
|
|
85
|
+
throw new Error('Empty command template');
|
|
86
|
+
}
|
|
87
|
+
return { command: interpolated[0], args: interpolated.slice(1) };
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Resolve a command template from explicit config.
|
|
91
|
+
* Returns the template string or throws if not available.
|
|
92
|
+
*/
|
|
93
|
+
export function resolveCommandTemplate(agentCommand) {
|
|
94
|
+
if (agentCommand) {
|
|
95
|
+
return agentCommand;
|
|
96
|
+
}
|
|
97
|
+
throw new Error('No command configured for this agent. ' +
|
|
98
|
+
'Set command in ~/.opencara/config.yml agents section or run `opencara agent create`.');
|
|
99
|
+
}
|
|
100
|
+
const CHARS_PER_TOKEN = 4;
|
|
101
|
+
/**
|
|
102
|
+
* Estimate token count from text length (~4 chars per token).
|
|
103
|
+
*/
|
|
104
|
+
export function estimateTokens(text) {
|
|
105
|
+
return Math.ceil(text.length / CHARS_PER_TOKEN);
|
|
106
|
+
}
|
|
107
|
+
function parseClaudeTokens(text) {
|
|
108
|
+
const inputMatch = text.match(/"input_tokens"\s*:\s*(\d+)/);
|
|
109
|
+
const outputMatch = text.match(/"output_tokens"\s*:\s*(\d+)/);
|
|
110
|
+
if (inputMatch && outputMatch) {
|
|
111
|
+
return parseInt(inputMatch[1], 10) + parseInt(outputMatch[1], 10);
|
|
112
|
+
}
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Parse token usage from tool output. Tries tool-specific patterns first,
|
|
117
|
+
* then falls back to character-based estimation.
|
|
118
|
+
*/
|
|
119
|
+
export function parseTokenUsage(stdout, stderr) {
|
|
120
|
+
// Codex: "tokens used 1,801" or "tokens used\n1,801" in stdout footer
|
|
121
|
+
const codexMatch = stdout.match(/tokens\s+used[\s:]*([0-9,]+)/i);
|
|
122
|
+
if (codexMatch)
|
|
123
|
+
return { tokens: parseInt(codexMatch[1].replace(/,/g, ''), 10), parsed: true };
|
|
124
|
+
// Claude JSON: "input_tokens" and "output_tokens" (order-independent)
|
|
125
|
+
const claudeTotal = parseClaudeTokens(stdout) ?? parseClaudeTokens(stderr);
|
|
126
|
+
if (claudeTotal !== null)
|
|
127
|
+
return { tokens: claudeTotal, parsed: true };
|
|
128
|
+
// Qwen JSON stats: "tokens": {"total": N}
|
|
129
|
+
const qwenMatch = stdout.match(/"tokens"\s*:\s*\{[^}]*"total"\s*:\s*(\d+)/);
|
|
130
|
+
if (qwenMatch)
|
|
131
|
+
return { tokens: parseInt(qwenMatch[1], 10), parsed: true };
|
|
132
|
+
// Fallback: estimate from output text length
|
|
133
|
+
return { tokens: estimateTokens(stdout), parsed: false };
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Execute a tool command with prompt.
|
|
137
|
+
*
|
|
138
|
+
* If the command template contains `${PROMPT}`, the prompt is interpolated
|
|
139
|
+
* as a CLI argument. Otherwise, the prompt is delivered via stdin.
|
|
140
|
+
*/
|
|
141
|
+
export function executeTool(commandTemplate, prompt, timeoutMs, signal, vars) {
|
|
142
|
+
const promptViaArg = commandTemplate.includes('${PROMPT}');
|
|
143
|
+
const allVars = { ...vars, PROMPT: prompt };
|
|
144
|
+
const { command, args } = parseCommandTemplate(commandTemplate, allVars);
|
|
145
|
+
return new Promise((resolve, reject) => {
|
|
146
|
+
if (signal?.aborted) {
|
|
147
|
+
reject(new ToolTimeoutError('Tool execution aborted'));
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
const child = spawn(command, args, {
|
|
151
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
152
|
+
});
|
|
153
|
+
let stdout = '';
|
|
154
|
+
let stderr = '';
|
|
155
|
+
let settled = false;
|
|
156
|
+
// Timeout handling via manual timer since spawn doesn't support timeout
|
|
157
|
+
const timer = setTimeout(() => {
|
|
158
|
+
child.kill('SIGTERM');
|
|
159
|
+
}, timeoutMs);
|
|
160
|
+
child.stdout?.on('data', (chunk) => {
|
|
161
|
+
stdout += chunk.toString();
|
|
162
|
+
});
|
|
163
|
+
child.stderr?.on('data', (chunk) => {
|
|
164
|
+
stderr += chunk.toString();
|
|
165
|
+
});
|
|
166
|
+
// Deliver prompt via stdin only if not already in args
|
|
167
|
+
if (!promptViaArg) {
|
|
168
|
+
child.stdin?.write(prompt);
|
|
169
|
+
}
|
|
170
|
+
child.stdin?.end();
|
|
171
|
+
// Set up abort signal handler (stored for cleanup)
|
|
172
|
+
let onAbort;
|
|
173
|
+
if (signal) {
|
|
174
|
+
onAbort = () => {
|
|
175
|
+
child.kill();
|
|
176
|
+
};
|
|
177
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
178
|
+
}
|
|
179
|
+
function cleanup() {
|
|
180
|
+
clearTimeout(timer);
|
|
181
|
+
if (onAbort && signal) {
|
|
182
|
+
signal.removeEventListener('abort', onAbort);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
child.on('error', (err) => {
|
|
186
|
+
cleanup();
|
|
187
|
+
if (settled)
|
|
188
|
+
return;
|
|
189
|
+
settled = true;
|
|
190
|
+
if (signal?.aborted) {
|
|
191
|
+
reject(new ToolTimeoutError('Tool execution aborted'));
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
reject(err);
|
|
195
|
+
});
|
|
196
|
+
child.on('close', (code, sig) => {
|
|
197
|
+
cleanup();
|
|
198
|
+
if (settled)
|
|
199
|
+
return;
|
|
200
|
+
settled = true;
|
|
201
|
+
if (signal?.aborted) {
|
|
202
|
+
reject(new ToolTimeoutError('Tool execution aborted'));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
if (sig === 'SIGTERM' || sig === 'SIGKILL') {
|
|
206
|
+
reject(new ToolTimeoutError(`Tool "${command}" timed out after ${Math.round(timeoutMs / 1000)}s`));
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (code !== 0) {
|
|
210
|
+
// Non-zero exit but has meaningful output — treat as partial success
|
|
211
|
+
if (stdout.length >= MIN_PARTIAL_RESULT_LENGTH) {
|
|
212
|
+
console.warn(`Tool "${command}" exited with code ${code} but produced output. Treating as partial result.`);
|
|
213
|
+
if (stderr) {
|
|
214
|
+
console.warn(`Tool stderr: ${stderr.slice(0, MAX_STDERR_LENGTH)}`);
|
|
215
|
+
}
|
|
216
|
+
const usage = parseTokenUsage(stdout, stderr);
|
|
217
|
+
resolve({ stdout, stderr, tokensUsed: usage.tokens, tokensParsed: usage.parsed });
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// No meaningful output — actual failure
|
|
221
|
+
const errMsg = stderr
|
|
222
|
+
? `Tool "${command}" failed (exit code ${code}): ${stderr.slice(0, MAX_STDERR_LENGTH)}`
|
|
223
|
+
: `Tool "${command}" failed with exit code ${code}`;
|
|
224
|
+
reject(new Error(errMsg));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const usage = parseTokenUsage(stdout, stderr);
|
|
228
|
+
resolve({ stdout, stderr, tokensUsed: usage.tokens, tokensParsed: usage.parsed });
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
//# sourceMappingURL=tool-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-executor.js","sourceRoot":"","sources":["../src/tool-executor.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "opencara",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"opencara": "dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc --build",
|
|
13
|
+
"dev": "tsx src/index.ts",
|
|
14
|
+
"clean": "rm -rf dist *.tsbuildinfo"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@inquirer/prompts": "^8.3.2",
|
|
18
|
+
"@opencara/shared": "workspace:*",
|
|
19
|
+
"commander": "^13.0.0",
|
|
20
|
+
"ws": "^8.18.0",
|
|
21
|
+
"yaml": "^2.7.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/ws": "^8.5.0",
|
|
25
|
+
"tsx": "^4.0.0"
|
|
26
|
+
}
|
|
27
|
+
}
|