agent-sh 0.10.0 → 0.10.2
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/README.md +12 -9
- package/dist/agent/agent-loop.d.ts +0 -3
- package/dist/agent/agent-loop.js +18 -35
- package/dist/agent/conversation-state.js +8 -2
- package/dist/agent/nuclear-form.d.ts +2 -0
- package/dist/agent/nuclear-form.js +11 -1
- package/dist/agent/system-prompt.js +1 -1
- package/dist/agent/token-budget.d.ts +8 -12
- package/dist/agent/token-budget.js +5 -40
- package/dist/agent/tool-registry.js +6 -0
- package/dist/agent/types.d.ts +3 -1
- package/dist/context-manager.d.ts +1 -21
- package/dist/context-manager.js +26 -163
- package/dist/event-bus.d.ts +0 -1
- package/dist/extension-loader.js +25 -4
- package/dist/extensions/agent-backend.js +3 -2
- package/dist/extensions/index.js +0 -1
- package/dist/extensions/tui-renderer.js +47 -29
- package/dist/settings.d.ts +3 -11
- package/dist/settings.js +0 -4
- package/dist/shell/input-handler.js +14 -9
- package/dist/types.d.ts +3 -0
- package/dist/utils/ansi.d.ts +6 -1
- package/dist/utils/ansi.js +114 -7
- package/dist/utils/box-frame.js +8 -2
- package/dist/utils/llm-client.d.ts +4 -0
- package/dist/utils/llm-client.js +8 -0
- package/dist/utils/markdown.d.ts +4 -0
- package/dist/utils/markdown.js +136 -48
- package/dist/utils/package-version.d.ts +1 -0
- package/dist/utils/package-version.js +10 -0
- package/dist/utils/shell-output-spill.d.ts +2 -0
- package/dist/utils/shell-output-spill.js +81 -0
- package/examples/extensions/claude-code-bridge/README.md +14 -0
- package/examples/extensions/claude-code-bridge/index.ts +13 -101
- package/examples/extensions/pi-bridge/README.md +16 -0
- package/examples/extensions/pi-bridge/index.ts +8 -154
- package/package.json +9 -1
- package/dist/extensions/shell-recall.d.ts +0 -9
- package/dist/extensions/shell-recall.js +0 -8
|
@@ -2,8 +2,14 @@
|
|
|
2
2
|
* Claude Code bridge — runs Claude Code Agent SDK in-process as agent-sh's backend.
|
|
3
3
|
*
|
|
4
4
|
* Uses the official @anthropic-ai/claude-agent-sdk to spawn a Claude Code
|
|
5
|
-
* session
|
|
6
|
-
*
|
|
5
|
+
* session. Claude Code handles its own model selection, tool execution, and
|
|
6
|
+
* permissions — the bridge is a pure protocol translator between the SDK's
|
|
7
|
+
* event stream and agent-sh's bus events.
|
|
8
|
+
*
|
|
9
|
+
* PTY-access tools (`terminal_read`, `terminal_keys`, `user_shell`) are
|
|
10
|
+
* intentionally NOT bundled here. If you want Claude Code to observe or
|
|
11
|
+
* drive the user's live terminal, load a companion extension that
|
|
12
|
+
* registers those tools as MCP tools the SDK can consume.
|
|
7
13
|
*
|
|
8
14
|
* Setup (from repo root):
|
|
9
15
|
* npm run build && npm link # register local agent-sh globally
|
|
@@ -15,103 +21,16 @@
|
|
|
15
21
|
*
|
|
16
22
|
* Requires: Claude Code CLI installed and authenticated (claude login).
|
|
17
23
|
*/
|
|
18
|
-
import {
|
|
19
|
-
query,
|
|
20
|
-
tool,
|
|
21
|
-
createSdkMcpServer,
|
|
22
|
-
type Query,
|
|
23
|
-
} from "@anthropic-ai/claude-agent-sdk";
|
|
24
|
-
import { z } from "zod";
|
|
24
|
+
import { query, type Query } from "@anthropic-ai/claude-agent-sdk";
|
|
25
25
|
import { readFile } from "node:fs/promises";
|
|
26
26
|
import { resolve } from "node:path";
|
|
27
27
|
import type { ExtensionContext } from "agent-sh/types";
|
|
28
|
-
import type { EventBus } from "agent-sh/event-bus";
|
|
29
28
|
import { computeDiff, type DiffResult } from "agent-sh/utils/diff";
|
|
30
29
|
|
|
31
|
-
// ── Helpers ──────────────────────────────────────────────────────
|
|
32
|
-
function interpretEscapes(str: string): string {
|
|
33
|
-
return str.replace(/\\(x[0-9a-fA-F]{2}|r|n|t|\\|0)/g, (_, seq: string) => {
|
|
34
|
-
if (seq === "r") return "\r";
|
|
35
|
-
if (seq === "n") return "\n";
|
|
36
|
-
if (seq === "t") return "\t";
|
|
37
|
-
if (seq === "\\") return "\\";
|
|
38
|
-
if (seq === "0") return "\0";
|
|
39
|
-
if (seq.startsWith("x")) return String.fromCharCode(parseInt(seq.slice(1), 16));
|
|
40
|
-
return seq;
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function settle(ms = 100): Promise<void> {
|
|
45
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// ── terminal_read MCP tool ────────────────────────────────────────
|
|
49
|
-
function createTerminalReadTool(ctx: ExtensionContext) {
|
|
50
|
-
return tool(
|
|
51
|
-
"terminal_read",
|
|
52
|
-
"Read the current terminal screen contents. Returns clean text (ANSI stripped) " +
|
|
53
|
-
"with cursor position and whether an alternate-screen program (vim, htop, less) is active. " +
|
|
54
|
-
"Use this to see what the user sees before sending keystrokes with terminal_keys.",
|
|
55
|
-
{},
|
|
56
|
-
async () => {
|
|
57
|
-
const tb = ctx.terminalBuffer;
|
|
58
|
-
if (!tb) return { content: [{ type: "text" as const, text: "terminal buffer not available" }] };
|
|
59
|
-
const { text, altScreen, cursorX, cursorY } = tb.readScreen();
|
|
60
|
-
const info = [
|
|
61
|
-
altScreen ? "mode: alternate screen" : "mode: normal",
|
|
62
|
-
`cursor: row=${cursorY} col=${cursorX}`,
|
|
63
|
-
].join(", ");
|
|
64
|
-
return { content: [{ type: "text" as const, text: `[${info}]\n\n${text}` }] };
|
|
65
|
-
},
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// ── terminal_keys MCP tool ───────────────────────────────────────
|
|
70
|
-
function createTerminalKeysTool(bus: EventBus, ctx: ExtensionContext) {
|
|
71
|
-
return tool(
|
|
72
|
-
"terminal_keys",
|
|
73
|
-
"Send keystrokes to the user's live terminal. The keys are written directly to the PTY " +
|
|
74
|
-
"as if the user typed them. Use escape sequences for special keys:\n" +
|
|
75
|
-
" - Escape: \\x1b - Enter: \\r - Tab: \\t\n" +
|
|
76
|
-
" - Ctrl+C: \\x03 - Arrow keys: \\x1b[A/B/C/D - Backspace: \\x7f\n" +
|
|
77
|
-
"Example: to quit vim without saving, send keys=\"\\x1b:q!\\r\".\n" +
|
|
78
|
-
"Always call terminal_read after sending keys to verify the result.",
|
|
79
|
-
{
|
|
80
|
-
keys: z.string().describe("Keystrokes to send (use \\x1b for Escape, \\r for Enter, etc.)"),
|
|
81
|
-
settle_ms: z.number().optional().describe("Wait time in ms after sending keys (default: 150)"),
|
|
82
|
-
},
|
|
83
|
-
async (args) => {
|
|
84
|
-
const keys = interpretEscapes(args.keys);
|
|
85
|
-
const settleMs = args.settle_ms ?? 150;
|
|
86
|
-
bus.emit("shell:stdout-show", {});
|
|
87
|
-
process.stdout.write("\n");
|
|
88
|
-
bus.emit("shell:pty-write", { data: keys });
|
|
89
|
-
await settle(settleMs);
|
|
90
|
-
|
|
91
|
-
const tb = ctx.terminalBuffer;
|
|
92
|
-
if (!tb) return { content: [{ type: "text" as const, text: "Keys sent." }] };
|
|
93
|
-
const { text, altScreen, cursorX, cursorY } = tb.readScreen();
|
|
94
|
-
const info = [
|
|
95
|
-
altScreen ? "mode: alternate screen" : "mode: normal",
|
|
96
|
-
`cursor: row=${cursorY} col=${cursorX}`,
|
|
97
|
-
].join(", ");
|
|
98
|
-
return { content: [{ type: "text" as const, text: `Keys sent. Screen after:\n[${info}]\n\n${text}` }] };
|
|
99
|
-
},
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
30
|
// ── Extension entry point ─────────────────────────────────────────
|
|
104
31
|
export default function activate(ctx: ExtensionContext): void {
|
|
105
32
|
const { bus } = ctx;
|
|
106
33
|
|
|
107
|
-
const termReadTool = createTerminalReadTool(ctx);
|
|
108
|
-
const termKeysTool = createTerminalKeysTool(bus, ctx);
|
|
109
|
-
const shellServer = createSdkMcpServer({
|
|
110
|
-
name: "agent-sh",
|
|
111
|
-
version: "1.0.0",
|
|
112
|
-
tools: [termReadTool, termKeysTool],
|
|
113
|
-
});
|
|
114
|
-
|
|
115
34
|
let activeQuery: Query | null = null;
|
|
116
35
|
const listeners: Array<{ event: string; fn: Function }> = [];
|
|
117
36
|
|
|
@@ -119,11 +38,11 @@ export default function activate(ctx: ExtensionContext): void {
|
|
|
119
38
|
|
|
120
39
|
/** Map Claude Code tool names to agent-sh display kinds. */
|
|
121
40
|
function toolKind(name: string): string {
|
|
122
|
-
if (name === "Read"
|
|
41
|
+
if (name === "Read") return "read";
|
|
123
42
|
if (name === "Edit") return "edit";
|
|
124
43
|
if (name === "Write") return "write";
|
|
125
44
|
if (name === "Glob" || name === "Grep") return "search";
|
|
126
|
-
if (name === "Bash"
|
|
45
|
+
if (name === "Bash") return "execute";
|
|
127
46
|
return "execute";
|
|
128
47
|
}
|
|
129
48
|
|
|
@@ -150,7 +69,6 @@ export default function activate(ctx: ExtensionContext): void {
|
|
|
150
69
|
if (name === "Bash") return `$ ${str(input.command)}`;
|
|
151
70
|
if (name === "Read" || name === "Edit" || name === "Write") return str(input.file_path ?? input.path);
|
|
152
71
|
if (name === "Grep" || name === "Glob") return `${str(input.pattern)} ${str(input.path)}`.trim();
|
|
153
|
-
if (name.includes("terminal_keys")) return str(input.keys);
|
|
154
72
|
return name;
|
|
155
73
|
}
|
|
156
74
|
|
|
@@ -180,15 +98,9 @@ export default function activate(ctx: ExtensionContext): void {
|
|
|
180
98
|
preset: "claude_code",
|
|
181
99
|
append:
|
|
182
100
|
"You are running inside agent-sh, a terminal wrapper.\n" +
|
|
183
|
-
"Use your standard tools (Read, Edit, Write, Bash, Glob, Grep) for investigation
|
|
184
|
-
"Use mcp__agent-sh__terminal_read and mcp__agent-sh__terminal_keys to observe and interact with the user's live terminal.",
|
|
101
|
+
"Use your standard tools (Read, Edit, Write, Bash, Glob, Grep) for investigation.",
|
|
185
102
|
},
|
|
186
|
-
|
|
187
|
-
allowedTools: [
|
|
188
|
-
"mcp__agent-sh__terminal_read",
|
|
189
|
-
"mcp__agent-sh__terminal_keys",
|
|
190
|
-
"Read", "Edit", "Write", "Bash", "Glob", "Grep",
|
|
191
|
-
],
|
|
103
|
+
allowedTools: ["Read", "Edit", "Write", "Bash", "Glob", "Grep"],
|
|
192
104
|
permissionMode: "acceptEdits",
|
|
193
105
|
includePartialMessages: true,
|
|
194
106
|
},
|
|
@@ -33,3 +33,19 @@ Or switch at runtime:
|
|
|
33
33
|
|
|
34
34
|
- pi must be configured separately (`~/.pi/settings.json`) with API keys and model preferences
|
|
35
35
|
- agent-sh does not override pi's configuration — it uses whatever pi is set up with
|
|
36
|
+
|
|
37
|
+
## What this bridge is
|
|
38
|
+
|
|
39
|
+
A pure protocol translator between pi's event stream and agent-sh's bus events. Pi's built-in tools (command execution, file ops, etc.) are used exactly as pi ships them. The bridge adds no tools of its own.
|
|
40
|
+
|
|
41
|
+
## What this bridge intentionally does NOT bundle
|
|
42
|
+
|
|
43
|
+
Three PTY-access tools are left out on purpose:
|
|
44
|
+
|
|
45
|
+
- `terminal_read` — observe the user's live terminal screen
|
|
46
|
+
- `terminal_keys` — send keystrokes to the user's PTY
|
|
47
|
+
- `user_shell` — run commands in the user's live shell with lasting `cd`/`export`/`source` effects
|
|
48
|
+
|
|
49
|
+
These are opt-in capabilities that belong in their own extensions. If you want any of them with pi, write a small companion extension that registers the tool as a pi `ToolDefinition` (TypeBox schema, wired to the relevant bus event: `shell:pty-write`, `shell:exec-request`, or `ctx.terminalBuffer.readScreen()`) and load it alongside pi-bridge.
|
|
50
|
+
|
|
51
|
+
Keeping this split means the bridge stays narrow — only translating events — and the capability surface is composable per-backend.
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
* provider settings, extensions, session management, and tool system.
|
|
6
6
|
* Agent-sh provides the shell frontend and TUI rendering.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* The bridge is a pure protocol translator between pi's event stream and
|
|
9
|
+
* agent-sh's bus events. Pi brings its own tools for command execution,
|
|
10
|
+
* file ops, etc. PTY-access tools (`terminal_read`, `terminal_keys`,
|
|
11
|
+
* `user_shell`) are intentionally NOT bundled here — if you want pi to
|
|
12
|
+
* observe or mutate the user's live terminal, load a companion extension
|
|
13
|
+
* that registers those tools in pi's ToolDefinition format.
|
|
11
14
|
*
|
|
12
15
|
* Setup:
|
|
13
16
|
* npm install @mariozechner/pi-agent-core @mariozechner/pi-ai @mariozechner/pi-coding-agent
|
|
@@ -22,157 +25,13 @@ import {
|
|
|
22
25
|
createAgentSessionRuntime,
|
|
23
26
|
SessionManager,
|
|
24
27
|
} from "@mariozechner/pi-coding-agent";
|
|
25
|
-
import { Type } from "@sinclair/typebox";
|
|
26
28
|
import type { ExtensionContext } from "agent-sh/types";
|
|
27
|
-
import type { EventBus } from "agent-sh/event-bus";
|
|
28
|
-
|
|
29
|
-
// ── Helpers ──────────────────────────────────────────────────────
|
|
30
|
-
function interpretEscapes(str: string): string {
|
|
31
|
-
return str.replace(/\\(x[0-9a-fA-F]{2}|r|n|t|\\|0)/g, (_, seq: string) => {
|
|
32
|
-
if (seq === "r") return "\r";
|
|
33
|
-
if (seq === "n") return "\n";
|
|
34
|
-
if (seq === "t") return "\t";
|
|
35
|
-
if (seq === "\\") return "\\";
|
|
36
|
-
if (seq === "0") return "\0";
|
|
37
|
-
if (seq.startsWith("x")) return String.fromCharCode(parseInt(seq.slice(1), 16));
|
|
38
|
-
return seq;
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function settle(ms = 100): Promise<void> {
|
|
43
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// ── user_shell as a pi ToolDefinition ─────────────────────────────
|
|
47
|
-
function createUserShellToolDef(bus: EventBus) {
|
|
48
|
-
// Track agent-sh's live cwd so user_shell always runs in the right place
|
|
49
|
-
let liveCwd = process.cwd();
|
|
50
|
-
bus.on("shell:cwd-change", ({ cwd }) => { liveCwd = cwd; });
|
|
51
|
-
|
|
52
|
-
const schema = Type.Object({
|
|
53
|
-
command: Type.String({ description: "Command to execute in user's shell" }),
|
|
54
|
-
return_output: Type.Optional(
|
|
55
|
-
Type.Boolean({
|
|
56
|
-
description:
|
|
57
|
-
"Whether to return the command output. Default false — output is shown directly to the user.",
|
|
58
|
-
}),
|
|
59
|
-
),
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
return {
|
|
63
|
-
name: "user_shell",
|
|
64
|
-
label: "user_shell",
|
|
65
|
-
description:
|
|
66
|
-
"Run a command with lasting effects in the user's live shell (cd, export, " +
|
|
67
|
-
"install packages, start servers) or show output the user wants to see. " +
|
|
68
|
-
"Output is shown directly to the user. Set return_output=true only " +
|
|
69
|
-
"if you need to inspect the result.",
|
|
70
|
-
promptSnippet: "Execute commands in the user's live terminal (PTY).",
|
|
71
|
-
promptGuidelines: [
|
|
72
|
-
"You are running inside agent-sh, a terminal wrapper.",
|
|
73
|
-
"Use your standard tools (bash, file ops) for investigation — output goes to you, not the user.",
|
|
74
|
-
"Use user_shell to run commands in the user's live shell when they ask to see output or need lasting effects (cd, install, start servers).",
|
|
75
|
-
"Default to standard tools. Use user_shell when the user is the intended audience for the output or the command has real effects.",
|
|
76
|
-
],
|
|
77
|
-
parameters: schema,
|
|
78
|
-
|
|
79
|
-
async execute(_toolCallId, params) {
|
|
80
|
-
const command = params.command;
|
|
81
|
-
const returnOutput = params.return_output ?? false;
|
|
82
|
-
|
|
83
|
-
const result = await bus.emitPipeAsync("shell:exec-request", {
|
|
84
|
-
command,
|
|
85
|
-
output: "",
|
|
86
|
-
cwd: liveCwd,
|
|
87
|
-
done: false,
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const text = returnOutput
|
|
91
|
-
? result.output || "(no output)"
|
|
92
|
-
: "Command executed.";
|
|
93
|
-
|
|
94
|
-
return { content: [{ type: "text", text }], details: undefined };
|
|
95
|
-
},
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// ── terminal_read as a pi ToolDefinition ─────────────────────────
|
|
100
|
-
function createTerminalReadToolDef(ctx: ExtensionContext) {
|
|
101
|
-
return {
|
|
102
|
-
name: "terminal_read",
|
|
103
|
-
label: "terminal_read",
|
|
104
|
-
description:
|
|
105
|
-
"Read the current terminal screen contents. Returns clean text (ANSI stripped) " +
|
|
106
|
-
"with cursor position and whether an alternate-screen program (vim, htop, less) is active.",
|
|
107
|
-
promptSnippet: "Read the terminal screen to see what the user sees.",
|
|
108
|
-
promptGuidelines: [
|
|
109
|
-
"Use terminal_read to see the current terminal screen before sending keystrokes.",
|
|
110
|
-
"Check altScreen to know if a full-screen program (vim, htop) is running.",
|
|
111
|
-
],
|
|
112
|
-
parameters: Type.Object({}),
|
|
113
|
-
async execute() {
|
|
114
|
-
const tb = ctx.terminalBuffer;
|
|
115
|
-
if (!tb) return { content: [{ type: "text", text: "terminal buffer not available" }], details: undefined };
|
|
116
|
-
const { text, altScreen, cursorX, cursorY } = tb.readScreen();
|
|
117
|
-
const info = [
|
|
118
|
-
altScreen ? "mode: alternate screen" : "mode: normal",
|
|
119
|
-
`cursor: row=${cursorY} col=${cursorX}`,
|
|
120
|
-
].join(", ");
|
|
121
|
-
return { content: [{ type: "text", text: `[${info}]\n\n${text}` }], details: undefined };
|
|
122
|
-
},
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// ── terminal_keys as a pi ToolDefinition ─────────────────────────
|
|
127
|
-
function createTerminalKeysToolDef(bus: EventBus, ctx: ExtensionContext) {
|
|
128
|
-
return {
|
|
129
|
-
name: "terminal_keys",
|
|
130
|
-
label: "terminal_keys",
|
|
131
|
-
description:
|
|
132
|
-
"Send keystrokes to the user's live terminal as if the user typed them. " +
|
|
133
|
-
"Use escape sequences: \\x1b for Escape, \\r for Enter, \\t for Tab, " +
|
|
134
|
-
"\\x03 for Ctrl+C, \\x1b[A/B/C/D for arrow keys, \\x7f for Backspace. " +
|
|
135
|
-
"Example: \\x1b:q!\\r to quit vim. Always call terminal_read after.",
|
|
136
|
-
promptSnippet: "Send keystrokes to interactive programs in the terminal.",
|
|
137
|
-
promptGuidelines: [
|
|
138
|
-
"Use terminal_keys to type into interactive programs (vim, htop, less).",
|
|
139
|
-
"Always call terminal_read after sending keys to verify the result.",
|
|
140
|
-
],
|
|
141
|
-
parameters: Type.Object({
|
|
142
|
-
keys: Type.String({ description: "Keystrokes to send (use \\x1b for Escape, \\r for Enter, etc.)" }),
|
|
143
|
-
settle_ms: Type.Optional(
|
|
144
|
-
Type.Number({ description: "Wait time in ms after sending keys (default: 150)" }),
|
|
145
|
-
),
|
|
146
|
-
}),
|
|
147
|
-
async execute(_toolCallId: string, params: any) {
|
|
148
|
-
const keys = interpretEscapes(params.keys);
|
|
149
|
-
const settleMs = params.settle_ms ?? 150;
|
|
150
|
-
bus.emit("shell:stdout-show", {});
|
|
151
|
-
process.stdout.write("\n");
|
|
152
|
-
bus.emit("shell:pty-write", { data: keys });
|
|
153
|
-
await settle(settleMs);
|
|
154
|
-
|
|
155
|
-
const tb = ctx.terminalBuffer;
|
|
156
|
-
if (!tb) return { content: [{ type: "text", text: "Keys sent." }], details: undefined };
|
|
157
|
-
const { text, altScreen, cursorX, cursorY } = tb.readScreen();
|
|
158
|
-
const info = [
|
|
159
|
-
altScreen ? "mode: alternate screen" : "mode: normal",
|
|
160
|
-
`cursor: row=${cursorY} col=${cursorX}`,
|
|
161
|
-
].join(", ");
|
|
162
|
-
return { content: [{ type: "text", text: `Keys sent. Screen after:\n[${info}]\n\n${text}` }], details: undefined };
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
29
|
|
|
167
30
|
// ── Extension entry point ─────────────────────────────────────────
|
|
168
31
|
export default function activate(ctx: ExtensionContext): void {
|
|
169
32
|
const { bus } = ctx;
|
|
170
33
|
const cwd = process.cwd();
|
|
171
34
|
|
|
172
|
-
const userShellTool = createUserShellToolDef(bus);
|
|
173
|
-
const termReadTool = createTerminalReadToolDef(ctx);
|
|
174
|
-
const termKeysTool = createTerminalKeysToolDef(bus, ctx);
|
|
175
|
-
|
|
176
35
|
// ── Boot pi session (async — register backend synchronously first) ──
|
|
177
36
|
let session: any = null;
|
|
178
37
|
let runtime: any = null;
|
|
@@ -190,7 +49,6 @@ export default function activate(ctx: ExtensionContext): void {
|
|
|
190
49
|
const result = await createAgentSessionFromServices({
|
|
191
50
|
services,
|
|
192
51
|
sessionManager: opts.sessionManager ?? sessionManager,
|
|
193
|
-
customTools: [userShellTool, termReadTool, termKeysTool],
|
|
194
52
|
});
|
|
195
53
|
return { ...result, services };
|
|
196
54
|
};
|
|
@@ -227,9 +85,7 @@ export default function activate(ctx: ExtensionContext): void {
|
|
|
227
85
|
bus.emit("agent:tool-started", {
|
|
228
86
|
title: (event as any).toolName,
|
|
229
87
|
toolCallId: (event as any).toolCallId,
|
|
230
|
-
kind: (event as any).toolName === "
|
|
231
|
-
? "execute"
|
|
232
|
-
: "read",
|
|
88
|
+
kind: (event as any).toolName === "bash" ? "execute" : "read",
|
|
233
89
|
});
|
|
234
90
|
break;
|
|
235
91
|
|
|
@@ -251,9 +107,7 @@ export default function activate(ctx: ExtensionContext): void {
|
|
|
251
107
|
bus.emit("agent:tool-completed", {
|
|
252
108
|
toolCallId: (event as any).toolCallId,
|
|
253
109
|
exitCode: (event as any).isError ? 1 : 0,
|
|
254
|
-
kind: (event as any).toolName === "
|
|
255
|
-
? "execute"
|
|
256
|
-
: "read",
|
|
110
|
+
kind: (event as any).toolName === "bash" ? "execute" : "read",
|
|
257
111
|
});
|
|
258
112
|
break;
|
|
259
113
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-sh",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.2",
|
|
4
4
|
"description": "A shell-first terminal where AI is one keystroke away",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/core.js",
|
|
@@ -70,6 +70,14 @@
|
|
|
70
70
|
"types": "./dist/agent/token-budget.d.ts",
|
|
71
71
|
"default": "./dist/agent/token-budget.js"
|
|
72
72
|
},
|
|
73
|
+
"./agent/history-file": {
|
|
74
|
+
"types": "./dist/agent/history-file.d.ts",
|
|
75
|
+
"default": "./dist/agent/history-file.js"
|
|
76
|
+
},
|
|
77
|
+
"./agent/nuclear-form": {
|
|
78
|
+
"types": "./dist/agent/nuclear-form.d.ts",
|
|
79
|
+
"default": "./dist/agent/nuclear-form.js"
|
|
80
|
+
},
|
|
73
81
|
"./executor": {
|
|
74
82
|
"types": "./dist/executor.d.ts",
|
|
75
83
|
"default": "./dist/executor.js"
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shell recall extension.
|
|
3
|
-
*
|
|
4
|
-
* Intercepts __shell_recall terminal commands via the
|
|
5
|
-
* "agent:terminal-intercept" pipe, returning virtual output from
|
|
6
|
-
* ContextManager's recall API without spawning a subprocess.
|
|
7
|
-
*/
|
|
8
|
-
import type { ExtensionContext } from "../types.js";
|
|
9
|
-
export default function activate({ bus, contextManager }: ExtensionContext): void;
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export default function activate({ bus, contextManager }) {
|
|
2
|
-
bus.onPipe("agent:terminal-intercept", (payload) => {
|
|
3
|
-
if (!payload.command.trimStart().startsWith("__shell_recall"))
|
|
4
|
-
return payload;
|
|
5
|
-
const output = contextManager.handleRecallCommand(payload.command.trim());
|
|
6
|
-
return { ...payload, intercepted: true, output };
|
|
7
|
-
});
|
|
8
|
-
}
|