@deepstrike/wasm 0.2.72 → 0.2.74
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/dist/agent.d.ts +123 -22
- package/dist/agent.js +210 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -1
- package/dist/memory/durable.d.ts +1 -1
- package/dist/memory/durable.js +2 -2
- package/dist/providers/request-plan.d.ts +2 -2
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/mcp-transport.d.ts +43 -0
- package/dist/runtime/mcp-transport.js +58 -0
- package/dist/types.d.ts +4 -4
- package/package.json +3 -3
- package/dist/agent-ir.d.ts +0 -81
- package/dist/agent-ir.js +0 -115
package/dist/agent.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import type { AgentCapabilityFilter } from "./runtime/types/agent.js";
|
|
2
|
-
import type { Memory, WorkingMemory } from "./memory/index.js";
|
|
1
|
+
import type { AgentCapabilityFilter, WorkflowOutcome, WorkflowSpec } from "./runtime/types/agent.js";
|
|
2
|
+
import type { Memory, WorkingMemory, MemoryRecord, MemoryRecall, MemoryKind } from "./memory/index.js";
|
|
3
3
|
import type { RegisteredTool } from "./tools/index.js";
|
|
4
|
+
import type { LLMProvider, StreamEvent, ContentPart } from "./types.js";
|
|
5
|
+
import { RuntimeRunner } from "./runtime/runner.js";
|
|
6
|
+
import { type ExecutionPlane } from "./runtime/execution-plane.js";
|
|
7
|
+
import { type SessionEvent, type SessionLog } from "./runtime/session-log.js";
|
|
8
|
+
import type { SignalSource } from "./signals/index.js";
|
|
9
|
+
import type { McpExecutionPlane } from "./runtime/mcp-transport.js";
|
|
4
10
|
type JsonSchema = Record<string, unknown>;
|
|
5
11
|
export interface MemoryReference {
|
|
6
12
|
kind?: "durable";
|
|
@@ -29,10 +35,7 @@ export type McpTransport = {
|
|
|
29
35
|
command: string;
|
|
30
36
|
args?: string[];
|
|
31
37
|
} | {
|
|
32
|
-
kind: "http";
|
|
33
|
-
url: string;
|
|
34
|
-
} | {
|
|
35
|
-
kind: "sse";
|
|
38
|
+
kind: "http" | "sse";
|
|
36
39
|
url: string;
|
|
37
40
|
} | {
|
|
38
41
|
kind: "custom";
|
|
@@ -61,22 +64,7 @@ export interface Skill {
|
|
|
61
64
|
providerOptions?: Record<string, unknown>;
|
|
62
65
|
}
|
|
63
66
|
export type KnowledgeSourceRef = {
|
|
64
|
-
kind: "file";
|
|
65
|
-
path: string;
|
|
66
|
-
} | {
|
|
67
|
-
kind: "directory";
|
|
68
|
-
path: string;
|
|
69
|
-
} | {
|
|
70
|
-
kind: "text";
|
|
71
|
-
content: string;
|
|
72
|
-
} | {
|
|
73
|
-
kind: "url";
|
|
74
|
-
url: string;
|
|
75
|
-
} | {
|
|
76
|
-
kind: "vector";
|
|
77
|
-
retriever: unknown;
|
|
78
|
-
} | {
|
|
79
|
-
kind: "custom";
|
|
67
|
+
kind: "file" | "directory" | "text" | "url" | "vector" | "custom";
|
|
80
68
|
[key: string]: unknown;
|
|
81
69
|
};
|
|
82
70
|
export interface Knowledge {
|
|
@@ -102,6 +90,16 @@ export interface Guardrail {
|
|
|
102
90
|
description?: string;
|
|
103
91
|
metadata?: Record<string, unknown>;
|
|
104
92
|
}
|
|
93
|
+
export interface AgentRuntimeBinding {
|
|
94
|
+
provider?: LLMProvider;
|
|
95
|
+
providerFor?: (model: string) => LLMProvider | undefined;
|
|
96
|
+
runtimeOptions?: Partial<import("./runtime/runner.js").RuntimeOptions>;
|
|
97
|
+
sessionLog?: SessionLog;
|
|
98
|
+
executionPlane?: ExecutionPlane;
|
|
99
|
+
mcpPlane?: McpExecutionPlane;
|
|
100
|
+
resolveAgent?: (name: string) => Agent | undefined | Promise<Agent | undefined>;
|
|
101
|
+
signalSource?: SignalSource;
|
|
102
|
+
}
|
|
105
103
|
export interface AgentOptions {
|
|
106
104
|
name: string;
|
|
107
105
|
description?: string;
|
|
@@ -118,6 +116,86 @@ export interface AgentOptions {
|
|
|
118
116
|
outputSchema?: JsonSchema;
|
|
119
117
|
metadata?: Record<string, unknown>;
|
|
120
118
|
guardrails?: Guardrail[];
|
|
119
|
+
runtimeBinding?: AgentRuntimeBinding;
|
|
120
|
+
}
|
|
121
|
+
export interface AgentRunOptions {
|
|
122
|
+
sessionId?: string;
|
|
123
|
+
maxTurns?: number;
|
|
124
|
+
maxTotalTokens?: number;
|
|
125
|
+
timeoutMs?: number;
|
|
126
|
+
metadata?: Record<string, unknown>;
|
|
127
|
+
providerOptions?: Record<string, unknown>;
|
|
128
|
+
attachments?: ContentPart[];
|
|
129
|
+
cancelSignal?: AbortSignal;
|
|
130
|
+
}
|
|
131
|
+
export interface AgentRunResult {
|
|
132
|
+
output: string;
|
|
133
|
+
runId?: string;
|
|
134
|
+
sessionId: string;
|
|
135
|
+
status: "completed" | "partial" | "failed" | "cancelled";
|
|
136
|
+
usage?: {
|
|
137
|
+
inputTokens: number;
|
|
138
|
+
outputTokens: number;
|
|
139
|
+
totalTokens: number;
|
|
140
|
+
};
|
|
141
|
+
outputValidation?: {
|
|
142
|
+
ok: boolean;
|
|
143
|
+
errors: string[];
|
|
144
|
+
};
|
|
145
|
+
evidence?: {
|
|
146
|
+
route?: unknown;
|
|
147
|
+
measurement?: unknown;
|
|
148
|
+
contextBinding?: unknown;
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
export interface MemoryInput {
|
|
152
|
+
name: string;
|
|
153
|
+
content: string;
|
|
154
|
+
description?: string;
|
|
155
|
+
kind?: MemoryKind;
|
|
156
|
+
confidence?: number;
|
|
157
|
+
pinned?: boolean;
|
|
158
|
+
ttlDays?: number;
|
|
159
|
+
}
|
|
160
|
+
export interface RecallOptions {
|
|
161
|
+
topK?: number;
|
|
162
|
+
kinds?: MemoryKind[];
|
|
163
|
+
minScore?: number;
|
|
164
|
+
}
|
|
165
|
+
export interface DelegationResult {
|
|
166
|
+
output: string;
|
|
167
|
+
status: "completed" | "partial" | "failed";
|
|
168
|
+
}
|
|
169
|
+
export declare class AgentSession {
|
|
170
|
+
private readonly owner;
|
|
171
|
+
readonly id: string;
|
|
172
|
+
private activeRunner?;
|
|
173
|
+
constructor(owner: Agent, id: string);
|
|
174
|
+
history(fromSeq?: number): Promise<{
|
|
175
|
+
seq: number;
|
|
176
|
+
event: SessionEvent;
|
|
177
|
+
}[]>;
|
|
178
|
+
latestSeq(): Promise<number>;
|
|
179
|
+
workflowTrace(): Promise<{
|
|
180
|
+
seq: number;
|
|
181
|
+
event: SessionEvent;
|
|
182
|
+
}[]>;
|
|
183
|
+
workflowReplay(): Promise<{
|
|
184
|
+
events: {
|
|
185
|
+
seq: number;
|
|
186
|
+
event: SessionEvent;
|
|
187
|
+
}[];
|
|
188
|
+
nodeOutcomes: Record<string, unknown>[];
|
|
189
|
+
completed: boolean;
|
|
190
|
+
}>;
|
|
191
|
+
private runner;
|
|
192
|
+
stream(goal: string, options?: Omit<AgentRunOptions, "sessionId">): AsyncIterable<StreamEvent>;
|
|
193
|
+
run(goal: string, options?: Omit<AgentRunOptions, "sessionId">): Promise<AgentRunResult>;
|
|
194
|
+
resume(options?: Omit<AgentRunOptions, "sessionId">): AsyncIterable<StreamEvent>;
|
|
195
|
+
interrupt(reason?: "user" | "deadline" | "lease_lost" | "host_shutdown"): void;
|
|
196
|
+
remember(input: MemoryInput): Promise<MemoryRecord>;
|
|
197
|
+
recall(query: string, options?: RecallOptions): Promise<MemoryRecall[]>;
|
|
198
|
+
workflow(spec: WorkflowSpec): Promise<WorkflowOutcome>;
|
|
121
199
|
}
|
|
122
200
|
export declare class Agent {
|
|
123
201
|
readonly name: string;
|
|
@@ -135,6 +213,29 @@ export declare class Agent {
|
|
|
135
213
|
readonly outputSchema?: JsonSchema;
|
|
136
214
|
readonly metadata?: Record<string, unknown>;
|
|
137
215
|
readonly guardrails?: Guardrail[];
|
|
216
|
+
readonly runtimeBinding?: AgentRuntimeBinding;
|
|
217
|
+
readonly sessionLog: SessionLog;
|
|
218
|
+
private readonly sessions;
|
|
138
219
|
constructor(options: AgentOptions);
|
|
220
|
+
session(id?: string): AgentSession;
|
|
221
|
+
createRunner(_goal: string, _sessionId: string, options?: AgentRunOptions): Promise<RuntimeRunner>;
|
|
222
|
+
run(goal: string, options?: AgentRunOptions): Promise<AgentRunResult>;
|
|
223
|
+
stream(goal: string, options?: AgentRunOptions): AsyncIterable<StreamEvent>;
|
|
224
|
+
resume(sessionId: string, options?: Omit<AgentRunOptions, "sessionId">): AsyncIterable<StreamEvent>;
|
|
225
|
+
interrupt(reason?: "user" | "deadline" | "lease_lost" | "host_shutdown", sessionId?: string): void;
|
|
226
|
+
workflow(spec: WorkflowSpec, options?: {
|
|
227
|
+
sessionId?: string;
|
|
228
|
+
}): Promise<WorkflowOutcome>;
|
|
229
|
+
remember(input: MemoryInput, sessionId?: string): Promise<MemoryRecord>;
|
|
230
|
+
recall(query: string, options?: RecallOptions, _sessionId?: string): Promise<MemoryRecall[]>;
|
|
231
|
+
delegate(request: {
|
|
232
|
+
target: AgentRef;
|
|
233
|
+
goal: string;
|
|
234
|
+
metadata?: Record<string, unknown>;
|
|
235
|
+
providerOptions?: Record<string, unknown>;
|
|
236
|
+
}): Promise<DelegationResult>;
|
|
237
|
+
listen(): Promise<AgentRunResult | null>;
|
|
238
|
+
close(): Promise<void>;
|
|
239
|
+
result(sessionId: string, events: StreamEvent[]): Promise<AgentRunResult>;
|
|
139
240
|
}
|
|
140
241
|
export {};
|
package/dist/agent.js
CHANGED
|
@@ -1,3 +1,98 @@
|
|
|
1
|
+
import { RuntimeRunner } from "./runtime/runner.js";
|
|
2
|
+
import { LocalExecutionPlane } from "./runtime/execution-plane.js";
|
|
3
|
+
import { InMemorySessionLog } from "./runtime/session-log.js";
|
|
4
|
+
import { extractJsonValue, validateAgainstSchema } from "./runtime/output-schema.js";
|
|
5
|
+
function statusOf(reason) {
|
|
6
|
+
if (["completed", "success", "done"].includes(reason))
|
|
7
|
+
return "completed";
|
|
8
|
+
if (["cancelled", "user", "user_abort", "deadline", "timeout"].includes(reason))
|
|
9
|
+
return "cancelled";
|
|
10
|
+
if (["failed", "error", "invalid_arg"].includes(reason))
|
|
11
|
+
return "failed";
|
|
12
|
+
return "partial";
|
|
13
|
+
}
|
|
14
|
+
export class AgentSession {
|
|
15
|
+
owner;
|
|
16
|
+
id;
|
|
17
|
+
activeRunner;
|
|
18
|
+
constructor(owner, id) {
|
|
19
|
+
this.owner = owner;
|
|
20
|
+
this.id = id;
|
|
21
|
+
}
|
|
22
|
+
history(fromSeq = 0) { return this.owner.sessionLog.read(this.id, fromSeq); }
|
|
23
|
+
latestSeq() { return this.owner.sessionLog.latestSeq(this.id); }
|
|
24
|
+
async workflowTrace() {
|
|
25
|
+
const kinds = new Set(["workflow_batch_spawned", "workflow_node_completed", "workflow_nodes_submitted", "workflow_completed"]);
|
|
26
|
+
return (await this.history()).filter(entry => kinds.has(entry.event.kind));
|
|
27
|
+
}
|
|
28
|
+
async workflowReplay() {
|
|
29
|
+
const events = await this.workflowTrace();
|
|
30
|
+
const outcomes = new Map();
|
|
31
|
+
let completed = false;
|
|
32
|
+
for (const entry of events) {
|
|
33
|
+
if (entry.event.kind === "workflow_node_completed") {
|
|
34
|
+
const id = entry.event.agent_id;
|
|
35
|
+
if (id)
|
|
36
|
+
outcomes.set(id, entry.event);
|
|
37
|
+
}
|
|
38
|
+
if (entry.event.kind === "workflow_completed") {
|
|
39
|
+
completed = true;
|
|
40
|
+
for (const outcome of entry.event.node_outcomes) {
|
|
41
|
+
const id = outcome.node_id;
|
|
42
|
+
if (id)
|
|
43
|
+
outcomes.set(id, outcome);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return { events, nodeOutcomes: [...outcomes.values()], completed };
|
|
48
|
+
}
|
|
49
|
+
runner(goal, options = {}) { return this.owner.createRunner(goal, this.id, options); }
|
|
50
|
+
async *stream(goal, options = {}) {
|
|
51
|
+
const runner = await this.runner(goal, { ...options, sessionId: this.id });
|
|
52
|
+
this.activeRunner = runner;
|
|
53
|
+
const abort = () => runner.interrupt("user");
|
|
54
|
+
if (options.cancelSignal?.aborted)
|
|
55
|
+
abort();
|
|
56
|
+
else
|
|
57
|
+
options.cancelSignal?.addEventListener("abort", abort, { once: true });
|
|
58
|
+
try {
|
|
59
|
+
yield* runner.run({ sessionId: this.id, goal, attachments: options.attachments, extensions: options.providerOptions });
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
options.cancelSignal?.removeEventListener("abort", abort);
|
|
63
|
+
this.activeRunner = undefined;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
async run(goal, options = {}) {
|
|
67
|
+
const events = [];
|
|
68
|
+
for await (const event of this.stream(goal, options))
|
|
69
|
+
events.push(event);
|
|
70
|
+
return this.owner.result(this.id, events);
|
|
71
|
+
}
|
|
72
|
+
async *resume(options = {}) {
|
|
73
|
+
const runner = await this.runner("resume", { ...options, sessionId: this.id });
|
|
74
|
+
this.activeRunner = runner;
|
|
75
|
+
try {
|
|
76
|
+
yield* runner.wake(this.id, options.providerOptions);
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
this.activeRunner = undefined;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
interrupt(reason = "user") { this.activeRunner?.interrupt(reason); }
|
|
83
|
+
remember(input) { return this.owner.remember(input, this.id); }
|
|
84
|
+
recall(query, options = {}) { return this.owner.recall(query, options, this.id); }
|
|
85
|
+
async workflow(spec) {
|
|
86
|
+
const runner = await this.runner("workflow", { sessionId: this.id });
|
|
87
|
+
this.activeRunner = runner;
|
|
88
|
+
try {
|
|
89
|
+
return await runner.runWorkflow(spec, { sessionId: this.id });
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
this.activeRunner = undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
1
96
|
export class Agent {
|
|
2
97
|
name;
|
|
3
98
|
description;
|
|
@@ -14,6 +109,9 @@ export class Agent {
|
|
|
14
109
|
outputSchema;
|
|
15
110
|
metadata;
|
|
16
111
|
guardrails;
|
|
112
|
+
runtimeBinding;
|
|
113
|
+
sessionLog;
|
|
114
|
+
sessions = new Map();
|
|
17
115
|
constructor(options) {
|
|
18
116
|
this.name = options.name;
|
|
19
117
|
this.description = options.description;
|
|
@@ -30,5 +128,117 @@ export class Agent {
|
|
|
30
128
|
this.outputSchema = options.outputSchema;
|
|
31
129
|
this.metadata = options.metadata;
|
|
32
130
|
this.guardrails = options.guardrails;
|
|
131
|
+
this.runtimeBinding = options.runtimeBinding;
|
|
132
|
+
this.sessionLog = options.runtimeBinding?.sessionLog ?? options.runtimeBinding?.runtimeOptions?.sessionLog ?? new InMemorySessionLog();
|
|
133
|
+
}
|
|
134
|
+
session(id = `session-${crypto.randomUUID()}`) { if (!this.sessions.has(id))
|
|
135
|
+
this.sessions.set(id, new AgentSession(this, id)); return this.sessions.get(id); }
|
|
136
|
+
async createRunner(_goal, _sessionId, options = {}) {
|
|
137
|
+
const binding = this.runtimeBinding;
|
|
138
|
+
const provider = binding?.provider ?? (typeof this.model === "string" ? binding?.providerFor?.(this.model) : undefined);
|
|
139
|
+
if (!provider)
|
|
140
|
+
throw new Error(`agent "${this.name}" has no runtime provider binding`);
|
|
141
|
+
const base = { ...(binding?.runtimeOptions ?? {}) };
|
|
142
|
+
if (options.maxTurns !== undefined)
|
|
143
|
+
base.maxTurns = options.maxTurns;
|
|
144
|
+
if (options.maxTotalTokens !== undefined)
|
|
145
|
+
base.maxTotalTokens = options.maxTotalTokens;
|
|
146
|
+
if (options.timeoutMs !== undefined)
|
|
147
|
+
base.timeoutMs = options.timeoutMs;
|
|
148
|
+
if (options.providerOptions)
|
|
149
|
+
base.extensions = { ...(base.extensions ?? {}), ...options.providerOptions };
|
|
150
|
+
const mcpPlane = binding?.mcpPlane;
|
|
151
|
+
if (mcpPlane)
|
|
152
|
+
await mcpPlane.connect();
|
|
153
|
+
return new RuntimeRunner({ provider, executionPlane: binding?.executionPlane ?? mcpPlane ?? new LocalExecutionPlane(), sessionLog: this.sessionLog, maxTokens: 32_000, agentId: this.name, ...(this.instructions ? { systemPrompt: this.instructions } : {}), ...base });
|
|
154
|
+
}
|
|
155
|
+
async run(goal, options = {}) { return this.session(options.sessionId).run(goal, options); }
|
|
156
|
+
stream(goal, options = {}) { return this.session(options.sessionId).stream(goal, options); }
|
|
157
|
+
resume(sessionId, options = {}) { return this.session(sessionId).resume(options); }
|
|
158
|
+
interrupt(reason = "user", sessionId) { sessionId ? this.session(sessionId).interrupt(reason) : [...this.sessions.values()].forEach(s => s.interrupt(reason)); }
|
|
159
|
+
workflow(spec, options = {}) { return this.session(options.sessionId).workflow(spec); }
|
|
160
|
+
async remember(input, sessionId) {
|
|
161
|
+
if (!this.memory || typeof this.memory.put !== "function")
|
|
162
|
+
throw new Error(`agent "${this.name}" memory is not runtime-bound`);
|
|
163
|
+
const now = Date.now();
|
|
164
|
+
const record = {
|
|
165
|
+
record_id: crypto.randomUUID(), scope: this.memory.scope
|
|
166
|
+
?? { tenant_id: "default", namespace: this.memory.namespace ?? this.name },
|
|
167
|
+
name: input.name, kind: input.kind ?? "reference", content: input.content,
|
|
168
|
+
description: input.description ?? input.name,
|
|
169
|
+
provenance: { author: "host", trust: "user_asserted", evidence_refs: [], session_id: sessionId ?? `memory-${crypto.randomUUID()}` },
|
|
170
|
+
created_at: now, updated_at: now, recall_count: 0, confidence: input.confidence ?? 1,
|
|
171
|
+
links: [], pinned: input.pinned ?? false, ...(input.ttlDays === undefined ? {} : { ttl_days: input.ttlDays }),
|
|
172
|
+
};
|
|
173
|
+
await this.memory.put(record);
|
|
174
|
+
return record;
|
|
175
|
+
}
|
|
176
|
+
async recall(query, options = {}, _sessionId) {
|
|
177
|
+
if (!this.memory || typeof this.memory.search !== "function")
|
|
178
|
+
throw new Error(`agent "${this.name}" memory is not runtime-bound`);
|
|
179
|
+
const records = await this.memory.search(query, { topK: options.topK ?? 8, kinds: options.kinds, minScore: options.minScore });
|
|
180
|
+
return records.map(record => ({ record, score: 1, why: "memory facade search" }));
|
|
181
|
+
}
|
|
182
|
+
async delegate(request) {
|
|
183
|
+
const targetName = typeof request.target === "string" ? request.target : request.target.name;
|
|
184
|
+
const declared = (this.handoffs ?? []).some(h => (typeof h.agent === "string" ? h.agent : h.agent.name) === targetName);
|
|
185
|
+
if (!declared)
|
|
186
|
+
throw new Error(`agent "${this.name}" cannot hand off to "${targetName}"`);
|
|
187
|
+
const resolver = this.runtimeBinding?.resolveAgent;
|
|
188
|
+
if (!resolver)
|
|
189
|
+
throw new Error(`agent "${this.name}" requires a host target resolver`);
|
|
190
|
+
const target = await resolver(targetName);
|
|
191
|
+
if (!target)
|
|
192
|
+
throw new Error(`target agent "${targetName}" is not registered`);
|
|
193
|
+
const result = await target.run(request.goal, { metadata: request.metadata, providerOptions: request.providerOptions });
|
|
194
|
+
return { output: result.output, status: result.status === "cancelled" ? "partial" : result.status };
|
|
195
|
+
}
|
|
196
|
+
async listen() {
|
|
197
|
+
const source = this.runtimeBinding?.signalSource;
|
|
198
|
+
if (!source)
|
|
199
|
+
throw new Error("agent signals require runtimeBinding.signalSource");
|
|
200
|
+
const claim = await source.claimSignal();
|
|
201
|
+
if (!claim)
|
|
202
|
+
return null;
|
|
203
|
+
const goal = String(claim.signal.payload.goal ?? claim.signal.payload.summary ?? JSON.stringify(claim.signal.payload));
|
|
204
|
+
try {
|
|
205
|
+
const result = await this.run(goal);
|
|
206
|
+
await source.ackSignal(claim);
|
|
207
|
+
return result;
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
await source.nackSignal(claim);
|
|
211
|
+
throw error;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
async close() { await this.runtimeBinding?.mcpPlane?.disconnect(); }
|
|
215
|
+
async result(sessionId, events) {
|
|
216
|
+
const entries = await this.sessionLog.read(sessionId);
|
|
217
|
+
const started = [...entries].reverse().find(e => e.event.kind === "run_started")?.event;
|
|
218
|
+
const terminal = [...entries].reverse().find(e => e.event.kind === "run_terminal")?.event;
|
|
219
|
+
const output = events.filter((e) => e.type === "text_delta" && "delta" in e).map(e => String(e.delta)).join("");
|
|
220
|
+
const usage = [...events].reverse().find((e) => e.type === "usage");
|
|
221
|
+
const result = { output, runId: started?.kind === "run_started" ? started.run_id : undefined, sessionId, status: statusOf(terminal?.kind === "run_terminal" ? terminal.reason : events.some(e => e.type === "error") ? "error" : "completed") };
|
|
222
|
+
const attempt = [...entries].reverse().find(e => e.event.kind === "provider_attempt")?.event;
|
|
223
|
+
if (usage)
|
|
224
|
+
result.usage = { inputTokens: usage.inputTokens ?? 0, outputTokens: usage.outputTokens ?? 0, totalTokens: usage.totalTokens };
|
|
225
|
+
else if (attempt?.kind === "provider_attempt" && attempt.usage) {
|
|
226
|
+
result.usage = { inputTokens: attempt.usage.inputTokens, outputTokens: attempt.usage.outputTokens, totalTokens: attempt.usage.inputTokens + attempt.usage.outputTokens };
|
|
227
|
+
}
|
|
228
|
+
const measured = [...entries].reverse().find(e => e.event.kind === "prompt_measured")?.event;
|
|
229
|
+
const prepared = [...entries].reverse().find(e => e.event.kind === "context_prepared")?.event;
|
|
230
|
+
if ((started?.kind === "run_started" && started.route) || (attempt?.kind === "provider_attempt" && attempt.route) || measured || prepared) {
|
|
231
|
+
result.evidence = {
|
|
232
|
+
...((attempt?.kind === "provider_attempt" ? attempt.route : started?.kind === "run_started" ? started.route : undefined) ? { route: attempt?.kind === "provider_attempt" ? attempt.route : started.route } : {}),
|
|
233
|
+
...(measured?.kind === "prompt_measured" ? { measurement: measured.measurement } : {}),
|
|
234
|
+
...(prepared?.kind === "context_prepared" ? { contextBinding: prepared.preparation.binding } : {}),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
if (this.outputSchema) {
|
|
238
|
+
result.outputValidation = validateAgainstSchema(extractJsonValue(output), this.outputSchema);
|
|
239
|
+
if (!result.outputValidation.ok && result.status === "completed")
|
|
240
|
+
result.status = "failed";
|
|
241
|
+
}
|
|
242
|
+
return result;
|
|
33
243
|
}
|
|
34
244
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,9 +14,9 @@ export type { AgentCapabilityFilter, AgentIdentity, AgentIsolation, AgentRunSpec
|
|
|
14
14
|
export { workflowSpecToKernel, workflowNodeSpecToKernel, submitWorkflowNodesTool, startWorkflowTool, fanoutSynthesize, generateAndFilter, genEval, verifyRules } from "./runtime/types/agent.js";
|
|
15
15
|
export { loopInstruction, classifyInstruction, judgeGoal, extractClassifyBranch, extractJudgeWinner, } from "./runtime/workflow-control-flow.js";
|
|
16
16
|
export { Agent } from "./agent.js";
|
|
17
|
-
export
|
|
18
|
-
export {
|
|
19
|
-
export type {
|
|
17
|
+
export { McpExecutionPlane } from "./runtime/mcp-transport.js";
|
|
18
|
+
export type { McpConnection, McpConnectionFactory, McpCredentialVault, McpServerConfig } from "./runtime/mcp-transport.js";
|
|
19
|
+
export type { AgentMemory, AgentOptions, AgentRunResult, AgentRunOptions, AgentToolDefinition, AgentRef, Guardrail, Handoff, Knowledge, KnowledgeSourceRef, MCPServer, McpTransport, MemoryReference, ModelRef, ModelRequirement, Skill, MemoryInput, RecallOptions, DelegationResult, AgentRuntimeBinding, AgentSession, } from "./agent.js";
|
|
20
20
|
export { AnthropicProvider } from "./providers/anthropic.js";
|
|
21
21
|
export { OpenAIProvider, qwen, deepseek, minimax, kimi } from "./providers/openai.js";
|
|
22
22
|
export type { OpenAIProviderOptions, BackendProviderOptions } from "./providers/openai.js";
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ export { SubAgentOrchestrator, defaultSubAgentOrchestrator, spawnStandalone } fr
|
|
|
10
10
|
export { workflowSpecToKernel, workflowNodeSpecToKernel, submitWorkflowNodesTool, startWorkflowTool, fanoutSynthesize, generateAndFilter, genEval, verifyRules } from "./runtime/types/agent.js";
|
|
11
11
|
export { loopInstruction, classifyInstruction, judgeGoal, extractClassifyBranch, extractJudgeWinner, } from "./runtime/workflow-control-flow.js";
|
|
12
12
|
export { Agent } from "./agent.js";
|
|
13
|
-
export {
|
|
13
|
+
export { McpExecutionPlane } from "./runtime/mcp-transport.js";
|
|
14
14
|
export { AnthropicProvider } from "./providers/anthropic.js";
|
|
15
15
|
export { OpenAIProvider, qwen, deepseek, minimax, kimi } from "./providers/openai.js";
|
|
16
16
|
export { ProviderError, classifyProviderError } from "./providers/provider-error.js";
|
package/dist/memory/durable.d.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type { Memory, MemoryRecord, MemoryScope, MemorySearchOptions, MemoryStor
|
|
|
3
3
|
export declare class DurableMemory implements Memory {
|
|
4
4
|
private readonly store;
|
|
5
5
|
private readonly agentId;
|
|
6
|
-
private readonly scope;
|
|
7
6
|
readonly namespace: string;
|
|
7
|
+
readonly scope: MemoryScope;
|
|
8
8
|
constructor(store: MemoryStore, agentId: string, scope: MemoryScope);
|
|
9
9
|
search(query: string, options?: MemorySearchOptions): Promise<MemoryRecord[]>;
|
|
10
10
|
get(recordId: string): Promise<MemoryRecord | null>;
|
package/dist/memory/durable.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
export class DurableMemory {
|
|
3
3
|
store;
|
|
4
4
|
agentId;
|
|
5
|
-
scope;
|
|
6
5
|
namespace;
|
|
6
|
+
scope;
|
|
7
7
|
constructor(store, agentId, scope) {
|
|
8
8
|
this.store = store;
|
|
9
9
|
this.agentId = agentId;
|
|
10
|
-
this.scope = scope;
|
|
11
10
|
this.namespace = scope.namespace;
|
|
11
|
+
this.scope = scope;
|
|
12
12
|
}
|
|
13
13
|
async search(query, options = {}) {
|
|
14
14
|
const request = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { GenerationProtocol, RenderedContext, ToolSchema } from "../types.js";
|
|
2
2
|
export interface ProviderRequestEndpoint {
|
|
3
3
|
id: string;
|
|
4
4
|
protocol: string;
|
|
@@ -46,7 +46,7 @@ export interface ResolvedProviderRoute {
|
|
|
46
46
|
request_fingerprint_scope?: "encoded_body" | "adapter_input";
|
|
47
47
|
routeId: string;
|
|
48
48
|
provider: string;
|
|
49
|
-
protocol:
|
|
49
|
+
protocol: GenerationProtocol;
|
|
50
50
|
model: string;
|
|
51
51
|
endpoint: ProviderRequestEndpoint;
|
|
52
52
|
adapterVersion: string;
|
package/dist/runtime/index.d.ts
CHANGED
|
@@ -14,6 +14,8 @@ export { CanonicalKernelHost, CanonicalKernelRejectedError, CanonicalKernelRebui
|
|
|
14
14
|
export type { CanonicalKernelInput, CanonicalPlannedStep, CanonicalRunnerRuntimeOptions, CanonicalTransition, CanonicalTransitionOptions, } from "./canonical-kernel-step.js";
|
|
15
15
|
export { runAgent, runFanout } from "./facade.js";
|
|
16
16
|
export type { RunAgentOptions, RunFanoutOptions } from "./facade.js";
|
|
17
|
+
export { McpExecutionPlane } from "./mcp-transport.js";
|
|
18
|
+
export type { McpConnection, McpConnectionFactory, McpCredentialVault, McpServerConfig } from "./mcp-transport.js";
|
|
17
19
|
export { builtinReducers, resolveReducer } from "./reducers.js";
|
|
18
20
|
export type { Reducer, ReducerRegistry, ReducerInput } from "./reducers.js";
|
|
19
21
|
export { getKernel } from "./kernel.js";
|
package/dist/runtime/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { RuntimeRunner, collectText } from "./runner.js";
|
|
|
9
9
|
export { MemoryPayloadDriver, PayloadStore } from "./payload-store.js";
|
|
10
10
|
export { CanonicalKernelHost, CanonicalKernelRejectedError, CanonicalKernelRebuildRequiredError, CanonicalRunnerRuntime, sha256, } from "./canonical-kernel-step.js";
|
|
11
11
|
export { runAgent, runFanout } from "./facade.js";
|
|
12
|
+
export { McpExecutionPlane } from "./mcp-transport.js";
|
|
12
13
|
export { builtinReducers, resolveReducer } from "./reducers.js";
|
|
13
14
|
export { getKernel } from "./kernel.js";
|
|
14
15
|
export { ReplayProvider } from "./replay-provider.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ToolCall, ToolSchema, StreamEvent } from "../types.js";
|
|
2
|
+
import { type ExecutionPlane, type RunContext } from "./execution-plane.js";
|
|
3
|
+
import type { RegisteredTool } from "../tools/index.js";
|
|
4
|
+
/** Browser-safe MCP connection boundary. Implement HTTP/SSE/custom transports in the host. */
|
|
5
|
+
export interface McpConnection {
|
|
6
|
+
start(): Promise<void>;
|
|
7
|
+
schemas(): ToolSchema[];
|
|
8
|
+
execute(call: ToolCall, context?: RunContext): Promise<{
|
|
9
|
+
content: string;
|
|
10
|
+
isError: boolean;
|
|
11
|
+
contentParts?: unknown[];
|
|
12
|
+
}>;
|
|
13
|
+
stop(): Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export interface McpCredentialVault {
|
|
16
|
+
get(key: string): Promise<string | undefined>;
|
|
17
|
+
}
|
|
18
|
+
export interface McpServerConfig {
|
|
19
|
+
name: string;
|
|
20
|
+
transport: {
|
|
21
|
+
kind: "http" | "sse" | "custom";
|
|
22
|
+
[key: string]: unknown;
|
|
23
|
+
};
|
|
24
|
+
credentialVault?: McpCredentialVault;
|
|
25
|
+
}
|
|
26
|
+
export type McpConnectionFactory = (config: McpServerConfig) => McpConnection | Promise<McpConnection>;
|
|
27
|
+
/** ExecutionPlane adapter that keeps MCP wire details outside the Kernel. */
|
|
28
|
+
export declare class McpExecutionPlane implements ExecutionPlane {
|
|
29
|
+
private readonly configs;
|
|
30
|
+
private readonly factory;
|
|
31
|
+
private readonly connections;
|
|
32
|
+
private readonly toolMap;
|
|
33
|
+
private connected;
|
|
34
|
+
private readonly local;
|
|
35
|
+
private readonly localNames;
|
|
36
|
+
constructor(configs: McpServerConfig[], factory: McpConnectionFactory);
|
|
37
|
+
connect(): Promise<void>;
|
|
38
|
+
register(...tools: RegisteredTool[]): this;
|
|
39
|
+
unregister(name: string): this;
|
|
40
|
+
schemas(): ToolSchema[];
|
|
41
|
+
executeAll(calls: ToolCall[], context: RunContext): AsyncIterable<StreamEvent>;
|
|
42
|
+
disconnect(): Promise<void>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { LocalExecutionPlane } from "./execution-plane.js";
|
|
2
|
+
/** ExecutionPlane adapter that keeps MCP wire details outside the Kernel. */
|
|
3
|
+
export class McpExecutionPlane {
|
|
4
|
+
configs;
|
|
5
|
+
factory;
|
|
6
|
+
connections = [];
|
|
7
|
+
toolMap = new Map();
|
|
8
|
+
connected = false;
|
|
9
|
+
local = new LocalExecutionPlane();
|
|
10
|
+
localNames = new Set();
|
|
11
|
+
constructor(configs, factory) {
|
|
12
|
+
this.configs = configs;
|
|
13
|
+
this.factory = factory;
|
|
14
|
+
}
|
|
15
|
+
async connect() {
|
|
16
|
+
if (this.connected)
|
|
17
|
+
return;
|
|
18
|
+
for (const config of this.configs) {
|
|
19
|
+
const connection = await this.factory(config);
|
|
20
|
+
await connection.start();
|
|
21
|
+
this.connections.push(connection);
|
|
22
|
+
for (const schema of connection.schemas())
|
|
23
|
+
this.toolMap.set(schema.name, connection);
|
|
24
|
+
}
|
|
25
|
+
this.connected = true;
|
|
26
|
+
}
|
|
27
|
+
register(...tools) { this.local.register(...tools); for (const tool of tools)
|
|
28
|
+
this.localNames.add(tool.schema.name); return this; }
|
|
29
|
+
unregister(name) { this.local.unregister(name); this.localNames.delete(name); this.toolMap.delete(name); return this; }
|
|
30
|
+
schemas() { return [...this.local.schemas(), ...this.connections.flatMap(connection => connection.schemas())]; }
|
|
31
|
+
async *executeAll(calls, context) {
|
|
32
|
+
const localCalls = calls.filter(call => this.localNames.has(call.name));
|
|
33
|
+
if (localCalls.length)
|
|
34
|
+
yield* this.local.executeAll(localCalls, context);
|
|
35
|
+
for (const call of calls) {
|
|
36
|
+
if (this.localNames.has(call.name))
|
|
37
|
+
continue;
|
|
38
|
+
const connection = this.toolMap.get(call.name);
|
|
39
|
+
if (!connection) {
|
|
40
|
+
yield { type: "tool_result", callId: call.id, name: call.name, content: `unknown MCP tool: ${call.name}`, isError: true };
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
const result = await connection.execute(call, context);
|
|
45
|
+
yield { type: "tool_result", callId: call.id, name: call.name, content: result.content, isError: result.isError, contentParts: result.contentParts };
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
yield { type: "tool_result", callId: call.id, name: call.name, content: String(error), isError: true };
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
async disconnect() {
|
|
53
|
+
await Promise.all(this.connections.map(connection => connection.stop()));
|
|
54
|
+
this.connections.length = 0;
|
|
55
|
+
this.toolMap.clear();
|
|
56
|
+
this.connected = false;
|
|
57
|
+
}
|
|
58
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -221,7 +221,7 @@ export interface EntropyWatchOptions {
|
|
|
221
221
|
* The framework creates and threads this object; providers may read/write it.
|
|
222
222
|
*/
|
|
223
223
|
export type ProviderRunState = Record<string, unknown>;
|
|
224
|
-
export type
|
|
224
|
+
export type GenerationProtocol = "anthropic-messages" | "openai-chat" | "openai-responses" | "gemini";
|
|
225
225
|
/**
|
|
226
226
|
* Cache_control placement strategy for the Anthropic protocol. Pass via
|
|
227
227
|
* `extensions.cacheBreakpointStrategy` on any provider call (the runner threads
|
|
@@ -231,7 +231,7 @@ export type ProviderProtocol = "anthropic-messages" | "openai-chat" | "openai-re
|
|
|
231
231
|
export type CacheBreakpointStrategy = "default" | "tools-only" | "system-only" | "frozen-prefix" | "none";
|
|
232
232
|
export interface ProviderDescriptor {
|
|
233
233
|
provider: string;
|
|
234
|
-
protocol:
|
|
234
|
+
protocol: GenerationProtocol;
|
|
235
235
|
model: string;
|
|
236
236
|
reasoning: {
|
|
237
237
|
supported: boolean;
|
|
@@ -260,7 +260,7 @@ export interface PromptMeasurement {
|
|
|
260
260
|
}
|
|
261
261
|
export interface ProviderReplay {
|
|
262
262
|
provider?: string;
|
|
263
|
-
protocol:
|
|
263
|
+
protocol: GenerationProtocol;
|
|
264
264
|
model?: string;
|
|
265
265
|
native_blocks?: Array<Record<string, unknown>>;
|
|
266
266
|
reasoning_content?: string;
|
|
@@ -270,7 +270,7 @@ export interface ProviderReplay {
|
|
|
270
270
|
}
|
|
271
271
|
/** P3 §3.3 (D1) mirror of the node ProviderWireEvidence — SessionLog wire evidence bundle. */
|
|
272
272
|
export interface ProviderWireEvidence {
|
|
273
|
-
protocol:
|
|
273
|
+
protocol: GenerationProtocol;
|
|
274
274
|
/** → ProviderRequestPlan.fingerprint. Mandatory non-empty (G2). */
|
|
275
275
|
request_fingerprint: string;
|
|
276
276
|
response_id?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepstrike/wasm",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.74",
|
|
4
4
|
"description": "DeepStrike WASM SDK — browser, Cloudflare Workers, Deno Deploy",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
|
@@ -12,12 +12,12 @@
|
|
|
12
12
|
],
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build:wasm": "wasm-pack build ../crates/deepstrike-wasm --target bundler --out-dir ../../wasm/pkg",
|
|
15
|
-
"build": "tsc",
|
|
15
|
+
"build": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && tsc",
|
|
16
16
|
"test": "node --experimental-vm-modules node_modules/.bin/jest",
|
|
17
17
|
"test:canonical-binding": "wasm-pack build ../crates/deepstrike-wasm --target nodejs --dev --out-dir ../../wasm/pkg-node && node tests/canonical-binding.node.cjs && node tests/golden-fixtures-sweep.node.cjs"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@deepstrike/wasm-kernel": "0.2.
|
|
20
|
+
"@deepstrike/wasm-kernel": "0.2.74"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/jest": "^30.0.0",
|
package/dist/agent-ir.d.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { Agent, type AgentOptions, type AgentToolDefinition, type Guardrail, type Handoff, type Knowledge, type MCPServer, type ModelRef, type Skill } from "./agent.js";
|
|
2
|
-
import type { AgentCapabilityFilter } from "./runtime/types/agent.js";
|
|
3
|
-
import type { RegisteredTool } from "./tools/index.js";
|
|
4
|
-
type JsonSchema = Record<string, unknown>;
|
|
5
|
-
export interface AgentDefinition extends Omit<AgentOptions, "tools"> {
|
|
6
|
-
tools?: Array<RegisteredTool | AgentToolDefinition>;
|
|
7
|
-
}
|
|
8
|
-
export interface AgentToolIR {
|
|
9
|
-
name: string;
|
|
10
|
-
description: string;
|
|
11
|
-
parameters: Record<string, unknown>;
|
|
12
|
-
providerOptions?: Record<string, unknown>;
|
|
13
|
-
}
|
|
14
|
-
export interface AgentMemoryIR {
|
|
15
|
-
kind: "durable" | "working";
|
|
16
|
-
namespace?: string;
|
|
17
|
-
}
|
|
18
|
-
export type AgentCapabilityIR = {
|
|
19
|
-
kind: "tool";
|
|
20
|
-
id: string;
|
|
21
|
-
description: string;
|
|
22
|
-
} | {
|
|
23
|
-
kind: "mcp_server";
|
|
24
|
-
id: string;
|
|
25
|
-
description: string;
|
|
26
|
-
} | {
|
|
27
|
-
kind: "skill";
|
|
28
|
-
id: string;
|
|
29
|
-
description: string;
|
|
30
|
-
};
|
|
31
|
-
export interface AgentLoweringInputs {
|
|
32
|
-
run: {
|
|
33
|
-
name: string;
|
|
34
|
-
model?: ModelRef;
|
|
35
|
-
};
|
|
36
|
-
context: {
|
|
37
|
-
description?: string;
|
|
38
|
-
instructions?: string;
|
|
39
|
-
outputSchema?: JsonSchema;
|
|
40
|
-
knowledge: Knowledge[];
|
|
41
|
-
};
|
|
42
|
-
capabilities: {
|
|
43
|
-
tools: AgentToolIR[];
|
|
44
|
-
mcpServers: MCPServer[];
|
|
45
|
-
skills: Skill[];
|
|
46
|
-
effective: AgentCapabilityIR[];
|
|
47
|
-
};
|
|
48
|
-
memory?: AgentMemoryIR;
|
|
49
|
-
delegation: {
|
|
50
|
-
handoffs: Handoff[];
|
|
51
|
-
};
|
|
52
|
-
governance: {
|
|
53
|
-
guardrails: Guardrail[];
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
/** Provider-neutral host descriptor. This is neither an execution plan nor a Kernel wire DTO. */
|
|
57
|
-
export interface AgentSpec {
|
|
58
|
-
name: string;
|
|
59
|
-
description?: string;
|
|
60
|
-
instructions?: string;
|
|
61
|
-
model?: ModelRef;
|
|
62
|
-
tools: AgentToolIR[];
|
|
63
|
-
outputSchema?: JsonSchema;
|
|
64
|
-
mcpServers?: MCPServer[];
|
|
65
|
-
skills?: Skill[];
|
|
66
|
-
memory?: AgentMemoryIR;
|
|
67
|
-
knowledge?: Knowledge[];
|
|
68
|
-
handoffs?: Handoff[];
|
|
69
|
-
guardrails?: Guardrail[];
|
|
70
|
-
metadata?: Record<string, unknown>;
|
|
71
|
-
capabilities: AgentCapabilityIR[];
|
|
72
|
-
capabilityFilter?: AgentCapabilityFilter;
|
|
73
|
-
effectiveCapabilities: AgentCapabilityIR[];
|
|
74
|
-
extensions: Record<string, unknown>;
|
|
75
|
-
inputs: AgentLoweringInputs;
|
|
76
|
-
}
|
|
77
|
-
/** Native Agents need no normalization; JSON-safe declarations remain schema-only capabilities. */
|
|
78
|
-
export declare function normalizeAgent(agent: Agent | AgentDefinition): Agent;
|
|
79
|
-
/** Pure lowering only: providers, Kernel scheduling, persistence, and grants remain outside it. */
|
|
80
|
-
export declare function lowerAgent(agent: Agent): AgentSpec;
|
|
81
|
-
export {};
|
package/dist/agent-ir.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { Agent, } from "./agent.js";
|
|
2
|
-
import { WorkingMemory } from "./memory/index.js";
|
|
3
|
-
function clone(value) {
|
|
4
|
-
if (value === undefined || value === null || typeof value !== "object")
|
|
5
|
-
return value;
|
|
6
|
-
if (Array.isArray(value))
|
|
7
|
-
return value.map(clone);
|
|
8
|
-
const copy = {};
|
|
9
|
-
for (const [key, nested] of Object.entries(value))
|
|
10
|
-
copy[key] = clone(nested);
|
|
11
|
-
return copy;
|
|
12
|
-
}
|
|
13
|
-
function isRegisteredTool(tool) {
|
|
14
|
-
return "schema" in tool && "execute" in tool;
|
|
15
|
-
}
|
|
16
|
-
/** Native Agents need no normalization; JSON-safe declarations remain schema-only capabilities. */
|
|
17
|
-
export function normalizeAgent(agent) {
|
|
18
|
-
if (agent instanceof Agent)
|
|
19
|
-
return agent;
|
|
20
|
-
return new Agent({ ...agent, ...(agent.tools ? { tools: clone(agent.tools) } : {}) });
|
|
21
|
-
}
|
|
22
|
-
function lowerTool(tool) {
|
|
23
|
-
if (!isRegisteredTool(tool)) {
|
|
24
|
-
const parameters = clone(tool.parameters ?? { type: "object", properties: {} });
|
|
25
|
-
if (parameters.type !== "object") {
|
|
26
|
-
throw new Error(`tool "${tool.name}": parameters must be a JSON Schema with root type "object"`);
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
name: tool.name,
|
|
30
|
-
description: tool.description ?? "",
|
|
31
|
-
parameters,
|
|
32
|
-
...(tool.providerOptions ? { providerOptions: clone(tool.providerOptions) } : {}),
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
let parameters;
|
|
36
|
-
try {
|
|
37
|
-
parameters = JSON.parse(tool.schema.parameters);
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
throw new Error(`tool "${tool.schema.name}" has invalid JSON Schema parameters`);
|
|
41
|
-
}
|
|
42
|
-
if (!parameters || typeof parameters !== "object" || Array.isArray(parameters) || parameters.type !== "object") {
|
|
43
|
-
throw new Error(`tool "${tool.schema.name}" parameters must decode to an object`);
|
|
44
|
-
}
|
|
45
|
-
return { name: tool.schema.name, description: tool.schema.description, parameters: clone(parameters) };
|
|
46
|
-
}
|
|
47
|
-
function lowerMemory(memory) {
|
|
48
|
-
if (!memory)
|
|
49
|
-
return undefined;
|
|
50
|
-
if (memory instanceof WorkingMemory)
|
|
51
|
-
return { kind: "working" };
|
|
52
|
-
const reference = memory;
|
|
53
|
-
return { kind: "durable", ...(reference.namespace ? { namespace: reference.namespace } : {}) };
|
|
54
|
-
}
|
|
55
|
-
function capabilityAllowed(capability, filter) {
|
|
56
|
-
if (!filter)
|
|
57
|
-
return true;
|
|
58
|
-
const kindAllowed = !filter.allowedKinds?.length || filter.allowedKinds.includes(capability.kind);
|
|
59
|
-
const idAllowed = !filter.allowedIds?.length || filter.allowedIds.includes(capability.id);
|
|
60
|
-
return kindAllowed && idAllowed;
|
|
61
|
-
}
|
|
62
|
-
/** Pure lowering only: providers, Kernel scheduling, persistence, and grants remain outside it. */
|
|
63
|
-
export function lowerAgent(agent) {
|
|
64
|
-
const tools = (agent.tools ?? []).map(lowerTool);
|
|
65
|
-
const mcpServers = clone(agent.mcpServers ?? []);
|
|
66
|
-
const skills = clone(agent.skills ?? []);
|
|
67
|
-
const knowledge = clone(agent.knowledge ?? []);
|
|
68
|
-
const handoffs = clone(agent.handoffs ?? []);
|
|
69
|
-
const guardrails = clone(agent.guardrails ?? []);
|
|
70
|
-
const memory = lowerMemory(agent.memory);
|
|
71
|
-
const extensions = clone(agent.providerOptions ?? {});
|
|
72
|
-
const capabilities = [
|
|
73
|
-
...tools.map(tool => ({ kind: "tool", id: tool.name, description: tool.description })),
|
|
74
|
-
...mcpServers.map(server => ({
|
|
75
|
-
kind: "mcp_server",
|
|
76
|
-
id: server.name ?? server.transport.kind,
|
|
77
|
-
description: server.name ?? `${server.transport.kind} MCP server`,
|
|
78
|
-
})),
|
|
79
|
-
...skills.map(skill => ({ kind: "skill", id: skill.name, description: skill.description ?? "" })),
|
|
80
|
-
];
|
|
81
|
-
const capabilityFilter = agent.capabilityFilter ? clone(agent.capabilityFilter) : undefined;
|
|
82
|
-
const effectiveCapabilities = capabilities.filter(capability => capabilityAllowed(capability, capabilityFilter));
|
|
83
|
-
return {
|
|
84
|
-
name: agent.name,
|
|
85
|
-
...(agent.description ? { description: agent.description } : {}),
|
|
86
|
-
...(agent.instructions ? { instructions: agent.instructions } : {}),
|
|
87
|
-
...(agent.model ? { model: clone(agent.model) } : {}),
|
|
88
|
-
tools,
|
|
89
|
-
...(agent.outputSchema ? { outputSchema: clone(agent.outputSchema) } : {}),
|
|
90
|
-
...(mcpServers.length ? { mcpServers } : {}),
|
|
91
|
-
...(skills.length ? { skills } : {}),
|
|
92
|
-
...(memory ? { memory } : {}),
|
|
93
|
-
...(knowledge.length ? { knowledge } : {}),
|
|
94
|
-
...(handoffs.length ? { handoffs } : {}),
|
|
95
|
-
...(guardrails.length ? { guardrails } : {}),
|
|
96
|
-
...(agent.metadata ? { metadata: clone(agent.metadata) } : {}),
|
|
97
|
-
capabilities,
|
|
98
|
-
...(capabilityFilter ? { capabilityFilter } : {}),
|
|
99
|
-
effectiveCapabilities,
|
|
100
|
-
extensions,
|
|
101
|
-
inputs: {
|
|
102
|
-
run: { name: agent.name, ...(agent.model ? { model: clone(agent.model) } : {}) },
|
|
103
|
-
context: {
|
|
104
|
-
...(agent.description ? { description: agent.description } : {}),
|
|
105
|
-
...(agent.instructions ? { instructions: agent.instructions } : {}),
|
|
106
|
-
...(agent.outputSchema ? { outputSchema: clone(agent.outputSchema) } : {}),
|
|
107
|
-
knowledge,
|
|
108
|
-
},
|
|
109
|
-
capabilities: { tools, mcpServers, skills, effective: effectiveCapabilities },
|
|
110
|
-
...(memory ? { memory } : {}),
|
|
111
|
-
delegation: { handoffs },
|
|
112
|
-
governance: { guardrails },
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
}
|