@ctrl-spc/cli 1.3.0 → 1.3.1
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/dispatch.js +44 -16
- package/package.json +1 -1
package/dist/dispatch.js
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
+
import { mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
2
5
|
import { resolveAgentCommand } from './agents.js';
|
|
3
6
|
function shellQuote(value) {
|
|
4
7
|
return `'${value.replaceAll("'", "'\\''")}'`;
|
|
5
8
|
}
|
|
6
|
-
function
|
|
7
|
-
|
|
9
|
+
export function agentTerminalScript(request, executable) {
|
|
10
|
+
const command = agentTerminalCommand(request, executable);
|
|
11
|
+
return [
|
|
12
|
+
'#!/bin/zsh',
|
|
13
|
+
'script_path="$0"',
|
|
14
|
+
'/bin/rm -f -- "$script_path"',
|
|
15
|
+
'/bin/rmdir -- "${script_path%/*}" 2>/dev/null || true',
|
|
16
|
+
`exec /bin/zsh -lc ${shellQuote(command)}`,
|
|
17
|
+
'',
|
|
18
|
+
].join('\n');
|
|
8
19
|
}
|
|
9
20
|
export function agentTerminalCommand(request, executable) {
|
|
10
21
|
const prompt = shellQuote(request.prompt);
|
|
@@ -25,22 +36,39 @@ export async function launchAgentDispatch(request) {
|
|
|
25
36
|
const executable = resolveAgentCommand(request.agent_kind);
|
|
26
37
|
if (!executable)
|
|
27
38
|
throw new Error(`${request.agent_kind} is not installed on this machine.`);
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
const directory = await mkdtemp(join(tmpdir(), 'ctrl-spc-dispatch-'));
|
|
40
|
+
const scriptPath = join(directory, `ctrl-spc-${request.id}.command`);
|
|
41
|
+
try {
|
|
42
|
+
await writeFile(scriptPath, agentTerminalScript(request, executable), {
|
|
43
|
+
encoding: 'utf8',
|
|
44
|
+
flag: 'wx',
|
|
45
|
+
mode: 0o700,
|
|
33
46
|
});
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
await new Promise((resolve, reject) => {
|
|
48
|
+
const child = spawn('/usr/bin/open', ['-a', 'Terminal', scriptPath], {
|
|
49
|
+
stdio: ['ignore', 'ignore', 'pipe'],
|
|
50
|
+
});
|
|
51
|
+
let stderr = '';
|
|
52
|
+
child.stderr.on('data', (chunk) => { stderr += String(chunk); });
|
|
53
|
+
child.once('error', reject);
|
|
54
|
+
child.once('exit', (code) => {
|
|
55
|
+
if (code === 0)
|
|
56
|
+
resolve();
|
|
57
|
+
else
|
|
58
|
+
reject(new Error(stderr.trim() || `Terminal launch exited with code ${code ?? 'unknown'}.`));
|
|
59
|
+
});
|
|
42
60
|
});
|
|
43
|
-
}
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
await rm(directory, { recursive: true, force: true }).catch(() => { });
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
// The script removes itself after Terminal opens it. This fallback handles
|
|
67
|
+
// cases where Terminal accepts the file but never executes it.
|
|
68
|
+
const cleanup = setTimeout(() => {
|
|
69
|
+
void rm(directory, { recursive: true, force: true });
|
|
70
|
+
}, 60_000);
|
|
71
|
+
cleanup.unref();
|
|
44
72
|
}
|
|
45
73
|
export function createAgentDispatchController(client, machineId, agents, deps = {}) {
|
|
46
74
|
const claim = deps.claim ?? (async () => {
|