agent-sh 0.14.0 → 0.14.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 +7 -18
- package/dist/agent/agent-loop.d.ts +1 -1
- package/dist/agent/agent-loop.js +42 -31
- package/dist/agent/conversation-state.d.ts +3 -2
- package/dist/agent/conversation-state.js +20 -3
- package/dist/agent/events.d.ts +2 -0
- package/dist/agent/host-types.d.ts +3 -0
- package/dist/agent/index.js +2 -1
- package/dist/agent/llm-client.js +1 -0
- package/dist/agent/subagent.d.ts +1 -1
- package/dist/agent/subagent.js +5 -1
- package/dist/agent/tool-protocol.d.ts +2 -2
- package/dist/agent/tool-protocol.js +5 -4
- package/dist/agent/tools/glob.d.ts +1 -1
- package/dist/agent/tools/glob.js +4 -2
- package/dist/agent/tools/grep.d.ts +1 -1
- package/dist/agent/tools/grep.js +4 -2
- package/dist/agent/tools/ls.d.ts +1 -1
- package/dist/agent/tools/ls.js +4 -2
- package/dist/agent/tools/read-file.d.ts +1 -1
- package/dist/agent/tools/read-file.js +30 -2
- package/dist/agent/types.d.ts +13 -3
- package/dist/agent/types.js +6 -1
- package/dist/cli/args.js +3 -1
- package/dist/cli/index.js +0 -0
- package/dist/cli/install.d.ts +1 -0
- package/dist/cli/install.js +86 -2
- package/dist/cli/subcommands.js +4 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/settings.d.ts +3 -0
- package/dist/core/settings.js +2 -2
- package/dist/shell/index.d.ts +6 -0
- package/dist/shell/index.js +10 -10
- package/dist/shell/shell.d.ts +4 -0
- package/dist/shell/shell.js +15 -29
- package/dist/shell/terminal.d.ts +33 -0
- package/dist/shell/terminal.js +62 -0
- package/dist/utils/tool-interactive.js +4 -2
- package/examples/extensions/ash-scheme/index.ts +2170 -0
- package/examples/extensions/ash-scheme/package.json +11 -0
- package/examples/extensions/ash-scheme-render.ts +58 -0
- package/examples/extensions/ashi/README.md +36 -26
- package/examples/extensions/ashi/package.json +9 -1
- package/examples/extensions/ashi/src/capture.ts +1 -0
- package/examples/extensions/ashi/src/cli.ts +25 -8
- package/examples/extensions/ashi/src/compaction.ts +25 -96
- package/examples/extensions/ashi/src/components.ts +64 -166
- package/examples/extensions/ashi/src/default-schema-renderers.ts +229 -0
- package/examples/extensions/ashi/src/display-config.ts +21 -22
- package/examples/extensions/ashi/src/frontend.ts +64 -65
- package/examples/extensions/ashi/src/hooks.ts +47 -63
- package/examples/extensions/ashi/src/multi-session-store.ts +44 -3
- package/examples/extensions/ashi/src/schema.ts +407 -0
- package/examples/extensions/ashi/src/session-store.ts +55 -4
- package/examples/extensions/ashi/src/status-footer.ts +27 -6
- package/examples/extensions/ashi-compact-llm.ts +93 -0
- package/examples/extensions/claude-code-bridge/index.ts +9 -2
- package/examples/extensions/claude-code-bridge/package.json +1 -1
- package/examples/extensions/opencode-bridge/index.ts +208 -53
- package/examples/extensions/opencode-bridge/package.json +1 -1
- package/examples/extensions/opencode-provider.ts +252 -0
- package/examples/extensions/pi-bridge/index.ts +1 -0
- package/package.json +12 -1
- package/examples/extensions/ashi/src/default-renderers.ts +0 -171
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-sh",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.2",
|
|
4
4
|
"description": "A shell-first terminal where AI is one keystroke away",
|
|
5
5
|
"type": "module",
|
|
6
|
+
"workspaces": [
|
|
7
|
+
"examples/extensions/*"
|
|
8
|
+
],
|
|
6
9
|
"main": "dist/core/index.js",
|
|
7
10
|
"types": "dist/core/index.d.ts",
|
|
8
11
|
"bin": {
|
|
@@ -38,6 +41,14 @@
|
|
|
38
41
|
"types": "./dist/shell/shell.d.ts",
|
|
39
42
|
"default": "./dist/shell/shell.js"
|
|
40
43
|
},
|
|
44
|
+
"./shell/strategies": {
|
|
45
|
+
"types": "./dist/shell/strategies/index.d.ts",
|
|
46
|
+
"default": "./dist/shell/strategies/index.js"
|
|
47
|
+
},
|
|
48
|
+
"./shell/terminal": {
|
|
49
|
+
"types": "./dist/shell/terminal.d.ts",
|
|
50
|
+
"default": "./dist/shell/terminal.js"
|
|
51
|
+
},
|
|
41
52
|
"./utils/stream-transform": {
|
|
42
53
|
"types": "./dist/utils/stream-transform.d.ts",
|
|
43
54
|
"default": "./dist/utils/stream-transform.js"
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
import { Container, Spacer, Text } from "@earendil-works/pi-tui";
|
|
2
|
-
import type { ExtensionContext } from "agent-sh/types";
|
|
3
|
-
import { theme } from "./theme.js";
|
|
4
|
-
import { GROUP_ICONS } from "./components.js";
|
|
5
|
-
import type { ToolCallArgs, ToolCallView } from "./hooks.js";
|
|
6
|
-
|
|
7
|
-
const TOOL_ICON: Record<string, string> = {
|
|
8
|
-
read_file: GROUP_ICONS.read!,
|
|
9
|
-
read: GROUP_ICONS.read!,
|
|
10
|
-
ls: GROUP_ICONS.read!,
|
|
11
|
-
grep: GROUP_ICONS.search!,
|
|
12
|
-
glob: GROUP_ICONS.search!,
|
|
13
|
-
edit: "✎",
|
|
14
|
-
edit_file: "✎",
|
|
15
|
-
write: "✎",
|
|
16
|
-
write_file: "✎",
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
function iconPrefix(name: string): string {
|
|
20
|
-
const icon = TOOL_ICON[name] ?? "⚙";
|
|
21
|
-
return `${theme.fg("warning", icon)} `;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
interface StatusOpts { exitCode: number | null; elapsedMs: number; summary?: string }
|
|
25
|
-
|
|
26
|
-
function fmtElapsed(ms: number): string {
|
|
27
|
-
if (ms < 1000) return `${ms}ms`;
|
|
28
|
-
if (ms < 10_000) return `${(ms / 1000).toFixed(2)}s`;
|
|
29
|
-
if (ms < 60_000) return `${(ms / 1000).toFixed(1)}s`;
|
|
30
|
-
const totalSeconds = Math.floor(ms / 1000);
|
|
31
|
-
const m = Math.floor(totalSeconds / 60);
|
|
32
|
-
const s = totalSeconds % 60;
|
|
33
|
-
return `${m}m ${s}s`;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function parseRaw(raw: unknown): Record<string, unknown> {
|
|
37
|
-
if (typeof raw === "string") {
|
|
38
|
-
try { return JSON.parse(raw) as Record<string, unknown>; } catch { return {}; }
|
|
39
|
-
}
|
|
40
|
-
if (raw && typeof raw === "object") return raw as Record<string, unknown>;
|
|
41
|
-
return {};
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
function str(v: unknown): string | undefined {
|
|
45
|
-
return typeof v === "string" && v.length > 0 ? v : undefined;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function num(v: unknown): number | undefined {
|
|
49
|
-
return typeof v === "number" && Number.isFinite(v) ? v : undefined;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function relativize(fp: string): string {
|
|
53
|
-
const home = process.env.HOME;
|
|
54
|
-
const cwd = process.cwd();
|
|
55
|
-
if (fp.startsWith(`${cwd}/`)) return fp.slice(cwd.length + 1);
|
|
56
|
-
if (home && fp.startsWith(`${home}/`)) return `~/${fp.slice(home.length + 1)}`;
|
|
57
|
-
return fp;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function statusSuffix(opts?: StatusOpts): string {
|
|
61
|
-
if (!opts) return ` ${theme.fg("muted", "…")}`;
|
|
62
|
-
const ok = opts.exitCode === null || opts.exitCode === 0;
|
|
63
|
-
const mark = ok ? theme.fg("success", "✓") : theme.fg("error", "✗");
|
|
64
|
-
const elapsed = opts.elapsedMs > 0 ? ` ${theme.fg("muted", fmtElapsed(opts.elapsedMs))}` : "";
|
|
65
|
-
const sum = opts.summary ? ` ${theme.fg("muted", opts.summary)}` : "";
|
|
66
|
-
return ` ${mark}${elapsed}${sum}`;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/** Renders a one-line tool call header from a label producer. The label is
|
|
70
|
-
* recomputed on setStatus so the trailing status mark updates in place. */
|
|
71
|
-
class LabeledCallLine extends Container implements ToolCallView {
|
|
72
|
-
private line: Text;
|
|
73
|
-
private status?: StatusOpts;
|
|
74
|
-
constructor(private label: () => string) {
|
|
75
|
-
super();
|
|
76
|
-
this.line = new Text("", 1, 0);
|
|
77
|
-
this.addChild(new Spacer(1));
|
|
78
|
-
this.addChild(this.line);
|
|
79
|
-
this.repaint();
|
|
80
|
-
}
|
|
81
|
-
setStatus(opts: StatusOpts): void {
|
|
82
|
-
this.status = opts;
|
|
83
|
-
this.repaint();
|
|
84
|
-
}
|
|
85
|
-
private repaint(): void {
|
|
86
|
-
this.line.setText(`${this.label()}${statusSuffix(this.status)}`);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
const bold = (t: string): string => theme.bold(theme.fg("toolTitle", t));
|
|
91
|
-
const accent = (t: string): string => theme.fg("accent", t);
|
|
92
|
-
const muted = (t: string): string => theme.fg("muted", t);
|
|
93
|
-
|
|
94
|
-
function bashLabel(args: ToolCallArgs): string {
|
|
95
|
-
const r = parseRaw(args.rawInput);
|
|
96
|
-
const command = str(r.command) ?? "…";
|
|
97
|
-
const timeout = num(r.timeout);
|
|
98
|
-
const to = timeout ? muted(` (timeout ${timeout}s)`) : "";
|
|
99
|
-
return `${bold("$")} ${accent(command)}${to}`;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
function readLabel(args: ToolCallArgs): string {
|
|
103
|
-
const r = parseRaw(args.rawInput);
|
|
104
|
-
const path = str(r.file_path) ?? str(r.path);
|
|
105
|
-
const offset = num(r.offset);
|
|
106
|
-
const limit = num(r.limit);
|
|
107
|
-
let range = "";
|
|
108
|
-
if (offset !== undefined || limit !== undefined) {
|
|
109
|
-
const from = offset ?? 1;
|
|
110
|
-
const to = limit !== undefined ? from + limit - 1 : undefined;
|
|
111
|
-
range = theme.fg("warning", to ? `:${from}-${to}` : `:${from}`);
|
|
112
|
-
}
|
|
113
|
-
return `${iconPrefix("read")}${bold("read")} ${accent(path ? relativize(path) : "…")}${range}`;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function grepLabel(args: ToolCallArgs): string {
|
|
117
|
-
const r = parseRaw(args.rawInput);
|
|
118
|
-
const pattern = str(r.pattern) ?? "…";
|
|
119
|
-
const scope = relativize(str(r.path) ?? ".");
|
|
120
|
-
const glob = str(r.glob);
|
|
121
|
-
const limit = num(r.limit);
|
|
122
|
-
const extras = [glob ? `(${glob})` : "", limit !== undefined ? `limit ${limit}` : ""].filter(Boolean).join(" ");
|
|
123
|
-
const tail = extras ? muted(` ${extras}`) : "";
|
|
124
|
-
return `${iconPrefix("grep")}${bold("grep")} ${accent(`/${pattern}/`)} ${muted(`in ${scope}`)}${tail}`;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function globLabel(args: ToolCallArgs): string {
|
|
128
|
-
const r = parseRaw(args.rawInput);
|
|
129
|
-
const pattern = str(r.pattern) ?? "…";
|
|
130
|
-
const scope = relativize(str(r.path) ?? ".");
|
|
131
|
-
return `${iconPrefix("glob")}${bold("glob")} ${accent(pattern)} ${muted(`in ${scope}`)}`;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function lsLabel(args: ToolCallArgs): string {
|
|
135
|
-
const r = parseRaw(args.rawInput);
|
|
136
|
-
const p = str(r.path) ?? ".";
|
|
137
|
-
return `${iconPrefix("ls")}${bold("ls")} ${accent(relativize(p))}`;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function pathOnlyLabel(name: string, args: ToolCallArgs): string {
|
|
141
|
-
const r = parseRaw(args.rawInput);
|
|
142
|
-
const path = str(r.file_path) ?? str(r.path);
|
|
143
|
-
return `${iconPrefix(name)}${bold(name)} ${accent(path ? relativize(path) : "…")}`;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
function genericLabel(args: ToolCallArgs): string {
|
|
147
|
-
const detail = args.displayDetail ? ` ${muted(args.displayDetail)}` : "";
|
|
148
|
-
return `${iconPrefix(args.name)}${bold(args.title)}${detail}`;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
export function registerDefaultToolRenderers(ctx: ExtensionContext): void {
|
|
152
|
-
const define = (name: string, fn: (args: ToolCallArgs) => ToolCallView): void => {
|
|
153
|
-
ctx.define(`ashi:render-tool-call:${name}`, fn);
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
define("bash", (args) => new LabeledCallLine(() => bashLabel(args)));
|
|
157
|
-
|
|
158
|
-
define("read_file", (args) => new LabeledCallLine(() => readLabel(args)));
|
|
159
|
-
define("read", (args) => new LabeledCallLine(() => readLabel(args)));
|
|
160
|
-
|
|
161
|
-
define("grep", (args) => new LabeledCallLine(() => grepLabel(args)));
|
|
162
|
-
define("glob", (args) => new LabeledCallLine(() => globLabel(args)));
|
|
163
|
-
define("ls", (args) => new LabeledCallLine(() => lsLabel(args)));
|
|
164
|
-
|
|
165
|
-
define("edit_file", (args) => new LabeledCallLine(() => pathOnlyLabel("edit", args)));
|
|
166
|
-
define("edit", (args) => new LabeledCallLine(() => pathOnlyLabel("edit", args)));
|
|
167
|
-
define("write_file", (args) => new LabeledCallLine(() => pathOnlyLabel("write", args)));
|
|
168
|
-
define("write", (args) => new LabeledCallLine(() => pathOnlyLabel("write", args)));
|
|
169
|
-
|
|
170
|
-
define("default", (args) => new LabeledCallLine(() => genericLabel(args)));
|
|
171
|
-
}
|