camouflage-tui 2.4.0-beta.7 → 2.5.0-beta.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "camouflage-tui",
3
- "version": "2.4.0-beta.7",
3
+ "version": "2.5.0-beta.4",
4
4
  "description": "High-performance terminal renderer for AI agent applications. A React Ink alternative built for streaming, persistence, and replay.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -9,7 +9,7 @@
9
9
  */
10
10
 
11
11
  import { createWriteStream, mkdirSync, chmodSync, existsSync, unlinkSync } from "node:fs";
12
- import { execFileSync } from "node:child_process";
12
+ import { execSync } from "node:child_process";
13
13
  import { join, dirname } from "node:path";
14
14
  import { fileURLToPath } from "node:url";
15
15
  import { get as httpsGet } from "node:https";
@@ -64,7 +64,7 @@ async function main() {
64
64
  await download(url, tmpPath);
65
65
 
66
66
  // Extract the binary from the tarball (Windows 10+ ships tar.exe).
67
- execFileSync("tar", ["xzf", tmpPath, "-C", BIN_DIR], { stdio: "pipe" });
67
+ execSync(`tar xzf "${tmpPath}" -C "${BIN_DIR}"`, { stdio: "pipe" });
68
68
  unlinkSync(tmpPath);
69
69
 
70
70
  chmodSync(BIN_PATH, 0o755);
package/src/binding.d.ts CHANGED
@@ -69,16 +69,6 @@ export function confirm(
69
69
  },
70
70
  ): Promise<ConfirmResponseEvent>;
71
71
 
72
- /**
73
- * Hand the terminal to a child process; resolves once the renderer has let
74
- * go of it. `supported: false` means run the child without a terminal
75
- * (Windows, full-screen mode, older renderers, or no answer in time).
76
- */
77
- export function suspendTerminal(cam: CamouflageHandle, opts?: { timeoutMs?: number }): Promise<{ supported: boolean }>;
78
-
79
- /** Take the terminal back after `suspendTerminal`. */
80
- export function resumeTerminal(cam: CamouflageHandle): void;
81
-
82
72
  /** Convenience helper: show a tabular data view. Display-only. */
