@deepstrike/wasm 0.1.10 → 0.1.14
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 +72 -27
- package/dist/harness/index.d.ts +5 -5
- package/dist/harness/index.js +18 -12
- package/dist/index.d.ts +4 -4
- package/dist/index.js +1 -1
- package/dist/memory/index.d.ts +4 -0
- package/dist/providers/anthropic.d.ts +3 -2
- package/dist/providers/anthropic.js +17 -4
- package/dist/providers/base.d.ts +16 -0
- package/dist/providers/base.js +42 -0
- package/dist/providers/openai.d.ts +7 -6
- package/dist/providers/openai.js +14 -11
- package/dist/runtime/execution-plane.d.ts +33 -0
- package/dist/runtime/execution-plane.js +108 -0
- package/dist/runtime/index.d.ts +7 -0
- package/dist/runtime/index.js +4 -0
- package/dist/runtime/kernel.d.ts +4 -0
- package/dist/runtime/kernel.js +8 -0
- package/dist/runtime/runner.d.ts +44 -0
- package/dist/runtime/runner.js +358 -0
- package/dist/runtime/session-log.d.ts +54 -0
- package/dist/runtime/session-log.js +18 -0
- package/dist/types.d.ts +21 -1
- package/package.json +2 -2
- package/dist/agent.d.ts +0 -57
- package/dist/agent.js +0 -244
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# DeepStrike WASM SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Runtime framework built on a Rust kernel compiled to WebAssembly. Runs in browsers, Cloudflare Workers, Deno Deploy, and Vercel Edge — anywhere that supports `fetch` and WASM.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -15,7 +15,14 @@ The Rust kernel is distributed as a pre-built `.wasm` binary (`@deepstrike/wasm-
|
|
|
15
15
|
## Quick start
|
|
16
16
|
|
|
17
17
|
```typescript
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
RuntimeRunner,
|
|
20
|
+
collectText,
|
|
21
|
+
InMemorySessionLog,
|
|
22
|
+
LocalExecutionPlane,
|
|
23
|
+
AnthropicProvider,
|
|
24
|
+
tool,
|
|
25
|
+
} from "@deepstrike/wasm"
|
|
19
26
|
|
|
20
27
|
const add = tool("add", "Add two numbers.", {
|
|
21
28
|
type: "object",
|
|
@@ -23,20 +30,25 @@ const add = tool("add", "Add two numbers.", {
|
|
|
23
30
|
required: ["x", "y"],
|
|
24
31
|
}, async ({ x, y }) => String((x as number) + (y as number)))
|
|
25
32
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
{ maxTokens: 32_000, maxTurns: 10 },
|
|
29
|
-
)
|
|
30
|
-
agent.register(add)
|
|
33
|
+
const plane = new LocalExecutionPlane()
|
|
34
|
+
plane.register(add)
|
|
31
35
|
|
|
32
|
-
const
|
|
36
|
+
const runner = new RuntimeRunner({
|
|
37
|
+
provider: new AnthropicProvider(apiKey),
|
|
38
|
+
sessionLog: new InMemorySessionLog(),
|
|
39
|
+
executionPlane: plane,
|
|
40
|
+
maxTokens: 32_000,
|
|
41
|
+
maxTurns: 10,
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const answer = await collectText(runner.run({ sessionId: "demo", goal: "What is 2 + 3?" }))
|
|
33
45
|
console.log(answer) // "5"
|
|
34
46
|
```
|
|
35
47
|
|
|
36
48
|
Streaming:
|
|
37
49
|
|
|
38
50
|
```typescript
|
|
39
|
-
for await (const event of
|
|
51
|
+
for await (const event of runner.run({ sessionId: "demo", goal: "Summarize this page" })) {
|
|
40
52
|
if (event.type === "text_delta") process.stdout.write(event.delta)
|
|
41
53
|
else if (event.type === "tool_call") console.log(`\n[→ ${event.name}]`)
|
|
42
54
|
else if (event.type === "done") console.log(`\ndone in ${event.iterations} turns (${event.status})`)
|
|
@@ -50,13 +62,13 @@ for await (const event of agent.runStreaming("Summarize this page")) {
|
|
|
50
62
|
```
|
|
51
63
|
src/
|
|
52
64
|
├── index.ts # Public exports
|
|
53
|
-
├──
|
|
65
|
+
├── runtime/ # RuntimeRunner, SessionLog, ExecutionPlane
|
|
54
66
|
├── types.ts # Shared type definitions
|
|
55
67
|
├── providers/ # LLM adapters (fetch-based SSE)
|
|
56
68
|
├── tools/ # tool() helper, executeTools (no fs/shell)
|
|
57
|
-
├── memory/ # WorkingMemory +
|
|
69
|
+
├── memory/ # WorkingMemory + DreamStore interfaces
|
|
58
70
|
├── knowledge/ # KnowledgeSource interface
|
|
59
|
-
├── harness/ # SinglePassHarness,
|
|
71
|
+
├── harness/ # SinglePassHarness, HarnessLoop
|
|
60
72
|
├── signals/ # RuntimeSignal, SignalSource, ScheduledPrompt
|
|
61
73
|
└── safety/ # PermissionManager
|
|
62
74
|
```
|
|
@@ -76,7 +88,7 @@ The kernel (`@deepstrike/wasm-kernel`, Rust/wasm-bindgen) owns:
|
|
|
76
88
|
| Long-term storage | IndexedDB | KV / D1 | SQLite |
|
|
77
89
|
| External signals | `postMessage` | event | any |
|
|
78
90
|
|
|
79
|
-
The WASM SDK ships **no `readFile` built-in**. Tools must be pure JS / serializable data.
|
|
91
|
+
The WASM SDK ships **no `readFile` built-in**. Tools must be pure JS / serializable data. Skills use `skillContentMap` on `RuntimeOptions` (no filesystem).
|
|
80
92
|
|
|
81
93
|
---
|
|
82
94
|
|
|
@@ -101,7 +113,11 @@ const provider = new AnthropicProvider("sk-...", "claude-opus-4-7")
|
|
|
101
113
|
Thinking / reasoning:
|
|
102
114
|
|
|
103
115
|
```typescript
|
|
104
|
-
for await (const event of
|
|
116
|
+
for await (const event of runner.run({
|
|
117
|
+
sessionId: "demo",
|
|
118
|
+
goal: "...",
|
|
119
|
+
extensions: { enable_thinking: true },
|
|
120
|
+
})) {
|
|
105
121
|
if (event.type === "thinking_delta") console.log(event.delta)
|
|
106
122
|
}
|
|
107
123
|
```
|
|
@@ -113,7 +129,7 @@ for await (const event of agent.runStreaming("...", undefined, { enable_thinking
|
|
|
113
129
|
Tools must be pure functions — no shell, no filesystem.
|
|
114
130
|
|
|
115
131
|
```typescript
|
|
116
|
-
import { tool,
|
|
132
|
+
import { tool, LocalExecutionPlane } from "@deepstrike/wasm"
|
|
117
133
|
|
|
118
134
|
const fetchUrl = tool("fetch_url", "Fetch a URL and return its text.", {
|
|
119
135
|
type: "object",
|
|
@@ -124,7 +140,8 @@ const fetchUrl = tool("fetch_url", "Fetch a URL and return its text.", {
|
|
|
124
140
|
return resp.text()
|
|
125
141
|
})
|
|
126
142
|
|
|
127
|
-
|
|
143
|
+
const plane = new LocalExecutionPlane()
|
|
144
|
+
plane.register(fetchUrl)
|
|
128
145
|
```
|
|
129
146
|
|
|
130
147
|
---
|
|
@@ -132,12 +149,15 @@ agent.register(fetchUrl)
|
|
|
132
149
|
## Governance
|
|
133
150
|
|
|
134
151
|
```typescript
|
|
135
|
-
import {
|
|
152
|
+
import { RuntimeRunner, AnthropicProvider, Governance } from "@deepstrike/wasm"
|
|
136
153
|
|
|
137
154
|
const gov = new Governance()
|
|
138
155
|
gov.blockTool("dangerous_tool")
|
|
139
156
|
|
|
140
|
-
const
|
|
157
|
+
const runner = new RuntimeRunner({
|
|
158
|
+
provider: new AnthropicProvider(apiKey),
|
|
159
|
+
sessionLog: new InMemorySessionLog(),
|
|
160
|
+
executionPlane: new LocalExecutionPlane(),
|
|
141
161
|
maxTokens: 32_000,
|
|
142
162
|
governance: gov,
|
|
143
163
|
})
|
|
@@ -171,7 +191,10 @@ class VectorSearch implements KnowledgeSource {
|
|
|
171
191
|
}
|
|
172
192
|
}
|
|
173
193
|
|
|
174
|
-
const
|
|
194
|
+
const runner = new RuntimeRunner({
|
|
195
|
+
provider,
|
|
196
|
+
sessionLog: new InMemorySessionLog(),
|
|
197
|
+
executionPlane: new LocalExecutionPlane(),
|
|
175
198
|
maxTokens: 32_000,
|
|
176
199
|
maxTurns: 10,
|
|
177
200
|
knowledgeSource: new VectorSearch(),
|
|
@@ -186,12 +209,12 @@ const agent = new Agent(provider, {
|
|
|
186
209
|
import { SinglePassHarness, HarnessLoop } from "@deepstrike/wasm"
|
|
187
210
|
|
|
188
211
|
// Single pass — always passes
|
|
189
|
-
const harness = new SinglePassHarness(
|
|
212
|
+
const harness = new SinglePassHarness(runner)
|
|
190
213
|
const outcome = await harness.run({ goal: "Write a haiku" })
|
|
191
214
|
console.log(outcome.result)
|
|
192
215
|
|
|
193
216
|
// Eval loop — LLM-judges the output; retries up to 3 times
|
|
194
|
-
const loop = new HarnessLoop(
|
|
217
|
+
const loop = new HarnessLoop(runner, evalProvider, { maxAttempts: 3 })
|
|
195
218
|
for await (const event of loop.runStreaming({
|
|
196
219
|
goal: "Write a haiku",
|
|
197
220
|
criteria: [
|
|
@@ -212,7 +235,7 @@ import { ScheduledPrompt } from "@deepstrike/wasm"
|
|
|
212
235
|
import type { SignalSource, RuntimeSignal } from "@deepstrike/wasm"
|
|
213
236
|
|
|
214
237
|
// Interrupt from a UI button
|
|
215
|
-
document.getElementById("stop")!.onclick = () =>
|
|
238
|
+
document.getElementById("stop")!.onclick = () => runner.interrupt()
|
|
216
239
|
|
|
217
240
|
// Convert a scheduled prompt to a RuntimeSignal
|
|
218
241
|
const prompt = new ScheduledPrompt("Daily standup summary", 1_700_000_000_000)
|
|
@@ -260,14 +283,29 @@ Modes: `DEFAULT` (evaluate grants), `PLAN` (block all), `AUTO` (allow all).
|
|
|
260
283
|
|
|
261
284
|
```typescript
|
|
262
285
|
import init from "@deepstrike/wasm-kernel"
|
|
263
|
-
import {
|
|
286
|
+
import {
|
|
287
|
+
RuntimeRunner,
|
|
288
|
+
collectText,
|
|
289
|
+
InMemorySessionLog,
|
|
290
|
+
LocalExecutionPlane,
|
|
291
|
+
AnthropicProvider,
|
|
292
|
+
} from "@deepstrike/wasm"
|
|
264
293
|
import wasmBinary from "@deepstrike/wasm-kernel/deepstrike_wasm_bg.wasm"
|
|
265
294
|
|
|
266
295
|
export default {
|
|
267
296
|
async fetch(request: Request, env: Env): Promise<Response> {
|
|
268
297
|
await init(wasmBinary)
|
|
269
|
-
const
|
|
270
|
-
|
|
298
|
+
const runner = new RuntimeRunner({
|
|
299
|
+
provider: new AnthropicProvider(env.ANTHROPIC_KEY),
|
|
300
|
+
sessionLog: new InMemorySessionLog(),
|
|
301
|
+
executionPlane: new LocalExecutionPlane(),
|
|
302
|
+
maxTokens: 32_000,
|
|
303
|
+
maxTurns: 10,
|
|
304
|
+
})
|
|
305
|
+
const result = await collectText(runner.run({
|
|
306
|
+
sessionId: crypto.randomUUID(),
|
|
307
|
+
goal: await request.text(),
|
|
308
|
+
}))
|
|
271
309
|
return new Response(result)
|
|
272
310
|
},
|
|
273
311
|
}
|
|
@@ -277,10 +315,16 @@ export default {
|
|
|
277
315
|
|
|
278
316
|
```typescript
|
|
279
317
|
import init from "@deepstrike/wasm-kernel"
|
|
280
|
-
import {
|
|
318
|
+
import { RuntimeRunner, InMemorySessionLog, LocalExecutionPlane, AnthropicProvider } from "@deepstrike/wasm"
|
|
281
319
|
|
|
282
320
|
await init()
|
|
283
|
-
const
|
|
321
|
+
const runner = new RuntimeRunner({
|
|
322
|
+
provider: new AnthropicProvider(import.meta.env.VITE_ANTHROPIC_KEY),
|
|
323
|
+
sessionLog: new InMemorySessionLog(),
|
|
324
|
+
executionPlane: new LocalExecutionPlane(),
|
|
325
|
+
maxTokens: 32_000,
|
|
326
|
+
maxTurns: 10,
|
|
327
|
+
})
|
|
284
328
|
```
|
|
285
329
|
|
|
286
330
|
---
|
|
@@ -291,6 +335,7 @@ const agent = new Agent(new AnthropicProvider(import.meta.env.VITE_ANTHROPIC_KEY
|
|
|
291
335
|
|------------|--------|
|
|
292
336
|
| `text_delta` | `delta: string` |
|
|
293
337
|
| `thinking_delta` | `delta: string` |
|
|
338
|
+
| `usage` | `totalTokens: number` |
|
|
294
339
|
| `tool_call` | `id, name, arguments` |
|
|
295
340
|
| `tool_result` | `callId, name, content, isError` |
|
|
296
341
|
| `done` | `iterations, totalTokens, status` |
|
package/dist/harness/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RuntimeRunner } from "../runtime/runner.js";
|
|
2
2
|
export interface Criterion {
|
|
3
3
|
text: string;
|
|
4
4
|
required: boolean;
|
|
@@ -58,17 +58,17 @@ export type HarnessEvent = {
|
|
|
58
58
|
type: "max_attempts_reached";
|
|
59
59
|
};
|
|
60
60
|
export declare class SinglePassHarness {
|
|
61
|
-
private
|
|
62
|
-
constructor(
|
|
61
|
+
private runner;
|
|
62
|
+
constructor(runner: RuntimeRunner);
|
|
63
63
|
run(request: HarnessRequest): Promise<HarnessOutcome>;
|
|
64
64
|
}
|
|
65
65
|
export interface HarnessLoopOptions {
|
|
66
66
|
maxAttempts?: number;
|
|
67
67
|
}
|
|
68
68
|
export declare class HarnessLoop {
|
|
69
|
-
private
|
|
69
|
+
private runner;
|
|
70
70
|
private evalProvider;
|
|
71
71
|
private maxAttempts;
|
|
72
|
-
constructor(
|
|
72
|
+
constructor(runner: RuntimeRunner, evalProvider: import("../types.js").LLMProvider, options?: HarnessLoopOptions);
|
|
73
73
|
runStreaming(request: HarnessRequest): AsyncIterable<HarnessEvent>;
|
|
74
74
|
}
|
package/dist/harness/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
async function runOnce(
|
|
1
|
+
async function runOnce(runner, req) {
|
|
2
2
|
let text = "";
|
|
3
3
|
let done;
|
|
4
|
-
|
|
4
|
+
const sessionId = crypto.randomUUID();
|
|
5
|
+
for await (const evt of runner.run({ sessionId, goal: req.goal, criteria: req.criteria?.map(c => c.text), extensions: req.extensions })) {
|
|
5
6
|
if (evt.type === "text_delta")
|
|
6
7
|
text += evt.delta;
|
|
7
8
|
else if (evt.type === "done")
|
|
@@ -10,20 +11,20 @@ async function runOnce(agent, goal, req) {
|
|
|
10
11
|
return { result: text, passed: false, iterations: done?.iterations ?? 0, totalTokens: done?.totalTokens ?? 0, status: done?.status ?? "error" };
|
|
11
12
|
}
|
|
12
13
|
export class SinglePassHarness {
|
|
13
|
-
|
|
14
|
-
constructor(
|
|
15
|
-
this.
|
|
14
|
+
runner;
|
|
15
|
+
constructor(runner) {
|
|
16
|
+
this.runner = runner;
|
|
16
17
|
}
|
|
17
18
|
async run(request) {
|
|
18
|
-
return { ...await runOnce(this.
|
|
19
|
+
return { ...await runOnce(this.runner, request), passed: true };
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
export class HarnessLoop {
|
|
22
|
-
|
|
23
|
+
runner;
|
|
23
24
|
evalProvider;
|
|
24
25
|
maxAttempts;
|
|
25
|
-
constructor(
|
|
26
|
-
this.
|
|
26
|
+
constructor(runner, evalProvider, options = {}) {
|
|
27
|
+
this.runner = runner;
|
|
27
28
|
this.evalProvider = evalProvider;
|
|
28
29
|
this.maxAttempts = options.maxAttempts ?? 3;
|
|
29
30
|
}
|
|
@@ -36,8 +37,9 @@ export class HarnessLoop {
|
|
|
36
37
|
let lastTotalTokens = 0;
|
|
37
38
|
let lastStatus = "error";
|
|
38
39
|
let lastResult = "";
|
|
40
|
+
const sessionId = crypto.randomUUID();
|
|
39
41
|
for (let attempt = 1; attempt <= this.maxAttempts; attempt++) {
|
|
40
|
-
for await (const evt of this.
|
|
42
|
+
for await (const evt of this.runner.run({ sessionId, goal: currentGoal, criteria: criteria.map(c => c.text), extensions: request.extensions })) {
|
|
41
43
|
if (evt.type === "text_delta") {
|
|
42
44
|
lastResult += evt.delta;
|
|
43
45
|
yield { type: "token", text: evt.delta };
|
|
@@ -64,7 +66,11 @@ export class HarnessLoop {
|
|
|
64
66
|
if (evalAction.kind !== "evaluate")
|
|
65
67
|
break;
|
|
66
68
|
let evalText = "";
|
|
67
|
-
|
|
69
|
+
const evalContext = {
|
|
70
|
+
systemText: "",
|
|
71
|
+
turns: (evalAction.messages ?? []),
|
|
72
|
+
};
|
|
73
|
+
for await (const evt of this.evalProvider.stream(evalContext, [], undefined)) {
|
|
68
74
|
if (evt.type === "text_delta")
|
|
69
75
|
evalText += evt.delta;
|
|
70
76
|
}
|
|
@@ -75,7 +81,7 @@ export class HarnessLoop {
|
|
|
75
81
|
passed: doneAction.passed ?? false,
|
|
76
82
|
overallScore: doneAction.overallScore ?? 0,
|
|
77
83
|
feedback: doneAction.feedback ?? "",
|
|
78
|
-
details: doneAction.details ?? [],
|
|
84
|
+
details: (doneAction.details ?? []),
|
|
79
85
|
};
|
|
80
86
|
if (verdict.passed) {
|
|
81
87
|
yield { type: "done", verdict, iterations: lastIterations, totalTokens: lastTotalTokens, status: lastStatus };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export type {
|
|
1
|
+
export { RuntimeRunner, collectText, InMemorySessionLog, LocalExecutionPlane, } from "./runtime/index.js";
|
|
2
|
+
export type { RuntimeOptions, SessionEvent, SessionLog, RunContext, ExecutionPlane, } from "./runtime/index.js";
|
|
3
3
|
export { Governance } from "./governance.js";
|
|
4
4
|
export type { GovernanceVerdict } from "./governance.js";
|
|
5
5
|
export { AnthropicProvider } from "./providers/anthropic.js";
|
|
@@ -7,7 +7,7 @@ export { OpenAIProvider, QwenProvider, DeepSeekProvider, MiniMaxProvider, KimiPr
|
|
|
7
7
|
export { tool, executeTools } from "./tools/index.js";
|
|
8
8
|
export type { RegisteredTool } from "./tools/index.js";
|
|
9
9
|
export { WorkingMemory } from "./memory/index.js";
|
|
10
|
-
export type { DreamStore, DreamResult, SessionData, SessionMessage, MemoryEntry, CurationResult, CurationStats, } from "./memory/index.js";
|
|
10
|
+
export type { DreamStore, DreamResult, SessionStore, SessionData, SessionMessage, MemoryEntry, CurationResult, CurationStats, } from "./memory/index.js";
|
|
11
11
|
export type { KnowledgeSource } from "./knowledge/index.js";
|
|
12
12
|
export { SinglePassHarness, HarnessLoop } from "./harness/index.js";
|
|
13
13
|
export type { HarnessRequest, HarnessOutcome, HarnessLoopOptions } from "./harness/index.js";
|
|
@@ -15,4 +15,4 @@ export { ScheduledPrompt } from "./signals/index.js";
|
|
|
15
15
|
export type { RuntimeSignal, SignalSource } from "./signals/index.js";
|
|
16
16
|
export { PermissionManager, PermissionMode } from "./safety/index.js";
|
|
17
17
|
export type { PermissionDecision } from "./safety/index.js";
|
|
18
|
-
export type { Message, ToolCall, ToolResult, ToolSchema, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolResultEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, LLMProvider, } from "./types.js";
|
|
18
|
+
export type { Message, ToolCall, ToolResult, ToolSchema, RenderedContext, ProviderRunState, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolResultEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, LLMProvider, } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { RuntimeRunner, collectText, InMemorySessionLog, LocalExecutionPlane, } from "./runtime/index.js";
|
|
2
2
|
export { Governance } from "./governance.js";
|
|
3
3
|
export { AnthropicProvider } from "./providers/anthropic.js";
|
|
4
4
|
export { OpenAIProvider, QwenProvider, DeepSeekProvider, MiniMaxProvider, KimiProvider } from "./providers/openai.js";
|
package/dist/memory/index.d.ts
CHANGED
|
@@ -54,3 +54,7 @@ export interface DreamStore {
|
|
|
54
54
|
/** Persist a completed session for future consolidation via `Agent.dream()`. */
|
|
55
55
|
saveSession(data: SessionData): Promise<void>;
|
|
56
56
|
}
|
|
57
|
+
export interface SessionStore {
|
|
58
|
+
loadSession(sessionId: string): Promise<SessionData | undefined>;
|
|
59
|
+
saveSession(data: SessionData): Promise<void>;
|
|
60
|
+
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RenderedContext, ToolSchema, StreamEvent, LLMProvider, Message } from "../types.js";
|
|
2
2
|
export declare class AnthropicProvider implements LLMProvider {
|
|
3
3
|
private readonly apiKey;
|
|
4
4
|
private readonly model;
|
|
5
5
|
private readonly maxTokens;
|
|
6
6
|
constructor(apiKey: string, model?: string, maxTokens?: number);
|
|
7
|
-
|
|
7
|
+
complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
|
|
8
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
8
9
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { collectStreamMessage, toAnthropicMessages } from "./base.js";
|
|
1
2
|
function buildAnthropicTools(tools) {
|
|
2
3
|
return tools.map(t => ({ name: t.name, description: t.description, input_schema: JSON.parse(t.parameters) }));
|
|
3
4
|
}
|
|
@@ -10,9 +11,12 @@ export class AnthropicProvider {
|
|
|
10
11
|
this.model = model;
|
|
11
12
|
this.maxTokens = maxTokens;
|
|
12
13
|
}
|
|
13
|
-
async
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
async complete(context, tools, extensions) {
|
|
15
|
+
return collectStreamMessage(this.stream(context, tools, extensions));
|
|
16
|
+
}
|
|
17
|
+
async *stream(context, tools, extensions) {
|
|
18
|
+
const system = context.systemText || undefined;
|
|
19
|
+
const msgs = toAnthropicMessages(context);
|
|
16
20
|
const body = {
|
|
17
21
|
model: this.model,
|
|
18
22
|
max_tokens: this.maxTokens,
|
|
@@ -54,7 +58,16 @@ export class AnthropicProvider {
|
|
|
54
58
|
return;
|
|
55
59
|
try {
|
|
56
60
|
const evt = JSON.parse(data);
|
|
57
|
-
if (evt.type === "
|
|
61
|
+
if (evt.type === "message_start" || evt.type === "message_delta") {
|
|
62
|
+
const usage = (evt.usage ?? evt.message?.usage);
|
|
63
|
+
if (usage?.input_tokens != null) {
|
|
64
|
+
yield {
|
|
65
|
+
type: "usage",
|
|
66
|
+
totalTokens: usage.input_tokens + (usage.output_tokens ?? 0),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (evt.type === "content_block_start") {
|
|
58
71
|
const cb = evt.content_block;
|
|
59
72
|
if (cb.type === "tool_use")
|
|
60
73
|
toolBlocks[evt.index] = { id: cb.id, name: cb.name, argsBuf: "" };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Message, RenderedContext } from "../types.js";
|
|
2
|
+
/** Build OpenAI-compatible chat messages from a RenderedContext. */
|
|
3
|
+
export declare function toOpenAIMessages(context: RenderedContext): Array<Record<string, unknown>>;
|
|
4
|
+
/** Anthropic messages array (system is a separate top-level param). */
|
|
5
|
+
export declare function toAnthropicMessages(context: RenderedContext): Array<{
|
|
6
|
+
role: string;
|
|
7
|
+
content: string;
|
|
8
|
+
}>;
|
|
9
|
+
/** Collect a non-streaming assistant Message from stream events. */
|
|
10
|
+
export declare function collectStreamMessage(stream: AsyncIterable<{
|
|
11
|
+
type: string;
|
|
12
|
+
delta?: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
name?: string;
|
|
15
|
+
arguments?: Record<string, unknown>;
|
|
16
|
+
}>): Promise<Message>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** Build OpenAI-compatible chat messages from a RenderedContext. */
|
|
2
|
+
export function toOpenAIMessages(context) {
|
|
3
|
+
const messages = [];
|
|
4
|
+
if (context.systemText) {
|
|
5
|
+
messages.push({ role: "system", content: context.systemText });
|
|
6
|
+
}
|
|
7
|
+
for (const msg of context.turns) {
|
|
8
|
+
if (msg.role === "tool") {
|
|
9
|
+
messages.push({ role: "tool", content: msg.content });
|
|
10
|
+
continue;
|
|
11
|
+
}
|
|
12
|
+
const next = { role: msg.role, content: msg.content };
|
|
13
|
+
if (msg.role === "assistant" && msg.toolCalls?.length) {
|
|
14
|
+
next.tool_calls = msg.toolCalls.map(tc => ({
|
|
15
|
+
id: tc.id,
|
|
16
|
+
type: "function",
|
|
17
|
+
function: { name: tc.name, arguments: tc.arguments },
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
messages.push(next);
|
|
21
|
+
}
|
|
22
|
+
return messages;
|
|
23
|
+
}
|
|
24
|
+
/** Anthropic messages array (system is a separate top-level param). */
|
|
25
|
+
export function toAnthropicMessages(context) {
|
|
26
|
+
return context.turns
|
|
27
|
+
.filter(m => m.role !== "system")
|
|
28
|
+
.map(m => ({ role: m.role, content: m.content }));
|
|
29
|
+
}
|
|
30
|
+
/** Collect a non-streaming assistant Message from stream events. */
|
|
31
|
+
export async function collectStreamMessage(stream) {
|
|
32
|
+
let content = "";
|
|
33
|
+
const toolCalls = [];
|
|
34
|
+
for await (const evt of stream) {
|
|
35
|
+
if (evt.type === "text_delta" && evt.delta)
|
|
36
|
+
content += evt.delta;
|
|
37
|
+
else if (evt.type === "tool_call" && evt.id && evt.name) {
|
|
38
|
+
toolCalls.push({ id: evt.id, name: evt.name, arguments: JSON.stringify(evt.arguments ?? {}) });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { role: "assistant", content, ...(toolCalls.length ? { toolCalls } : {}) };
|
|
42
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RenderedContext, ToolSchema, StreamEvent, LLMProvider, Message } from "../types.js";
|
|
2
2
|
export declare class OpenAIProvider implements LLMProvider {
|
|
3
3
|
protected readonly apiKey: string;
|
|
4
4
|
protected readonly model: string;
|
|
@@ -12,20 +12,21 @@ export declare class OpenAIProvider implements LLMProvider {
|
|
|
12
12
|
parameters: any;
|
|
13
13
|
};
|
|
14
14
|
}[];
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
|
|
16
|
+
protected streamInner(context: RenderedContext, tools: ToolSchema[], extraBody: Record<string, unknown>, exposeReasoning?: boolean): AsyncIterable<StreamEvent>;
|
|
17
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
17
18
|
}
|
|
18
19
|
export declare class QwenProvider extends OpenAIProvider {
|
|
19
20
|
constructor(apiKey: string, model?: string);
|
|
20
|
-
stream(
|
|
21
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
21
22
|
}
|
|
22
23
|
export declare class DeepSeekProvider extends OpenAIProvider {
|
|
23
24
|
constructor(apiKey: string, model?: string);
|
|
24
|
-
stream(
|
|
25
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
25
26
|
}
|
|
26
27
|
export declare class MiniMaxProvider extends OpenAIProvider {
|
|
27
28
|
constructor(apiKey: string, model?: string);
|
|
28
|
-
stream(
|
|
29
|
+
stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
29
30
|
}
|
|
30
31
|
export declare class KimiProvider extends OpenAIProvider {
|
|
31
32
|
constructor(apiKey: string, model?: string);
|
package/dist/providers/openai.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { collectStreamMessage, toOpenAIMessages } from "./base.js";
|
|
1
2
|
const DEEPSEEK_REASONERS = new Set(["deepseek-reasoner", "deepseek-r1"]);
|
|
2
3
|
const MINIMAX_REASONERS = new Set(["MiniMax-M1", "minimax-m1"]);
|
|
3
4
|
// OpenAI-compatible provider — works for OpenAI, Qwen (DashScope), DeepSeek, MiniMax, Kimi
|
|
@@ -13,11 +14,13 @@ export class OpenAIProvider {
|
|
|
13
14
|
buildTools(tools) {
|
|
14
15
|
return tools.map(t => ({ type: "function", function: { name: t.name, description: t.description, parameters: JSON.parse(t.parameters) } }));
|
|
15
16
|
}
|
|
16
|
-
async
|
|
17
|
-
|
|
17
|
+
async complete(context, tools, extensions) {
|
|
18
|
+
return collectStreamMessage(this.stream(context, tools, extensions));
|
|
19
|
+
}
|
|
20
|
+
async *streamInner(context, tools, extraBody, exposeReasoning = false) {
|
|
18
21
|
const body = {
|
|
19
22
|
model: this.model,
|
|
20
|
-
messages:
|
|
23
|
+
messages: toOpenAIMessages(context),
|
|
21
24
|
stream: true,
|
|
22
25
|
...(tools.length ? { tools: this.buildTools(tools) } : {}),
|
|
23
26
|
...extraBody,
|
|
@@ -76,16 +79,16 @@ export class OpenAIProvider {
|
|
|
76
79
|
yield { type: "tool_call", id: tb.id, name: tb.name, arguments: args };
|
|
77
80
|
}
|
|
78
81
|
}
|
|
79
|
-
async *stream(
|
|
82
|
+
async *stream(context, tools, extensions) {
|
|
80
83
|
const { expose_reasoning: _, exposeReasoning: __, ...passthrough } = extensions ?? {};
|
|
81
|
-
yield* this.streamInner(
|
|
84
|
+
yield* this.streamInner(context, tools, passthrough);
|
|
82
85
|
}
|
|
83
86
|
}
|
|
84
87
|
export class QwenProvider extends OpenAIProvider {
|
|
85
88
|
constructor(apiKey, model = "qwen-max") {
|
|
86
89
|
super(apiKey, model, "https://dashscope.aliyuncs.com/compatible-mode/v1");
|
|
87
90
|
}
|
|
88
|
-
async *stream(
|
|
91
|
+
async *stream(context, tools, extensions) {
|
|
89
92
|
const enableThinking = Boolean(extensions?.enableThinking);
|
|
90
93
|
const thinkingBudget = extensions?.thinkingBudget;
|
|
91
94
|
const { enableThinking: _, thinkingBudget: __, expose_reasoning: ___, exposeReasoning: ____, ...passthrough } = extensions ?? {};
|
|
@@ -93,31 +96,31 @@ export class QwenProvider extends OpenAIProvider {
|
|
|
93
96
|
...passthrough,
|
|
94
97
|
...(enableThinking ? { enable_thinking: true, ...(thinkingBudget ? { thinking_budget: thinkingBudget } : {}) } : {}),
|
|
95
98
|
};
|
|
96
|
-
yield* this.streamInner(
|
|
99
|
+
yield* this.streamInner(context, tools, extra, enableThinking);
|
|
97
100
|
}
|
|
98
101
|
}
|
|
99
102
|
export class DeepSeekProvider extends OpenAIProvider {
|
|
100
103
|
constructor(apiKey, model = "deepseek-chat") {
|
|
101
104
|
super(apiKey, model, "https://api.deepseek.com/v1");
|
|
102
105
|
}
|
|
103
|
-
async *stream(
|
|
106
|
+
async *stream(context, tools, extensions) {
|
|
104
107
|
const exposeReasoning = Boolean(extensions?.exposeReasoning);
|
|
105
108
|
const isReasoner = DEEPSEEK_REASONERS.has(this.model);
|
|
106
109
|
const filteredTools = isReasoner ? [] : tools;
|
|
107
110
|
const { exposeReasoning: _, expose_reasoning: __, ...passthrough } = extensions ?? {};
|
|
108
|
-
yield* this.streamInner(
|
|
111
|
+
yield* this.streamInner(context, filteredTools, passthrough, exposeReasoning);
|
|
109
112
|
}
|
|
110
113
|
}
|
|
111
114
|
export class MiniMaxProvider extends OpenAIProvider {
|
|
112
115
|
constructor(apiKey, model = "MiniMax-Text-01") {
|
|
113
116
|
super(apiKey, model, "https://api.minimax.chat/v1");
|
|
114
117
|
}
|
|
115
|
-
async *stream(
|
|
118
|
+
async *stream(context, tools, extensions) {
|
|
116
119
|
const exposeReasoning = Boolean(extensions?.exposeReasoning);
|
|
117
120
|
const isReasoner = MINIMAX_REASONERS.has(this.model);
|
|
118
121
|
const filteredTools = isReasoner ? [] : tools;
|
|
119
122
|
const { exposeReasoning: _, expose_reasoning: __, ...passthrough } = extensions ?? {};
|
|
120
|
-
yield* this.streamInner(
|
|
123
|
+
yield* this.streamInner(context, filteredTools, passthrough, exposeReasoning);
|
|
121
124
|
}
|
|
122
125
|
}
|
|
123
126
|
export class KimiProvider extends OpenAIProvider {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ToolCall, ToolSchema, StreamEvent } from "../types.js";
|
|
2
|
+
import type { RegisteredTool } from "../tools/index.js";
|
|
3
|
+
import type { DreamStore } from "../memory/index.js";
|
|
4
|
+
import type { KnowledgeSource } from "../knowledge/index.js";
|
|
5
|
+
import type { Governance } from "../governance.js";
|
|
6
|
+
export interface ToolSuspendEvent {
|
|
7
|
+
type: "tool_suspend";
|
|
8
|
+
callId: string;
|
|
9
|
+
name: string;
|
|
10
|
+
suspensionId: string;
|
|
11
|
+
payload?: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface RunContext {
|
|
14
|
+
agentId?: string;
|
|
15
|
+
skillContentMap?: Map<string, string>;
|
|
16
|
+
dreamStore?: DreamStore;
|
|
17
|
+
knowledgeSource?: KnowledgeSource;
|
|
18
|
+
governance?: Governance;
|
|
19
|
+
onToolSuspend?: (event: ToolSuspendEvent) => Promise<unknown> | unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface ExecutionPlane {
|
|
22
|
+
register(...tools: RegisteredTool[]): this;
|
|
23
|
+
unregister(name: string): this;
|
|
24
|
+
schemas(): ToolSchema[];
|
|
25
|
+
executeAll(calls: ToolCall[], ctx: RunContext): AsyncIterable<StreamEvent>;
|
|
26
|
+
}
|
|
27
|
+
export declare class LocalExecutionPlane implements ExecutionPlane {
|
|
28
|
+
private tools;
|
|
29
|
+
register(...tools: RegisteredTool[]): this;
|
|
30
|
+
unregister(name: string): this;
|
|
31
|
+
schemas(): ToolSchema[];
|
|
32
|
+
executeAll(calls: ToolCall[], ctx: RunContext): AsyncIterable<StreamEvent>;
|
|
33
|
+
}
|