@workerdeck/core 2.15.0 → 3.0.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/build/index.d.mts +104 -4
- package/build/index.mjs +380 -24
- package/build/index.mjs.map +1 -1
- package/package.json +3 -3
package/build/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { createHash, randomUUID } from "node:crypto";
|
|
3
3
|
import { createSdkMcpServer, getSessionInfo, getSessionMessages, listSessions, query, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
4
|
-
import { CHECKLIST_TEXT_MAX, ENGINE_CAPABILITIES, PEER_MENTION_MAX, PROTOCOL_VERSION, SHELL_CONTEXT_FLUSH_MAX_CHARS, SHELL_CONTEXT_HEAD_CHARS, SHELL_CONTEXT_HEAD_LINES, SHELL_CONTEXT_TAIL_CHARS, SHELL_CONTEXT_TAIL_LINES, SHELL_INLINE_CHARS, SHELL_INLINE_LINES, SHELL_INLINE_LINE_CHARS, SHELL_READ_DEFAULT_LINES, SHELL_READ_MAX_LINES, SUBAGENT_HISTORY, TOOL_RESULT_HEAD_CHARS, addTokenUsage, byModelTotalTokens, canonicalModel, contextReading, costOfByModel, emptyTokenUsage, imagePartRef, logCoalesceKey, mergeByModel, parseTodoWriteInput, peerDeliveredPrefix, replayCoalesceKey, replayRetains, sanitizeToolTitle, snapshotRetains, tokenUsageFromWire, totalTokens, transcriptActivity, transcriptContent, transcriptProse } from "@workerdeck/protocol";
|
|
4
|
+
import { CHECKLIST_TEXT_MAX, ENGINE_CAPABILITIES, PEER_MENTION_MAX, PROTOCOL_VERSION, SHELL_COMMAND_MAX, SHELL_CONTEXT_FLUSH_MAX_CHARS, SHELL_CONTEXT_HEAD_CHARS, SHELL_CONTEXT_HEAD_LINES, SHELL_CONTEXT_TAIL_CHARS, SHELL_CONTEXT_TAIL_LINES, SHELL_INLINE_CHARS, SHELL_INLINE_LINES, SHELL_INLINE_LINE_CHARS, SHELL_INPUT_MAX, SHELL_INTERACTIVE_NOTE, SHELL_READ_DEFAULT_LINES, SHELL_READ_MAX_LINES, SHELL_WAIT_DEFAULT_MS, SHELL_WAIT_MAX_MS, SUBAGENT_HISTORY, TOOL_RESULT_HEAD_CHARS, addTokenUsage, byModelTotalTokens, canonicalModel, contextReading, costOfByModel, emptyTokenUsage, imagePartRef, logCoalesceKey, mergeByModel, parseTodoWriteInput, peerDeliveredPrefix, replayCoalesceKey, replayRetains, sanitizeToolTitle, snapshotRetains, tokenUsageFromWire, totalTokens, transcriptActivity, transcriptContent, transcriptProse } from "@workerdeck/protocol";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
import { ToolLoopAgent, generateText, isStepCount, tool as tool$1 } from "ai";
|
|
7
7
|
import { execFile, spawn } from "node:child_process";
|
|
@@ -281,9 +281,14 @@ const STRING_SEQUENCE = /(?:\x1b[PX^_]|[\x90\x98\x9e\x9f])[\s\S]*?(?:\x1b\\|\x9c
|
|
|
281
281
|
const CSI_SEQUENCE = /(?:\x1b\[|\x9b)[0-?]*[ -/]*[@-~]/g;
|
|
282
282
|
const ESCAPE_SEQUENCE = /\x1b[ -/]*[0-~]/g;
|
|
283
283
|
const CONTROL_CHARS = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g;
|
|
284
|
+
const REDRAW_SEQUENCE = /(?:\x1b\[|\x9b)(?:\?(?:1049|1047|47)h|\d*[AF]|\d+;\d+[Hf]|\d+d)/;
|
|
285
|
+
const TTY_REDRAW_CARRY = 16;
|
|
284
286
|
function ttyText(raw) {
|
|
285
287
|
return raw.replace(OSC_SEQUENCE, "").replace(STRING_SEQUENCE, "").replace(CSI_SEQUENCE, "").replace(ESCAPE_SEQUENCE, "").replace(CONTROL_CHARS, "").replace(/\r\n/g, "\n").split("\n").map((line) => overwritten(line).trimEnd()).join("\n");
|
|
286
288
|
}
|
|
289
|
+
function ttyRedraws(raw) {
|
|
290
|
+
return REDRAW_SEQUENCE.test(raw);
|
|
291
|
+
}
|
|
287
292
|
function splitLines(text) {
|
|
288
293
|
if (text === "") return [];
|
|
289
294
|
return (text.endsWith("\n") ? text.slice(0, -1) : text).split("\n");
|
|
@@ -414,9 +419,13 @@ function localCommandEvent(text, uuid, shell) {
|
|
|
414
419
|
};
|
|
415
420
|
}
|
|
416
421
|
function shellInlineText(shell, text) {
|
|
417
|
-
const
|
|
418
|
-
|
|
419
|
-
|
|
422
|
+
const body = [`$ ${shell.command}`];
|
|
423
|
+
if (shell.interactive) body.push(`[${SHELL_INTERACTIVE_NOTE}]`);
|
|
424
|
+
else {
|
|
425
|
+
const head = inlineHead(text);
|
|
426
|
+
body.push(...head.lines);
|
|
427
|
+
if (head.more) body.push(INLINE_MORE);
|
|
428
|
+
}
|
|
420
429
|
const end = shellEndLine(shell);
|
|
421
430
|
if (end) body.push(end);
|
|
422
431
|
return frame(shellTag(shell), body);
|
|
@@ -451,6 +460,7 @@ function shellContextText(shell, text, options = {}) {
|
|
|
451
460
|
}
|
|
452
461
|
var LocalCommandQueue = class {
|
|
453
462
|
#entries = [];
|
|
463
|
+
#rows = /* @__PURE__ */ new Set();
|
|
454
464
|
#emit;
|
|
455
465
|
constructor(emit) {
|
|
456
466
|
this.#emit = emit;
|
|
@@ -470,6 +480,22 @@ var LocalCommandQueue = class {
|
|
|
470
480
|
const info = { ...input.info() };
|
|
471
481
|
this.#emit(shellInlineText(info, input.text()), uuid, info);
|
|
472
482
|
};
|
|
483
|
+
if (input.info().owner === "agent") {
|
|
484
|
+
const settle = () => {
|
|
485
|
+
if (input.info().status !== "running") {
|
|
486
|
+
unsubscribe();
|
|
487
|
+
this.#rows.delete(unsubscribe);
|
|
488
|
+
}
|
|
489
|
+
};
|
|
490
|
+
const unsubscribe = input.subscribe(() => {
|
|
491
|
+
row();
|
|
492
|
+
settle();
|
|
493
|
+
});
|
|
494
|
+
this.#rows.add(unsubscribe);
|
|
495
|
+
row();
|
|
496
|
+
settle();
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
473
499
|
row();
|
|
474
500
|
const unsubscribe = input.subscribe(row);
|
|
475
501
|
this.#entries.push({
|
|
@@ -507,6 +533,8 @@ var LocalCommandQueue = class {
|
|
|
507
533
|
clear() {
|
|
508
534
|
for (const entry of this.#entries) if (entry.kind === "shell") entry.unsubscribe();
|
|
509
535
|
this.#entries = [];
|
|
536
|
+
for (const unsubscribe of this.#rows) unsubscribe();
|
|
537
|
+
this.#rows.clear();
|
|
510
538
|
}
|
|
511
539
|
};
|
|
512
540
|
function render(entry) {
|
|
@@ -1499,23 +1527,125 @@ function peerDirectoryHandle() {
|
|
|
1499
1527
|
//#endregion
|
|
1500
1528
|
//#region src/lib/shells.ts
|
|
1501
1529
|
const SHELL_REFUSAL = "shell commands are not available on this session";
|
|
1530
|
+
const SHELL_WRITE_REFUSAL = "the agent may not start, type into or kill shells on this session (shell.agentWrite is read-only)";
|
|
1531
|
+
const SHELL_KEYS_MAX = 64;
|
|
1502
1532
|
const SHELL_DIRECTORY_SLOT = Symbol.for("workerdeck.shells.directory");
|
|
1533
|
+
const CTRL_LETTERS = "abcdefghijklmnopqrstuvwxyz";
|
|
1534
|
+
const NAMED_KEYS = {
|
|
1535
|
+
enter: "\r",
|
|
1536
|
+
return: "\r",
|
|
1537
|
+
tab: " ",
|
|
1538
|
+
"shift-tab": "\x1B[Z",
|
|
1539
|
+
escape: "\x1B",
|
|
1540
|
+
esc: "\x1B",
|
|
1541
|
+
backspace: "",
|
|
1542
|
+
delete: "\x1B[3~",
|
|
1543
|
+
insert: "\x1B[2~",
|
|
1544
|
+
pageup: "\x1B[5~",
|
|
1545
|
+
pagedown: "\x1B[6~",
|
|
1546
|
+
space: " ",
|
|
1547
|
+
f1: "\x1BOP",
|
|
1548
|
+
f2: "\x1BOQ",
|
|
1549
|
+
f3: "\x1BOR",
|
|
1550
|
+
f4: "\x1BOS",
|
|
1551
|
+
f5: "\x1B[15~",
|
|
1552
|
+
f6: "\x1B[17~",
|
|
1553
|
+
f7: "\x1B[18~",
|
|
1554
|
+
f8: "\x1B[19~",
|
|
1555
|
+
f9: "\x1B[20~",
|
|
1556
|
+
f10: "\x1B[21~",
|
|
1557
|
+
f11: "\x1B[23~",
|
|
1558
|
+
f12: "\x1B[24~"
|
|
1559
|
+
};
|
|
1560
|
+
const CURSOR_KEYS = {
|
|
1561
|
+
up: "A",
|
|
1562
|
+
down: "B",
|
|
1563
|
+
right: "C",
|
|
1564
|
+
left: "D",
|
|
1565
|
+
home: "H",
|
|
1566
|
+
end: "F"
|
|
1567
|
+
};
|
|
1568
|
+
const SHELL_KEY_NAMES = [
|
|
1569
|
+
"enter",
|
|
1570
|
+
"tab",
|
|
1571
|
+
"shift-tab",
|
|
1572
|
+
"escape",
|
|
1573
|
+
"backspace",
|
|
1574
|
+
"delete",
|
|
1575
|
+
"insert",
|
|
1576
|
+
"up",
|
|
1577
|
+
"down",
|
|
1578
|
+
"left",
|
|
1579
|
+
"right",
|
|
1580
|
+
"home",
|
|
1581
|
+
"end",
|
|
1582
|
+
"pageup",
|
|
1583
|
+
"pagedown",
|
|
1584
|
+
"space",
|
|
1585
|
+
"f1 to f12",
|
|
1586
|
+
"ctrl-a to ctrl-z",
|
|
1587
|
+
"any single printable character"
|
|
1588
|
+
];
|
|
1589
|
+
const waitForShape = z.union([z.string().min(1), z.array(z.string().min(1)).min(1).max(8)]).optional().describe("Wait until this text (or any of these) appears, the shell exits, or timeoutMs passes, then return the view. A plain case-sensitive substring, not a pattern.");
|
|
1590
|
+
const timeoutShape = z.number().int().min(0).max(SHELL_WAIT_MAX_MS).optional().describe(`With waitFor: how long to wait (default ${SHELL_WAIT_DEFAULT_MS}, at most ${SHELL_WAIT_MAX_MS})`);
|
|
1503
1591
|
const SHELL_TOOL_SHAPES = {
|
|
1504
1592
|
shell_list: {
|
|
1505
|
-
description: "List the
|
|
1593
|
+
description: "List the shells of this session: the commands your user ran with `$` and the ones you started with shell_run. Each has an id, a command, an owner (user or agent), whether it is still running, its exit code, how much output it produced and whether it is interactive (a program that redraws the screen). Call this before shell_read, shell_write or shell_kill to find the shell id.",
|
|
1506
1594
|
shape: {}
|
|
1507
1595
|
},
|
|
1508
1596
|
shell_read: {
|
|
1509
|
-
description: "Read
|
|
1597
|
+
description: "Read one shell's output. Use it to answer \"what is the dev server printing now\", to see more of a command whose output was summarised in the conversation, or with waitFor to block until a server is ready. Reading never writes to the shell and never interrupts it.",
|
|
1510
1598
|
shape: {
|
|
1511
1599
|
shellId: z.string().describe("The shell id from shell_list"),
|
|
1512
|
-
|
|
1600
|
+
view: z.enum(["lines", "screen"]).optional().describe("lines: the trailing lines of the output as plain text. screen: what the terminal shows right now, the only readable view of a program that redraws (a TUI, a dev server dashboard, a multi-line progress display). Defaults to screen for an interactive shell and lines otherwise."),
|
|
1601
|
+
tail: z.number().int().min(1).optional().describe(`With view lines: how many trailing lines to return (default ${SHELL_READ_DEFAULT_LINES}, capped at ${SHELL_READ_MAX_LINES})`),
|
|
1602
|
+
waitFor: z.union([z.string().min(1), z.array(z.string().min(1)).min(1).max(8)]).optional().describe("Wait until the view contains this text (or any of these), the shell exits, or timeoutMs passes, then read. A plain case-sensitive substring, not a pattern. Text already there counts, so a server that was ready before the call returns at once."),
|
|
1603
|
+
timeoutMs: timeoutShape
|
|
1604
|
+
}
|
|
1605
|
+
},
|
|
1606
|
+
shell_run: {
|
|
1607
|
+
description: "Start a shell command of your own in the session's working directory, in a real terminal (a PTY) that keeps running after this call returns: a dev server, a watcher, a TUI. The result names the new shell id; use shell_read to watch it, shell_write to type into it and shell_kill to stop it. With waitFor the call blocks until the output contains that text (or the command exits or timeoutMs passes), so \"start vite and wait for 'ready in'\" is one call. This needs the user's approval and every shell you start is visible to them. For a command that just runs and finishes, prefer your ordinary shell tool.",
|
|
1608
|
+
shape: {
|
|
1609
|
+
command: z.string().min(1).max(SHELL_COMMAND_MAX).refine((command) => command.trim() !== "" && !command.includes("\0"), "command must be non-empty text").describe("The command line, run by the user's login shell in the session's working directory"),
|
|
1610
|
+
waitFor: waitForShape,
|
|
1611
|
+
timeoutMs: timeoutShape
|
|
1612
|
+
}
|
|
1613
|
+
},
|
|
1614
|
+
shell_write: {
|
|
1615
|
+
description: `Type into a shell you started with shell_run: literal text in data, named keys in keys, or both (data is sent first, then the keys in order). To press Enter use keys ["enter"]; a "\\n" in data ends a line only for line-mode programs, not for a TUI. Key names: ${SHELL_KEY_NAMES.join(", ")}. With waitFor the call blocks until the shell prints that text AFTER your keystrokes (earlier output never counts), then returns the view, so "press r and wait for 'reloaded'" is one call. Typing into a shell the user started is refused unless they granted it through shell_request_write.`,
|
|
1616
|
+
shape: {
|
|
1617
|
+
shellId: z.string().describe("The shell id from shell_run or shell_list"),
|
|
1618
|
+
data: z.string().max(SHELL_INPUT_MAX).optional().describe("Literal text to type, sent as-is"),
|
|
1619
|
+
keys: z.array(z.string().min(1)).min(1).max(64).optional().describe("Named keys to press after data, in order, e.g. [\"r\"], [\"enter\"], [\"ctrl-c\"], [\"down\", \"down\", \"enter\"]"),
|
|
1620
|
+
waitFor: waitForShape,
|
|
1621
|
+
timeoutMs: timeoutShape
|
|
1622
|
+
}
|
|
1623
|
+
},
|
|
1624
|
+
shell_kill: {
|
|
1625
|
+
description: "Stop a shell you started with shell_run, killing its whole process tree. Use it when the user asks you to stop the server or when you are done with it. Killing a shell the user started is refused unless they granted it through shell_request_write.",
|
|
1626
|
+
shape: { shellId: z.string().describe("The shell id from shell_run or shell_list") }
|
|
1627
|
+
},
|
|
1628
|
+
shell_request_write: {
|
|
1629
|
+
description: "Ask the user to let you type into (and kill) a shell THEY started with `$`, for example to answer a prompt in a script or to drive a TUI they launched. The user sees the shell and your reason and allows or denies; once allowed, shell_write and shell_kill work on it until the shell ends or the user revokes the grant. Never needed for a shell you started with shell_run.",
|
|
1630
|
+
shape: {
|
|
1631
|
+
shellId: z.string().describe("The id of a running shell the user started, from shell_list"),
|
|
1632
|
+
reason: z.string().min(1).max(500).describe("One sentence the user reads on the approval card: what you will type and why")
|
|
1513
1633
|
}
|
|
1514
1634
|
}
|
|
1515
1635
|
};
|
|
1516
1636
|
const SHELL_TOOL_NAMES = Object.keys(SHELL_TOOL_SHAPES);
|
|
1517
|
-
|
|
1518
|
-
|
|
1637
|
+
const SHELL_READ_TOOL_NAMES = ["shell_list", "shell_read"];
|
|
1638
|
+
const SHELL_WRITE_TOOL_NAMES = [
|
|
1639
|
+
"shell_run",
|
|
1640
|
+
"shell_write",
|
|
1641
|
+
"shell_kill",
|
|
1642
|
+
"shell_request_write"
|
|
1643
|
+
];
|
|
1644
|
+
function shellToolNames(write) {
|
|
1645
|
+
return write ? [...SHELL_READ_TOOL_NAMES, ...SHELL_WRITE_TOOL_NAMES] : [...SHELL_READ_TOOL_NAMES];
|
|
1646
|
+
}
|
|
1647
|
+
function shellToolSpecs(write = false) {
|
|
1648
|
+
return shellToolNames(write).map((name) => {
|
|
1519
1649
|
const { description, shape } = SHELL_TOOL_SHAPES[name];
|
|
1520
1650
|
return {
|
|
1521
1651
|
name,
|
|
@@ -1527,10 +1657,59 @@ function shellToolSpecs() {
|
|
|
1527
1657
|
function isShellToolName(name) {
|
|
1528
1658
|
return Object.hasOwn(SHELL_TOOL_SHAPES, name);
|
|
1529
1659
|
}
|
|
1660
|
+
function isShellWriteToolName(name) {
|
|
1661
|
+
return SHELL_WRITE_TOOL_NAMES.includes(name);
|
|
1662
|
+
}
|
|
1663
|
+
function shellWriteToolOf(toolName) {
|
|
1664
|
+
const bare = toolName.startsWith("mcp__") ? toolName.slice(toolName.indexOf("__", 5) + 2) : toolName;
|
|
1665
|
+
return isShellWriteToolName(bare) ? bare : void 0;
|
|
1666
|
+
}
|
|
1667
|
+
function shellToolOf(toolName) {
|
|
1668
|
+
const bare = toolName.startsWith("mcp__") ? toolName.slice(toolName.indexOf("__", 5) + 2) : toolName;
|
|
1669
|
+
return isShellToolName(bare) ? bare : void 0;
|
|
1670
|
+
}
|
|
1671
|
+
function shellToolNeedsCard(toolName, agentWrite) {
|
|
1672
|
+
const tool = shellWriteToolOf(toolName);
|
|
1673
|
+
if (tool === void 0 || agentWrite === void 0) return false;
|
|
1674
|
+
return agentWrite === "gated" || tool === "shell_request_write";
|
|
1675
|
+
}
|
|
1530
1676
|
function clampShellTail(tail) {
|
|
1531
1677
|
if (tail === void 0 || !Number.isFinite(tail)) return SHELL_READ_DEFAULT_LINES;
|
|
1532
1678
|
return Math.max(1, Math.min(Math.floor(tail), SHELL_READ_MAX_LINES));
|
|
1533
1679
|
}
|
|
1680
|
+
function agentMayWrite(shell, from) {
|
|
1681
|
+
return shell.sessionId === from && (shell.owner === "agent" || shell.agentWrite === true);
|
|
1682
|
+
}
|
|
1683
|
+
function shellOwnershipRefusal(shellId) {
|
|
1684
|
+
return `shell ${shellId} was started by the user; the agent may only type into or kill shells it started, or one the user granted through shell_request_write`;
|
|
1685
|
+
}
|
|
1686
|
+
function shellWriteDeniedText(name, message) {
|
|
1687
|
+
return `the user denied this ${name}${message ? `: ${message}` : ""}`;
|
|
1688
|
+
}
|
|
1689
|
+
function encodeShellKey(key, options = {}) {
|
|
1690
|
+
if ([...key].length === 1) {
|
|
1691
|
+
const code = key.codePointAt(0);
|
|
1692
|
+
return code < 32 || code === 127 ? void 0 : key;
|
|
1693
|
+
}
|
|
1694
|
+
const name = key.toLowerCase().replace(/\+/g, "-").replace(/^control-/, "ctrl-").replace(/^c-/, "ctrl-");
|
|
1695
|
+
const named = NAMED_KEYS[name];
|
|
1696
|
+
if (named !== void 0) return named;
|
|
1697
|
+
const cursor = CURSOR_KEYS[name];
|
|
1698
|
+
if (cursor !== void 0) return `\x1b${options.applicationCursorKeys ? "O" : "["}${cursor}`;
|
|
1699
|
+
if (name.startsWith("ctrl-") && name.length === 6) {
|
|
1700
|
+
const index = CTRL_LETTERS.indexOf(name[5]);
|
|
1701
|
+
if (index !== -1) return String.fromCharCode(index + 1);
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
function encodeShellKeys(keys, options = {}) {
|
|
1705
|
+
let out = "";
|
|
1706
|
+
for (const key of keys) {
|
|
1707
|
+
const encoded = encodeShellKey(key, options);
|
|
1708
|
+
if (encoded === void 0) throw new Error(`unknown key ${JSON.stringify(key)}; use one of ${SHELL_KEY_NAMES.join(", ")}`);
|
|
1709
|
+
out += encoded;
|
|
1710
|
+
}
|
|
1711
|
+
return out;
|
|
1712
|
+
}
|
|
1534
1713
|
function shellSummary(info) {
|
|
1535
1714
|
return {
|
|
1536
1715
|
id: info.id,
|
|
@@ -1545,7 +1724,9 @@ function shellSummary(info) {
|
|
|
1545
1724
|
exitCode: info.exitCode,
|
|
1546
1725
|
endReason: info.endReason,
|
|
1547
1726
|
bytes: info.bytes,
|
|
1548
|
-
capped: info.capped
|
|
1727
|
+
capped: info.capped,
|
|
1728
|
+
interactive: info.interactive,
|
|
1729
|
+
agentWrite: info.agentWrite
|
|
1549
1730
|
};
|
|
1550
1731
|
}
|
|
1551
1732
|
function shellTail(text, tail) {
|
|
@@ -1553,17 +1734,22 @@ function shellTail(text, tail) {
|
|
|
1553
1734
|
const all = body.length === 0 ? [] : body.split("\n");
|
|
1554
1735
|
const kept = all.slice(Math.max(0, all.length - tail));
|
|
1555
1736
|
return {
|
|
1737
|
+
view: "lines",
|
|
1556
1738
|
text: kept.join("\n"),
|
|
1557
1739
|
lines: kept.length,
|
|
1558
1740
|
totalLines: all.length,
|
|
1559
1741
|
truncated: kept.length < all.length
|
|
1560
1742
|
};
|
|
1561
1743
|
}
|
|
1562
|
-
async function runShellTool(shells, from, name, args) {
|
|
1744
|
+
async function runShellTool(shells, from, name, args, options = {}) {
|
|
1563
1745
|
if (!isShellToolName(name)) return {
|
|
1564
1746
|
text: `unknown shell tool: ${name}`,
|
|
1565
1747
|
isError: true
|
|
1566
1748
|
};
|
|
1749
|
+
if (isShellWriteToolName(name) && options.write !== true) return {
|
|
1750
|
+
text: SHELL_WRITE_REFUSAL,
|
|
1751
|
+
isError: true
|
|
1752
|
+
};
|
|
1567
1753
|
try {
|
|
1568
1754
|
switch (name) {
|
|
1569
1755
|
case "shell_list": {
|
|
@@ -1576,7 +1762,13 @@ async function runShellTool(shells, from, name, args) {
|
|
|
1576
1762
|
case "shell_read": {
|
|
1577
1763
|
const input = z.object(SHELL_TOOL_SHAPES.shell_read.shape).safeParse(args ?? {});
|
|
1578
1764
|
if (!input.success) return invalidArguments(name, input.error);
|
|
1579
|
-
const
|
|
1765
|
+
const { shellId, view, tail, waitFor, timeoutMs } = input.data;
|
|
1766
|
+
const result = await shells.read(from, shellId, {
|
|
1767
|
+
tail: clampShellTail(tail),
|
|
1768
|
+
view,
|
|
1769
|
+
waitFor: needles(waitFor),
|
|
1770
|
+
timeoutMs
|
|
1771
|
+
});
|
|
1580
1772
|
if (!result) return {
|
|
1581
1773
|
text: `no such shell: ${input.data.shellId}`,
|
|
1582
1774
|
isError: true
|
|
@@ -1586,6 +1778,76 @@ async function runShellTool(shells, from, name, args) {
|
|
|
1586
1778
|
isError: false
|
|
1587
1779
|
};
|
|
1588
1780
|
}
|
|
1781
|
+
case "shell_run": {
|
|
1782
|
+
const input = z.object(SHELL_TOOL_SHAPES.shell_run.shape).safeParse(args ?? {});
|
|
1783
|
+
if (!input.success) return invalidArguments(name, input.error);
|
|
1784
|
+
const { command, waitFor, timeoutMs } = input.data;
|
|
1785
|
+
return {
|
|
1786
|
+
text: shellReadText(await shells.run(from, {
|
|
1787
|
+
command,
|
|
1788
|
+
waitFor: needles(waitFor),
|
|
1789
|
+
timeoutMs
|
|
1790
|
+
}), "started"),
|
|
1791
|
+
isError: false
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1794
|
+
case "shell_write": {
|
|
1795
|
+
const input = z.object(SHELL_TOOL_SHAPES.shell_write.shape).safeParse(args ?? {});
|
|
1796
|
+
if (!input.success) return invalidArguments(name, input.error);
|
|
1797
|
+
const { shellId, data, keys, waitFor, timeoutMs } = input.data;
|
|
1798
|
+
if (!data && !keys) return {
|
|
1799
|
+
text: `invalid arguments for ${name}: give data, keys or both`,
|
|
1800
|
+
isError: true
|
|
1801
|
+
};
|
|
1802
|
+
try {
|
|
1803
|
+
encodeShellKeys(keys ?? []);
|
|
1804
|
+
} catch (error) {
|
|
1805
|
+
return {
|
|
1806
|
+
text: `invalid arguments for ${name}: ${error instanceof Error ? error.message : String(error)}`,
|
|
1807
|
+
isError: true
|
|
1808
|
+
};
|
|
1809
|
+
}
|
|
1810
|
+
const result = await shells.write(from, shellId, {
|
|
1811
|
+
data,
|
|
1812
|
+
keys,
|
|
1813
|
+
waitFor: needles(waitFor),
|
|
1814
|
+
timeoutMs
|
|
1815
|
+
});
|
|
1816
|
+
if (!result) return {
|
|
1817
|
+
text: `no such shell: ${shellId}`,
|
|
1818
|
+
isError: true
|
|
1819
|
+
};
|
|
1820
|
+
return {
|
|
1821
|
+
text: shellReadText(result, "typed"),
|
|
1822
|
+
isError: false
|
|
1823
|
+
};
|
|
1824
|
+
}
|
|
1825
|
+
case "shell_kill": {
|
|
1826
|
+
const input = z.object(SHELL_TOOL_SHAPES.shell_kill.shape).safeParse(args ?? {});
|
|
1827
|
+
if (!input.success) return invalidArguments(name, input.error);
|
|
1828
|
+
const result = await shells.kill(from, input.data.shellId);
|
|
1829
|
+
if (!result) return {
|
|
1830
|
+
text: `no such shell: ${input.data.shellId}`,
|
|
1831
|
+
isError: true
|
|
1832
|
+
};
|
|
1833
|
+
return {
|
|
1834
|
+
text: shellKillText(result),
|
|
1835
|
+
isError: false
|
|
1836
|
+
};
|
|
1837
|
+
}
|
|
1838
|
+
case "shell_request_write": {
|
|
1839
|
+
const input = z.object(SHELL_TOOL_SHAPES.shell_request_write.shape).safeParse(args ?? {});
|
|
1840
|
+
if (!input.success) return invalidArguments(name, input.error);
|
|
1841
|
+
const shell = await shells.grant(from, input.data.shellId);
|
|
1842
|
+
if (!shell) return {
|
|
1843
|
+
text: `no such shell: ${input.data.shellId}`,
|
|
1844
|
+
isError: true
|
|
1845
|
+
};
|
|
1846
|
+
return {
|
|
1847
|
+
text: `granted: you may now type into and kill shell #${shell.ordinal} ${shell.id} ($ ${shell.command}) until it ends or the user revokes it`,
|
|
1848
|
+
isError: false
|
|
1849
|
+
};
|
|
1850
|
+
}
|
|
1589
1851
|
}
|
|
1590
1852
|
} catch (error) {
|
|
1591
1853
|
return {
|
|
@@ -1594,18 +1856,43 @@ async function runShellTool(shells, from, name, args) {
|
|
|
1594
1856
|
};
|
|
1595
1857
|
}
|
|
1596
1858
|
}
|
|
1859
|
+
function needles(waitFor) {
|
|
1860
|
+
if (waitFor === void 0) return;
|
|
1861
|
+
return typeof waitFor === "string" ? [waitFor] : waitFor;
|
|
1862
|
+
}
|
|
1597
1863
|
function invalidArguments(name, error) {
|
|
1598
1864
|
return {
|
|
1599
1865
|
text: `invalid arguments for ${name}: ${error.issues.map((issue) => `${issue.path.join(".") || "input"}: ${issue.message}`).join("; ")}`,
|
|
1600
1866
|
isError: true
|
|
1601
1867
|
};
|
|
1602
1868
|
}
|
|
1603
|
-
function shellReadText(result) {
|
|
1869
|
+
function shellReadText(result, verb) {
|
|
1604
1870
|
const { shell } = result;
|
|
1605
|
-
const scope = result.truncated ? `showing the last ${result.lines} of ${result.totalLines} lines` : `showing all ${result.lines} lines`;
|
|
1606
|
-
const
|
|
1871
|
+
const scope = result.view === "screen" ? "the current screen" : result.truncated ? `showing the last ${result.lines} of ${result.totalLines} lines` : `showing all ${result.lines} lines`;
|
|
1872
|
+
const parts = [
|
|
1873
|
+
`$ ${shell.command}`,
|
|
1874
|
+
...verb ? [verb] : [],
|
|
1875
|
+
shellState(shell),
|
|
1876
|
+
...shell.interactive ? ["interactive"] : [],
|
|
1877
|
+
scope
|
|
1878
|
+
];
|
|
1879
|
+
if (result.wait) parts.push(waitText(result.wait));
|
|
1880
|
+
const head = `[shell #${shell.ordinal} ${shell.id}: ${parts.join(", ")}]`;
|
|
1607
1881
|
return result.text ? `${head}\n${result.text}` : `${head}\n(no output)`;
|
|
1608
1882
|
}
|
|
1883
|
+
function shellKillText(result) {
|
|
1884
|
+
const { shell } = result;
|
|
1885
|
+
const name = `shell #${shell.ordinal} ${shell.id} ($ ${shell.command})`;
|
|
1886
|
+
return result.killed ? `killed ${name}` : `${name} had already ended (${shellState(shell)})`;
|
|
1887
|
+
}
|
|
1888
|
+
function waitText(wait) {
|
|
1889
|
+
const seconds = `${(wait.ms / 1e3).toFixed(1)}s`;
|
|
1890
|
+
switch (wait.outcome) {
|
|
1891
|
+
case "matched": return `found ${JSON.stringify(wait.match)} after ${seconds}`;
|
|
1892
|
+
case "exited": return `the shell ended before the text appeared (${seconds})`;
|
|
1893
|
+
case "timeout": return `the text did not appear within ${seconds}`;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1609
1896
|
function shellState(shell) {
|
|
1610
1897
|
if (shell.status === "running") return "still running";
|
|
1611
1898
|
if (shell.exitCode !== void 0) return `exited ${shell.exitCode}`;
|
|
@@ -1625,7 +1912,11 @@ function shellDirectoryHandle() {
|
|
|
1625
1912
|
};
|
|
1626
1913
|
return {
|
|
1627
1914
|
list: async (from) => resolve().list(from),
|
|
1628
|
-
read: async (from, shellId, options) => resolve().read(from, shellId, options)
|
|
1915
|
+
read: async (from, shellId, options) => resolve().read(from, shellId, options),
|
|
1916
|
+
run: async (from, options) => resolve().run(from, options),
|
|
1917
|
+
write: async (from, shellId, options) => resolve().write(from, shellId, options),
|
|
1918
|
+
kill: async (from, shellId) => resolve().kill(from, shellId),
|
|
1919
|
+
grant: async (from, shellId) => resolve().grant(from, shellId)
|
|
1629
1920
|
};
|
|
1630
1921
|
}
|
|
1631
1922
|
//#endregion
|
|
@@ -1887,6 +2178,7 @@ var SessionRunner = class {
|
|
|
1887
2178
|
cwd: this.#cwd,
|
|
1888
2179
|
profile: this.#config.profile,
|
|
1889
2180
|
engine: "claude",
|
|
2181
|
+
shellAgentWrite: this.#config.shells ? this.#config.shellAgentWrite : void 0,
|
|
1890
2182
|
capabilities: ENGINE_CAPABILITIES.claude,
|
|
1891
2183
|
model: this.#model ?? this.#config.model,
|
|
1892
2184
|
permissionMode: this.#permissionMode,
|
|
@@ -2154,8 +2446,8 @@ var SessionRunner = class {
|
|
|
2154
2446
|
}],
|
|
2155
2447
|
isError: output.isError
|
|
2156
2448
|
};
|
|
2157
|
-
})) : [], ...shells ?
|
|
2158
|
-
const output = await runShellTool(shells, this.id, name, args);
|
|
2449
|
+
})) : [], ...shells ? shellToolNames(this.#config.shellAgentWrite !== void 0).map((name) => tool(name, SHELL_TOOL_SHAPES[name].description, SHELL_TOOL_SHAPES[name].shape, async (args) => {
|
|
2450
|
+
const output = await runShellTool(shells, this.id, name, args, { write: this.#config.shellAgentWrite !== void 0 });
|
|
2159
2451
|
return {
|
|
2160
2452
|
content: [{
|
|
2161
2453
|
type: "text",
|
|
@@ -2390,6 +2682,10 @@ var SessionRunner = class {
|
|
|
2390
2682
|
delete request.expiresAt;
|
|
2391
2683
|
return Promise.resolve(this.#resolveQuestionByPolicy(request, questionBehavior));
|
|
2392
2684
|
}
|
|
2685
|
+
if (this.#allowsShellToolByPolicy(toolName)) {
|
|
2686
|
+
delete request.expiresAt;
|
|
2687
|
+
return Promise.resolve(this.#allowByPolicy(request));
|
|
2688
|
+
}
|
|
2393
2689
|
return new Promise((resolve) => {
|
|
2394
2690
|
const timer = timeoutMs === void 0 ? void 0 : setTimeout(() => {
|
|
2395
2691
|
const pending = this.#pending.get(id);
|
|
@@ -2417,6 +2713,27 @@ var SessionRunner = class {
|
|
|
2417
2713
|
this.#setStatus("awaiting_approval");
|
|
2418
2714
|
});
|
|
2419
2715
|
};
|
|
2716
|
+
#allowsShellToolByPolicy(toolName) {
|
|
2717
|
+
if ((this.#config.shells ? shellToolOf(toolName) : void 0) === void 0) return false;
|
|
2718
|
+
return shellWriteToolOf(toolName) === void 0 || !shellToolNeedsCard(toolName, this.#config.shellAgentWrite);
|
|
2719
|
+
}
|
|
2720
|
+
#allowByPolicy(request) {
|
|
2721
|
+
this.#emit({
|
|
2722
|
+
type: "permission_requested",
|
|
2723
|
+
request
|
|
2724
|
+
});
|
|
2725
|
+
this.#emit({
|
|
2726
|
+
type: "permission_resolved",
|
|
2727
|
+
requestId: request.id,
|
|
2728
|
+
behavior: "allow",
|
|
2729
|
+
resolvedBy: "policy"
|
|
2730
|
+
});
|
|
2731
|
+
return {
|
|
2732
|
+
behavior: "allow",
|
|
2733
|
+
updatedInput: request.input,
|
|
2734
|
+
toolUseID: request.toolUseId
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2420
2737
|
#resolveQuestionByPolicy(request, mode) {
|
|
2421
2738
|
this.#emit({
|
|
2422
2739
|
type: "permission_requested",
|
|
@@ -2619,6 +2936,7 @@ var AiSdkRunner = class {
|
|
|
2619
2936
|
cwd: this.#config.cwd ?? "",
|
|
2620
2937
|
profile: this.#config.profile,
|
|
2621
2938
|
engine: "provider",
|
|
2939
|
+
shellAgentWrite: this.#config.shells ? this.#config.shellAgentWrite : void 0,
|
|
2622
2940
|
capabilities: this.#config.shouldApprove ? {
|
|
2623
2941
|
...ENGINE_CAPABILITIES.provider,
|
|
2624
2942
|
interactiveApprovals: true
|
|
@@ -3831,15 +4149,16 @@ function createToolContext(options) {
|
|
|
3831
4149
|
}
|
|
3832
4150
|
if (options.shells) {
|
|
3833
4151
|
const shells = options.shells;
|
|
4152
|
+
const write = options.shellWrite === true;
|
|
3834
4153
|
const selfId = options.selfId ?? (() => options.sessionId);
|
|
3835
|
-
for (const name of
|
|
4154
|
+
for (const name of shellToolNames(write)) definitions.push({
|
|
3836
4155
|
name,
|
|
3837
4156
|
trust: "authoritative",
|
|
3838
4157
|
tool: tool$1({
|
|
3839
4158
|
description: SHELL_TOOL_SHAPES[name].description,
|
|
3840
4159
|
inputSchema: z.object(SHELL_TOOL_SHAPES[name].shape),
|
|
3841
4160
|
execute: async (args) => {
|
|
3842
|
-
const output = await runShellTool(shells, selfId(), name, args);
|
|
4161
|
+
const output = await runShellTool(shells, selfId(), name, args, { write });
|
|
3843
4162
|
return output.isError ? { error: output.text } : { result: output.text };
|
|
3844
4163
|
}
|
|
3845
4164
|
})
|
|
@@ -4206,6 +4525,7 @@ function createEngineSession(options) {
|
|
|
4206
4525
|
onFileDelivered: options.capabilities?.deliverFiles === false || !isGranted("deliverFiles") ? void 0 : (file) => runner?.emitFileDelivered(file),
|
|
4207
4526
|
peers: options.config.peers,
|
|
4208
4527
|
shells: options.config.shells,
|
|
4528
|
+
shellWrite: options.config.shellAgentWrite !== void 0,
|
|
4209
4529
|
selfId: () => runner?.id ?? "pending"
|
|
4210
4530
|
});
|
|
4211
4531
|
const declaredServers = options.profile?.session?.mcpServers;
|
|
@@ -5148,6 +5468,28 @@ function codexAnswers(questions, answers) {
|
|
|
5148
5468
|
}
|
|
5149
5469
|
return out;
|
|
5150
5470
|
}
|
|
5471
|
+
const SHELL_WRITE_CHANNEL = {
|
|
5472
|
+
describe: (raw) => {
|
|
5473
|
+
const call = raw;
|
|
5474
|
+
const input = typeof call.arguments === "object" && call.arguments !== null ? call.arguments : {};
|
|
5475
|
+
return {
|
|
5476
|
+
toolName: call.tool,
|
|
5477
|
+
input,
|
|
5478
|
+
title: `Agent wants to run ${call.tool}`,
|
|
5479
|
+
displayName: call.tool
|
|
5480
|
+
};
|
|
5481
|
+
},
|
|
5482
|
+
itemId: (raw) => raw.callId,
|
|
5483
|
+
allow: (_raw, updatedInput) => ({ response: {
|
|
5484
|
+
allowed: true,
|
|
5485
|
+
updatedInput
|
|
5486
|
+
} }),
|
|
5487
|
+
deny: (_raw, _interrupt, _offered, message) => ({ response: {
|
|
5488
|
+
allowed: false,
|
|
5489
|
+
message
|
|
5490
|
+
} })
|
|
5491
|
+
};
|
|
5492
|
+
const SHELL_WRITE_GATE_MODES = /* @__PURE__ */ new Set(["default", "acceptEdits"]);
|
|
5151
5493
|
function decisionChannel(describe, itemId) {
|
|
5152
5494
|
return {
|
|
5153
5495
|
describe,
|
|
@@ -5368,6 +5710,7 @@ var CodexRunner = class {
|
|
|
5368
5710
|
cwd: this.#cwd,
|
|
5369
5711
|
profile: this.#config.profile,
|
|
5370
5712
|
engine: "codex",
|
|
5713
|
+
shellAgentWrite: this.#config.shells ? this.#config.shellAgentWrite : void 0,
|
|
5371
5714
|
capabilities: ENGINE_CAPABILITIES.codex,
|
|
5372
5715
|
model: this.#model ?? this.#resolvedModel,
|
|
5373
5716
|
permissionMode: this.#permissionMode,
|
|
@@ -5755,7 +6098,7 @@ var CodexRunner = class {
|
|
|
5755
6098
|
};
|
|
5756
6099
|
if (this.#model) options.model = this.#model;
|
|
5757
6100
|
if (this.#instructions !== void 0) options.developerInstructions = this.#instructions;
|
|
5758
|
-
const dynamic = [...this.#config.peers ? peerToolSpecs() : [], ...this.#config.shells ? shellToolSpecs() : []];
|
|
6101
|
+
const dynamic = [...this.#config.peers ? peerToolSpecs() : [], ...this.#config.shells ? shellToolSpecs(this.#config.shellAgentWrite !== void 0) : []];
|
|
5759
6102
|
if (dynamic.length) options.dynamicTools = dynamic.map((spec) => ({
|
|
5760
6103
|
type: "function",
|
|
5761
6104
|
...spec
|
|
@@ -6193,7 +6536,20 @@ var CodexRunner = class {
|
|
|
6193
6536
|
};
|
|
6194
6537
|
}
|
|
6195
6538
|
if (shells && isShellToolName(call.tool)) {
|
|
6196
|
-
const
|
|
6539
|
+
const write = this.#config.shellAgentWrite !== void 0;
|
|
6540
|
+
let args = call.arguments;
|
|
6541
|
+
if (write && shellToolNeedsCard(call.tool, this.#config.shellAgentWrite) && SHELL_WRITE_GATE_MODES.has(this.#permissionMode)) {
|
|
6542
|
+
const verdict = await this.#requestApproval(SHELL_WRITE_CHANNEL, method, call, void 0);
|
|
6543
|
+
if (!verdict.allowed) return {
|
|
6544
|
+
success: false,
|
|
6545
|
+
contentItems: [{
|
|
6546
|
+
type: "inputText",
|
|
6547
|
+
text: shellWriteDeniedText(call.tool, verdict.message)
|
|
6548
|
+
}]
|
|
6549
|
+
};
|
|
6550
|
+
args = verdict.updatedInput ?? args;
|
|
6551
|
+
}
|
|
6552
|
+
const output = await runShellTool(shells, this.id, call.tool, args, { write });
|
|
6197
6553
|
return {
|
|
6198
6554
|
success: !output.isError,
|
|
6199
6555
|
contentItems: [{
|
|
@@ -6292,7 +6648,7 @@ var CodexRunner = class {
|
|
|
6292
6648
|
message = "codex offered no plain accept for this request (only broader session/policy grants), denied instead";
|
|
6293
6649
|
sent = pending.channel.deny(pending.params, false, pending.offered);
|
|
6294
6650
|
}
|
|
6295
|
-
} else sent = pending.channel.deny(pending.params, decision.interrupt === true, pending.offered);
|
|
6651
|
+
} else sent = pending.channel.deny(pending.params, decision.interrupt === true, pending.offered, message);
|
|
6296
6652
|
pending.respond(sent.response);
|
|
6297
6653
|
this.#emit({
|
|
6298
6654
|
type: "permission_resolved",
|
|
@@ -6962,6 +7318,6 @@ function getEngineAdapter(engine) {
|
|
|
6962
7318
|
return ADAPTERS[engine ?? "claude"];
|
|
6963
7319
|
}
|
|
6964
7320
|
//#endregion
|
|
6965
|
-
export { AiSdkRunner, BrowserBridgeExecutor, CLAUDE_CATALOG, CODEX_CATALOG, CodexRunner, CostLedger, DeferredExecutor, InputQueue, JsonRpcError, JsonRpcStdioConnection, LocalCommandQueue, PEER_MCP_SERVER, PEER_MESSAGE_MAX_CHARS, PEER_RECENT_DEFAULT, PEER_RECENT_MAX, PEER_TOOL_NAMES, PendingRequestRegistry, QuickJsExecutor, SHELL_REFUSAL, SHELL_TOOL_NAMES, SHELL_TOOL_SHAPES, SUPPORTED_ATTACHMENT_TYPES, SessionRunner, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, clampShellTail, claudeAdapter, codexAdapter, composeInstructions, connectAppServer, connectMcpTools, countLines, createEngineSession, createToolContext, createWebFetch, getEngineAdapter, headTail, htmlToMarkdown, installPeerDirectory, installShellDirectory, installedPeerDirectory, installedShellDirectory, isHostAllowed, isLocalShellSource, isPrivateAddress, isShellToolName, isSlashCommand, listCodexSessions, localCommandContext, localCommandEvent, localCommandTranscript, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, peerDirectoryHandle, peerMentionsEnvelope, peerMessageEnvelope, peerSummary, peerToolSpecs, providerAdapter, recentLines, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, resolveInstructions, runPeerTool, runShellTool, shellContextText, shellDirectoryHandle, shellInlineText, shellReadText, shellSummary, shellTail, shellToolSpecs, splitLines, toApiMessage, toExecutionResult, truncateResultBlocks, ttyText, withHostTools, withMcpTools, withPeerContext };
|
|
7321
|
+
export { AiSdkRunner, BrowserBridgeExecutor, CLAUDE_CATALOG, CODEX_CATALOG, CodexRunner, CostLedger, DeferredExecutor, InputQueue, JsonRpcError, JsonRpcStdioConnection, LocalCommandQueue, PEER_MCP_SERVER, PEER_MESSAGE_MAX_CHARS, PEER_RECENT_DEFAULT, PEER_RECENT_MAX, PEER_TOOL_NAMES, PendingRequestRegistry, QuickJsExecutor, SHELL_KEYS_MAX, SHELL_KEY_NAMES, SHELL_READ_TOOL_NAMES, SHELL_REFUSAL, SHELL_TOOL_NAMES, SHELL_TOOL_SHAPES, SHELL_WRITE_REFUSAL, SHELL_WRITE_TOOL_NAMES, SUPPORTED_ATTACHMENT_TYPES, SessionRunner, TTY_REDRAW_CARRY, agentMayWrite, attachmentContentBlocks, attachmentKind, attachmentRef, checkClaudeAuth, clampShellTail, claudeAdapter, codexAdapter, composeInstructions, connectAppServer, connectMcpTools, countLines, createEngineSession, createToolContext, createWebFetch, encodeShellKey, encodeShellKeys, getEngineAdapter, headTail, htmlToMarkdown, installPeerDirectory, installShellDirectory, installedPeerDirectory, installedShellDirectory, isHostAllowed, isLocalShellSource, isPrivateAddress, isShellToolName, isShellWriteToolName, isSlashCommand, listCodexSessions, localCommandContext, localCommandEvent, localCommandTranscript, mcpStatusInfo, modelOptionsFromSdk, normalizeMediaType, normalizeSdkMessage, peerDirectoryHandle, peerMentionsEnvelope, peerMessageEnvelope, peerSummary, peerToolSpecs, providerAdapter, recentLines, replaySlice, resolveBundledClaudeExecutable, resolveBundledCodexExecutable, resolveInstructions, runPeerTool, runShellTool, shellContextText, shellDirectoryHandle, shellInlineText, shellKillText, shellOwnershipRefusal, shellReadText, shellSummary, shellTail, shellToolNames, shellToolNeedsCard, shellToolOf, shellToolSpecs, shellWriteDeniedText, shellWriteToolOf, splitLines, toApiMessage, toExecutionResult, truncateResultBlocks, ttyRedraws, ttyText, withHostTools, withMcpTools, withPeerContext };
|
|
6966
7322
|
|
|
6967
7323
|
//# sourceMappingURL=index.mjs.map
|