@deepstrike/wasm 0.2.51 → 0.2.60
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 +15 -14
- package/dist/agent-ir.d.ts +81 -0
- package/dist/agent-ir.js +115 -0
- package/dist/agent.d.ts +140 -0
- package/dist/agent.js +34 -0
- package/dist/governance.d.ts +0 -25
- package/dist/governance.js +1 -53
- package/dist/index.d.ts +23 -8
- package/dist/index.js +11 -4
- package/dist/memory/durable.d.ts +13 -0
- package/dist/memory/durable.js +42 -0
- package/dist/memory/in-memory-store.d.ts +8 -6
- package/dist/memory/in-memory-store.js +8 -2
- package/dist/memory/index.d.ts +18 -2
- package/dist/providers/anthropic.d.ts +9 -0
- package/dist/providers/anthropic.js +12 -33
- package/dist/providers/content-policy.d.ts +16 -0
- package/dist/providers/content-policy.js +39 -0
- package/dist/providers/openai.d.ts +36 -17
- package/dist/providers/openai.js +86 -46
- package/dist/providers/provider-error.d.ts +22 -0
- package/dist/providers/provider-error.js +90 -0
- package/dist/providers/request-plan.d.ts +87 -0
- package/dist/providers/request-plan.js +153 -0
- package/dist/providers/stop-reason.d.ts +5 -0
- package/dist/providers/stop-reason.js +24 -0
- package/dist/runtime/canonical-kernel-step.d.ts +11 -5
- package/dist/runtime/canonical-kernel-step.js +99 -78
- package/dist/runtime/context-policy.d.ts +10 -12
- package/dist/runtime/context-policy.js +6 -8
- package/dist/runtime/durable-content.d.ts +44 -0
- package/dist/runtime/durable-content.js +119 -0
- package/dist/runtime/execution-plane.d.ts +2 -2
- package/dist/runtime/execution-plane.js +2 -2
- package/dist/runtime/kernel-event-log.js +0 -1
- package/dist/runtime/kernel-step.d.ts +1 -2
- package/dist/runtime/kernel-step.js +1 -1
- package/dist/runtime/provider-replay.d.ts +1 -1
- package/dist/runtime/provider-replay.js +12 -20
- package/dist/runtime/runner.d.ts +22 -18
- package/dist/runtime/runner.js +115 -55
- package/dist/runtime/session-log.d.ts +8 -1
- package/dist/runtime/session-repair.d.ts +1 -1
- package/dist/runtime/session-repair.js +1 -1
- package/dist/runtime/sha256.d.ts +2 -0
- package/dist/runtime/sha256.js +38 -0
- package/dist/runtime/sub-agent-orchestrator.d.ts +1 -1
- package/dist/runtime/sub-agent-orchestrator.js +3 -3
- package/dist/runtime/types/agent.d.ts +17 -7
- package/dist/runtime/types/agent.js +30 -4
- package/dist/runtime/workflow-control-flow.d.ts +0 -4
- package/dist/runtime/workflow-control-flow.js +0 -16
- package/dist/types.d.ts +58 -5
- package/package.json +2 -2
|
@@ -1,35 +1,33 @@
|
|
|
1
|
-
export declare const CONTEXT_POLICY_VERSION: 1;
|
|
2
1
|
export declare const PPM_SCALE: 1000000;
|
|
3
|
-
export interface
|
|
2
|
+
export interface ContextPressureThresholds {
|
|
4
3
|
snip: number;
|
|
5
4
|
micro: number;
|
|
6
5
|
collapse: number;
|
|
7
6
|
auto: number;
|
|
8
7
|
renewal: number;
|
|
9
8
|
}
|
|
10
|
-
export interface
|
|
11
|
-
pressureThresholds:
|
|
9
|
+
export interface ContextPolicy {
|
|
10
|
+
pressureThresholds: ContextPressureThresholds;
|
|
12
11
|
targetAfterCompress: number;
|
|
13
12
|
preserveRecentTurns: number;
|
|
14
13
|
renewalCarryover: number;
|
|
15
14
|
collapseOldAssistantNarration: boolean;
|
|
16
15
|
idleMicroCompactMinutes: number;
|
|
17
16
|
}
|
|
18
|
-
export interface
|
|
19
|
-
|
|
20
|
-
pressure_thresholds_ppm: ContextPressureThresholdsV1;
|
|
17
|
+
export interface ContextPolicyWire {
|
|
18
|
+
pressure_thresholds_ppm: ContextPressureThresholds;
|
|
21
19
|
target_after_compress_ppm: number;
|
|
22
20
|
preserve_recent_turns: number;
|
|
23
21
|
renewal_carryover_ppm: number;
|
|
24
22
|
collapse_old_assistant_narration: boolean;
|
|
25
23
|
idle_micro_compact_minutes: number;
|
|
26
24
|
}
|
|
27
|
-
export interface
|
|
28
|
-
pressureThresholds?: Partial<
|
|
25
|
+
export interface ContextPolicyOverrides extends Partial<Omit<ContextPolicy, "pressureThresholds">> {
|
|
26
|
+
pressureThresholds?: Partial<ContextPressureThresholds>;
|
|
29
27
|
}
|
|
30
|
-
export declare const
|
|
28
|
+
export declare const DEFAULT_CONTEXT_POLICY: Readonly<ContextPolicy>;
|
|
31
29
|
/** Resolve ergonomic partial SDK options into one complete, atomically validated policy. */
|
|
32
|
-
export declare function
|
|
30
|
+
export declare function contextPolicy(overrides?: ContextPolicyOverrides): ContextPolicy;
|
|
33
31
|
/** Convert the public ratio-based policy to the canonical integer-only ABI wire shape. */
|
|
34
|
-
export declare function
|
|
32
|
+
export declare function normalizeContextPolicy(policy: ContextPolicy): ContextPolicyWire;
|
|
35
33
|
export declare function ratioToPpm(value: number, field?: string): number;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
export const CONTEXT_POLICY_VERSION = 1;
|
|
2
1
|
export const PPM_SCALE = 1_000_000;
|
|
3
|
-
export const
|
|
2
|
+
export const DEFAULT_CONTEXT_POLICY = Object.freeze({
|
|
4
3
|
pressureThresholds: Object.freeze({ snip: 0.70, micro: 0.80, collapse: 0.90, auto: 0.95, renewal: 0.98 }),
|
|
5
4
|
targetAfterCompress: 0.65,
|
|
6
5
|
preserveRecentTurns: 2,
|
|
@@ -9,20 +8,20 @@ export const DEFAULT_CONTEXT_POLICY_V1 = Object.freeze({
|
|
|
9
8
|
idleMicroCompactMinutes: 60,
|
|
10
9
|
});
|
|
11
10
|
/** Resolve ergonomic partial SDK options into one complete, atomically validated policy. */
|
|
12
|
-
export function
|
|
11
|
+
export function contextPolicy(overrides = {}) {
|
|
13
12
|
const policy = {
|
|
14
|
-
...
|
|
13
|
+
...DEFAULT_CONTEXT_POLICY,
|
|
15
14
|
...overrides,
|
|
16
15
|
pressureThresholds: {
|
|
17
|
-
...
|
|
16
|
+
...DEFAULT_CONTEXT_POLICY.pressureThresholds,
|
|
18
17
|
...overrides.pressureThresholds,
|
|
19
18
|
},
|
|
20
19
|
};
|
|
21
|
-
|
|
20
|
+
normalizeContextPolicy(policy);
|
|
22
21
|
return policy;
|
|
23
22
|
}
|
|
24
23
|
/** Convert the public ratio-based policy to the canonical integer-only ABI wire shape. */
|
|
25
|
-
export function
|
|
24
|
+
export function normalizeContextPolicy(policy) {
|
|
26
25
|
const pressure_thresholds_ppm = {
|
|
27
26
|
snip: ratioToPpm(policy.pressureThresholds.snip, "pressureThresholds.snip"),
|
|
28
27
|
micro: ratioToPpm(policy.pressureThresholds.micro, "pressureThresholds.micro"),
|
|
@@ -44,7 +43,6 @@ export function normalizeContextPolicyV1(policy) {
|
|
|
44
43
|
throw new TypeError("collapseOldAssistantNarration must be boolean");
|
|
45
44
|
}
|
|
46
45
|
return {
|
|
47
|
-
version: CONTEXT_POLICY_VERSION,
|
|
48
46
|
pressure_thresholds_ppm,
|
|
49
47
|
target_after_compress_ppm,
|
|
50
48
|
preserve_recent_turns: policy.preserveRecentTurns,
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare class DurableContentError extends Error {
|
|
2
|
+
constructor(message: string);
|
|
3
|
+
}
|
|
4
|
+
export type DurableSource = {
|
|
5
|
+
kind: "url";
|
|
6
|
+
url: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: "base64";
|
|
9
|
+
data: string;
|
|
10
|
+
} | {
|
|
11
|
+
kind: "file_id";
|
|
12
|
+
id: string;
|
|
13
|
+
affinity: {
|
|
14
|
+
provider_id: string;
|
|
15
|
+
endpoint_id: string;
|
|
16
|
+
};
|
|
17
|
+
} | {
|
|
18
|
+
kind: "object";
|
|
19
|
+
handle: string;
|
|
20
|
+
owner: string;
|
|
21
|
+
payload_ref: string;
|
|
22
|
+
};
|
|
23
|
+
export type DurableContentBlock = {
|
|
24
|
+
type: "text";
|
|
25
|
+
text: string;
|
|
26
|
+
} | {
|
|
27
|
+
type: "image" | "audio" | "video" | "file";
|
|
28
|
+
source: DurableSource;
|
|
29
|
+
media_type?: string;
|
|
30
|
+
provider_options?: Record<string, unknown>;
|
|
31
|
+
};
|
|
32
|
+
export interface DurableContent {
|
|
33
|
+
blocks: DurableContentBlock[];
|
|
34
|
+
}
|
|
35
|
+
export interface DurableToolResult extends DurableContent {
|
|
36
|
+
call_id: string;
|
|
37
|
+
is_error: boolean;
|
|
38
|
+
}
|
|
39
|
+
export declare function decodeDurableContent(value: unknown): DurableContent;
|
|
40
|
+
export declare function decodeDurableToolResult(value: unknown): DurableToolResult;
|
|
41
|
+
export declare function encodeDurableContent(content: DurableContent): Record<string, unknown>;
|
|
42
|
+
export declare function encodeDurableToolResult(result: DurableToolResult): Record<string, unknown>;
|
|
43
|
+
export declare function toolOutputBlocksToDurable(blocks: readonly import("../types.js").ToolOutputBlock[]): DurableContentBlock[];
|
|
44
|
+
export declare function durableBlocksToToolOutput(blocks: readonly DurableContentBlock[]): import("../types.js").ToolOutputBlock[];
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
export class DurableContentError extends Error {
|
|
2
|
+
constructor(message) { super(message); this.name = "DurableContentError"; }
|
|
3
|
+
}
|
|
4
|
+
function obj(value, label) {
|
|
5
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
6
|
+
throw new DurableContentError(`${label} must be an object`);
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
function keys(value, allowed, label) {
|
|
10
|
+
for (const key of Object.keys(value))
|
|
11
|
+
if (!allowed.includes(key))
|
|
12
|
+
throw new DurableContentError(`${label} has unknown field ${key}`);
|
|
13
|
+
}
|
|
14
|
+
function string(value, label) {
|
|
15
|
+
if (typeof value !== "string" || !value)
|
|
16
|
+
throw new DurableContentError(`${label} must be a non-empty string`);
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
function boolean(value, label) {
|
|
20
|
+
if (typeof value !== "boolean")
|
|
21
|
+
throw new DurableContentError(`${label} must be a boolean`);
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
function base64(value, label) {
|
|
25
|
+
const data = string(value, label);
|
|
26
|
+
if (data.length % 4 !== 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(data))
|
|
27
|
+
throw new DurableContentError(`${label} is not valid base64`);
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
function source(value, label) {
|
|
31
|
+
const raw = obj(value, `${label} source`);
|
|
32
|
+
const kind = raw.kind;
|
|
33
|
+
if (kind === "url") {
|
|
34
|
+
keys(raw, ["kind", "url"], `${label} source`);
|
|
35
|
+
return { kind, url: string(raw.url, `${label} URL`) };
|
|
36
|
+
}
|
|
37
|
+
if (kind === "base64") {
|
|
38
|
+
keys(raw, ["kind", "data"], `${label} source`);
|
|
39
|
+
return { kind, data: base64(raw.data, `${label} base64 data`) };
|
|
40
|
+
}
|
|
41
|
+
if (kind === "file_id") {
|
|
42
|
+
keys(raw, ["kind", "id", "affinity"], `${label} source`);
|
|
43
|
+
const a = obj(raw.affinity, `${label} affinity`);
|
|
44
|
+
keys(a, ["provider_id", "endpoint_id"], `${label} affinity`);
|
|
45
|
+
return { kind, id: string(raw.id, `${label} file id`), affinity: { provider_id: string(a.provider_id, `${label} affinity provider_id`), endpoint_id: string(a.endpoint_id, `${label} affinity endpoint_id`) } };
|
|
46
|
+
}
|
|
47
|
+
if (kind === "object") {
|
|
48
|
+
keys(raw, ["kind", "handle", "owner", "payload_ref"], `${label} source`);
|
|
49
|
+
return { kind, handle: string(raw.handle, `${label} object handle`), owner: string(raw.owner, `${label} object owner`), payload_ref: string(raw.payload_ref, `${label} payload_ref`) };
|
|
50
|
+
}
|
|
51
|
+
throw new DurableContentError(`${label} source kind is invalid`);
|
|
52
|
+
}
|
|
53
|
+
function block(value, index) {
|
|
54
|
+
const raw = obj(value, `content block ${index}`);
|
|
55
|
+
if (raw.type === "text") {
|
|
56
|
+
keys(raw, ["type", "text"], `content block ${index}`);
|
|
57
|
+
return { type: "text", text: string(raw.text, `content block ${index} text`) };
|
|
58
|
+
}
|
|
59
|
+
if (raw.type === "tool_result")
|
|
60
|
+
throw new DurableContentError("nested tool_result blocks are forbidden");
|
|
61
|
+
if (raw.type !== "image" && raw.type !== "audio" && raw.type !== "video" && raw.type !== "file")
|
|
62
|
+
throw new DurableContentError(`unknown content block type: ${String(raw.type)}`);
|
|
63
|
+
keys(raw, ["type", "source", "media_type", "provider_options"], `content block ${index}`);
|
|
64
|
+
const result = { type: raw.type, source: source(raw.source, `content block ${index}`) };
|
|
65
|
+
if (raw.media_type !== undefined)
|
|
66
|
+
result.media_type = string(raw.media_type, `content block ${index} media_type`);
|
|
67
|
+
if (raw.provider_options !== undefined)
|
|
68
|
+
result.provider_options = obj(raw.provider_options, `content block ${index} provider_options`);
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
function blocks(value) { if (!Array.isArray(value))
|
|
72
|
+
throw new DurableContentError("content blocks must be an array"); return value.map(block); }
|
|
73
|
+
export function decodeDurableContent(value) {
|
|
74
|
+
const raw = obj(value, "durable content");
|
|
75
|
+
keys(raw, ["blocks"], "durable content");
|
|
76
|
+
return { blocks: blocks(raw.blocks) };
|
|
77
|
+
}
|
|
78
|
+
export function decodeDurableToolResult(value) {
|
|
79
|
+
const raw = obj(value, "durable tool result");
|
|
80
|
+
keys(raw, ["call_id", "is_error", "blocks"], "durable tool result");
|
|
81
|
+
return { call_id: string(raw.call_id, "tool result call_id"), is_error: boolean(raw.is_error, "tool result is_error"), blocks: blocks(raw.blocks) };
|
|
82
|
+
}
|
|
83
|
+
export function encodeDurableContent(content) { return decodeDurableContent(content); }
|
|
84
|
+
export function encodeDurableToolResult(result) { return decodeDurableToolResult(result); }
|
|
85
|
+
export function toolOutputBlocksToDurable(blocks) {
|
|
86
|
+
return blocks.map((part, index) => {
|
|
87
|
+
if (part.type === "text")
|
|
88
|
+
return { type: "text", text: part.text };
|
|
89
|
+
const source = part.source;
|
|
90
|
+
const durableSource = source.kind === "fileId"
|
|
91
|
+
? {
|
|
92
|
+
kind: "file_id",
|
|
93
|
+
id: source.id,
|
|
94
|
+
affinity: source.affinity
|
|
95
|
+
? { provider_id: source.affinity.providerId, endpoint_id: source.affinity.endpointId }
|
|
96
|
+
: (() => { throw new DurableContentError(`tool output block ${index} fileId source requires endpoint affinity`); })(),
|
|
97
|
+
}
|
|
98
|
+
: source.kind === "base64" ? { kind: "base64", data: source.data }
|
|
99
|
+
: source.kind === "url" ? { kind: "url", url: source.url }
|
|
100
|
+
: {
|
|
101
|
+
kind: "object",
|
|
102
|
+
handle: source.handle,
|
|
103
|
+
owner: source.owner ?? (() => { throw new DurableContentError(`tool output block ${index} object source requires owner`); })(),
|
|
104
|
+
payload_ref: source.payloadRef ?? (() => { throw new DurableContentError(`tool output block ${index} object source requires payloadRef`); })(),
|
|
105
|
+
};
|
|
106
|
+
return { type: part.type, source: durableSource, ...(part.mediaType ? { media_type: part.mediaType } : {}), ...(part.providerOptions ? { provider_options: part.providerOptions } : {}) };
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
export function durableBlocksToToolOutput(blocks) {
|
|
110
|
+
return blocks.map((part) => {
|
|
111
|
+
if (part.type === "text")
|
|
112
|
+
return part;
|
|
113
|
+
const source = part.source;
|
|
114
|
+
const sdkSource = source.kind === "file_id"
|
|
115
|
+
? { kind: "fileId", id: source.id, affinity: { providerId: source.affinity.provider_id, endpointId: source.affinity.endpoint_id } }
|
|
116
|
+
: source.kind === "base64" ? source : source.kind === "url" ? source : { kind: "object", handle: source.handle, owner: source.owner, payloadRef: source.payload_ref };
|
|
117
|
+
return { type: part.type, source: sdkSource, ...(part.media_type ? { mediaType: part.media_type } : {}), ...(part.provider_options ? { providerOptions: part.provider_options } : {}) };
|
|
118
|
+
});
|
|
119
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ToolCall, ToolSchema, StreamEvent, PermissionRequestEvent, PermissionResponse } from "../types.js";
|
|
2
2
|
import type { RegisteredTool } from "../tools/index.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { MemoryStore, MemoryScope } from "../memory/index.js";
|
|
4
4
|
import type { KnowledgeSource } from "../knowledge/index.js";
|
|
5
5
|
export interface ToolSuspendEvent {
|
|
6
6
|
type: "tool_suspend";
|
|
@@ -13,7 +13,7 @@ export interface RunContext {
|
|
|
13
13
|
agentId?: string;
|
|
14
14
|
memoryScope?: MemoryScope;
|
|
15
15
|
skillContentMap?: Map<string, string>;
|
|
16
|
-
|
|
16
|
+
memoryStore?: MemoryStore;
|
|
17
17
|
knowledgeSource?: KnowledgeSource;
|
|
18
18
|
onToolSuspend?: (event: ToolSuspendEvent) => Promise<unknown> | unknown;
|
|
19
19
|
onPermissionRequest?: (event: PermissionRequestEvent) => Promise<PermissionResponse | boolean> | PermissionResponse | boolean;
|
|
@@ -43,8 +43,8 @@ export class LocalExecutionPlane {
|
|
|
43
43
|
for (const c of memoryCalls) {
|
|
44
44
|
const args = tryParseJson(c.arguments);
|
|
45
45
|
const topK = typeof args?.top_k === "number" ? args.top_k : 5;
|
|
46
|
-
const entries = (ctx.
|
|
47
|
-
? await ctx.
|
|
46
|
+
const entries = (ctx.memoryStore && ctx.agentId && ctx.memoryScope)
|
|
47
|
+
? await ctx.memoryStore.search(ctx.agentId, { scope: ctx.memoryScope, query: String(args?.query ?? ""), top_k: topK, kinds: [] })
|
|
48
48
|
: [];
|
|
49
49
|
const content = entries.length
|
|
50
50
|
? entries.map(e => `[memory record_id=${e.record.record_id} score=${e.score.toFixed(3)}] ${e.record.content}`).join("\n---\n")
|
|
@@ -91,7 +91,6 @@ export function kernelObservationToSessionEvent(obs, turn, opts = {}) {
|
|
|
91
91
|
kind: "entropy_sample",
|
|
92
92
|
turn: t,
|
|
93
93
|
score: obs.score ?? 0,
|
|
94
|
-
score_version: obs.score_version ?? 0,
|
|
95
94
|
rho: obs.rho ?? 0,
|
|
96
95
|
repeat_pressure: obs.repeat_pressure ?? 0,
|
|
97
96
|
failure_rate: obs.failure_rate ?? 0,
|
|
@@ -18,7 +18,7 @@ interface SkillMetadata {
|
|
|
18
18
|
* `stable-core ∪ allowedTools`. Absent ⇒ no narrowing (back-compat). */
|
|
19
19
|
allowedTools?: string[];
|
|
20
20
|
}
|
|
21
|
-
export declare const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts
|
|
21
|
+
export declare const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts]]";
|
|
22
22
|
/**
|
|
23
23
|
* Browser/worker-safe transport for typed content. `btoa` and `atob` operate on
|
|
24
24
|
* binary strings, so explicitly bridge UTF-8 bytes rather than assuming Latin-1.
|
|
@@ -198,7 +198,6 @@ export interface KernelObservation {
|
|
|
198
198
|
node_outcomes?: import("./types/agent.js").KernelWorkflowNodeOutcome[];
|
|
199
199
|
node_index?: number;
|
|
200
200
|
score?: number;
|
|
201
|
-
score_version?: number;
|
|
202
201
|
rho?: number;
|
|
203
202
|
repeat_pressure?: number;
|
|
204
203
|
failure_rate?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts
|
|
1
|
+
export const CANONICAL_CONTENT_PARTS_PREFIX = "[[deepstrike-content-parts]]";
|
|
2
2
|
/**
|
|
3
3
|
* Browser/worker-safe transport for typed content. `btoa` and `atob` operate on
|
|
4
4
|
* binary strings, so explicitly bridge UTF-8 bytes rather than assuming Latin-1.
|
|
@@ -6,7 +6,7 @@ export declare function assistantReplayKey(message: Pick<Message, "content" | "t
|
|
|
6
6
|
* protocol; on a cross-protocol fallback the incompatible envelope is skipped so
|
|
7
7
|
* the new provider re-serializes neutral context instead.
|
|
8
8
|
*/
|
|
9
|
-
export declare function isReplayCompatibleWithProvider(replay: ProviderReplay
|
|
9
|
+
export declare function isReplayCompatibleWithProvider(replay: Partial<ProviderReplay>, descriptor: ProviderDescriptor | undefined): boolean;
|
|
10
10
|
export declare function seedProviderReplayFromEvents(provider: LLMProvider, events: Array<{
|
|
11
11
|
event: SessionEvent;
|
|
12
12
|
}>): void;
|
|
@@ -4,28 +4,22 @@ export function assistantReplayKey(message) {
|
|
|
4
4
|
toolCalls: message.toolCalls ?? [],
|
|
5
5
|
});
|
|
6
6
|
}
|
|
7
|
-
/** Infer the wire protocol a stored replay envelope belongs to (explicit, or by shape for legacy logs). */
|
|
8
|
-
function replayProtocol(replay) {
|
|
9
|
-
if (replay.protocol)
|
|
10
|
-
return replay.protocol;
|
|
11
|
-
if (replay.native_blocks?.length)
|
|
12
|
-
return "anthropic-messages";
|
|
13
|
-
if (replay.reasoning_content != null || replay.reasoning_details !== undefined)
|
|
14
|
-
return "openai-chat";
|
|
15
|
-
return undefined;
|
|
16
|
-
}
|
|
17
7
|
/**
|
|
18
8
|
* A stored replay may only be seeded into a provider speaking the same wire
|
|
19
9
|
* protocol; on a cross-protocol fallback the incompatible envelope is skipped so
|
|
20
10
|
* the new provider re-serializes neutral context instead.
|
|
21
11
|
*/
|
|
22
12
|
export function isReplayCompatibleWithProvider(replay, descriptor) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
13
|
+
assertCanonicalReplay(replay);
|
|
14
|
+
return !descriptor || replay.protocol === descriptor.protocol;
|
|
15
|
+
}
|
|
16
|
+
const REPLAY_KEYS = new Set(["protocol", "provider", "model", "native_blocks", "reasoning_content", "reasoning_details", "native_message", "tool_calls"]);
|
|
17
|
+
function assertCanonicalReplay(replay) {
|
|
18
|
+
for (const key of Object.keys(replay))
|
|
19
|
+
if (!REPLAY_KEYS.has(key))
|
|
20
|
+
throw new Error(`provider replay has unknown field ${key}`);
|
|
21
|
+
if (typeof replay.protocol !== "string" || replay.protocol.length === 0)
|
|
22
|
+
throw new Error("provider replay protocol is required");
|
|
29
23
|
}
|
|
30
24
|
export function seedProviderReplayFromEvents(provider, events) {
|
|
31
25
|
if (!provider.seedProviderReplay)
|
|
@@ -36,11 +30,9 @@ export function seedProviderReplayFromEvents(provider, events) {
|
|
|
36
30
|
continue;
|
|
37
31
|
const toolCalls = event.tool_calls ?? [];
|
|
38
32
|
const stored = event.provider_replay;
|
|
39
|
-
if (stored
|
|
33
|
+
if (!stored || !isReplayCompatibleWithProvider(stored, descriptor))
|
|
40
34
|
continue;
|
|
41
|
-
|
|
42
|
-
// a legacy replay (e.g. Anthropic native_blocks) from the neutral transcript.
|
|
43
|
-
provider.seedProviderReplay({ content: event.content, toolCalls }, stored ?? {});
|
|
35
|
+
provider.seedProviderReplay({ content: event.content, toolCalls }, stored);
|
|
44
36
|
}
|
|
45
37
|
}
|
|
46
38
|
export function peekProviderReplay(provider, content, toolCalls) {
|
package/dist/runtime/runner.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { LLMProvider, Message, StreamEvent, PermissionRequestEvent, PermissionResponse, EntropySample, EntropyWatchOptions,
|
|
1
|
+
import type { LLMProvider, Message, StreamEvent, PermissionRequestEvent, PermissionResponse, EntropySample, EntropyWatchOptions, MemorySummarizer } from "../types.js";
|
|
2
2
|
import type { ToolSuspendEvent } from "./execution-plane.js";
|
|
3
|
-
import type {
|
|
3
|
+
import type { MemoryStore, MemoryQuery, MemoryRecord, MemoryScope } from "../memory/index.js";
|
|
4
4
|
import type { KnowledgeSource } from "../knowledge/index.js";
|
|
5
5
|
import type { SignalSource, RuntimeSignal } from "../signals/index.js";
|
|
6
6
|
import type { SessionLog, SessionEvent } from "./session-log.js";
|
|
@@ -12,7 +12,7 @@ import { type SubAgentOrchestrator } from "./sub-agent-orchestrator.js";
|
|
|
12
12
|
import { type ReducerRegistry } from "./reducers.js";
|
|
13
13
|
import { type NativeOsProfile, type OsProfileId, type SignalPolicy } from "./os-profile.js";
|
|
14
14
|
import { PayloadStore } from "./payload-store.js";
|
|
15
|
-
import { type
|
|
15
|
+
import { type ContextPolicyOverrides } from "./context-policy.js";
|
|
16
16
|
export interface MemoryWriteRateLimit {
|
|
17
17
|
maxWrites: number;
|
|
18
18
|
windowMs: number;
|
|
@@ -28,11 +28,14 @@ export interface ResourceQuota {
|
|
|
28
28
|
memoryWritesPerWindow?: MemoryWriteRateLimit;
|
|
29
29
|
}
|
|
30
30
|
export interface SchedulerPolicy {
|
|
31
|
-
version: 1;
|
|
32
31
|
criticalPathWeight: number;
|
|
33
32
|
fanoutWeight: number;
|
|
34
33
|
ageWeight: number;
|
|
35
34
|
tokenCostWeight: number;
|
|
35
|
+
deadlineWeight?: number;
|
|
36
|
+
processPriorityWeight?: number;
|
|
37
|
+
resourcePressureWeight?: number;
|
|
38
|
+
budgetPressureWeight?: number;
|
|
36
39
|
}
|
|
37
40
|
export declare function schedulerPolicyToKernel(policy: SchedulerPolicy): Record<string, number>;
|
|
38
41
|
/** Host-counted provider envelope and response reserves deducted from the model context window. */
|
|
@@ -45,7 +48,7 @@ export interface PromptBudget {
|
|
|
45
48
|
* Long-term memory policy (`set_memory_policy`) — opt-in, kernel-enforced. `validationEnabled:
|
|
46
49
|
* false` admits writes without validation, `maxContentBytes` / `maxNameLength` override the
|
|
47
50
|
* validation limits, and `retrievalTopK` caps `query_memory` breadth. Host storage is configured
|
|
48
|
-
* on the `
|
|
51
|
+
* on the `MemoryStore` and never enters this contract. Omitted fields keep the kernel defaults.
|
|
49
52
|
*/
|
|
50
53
|
export interface MemoryPolicy {
|
|
51
54
|
staleWarningDays?: number;
|
|
@@ -112,8 +115,8 @@ export interface RuntimeOptions {
|
|
|
112
115
|
agentId?: string;
|
|
113
116
|
memoryScope?: MemoryScope;
|
|
114
117
|
/** I4: optional run-start memory pre-fetch hook (mirrors Node SDK). Called once per run before
|
|
115
|
-
* the first LLM turn; each returned query string becomes a
|
|
116
|
-
* the knowledge partition before turn 1. Requires
|
|
118
|
+
* the first LLM turn; each returned query string becomes a memoryStore search; hits page into
|
|
119
|
+
* the knowledge partition before turn 1. Requires memoryStore + agentId. */
|
|
117
120
|
preQueryMemory?: (ctx: {
|
|
118
121
|
goal: string;
|
|
119
122
|
/** K4: `"initial"` = pre-turn-1 fetch; `"renewal"` = re-fired after a sprint renewal. */
|
|
@@ -123,7 +126,7 @@ export interface RuntimeOptions {
|
|
|
123
126
|
initialMemory?: string[];
|
|
124
127
|
/** Skill name → markdown body (WASM has no filesystem). */
|
|
125
128
|
skillContentMap?: Map<string, string>;
|
|
126
|
-
|
|
129
|
+
memoryStore?: MemoryStore;
|
|
127
130
|
/** M4: advisory callback when a recalled record crosses the promotion threshold. */
|
|
128
131
|
onPromotionSuggested?: (info: {
|
|
129
132
|
recordId: string;
|
|
@@ -138,7 +141,7 @@ export interface RuntimeOptions {
|
|
|
138
141
|
signalPolicy?: SignalPolicy;
|
|
139
142
|
promptBudget?: PromptBudget;
|
|
140
143
|
/** Stable replayable context behavior; ratios are normalized to integer ppm. */
|
|
141
|
-
contextPolicy?:
|
|
144
|
+
contextPolicy?: ContextPolicyOverrides;
|
|
142
145
|
schedulerPolicy?: SchedulerPolicy;
|
|
143
146
|
kernelReliability?: KernelReliabilityOptions;
|
|
144
147
|
/** Attempts allowed for a workflow node to satisfy its output schema, 1..16. Default: 2. */
|
|
@@ -214,8 +217,7 @@ export interface RuntimeOptions {
|
|
|
214
217
|
* synthesizes a minimal run spec. Omitted **or empty** ⇒ no ceiling (all registered tools) — the
|
|
215
218
|
* empty array is NOT a minimal surface here; use `baselineToolIds: []` for that.
|
|
216
219
|
*
|
|
217
|
-
*
|
|
218
|
-
* tool outside the advertised set never executes.
|
|
220
|
+
* Dispatch is always fail-closed: a call outside the advertised set never executes.
|
|
219
221
|
*/
|
|
220
222
|
allowedToolIds?: string[];
|
|
221
223
|
/**
|
|
@@ -226,10 +228,9 @@ export interface RuntimeOptions {
|
|
|
226
228
|
*
|
|
227
229
|
* `exposed = meta ∪ ((baseline ∪ stableCore ∪ ⋃ activeSkills.allowed_tools) ∩ ceiling)`
|
|
228
230
|
*
|
|
229
|
-
* An active skill that declares no `allowed_tools` contributes nothing
|
|
230
|
-
* surface stays narrow (strict; the legacy errs-open widening is deliberately not inherited).
|
|
231
|
+
* An active skill that declares no `allowed_tools` contributes nothing and the surface stays narrow.
|
|
231
232
|
*
|
|
232
|
-
* `undefined`
|
|
233
|
+
* `undefined` and `[]` both mean the minimal
|
|
233
234
|
* surface (meta-tools + `stableCoreToolIds` only) — the `allowedToolIds` "empty means no gating"
|
|
234
235
|
* trap does NOT recur here. Entries outside the ceiling silently intersect away.
|
|
235
236
|
*/
|
|
@@ -242,7 +243,6 @@ export interface RuntimeOptions {
|
|
|
242
243
|
* pass through. `"registered"` is the escape hatch restoring the pre-gate permissive behavior (any
|
|
243
244
|
* registered tool the model names executes, even if it was gated out of the tools schema).
|
|
244
245
|
*/
|
|
245
|
-
toolDispatchGate?: "exposed" | "registered";
|
|
246
246
|
/** P0-C: optional per-turn metrics sink for tool-gating telemetry (see `TurnMetrics`). Pure
|
|
247
247
|
* observation; invoked once per LLM turn. Never throws into the run loop (errors are swallowed). */
|
|
248
248
|
onTurnMetrics?: (metrics: TurnMetrics) => void;
|
|
@@ -250,9 +250,9 @@ export interface RuntimeOptions {
|
|
|
250
250
|
* to exactly their declared tools + meta-tools. (wasm skills come from `skillContentMap`; gating
|
|
251
251
|
* engages only once that carries per-skill tool lists.) */
|
|
252
252
|
stableCoreToolIds?: string[];
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
253
|
+
memoryProvider?: LLMProvider;
|
|
254
|
+
memorySummarizer?: MemorySummarizer;
|
|
255
|
+
memorySystemPrompt?: string;
|
|
256
256
|
payloadStore?: PayloadStore;
|
|
257
257
|
}
|
|
258
258
|
export type OperationCancellationReason = "user" | "deadline" | "lease_lost" | "host_shutdown";
|
|
@@ -389,4 +389,8 @@ export declare class RuntimeRunner {
|
|
|
389
389
|
private prefetchMemoryIntoHistory;
|
|
390
390
|
private archiveSemanticPageOut;
|
|
391
391
|
}
|
|
392
|
+
export declare function replayMessages(events: Array<{
|
|
393
|
+
seq: number;
|
|
394
|
+
event: SessionEvent;
|
|
395
|
+
}>, maxBytes?: number, archiveStore?: ArchiveStore): Promise<Message[]>;
|
|
392
396
|
export declare function collectText(stream: AsyncIterable<StreamEvent>): Promise<string>;
|