@deepstrike/sdk 0.2.36 → 0.2.38
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/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/os/public.d.ts +1 -1
- package/dist/os/public.js +1 -1
- package/dist/runtime/facade.js +11 -11
- package/dist/runtime/kernel-event-log.d.ts +0 -6
- package/dist/runtime/kernel-event-log.js +57 -62
- package/dist/runtime/kernel-step.d.ts +20 -1
- package/dist/runtime/kernel-step.js +25 -0
- package/dist/runtime/loop-driver.d.ts +108 -0
- package/dist/runtime/loop-driver.js +198 -0
- package/dist/runtime/os-snapshot.d.ts +0 -1
- package/dist/runtime/os-snapshot.js +0 -19
- package/dist/runtime/reactive-session.d.ts +5 -2
- package/dist/runtime/reactive-session.js +17 -4
- package/dist/runtime/run-group.d.ts +9 -0
- package/dist/runtime/run-group.js +18 -4
- package/dist/runtime/runner.d.ts +43 -6
- package/dist/runtime/runner.js +305 -71
- package/dist/runtime/session-log.d.ts +46 -54
- package/dist/runtime/session-repair.d.ts +29 -7
- package/dist/runtime/session-repair.js +37 -9
- package/dist/runtime/sub-agent-orchestrator.d.ts +12 -0
- package/dist/runtime/sub-agent-orchestrator.js +48 -32
- package/dist/runtime/workflow-control-flow.d.ts +10 -2
- package/dist/runtime/workflow-control-flow.js +27 -6
- package/dist/signals/gateway.d.ts +4 -2
- package/dist/signals/gateway.js +8 -1
- package/dist/types/agent.d.ts +28 -1
- package/dist/types/agent.js +25 -1
- package/dist/types.d.ts +50 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { runAgent, runFanout } from "./runtime/facade.js";
|
|
2
|
+
export { runLoop, LoopDriver, foldLoopState } from "./runtime/loop-driver.js";
|
|
3
|
+
export type { LoopSpec, LoopOutcome } from "./runtime/loop-driver.js";
|
|
2
4
|
export type { RunAgentOptions, RunFanoutOptions } from "./runtime/facade.js";
|
|
3
5
|
export { RuntimeRunner, collectText } from "./runtime/runner.js";
|
|
4
6
|
export type { RuntimeOptions } from "./runtime/runner.js";
|
|
@@ -29,5 +31,5 @@ export { Governance } from "./governance.js";
|
|
|
29
31
|
export type { GovernanceVerdict, GovernancePolicy, GovernanceConstraint } from "./governance.js";
|
|
30
32
|
export { AgentPool } from "./collaboration/pool.js";
|
|
31
33
|
export type { RuntimeSignal, SignalSource } from "./signals/types.js";
|
|
32
|
-
export type { Message, ToolCall, ToolResult, ToolSchema, ContentPart, TextPart, ImagePart, AudioPart, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolChunk, ToolDeltaEvent, ToolSuspendEvent, ToolResultEvent, ToolAuditFailedEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, PermissionResolvedEvent, PermissionResponse, LLMProvider, RetryConfig, TokenUsage, } from "./types.js";
|
|
34
|
+
export type { Message, ToolCall, ToolResult, ToolSchema, ContentPart, TextPart, ImagePart, AudioPart, StreamEvent, TextDelta, ThinkingDelta, ToolCallEvent, ToolChunk, ToolDeltaEvent, ToolSuspendEvent, ToolResultEvent, ToolAuditFailedEvent, DoneEvent, ErrorEvent, PermissionRequestEvent, PermissionResolvedEvent, PermissionResponse, EntropySample, EntropySampleEvent, EntropyAlertEvent, EntropyWatchOptions, LLMProvider, RetryConfig, TokenUsage, } from "./types.js";
|
|
33
35
|
export type { WorkflowSpec, WorkflowNodeSpec, } from "./types/agent.js";
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
// ╚══════════════════════════════════════════════════════════════════════════╝
|
|
13
13
|
// ── Start here: the canonical entry points ─────────────────────────────────
|
|
14
14
|
export { runAgent, runFanout } from "./runtime/facade.js";
|
|
15
|
+
// ③ dynamic loop agents: self-pacing rounds over the kernel pacing trap.
|
|
16
|
+
export { runLoop, LoopDriver, foldLoopState } from "./runtime/loop-driver.js";
|
|
15
17
|
export { RuntimeRunner, collectText } from "./runtime/runner.js";
|
|
16
18
|
// ── Execution plane + session log (the defaults) ────────────────────────────
|
|
17
19
|
export { LocalExecutionPlane } from "./runtime/execution-plane.js";
|
package/dist/os/public.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { DEFAULT_NATIVE_ATTENTION_POLICY, DEFAULT_NATIVE_GOVERNANCE_POLICY, assertNativeProfile, osProfile, } from "../runtime/os-profile.js";
|
|
2
2
|
export type { NativeOsProfile, OsProfileId } from "../runtime/os-profile.js";
|
|
3
|
-
export { rebuildOsSnapshotFromSessionEvents
|
|
3
|
+
export { rebuildOsSnapshotFromSessionEvents } from "../runtime/os-snapshot.js";
|
|
4
4
|
export type { OsSnapshot } from "../runtime/os-snapshot.js";
|
|
5
5
|
export type { KernelEventCategory } from "../runtime/kernel-event-log.js";
|
|
6
6
|
export { KernelPrimitivesDashboard } from "../runtime/kernel-primitives-dashboard.js";
|
package/dist/os/public.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// `@deepstrike/sdk/os` — Agent-OS diagnostics, profiles, signal/permission machinery, replay-testing,
|
|
2
2
|
// and the scheduler/quota/policy types referenced by advanced `RuntimeOptions` fields.
|
|
3
3
|
export { DEFAULT_NATIVE_ATTENTION_POLICY, DEFAULT_NATIVE_GOVERNANCE_POLICY, assertNativeProfile, osProfile, } from "../runtime/os-profile.js";
|
|
4
|
-
export { rebuildOsSnapshotFromSessionEvents
|
|
4
|
+
export { rebuildOsSnapshotFromSessionEvents } from "../runtime/os-snapshot.js";
|
|
5
5
|
export { KernelPrimitivesDashboard } from "../runtime/kernel-primitives-dashboard.js";
|
|
6
6
|
// Signals + SDK-side permissions.
|
|
7
7
|
export { ScheduledPrompt } from "../signals/scheduled.js";
|
package/dist/runtime/facade.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { RuntimeRunner, collectText } from "./runner.js";
|
|
16
16
|
import { LocalExecutionPlane } from "./execution-plane.js";
|
|
17
17
|
import { InMemorySessionLog } from "./session-log.js";
|
|
18
|
+
import { fanoutSynthesize } from "../types/agent.js";
|
|
18
19
|
/**
|
|
19
20
|
* Run a single agent to completion and return its final text — `RuntimeRunner` + `run` + `collectText`
|
|
20
21
|
* in one call. Register tools by passing `tools`; everything else has a working default.
|
|
@@ -46,17 +47,16 @@ export async function runFanout(opts) {
|
|
|
46
47
|
maxTokens: opts.maxTokens ?? 32_000,
|
|
47
48
|
...(opts.maxTurns !== undefined ? { maxTurns: opts.maxTurns } : {}),
|
|
48
49
|
});
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
]
|
|
59
|
-
};
|
|
50
|
+
// W-N8: build the spec via the ONE fanout template (it pins the pattern's isolation /
|
|
51
|
+
// context-inheritance choices — read-only system-only workers, full-context synthesizer — which
|
|
52
|
+
// this facade used to silently drop), then apply the caller's role overrides on top.
|
|
53
|
+
const spec = fanoutSynthesize(opts.tasks, opts.synthesize);
|
|
54
|
+
if (opts.workerRole) {
|
|
55
|
+
for (const node of spec.nodes.slice(0, opts.tasks.length))
|
|
56
|
+
node.role = opts.workerRole;
|
|
57
|
+
}
|
|
58
|
+
if (opts.synthesisRole)
|
|
59
|
+
spec.nodes[spec.nodes.length - 1].role = opts.synthesisRole;
|
|
60
60
|
const outcome = await runner.runWorkflow(spec, opts.sessionId ? { sessionId: opts.sessionId } : undefined);
|
|
61
61
|
// The synthesis node is the last spec node; the kernel ids nodes `wf-node{index}`. Prefer that id,
|
|
62
62
|
// but fall back to the last completed node's output so a kernel id-scheme change can't silently
|
|
@@ -3,12 +3,6 @@ import type { SessionEvent } from "./session-log.js";
|
|
|
3
3
|
/** Agent OS kernel event category (Phase 5). */
|
|
4
4
|
export type KernelEventCategory = "syscall" | "sched" | "mm" | "proc" | "ipc";
|
|
5
5
|
export declare function categoryForKind(kind: string): KernelEventCategory;
|
|
6
|
-
export declare function withCategory<T extends {
|
|
7
|
-
kind: string;
|
|
8
|
-
}>(event: T): T & {
|
|
9
|
-
category: KernelEventCategory;
|
|
10
|
-
primitive: KernelPrimitive;
|
|
11
|
-
};
|
|
12
6
|
type CompressionAction = Extract<SessionEvent, {
|
|
13
7
|
kind: "compressed";
|
|
14
8
|
}>["action"];
|
|
@@ -22,33 +22,16 @@ export function categoryForKind(kind) {
|
|
|
22
22
|
return "sched";
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
export function withCategory(event) {
|
|
26
|
-
const category = categoryForKind(event.kind);
|
|
27
|
-
return {
|
|
28
|
-
...event,
|
|
29
|
-
category,
|
|
30
|
-
primitive: primitiveForCategory(category),
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
25
|
export function kernelObservationToSessionEvent(obs, turn, opts = {}) {
|
|
34
26
|
const t = obs.turn ?? turn;
|
|
35
27
|
const compressionAction = opts.compressionAction ?? (() => undefined);
|
|
36
28
|
switch (obs.kind) {
|
|
37
|
-
case "page_out":
|
|
38
|
-
return withCategory({
|
|
39
|
-
kind: "page_out",
|
|
40
|
-
turn: t,
|
|
41
|
-
action: compressionAction(obs.action),
|
|
42
|
-
summary: obs.summary,
|
|
43
|
-
tier_hint: obs.tier_hint ?? "durable",
|
|
44
|
-
message_count: Array.isArray(obs.archived) ? obs.archived.length : 0,
|
|
45
|
-
});
|
|
46
29
|
case "compressed": {
|
|
47
30
|
const latest = opts.latestSeq ?? -1;
|
|
48
31
|
const start = opts.nextArchiveStart ?? 0;
|
|
49
32
|
if (latest < start)
|
|
50
33
|
return null;
|
|
51
|
-
return
|
|
34
|
+
return {
|
|
52
35
|
kind: "compressed",
|
|
53
36
|
turn: t,
|
|
54
37
|
archived_seq_range: [start, latest],
|
|
@@ -57,24 +40,24 @@ export function kernelObservationToSessionEvent(obs, turn, opts = {}) {
|
|
|
57
40
|
summary_tokens: obs.summary ? Math.max(1, Math.ceil(obs.summary.length / 4)) : undefined,
|
|
58
41
|
archive_ref: opts.archiveRef,
|
|
59
42
|
preserved_refs: opts.preservedRefs ?? [],
|
|
60
|
-
}
|
|
43
|
+
};
|
|
61
44
|
}
|
|
62
45
|
case "renewed":
|
|
63
|
-
return
|
|
46
|
+
return {
|
|
64
47
|
kind: "context_renewed",
|
|
65
48
|
turn: t,
|
|
66
49
|
sprint: obs.sprint ?? 0,
|
|
67
50
|
handoff_ref: "",
|
|
68
|
-
}
|
|
51
|
+
};
|
|
69
52
|
case "rollbacked":
|
|
70
|
-
return
|
|
53
|
+
return {
|
|
71
54
|
kind: "rollbacked",
|
|
72
55
|
turn: t,
|
|
73
56
|
checkpoint_history_len: obs.checkpoint_history_len ?? 0,
|
|
74
57
|
reason: obs.reason,
|
|
75
|
-
}
|
|
58
|
+
};
|
|
76
59
|
case "capability_changed":
|
|
77
|
-
return
|
|
60
|
+
return {
|
|
78
61
|
kind: "capability_changed",
|
|
79
62
|
turn: t,
|
|
80
63
|
added: obs.added ?? [],
|
|
@@ -84,36 +67,48 @@ export function kernelObservationToSessionEvent(obs, turn, opts = {}) {
|
|
|
84
67
|
...(obs.version != null && { version: obs.version }),
|
|
85
68
|
...(obs.mounted_by != null && { mounted_by: obs.mounted_by }),
|
|
86
69
|
...(obs.mount_reason != null && { mount_reason: obs.mount_reason }),
|
|
87
|
-
}
|
|
70
|
+
};
|
|
88
71
|
case "milestone_advanced":
|
|
89
|
-
return
|
|
72
|
+
return {
|
|
90
73
|
kind: "milestone_advanced",
|
|
91
74
|
turn: t,
|
|
92
75
|
phase_id: obs.phase_id ?? "",
|
|
93
76
|
capabilities_unlocked: obs.capabilities_unlocked ?? [],
|
|
94
|
-
}
|
|
77
|
+
};
|
|
95
78
|
case "milestone_blocked":
|
|
96
|
-
return
|
|
79
|
+
return {
|
|
97
80
|
kind: "milestone_blocked",
|
|
98
81
|
turn: t,
|
|
99
82
|
phase_id: obs.phase_id ?? "",
|
|
100
83
|
reason: typeof obs.reason === "string" ? obs.reason : "",
|
|
101
|
-
}
|
|
102
|
-
case "milestone_evidence":
|
|
103
|
-
return withCategory({
|
|
104
|
-
kind: "milestone_evidence",
|
|
105
|
-
turn: t,
|
|
106
|
-
phase_id: obs.phase_id ?? "",
|
|
107
|
-
evidence: obs.evidence ?? [],
|
|
108
|
-
});
|
|
84
|
+
};
|
|
109
85
|
case "checkpoint_taken":
|
|
110
|
-
return
|
|
86
|
+
return {
|
|
111
87
|
kind: "checkpoint_taken",
|
|
112
88
|
turn: t,
|
|
113
89
|
history_len: obs.history_len ?? 0,
|
|
114
|
-
}
|
|
90
|
+
};
|
|
91
|
+
case "entropy_sample":
|
|
92
|
+
return {
|
|
93
|
+
kind: "entropy_sample",
|
|
94
|
+
turn: t,
|
|
95
|
+
score: obs.score ?? 0,
|
|
96
|
+
score_version: obs.score_version ?? 0,
|
|
97
|
+
rho: obs.rho ?? 0,
|
|
98
|
+
repeat_pressure: obs.repeat_pressure ?? 0,
|
|
99
|
+
failure_rate: obs.failure_rate ?? 0,
|
|
100
|
+
rollbacks_in_window: obs.rollbacks_in_window ?? 0,
|
|
101
|
+
window_turns: obs.window_turns ?? 0,
|
|
102
|
+
};
|
|
103
|
+
case "entropy_alert":
|
|
104
|
+
return {
|
|
105
|
+
kind: "entropy_alert",
|
|
106
|
+
turn: t,
|
|
107
|
+
score: obs.score ?? 0,
|
|
108
|
+
threshold: obs.threshold ?? 0,
|
|
109
|
+
};
|
|
115
110
|
case "agent_process_changed":
|
|
116
|
-
return
|
|
111
|
+
return {
|
|
117
112
|
kind: "agent_process_changed",
|
|
118
113
|
turn: t,
|
|
119
114
|
agent_id: obs.agent_id ?? "",
|
|
@@ -126,47 +121,47 @@ export function kernelObservationToSessionEvent(obs, turn, opts = {}) {
|
|
|
126
121
|
...(obs.result_termination
|
|
127
122
|
? { result_termination: obs.result_termination }
|
|
128
123
|
: {}),
|
|
129
|
-
}
|
|
124
|
+
};
|
|
130
125
|
case "tool_gated":
|
|
131
|
-
return
|
|
126
|
+
return {
|
|
132
127
|
kind: "tool_gated",
|
|
133
128
|
turn: t,
|
|
134
129
|
call_id: obs.call_id ?? "",
|
|
135
130
|
tool: obs.tool ?? "",
|
|
136
131
|
reason: typeof obs.reason === "string" ? obs.reason : "",
|
|
137
|
-
}
|
|
132
|
+
};
|
|
138
133
|
case "signal_disposed":
|
|
139
|
-
return
|
|
134
|
+
return {
|
|
140
135
|
kind: "signal_disposed",
|
|
141
136
|
turn: t,
|
|
142
137
|
signal_id: obs.signal_id ?? "",
|
|
143
138
|
disposition: obs.disposition ?? "",
|
|
144
139
|
queue_depth: obs.queue_depth ?? 0,
|
|
145
|
-
}
|
|
140
|
+
};
|
|
146
141
|
case "budget_exceeded":
|
|
147
|
-
return
|
|
142
|
+
return {
|
|
148
143
|
kind: "budget_exceeded",
|
|
149
144
|
turn: t,
|
|
150
145
|
budget: obs.budget ?? "",
|
|
151
|
-
}
|
|
146
|
+
};
|
|
152
147
|
case "suspended":
|
|
153
|
-
return
|
|
148
|
+
return {
|
|
154
149
|
kind: "suspended",
|
|
155
150
|
turn: t,
|
|
156
151
|
reason: typeof obs.reason === "string" ? obs.reason : "",
|
|
157
152
|
pending_calls: obs.pending_calls ?? [],
|
|
158
|
-
}
|
|
153
|
+
};
|
|
159
154
|
case "resumed":
|
|
160
|
-
return
|
|
155
|
+
return {
|
|
161
156
|
kind: "resumed",
|
|
162
157
|
turn: t,
|
|
163
158
|
approved: obs.approved ?? [],
|
|
164
159
|
denied: obs.denied ?? [],
|
|
165
|
-
}
|
|
160
|
+
};
|
|
166
161
|
case "page_in_requested":
|
|
167
162
|
return null;
|
|
168
163
|
case "large_result_spooled":
|
|
169
|
-
return
|
|
164
|
+
return {
|
|
170
165
|
kind: "large_result_spooled",
|
|
171
166
|
turn: t,
|
|
172
167
|
call_id: obs.call_id ?? "",
|
|
@@ -174,51 +169,51 @@ export function kernelObservationToSessionEvent(obs, turn, opts = {}) {
|
|
|
174
169
|
original_size: obs.original_size ?? 0,
|
|
175
170
|
preview_size: obs.preview_size ?? 0,
|
|
176
171
|
spool_ref: opts.spoolRef,
|
|
177
|
-
}
|
|
172
|
+
};
|
|
178
173
|
case "memory_written":
|
|
179
|
-
return
|
|
174
|
+
return {
|
|
180
175
|
kind: "memory_written",
|
|
181
176
|
turn: t,
|
|
182
177
|
memory_id: obs.memory_id ?? "",
|
|
183
178
|
memory_kind: obs.memory_kind ?? "",
|
|
184
179
|
size_bytes: obs.size_bytes ?? 0,
|
|
185
|
-
}
|
|
180
|
+
};
|
|
186
181
|
case "memory_queried":
|
|
187
|
-
return
|
|
182
|
+
return {
|
|
188
183
|
kind: "memory_queried",
|
|
189
184
|
turn: t,
|
|
190
185
|
query_context: obs.query_context ?? "",
|
|
191
186
|
requested_k: obs.requested_k ?? 0,
|
|
192
187
|
requires_async_response: obs.requires_async_response ?? false,
|
|
193
|
-
}
|
|
188
|
+
};
|
|
194
189
|
case "memory_validation_failed":
|
|
195
|
-
return
|
|
190
|
+
return {
|
|
196
191
|
kind: "memory_validation_failed",
|
|
197
192
|
turn: t,
|
|
198
193
|
memory_id: obs.memory_id ?? "",
|
|
199
194
|
error: obs.error ?? "",
|
|
200
|
-
}
|
|
195
|
+
};
|
|
201
196
|
case "workflow_batch_spawned": {
|
|
202
197
|
// Batch metadata persisted for resume recovery; individual nodes are
|
|
203
198
|
// recorded when they complete (via workflow_node_completed).
|
|
204
199
|
const nodes = obs.nodes ?? [];
|
|
205
|
-
return
|
|
200
|
+
return {
|
|
206
201
|
kind: "workflow_batch_spawned",
|
|
207
202
|
turn: t,
|
|
208
203
|
node_count: nodes.length,
|
|
209
204
|
node_ids: nodes.map((n) => n.agent_id ?? ""),
|
|
210
|
-
}
|
|
205
|
+
};
|
|
211
206
|
}
|
|
212
207
|
case "workflow_completed": {
|
|
213
208
|
const completed = obs.completed ?? [];
|
|
214
209
|
const failed = obs.failed ?? [];
|
|
215
|
-
return
|
|
210
|
+
return {
|
|
216
211
|
kind: "workflow_completed",
|
|
217
212
|
turn: t,
|
|
218
213
|
completed,
|
|
219
214
|
failed,
|
|
220
215
|
total_nodes: completed.length + failed.length,
|
|
221
|
-
}
|
|
216
|
+
};
|
|
222
217
|
}
|
|
223
218
|
default:
|
|
224
219
|
return null;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Message, RenderedContext, TaskUpdate, ToolCall, ToolResult, ToolSchema } from "../types.js";
|
|
1
|
+
import type { EntropySample, Message, RenderedContext, TaskUpdate, ToolCall, ToolResult, ToolSchema } from "../types.js";
|
|
2
2
|
import type { SkillMetadata } from "../skills/loader.js";
|
|
3
3
|
import type { RollbackReason } from "./session-log.js";
|
|
4
4
|
export declare const KERNEL_ABI_VERSION = 1;
|
|
@@ -11,10 +11,19 @@ export interface KernelRuntimeHandle {
|
|
|
11
11
|
drainNewMessages(): Message[];
|
|
12
12
|
preservedRefs(): string[];
|
|
13
13
|
}
|
|
14
|
+
export interface PaceDecision {
|
|
15
|
+
action: "continue" | "sleep" | "stop";
|
|
16
|
+
delayMs?: number;
|
|
17
|
+
reason: string;
|
|
18
|
+
/** Set when the kernel trap coerced the model's proposal (clamped delay / forced stop). */
|
|
19
|
+
coercedFrom?: string;
|
|
20
|
+
}
|
|
14
21
|
export interface KernelLoopResult {
|
|
15
22
|
termination: string;
|
|
16
23
|
turnsUsed: number;
|
|
17
24
|
totalTokensUsed: number;
|
|
25
|
+
/** ③ loop-agent: the kernel-adjudicated after-round decision (absent on non-loop runs). */
|
|
26
|
+
paceDecision?: PaceDecision;
|
|
18
27
|
}
|
|
19
28
|
export type MilestoneVerifierKind = {
|
|
20
29
|
kind: "machine_check";
|
|
@@ -105,6 +114,14 @@ export interface KernelObservation {
|
|
|
105
114
|
/** workflow_completed. */
|
|
106
115
|
completed?: string[];
|
|
107
116
|
failed?: string[];
|
|
117
|
+
score?: number;
|
|
118
|
+
score_version?: number;
|
|
119
|
+
rho?: number;
|
|
120
|
+
repeat_pressure?: number;
|
|
121
|
+
failure_rate?: number;
|
|
122
|
+
rollbacks_in_window?: number;
|
|
123
|
+
window_turns?: number;
|
|
124
|
+
threshold?: number;
|
|
108
125
|
}
|
|
109
126
|
export declare function toolSchemaToKernel(schema: ToolSchema): Record<string, unknown>;
|
|
110
127
|
export declare function skillMetadataToKernel(skill: SkillMetadata): Record<string, unknown>;
|
|
@@ -116,6 +133,8 @@ export declare function capabilitySkill(skill: SkillMetadata): Record<string, un
|
|
|
116
133
|
export declare function capabilityMarker(kind: string, id: string, description: string): Record<string, unknown>;
|
|
117
134
|
export declare function capabilityCommandMount(capability: Record<string, unknown>, mountedBy?: string, mountReason?: string): Record<string, unknown>;
|
|
118
135
|
export declare function capabilityCommandUnmount(capabilityKind: string, id: string): Record<string, unknown>;
|
|
136
|
+
/** Camel-case an `entropy_sample` kernel observation into the SDK's `EntropySample`. */
|
|
137
|
+
export declare function entropySampleFromObservation(obs: KernelObservation): EntropySample;
|
|
119
138
|
export declare function kernelApply(runtime: KernelRuntimeHandle, pending: KernelObservation[], event: Record<string, unknown>): KernelObservation[];
|
|
120
139
|
export declare function kernelAction(runtime: KernelRuntimeHandle, pending: KernelObservation[], event: Record<string, unknown>): KernelRunnerAction;
|
|
121
140
|
/**
|
|
@@ -135,6 +135,19 @@ export function capabilityCommandUnmount(capabilityKind, id) {
|
|
|
135
135
|
function parseStep(raw) {
|
|
136
136
|
return JSON.parse(raw);
|
|
137
137
|
}
|
|
138
|
+
/** Camel-case an `entropy_sample` kernel observation into the SDK's `EntropySample`. */
|
|
139
|
+
export function entropySampleFromObservation(obs) {
|
|
140
|
+
return {
|
|
141
|
+
turn: obs.turn ?? 0,
|
|
142
|
+
score: obs.score ?? 0,
|
|
143
|
+
scoreVersion: obs.score_version ?? 0,
|
|
144
|
+
rho: obs.rho ?? 0,
|
|
145
|
+
repeatPressure: obs.repeat_pressure ?? 0,
|
|
146
|
+
failureRate: obs.failure_rate ?? 0,
|
|
147
|
+
rollbacksInWindow: obs.rollbacks_in_window ?? 0,
|
|
148
|
+
windowTurns: obs.window_turns ?? 0,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
138
151
|
function kernelMessageToSdk(raw) {
|
|
139
152
|
const content = raw.content;
|
|
140
153
|
const message = {
|
|
@@ -240,12 +253,24 @@ function mapKernelAction(raw) {
|
|
|
240
253
|
};
|
|
241
254
|
case "done": {
|
|
242
255
|
const result = raw.result ?? {};
|
|
256
|
+
const pace = result.pace_decision;
|
|
243
257
|
return {
|
|
244
258
|
kind: "done",
|
|
245
259
|
result: {
|
|
246
260
|
termination: String(result.termination ?? "error"),
|
|
247
261
|
turnsUsed: Number(result.turns_used ?? 0),
|
|
248
262
|
totalTokensUsed: Number(result.total_tokens_used ?? 0),
|
|
263
|
+
// ③ loop-agent: the kernel-adjudicated after-round decision (absent on non-loop runs).
|
|
264
|
+
...(pace
|
|
265
|
+
? {
|
|
266
|
+
paceDecision: {
|
|
267
|
+
action: (pace.action ?? "stop"),
|
|
268
|
+
delayMs: pace.delay_ms,
|
|
269
|
+
reason: pace.reason ?? "",
|
|
270
|
+
coercedFrom: pace.coerced_from,
|
|
271
|
+
},
|
|
272
|
+
}
|
|
273
|
+
: {}),
|
|
249
274
|
},
|
|
250
275
|
};
|
|
251
276
|
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ③ Dynamic loop-agent engineering system — the SDK driver.
|
|
3
|
+
*
|
|
4
|
+
* A loop agent is NOT a new execution engine:
|
|
5
|
+
* - a ROUND is exactly one bounded `RuntimeRunner.run()` (compaction, RepeatFuse,
|
|
6
|
+
* criteria gate, and budget verdicts all apply per round for free);
|
|
7
|
+
* - CONTINUITY is the session log replayed under ONE stable sessionId;
|
|
8
|
+
* - LIFETIME GOVERNANCE is the RunGroup the rounds are members of;
|
|
9
|
+
* - the only new decision — what happens AFTER a round — is the model-proposed,
|
|
10
|
+
* kernel-adjudicated `pace` verb (see the kernel pacing trap). The kernel never
|
|
11
|
+
* sleeps; all timers and judge calls live here, in SDK I/O land.
|
|
12
|
+
*
|
|
13
|
+
* Durable pacing: every round appends `round_started` / `round_paced` to the loop's
|
|
14
|
+
* session log, so `LoopDriver.resume()`-style recovery is a fold over the log
|
|
15
|
+
* (the SessionLogGroupBudgetStore pattern) — zero new storage. A stateless host
|
|
16
|
+
* reads `wake_at_ms` from the fold and re-arms via its own cron/queue; an
|
|
17
|
+
* in-process host lets `run()` sleep inline.
|
|
18
|
+
*/
|
|
19
|
+
import type { RuntimeRunner } from "./runner.js";
|
|
20
|
+
import type { SessionEvent } from "./session-log.js";
|
|
21
|
+
import type { PaceDecision } from "./kernel-step.js";
|
|
22
|
+
import type { StreamEvent } from "../types.js";
|
|
23
|
+
export interface LoopSpec {
|
|
24
|
+
/** Stable loop id = the ONE session id every round replays (transcript continuity). */
|
|
25
|
+
loopId: string;
|
|
26
|
+
goal: string;
|
|
27
|
+
criteria?: string[];
|
|
28
|
+
/** Hard round cap; the kernel coerces continue/sleep to stop at the cap. */
|
|
29
|
+
maxRounds?: number;
|
|
30
|
+
/** Sleep clamp bounds (ms), enforced in-kernel. */
|
|
31
|
+
minSleepMs?: number;
|
|
32
|
+
maxSleepMs?: number;
|
|
33
|
+
/** "stop" (goal loop, default) | "sleep" (cron loop) when a round never calls pace. */
|
|
34
|
+
defaultAction?: "stop" | "sleep";
|
|
35
|
+
/** Cross-round done-gate: judges a stop proposal; a failing verdict overrides
|
|
36
|
+
* stop→continue at most `maxVerdictOverrides` times, its feedback becoming the
|
|
37
|
+
* next round's steering note. The in-kernel O4 criteria gate is the per-round rung
|
|
38
|
+
* of the same ladder — this is the cross-round rung. */
|
|
39
|
+
verdictFn?: (ctx: {
|
|
40
|
+
loopId: string;
|
|
41
|
+
round: number;
|
|
42
|
+
reason: string;
|
|
43
|
+
}) => Promise<{
|
|
44
|
+
pass: boolean;
|
|
45
|
+
feedback?: string;
|
|
46
|
+
}> | {
|
|
47
|
+
pass: boolean;
|
|
48
|
+
feedback?: string;
|
|
49
|
+
};
|
|
50
|
+
maxVerdictOverrides?: number;
|
|
51
|
+
/** Sleep implementation (injectable for tests / stateless hosts). Default: setTimeout.
|
|
52
|
+
* Return `false` to hand the wake to an external scheduler and end `run()` dormant. */
|
|
53
|
+
sleeper?: (delayMs: number, wakeAtMs: number) => Promise<boolean>;
|
|
54
|
+
/** Per-round event tap (streaming passthrough). */
|
|
55
|
+
onEvent?: (round: number, event: StreamEvent) => void;
|
|
56
|
+
}
|
|
57
|
+
export interface LoopOutcome {
|
|
58
|
+
loopId: string;
|
|
59
|
+
roundsCompleted: number;
|
|
60
|
+
stopped: boolean;
|
|
61
|
+
/** "stopped" | "dormant" (sleeper handed off to an external scheduler) */
|
|
62
|
+
state: "stopped" | "dormant";
|
|
63
|
+
lastPace?: PaceDecision;
|
|
64
|
+
lastStatus?: string;
|
|
65
|
+
/** Absolute wake time when dormant. */
|
|
66
|
+
wakeAtMs?: number;
|
|
67
|
+
}
|
|
68
|
+
/** Fold the loop's session log into resumable pacing state — zero new storage. DW-5: the judge's
|
|
69
|
+
* override budget folds too, so a crash/restart can't grant the verdictFn fresh overrides. */
|
|
70
|
+
export declare function foldLoopState(events: Array<{
|
|
71
|
+
seq: number;
|
|
72
|
+
event: SessionEvent;
|
|
73
|
+
}>): {
|
|
74
|
+
roundsCompleted: number;
|
|
75
|
+
pendingWakeAtMs?: number;
|
|
76
|
+
lastPace?: {
|
|
77
|
+
action: string;
|
|
78
|
+
reason: string;
|
|
79
|
+
};
|
|
80
|
+
overridesUsed: number;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* DW-6 completion→wake bridge, composed from two existing seams (zero new mechanism): a `sleeper`
|
|
84
|
+
* that races the timer against an L0 recipient-addressed signal on the shared gateway. Ingest a
|
|
85
|
+
* signal with `recipient: loopId` (a subagent/workflow completion, a webhook) and the sleeping loop
|
|
86
|
+
* wakes into its next round immediately — where the SAME queued signal then reaches the model
|
|
87
|
+
* through the kernel's normal signal path, so the wake reason is visible in-round.
|
|
88
|
+
*/
|
|
89
|
+
export declare function signalAwareSleeper(gateway: {
|
|
90
|
+
onSignal(listener: (sig: {
|
|
91
|
+
recipient?: string;
|
|
92
|
+
}) => void): () => void;
|
|
93
|
+
}, loopId: string): NonNullable<LoopSpec["sleeper"]>;
|
|
94
|
+
export declare class LoopDriver {
|
|
95
|
+
private readonly runner;
|
|
96
|
+
private readonly spec;
|
|
97
|
+
private overridesUsed;
|
|
98
|
+
constructor(runner: RuntimeRunner, spec: LoopSpec);
|
|
99
|
+
/**
|
|
100
|
+
* Drive rounds until the loop stops or goes dormant. Resumable by construction:
|
|
101
|
+
* the round count and any pending wake are folded from the session log, so
|
|
102
|
+
* calling `run()` again after a crash / on a stateless host continues in place.
|
|
103
|
+
*/
|
|
104
|
+
run(): Promise<LoopOutcome>;
|
|
105
|
+
private sleep;
|
|
106
|
+
}
|
|
107
|
+
/** Facade: run a self-pacing loop agent (joins runAgent/runFanout as an entry point). */
|
|
108
|
+
export declare function runLoop(runner: RuntimeRunner, spec: LoopSpec): Promise<LoopOutcome>;
|