orchestrating 0.1.18 → 0.1.20

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.
Files changed (2) hide show
  1. package/bin/orch +35 -1
  2. package/package.json +1 -1
package/bin/orch CHANGED
@@ -249,7 +249,7 @@ if (commandArgs.length === 0) {
249
249
  const command = commandArgs[0];
250
250
  const spawnArgs = commandArgs.slice(1);
251
251
  let sessionId;
252
- const hostname = os.hostname();
252
+ const hostname = os.hostname().replace(/\.(lan|local|home|internal)$/i, "");
253
253
  const serverUrl = process.env.ORC_URL || process.env.CAST_URL || "wss://api.orchestrat.ing/ws";
254
254
  let authToken = getAuthToken();
255
255
  const cwdFolder = path.basename(process.cwd());
@@ -273,9 +273,13 @@ if (!authToken && !serverUrl.includes("localhost") && !serverUrl.includes("127.0
273
273
 
274
274
  // --- WebSocket connection with reconnect ---
275
275
  const BUFFER_MAX = 50 * 1024; // 50KB reconnect buffer
276
+ const PING_INTERVAL_MS = 30_000; // 30s keepalive ping
277
+ const PONG_TIMEOUT_MS = 10_000; // 10s to receive pong before assuming dead
276
278
  let ws = null;
277
279
  let wsReady = false;
278
280
  let reconnectTimer = null;
281
+ let pingTimer = null;
282
+ let pongTimer = null;
279
283
  let authFailed = false;
280
284
  const sendBuffer = [];
281
285
  let bufferSize = 0;
@@ -575,6 +579,15 @@ if (adapter) {
575
579
  // Claude already finished — respawn with -c to retry with new permission
576
580
  respawnWithContinue(`Permission for ${msg.tool} was granted. Please retry your last action.`);
577
581
  }
582
+ } else if (msg.type === "agent_permission" && msg.tool && msg.action === "deny") {
583
+ process.stderr.write(`${RED}Permission denied: ${msg.tool}${RESET}\n`);
584
+
585
+ if (childRunning) {
586
+ // Claude is still running — remember and respawn when it exits
587
+ pendingPermissionGrant = null;
588
+ } else {
589
+ respawnWithContinue(`Permission for ${msg.tool} was denied by the user. Do not retry this tool — find an alternative approach or skip this step.`);
590
+ }
578
591
  } else if (msg.type === "agent_permission" && msg.tool && msg.action === "revoke") {
579
592
  removePermission(msg.tool);
580
593
  broadcastPermissions();
@@ -920,6 +933,23 @@ async function connectWs() {
920
933
  if (adapter) {
921
934
  broadcastPermissions();
922
935
  }
936
+
937
+ // Keepalive: send WebSocket ping frames every 30s to prevent idle disconnects
938
+ if (pingTimer) clearInterval(pingTimer);
939
+ if (pongTimer) clearTimeout(pongTimer);
940
+ pingTimer = setInterval(() => {
941
+ if (ws && ws.readyState === WebSocket.OPEN) {
942
+ ws.ping();
943
+ pongTimer = setTimeout(() => {
944
+ // No pong received — connection is dead, force reconnect
945
+ if (ws) ws.terminate();
946
+ }, PONG_TIMEOUT_MS);
947
+ }
948
+ }, PING_INTERVAL_MS);
949
+ });
950
+
951
+ ws.on("pong", () => {
952
+ if (pongTimer) { clearTimeout(pongTimer); pongTimer = null; }
923
953
  });
924
954
 
925
955
  ws.on("message", (raw) => {
@@ -950,6 +980,8 @@ async function connectWs() {
950
980
  ws.on("close", () => {
951
981
  wsReady = false;
952
982
  ws = null;
983
+ if (pingTimer) { clearInterval(pingTimer); pingTimer = null; }
984
+ if (pongTimer) { clearTimeout(pongTimer); pongTimer = null; }
953
985
  if (!authFailed) {
954
986
  reconnectTimer = setTimeout(connectWs, 2000);
955
987
  }
@@ -986,6 +1018,8 @@ function revokeSessionPermissions() {
986
1018
 
987
1019
  function cleanup() {
988
1020
  revokeSessionPermissions();
1021
+ if (pingTimer) clearInterval(pingTimer);
1022
+ if (pongTimer) clearTimeout(pongTimer);
989
1023
  if (reconnectTimer) clearTimeout(reconnectTimer);
990
1024
  if (ws) ws.close();
991
1025
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orchestrating",
3
- "version": "0.1.18",
3
+ "version": "0.1.20",
4
4
  "description": "Stream terminal sessions to the orchestrat.ing dashboard",
5
5
  "type": "module",
6
6
  "bin": {