@deepstrike/wasm 0.2.2 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -2
- package/dist/governance.d.ts +32 -0
- package/dist/governance.js +18 -0
- package/dist/index.d.ts +2 -2
- package/dist/providers/anthropic.js +20 -3
- package/dist/providers/base.js +11 -1
- package/dist/runtime/execution-plane.d.ts +6 -3
- package/dist/runtime/execution-plane.js +54 -23
- package/dist/runtime/kernel-event-log.d.ts +26 -0
- package/dist/runtime/kernel-event-log.js +212 -0
- package/dist/runtime/kernel-step.d.ts +21 -1
- package/dist/runtime/kernel-step.js +9 -0
- package/dist/runtime/large-result-spool.d.ts +49 -0
- package/dist/runtime/large-result-spool.js +137 -0
- package/dist/runtime/os-profile.d.ts +7 -0
- package/dist/runtime/os-profile.js +6 -0
- package/dist/runtime/os-snapshot.d.ts +31 -0
- package/dist/runtime/os-snapshot.js +108 -0
- package/dist/runtime/runner.d.ts +20 -5
- package/dist/runtime/runner.js +305 -147
- package/dist/runtime/session-log.d.ts +110 -3
- package/dist/runtime/session-log.js +10 -2
- package/dist/runtime/sub-agent-orchestrator.d.ts +2 -2
- package/dist/runtime/sub-agent-orchestrator.js +14 -23
- package/dist/runtime/types/agent.d.ts +12 -3
- package/dist/runtime/types/agent.js +18 -0
- package/dist/types.d.ts +24 -0
- package/package.json +2 -2
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export interface ToolResult {
|
|
2
|
+
callId: string;
|
|
3
|
+
tool: string;
|
|
4
|
+
output: string;
|
|
5
|
+
isError?: boolean;
|
|
6
|
+
}
|
|
7
|
+
export interface SpooledToolResult {
|
|
8
|
+
originalOutput: string;
|
|
9
|
+
preview: string;
|
|
10
|
+
spoolRef: string;
|
|
11
|
+
wasSpooled: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface SpoolConfig {
|
|
14
|
+
spoolThresholdBytes: number;
|
|
15
|
+
previewTokens: number;
|
|
16
|
+
totalMessageLimitBytes: number;
|
|
17
|
+
maxAgeMs?: number;
|
|
18
|
+
driver?: SpoolStorageDriver;
|
|
19
|
+
}
|
|
20
|
+
export interface SpoolStorageDriver {
|
|
21
|
+
write(key: string, content: string): Promise<void> | void;
|
|
22
|
+
read(key: string): Promise<string> | string;
|
|
23
|
+
delete(key: string): Promise<void> | void;
|
|
24
|
+
list(): Promise<string[]> | string[];
|
|
25
|
+
mtime?(key: string): Promise<number> | number;
|
|
26
|
+
}
|
|
27
|
+
export declare class MemorySpoolDriver implements SpoolStorageDriver {
|
|
28
|
+
private cache;
|
|
29
|
+
write(key: string, content: string): Promise<void>;
|
|
30
|
+
read(key: string): Promise<string>;
|
|
31
|
+
delete(key: string): Promise<void>;
|
|
32
|
+
list(): Promise<string[]>;
|
|
33
|
+
mtime(key: string): Promise<number>;
|
|
34
|
+
}
|
|
35
|
+
export declare const DEFAULT_SPOOL_CONFIG: SpoolConfig;
|
|
36
|
+
export declare class LargeResultSpool {
|
|
37
|
+
private config;
|
|
38
|
+
private driver;
|
|
39
|
+
private activeWrites;
|
|
40
|
+
constructor(config?: Partial<SpoolConfig>);
|
|
41
|
+
private needsSpool;
|
|
42
|
+
private getSpoolKey;
|
|
43
|
+
private writeToDriver;
|
|
44
|
+
private generatePreview;
|
|
45
|
+
processToolResult(result: ToolResult): Promise<SpooledToolResult>;
|
|
46
|
+
persistOutput(callId: string, content: string): Promise<string>;
|
|
47
|
+
readSpooledResult(spoolRef: string): Promise<string>;
|
|
48
|
+
cleanup(maxAgeMs?: number): Promise<number>;
|
|
49
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
export class MemorySpoolDriver {
|
|
2
|
+
cache = new Map();
|
|
3
|
+
async write(key, content) {
|
|
4
|
+
this.cache.set(key, { content, mtime: Date.now() });
|
|
5
|
+
}
|
|
6
|
+
async read(key) {
|
|
7
|
+
const val = this.cache.get(key);
|
|
8
|
+
if (!val)
|
|
9
|
+
throw new Error(`Spooled result not found: ${key}`);
|
|
10
|
+
return val.content;
|
|
11
|
+
}
|
|
12
|
+
async delete(key) {
|
|
13
|
+
this.cache.delete(key);
|
|
14
|
+
}
|
|
15
|
+
async list() {
|
|
16
|
+
return Array.from(this.cache.keys());
|
|
17
|
+
}
|
|
18
|
+
async mtime(key) {
|
|
19
|
+
return this.cache.get(key)?.mtime ?? 0;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export const DEFAULT_SPOOL_CONFIG = {
|
|
23
|
+
spoolThresholdBytes: 50 * 1024, // 50KB
|
|
24
|
+
previewTokens: 500, // ~2KB
|
|
25
|
+
totalMessageLimitBytes: 200 * 1024, // 200KB
|
|
26
|
+
};
|
|
27
|
+
function simpleHash(content) {
|
|
28
|
+
let hash = 5381;
|
|
29
|
+
for (let i = 0; i < content.length; i++) {
|
|
30
|
+
hash = (hash * 33) ^ content.charCodeAt(i);
|
|
31
|
+
}
|
|
32
|
+
return (hash >>> 0).toString(16);
|
|
33
|
+
}
|
|
34
|
+
export class LargeResultSpool {
|
|
35
|
+
config;
|
|
36
|
+
driver;
|
|
37
|
+
activeWrites = new Map();
|
|
38
|
+
constructor(config = {}) {
|
|
39
|
+
this.config = { ...DEFAULT_SPOOL_CONFIG, ...config };
|
|
40
|
+
this.driver = this.config.driver ?? new MemorySpoolDriver();
|
|
41
|
+
}
|
|
42
|
+
needsSpool(result) {
|
|
43
|
+
return result.output.length > this.config.spoolThresholdBytes;
|
|
44
|
+
}
|
|
45
|
+
getSpoolKey(hash) {
|
|
46
|
+
return `.spool/${hash}.txt`;
|
|
47
|
+
}
|
|
48
|
+
async writeToDriver(content, hash) {
|
|
49
|
+
const key = this.getSpoolKey(hash);
|
|
50
|
+
let promise = this.activeWrites.get(key);
|
|
51
|
+
if (!promise) {
|
|
52
|
+
promise = (async () => {
|
|
53
|
+
try {
|
|
54
|
+
await this.driver.write(key, content);
|
|
55
|
+
return key;
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
this.activeWrites.delete(key);
|
|
59
|
+
}
|
|
60
|
+
})();
|
|
61
|
+
this.activeWrites.set(key, promise);
|
|
62
|
+
}
|
|
63
|
+
return promise;
|
|
64
|
+
}
|
|
65
|
+
generatePreview(content) {
|
|
66
|
+
const previewTokens = Math.min(this.config.previewTokens, content.length / 4);
|
|
67
|
+
const preview = content.substring(0, previewTokens);
|
|
68
|
+
const omitted = content.length - previewTokens;
|
|
69
|
+
return `[tool_result_spooled]
|
|
70
|
+
size: ${content.length} bytes
|
|
71
|
+
preview: first ${previewTokens} chars
|
|
72
|
+
omitted: ${omitted} chars
|
|
73
|
+
[full content available via Read tool]
|
|
74
|
+
`;
|
|
75
|
+
}
|
|
76
|
+
async processToolResult(result) {
|
|
77
|
+
if (!this.needsSpool(result)) {
|
|
78
|
+
return {
|
|
79
|
+
originalOutput: result.output,
|
|
80
|
+
preview: result.output,
|
|
81
|
+
spoolRef: "",
|
|
82
|
+
wasSpooled: false,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
const hash = simpleHash(result.output);
|
|
86
|
+
const spoolRef = await this.writeToDriver(result.output, hash);
|
|
87
|
+
const preview = this.generatePreview(result.output);
|
|
88
|
+
return {
|
|
89
|
+
originalOutput: result.output,
|
|
90
|
+
preview,
|
|
91
|
+
spoolRef,
|
|
92
|
+
wasSpooled: true,
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
async persistOutput(callId, content) {
|
|
96
|
+
const hash = simpleHash(content);
|
|
97
|
+
const key = `.spool/${callId}-${hash.slice(0, 16)}.txt`;
|
|
98
|
+
let promise = this.activeWrites.get(key);
|
|
99
|
+
if (!promise) {
|
|
100
|
+
promise = (async () => {
|
|
101
|
+
try {
|
|
102
|
+
await this.driver.write(key, content);
|
|
103
|
+
return key;
|
|
104
|
+
}
|
|
105
|
+
finally {
|
|
106
|
+
this.activeWrites.delete(key);
|
|
107
|
+
}
|
|
108
|
+
})();
|
|
109
|
+
this.activeWrites.set(key, promise);
|
|
110
|
+
}
|
|
111
|
+
return promise;
|
|
112
|
+
}
|
|
113
|
+
async readSpooledResult(spoolRef) {
|
|
114
|
+
return this.driver.read(spoolRef);
|
|
115
|
+
}
|
|
116
|
+
async cleanup(maxAgeMs) {
|
|
117
|
+
const limit = maxAgeMs ?? this.config.maxAgeMs ?? 7 * 24 * 60 * 60 * 1000;
|
|
118
|
+
try {
|
|
119
|
+
const keys = await this.driver.list();
|
|
120
|
+
let count = 0;
|
|
121
|
+
const now = Date.now();
|
|
122
|
+
for (const key of keys) {
|
|
123
|
+
if (this.driver.mtime) {
|
|
124
|
+
const mtime = await this.driver.mtime(key);
|
|
125
|
+
if (now - mtime > limit) {
|
|
126
|
+
await this.driver.delete(key);
|
|
127
|
+
count++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return count;
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return 0;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { GovernancePolicy } from "../governance.js";
|
|
2
|
+
/** Default attention policy for native profile smoke tests. */
|
|
3
|
+
export declare const DEFAULT_NATIVE_ATTENTION_POLICY: {
|
|
4
|
+
maxQueueSize: number;
|
|
5
|
+
};
|
|
6
|
+
/** Permissive governance policy for native runs that do not need AskUser. */
|
|
7
|
+
export declare const DEFAULT_NATIVE_GOVERNANCE_POLICY: GovernancePolicy;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Default attention policy for native profile smoke tests. */
|
|
2
|
+
export const DEFAULT_NATIVE_ATTENTION_POLICY = { maxQueueSize: 64 };
|
|
3
|
+
/** Permissive governance policy for native runs that do not need AskUser. */
|
|
4
|
+
export const DEFAULT_NATIVE_GOVERNANCE_POLICY = {
|
|
5
|
+
rules: [{ pattern: "*", action: "allow" }],
|
|
6
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { SessionEvent } from "./session-log.js";
|
|
2
|
+
export interface OsSnapshot {
|
|
3
|
+
lastSuspend?: {
|
|
4
|
+
turn: number;
|
|
5
|
+
reason: string;
|
|
6
|
+
pending_calls: string[];
|
|
7
|
+
};
|
|
8
|
+
lastResumedTurn?: number;
|
|
9
|
+
processByAgent: Array<{
|
|
10
|
+
turn: number;
|
|
11
|
+
agent_id: string;
|
|
12
|
+
parent_session_id: string;
|
|
13
|
+
state: string;
|
|
14
|
+
}>;
|
|
15
|
+
budgetExceeded: Array<{
|
|
16
|
+
turn: number;
|
|
17
|
+
budget: string;
|
|
18
|
+
}>;
|
|
19
|
+
signals: Array<{
|
|
20
|
+
turn: number;
|
|
21
|
+
signal_id: string;
|
|
22
|
+
disposition: string;
|
|
23
|
+
queue_depth: number;
|
|
24
|
+
}>;
|
|
25
|
+
pageOutCount: number;
|
|
26
|
+
pageInCount: number;
|
|
27
|
+
spoolCount: number;
|
|
28
|
+
toolGatedCount: number;
|
|
29
|
+
}
|
|
30
|
+
export declare function rebuildOsSnapshotFromSessionEvents(events: SessionEvent[]): OsSnapshot;
|
|
31
|
+
export declare function sessionLogHasRequiredCategories(events: SessionEvent[]): boolean;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { categoryForKind, primitiveForKind } from "./kernel-event-log.js";
|
|
2
|
+
const KERNEL_KINDS = new Set([
|
|
3
|
+
"compressed",
|
|
4
|
+
"page_out",
|
|
5
|
+
"page_in",
|
|
6
|
+
"large_result_spooled",
|
|
7
|
+
"capability_changed",
|
|
8
|
+
"context_renewed",
|
|
9
|
+
"suspended",
|
|
10
|
+
"resumed",
|
|
11
|
+
"tool_gated",
|
|
12
|
+
"signal_disposed",
|
|
13
|
+
"budget_exceeded",
|
|
14
|
+
"checkpoint_taken",
|
|
15
|
+
"rollbacked",
|
|
16
|
+
"agent_process_changed",
|
|
17
|
+
"milestone_advanced",
|
|
18
|
+
"milestone_blocked",
|
|
19
|
+
"milestone_evidence",
|
|
20
|
+
]);
|
|
21
|
+
export function rebuildOsSnapshotFromSessionEvents(events) {
|
|
22
|
+
const snap = {
|
|
23
|
+
processByAgent: [],
|
|
24
|
+
budgetExceeded: [],
|
|
25
|
+
signals: [],
|
|
26
|
+
pageOutCount: 0,
|
|
27
|
+
pageInCount: 0,
|
|
28
|
+
spoolCount: 0,
|
|
29
|
+
toolGatedCount: 0,
|
|
30
|
+
};
|
|
31
|
+
const index = new Map();
|
|
32
|
+
for (const event of events) {
|
|
33
|
+
if (!KERNEL_KINDS.has(event.kind) && event.kind !== "suspended" && event.kind !== "resumed") {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
switch (event.kind) {
|
|
37
|
+
case "suspended":
|
|
38
|
+
snap.lastSuspend = {
|
|
39
|
+
turn: event.turn,
|
|
40
|
+
reason: event.reason,
|
|
41
|
+
pending_calls: event.pending_calls ?? [],
|
|
42
|
+
};
|
|
43
|
+
break;
|
|
44
|
+
case "resumed":
|
|
45
|
+
snap.lastResumedTurn = event.turn;
|
|
46
|
+
break;
|
|
47
|
+
case "tool_gated":
|
|
48
|
+
snap.toolGatedCount += 1;
|
|
49
|
+
break;
|
|
50
|
+
case "agent_process_changed": {
|
|
51
|
+
const record = {
|
|
52
|
+
turn: event.turn,
|
|
53
|
+
agent_id: event.agent_id,
|
|
54
|
+
parent_session_id: event.parent_session_id,
|
|
55
|
+
state: event.state ?? "running",
|
|
56
|
+
};
|
|
57
|
+
const idx = index.get(event.agent_id);
|
|
58
|
+
if (idx !== undefined)
|
|
59
|
+
snap.processByAgent[idx] = record;
|
|
60
|
+
else {
|
|
61
|
+
index.set(event.agent_id, snap.processByAgent.length);
|
|
62
|
+
snap.processByAgent.push(record);
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case "budget_exceeded":
|
|
67
|
+
snap.budgetExceeded.push({ turn: event.turn, budget: event.budget });
|
|
68
|
+
break;
|
|
69
|
+
case "signal_disposed":
|
|
70
|
+
snap.signals.push({
|
|
71
|
+
turn: event.turn,
|
|
72
|
+
signal_id: event.signal_id,
|
|
73
|
+
disposition: event.disposition,
|
|
74
|
+
queue_depth: event.queue_depth,
|
|
75
|
+
});
|
|
76
|
+
break;
|
|
77
|
+
case "page_out":
|
|
78
|
+
snap.pageOutCount += 1;
|
|
79
|
+
break;
|
|
80
|
+
case "page_in":
|
|
81
|
+
snap.pageInCount += 1;
|
|
82
|
+
break;
|
|
83
|
+
case "large_result_spooled":
|
|
84
|
+
snap.spoolCount += 1;
|
|
85
|
+
break;
|
|
86
|
+
default:
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return snap;
|
|
91
|
+
}
|
|
92
|
+
export function sessionLogHasRequiredCategories(events) {
|
|
93
|
+
for (const event of events) {
|
|
94
|
+
if (!KERNEL_KINDS.has(event.kind))
|
|
95
|
+
continue;
|
|
96
|
+
const cat = event.category;
|
|
97
|
+
if (!cat)
|
|
98
|
+
return false;
|
|
99
|
+
if (cat !== categoryForKind(event.kind))
|
|
100
|
+
return false;
|
|
101
|
+
const prim = event.primitive;
|
|
102
|
+
if (prim !== undefined) {
|
|
103
|
+
if (prim !== primitiveForKind(event.kind))
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return true;
|
|
108
|
+
}
|
package/dist/runtime/runner.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { LLMProvider, Message, StreamEvent } from "../types.js";
|
|
1
|
+
import type { LLMProvider, Message, StreamEvent, PermissionRequestEvent, PermissionResponse, DreamSummarizer } from "../types.js";
|
|
2
2
|
import type { ToolSuspendEvent } from "./execution-plane.js";
|
|
3
3
|
import type { DreamStore, DreamResult } from "../memory/index.js";
|
|
4
4
|
import type { KnowledgeSource } from "../knowledge/index.js";
|
|
5
5
|
import type { SignalSource } from "../signals/index.js";
|
|
6
6
|
import type { SessionLog, SessionEvent } from "./session-log.js";
|
|
7
7
|
import type { ExecutionPlane } from "./execution-plane.js";
|
|
8
|
-
import type
|
|
8
|
+
import { type GovernancePolicy } from "../governance.js";
|
|
9
9
|
import type { AgentRunSpec, SubAgentResult, MilestonePolicy, MilestoneContract, MilestoneCheckResult } from "./types/agent.js";
|
|
10
10
|
import { type SubAgentOrchestrator } from "./sub-agent-orchestrator.js";
|
|
11
|
+
import { LargeResultSpool } from "./large-result-spool.js";
|
|
11
12
|
export interface RuntimeOptions {
|
|
12
13
|
provider: LLMProvider;
|
|
13
14
|
sessionLog: SessionLog;
|
|
@@ -24,8 +25,12 @@ export interface RuntimeOptions {
|
|
|
24
25
|
knowledgeSource?: KnowledgeSource;
|
|
25
26
|
signalSource?: SignalSource;
|
|
26
27
|
extensions?: Record<string, unknown>;
|
|
27
|
-
|
|
28
|
+
governancePolicy?: GovernancePolicy;
|
|
29
|
+
attentionPolicy?: {
|
|
30
|
+
maxQueueSize?: number;
|
|
31
|
+
};
|
|
28
32
|
onToolSuspend?: (event: ToolSuspendEvent) => Promise<unknown> | unknown;
|
|
33
|
+
onPermissionRequest?: (event: PermissionRequestEvent) => Promise<PermissionResponse | boolean> | PermissionResponse | boolean;
|
|
29
34
|
subAgentOrchestrator?: SubAgentOrchestrator;
|
|
30
35
|
milestonePolicy?: MilestonePolicy;
|
|
31
36
|
milestoneContract?: MilestoneContract;
|
|
@@ -35,6 +40,10 @@ export interface RuntimeOptions {
|
|
|
35
40
|
requiredEvidence: string[];
|
|
36
41
|
}) => Promise<MilestoneCheckResult> | MilestoneCheckResult;
|
|
37
42
|
runSpec?: AgentRunSpec;
|
|
43
|
+
dreamProvider?: LLMProvider;
|
|
44
|
+
dreamSummarizer?: DreamSummarizer;
|
|
45
|
+
dreamSystemPrompt?: string;
|
|
46
|
+
resultSpool?: LargeResultSpool;
|
|
38
47
|
}
|
|
39
48
|
export declare class RuntimeRunner {
|
|
40
49
|
private readonly opts;
|
|
@@ -43,6 +52,8 @@ export declare class RuntimeRunner {
|
|
|
43
52
|
private activeKernel;
|
|
44
53
|
private currentSessionId;
|
|
45
54
|
private nextArchiveStart;
|
|
55
|
+
private localPageOutCache;
|
|
56
|
+
private pendingSpoolOutputs;
|
|
46
57
|
constructor(opts: RuntimeOptions);
|
|
47
58
|
get hostOptions(): RuntimeOptions;
|
|
48
59
|
interrupt(): void;
|
|
@@ -57,11 +68,15 @@ export declare class RuntimeRunner {
|
|
|
57
68
|
}>;
|
|
58
69
|
}): AsyncIterable<StreamEvent>;
|
|
59
70
|
wake(sessionId: string, extensions?: Record<string, unknown>): AsyncIterable<StreamEvent>;
|
|
60
|
-
/** Push
|
|
61
|
-
|
|
71
|
+
/** Push content into Slot 2 (system_knowledge) via add_knowledge_message. */
|
|
72
|
+
pushKnowledge(message: Message, tokens?: number): void;
|
|
73
|
+
/** Phase 4: satisfy kernel page-in requests before meta-tool execution. */
|
|
74
|
+
private applyKernelPageIn;
|
|
75
|
+
private resolveKernelSuspend;
|
|
62
76
|
dream(agentId: string, nowMs?: number): Promise<DreamResult>;
|
|
63
77
|
private execute;
|
|
64
78
|
spawnSubAgent(spec: AgentRunSpec): Promise<SubAgentResult>;
|
|
65
79
|
private appendObservations;
|
|
80
|
+
private archiveSemanticPageOut;
|
|
66
81
|
}
|
|
67
82
|
export declare function collectText(stream: AsyncIterable<StreamEvent>): Promise<string>;
|