orchestrating 0.1.30 → 0.1.32
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 +42 -0
- package/package.json +1 -1
package/bin/orch
CHANGED
|
@@ -249,6 +249,7 @@ async function handleDaemon(projectsDir) {
|
|
|
249
249
|
|
|
250
250
|
let reconnecting = false;
|
|
251
251
|
const recentRequests = new Set();
|
|
252
|
+
const recentSpawns = new Map(); // "command:cwd" -> timestamp
|
|
252
253
|
|
|
253
254
|
function scheduleReconnect(delaySec) {
|
|
254
255
|
if (reconnecting) return;
|
|
@@ -336,6 +337,15 @@ async function handleDaemon(projectsDir) {
|
|
|
336
337
|
recentRequests.add(requestId);
|
|
337
338
|
setTimeout(() => recentRequests.delete(requestId), 30_000);
|
|
338
339
|
|
|
340
|
+
// Dedup: prevent spawning same command in same directory within 10s
|
|
341
|
+
const spawnKey = `${cmd}:${(cmdArgs || []).join(",")}:${cwd || ""}`;
|
|
342
|
+
const lastSpawn = recentSpawns.get(spawnKey);
|
|
343
|
+
if (lastSpawn && Date.now() - lastSpawn < 10_000) {
|
|
344
|
+
process.stderr.write(`${DIM}${PREFIX} Ignoring duplicate spawn: ${spawnKey}${RESET}\n`);
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
recentSpawns.set(spawnKey, Date.now());
|
|
348
|
+
|
|
339
349
|
const cmdStr = [cmd, ...cmdArgs].join(" ");
|
|
340
350
|
process.stderr.write(`${GREEN}${PREFIX} Spawning: ${cmdStr}${RESET}\n`);
|
|
341
351
|
|
|
@@ -372,6 +382,38 @@ async function handleDaemon(projectsDir) {
|
|
|
372
382
|
}
|
|
373
383
|
}
|
|
374
384
|
}
|
|
385
|
+
|
|
386
|
+
if (msg.type === "browse_directory") {
|
|
387
|
+
const { requestId: browseReqId, path: dirPath } = msg;
|
|
388
|
+
try {
|
|
389
|
+
const entries = readdirSync(dirPath)
|
|
390
|
+
.filter((e) => !e.startsWith("."))
|
|
391
|
+
.map((e) => {
|
|
392
|
+
const full = path.join(dirPath, e);
|
|
393
|
+
try { return statSync(full).isDirectory() ? full : null; } catch { return null; }
|
|
394
|
+
})
|
|
395
|
+
.filter(Boolean)
|
|
396
|
+
.sort();
|
|
397
|
+
if (sock.readyState === WebSocket.OPEN) {
|
|
398
|
+
sock.send(JSON.stringify({
|
|
399
|
+
type: "directory_listing",
|
|
400
|
+
requestId: browseReqId,
|
|
401
|
+
path: dirPath,
|
|
402
|
+
directories: entries,
|
|
403
|
+
}));
|
|
404
|
+
}
|
|
405
|
+
} catch (err) {
|
|
406
|
+
if (sock.readyState === WebSocket.OPEN) {
|
|
407
|
+
sock.send(JSON.stringify({
|
|
408
|
+
type: "directory_listing",
|
|
409
|
+
requestId: browseReqId,
|
|
410
|
+
path: dirPath,
|
|
411
|
+
directories: [],
|
|
412
|
+
error: err.message,
|
|
413
|
+
}));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
375
417
|
});
|
|
376
418
|
|
|
377
419
|
sock.on("close", () => {
|