83
73
  export function table(
84
74
  cam: CamouflageHandle,
package/src/binding.js CHANGED
@@ -344,8 +344,6 @@ export async function mount(opts = {}) {
344
344
  handle.emit("cancelRequested", {});
345
345
  } else if (ev.event_type === "MentionQuery") {
346
346
  handle.emit("mentionQuery", { query: ev.payload?.query ?? "" });
347
- } else if (ev.event_type === "TerminalSuspended") {
348
- handle.emit("terminalSuspended", { id: ev.payload?.id, supported: ev.payload?.supported === true });
349
347
  }
350
348
  // Always also emit the raw Event for advanced consumers.
351
349
  handle.emit("event", ev);
@@ -423,41 +421,6 @@ export function confirm(cam, spec) {
423
421
  return done;
424
422
  }
425
423
 
426
- /**
427
- * Hand the terminal to a child process (a `!` shell command, an editor, a
428
- * login prompt). The inline renderer clears its live area, leaves raw mode
429
- * and stops reading keys before this resolves. Run the child with
430
- * `stdio: "inherit"`, then call `resumeTerminal(cam)`.
431
- *
432
- * Resolves `{ supported: false }` when the renderer can't hand the terminal
433
- * over (Windows, full-screen mode, renderers older than 2.4.0-beta.7, or no
434
- * answer within `timeoutMs`); run the child without a terminal then.
435
- *
436
- * @param {CamouflageHandle} cam
437
- * @param {{timeoutMs?: number}} [opts]
438
- * @returns {Promise<{supported: boolean}>}
439
- */
440
- export function suspendTerminal(cam, opts = {}) {
441
- const id = `suspend-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
442
- const answer = awaitResponse(cam, "terminalSuspended", (r) => r.id === id, { id, supported: false });
443
- const timeout = new Promise((resolve) => {
444
- const t = setTimeout(() => resolve({ id, supported: false }), opts.timeoutMs ?? 1000);
445
- t.unref?.();
446
- });
447
- cam.send("TerminalSuspend", { id });
448
- return Promise.race([answer, timeout]).then((r) => ({ supported: r.supported === true }));
449
- }
450
-
451
- /**
452
- * Take the terminal back after `suspendTerminal`: the renderer re-enters
453
- * raw mode and redraws below whatever the child printed.
454
- *
455
- * @param {CamouflageHandle} cam
456
- */
457
- export function resumeTerminal(cam) {
458
- cam.send("TerminalResume", { id: "resume" });
459
- }
460
-
461
424
  /**
462
425
  * Ask the user for permission and resolve to their answer. Resolves
463
426
  * `{ choice: "deny" }` if the renderer exits first.
@@ -2,7 +2,7 @@ import { test } from "node:test";
2
2
  import assert from "node:assert/strict";
3
3
  import { fileURLToPath } from "node:url";
4
4
  import { dirname, join } from "node:path";
5
- import { mount, selectList, confirm, permission, suspendTerminal, resumeTerminal } from "./index.js";
5
+ import { mount, selectList, confirm, permission } from "./index.js";
6
6
 
7
7
  const FAKE = join(dirname(fileURLToPath(import.meta.url)), "__fake-renderer.js");
8
8
 
@@ -181,11 +181,3 @@ test("a renderer that exits at startup doesn't crash the host", async () => {
181
181
  await exited;
182
182
  assert.equal(cam.send("SessionEnded", {}), false);
183
183
  });
184
-
185
- test("suspendTerminal() falls back to unsupported when the renderer doesn't answer", async () => {
186
- const cam = await mountFake(); // echoes TerminalSuspend back; never sends TerminalSuspended
187
- const r = await suspendTerminal(cam, { timeoutMs: 50 });
188
- assert.deepEqual(r, { supported: false });
189
- resumeTerminal(cam);
190
- await cam.close();
191
- });
package/src/index.d.ts CHANGED
@@ -78,8 +78,6 @@ export {
78
78
  mount,
79
79
  selectList,
80
80
  confirm,
81
- suspendTerminal,
82
- resumeTerminal,
83
81
  permission,
84
82
  tasksSet,
85
83
  table,
package/src/index.js CHANGED
@@ -15,4 +15,4 @@ export {
15
15
  encode,
16
16
  } from "./types.js";
17
17
 
18
- export { mount, selectList, confirm, permission, table, keyValueView, form, wizard, tasksSet, suspendTerminal, resumeTerminal } from "./binding.js";
18
+ export { mount, selectList, confirm, permission, table, keyValueView, form, wizard, tasksSet } from "./binding.js";
package/src/types.d.ts CHANGED
@@ -53,10 +53,7 @@ export type EventType =
53
53
  | "Splash"
54
54
  | "ShowToast"
55
55
  | "MentionQuery"
56
- | "AssistantReasoningDelta"
57
- | "TerminalSuspend"
58
- | "TerminalResume"
59
- | "TerminalSuspended";
56
+ | "AssistantReasoningDelta";
60
57
 
61
58
  export type Direction = "inbound" | "outbound";
62
59
 
@@ -373,10 +370,6 @@ export type Event = EnvelopeMeta &
373
370
  | { event_type: "AssistantTokenDelta"; payload: AssistantTokenDelta }
374
371
  /** v2.4+: the model's reasoning, shown when the user presses Ctrl+R (inline UI). */
375
372
  | { event_type: "AssistantReasoningDelta"; payload: AssistantTokenDelta }
376
- /** v2.4+: hand the terminal to a child process; see `suspendTerminal()`. */
377
- | { event_type: "TerminalSuspend"; payload: { id: string } }
378
- | { event_type: "TerminalResume"; payload: { id: string } }
379
- | { event_type: "TerminalSuspended"; payload: { id: string; supported: boolean } }
380
373
  | { event_type: "AssistantMessageCompleted"; payload: AssistantMessageCompleted }
381
374
  | { event_type: "ToolExecutionStarted"; payload: ToolStarted }
382
375
  | { event_type: "ToolExecutionStdout"; payload: ToolOutput }
package/src/types.js CHANGED
@@ -24,7 +24,6 @@ const KNOWN_TYPES = new Set([
24
24
  "ModeChangeRequested", "CancelRequested",
25
25
  "TranscriptCleared", "Splash", "ShowToast", "MentionQuery",
26
26
  "AssistantReasoningDelta",
27
- "TerminalSuspend", "TerminalResume", "TerminalSuspended",
28
27
  ]);
29
28
 
30
29
  /**