@cotal-ai/manager 0.8.3 → 0.9.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.
@@ -1,7 +1,20 @@
1
+ /**
2
+ * The detach key — Ctrl-] (0x1d) by default, as in telnet/ssh escape conventions. `COTAL_DETACH_KEY`
3
+ * rebinds it to another control key when Ctrl-] clashes with a keybinding inside the agent's TUI;
4
+ * accepts `ctrl-<char>` or `^<char>` (e.g. `ctrl-b`, `^_`). Read at point of use, per the repo's
5
+ * `COTAL_*` convention. An unparseable value — including a set-but-empty or whitespace-only one —
6
+ * throws (named), never silently falling back; the caller turns that into a loud exit. Only an
7
+ * unset var = the Ctrl-] default.
8
+ */
9
+ export declare function detachKey(): {
10
+ byte: number;
11
+ label: string;
12
+ overridden: boolean;
13
+ };
1
14
  /**
2
15
  * Drive a manager's attach endpoint from the terminal: raw-mode stdin streams to
3
16
  * the PTY, PTY output streams to stdout, and SIGWINCH-style resizes are forwarded.
4
- * Ctrl-] detaches without killing the agent.
17
+ * The detach key (Ctrl-] by default, {@link detachKey}) detaches without killing the agent.
5
18
  */
6
19
  export declare function attachClient(url: string): Promise<void>;
7
20
  //# sourceMappingURL=attach-client.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"attach-client.d.ts","sourceRoot":"","sources":["../src/attach-client.ts"],"names":[],"mappings":"AAsBA;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA+CvD"}
