orchestrating 0.1.6 → 0.1.8
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/orch +46 -29
- package/package.json +1 -1
package/bin/orch
CHANGED
|
@@ -342,7 +342,6 @@ if (adapter) {
|
|
|
342
342
|
|
|
343
343
|
// Spawn a claude process and wire up output handling
|
|
344
344
|
function spawnClaude(claudeArgs) {
|
|
345
|
-
process.stderr.write(`${DIM}[orch] Spawning: ${command} ${claudeArgs.join(" ")}${RESET}\n`);
|
|
346
345
|
const proc = spawn(command, claudeArgs, {
|
|
347
346
|
stdio: ["ignore", "pipe", "pipe"],
|
|
348
347
|
cwd: process.cwd(),
|
|
@@ -350,16 +349,12 @@ if (adapter) {
|
|
|
350
349
|
});
|
|
351
350
|
childRunning = true;
|
|
352
351
|
child = proc;
|
|
353
|
-
process.stderr.write(`${DIM}[orch] Child PID: ${proc.pid}${RESET}\n`);
|
|
354
352
|
|
|
355
353
|
// Parse NDJSON from stdout line-by-line
|
|
356
354
|
const rl = readline.createInterface({ input: proc.stdout });
|
|
357
355
|
let permissionsSent = false;
|
|
358
|
-
let lineCount = 0;
|
|
359
356
|
|
|
360
357
|
rl.on("line", (line) => {
|
|
361
|
-
lineCount++;
|
|
362
|
-
process.stderr.write(`${DIM}[orch] stdout line #${lineCount}: ${line.slice(0, 120)}${RESET}\n`);
|
|
363
358
|
if (!permissionsSent) {
|
|
364
359
|
permissionsSent = true;
|
|
365
360
|
broadcastPermissions();
|
|
@@ -369,41 +364,41 @@ if (adapter) {
|
|
|
369
364
|
try {
|
|
370
365
|
raw = JSON.parse(line);
|
|
371
366
|
} catch {
|
|
372
|
-
process.stderr.write(`${DIM}[orch] JSON parse failed for line${RESET}\n`);
|
|
373
367
|
return;
|
|
374
368
|
}
|
|
375
369
|
|
|
376
370
|
// Normalize and relay each event
|
|
377
371
|
const events = normalizeClaudeEvent(raw);
|
|
378
|
-
process.stderr.write(`${DIM}[orch] Normalized ${events.length} events (type=${raw.type})${RESET}\n`);
|
|
379
372
|
for (const event of events) {
|
|
380
373
|
printLocalEvent(event);
|
|
381
374
|
sendToServer({ type: "agent_event", sessionId, event });
|
|
382
375
|
|
|
383
|
-
// Yolo mode: auto-approve permission denials
|
|
376
|
+
// Yolo mode: auto-approve permission denials — save to settings,
|
|
377
|
+
// claude will pick it up on respawn via pendingPermissionGrant
|
|
384
378
|
if (yoloMode && event.kind === "permission_denied") {
|
|
385
379
|
process.stderr.write(`${GREEN}[yolo] Auto-approving: ${event.toolName}${RESET}\n`);
|
|
386
380
|
approvePermission(event.toolName, "session");
|
|
381
|
+
pendingPermissionGrant = event.toolName;
|
|
387
382
|
}
|
|
388
383
|
}
|
|
389
384
|
});
|
|
390
385
|
|
|
391
|
-
proc.stdout.on("end", () => {
|
|
392
|
-
process.stderr.write(`${DIM}[orch] stdout stream ended (${lineCount} lines total)${RESET}\n`);
|
|
393
|
-
});
|
|
394
|
-
|
|
395
386
|
proc.stderr.on("data", (buf) => {
|
|
396
|
-
process.stderr.write(`${DIM}[orch] child stderr: ${RESET}`);
|
|
397
387
|
process.stderr.write(buf);
|
|
398
388
|
});
|
|
399
389
|
|
|
400
|
-
proc.on("exit", (code
|
|
390
|
+
proc.on("exit", (code) => {
|
|
401
391
|
childRunning = false;
|
|
402
|
-
process.stderr.write(`${DIM}[orch] Child exited: code=${code} signal=${signal}${RESET}\n`);
|
|
403
392
|
const exitCode = code ?? 0;
|
|
404
393
|
if (exitCode !== 0 || exitRequested) {
|
|
405
394
|
sendToServer({ type: "exit", sessionId, exitCode });
|
|
406
395
|
setTimeout(() => process.exit(exitCode), 200);
|
|
396
|
+
} else if (pendingPermissionGrant) {
|
|
397
|
+
// Permission was granted while claude was running — respawn to retry
|
|
398
|
+
const tool = pendingPermissionGrant;
|
|
399
|
+
pendingPermissionGrant = null;
|
|
400
|
+
process.stderr.write(`${GREEN}Retrying with new permission: ${tool}${RESET}\n`);
|
|
401
|
+
respawnWithContinue(`Permission for ${tool} was granted. Please retry your last action.`);
|
|
407
402
|
} else {
|
|
408
403
|
sendToServer({
|
|
409
404
|
type: "agent_event", sessionId,
|
|
@@ -414,7 +409,7 @@ if (adapter) {
|
|
|
414
409
|
|
|
415
410
|
proc.on("error", (err) => {
|
|
416
411
|
childRunning = false;
|
|
417
|
-
|
|
412
|
+
console.error("Failed to start:", err.message);
|
|
418
413
|
process.exit(1);
|
|
419
414
|
});
|
|
420
415
|
|
|
@@ -468,23 +463,37 @@ if (adapter) {
|
|
|
468
463
|
}
|
|
469
464
|
spawnClaude(initialArgs);
|
|
470
465
|
|
|
466
|
+
// Respawn claude with -c to continue after permission grants or follow-up
|
|
467
|
+
function respawnWithContinue(prompt) {
|
|
468
|
+
const args = ["--output-format", "stream-json", "--verbose", "-c"];
|
|
469
|
+
if (prompt) args.push("-p", prompt);
|
|
470
|
+
if (yoloMode) args.push("--dangerously-skip-permissions");
|
|
471
|
+
spawnClaude(args);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Queue of permission grants received while claude is still running
|
|
475
|
+
let pendingPermissionGrant = null;
|
|
476
|
+
|
|
471
477
|
handleServerMessage = (msg) => {
|
|
472
478
|
if (msg.type === "agent_input" && (msg.text || msg.images)) {
|
|
473
479
|
// Follow-up from dashboard — spawn new claude with -c (continue)
|
|
474
480
|
if (childRunning) {
|
|
475
|
-
// Child still running, queue or ignore
|
|
476
481
|
process.stderr.write(`${DIM}[orch] Ignoring input — claude is still running${RESET}\n`);
|
|
477
482
|
return;
|
|
478
483
|
}
|
|
479
|
-
|
|
480
|
-
if (yoloMode) {
|
|
481
|
-
followUpArgs.push("--dangerously-skip-permissions");
|
|
482
|
-
}
|
|
483
|
-
spawnClaude(followUpArgs);
|
|
484
|
+
respawnWithContinue(msg.text || "continue");
|
|
484
485
|
} else if (msg.type === "agent_permission" && msg.tool && msg.action === "allow") {
|
|
485
486
|
const scope = msg.scope || "session";
|
|
486
487
|
approvePermission(msg.tool, scope);
|
|
487
488
|
process.stderr.write(`${GREEN}Permission granted (${scope}): ${msg.tool}${RESET}\n`);
|
|
489
|
+
|
|
490
|
+
if (childRunning) {
|
|
491
|
+
// Claude is still running — remember the grant and respawn when it exits
|
|
492
|
+
pendingPermissionGrant = msg.tool;
|
|
493
|
+
} else {
|
|
494
|
+
// Claude already finished — respawn with -c to retry with new permission
|
|
495
|
+
respawnWithContinue(`Permission for ${msg.tool} was granted. Please retry your last action.`);
|
|
496
|
+
}
|
|
488
497
|
} else if (msg.type === "agent_permission" && msg.tool && msg.action === "revoke") {
|
|
489
498
|
removePermission(msg.tool);
|
|
490
499
|
broadcastPermissions();
|
|
@@ -535,7 +544,18 @@ if (adapter) {
|
|
|
535
544
|
if (process.stdin.isTTY) {
|
|
536
545
|
process.stdin.setRawMode(false);
|
|
537
546
|
}
|
|
538
|
-
|
|
547
|
+
// Wait for WS to connect and flush buffer before exiting
|
|
548
|
+
// (fast commands like `ls` may finish before the WS handshake)
|
|
549
|
+
function tryExit() {
|
|
550
|
+
if (wsReady && sendBuffer.length === 0) {
|
|
551
|
+
setTimeout(() => process.exit(exitCode), 100);
|
|
552
|
+
} else {
|
|
553
|
+
setTimeout(tryExit, 50);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
// Give up after 3 seconds regardless
|
|
557
|
+
setTimeout(() => process.exit(exitCode), 3000);
|
|
558
|
+
tryExit();
|
|
539
559
|
});
|
|
540
560
|
|
|
541
561
|
child.on("error", (err) => {
|
|
@@ -770,8 +790,6 @@ function connectWs() {
|
|
|
770
790
|
ws = new WebSocket(serverUrl);
|
|
771
791
|
|
|
772
792
|
ws.on("open", () => {
|
|
773
|
-
process.stderr.write(`${DIM}[orch] WS connected to ${serverUrl}${RESET}\n`);
|
|
774
|
-
process.stderr.write(`${DIM}[orch] Token: ${authToken ? authToken.slice(0, 20) + "..." : "(none)"}${RESET}\n`);
|
|
775
793
|
ws.send(JSON.stringify({
|
|
776
794
|
type: "register",
|
|
777
795
|
token: authToken,
|
|
@@ -816,8 +834,7 @@ function connectWs() {
|
|
|
816
834
|
} catch {}
|
|
817
835
|
});
|
|
818
836
|
|
|
819
|
-
ws.on("close", (
|
|
820
|
-
process.stderr.write(`${DIM}[orch] WS closed: code=${code} reason=${reason}${RESET}\n`);
|
|
837
|
+
ws.on("close", () => {
|
|
821
838
|
wsReady = false;
|
|
822
839
|
ws = null;
|
|
823
840
|
if (!authFailed) {
|
|
@@ -825,8 +842,8 @@ function connectWs() {
|
|
|
825
842
|
}
|
|
826
843
|
});
|
|
827
844
|
|
|
828
|
-
ws.on("error", (
|
|
829
|
-
|
|
845
|
+
ws.on("error", () => {
|
|
846
|
+
// Will trigger close
|
|
830
847
|
});
|
|
831
848
|
}
|
|
832
849
|
|