@deepstrike/wasm 0.1.11 → 0.1.15
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 +7 -2
- package/dist/providers/anthropic.js +68 -18
- package/dist/providers/base.d.ts +14 -0
- package/dist/providers/base.js +75 -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/provider-replay.d.ts +7 -0
- package/dist/runtime/provider-replay.js +18 -0
- package/dist/runtime/runner.d.ts +44 -0
- package/dist/runtime/runner.js +362 -0
- package/dist/runtime/session-log.d.ts +55 -0
- package/dist/runtime/session-log.js +18 -0
- package/dist/types.d.ts +27 -1
- package/package.json +2 -2
- package/dist/agent.d.ts +0 -57
- package/dist/agent.js +0 -244
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
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
function stripFrontmatter(content) {
|
|
2
|
+
const s = content.trimStart();
|
|
3
|
+
if (!s.startsWith("---"))
|
|
4
|
+
return s;
|
|
5
|
+
const rest = s.slice(3);
|
|
6
|
+
const end = rest.indexOf("\n---");
|
|
7
|
+
return end >= 0 ? rest.slice(end + 4).trimStart() : s;
|
|
8
|
+
}
|
|
9
|
+
export class LocalExecutionPlane {
|
|
10
|
+
tools = new Map();
|
|
11
|
+
register(...tools) {
|
|
12
|
+
for (const t of tools)
|
|
13
|
+
this.tools.set(t.schema.name, t);
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
unregister(name) {
|
|
17
|
+
this.tools.delete(name);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
schemas() {
|
|
21
|
+
return Array.from(this.tools.values()).map(t => t.schema);
|
|
22
|
+
}
|
|
23
|
+
async *executeAll(calls, ctx) {
|
|
24
|
+
const permitted = [];
|
|
25
|
+
for (const c of calls) {
|
|
26
|
+
if (ctx.governance) {
|
|
27
|
+
ctx.governance.setTime(Date.now());
|
|
28
|
+
const v = ctx.governance.evaluate(c.name, c.arguments);
|
|
29
|
+
if (v.kind === "deny") {
|
|
30
|
+
yield { type: "error", message: `permission denied: ${c.name} — ${v.reason ?? ""}` };
|
|
31
|
+
yield { type: "tool_result", callId: c.id, name: c.name, content: `permission denied: ${v.reason ?? ""}`, isError: true };
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (v.kind === "rate_limited") {
|
|
35
|
+
yield { type: "error", message: `rate limited: ${c.name}` };
|
|
36
|
+
yield { type: "tool_result", callId: c.id, name: c.name, content: "rate limited", isError: true };
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (v.kind === "ask_user") {
|
|
40
|
+
yield { type: "permission_request", callId: c.id, toolName: c.name, arguments: c.arguments, reason: v.reason ?? "" };
|
|
41
|
+
yield { type: "tool_result", callId: c.id, name: c.name, content: "awaiting user approval", isError: true };
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
permitted.push(c);
|
|
46
|
+
}
|
|
47
|
+
const skillCalls = permitted.filter(c => c.name === "skill");
|
|
48
|
+
const memoryCalls = permitted.filter(c => c.name === "memory");
|
|
49
|
+
const knowledgeCalls = permitted.filter(c => c.name === "knowledge");
|
|
50
|
+
const regularCalls = permitted.filter(c => !["skill", "memory", "knowledge"].includes(c.name));
|
|
51
|
+
for (const c of skillCalls) {
|
|
52
|
+
const args = tryParseJson(c.arguments);
|
|
53
|
+
const name = String(args?.name ?? "");
|
|
54
|
+
const raw = ctx.skillContentMap?.get(name);
|
|
55
|
+
const content = raw != null ? stripFrontmatter(raw) : null;
|
|
56
|
+
yield {
|
|
57
|
+
type: "tool_result",
|
|
58
|
+
callId: c.id,
|
|
59
|
+
name: c.name,
|
|
60
|
+
content: content ?? `Skill "${name}" not found.`,
|
|
61
|
+
isError: content == null,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
for (const c of memoryCalls) {
|
|
65
|
+
const args = tryParseJson(c.arguments);
|
|
66
|
+
const topK = typeof args?.top_k === "number" ? args.top_k : 5;
|
|
67
|
+
const entries = (ctx.dreamStore && ctx.agentId)
|
|
68
|
+
? await ctx.dreamStore.search(ctx.agentId, String(args?.query ?? ""), topK)
|
|
69
|
+
: [];
|
|
70
|
+
const content = entries.length
|
|
71
|
+
? entries.map((e) => `[score=${e.score.toFixed(3)}] ${e.text}`).join("\n---\n")
|
|
72
|
+
: "No relevant memories found.";
|
|
73
|
+
yield { type: "tool_result", callId: c.id, name: c.name, content, isError: false };
|
|
74
|
+
}
|
|
75
|
+
for (const c of knowledgeCalls) {
|
|
76
|
+
const args = tryParseJson(c.arguments);
|
|
77
|
+
const topK = typeof args?.top_k === "number" ? args.top_k : 5;
|
|
78
|
+
const snippets = ctx.knowledgeSource
|
|
79
|
+
? await ctx.knowledgeSource.retrieve(String(args?.query ?? ""), topK)
|
|
80
|
+
: [];
|
|
81
|
+
const content = snippets.length ? snippets.join("\n---\n") : "No relevant knowledge found.";
|
|
82
|
+
yield { type: "tool_result", callId: c.id, name: c.name, content, isError: false };
|
|
83
|
+
}
|
|
84
|
+
for (const call of regularCalls) {
|
|
85
|
+
const registered = this.tools.get(call.name);
|
|
86
|
+
if (!registered) {
|
|
87
|
+
yield { type: "tool_result", callId: call.id, name: call.name, content: `unknown tool: ${call.name}`, isError: true };
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const args = JSON.parse(call.arguments || "{}");
|
|
92
|
+
const output = await registered.execute(args);
|
|
93
|
+
yield { type: "tool_result", callId: call.id, name: call.name, content: String(output), isError: false };
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
yield { type: "tool_result", callId: call.id, name: call.name, content: String(err), isError: true };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
function tryParseJson(s) {
|
|
102
|
+
try {
|
|
103
|
+
return JSON.parse(s);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { SessionEvent, SessionLog } from "./session-log.js";
|
|
2
|
+
export { InMemorySessionLog } from "./session-log.js";
|
|
3
|
+
export type { RunContext, ExecutionPlane } from "./execution-plane.js";
|
|
4
|
+
export { LocalExecutionPlane } from "./execution-plane.js";
|
|
5
|
+
export type { RuntimeOptions } from "./runner.js";
|
|
6
|
+
export { RuntimeRunner, collectText } from "./runner.js";
|
|
7
|
+
export { getKernel } from "./kernel.js";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LLMProvider, Message, ProviderReplay, ToolCall } from "../types.js";
|
|
2
|
+
import type { SessionEvent } from "./session-log.js";
|
|
3
|
+
export declare function assistantReplayKey(message: Pick<Message, "content" | "toolCalls">): string;
|
|
4
|
+
export declare function seedProviderReplayFromEvents(provider: LLMProvider, events: Array<{
|
|
5
|
+
event: SessionEvent;
|
|
6
|
+
}>): void;
|
|
7
|
+
export declare function peekProviderReplay(provider: LLMProvider, content: string, toolCalls: ToolCall[]): ProviderReplay | undefined;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function assistantReplayKey(message) {
|
|
2
|
+
return JSON.stringify({
|
|
3
|
+
content: message.content,
|
|
4
|
+
toolCalls: message.toolCalls ?? [],
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
export function seedProviderReplayFromEvents(provider, events) {
|
|
8
|
+
if (!provider.seedProviderReplay)
|
|
9
|
+
return;
|
|
10
|
+
for (const { event } of events) {
|
|
11
|
+
if (event.kind !== "llm_completed" || !event.provider_replay)
|
|
12
|
+
continue;
|
|
13
|
+
provider.seedProviderReplay({ content: event.content, toolCalls: event.tool_calls ?? [] }, event.provider_replay);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
export function peekProviderReplay(provider, content, toolCalls) {
|
|
17
|
+
return provider.peekProviderReplay?.({ content, toolCalls });
|
|
18
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { LLMProvider, StreamEvent } from "../types.js";
|
|
2
|
+
import type { ToolSuspendEvent } from "./execution-plane.js";
|
|
3
|
+
import type { DreamStore, DreamResult } from "../memory/index.js";
|
|
4
|
+
import type { KnowledgeSource } from "../knowledge/index.js";
|
|
5
|
+
import type { SignalSource } from "../signals/index.js";
|
|
6
|
+
import type { SessionLog } from "./session-log.js";
|
|
7
|
+
import type { ExecutionPlane } from "./execution-plane.js";
|
|
8
|
+
import type { Governance } from "../governance.js";
|
|
9
|
+
export interface RuntimeOptions {
|
|
10
|
+
provider: LLMProvider;
|
|
11
|
+
sessionLog: SessionLog;
|
|
12
|
+
executionPlane: ExecutionPlane;
|
|
13
|
+
maxTokens: number;
|
|
14
|
+
maxTurns?: number;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
agentId?: string;
|
|
17
|
+
systemPrompt?: string;
|
|
18
|
+
initialMemory?: string[];
|
|
19
|
+
/** Skill name → markdown body (WASM has no filesystem). */
|
|
20
|
+
skillContentMap?: Map<string, string>;
|
|
21
|
+
dreamStore?: DreamStore;
|
|
22
|
+
knowledgeSource?: KnowledgeSource;
|
|
23
|
+
signalSource?: SignalSource;
|
|
24
|
+
extensions?: Record<string, unknown>;
|
|
25
|
+
governance?: Governance;
|
|
26
|
+
onToolSuspend?: (event: ToolSuspendEvent) => Promise<unknown> | unknown;
|
|
27
|
+
}
|
|
28
|
+
export declare class RuntimeRunner {
|
|
29
|
+
private readonly opts;
|
|
30
|
+
private interrupted;
|
|
31
|
+
constructor(opts: RuntimeOptions);
|
|
32
|
+
interrupt(): void;
|
|
33
|
+
run(req: {
|
|
34
|
+
sessionId: string;
|
|
35
|
+
goal: string;
|
|
36
|
+
criteria?: string[];
|
|
37
|
+
extensions?: Record<string, unknown>;
|
|
38
|
+
}): AsyncIterable<StreamEvent>;
|
|
39
|
+
wake(sessionId: string, extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
40
|
+
dream(agentId: string, nowMs?: number): Promise<DreamResult>;
|
|
41
|
+
private execute;
|
|
42
|
+
private appendObservations;
|
|
43
|
+
}
|
|
44
|
+
export declare function collectText(stream: AsyncIterable<StreamEvent>): Promise<string>;
|