@corbat-tech/coco 1.5.0 → 1.7.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/dist/cli/index.js +1958 -875
- package/dist/cli/index.js.map +1 -1
- package/dist/index.js +271 -25
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/README.old.md +0 -310
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { z } from 'zod';
|
|
|
18
18
|
import { Logger } from 'tslog';
|
|
19
19
|
import Anthropic from '@anthropic-ai/sdk';
|
|
20
20
|
import OpenAI from 'openai';
|
|
21
|
+
import { jsonrepair } from 'jsonrepair';
|
|
21
22
|
import 'http';
|
|
22
23
|
import { GoogleGenerativeAI, FunctionCallingMode } from '@google/generative-ai';
|
|
23
24
|
import JSON5 from 'json5';
|
|
@@ -255,6 +256,71 @@ var init_allowed_paths = __esm({
|
|
|
255
256
|
}
|
|
256
257
|
});
|
|
257
258
|
|
|
259
|
+
// src/tools/utils/heartbeat.ts
|
|
260
|
+
var heartbeat_exports = {};
|
|
261
|
+
__export(heartbeat_exports, {
|
|
262
|
+
CommandHeartbeat: () => CommandHeartbeat
|
|
263
|
+
});
|
|
264
|
+
var CommandHeartbeat;
|
|
265
|
+
var init_heartbeat = __esm({
|
|
266
|
+
"src/tools/utils/heartbeat.ts"() {
|
|
267
|
+
CommandHeartbeat = class {
|
|
268
|
+
startTime = 0;
|
|
269
|
+
lastActivityTime = 0;
|
|
270
|
+
updateInterval = null;
|
|
271
|
+
warnThreshold = 30;
|
|
272
|
+
// seconds
|
|
273
|
+
updateIntervalSeconds = 10;
|
|
274
|
+
// seconds
|
|
275
|
+
callbacks;
|
|
276
|
+
constructor(callbacks = {}) {
|
|
277
|
+
this.callbacks = callbacks;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Start monitoring - begins periodic updates and silence warnings
|
|
281
|
+
*/
|
|
282
|
+
start() {
|
|
283
|
+
this.startTime = Date.now();
|
|
284
|
+
this.lastActivityTime = Date.now();
|
|
285
|
+
this.updateInterval = setInterval(() => {
|
|
286
|
+
const stats = this.getStats();
|
|
287
|
+
this.callbacks.onUpdate?.(stats);
|
|
288
|
+
if (stats.silentSeconds >= this.warnThreshold) {
|
|
289
|
+
this.callbacks.onWarn?.(`\u26A0\uFE0F Command silent for ${stats.silentSeconds}s`);
|
|
290
|
+
}
|
|
291
|
+
}, this.updateIntervalSeconds * 1e3);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Register activity - call this when command produces output
|
|
295
|
+
* Resets the silence timer
|
|
296
|
+
*/
|
|
297
|
+
activity() {
|
|
298
|
+
this.lastActivityTime = Date.now();
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Stop monitoring - clears periodic interval
|
|
302
|
+
* Should be called in finally{} block to ensure cleanup
|
|
303
|
+
*/
|
|
304
|
+
stop() {
|
|
305
|
+
if (this.updateInterval) {
|
|
306
|
+
clearInterval(this.updateInterval);
|
|
307
|
+
this.updateInterval = null;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
/**
|
|
311
|
+
* Get current heartbeat statistics
|
|
312
|
+
*/
|
|
313
|
+
getStats() {
|
|
314
|
+
const now = Date.now();
|
|
315
|
+
return {
|
|
316
|
+
elapsedSeconds: Math.floor((now - this.startTime) / 1e3),
|
|
317
|
+
silentSeconds: Math.floor((now - this.lastActivityTime) / 1e3)
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
});
|
|
323
|
+
|
|
258
324
|
// src/cli/repl/allow-path-prompt.ts
|
|
259
325
|
var allow_path_prompt_exports = {};
|
|
260
326
|
__export(allow_path_prompt_exports, {
|
|
@@ -10616,8 +10682,10 @@ var OpenAIProvider = class {
|
|
|
10616
10682
|
const timeoutInterval = setInterval(checkTimeout, 5e3);
|
|
10617
10683
|
try {
|
|
10618
10684
|
for await (const chunk of stream) {
|
|
10619
|
-
lastActivityTime = Date.now();
|
|
10620
10685
|
const delta = chunk.choices[0]?.delta;
|
|
10686
|
+
if (delta?.content || delta?.tool_calls) {
|
|
10687
|
+
lastActivityTime = Date.now();
|
|
10688
|
+
}
|
|
10621
10689
|
if (delta?.content) {
|
|
10622
10690
|
yield { type: "text", text: delta.content };
|
|
10623
10691
|
}
|
|
@@ -10663,10 +10731,22 @@ var OpenAIProvider = class {
|
|
|
10663
10731
|
let input = {};
|
|
10664
10732
|
try {
|
|
10665
10733
|
input = builder.arguments ? JSON.parse(builder.arguments) : {};
|
|
10666
|
-
} catch {
|
|
10734
|
+
} catch (error) {
|
|
10667
10735
|
console.warn(
|
|
10668
|
-
`[
|
|
10736
|
+
`[${this.name}] Failed to parse tool call arguments for ${builder.name}: ${builder.arguments?.slice(0, 100)}`
|
|
10669
10737
|
);
|
|
10738
|
+
try {
|
|
10739
|
+
if (builder.arguments) {
|
|
10740
|
+
const repaired = jsonrepair(builder.arguments);
|
|
10741
|
+
input = JSON.parse(repaired);
|
|
10742
|
+
console.log(`[${this.name}] \u2713 Successfully repaired JSON for ${builder.name}`);
|
|
10743
|
+
}
|
|
10744
|
+
} catch (repairError) {
|
|
10745
|
+
console.error(
|
|
10746
|
+
`[${this.name}] Cannot repair JSON for ${builder.name}, using empty object`
|
|
10747
|
+
);
|
|
10748
|
+
console.error(`[${this.name}] Original error:`, error);
|
|
10749
|
+
}
|
|
10670
10750
|
}
|
|
10671
10751
|
yield {
|
|
10672
10752
|
type: "tool_use_end",
|
|
@@ -10960,7 +11040,7 @@ var OpenAIProvider = class {
|
|
|
10960
11040
|
return JSON.parse(tc.function.arguments || "{}");
|
|
10961
11041
|
} catch {
|
|
10962
11042
|
console.warn(
|
|
10963
|
-
`[
|
|
11043
|
+
`[${this.name}] Failed to parse tool call arguments: ${tc.function.arguments?.slice(0, 100)}`
|
|
10964
11044
|
);
|
|
10965
11045
|
return {};
|
|
10966
11046
|
}
|
|
@@ -11898,12 +11978,12 @@ async function createProvider(type, config = {}) {
|
|
|
11898
11978
|
await provider.initialize(mergedConfig);
|
|
11899
11979
|
return provider;
|
|
11900
11980
|
case "lmstudio":
|
|
11901
|
-
provider = new OpenAIProvider();
|
|
11981
|
+
provider = new OpenAIProvider("lmstudio", "LM Studio");
|
|
11902
11982
|
mergedConfig.baseUrl = mergedConfig.baseUrl ?? "http://localhost:1234/v1";
|
|
11903
11983
|
mergedConfig.apiKey = mergedConfig.apiKey ?? "lm-studio";
|
|
11904
11984
|
break;
|
|
11905
11985
|
case "ollama":
|
|
11906
|
-
provider = new OpenAIProvider();
|
|
11986
|
+
provider = new OpenAIProvider("ollama", "Ollama");
|
|
11907
11987
|
mergedConfig.baseUrl = mergedConfig.baseUrl ?? "http://localhost:11434/v1";
|
|
11908
11988
|
mergedConfig.apiKey = mergedConfig.apiKey ?? "ollama";
|
|
11909
11989
|
break;
|
|
@@ -13394,23 +13474,50 @@ Examples:
|
|
|
13394
13474
|
}
|
|
13395
13475
|
const startTime = performance.now();
|
|
13396
13476
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS;
|
|
13477
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
13478
|
+
const heartbeat = new CommandHeartbeat2({
|
|
13479
|
+
onUpdate: (stats) => {
|
|
13480
|
+
if (stats.elapsedSeconds > 10) {
|
|
13481
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
13482
|
+
}
|
|
13483
|
+
},
|
|
13484
|
+
onWarn: (message) => {
|
|
13485
|
+
process.stderr.write(`
|
|
13486
|
+
${message}
|
|
13487
|
+
`);
|
|
13488
|
+
}
|
|
13489
|
+
});
|
|
13397
13490
|
try {
|
|
13491
|
+
heartbeat.start();
|
|
13398
13492
|
const options = {
|
|
13399
13493
|
cwd: cwd ?? process.cwd(),
|
|
13400
13494
|
timeout: timeoutMs,
|
|
13401
13495
|
env: { ...process.env, ...env2 },
|
|
13402
13496
|
shell: true,
|
|
13403
13497
|
reject: false,
|
|
13498
|
+
buffer: false,
|
|
13499
|
+
// Enable streaming
|
|
13404
13500
|
maxBuffer: MAX_OUTPUT_SIZE
|
|
13405
13501
|
};
|
|
13406
|
-
const
|
|
13502
|
+
const subprocess = execa(command, options);
|
|
13503
|
+
let stdoutBuffer = "";
|
|
13504
|
+
let stderrBuffer = "";
|
|
13505
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
13506
|
+
const text = chunk.toString();
|
|
13507
|
+
stdoutBuffer += text;
|
|
13508
|
+
process.stdout.write(text);
|
|
13509
|
+
heartbeat.activity();
|
|
13510
|
+
});
|
|
13511
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
13512
|
+
const text = chunk.toString();
|
|
13513
|
+
stderrBuffer += text;
|
|
13514
|
+
process.stderr.write(text);
|
|
13515
|
+
heartbeat.activity();
|
|
13516
|
+
});
|
|
13517
|
+
const result = await subprocess;
|
|
13407
13518
|
return {
|
|
13408
|
-
stdout: truncateOutput(
|
|
13409
|
-
|
|
13410
|
-
),
|
|
13411
|
-
stderr: truncateOutput(
|
|
13412
|
-
typeof result.stderr === "string" ? result.stderr : String(result.stderr ?? "")
|
|
13413
|
-
),
|
|
13519
|
+
stdout: truncateOutput(stdoutBuffer),
|
|
13520
|
+
stderr: truncateOutput(stderrBuffer),
|
|
13414
13521
|
exitCode: result.exitCode ?? 0,
|
|
13415
13522
|
duration: performance.now() - startTime
|
|
13416
13523
|
};
|
|
@@ -13425,6 +13532,9 @@ Examples:
|
|
|
13425
13532
|
`Command execution failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
13426
13533
|
{ tool: "bash_exec", cause: error instanceof Error ? error : void 0 }
|
|
13427
13534
|
);
|
|
13535
|
+
} finally {
|
|
13536
|
+
heartbeat.stop();
|
|
13537
|
+
process.stderr.write("\r \r");
|
|
13428
13538
|
}
|
|
13429
13539
|
}
|
|
13430
13540
|
});
|
|
@@ -15051,7 +15161,21 @@ Examples:
|
|
|
15051
15161
|
const projectDir = cwd ?? process.cwd();
|
|
15052
15162
|
const startTime = performance.now();
|
|
15053
15163
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
|
|
15164
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
15165
|
+
const heartbeat = new CommandHeartbeat2({
|
|
15166
|
+
onUpdate: (stats) => {
|
|
15167
|
+
if (stats.elapsedSeconds > 10) {
|
|
15168
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
15169
|
+
}
|
|
15170
|
+
},
|
|
15171
|
+
onWarn: (message) => {
|
|
15172
|
+
process.stderr.write(`
|
|
15173
|
+
${message}
|
|
15174
|
+
`);
|
|
15175
|
+
}
|
|
15176
|
+
});
|
|
15054
15177
|
try {
|
|
15178
|
+
heartbeat.start();
|
|
15055
15179
|
const pm = packageManager ?? await detectPackageManager(projectDir);
|
|
15056
15180
|
const cmdArgs = ["run", script];
|
|
15057
15181
|
if (args && args.length > 0) {
|
|
@@ -15062,13 +15186,30 @@ Examples:
|
|
|
15062
15186
|
timeout: timeoutMs,
|
|
15063
15187
|
env: { ...process.env, ...env2 },
|
|
15064
15188
|
reject: false,
|
|
15189
|
+
buffer: false,
|
|
15190
|
+
// Enable streaming
|
|
15065
15191
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
15066
15192
|
};
|
|
15067
|
-
const
|
|
15193
|
+
const subprocess = execa(pm, cmdArgs, options);
|
|
15194
|
+
let stdoutBuffer = "";
|
|
15195
|
+
let stderrBuffer = "";
|
|
15196
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
15197
|
+
const text = chunk.toString();
|
|
15198
|
+
stdoutBuffer += text;
|
|
15199
|
+
process.stdout.write(text);
|
|
15200
|
+
heartbeat.activity();
|
|
15201
|
+
});
|
|
15202
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
15203
|
+
const text = chunk.toString();
|
|
15204
|
+
stderrBuffer += text;
|
|
15205
|
+
process.stderr.write(text);
|
|
15206
|
+
heartbeat.activity();
|
|
15207
|
+
});
|
|
15208
|
+
const result = await subprocess;
|
|
15068
15209
|
return {
|
|
15069
15210
|
success: result.exitCode === 0,
|
|
15070
|
-
stdout: truncateOutput2(
|
|
15071
|
-
stderr: truncateOutput2(
|
|
15211
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
15212
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
15072
15213
|
exitCode: result.exitCode ?? 0,
|
|
15073
15214
|
duration: performance.now() - startTime,
|
|
15074
15215
|
packageManager: pm
|
|
@@ -15084,6 +15225,9 @@ Examples:
|
|
|
15084
15225
|
`Failed to run script '${script}': ${error instanceof Error ? error.message : String(error)}`,
|
|
15085
15226
|
{ tool: "run_script", cause: error instanceof Error ? error : void 0 }
|
|
15086
15227
|
);
|
|
15228
|
+
} finally {
|
|
15229
|
+
heartbeat.stop();
|
|
15230
|
+
process.stderr.write("\r \r");
|
|
15087
15231
|
}
|
|
15088
15232
|
}
|
|
15089
15233
|
});
|
|
@@ -15109,7 +15253,21 @@ Examples:
|
|
|
15109
15253
|
const projectDir = cwd ?? process.cwd();
|
|
15110
15254
|
const startTime = performance.now();
|
|
15111
15255
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
|
|
15256
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
15257
|
+
const heartbeat = new CommandHeartbeat2({
|
|
15258
|
+
onUpdate: (stats) => {
|
|
15259
|
+
if (stats.elapsedSeconds > 10) {
|
|
15260
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
15261
|
+
}
|
|
15262
|
+
},
|
|
15263
|
+
onWarn: (message) => {
|
|
15264
|
+
process.stderr.write(`
|
|
15265
|
+
${message}
|
|
15266
|
+
`);
|
|
15267
|
+
}
|
|
15268
|
+
});
|
|
15112
15269
|
try {
|
|
15270
|
+
heartbeat.start();
|
|
15113
15271
|
const pm = packageManager ?? await detectPackageManager(projectDir);
|
|
15114
15272
|
let cmdArgs;
|
|
15115
15273
|
if (packages && packages.length > 0) {
|
|
@@ -15149,13 +15307,30 @@ Examples:
|
|
|
15149
15307
|
cwd: projectDir,
|
|
15150
15308
|
timeout: timeoutMs,
|
|
15151
15309
|
reject: false,
|
|
15310
|
+
buffer: false,
|
|
15311
|
+
// Enable streaming
|
|
15152
15312
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
15153
15313
|
};
|
|
15154
|
-
const
|
|
15314
|
+
const subprocess = execa(pm, cmdArgs, options);
|
|
15315
|
+
let stdoutBuffer = "";
|
|
15316
|
+
let stderrBuffer = "";
|
|
15317
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
15318
|
+
const text = chunk.toString();
|
|
15319
|
+
stdoutBuffer += text;
|
|
15320
|
+
process.stdout.write(text);
|
|
15321
|
+
heartbeat.activity();
|
|
15322
|
+
});
|
|
15323
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
15324
|
+
const text = chunk.toString();
|
|
15325
|
+
stderrBuffer += text;
|
|
15326
|
+
process.stderr.write(text);
|
|
15327
|
+
heartbeat.activity();
|
|
15328
|
+
});
|
|
15329
|
+
const result = await subprocess;
|
|
15155
15330
|
return {
|
|
15156
15331
|
success: result.exitCode === 0,
|
|
15157
|
-
stdout: truncateOutput2(
|
|
15158
|
-
stderr: truncateOutput2(
|
|
15332
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
15333
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
15159
15334
|
exitCode: result.exitCode ?? 0,
|
|
15160
15335
|
duration: performance.now() - startTime,
|
|
15161
15336
|
packageManager: pm
|
|
@@ -15171,6 +15346,9 @@ Examples:
|
|
|
15171
15346
|
`Failed to install dependencies: ${error instanceof Error ? error.message : String(error)}`,
|
|
15172
15347
|
{ tool: "install_deps", cause: error instanceof Error ? error : void 0 }
|
|
15173
15348
|
);
|
|
15349
|
+
} finally {
|
|
15350
|
+
heartbeat.stop();
|
|
15351
|
+
process.stderr.write("\r \r");
|
|
15174
15352
|
}
|
|
15175
15353
|
}
|
|
15176
15354
|
});
|
|
@@ -15195,12 +15373,26 @@ Examples:
|
|
|
15195
15373
|
const projectDir = cwd ?? process.cwd();
|
|
15196
15374
|
const startTime = performance.now();
|
|
15197
15375
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
|
|
15376
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
15377
|
+
const heartbeat = new CommandHeartbeat2({
|
|
15378
|
+
onUpdate: (stats) => {
|
|
15379
|
+
if (stats.elapsedSeconds > 10) {
|
|
15380
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
15381
|
+
}
|
|
15382
|
+
},
|
|
15383
|
+
onWarn: (message) => {
|
|
15384
|
+
process.stderr.write(`
|
|
15385
|
+
${message}
|
|
15386
|
+
`);
|
|
15387
|
+
}
|
|
15388
|
+
});
|
|
15198
15389
|
try {
|
|
15199
15390
|
try {
|
|
15200
15391
|
await fs14__default.access(path14__default.join(projectDir, "Makefile"));
|
|
15201
15392
|
} catch {
|
|
15202
15393
|
throw new ToolError("No Makefile found in directory", { tool: "make" });
|
|
15203
15394
|
}
|
|
15395
|
+
heartbeat.start();
|
|
15204
15396
|
const cmdArgs = [];
|
|
15205
15397
|
if (target) {
|
|
15206
15398
|
cmdArgs.push(...target.split(/\s+/));
|
|
@@ -15213,13 +15405,30 @@ Examples:
|
|
|
15213
15405
|
timeout: timeoutMs,
|
|
15214
15406
|
env: { ...process.env, ...env2 },
|
|
15215
15407
|
reject: false,
|
|
15408
|
+
buffer: false,
|
|
15409
|
+
// Enable streaming
|
|
15216
15410
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
15217
15411
|
};
|
|
15218
|
-
const
|
|
15412
|
+
const subprocess = execa("make", cmdArgs, options);
|
|
15413
|
+
let stdoutBuffer = "";
|
|
15414
|
+
let stderrBuffer = "";
|
|
15415
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
15416
|
+
const text = chunk.toString();
|
|
15417
|
+
stdoutBuffer += text;
|
|
15418
|
+
process.stdout.write(text);
|
|
15419
|
+
heartbeat.activity();
|
|
15420
|
+
});
|
|
15421
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
15422
|
+
const text = chunk.toString();
|
|
15423
|
+
stderrBuffer += text;
|
|
15424
|
+
process.stderr.write(text);
|
|
15425
|
+
heartbeat.activity();
|
|
15426
|
+
});
|
|
15427
|
+
const result = await subprocess;
|
|
15219
15428
|
return {
|
|
15220
15429
|
success: result.exitCode === 0,
|
|
15221
|
-
stdout: truncateOutput2(
|
|
15222
|
-
stderr: truncateOutput2(
|
|
15430
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
15431
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
15223
15432
|
exitCode: result.exitCode ?? 0,
|
|
15224
15433
|
duration: performance.now() - startTime
|
|
15225
15434
|
};
|
|
@@ -15235,6 +15444,9 @@ Examples:
|
|
|
15235
15444
|
`Make failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
15236
15445
|
{ tool: "make", cause: error instanceof Error ? error : void 0 }
|
|
15237
15446
|
);
|
|
15447
|
+
} finally {
|
|
15448
|
+
heartbeat.stop();
|
|
15449
|
+
process.stderr.write("\r \r");
|
|
15238
15450
|
}
|
|
15239
15451
|
}
|
|
15240
15452
|
});
|
|
@@ -15260,7 +15472,21 @@ Examples:
|
|
|
15260
15472
|
const projectDir = cwd ?? process.cwd();
|
|
15261
15473
|
const startTime = performance.now();
|
|
15262
15474
|
const timeoutMs = timeout ?? DEFAULT_TIMEOUT_MS3;
|
|
15475
|
+
const { CommandHeartbeat: CommandHeartbeat2 } = await Promise.resolve().then(() => (init_heartbeat(), heartbeat_exports));
|
|
15476
|
+
const heartbeat = new CommandHeartbeat2({
|
|
15477
|
+
onUpdate: (stats) => {
|
|
15478
|
+
if (stats.elapsedSeconds > 10) {
|
|
15479
|
+
process.stderr.write(`\r\u23F1\uFE0F ${stats.elapsedSeconds}s elapsed`);
|
|
15480
|
+
}
|
|
15481
|
+
},
|
|
15482
|
+
onWarn: (message) => {
|
|
15483
|
+
process.stderr.write(`
|
|
15484
|
+
${message}
|
|
15485
|
+
`);
|
|
15486
|
+
}
|
|
15487
|
+
});
|
|
15263
15488
|
try {
|
|
15489
|
+
heartbeat.start();
|
|
15264
15490
|
const cmdArgs = [];
|
|
15265
15491
|
if (project) {
|
|
15266
15492
|
cmdArgs.push("--project", project);
|
|
@@ -15278,13 +15504,30 @@ Examples:
|
|
|
15278
15504
|
cwd: projectDir,
|
|
15279
15505
|
timeout: timeoutMs,
|
|
15280
15506
|
reject: false,
|
|
15507
|
+
buffer: false,
|
|
15508
|
+
// Enable streaming
|
|
15281
15509
|
maxBuffer: MAX_OUTPUT_SIZE2
|
|
15282
15510
|
};
|
|
15283
|
-
const
|
|
15511
|
+
const subprocess = execa("npx", ["tsc", ...cmdArgs], options);
|
|
15512
|
+
let stdoutBuffer = "";
|
|
15513
|
+
let stderrBuffer = "";
|
|
15514
|
+
subprocess.stdout?.on("data", (chunk) => {
|
|
15515
|
+
const text = chunk.toString();
|
|
15516
|
+
stdoutBuffer += text;
|
|
15517
|
+
process.stdout.write(text);
|
|
15518
|
+
heartbeat.activity();
|
|
15519
|
+
});
|
|
15520
|
+
subprocess.stderr?.on("data", (chunk) => {
|
|
15521
|
+
const text = chunk.toString();
|
|
15522
|
+
stderrBuffer += text;
|
|
15523
|
+
process.stderr.write(text);
|
|
15524
|
+
heartbeat.activity();
|
|
15525
|
+
});
|
|
15526
|
+
const result = await subprocess;
|
|
15284
15527
|
return {
|
|
15285
15528
|
success: result.exitCode === 0,
|
|
15286
|
-
stdout: truncateOutput2(
|
|
15287
|
-
stderr: truncateOutput2(
|
|
15529
|
+
stdout: truncateOutput2(stdoutBuffer),
|
|
15530
|
+
stderr: truncateOutput2(stderrBuffer),
|
|
15288
15531
|
exitCode: result.exitCode ?? 0,
|
|
15289
15532
|
duration: performance.now() - startTime
|
|
15290
15533
|
};
|
|
@@ -15299,6 +15542,9 @@ Examples:
|
|
|
15299
15542
|
`TypeScript compile failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
15300
15543
|
{ tool: "tsc", cause: error instanceof Error ? error : void 0 }
|
|
15301
15544
|
);
|
|
15545
|
+
} finally {
|
|
15546
|
+
heartbeat.stop();
|
|
15547
|
+
process.stderr.write("\r \r");
|
|
15302
15548
|
}
|
|
15303
15549
|
}
|
|
15304
15550
|
});
|