agent-sh 0.14.10 → 0.15.0

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.
Files changed (97) hide show
  1. package/README.md +36 -13
  2. package/dist/agent/agent-loop.d.ts +9 -17
  3. package/dist/agent/agent-loop.js +123 -150
  4. package/dist/agent/events.d.ts +10 -12
  5. package/dist/agent/host-types.d.ts +17 -11
  6. package/dist/agent/index.d.ts +1 -1
  7. package/dist/agent/index.js +76 -29
  8. package/dist/agent/live-view.d.ts +3 -3
  9. package/dist/agent/live-view.js +15 -7
  10. package/dist/agent/providers/deepseek.js +9 -1
  11. package/dist/agent/providers/openrouter.js +9 -0
  12. package/dist/agent/session-store.js +1 -1
  13. package/dist/agent/subagent.js +1 -1
  14. package/dist/agent/system-prompt.d.ts +7 -3
  15. package/dist/agent/system-prompt.js +11 -14
  16. package/dist/agent/tool-protocol.js +0 -7
  17. package/dist/cli/args.js +2 -1
  18. package/dist/cli/install.d.ts +1 -0
  19. package/dist/cli/install.js +39 -2
  20. package/dist/cli/subcommands.js +1 -0
  21. package/dist/core/event-bus.js +0 -2
  22. package/dist/core/extension-loader.js +3 -1
  23. package/dist/core/index.d.ts +1 -1
  24. package/dist/core/index.js +3 -2
  25. package/dist/extensions/slash-commands/index.js +16 -11
  26. package/dist/shell/events.d.ts +3 -0
  27. package/dist/shell/index.js +9 -0
  28. package/dist/shell/shell-context.d.ts +2 -2
  29. package/dist/shell/shell-context.js +26 -11
  30. package/dist/shell/shell.js +3 -0
  31. package/dist/shell/tui-renderer.js +0 -1
  32. package/dist/utils/diff-renderer.d.ts +4 -0
  33. package/dist/utils/diff-renderer.js +15 -27
  34. package/dist/utils/handler-registry.d.ts +1 -6
  35. package/dist/utils/handler-registry.js +1 -6
  36. package/dist/utils/line-editor.js +0 -2
  37. package/dist/utils/palette.js +4 -4
  38. package/dist/utils/terminal-buffer.d.ts +2 -0
  39. package/dist/utils/terminal-buffer.js +4 -0
  40. package/examples/extensions/ads/SKILL.md +170 -0
  41. package/examples/extensions/ash-acp-bridge/src/index.ts +11 -7
  42. package/examples/extensions/ash-scheme/index.ts +377 -687
  43. package/examples/extensions/ash-scheme/package.json +1 -1
  44. package/examples/extensions/ashi/EXTENDING.md +118 -0
  45. package/examples/extensions/ashi/README.md +26 -54
  46. package/examples/extensions/ashi/docs/ui-surface-protocol.md +163 -0
  47. package/examples/extensions/ashi/package.json +14 -2
  48. package/examples/extensions/ashi/src/autocomplete-controller.ts +95 -0
  49. package/examples/extensions/ashi/src/autocomplete.ts +1 -23
  50. package/examples/extensions/ashi/src/capture.ts +54 -10
  51. package/examples/extensions/ashi/src/chat/assistant.ts +67 -0
  52. package/examples/extensions/ashi/src/chat/lines.ts +39 -0
  53. package/examples/extensions/ashi/src/chat/thinking.ts +42 -0
  54. package/examples/extensions/ashi/src/chat/tool-group.ts +84 -0
  55. package/examples/extensions/ashi/src/chat/user-message.ts +20 -0
  56. package/examples/extensions/ashi/src/cli.ts +80 -12
  57. package/examples/extensions/ashi/src/clipboard-image.ts +41 -0
  58. package/examples/extensions/ashi/src/commands.ts +11 -1
  59. package/examples/extensions/ashi/src/dialogs.ts +67 -0
  60. package/examples/extensions/ashi/src/display-config.ts +16 -1
  61. package/examples/extensions/ashi/src/docks.ts +31 -0
  62. package/examples/extensions/ashi/src/events.ts +16 -0
  63. package/examples/extensions/ashi/src/frontend.ts +456 -268
  64. package/examples/extensions/ashi/src/hooks.ts +27 -40
  65. package/examples/extensions/ashi/src/input-prompt.ts +64 -0
  66. package/examples/extensions/ashi/src/renderer.ts +222 -0
  67. package/examples/extensions/ashi/src/renderers/pi-tui/app.ts +122 -0
  68. package/examples/extensions/ashi/src/renderers/pi-tui/index.ts +27 -0
  69. package/examples/extensions/ashi/src/renderers/pi-tui/nodes.ts +190 -0
  70. package/examples/extensions/ashi/src/renderers/pi-tui/schema-mount.ts +203 -0
  71. package/examples/extensions/ashi/src/renderers/pi-tui/theme-adapters.ts +48 -0
  72. package/examples/extensions/ashi/src/renderers/pi-tui/tool-group.ts +21 -0
  73. package/examples/extensions/ashi/src/schema.ts +46 -205
  74. package/examples/extensions/ashi/src/session-commands.ts +2 -1
  75. package/examples/extensions/ashi/src/status-footer.ts +35 -25
  76. package/examples/extensions/ashi/src/terminal-mode.ts +9 -0
  77. package/examples/extensions/ashi/src/theme.ts +1 -47
  78. package/examples/extensions/ashi/src/ui.ts +88 -0
  79. package/examples/extensions/ashi-ink/README.md +61 -0
  80. package/examples/extensions/ashi-ink/package.json +30 -0
  81. package/examples/extensions/ashi-ink/src/index.ts +6 -0
  82. package/examples/extensions/ashi-ink/src/ink-renderer.tsx +865 -0
  83. package/examples/extensions/ashi-ink/src/shims.d.ts +5 -0
  84. package/examples/extensions/ashi-ink/test/render.test.tsx +408 -0
  85. package/examples/extensions/ashi-ink/tsconfig.json +14 -0
  86. package/examples/extensions/ashi-scheme-render.ts +10 -10
  87. package/examples/extensions/ashi-shell-passthrough.ts +95 -0
  88. package/examples/extensions/ashi-ui-demo.ts +63 -0
  89. package/examples/extensions/latex-images.ts +70 -19
  90. package/examples/extensions/overlay-agent.ts +5 -5
  91. package/examples/extensions/pi-bridge/index.ts +7 -12
  92. package/examples/extensions/terminal-buffer.ts +4 -2
  93. package/package.json +3 -9
  94. package/examples/extensions/ashi/src/components.ts +0 -238
  95. package/examples/extensions/ollama.ts +0 -108
  96. package/examples/extensions/opencode-provider.ts +0 -251
  97. package/examples/extensions/zai-coding-plan.ts +0 -35
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
1
  # agent-sh
