@draht/coding-agent 2026.3.25 → 2026.4.5
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/CHANGELOG.md +107 -0
- package/README.md +6 -2
- package/dist/core/agent-session-runtime.d.ts +136 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -0
- package/dist/core/agent-session-runtime.js +267 -0
- package/dist/core/agent-session-runtime.js.map +1 -0
- package/dist/core/agent-session.d.ts +22 -44
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +44 -248
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +3 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +5 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +2 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +2 -2
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +2 -2
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +9 -9
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts +2 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +2 -2
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +16 -16
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +10 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +5 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +70 -8
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/model-registry.d.ts +21 -3
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +90 -70
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +4 -4
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/resolve-config-value.d.ts +6 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +37 -5
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +2 -0
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +5 -1
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +6 -3
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +17 -23
- package/dist/core/sdk.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +49 -10
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +1 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +8 -4
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +90 -87
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +6 -11
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/print-mode.d.ts +4 -4
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +87 -74
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +69 -49
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/docs/development.md +2 -2
- package/docs/extensions.md +78 -22
- package/docs/models.md +6 -0
- package/docs/packages.md +3 -3
- package/docs/rpc.md +2 -2
- package/docs/sdk.md +170 -82
- package/docs/tree.md +1 -1
- package/examples/extensions/custom-compaction.ts +17 -4
- package/examples/extensions/handoff.ts +5 -2
- package/examples/extensions/hello.ts +18 -17
- package/examples/extensions/qna.ts +5 -2
- package/examples/extensions/rpc-demo.ts +3 -9
- package/examples/extensions/status-line.ts +0 -8
- package/examples/extensions/subagent/index.ts +1 -1
- package/examples/extensions/summarize.ts +15 -4
- package/examples/extensions/todo.ts +0 -2
- package/examples/extensions/tools.ts +0 -5
- package/examples/extensions/widget-placement.ts +4 -12
- package/examples/sdk/02-custom-model.ts +1 -1
- package/examples/sdk/09-api-keys-and-oauth.ts +3 -3
- package/examples/sdk/12-full-control.ts +1 -1
- package/examples/sdk/13-session-runtime.ts +49 -0
- package/examples/sdk/README.md +5 -4
- package/package.json +4 -4
|
@@ -165,12 +165,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
165
165
|
ctx.ui.notify("Model openai/gpt-5.2 not found", "warning");
|
|
166
166
|
}
|
|
167
167
|
|
|
168
|
-
const
|
|
169
|
-
if (!
|
|
168
|
+
const auth = model ? await ctx.modelRegistry.getApiKeyAndHeaders(model) : undefined;
|
|
169
|
+
if (auth && !auth.ok && ctx.hasUI) {
|
|
170
|
+
ctx.ui.notify(auth.error, "warning");
|
|
171
|
+
}
|
|
172
|
+
if (auth?.ok && !auth.apiKey && ctx.hasUI) {
|
|
170
173
|
ctx.ui.notify("No API key for openai/gpt-5.2", "warning");
|
|
171
174
|
}
|
|
172
175
|
|
|
173
|
-
if (!model || !apiKey) {
|
|
176
|
+
if (!model || !auth?.ok || !auth.apiKey) {
|
|
174
177
|
return;
|
|
175
178
|
}
|
|
176
179
|
|
|
@@ -182,7 +185,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
182
185
|
},
|
|
183
186
|
];
|
|
184
187
|
|
|
185
|
-
const response = await complete(
|
|
188
|
+
const response = await complete(
|
|
189
|
+
model,
|
|
190
|
+
{ messages: summaryMessages },
|
|
191
|
+
{
|
|
192
|
+
apiKey: auth.apiKey,
|
|
193
|
+
headers: auth.headers,
|
|
194
|
+
reasoningEffort: "high",
|
|
195
|
+
},
|
|
196
|
+
);
|
|
186
197
|
|
|
187
198
|
const summary = response.content
|
|
188
199
|
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
|
@@ -130,8 +130,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
130
130
|
|
|
131
131
|
// Reconstruct state on session events
|
|
132
132
|
pi.on("session_start", async (_event, ctx) => reconstructState(ctx));
|
|
133
|
-
pi.on("session_switch", async (_event, ctx) => reconstructState(ctx));
|
|
134
|
-
pi.on("session_fork", async (_event, ctx) => reconstructState(ctx));
|
|
135
133
|
pi.on("session_tree", async (_event, ctx) => reconstructState(ctx));
|
|
136
134
|
|
|
137
135
|
// Register the todo tool for the LLM
|
|
@@ -138,9 +138,4 @@ export default function toolsExtension(pi: ExtensionAPI) {
|
|
|
138
138
|
pi.on("session_tree", async (_event, ctx) => {
|
|
139
139
|
restoreFromBranch(ctx);
|
|
140
140
|
});
|
|
141
|
-
|
|
142
|
-
// Restore state after forking
|
|
143
|
-
pi.on("session_fork", async (_event, ctx) => {
|
|
144
|
-
restoreFromBranch(ctx);
|
|
145
|
-
});
|
|
146
141
|
}
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import type { ExtensionAPI
|
|
2
|
-
|
|
3
|
-
const applyWidgets = (ctx: ExtensionContext) => {
|
|
4
|
-
if (!ctx.hasUI) return;
|
|
5
|
-
ctx.ui.setWidget("widget-above", ["Above editor widget"]);
|
|
6
|
-
ctx.ui.setWidget("widget-below", ["Below editor widget"], { placement: "belowEditor" });
|
|
7
|
-
};
|
|
1
|
+
import type { ExtensionAPI } from "@draht/coding-agent";
|
|
8
2
|
|
|
9
3
|
export default function widgetPlacementExtension(pi: ExtensionAPI) {
|
|
10
4
|
pi.on("session_start", (_event, ctx) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
pi.on("session_switch", (_event, ctx) => {
|
|
15
|
-
applyWidgets(ctx);
|
|
5
|
+
if (!ctx.hasUI) return;
|
|
6
|
+
ctx.ui.setWidget("widget-above", ["Above editor widget"]);
|
|
7
|
+
ctx.ui.setWidget("widget-below", ["Below editor widget"], { placement: "belowEditor" });
|
|
16
8
|
});
|
|
17
9
|
}
|
|
@@ -9,7 +9,7 @@ import { AuthStorage, createAgentSession, ModelRegistry } from "@draht/coding-ag
|
|
|
9
9
|
|
|
10
10
|
// Set up auth storage and model registry
|
|
11
11
|
const authStorage = AuthStorage.create();
|
|
12
|
-
const modelRegistry =
|
|
12
|
+
const modelRegistry = ModelRegistry.create(authStorage);
|
|
13
13
|
|
|
14
14
|
// Option 1: Find a specific built-in model by provider/id
|
|
15
15
|
const opus = getModel("anthropic", "claude-opus-4-5");
|
|
@@ -9,7 +9,7 @@ import { AuthStorage, createAgentSession, ModelRegistry, SessionManager } from "
|
|
|
9
9
|
// Default: AuthStorage uses ~/.pi/agent/auth.json
|
|
10
10
|
// ModelRegistry loads built-in + custom models from ~/.pi/agent/models.json
|
|
11
11
|
const authStorage = AuthStorage.create();
|
|
12
|
-
const modelRegistry =
|
|
12
|
+
const modelRegistry = ModelRegistry.create(authStorage);
|
|
13
13
|
|
|
14
14
|
await createAgentSession({
|
|
15
15
|
sessionManager: SessionManager.inMemory(),
|
|
@@ -20,7 +20,7 @@ console.log("Session with default auth storage and model registry");
|
|
|
20
20
|
|
|
21
21
|
// Custom auth storage location
|
|
22
22
|
const customAuthStorage = AuthStorage.create("/tmp/my-app/auth.json");
|
|
23
|
-
const customModelRegistry =
|
|
23
|
+
const customModelRegistry = ModelRegistry.create(customAuthStorage, "/tmp/my-app/models.json");
|
|
24
24
|
|
|
25
25
|
await createAgentSession({
|
|
26
26
|
sessionManager: SessionManager.inMemory(),
|
|
@@ -39,7 +39,7 @@ await createAgentSession({
|
|
|
39
39
|
console.log("Session with runtime API key override");
|
|
40
40
|
|
|
41
41
|
// No models.json - only built-in models
|
|
42
|
-
const simpleRegistry =
|
|
42
|
+
const simpleRegistry = ModelRegistry.inMemory(authStorage);
|
|
43
43
|
await createAgentSession({
|
|
44
44
|
sessionManager: SessionManager.inMemory(),
|
|
45
45
|
authStorage,
|
|
@@ -30,7 +30,7 @@ if (process.env.MY_ANTHROPIC_KEY) {
|
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
// Model registry with no custom models.json
|
|
33
|
-
const modelRegistry =
|
|
33
|
+
const modelRegistry = ModelRegistry.inMemory(authStorage);
|
|
34
34
|
|
|
35
35
|
const model = getModel("anthropic", "claude-sonnet-4-20250514");
|
|
36
36
|
if (!model) throw new Error("Model not found");
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Runtime Host
|
|
3
|
+
*
|
|
4
|
+
* Use the runtime host when you need to replace the active AgentSession,
|
|
5
|
+
* for example for new-session, resume, fork, or import flows.
|
|
6
|
+
*
|
|
7
|
+
* The important pattern is: after the host replaces the runtime, rebind any
|
|
8
|
+
* session-local subscriptions and extension bindings to `runtimeHost.session`.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { AgentSessionRuntimeHost, createAgentSessionRuntime, SessionManager } from "@draht/coding-agent";
|
|
12
|
+
|
|
13
|
+
const bootstrap = {};
|
|
14
|
+
const runtime = await createAgentSessionRuntime(bootstrap, {
|
|
15
|
+
cwd: process.cwd(),
|
|
16
|
+
sessionManager: SessionManager.create(process.cwd()),
|
|
17
|
+
});
|
|
18
|
+
const runtimeHost = new AgentSessionRuntimeHost(bootstrap, runtime);
|
|
19
|
+
|
|
20
|
+
let unsubscribe: (() => void) | undefined;
|
|
21
|
+
|
|
22
|
+
async function bindSession() {
|
|
23
|
+
unsubscribe?.();
|
|
24
|
+
const session = runtimeHost.session;
|
|
25
|
+
await session.bindExtensions({});
|
|
26
|
+
unsubscribe = session.subscribe((event) => {
|
|
27
|
+
if (event.type === "queue_update") {
|
|
28
|
+
console.log("Queued:", event.steering.length + event.followUp.length);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
return session;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let session = await bindSession();
|
|
35
|
+
const originalSessionFile = session.sessionFile;
|
|
36
|
+
console.log("Initial session:", originalSessionFile);
|
|
37
|
+
|
|
38
|
+
await runtimeHost.newSession();
|
|
39
|
+
session = await bindSession();
|
|
40
|
+
console.log("After newSession():", session.sessionFile);
|
|
41
|
+
|
|
42
|
+
if (originalSessionFile) {
|
|
43
|
+
await runtimeHost.switchSession(originalSessionFile);
|
|
44
|
+
session = await bindSession();
|
|
45
|
+
console.log("After switchSession():", session.sessionFile);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
unsubscribe?.();
|
|
49
|
+
await runtimeHost.dispose();
|
package/examples/sdk/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SDK Examples
|
|
2
2
|
|
|
3
|
-
Programmatic usage of @draht/coding-agent via `createAgentSession()`.
|
|
3
|
+
Programmatic usage of @draht/coding-agent via `createAgentSession()` and `createAgentSessionRuntime()`.
|
|
4
4
|
|
|
5
5
|
## Examples
|
|
6
6
|
|
|
@@ -18,6 +18,7 @@ Programmatic usage of @draht/coding-agent via `createAgentSession()`.
|
|
|
18
18
|
| `10-settings.ts` | Override compaction, retry, terminal settings |
|
|
19
19
|
| `11-sessions.ts` | In-memory, persistent, continue, list sessions |
|
|
20
20
|
| `12-full-control.ts` | Replace everything, no discovery |
|
|
21
|
+
| `13-session-runtime.ts` | Manage runtime-backed session replacement |
|
|
21
22
|
|
|
22
23
|
## Running
|
|
23
24
|
|
|
@@ -44,7 +45,7 @@ import {
|
|
|
44
45
|
|
|
45
46
|
// Auth and models setup
|
|
46
47
|
const authStorage = AuthStorage.create();
|
|
47
|
-
const modelRegistry =
|
|
48
|
+
const modelRegistry = ModelRegistry.create(authStorage);
|
|
48
49
|
|
|
49
50
|
// Minimal
|
|
50
51
|
const { session } = await createAgentSession({ authStorage, modelRegistry });
|
|
@@ -73,7 +74,7 @@ const { session } = await createAgentSession({
|
|
|
73
74
|
// Full control
|
|
74
75
|
const customAuth = AuthStorage.create("/my/app/auth.json");
|
|
75
76
|
customAuth.setRuntimeApiKey("anthropic", process.env.MY_KEY!);
|
|
76
|
-
const customRegistry =
|
|
77
|
+
const customRegistry = ModelRegistry.create(customAuth);
|
|
77
78
|
|
|
78
79
|
const resourceLoader = new DefaultResourceLoader({
|
|
79
80
|
systemPromptOverride: () => "You are helpful.",
|
|
@@ -109,7 +110,7 @@ await session.prompt("Hello");
|
|
|
109
110
|
| Option | Default | Description |
|
|
110
111
|
|--------|---------|-------------|
|
|
111
112
|
| `authStorage` | `AuthStorage.create()` | Credential storage |
|
|
112
|
-
| `modelRegistry` | `
|
|
113
|
+
| `modelRegistry` | `ModelRegistry.create(authStorage)` | Model registry |
|
|
113
114
|
| `cwd` | `process.cwd()` | Working directory |
|
|
114
115
|
| `agentDir` | `~/.draht/agent` | Config directory |
|
|
115
116
|
| `model` | From settings/first available | Model to use |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@draht/coding-agent",
|
|
3
|
-
"version": "2026.
|
|
3
|
+
"version": "2026.4.5",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"drahtConfig": {
|
|
@@ -48,9 +48,9 @@
|
|
|
48
48
|
"@mariozechner/jiti": "^2.6.2",
|
|
49
49
|
"@sinclair/typebox": "^0.34.41",
|
|
50
50
|
"ajv": "^8.17.1",
|
|
51
|
-
"@draht/agent-core": "2026.
|
|
52
|
-
"@draht/ai": "2026.
|
|
53
|
-
"@draht/tui": "2026.
|
|
51
|
+
"@draht/agent-core": "2026.4.5",
|
|
52
|
+
"@draht/ai": "2026.4.5",
|
|
53
|
+
"@draht/tui": "2026.4.5",
|
|
54
54
|
"@silvia-odwyer/photon-node": "^0.3.4",
|
|
55
55
|
"chalk": "^5.5.0",
|
|
56
56
|
"cli-highlight": "^2.1.11",
|