@testchimp/cli 0.1.46 → 0.1.47
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/chimphands/run.js +84 -16
- package/package.json +1 -1
package/dist/chimphands/run.js
CHANGED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* Relies on TESTCHIMP_API_KEY (+ optional TESTCHIMP_BACKEND_URL; defaults to prod).
|
|
4
4
|
* Does not write mcp.json — TestChimp MCP is wired via opencode.json for OpenCode.
|
|
5
5
|
*/
|
|
6
|
-
import { spawn } from "node:child_process";
|
|
7
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
6
|
+
import { execSync, spawn } from "node:child_process";
|
|
7
|
+
import { mkdirSync, openSync, writeFileSync } from "node:fs";
|
|
8
8
|
import http from "node:http";
|
|
9
9
|
import https from "node:https";
|
|
10
10
|
import { URL } from "node:url";
|
|
@@ -372,7 +372,16 @@ function writeOpencodeConfig(backend, apiKey, boot) {
|
|
|
372
372
|
return model;
|
|
373
373
|
}
|
|
374
374
|
function buildOpencodeArgs(prompt, model, opencodeSessionId, attachUrl) {
|
|
375
|
-
const args = [
|
|
375
|
+
const args = [
|
|
376
|
+
"run",
|
|
377
|
+
prompt,
|
|
378
|
+
"--model",
|
|
379
|
+
model,
|
|
380
|
+
"--format",
|
|
381
|
+
"json",
|
|
382
|
+
"--agent",
|
|
383
|
+
OPENCODE_AGENT_ID,
|
|
384
|
+
];
|
|
376
385
|
if (opencodeSessionId?.trim()) {
|
|
377
386
|
args.push("--session", opencodeSessionId.trim());
|
|
378
387
|
}
|
|
@@ -381,6 +390,74 @@ function buildOpencodeArgs(prompt, model, opencodeSessionId, attachUrl) {
|
|
|
381
390
|
}
|
|
382
391
|
return args;
|
|
383
392
|
}
|
|
393
|
+
function killListenersOnPort(port) {
|
|
394
|
+
try {
|
|
395
|
+
const out = execSync(`lsof -tiTCP:${port} -sTCP:LISTEN`, {
|
|
396
|
+
encoding: "utf8",
|
|
397
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
398
|
+
}).trim();
|
|
399
|
+
for (const pid of out.split(/\s+/).filter(Boolean)) {
|
|
400
|
+
const n = Number(pid);
|
|
401
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
402
|
+
continue;
|
|
403
|
+
try {
|
|
404
|
+
process.kill(n, "SIGTERM");
|
|
405
|
+
}
|
|
406
|
+
catch {
|
|
407
|
+
/* already gone */
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
catch {
|
|
412
|
+
/* nothing listening */
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
async function waitForOpencodeHttp(attachUrl, timeoutMs) {
|
|
416
|
+
const base = attachUrl.replace(/\/$/, "");
|
|
417
|
+
const deadline = Date.now() + timeoutMs;
|
|
418
|
+
while (Date.now() < deadline) {
|
|
419
|
+
for (const path of ["/global/health", "/"]) {
|
|
420
|
+
try {
|
|
421
|
+
const res = await fetch(`${base}${path}`);
|
|
422
|
+
if (res.ok || res.status === 401 || res.status === 404)
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
/* retry */
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
await sleep(400);
|
|
430
|
+
}
|
|
431
|
+
throw new Error(`OpenCode server not ready at ${attachUrl} within ${timeoutMs}ms`);
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Restart local `opencode serve` after writing opencode.json so the server loads
|
|
435
|
+
* TestChimp provider + default_agent. Workflow may have started serve earlier without config.
|
|
436
|
+
*/
|
|
437
|
+
async function restartLocalOpencodeServer(attachUrl) {
|
|
438
|
+
const u = new URL(attachUrl);
|
|
439
|
+
const hostname = u.hostname || "127.0.0.1";
|
|
440
|
+
const port = u.port || (u.protocol === "https:" ? "443" : "80");
|
|
441
|
+
killListenersOnPort(port);
|
|
442
|
+
await sleep(300);
|
|
443
|
+
const logFd = openSync("opencode-server.log", "a");
|
|
444
|
+
const child = spawn("opencode", ["serve", "--port", port, "--hostname", hostname], {
|
|
445
|
+
detached: true,
|
|
446
|
+
stdio: ["ignore", logFd, logFd],
|
|
447
|
+
env: process.env,
|
|
448
|
+
});
|
|
449
|
+
child.unref();
|
|
450
|
+
if (child.pid) {
|
|
451
|
+
try {
|
|
452
|
+
writeFileSync("/tmp/opencode-server.pid", String(child.pid));
|
|
453
|
+
}
|
|
454
|
+
catch {
|
|
455
|
+
/* best effort */
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
console.error(`ChimpHands restarted OpenCode serve on ${hostname}:${port} (pid ${child.pid ?? "?"})`);
|
|
459
|
+
await waitForOpencodeHttp(attachUrl, 60_000);
|
|
460
|
+
}
|
|
384
461
|
function runOpencode(prompt, model, childEnv, opencodeSessionId, callbacks, attachUrl) {
|
|
385
462
|
let activeSessionId = opencodeSessionId?.trim() || undefined;
|
|
386
463
|
const baseArgs = buildOpencodeArgs(prompt, model, activeSessionId, attachUrl);
|
|
@@ -649,6 +726,9 @@ export async function runChimphands(opts) {
|
|
|
649
726
|
console.error(`ChimpHands OpenCode model: ${opencodeModel}`);
|
|
650
727
|
if (attachUrl) {
|
|
651
728
|
console.error(`ChimpHands OpenCode attach: ${attachUrl}`);
|
|
729
|
+
// Serve must load opencode.json (provider + default_agent). Workflow often starts
|
|
730
|
+
// serve before this file exists; restart so attach mode can omit --agent safely.
|
|
731
|
+
await restartLocalOpencodeServer(attachUrl);
|
|
652
732
|
}
|
|
653
733
|
let opencodeSessionId = bootStr(boot, "opencode_session_id", "opencodeSessionId") || undefined;
|
|
654
734
|
const conversationSummary = bootStr(boot, "conversation_summary", "conversationSummary");
|
|
@@ -1213,18 +1293,6 @@ export async function serveChimphands(opts) {
|
|
|
1213
1293
|
if (!attachUrl) {
|
|
1214
1294
|
throw new Error("--attach URL is required for chimphands serve");
|
|
1215
1295
|
}
|
|
1216
|
-
//
|
|
1217
|
-
const deadline = Date.now() + 60_000;
|
|
1218
|
-
while (Date.now() < deadline) {
|
|
1219
|
-
try {
|
|
1220
|
-
const res = await fetch(attachUrl.replace(/\/$/, "") + "/");
|
|
1221
|
-
if (res.ok || res.status === 401 || res.status === 404)
|
|
1222
|
-
break;
|
|
1223
|
-
}
|
|
1224
|
-
catch {
|
|
1225
|
-
/* retry */
|
|
1226
|
-
}
|
|
1227
|
-
await sleep(500);
|
|
1228
|
-
}
|
|
1296
|
+
// Server is (re)started inside runChimphands after opencode.json is written.
|
|
1229
1297
|
await runChimphands({ ...opts, attachUrl });
|
|
1230
1298
|
}
|
package/package.json
CHANGED