1
+ {"version":3,"file":"attach-client.d.ts","sourceRoot":"","sources":["../src/attach-client.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,wBAAgB,SAAS,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,CAYhF;AAwDD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAmIvD"}
@@ -1,27 +1,91 @@
1
1
  import WebSocket from "ws";
2
- /** Detach key Ctrl-] (0x1d), as in telnet/ssh escape conventions. */
3
- const DETACH = 0x1d;
2
+ import { c } from "./ui.js";
4
3
  /**
5
- * Terminal modes a full-screen child (e.g. Claude's TUI) commonly turns on but that we must undo
6
- * locally on detach/exit: the agent keeps running after Ctrl-], so it never restores OUR terminal.
7
- * Without this, detaching from a mouse-tracking TUI leaves the terminal reporting every cursor move
8
- * as input (a stream of `ESC[<…M` escape codes), or its focus in/out as `ESC[I`/`ESC[O`. Disables
9
- * all mouse-report modes + focus reporting + bracketed paste, resets the keypad/cursor-key modes,
10
- * shows the cursor, and resets attributes. Deliberately does NOT toggle the alternate screen.
4
+ * The detach key — Ctrl-] (0x1d) by default, as in telnet/ssh escape conventions. `COTAL_DETACH_KEY`
5
+ * rebinds it to another control key when Ctrl-] clashes with a keybinding inside the agent's TUI;
6
+ * accepts `ctrl-<char>` or `^<char>` (e.g. `ctrl-b`, `^_`). Read at point of use, per the repo's
7
+ * `COTAL_*` convention. An unparseable value including a set-but-empty or whitespace-only one
8
+ * throws (named), never silently falling back; the caller turns that into a loud exit. Only an
9
+ * unset var = the Ctrl-] default.
11
10
  */
12
- const RESTORE = "\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1005l\x1b[?1006l\x1b[?1015l" + // mouse tracking off
11
+ export function detachKey() {
12
+ const spec = process.env.COTAL_DETACH_KEY;
13
+ if (spec === undefined)
14
+ return { byte: 0x1d, label: "Ctrl-]", overridden: false };
15
+ const m = /^(?:ctrl-|\^)([a-z@[\\\]^_])$/i.exec(spec.trim());
16
+ if (!m) {
17
+ throw new Error(`invalid COTAL_DETACH_KEY "${spec}" — expected ctrl-<char> or ^<char> for a control key ` +
18
+ `(a-z, or one of @ [ \\ ] ^ _), e.g. ctrl-b`);
19
+ }
20
+ const ch = m[1].toUpperCase();
21
+ return { byte: ch.charCodeAt(0) & 0x1f, label: `Ctrl-${ch}`, overridden: true };
22
+ }
23
+ /**
24
+ * Terminal modes a full-screen child (a fullscreen TUI: OpenCode, or Claude under `/tui fullscreen`)
25
+ * commonly turns on but that we must undo locally on detach/exit: the agent keeps running after
26
+ * Ctrl-], so it never restores OUR terminal. Without this, detaching from a mouse-tracking TUI leaves
27
+ * the terminal reporting every cursor move as input (a stream of `ESC[<…M` escape codes), or its
28
+ * focus in/out as `ESC[I`/`ESC[O`. Disables all mouse-report modes + focus reporting + bracketed
29
+ * paste, resets the keypad/cursor-key modes, shows the cursor, and resets attributes. Leaving the
30
+ * alternate screen is handled separately (ALT_LEAVE_SEQ), only when we actually entered it — see
31
+ * cleanup().
32
+ */
33
+ const MOUSE_OFF = "\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1005l\x1b[?1006l\x1b[?1015l"; // all mouse tracking off
34
+ const RESTORE = MOUSE_OFF +
13
35
  "\x1b[?1004l" + // focus reporting off
14
36
  "\x1b[?2004l" + // bracketed paste off
15
37
  "\x1b[?1l" + // application cursor keys off (DECCKM): a full-screen TUI enables it; left on, arrows emit ESC O A not ESC [ A
16
38
  "\x1b>" + // keypad → numeric (DECKPNM)
17
39
  "\x1b[?25h" + // show cursor
18
40
  "\x1b[0m"; // reset attributes
41
+ // Leave the alternate screen on detach, but ONLY if the child put us there (altScreen). The attach
42
+ // snapshot faithfully re-enters the child's alt-screen (`?1049h`) on our terminal; without a matching
43
+ // leave we strand it in the alt buffer, which has no scrollback and — with xterm alt-scroll — turns
44
+ // the wheel into ↑/↓ that walk shell history. Leaving the alt buffer IS the whole fix: alt-scroll
45
+ // (`?1007`) only acts inside the alt buffer, so `?1049l` alone makes it inert. We deliberately don't
46
+ // send `?1007l` — nothing on this path ever enabled it (unlike console.ts, which sets `?1007h` on
47
+ // entry), so disabling it would clobber the operator's own alternate-scroll preference for later apps.
48
+ const ALT_LEAVE_SEQ = "\x1b[?1049l"; // leave alt-screen — alt-scroll is inert once back in the main buffer
49
+ // Wheel-scroll for full-screen children. A fullscreen TUI (OpenCode, or Claude under `/tui
50
+ // fullscreen`) runs in the alternate screen — where the terminal's native scrollback is dead — and
51
+ // scrolls its content itself off mouse reports. But it enables that mouse capture on ITS pty, and the
52
+ // enable doesn't reliably survive the attach hop (backlog eviction / nested pty), so our terminal
53
+ // never reports the wheel and scrolling dies. So while the child is in the alternate screen we enable
54
+ // SGR mouse reporting on OUR terminal and translate each wheel tick into PageUp/PageDown — the
55
+ // keystrokes a fullscreen TUI treats as "scroll the view" (OpenCode: `messages_page_up`/`_down`;
56
+ // Claude's fullscreen binds PageUp/PageDown too). A child in the normal screen (inline Claude) keeps
57
+ // altScreen=false, so this stays off and its native terminal-scrollback wheel is untouched.
58
+ const MOUSE_ON = "\x1b[?1002h\x1b[?1006h"; // button+drag tracking, SGR encoding
59
+ const PAGE_UP = "\x1b[5~";
60
+ const PAGE_DOWN = "\x1b[6~";
61
+ // Enter/leave the alternate screen: xterm `?1049`, plus the older `?1047`/`?47`.
62
+ const ALT_ENTER = /\x1b\[\?(?:1049|1047|47)h/g;
63
+ const ALT_LEAVE = /\x1b\[\?(?:1049|1047|47)l/g;
64
+ // A complete SGR mouse report: `ESC [ < btn ; col ; row (M|m)`.
65
+ const SGR_MOUSE = /^\x1b\[<(\d+);\d+;\d+[Mm]/;
66
+ const lastIndexOfRe = (re, s) => {
67
+ re.lastIndex = 0;
68
+ let last = -1;
69
+ for (let m = re.exec(s); m; m = re.exec(s))
70
+ last = m.index;
71
+ return last;
72
+ };
19
73
  /**
20
74
  * Drive a manager's attach endpoint from the terminal: raw-mode stdin streams to
21
75
  * the PTY, PTY output streams to stdout, and SIGWINCH-style resizes are forwarded.
22
- * Ctrl-] detaches without killing the agent.
76
+ * The detach key (Ctrl-] by default, {@link detachKey}) detaches without killing the agent.
23
77
  */
24
78
  export function attachClient(url) {
79
+ // Resolve the detach key before connecting so a bad COTAL_DETACH_KEY fails loudly up front
80
+ // (matching the manager's other fail-fast exits) instead of after an attach we'd only tear down.
81
+ let detach;
82
+ try {
83
+ detach = detachKey();
84
+ }
85
+ catch (e) {
86
+ console.error(c.red(`✗ ${e.message}`));
87
+ process.exit(1);
88
+ }
25
89
  return new Promise((resolve, reject) => {
26
90
  const ws = new WebSocket(url);
27
91
  const stdin = process.stdin;
@@ -31,25 +95,105 @@ export function attachClient(url) {
31
95
  // PTY write or the on-detach restore write. Register a no-op listener once here (not in cleanup,
32
96
  // so it outlives the async error tick) to turn it into a handled no-op.
33
97
  process.stdout.on("error", () => { });
98
+ // Wheel-scroll state (see MOUSE_ON above): whether the child is in the alternate screen, and a
99
+ // buffer for an SGR mouse report split across stdin reads.
100
+ let altScreen = false;
101
+ let mouseBuf = "";
102
+ // Carry the tail of the previous output frame so an alt-screen escape split across ws frames
103
+ // (e.g. `ESC[?10` then `49h`) is still detected; 16 bytes covers these private-mode sequences.
104
+ // Acting only on state *change* below makes re-scanning the carried bytes idempotent.
105
+ let scanTail = "";
106
+ // Track the child's alt-screen transitions in its output so we can arm/disarm wheel translation.
107
+ const trackAltScreen = (data) => {
108
+ const s = scanTail + data.toString("latin1");
109
+ scanTail = s.slice(-16);
110
+ const enter = lastIndexOfRe(ALT_ENTER, s);
111
+ const leave = lastIndexOfRe(ALT_LEAVE, s);
112
+ if (enter === -1 && leave === -1)
113
+ return;
114
+ const nowAlt = enter > leave;
115
+ if (nowAlt === altScreen)
116
+ return;
117
+ altScreen = nowAlt;
118
+ if (altScreen) {
119
+ if (process.stdout.isTTY)
120
+ process.stdout.write(MOUSE_ON);
121
+ }
122
+ else {
123
+ // Leaving alt-screen mid-session: undo the mouse modes WE enabled so the terminal stops
124
+ // reporting the wheel/clicks and native scrollback works again — don't wait for detach.
125
+ mouseBuf = "";
126
+ if (process.stdout.isTTY)
127
+ process.stdout.write(MOUSE_OFF);
128
+ }
129
+ };
34
130
  const sendResize = () => ws.send(`r:${process.stdout.columns ?? 80},${process.stdout.rows ?? 24}`);
35
131
  const onInput = (d) => {
36
- if (d.length === 1 && d[0] === DETACH) {
132
+ if (d.length === 1 && d[0] === detach.byte) {
37
133
  ws.close();
38
134
  return;
39
135
  }
40
- ws.send(d);
136
+ // Inline child: forward keystrokes raw (its wheel scrolls the local terminal, not the app).
137
+ if (!altScreen) {
138
+ ws.send(d);
139
+ return;
140
+ }
141
+ // Full-screen child: rewrite wheel reports to PageUp/PageDown, pass everything else through.
142
+ mouseBuf += d.toString("latin1");
143
+ let out = "";
144
+ for (;;) {
145
+ const i = mouseBuf.indexOf("\x1b[<");
146
+ if (i === -1) {
147
+ // A report split right before `<` (`ESC[` now, `<…M` next) would slip through untranslated:
148
+ // hold a trailing `ESC[` for the next read. Never hold a bare trailing `ESC` — that's the
149
+ // Escape key and must forward at once (e.g. OpenCode's interrupt); the rarer `ESC`|`[<…`
150
+ // split stays raw by design.
151
+ const keep = mouseBuf.endsWith("\x1b[") ? 2 : 0;
152
+ out += mouseBuf.slice(0, mouseBuf.length - keep);
153
+ mouseBuf = mouseBuf.slice(mouseBuf.length - keep);
154
+ break;
155
+ }
156
+ out += mouseBuf.slice(0, i);
157
+ const rest = mouseBuf.slice(i);
158
+ const m = SGR_MOUSE.exec(rest);
159
+ if (!m) {
160
+ // Hold only a still-valid partial report (`ESC[<` + digits/semicolons) for the next read;
161
+ // anything else can't become an SGR mouse report, so pass it straight through.
162
+ if (/^\x1b\[<[\d;]*$/.test(rest))
163
+ mouseBuf = rest;
164
+ else {
165
+ out += rest;
166
+ mouseBuf = "";
167
+ }
168
+ break;
169
+ }
170
+ const btn = Number(m[1]);
171
+ if (btn & 0x40)
172
+ out += btn & 1 ? PAGE_DOWN : PAGE_UP; // wheel: 64=up, 65=down
173
+ else
174
+ out += m[0]; // other mouse (click/drag): forward raw so the TUI still gets it
175
+ mouseBuf = rest.slice(m[0].length);
176
+ }
177
+ if (out)
178
+ ws.send(Buffer.from(out, "latin1"));
41
179
  };
42
180
  const cleanup = () => {
43
181
  stdin.off("data", onInput);
44
182
  process.stdout.off("resize", sendResize);
45
183
  // Undo terminal modes the (still-running) agent's TUI enabled — it won't restore us on detach.
184
+ // If the child put us in its alternate screen (altScreen), leave it too so the terminal isn't
185
+ // stranded in the alt buffer; an inline child (altScreen=false) keeps its scrollback.
46
186
  if (process.stdout.isTTY)
47
- process.stdout.write(RESTORE);
187
+ process.stdout.write(RESTORE + (altScreen ? ALT_LEAVE_SEQ : ""));
48
188
  if (stdin.isTTY)
49
189
  stdin.setRawMode(wasRaw);
50
190
  stdin.pause();
51
191
  };
52
192
  ws.on("open", () => {
193
+ // Make an override visible (the CLI's "attached to X — Ctrl-] to detach" hint still prints the
194
+ // default label). Only on override, so the default case stays free of duplicate noise.
195
+ if (detach.overridden)
196
+ console.error(c.dim(`detach key: ${detach.label} (via COTAL_DETACH_KEY)`));
53
197
  if (stdin.isTTY)
54
198
  stdin.setRawMode(true);
55
199
  stdin.resume();
@@ -57,7 +201,10 @@ export function attachClient(url) {
57
201
  process.stdout.on("resize", sendResize);
58
202
  stdin.on("data", onInput);
59
203
  });
60
- ws.on("message", (data) => process.stdout.write(data));
204
+ ws.on("message", (data) => {
205
+ trackAltScreen(data);
206
+ process.stdout.write(data);
207
+ });
61
208
  ws.on("close", () => {
62
209
  cleanup();
63
210
  resolve();
@@ -1 +1 @@
1
- {"version":3,"file":"attach-client.js","sourceRoot":"","sources":["../src/attach-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"attach-client.js","sourceRoot":"","sources":["../src/attach-client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"attach-endpoint.d.ts","sourceRoot":"","sources":["../src/attach-endpoint.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAmBtD,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,cAAc;;IAQvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,2FAA2F;IAC3F,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAHR,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,EACjD,IAAI,EAAE,MAAM,OAAO;IACpC,2FAA2F;IAC1E,QAAQ,EAAE,MAAM,SAAS,EAAE,EAC5C,IAAI,SAAI;IAsBJ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,2DAA2D;IAC3D,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAI3C,oDAAoD;IACpD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIzB,4BAA4B;IAC5B,UAAU,IAAI,MAAM;CA+GrB"}
1
+ {"version":3,"file":"attach-endpoint.d.ts","sourceRoot":"","sources":["../src/attach-endpoint.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAmBtD,sEAAsE;AACtE,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,cAAc;;IAQvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,2FAA2F;IAC3F,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBAHR,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,EACjD,IAAI,EAAE,MAAM,OAAO;IACpC,2FAA2F;IAC1E,QAAQ,EAAE,MAAM,SAAS,EAAE,EAC5C,IAAI,SAAI;IAwBJ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAUtB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,2DAA2D;IAC3D,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAI3C,oDAAoD;IACpD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIzB,4BAA4B;IAC5B,UAAU,IAAI,MAAM;CA2IrB"}
@@ -63,7 +63,9 @@ export class AttachEndpoint {
63
63
  socket.end("HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n");
64
64
  return;
65
65
  }
66
- this.#wss.handleUpgrade(req, socket, head, (ws) => this.#onConnection(ws, name));
66
+ this.#wss.handleUpgrade(req, socket, head, (ws) => {
67
+ this.#onConnection(ws, name).catch(() => ws.close());
68
+ });
67
69
  });
68
70
  }
69
71
  async start() {
@@ -172,7 +174,7 @@ export class AttachEndpoint {
172
174
  return;
173
175
  res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
174
176
  }
175
- #onConnection(ws, name) {
177
+ async #onConnection(ws, name) {
176
178
  const handle = this.lookup(name);
177
179
  if (!handle || handle.status() !== "running") {
178
180
  ws.close();
@@ -188,14 +190,26 @@ export class AttachEndpoint {
188
190
  ws.close(1011, `attach unsupported for the ${handle.kind} runtime — watch its surface directly`);
189
191
  return;
190
192
  }
191
- const backlog = session.backlog();
192
- if (backlog.length)
193
- ws.send(backlog);
194
- const offData = session.onData((chunk) => {
193
+ const send = (b) => {
195
194
  if (ws.readyState === ws.OPEN)
196
- ws.send(chunk);
195
+ ws.send(b);
196
+ };
197
+ // Subscribe to live output BEFORE requesting the snapshot, and buffer what arrives until the
198
+ // snapshot is sent. The snapshot (below) is a point-in-time screen image; anything the child
199
+ // emits after it must land after it, in order. Subscribing first (no await in between) means no
200
+ // chunk can slip through unobserved, and the buffer stops a mid-snapshot burst from racing ahead
201
+ // of — or being lost before — the image.
202
+ let live = false;
203
+ const buffered = [];
204
+ const offData = session.onData((chunk) => {
205
+ if (live)
206
+ send(chunk);
207
+ else
208
+ buffered.push(chunk);
197
209
  });
198
210
  const offExit = session.onExit(() => ws.close());
211
+ // Wire input + cleanup now too, so the client's initial `r:cols,rows` (and any early keystrokes)
212
+ // during the snapshot await aren't dropped, and a disconnect mid-await still unsubscribes.
199
213
  ws.on("message", (data, isBinary) => {
200
214
  if (isBinary) {
201
215
  session.write(data.toString("utf8"));
@@ -203,15 +217,34 @@ export class AttachEndpoint {
203
217
  }
204
218
  const text = data.toString();
205
219
  const m = /^r:(\d+),(\d+)$/.exec(text);
206
- if (m)
207
- session.resize(Number(m[1]), Number(m[2]));
208
- else
220
+ if (!m) {
209
221
  session.write(text);
222
+ return;
223
+ }
224
+ session.resize(Number(m[1]), Number(m[2]));
210
225
  });
211
226
  ws.on("close", () => {
212
227
  offData();
213
228
  offExit();
214
229
  });
230
+ // Reconstructed screen image: the backend replays a byte-exact snapshot — including the
231
+ // alternate-screen buffer of a full-screen TUI (OpenCode/Claude) — so a late or concurrent attach
232
+ // paints correctly without depending on the child to repaint. (Raw scrollback replay couldn't
233
+ // rebuild an alt-screen, leaving same-size re/co-attaches a partial screen.) Then flush anything
234
+ // that arrived while we built it, and switch to sending live output straight through.
235
+ let snapshot;
236
+ try {
237
+ snapshot = await session.backlog();
238
+ }
239
+ catch {
240
+ ws.close(1011, "attach snapshot failed");
241
+ return;
242
+ }
243
+ if (snapshot.length)
244
+ send(snapshot);
245
+ for (const chunk of buffered)
246
+ send(chunk);
247
+ live = true; // snapshot delivered — stream subsequent output straight through
215
248
  }
216
249
  }
217
250
  //# sourceMappingURL=attach-endpoint.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"attach-endpoint.js","sourceRoot":"","sources":["../src/attach-endpoint.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"attach-endpoint.js","sourceRoot":"","sources":["../src/attach-endpoint.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import { type Profile } from "@cotal-ai/core";
1
2
  type Values = Record<string, string | undefined>;
2
3
  /** Resolve which running mesh a control command (`ps`/`start`/`stop`/`attach`) targets, with the
3
4
  * same precedence + preflight as the rest of the CLI ({@link resolveMeshTarget} / `connectOrExit`):
@@ -9,15 +10,15 @@ type Values = Record<string, string | undefined>;
9
10
  * same escape hatch `connectOrExit` has; plain reachability, no prune).
10
11
  * 3. otherwise the registry/`current` resolver, with the same stale-prune + friendly preflight —
11
12
  * so `cotal ps --space <name>` reaches that mesh's RECORDED broker instead of silently assuming
12
- * `DEFAULT_SERVER` (:4222); `--server` overrides. The privileged "manager" cred is minted from
13
- * the RESOLVED mesh's own recorded root (so `--space other` loads other's auth, guarded by
13
+ * `DEFAULT_SERVER` (:4222); `--server` overrides. The tier-scoped caller cred (`profile`) is minted
14
+ * from the RESOLVED mesh's own recorded root (so `--space other` loads other's auth, guarded by
14
15
  * `targetFromEntry`'s `auth.space === m.space` check), or none for an open mesh.
15
16
  * Shares `@cotal-ai/workspace`'s `preflightTarget`/`pruneStaleMeshes` with the CLI, so a dead/mismatched entry gets
16
17
  * the same one-sentence message + stale-prune the rest of the CLI gives — not a raw NATS trace. The
17
18
  * pre-resolution sweep runs only for bare / `--server`-only resolution; an explicit `--space` is
18
19
  * resolved + preflighted directly (so a `--server` override can recover a dead-recorded mesh).
19
20
  * `ask()` can therefore trust the target is reachable + auth-valid. */
20
- export declare function resolveManagerTarget(v: Values): Promise<{
21
+ export declare function resolveManagerTarget(v: Values, profile: Profile): Promise<{
21
22
  space: string;
22
23
  server: string;
23
24
  creds?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAsCA,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AA+BjD;;;;;;;;;;;;;;;;;wEAiBwE;AACxE,wBAAsB,oBAAoB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkChH"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"AAGA,OAAO,EAcL,KAAK,OAAO,EACb,MAAM,gBAAgB,CAAC;AAqBxB,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AA+BjD;;;;;;;;;;;;;;;;;wEAiBwE;AACxE,wBAAsB,oBAAoB,CACxC,CAAC,EAAE,MAAM,EACT,OAAO,EAAE,OAAO,GACf,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAkC5D"}
package/dist/commands.js CHANGED
@@ -48,15 +48,15 @@ async function preflightOrExit(target, probeCreds) {
48
48
  * same escape hatch `connectOrExit` has; plain reachability, no prune).
49
49
  * 3. otherwise the registry/`current` resolver, with the same stale-prune + friendly preflight —
50
50
  * so `cotal ps --space <name>` reaches that mesh's RECORDED broker instead of silently assuming
51
- * `DEFAULT_SERVER` (:4222); `--server` overrides. The privileged "manager" cred is minted from
52
- * the RESOLVED mesh's own recorded root (so `--space other` loads other's auth, guarded by
51
+ * `DEFAULT_SERVER` (:4222); `--server` overrides. The tier-scoped caller cred (`profile`) is minted
52
+ * from the RESOLVED mesh's own recorded root (so `--space other` loads other's auth, guarded by
53
53
  * `targetFromEntry`'s `auth.space === m.space` check), or none for an open mesh.
54
54
  * Shares `@cotal-ai/workspace`'s `preflightTarget`/`pruneStaleMeshes` with the CLI, so a dead/mismatched entry gets
55
55
  * the same one-sentence message + stale-prune the rest of the CLI gives — not a raw NATS trace. The
56
56
  * pre-resolution sweep runs only for bare / `--server`-only resolution; an explicit `--space` is
57
57
  * resolved + preflighted directly (so a `--server` override can recover a dead-recorded mesh).
58
58
  * `ask()` can therefore trust the target is reachable + auth-valid. */
59
- export async function resolveManagerTarget(v) {
59
+ export async function resolveManagerTarget(v, profile) {
60
60
  if (v.creds) {
61
61
  const server = v.server ?? DEFAULT_SERVER;
62
62
  const creds = readFileSync(v.creds, "utf8");
@@ -89,7 +89,7 @@ export async function resolveManagerTarget(v) {
89
89
  }
90
90
  throw e;
91
91
  }
92
- const creds = target.auth ? await mintCreds(target.auth, newIdentity(), "manager") : undefined;
92
+ const creds = target.auth ? await mintCreds(target.auth, newIdentity(), profile) : undefined;
93
93
  await preflightOrExit(target, creds);
94
94
  return { space: target.space, server: target.server, creds };
95
95
  }
@@ -105,6 +105,7 @@ function parse(argv) {
105
105
  agent: { type: "string" },
106
106
  config: { type: "string" },
107
107
  model: { type: "string" }, // start: model override, wins over the agent file's `model:`
108
+ resume: { type: "string" }, // start: fork an existing session id into the mesh (host-local; claude only)
108
109
  roster: { type: "string" },
109
110
  creds: { type: "string" },
110
111
  runtime: { type: "string" }, // supervise: force pty | tmux | cmux (default pty)
@@ -130,10 +131,11 @@ function parse(argv) {
130
131
  /** Connect a short-lived client with the resolved creds, send one control request to the manager,
131
132
  * disconnect. The target is already reachability- + auth-preflighted by {@link resolveManagerTarget}
132
133
  * (which prints the friendly message + prunes on failure), so this connects straight through. `tier`
133
- * picks the control subject: privileged for spawn/ps; admin for the operator's cross-agent ops
134
+ * picks the control subject: privileged for start/ps; admin for the operator's cross-agent ops
134
135
  * (stop/attach/purge), which the manager refuses on the privileged subject for a non-owner. `creds`
135
- * is the privileged "manager" cred resolved by {@link resolveManagerTarget} (allow-all, so it
136
- * reaches either subject), or undefined on an open mesh. */
136
+ * is the tier-scoped caller cred resolved by {@link resolveManagerTarget} (`control-caller-privileged`
137
+ * for start/ps, `control-caller-admin` for stop/attach each holds ONLY its own tier's pub grant, so
138
+ * `tier` here matches the cred the caller minted), or undefined on an open mesh. */
137
139
  async function ask(space, server, op, args, creds, tier = CONTROL_PRIVILEGED) {
138
140
  const ep = new CotalEndpoint({
139
141
  space,
@@ -169,13 +171,19 @@ async function start(argv) {
169
171
  console.error(c.red("--name is required"));
170
172
  process.exit(1);
171
173
  }
172
- const t = await resolveManagerTarget(v);
174
+ // `--resume ""` asked to resume but named no session — fail loud, don't silently start fresh.
175
+ if (v.resume !== undefined && !v.resume.trim()) {
176
+ console.error(c.red("--resume needs a session id (got an empty value)"));
177
+ process.exit(1);
178
+ }
179
+ const t = await resolveManagerTarget(v, "control-caller-privileged");
173
180
  const reply = await ask(t.space, t.server, "start", {
174
181
  name: v.name,
175
182
  role: v.role,
176
183
  agent: v.agent,
177
184
  config: v.config,
178
185
  model: v.model,
186
+ resume: v.resume, // fork an existing session into the mesh (host-local id; caveated for detached start — see docs)
179
187
  // Opt-in: only sent when `--transcript` is given; absent => the daemon's default (mirror off).
180
188
  transcript: v.transcript ? true : undefined,
181
189
  cwd: v.cwd,
@@ -192,8 +200,10 @@ async function stop(argv) {
192
200
  process.exit(1);
193
201
  }
194
202
  // Operator stop is a cross-agent (admin) op — the CLI operator isn't the agent's spawner, so the
195
- // privileged subject would reject it; admin (its allow-all "manager" cred reaches it) is correct.
196
- const t = await resolveManagerTarget(v);
203
+ // privileged subject would reject it; the admin tier reaches any agent. The scoped `control-caller-admin`
204
+ // cred holds ONLY `ctl.<admin>.<id>` (that IS the cross-agent authority — the manager doesn't re-check
205
+ // the caller), so it reaches this op and nothing else.
206
+ const t = await resolveManagerTarget(v, "control-caller-admin");
197
207
  const reply = await ask(t.space, t.server, "stop", {
198
208
  name: v.name,
199
209
  }, t.creds, CONTROL_ADMIN);
@@ -202,7 +212,7 @@ async function stop(argv) {
202
212
  }
203
213
  async function ps(argv) {
204
214
  const v = parse(argv);
205
- const t = await resolveManagerTarget(v);
215
+ const t = await resolveManagerTarget(v, "control-caller-privileged");
206
216
  const reply = await ask(t.space, t.server, "ps", undefined, t.creds);
207
217
  failIfNotOk(reply);
208
218
  const rows = reply.data ?? [];
@@ -230,8 +240,8 @@ async function attach(argv) {
230
240
  process.exit(1);
231
241
  }
232
242
  // Operator attach is a cross-agent (admin) op — same reasoning as stop (the operator isn't the
233
- // spawner; admin reaches any agent).
234
- const t = await resolveManagerTarget(v);
243
+ // spawner; admin reaches any agent). Scoped `control-caller-admin`: ctl.<admin> only.
244
+ const t = await resolveManagerTarget(v, "control-caller-admin");
235
245
  const reply = await ask(t.space, t.server, "attach", {
236
246
  name: v.name,
237
247
  }, t.creds, CONTROL_ADMIN);
@@ -270,7 +280,17 @@ async function runManager(argv, defaultRuntime) {
270
280
  process.exit(1);
271
281
  }
272
282
  const consolePort = v["console-port"] ? Number(v["console-port"]) : undefined;
273
- const mgr = new Manager({ space, servers: server, runtime, consolePort });
283
+ // Construction resolves the runtime (createRuntime) which fails loud on an unusable env, e.g. the
284
+ // pty runtime under Bun. Render that as one actionable line, not a raw stack (this also lands in
285
+ // `.cotal/manager.log` for a detached `cotal up` daemon).
286
+ let mgr;
287
+ try {
288
+ mgr = new Manager({ space, servers: server, runtime, consolePort });
289
+ }
290
+ catch (e) {
291
+ console.error(c.red(`✗ ${e.message}`));
292
+ process.exit(1);
293
+ }
274
294
  await mgr.start();
275
295
  console.log(c.green("✓ manager up") +
276
296
  c.dim(` (space ${space} · ${mgr.runtimeKind})`) +
@@ -361,7 +381,7 @@ const managerCommands = [
361
381
  kind: "command",
362
382
  name: "start",
363
383
  group: "Control plane",
364
- summary: "ask the manager to spawn a persona — --name <persona> [--role <r>] [--agent <a>] [--config <file>] [--model <m>] [--cwd <dir>] (loads .cotal/agents/<persona>.md; the peer joins under its name:)",
384
+ summary: "ask the manager to spawn a persona — --name <persona> [--role <r>] [--agent <a>] [--config <file>] [--model <m>] [--cwd <dir>] [--resume <id> (pair with --cwd)] (loads .cotal/agents/<persona>.md; the peer joins under its name:)",
365
385
  run: start,
366
386
  },
367
387
  {