@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.
Files changed (2) hide show
  1. package/dist/dispatch.js +44 -16
  2. 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 appleScriptString(value) {
7
- return `"${value.replaceAll('\\', '\\\\').replaceAll('"', '\\"')}"`;
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 command = agentTerminalCommand(request, executable);
29
- const script = `tell application "Terminal" to activate\ntell application "Terminal" to do script ${appleScriptString(command)}`;
30
- await new Promise((resolve, reject) => {
31
- const child = spawn('/usr/bin/osascript', ['-e', script], {
32
- stdio: ['ignore', 'ignore', 'pipe'],
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
- let stderr = '';
35
- child.stderr.on('data', (chunk) => { stderr += String(chunk); });
36
- child.once('error', reject);
37
- child.once('exit', (code) => {
38
- if (code === 0)
39
- resolve();
40
- else
41
- reject(new Error(stderr.trim() || `Terminal launch exited with code ${code ?? 'unknown'}.`));
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 () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ctrl-spc/cli",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "CTRL+SPC CLI — per-machine agent for browser login, project linking, presence, and the local MCP server.",
5
5
  "engines": {
6
6
  "node": ">=22"