2
2
 
3
- A real shell with an AI agent one keystroke away.
4
-
5
3
  [![npm version](https://img.shields.io/npm/v/agent-sh.svg)](https://www.npmjs.com/package/agent-sh)
6
4
  [![license](https://img.shields.io/npm/l/agent-sh.svg)](https://github.com/guanyilun/agent-sh/blob/main/LICENSE)
7
5
 
8
- ![demo](assets/demo.gif)
6
+ A composable agent runtime — pair any frontend with any agent backend, over one shared extension layer.
9
7
 
10
- I live in my terminal. A lot of the time I'm not coding — I'm deploying something, poking at a failing `rsync`, figuring out why `docker build` won't start, fixing a one-liner. And very often I need an AI agent to help. Spinning up a full coding agent for this stuff is overkill, and I got tired of copy-pasting errors into a chat window every time.
8
+ ## A shell with the agent one keystroke away
11
9
 
12
- So I built agent-sh. Under the hood it's a normal shell on top of node-pty — your rc config, your aliases, vim and tmux all just work. But at the start of any line, type `>` and you're talking to a small agent that already sees your cwd, your last command, and its output. Nothing to set up, no project to explain.
10
+ The frontend bundled with agent-sh: a normal shell on top of node-pty — your rc config, your aliases, vim and tmux all just work. But at the start of any line, type `>` and you're talking to an agent that already sees your cwd, your last command, and its output. Nothing to set up, no project to explain.
11
+
12
+ ![demo](assets/demo.gif)
13
13
 
14
14
  ```
15
15
  ~ $ ls -la # real shell command
@@ -19,10 +19,12 @@ So I built agent-sh. Under the hood it's a normal shell on top of node-pty — y
19
19
  ~ $ > draft a commit message # agent reads your diff and shell history
20
20
  ```
21
21
 
22
- agent-sh is built to be agent-agnostic. The recommended path is the built-in agent `ash` a lightweight agent designed so extensions can plug into the same tool surface. If you'd rather host an existing coding agent (pi, claude-code, opencode), you can [bring your own](#bring-your-own-agent) with the trade-off that it manages its own separate tools.
22
+ **The agent behind `>` is swappable the terminal stays the same.** Out of the box it's **`ash`**, agent-sh's own lightweight agent: it works with any OpenAI-compatible API and shares its tool surface with every extension you install. Already invested in another coding agent? The same `>` and the same shell-context wiring can host **pi**, **claude-code**, or **opencode** instead through in-the-box bridges — bring your own backend, keep the workflow. The Quick Start below walks through both.
23
23
 
24
24
  ## Quick Start
25
25
 
26
+ **This sets up the agent-sh shell** — the frontend bundled in the `agent-sh` package. (For the other frontends, install [ashi](examples/extensions/ashi/) or [asHub](https://github.com/firslov/asHub) instead.)
27
+
26
28
  ### Installation
27
29
 
28
30
  Install from npm:
@@ -139,19 +141,40 @@ All three bridges receive agent-sh's per-query shell context (`<shell_events>`)
139
141
 
140
142
  **Caveat:** pi, claude-code, and opencode each manage their own tool surfaces, so agent-sh extensions that register tools (or skills, instructions, etc.) for the built-in `ash` agent generally won't be visible to a hosted backend. Frontend extensions (themes, content transforms, slash commands, the TUI renderer) keep working — only the agent-side capabilities differ. Use the bridges when you want that agent's toolset; stay on `ash` when you want agent-sh's extension ecosystem.
141
143
 
142
- ## Key Features
144
+ ## Same runtime, other frontends
145
+
146
+ The shell is just one frontend. Because the frontend is itself an extension on the bus, the same runtime — same agent backends, tools, providers, and `~/.agent-sh/settings.json` — drives completely different apps.
147
+
148
+ ### ashi — a standalone coding agent
149
+
150
+ [**`@guanyilun/ashi`**](examples/extensions/ashi/) is the same `ash` agent in a chat-style TUI, with no shell underneath — just the agent. Installed separately, it reuses agent-sh's backend, tools, slash commands, providers, and skills, and adds session history, in-session branching, and LLM-driven compaction.
151
+
152
+ ```bash
153
+ npm install -g @guanyilun/ashi
154
+ ashi
155
+ ```
156
+
157
+ ashi makes the runtime's **decoupled rendering** concrete: the frontend is itself an extension, and even *how* it draws tool calls and results is a swappable render extension. Same agent backend, same conversation — load a different render extension and the whole TUI restyles, no code changes:
158
+
159
+ | pi-style rendering | claude-code-style rendering |
160
+ |---|---|
161
+ | ![ashi rendering tool calls pi-style](assets/ashi-pi-style.png) | ![ashi rendering tool calls claude-code-style](assets/ashi-claude-code-style.png) |
162
+
163
+ ### asHub — a GUI coding agent
164
+
165
+ [**firslov/asHub**](https://github.com/firslov/asHub) is a third-party cross-platform desktop app (Electron) built on the agent-sh runtime: a multi-session sidebar, persistence across restarts, and a live-streaming interface with Markdown, syntax-highlighted code, diffs, and tool-call rendering. macOS / Windows / Linux.
143
166
 
144
- **Real terminal, zero compromise.** Full PTY with your shell config, aliases, and environment. Shell starts instantly the agent connects asynchronously in the background.
167
+ It pushes the same decoupling one step further the frontend isn't a terminal at all, but a full desktop GUI on the same runtime, backends, and tools:
145
168
 
146
- **One entry point, smart tool selection.** Type `>` and agent-sh figures out how to help. Scratchpad tools (`bash`, `read_file`, `grep`, `glob`) for investigation. Extensions add capabilities like running commands in your live shell. No modes to pick — the agent reasons about which tools to use based on your intent.
169
+ ![asHub desktop GUI](assets/ashub.png)
147
170
 
148
- **Context that just works.** Every query includes your cwd, recent commands, and their output. Run a failing test, type `> fix this`, and agent-sh knows exactly what happened. Context management works like shell history — continuous, persistent across restarts, no sessions to manage. See [Context Management](docs/context-management.md).
171
+ ## How it works
149
172
 
150
- **Any LLM, any backend.** agent-sh works with any OpenAI-compatible API out of the box. Define multiple providers in settings and switch models at runtime with `/model <name>`. Or swap in a completely different agent bundled bridges run [pi](examples/extensions/pi-bridge/), [claude-code](examples/extensions/claude-code-bridge/), or [opencode](examples/extensions/opencode-bridge/) as a drop-in backend (see [Bring your own agent](#bring-your-own-agent)).
173
+ At agent-sh's center is a pure kernel a typed event bus, a named-handler registry, and an extension loader that knows nothing about terminals, LLMs, shells, or rendering. Everything else plugs into it: the agent backend, its tools, provider management, and the frontend that drives it.
151
174
 
152
- **Extensible by design.** The entire system is built on a typed event bus. Extensions can add custom input modes, content transforms (render LaTeX as images, Mermaid as diagrams), themes, slash commands, or replace the agent backend entirely. The built-in TUI renderer is itself just an extension.
175
+ The frontend and the agent backend are both just components on the bus, so you **mix and match** them freely wire several frontends to one backend, or keep one frontend and swap the backend underneath — all sharing the **same extension layer** of tools, content transforms, slash commands, and themes. The shell swapping `ash` for a bridged agent, and ashi/asHub putting a different UI on the same backend, are the same idea seen from two directions. `import { createCore } from "agent-sh"` gives you the headless kernel; load the pieces you want and wire your own I/O.
153
176
 
154
- **Embeddable as a library.** The core is a headless kernel `import { createCore } from "agent-sh"` to build WebSocket servers, REST APIs, Electron apps, or test harnesses. No terminal required.
177
+ For the kernel design in full the bus, handlers, the compositor, and the shell agent boundary see [Architecture](docs/architecture.md). To embed the runtime in your own frontend, see the [Library Guide](docs/library.md).
155
178
 
156
179
  ## Documentation
157
180
 
@@ -1,18 +1,10 @@
1
1
  /**
2
- * Internal agent backend — bus-driven, self-wiring.
3
- *
4
- * Subscribes to bus events in constructor:
5
- * - agent:submit → run query through LLM tool loop
6
- * - agent:cancel-request → abort current loop
7
- *
8
- * Emits bus events during execution:
9
- * - agent:query, agent:processing-start/done, agent:response-chunk/done
10
- * - agent:tool-started, agent:tool-call, agent:tool-output-chunk,
11
- * agent:tool-completed, agent:tool-output
12
- * - agent:thinking-chunk, agent:cancelled, agent:error
2
+ * Internal agent backend — bus-driven and self-wiring. wire() subscribes to
3
+ * agent:submit (run the LLM tool loop) and agent:cancel-request (abort it),
4
+ * and the loop emits the agent:* progress/response/tool event stream.
13
5
  */
14
6
  import type { EventBus } from "../core/event-bus.js";
15
- import type { AgentMode } from "./host-types.js";
7
+ import type { Model } from "./host-types.js";
16
8
  import type { LlmClient } from "./llm-client.js";
17
9
  import type { HandlerFunctions } from "../utils/handler-registry.js";
18
10
  import { type AgentBackend, type ToolDefinition } from "./types.js";
@@ -21,7 +13,7 @@ export interface AgentLoopConfig {
21
13
  bus: EventBus;
22
14
  llmClient: LlmClient;
23
15
  handlers: HandlerFunctions;
24
- initialMode?: AgentMode;
16
+ initialModel?: Model;
25
17
  compositor?: Compositor;
26
18
  /** Instance ID from core — ensures history entries match the ID in prompts. */
27
19
  instanceId?: string;
@@ -31,7 +23,8 @@ export declare class AgentLoop implements AgentBackend {
31
23
  private toolRegistry;
32
24
  private conversation;
33
25
  private fileReadCache;
34
- private activeMode;
26
+ private activeModel;
27
+ private activeEndpoint;
35
28
  private boundListeners;
36
29
  private boundPipeListeners;
37
30
  private lastProjectSkillNames;
@@ -91,10 +84,9 @@ export declare class AgentLoop implements AgentBackend {
91
84
  kill(): void;
92
85
  private cancel;
93
86
  private reasoningParams;
94
- private get currentMode();
95
- private pullModes;
87
+ private resolveEndpoint;
88
+ private pullModels;
96
89
  private emitIdentity;
97
- private get currentModel();
98
90
  /**
99
91
  * Run compaction via the `conversation:compact` handler. After any
100
92
  * compaction, emit `conversation:after-compact` so listeners