@deepstrike/sdk 0.2.6 → 0.2.7

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.
Files changed (38) hide show
  1. package/dist/index.d.ts +5 -3
  2. package/dist/index.js +3 -2
  3. package/dist/kernel.d.ts +54 -0
  4. package/dist/kernel.js +8 -0
  5. package/dist/providers/anthropic.d.ts +4 -1
  6. package/dist/providers/anthropic.js +51 -0
  7. package/dist/providers/catalog.js +5 -2
  8. package/dist/providers/deepseek.d.ts +4 -1
  9. package/dist/providers/deepseek.js +76 -8
  10. package/dist/providers/glm.d.ts +2 -1
  11. package/dist/providers/glm.js +7 -0
  12. package/dist/providers/kimi.d.ts +2 -1
  13. package/dist/providers/kimi.js +7 -0
  14. package/dist/providers/minimax.d.ts +28 -2
  15. package/dist/providers/minimax.js +197 -1
  16. package/dist/providers/openai-chat.d.ts +6 -2
  17. package/dist/providers/openai-chat.js +20 -3
  18. package/dist/providers/openai.d.ts +4 -1
  19. package/dist/providers/openai.js +31 -7
  20. package/dist/providers/profiles.d.ts +6 -0
  21. package/dist/providers/profiles.js +6 -0
  22. package/dist/providers/qwen.d.ts +3 -1
  23. package/dist/providers/qwen.js +20 -2
  24. package/dist/providers/replay-validator.d.ts +10 -0
  25. package/dist/providers/replay-validator.js +57 -0
  26. package/dist/runtime/kernel-event-log.js +22 -0
  27. package/dist/runtime/kernel-step.d.ts +13 -0
  28. package/dist/runtime/provider-replay.d.ts +8 -1
  29. package/dist/runtime/provider-replay.js +37 -4
  30. package/dist/runtime/runner.d.ts +22 -1
  31. package/dist/runtime/runner.js +68 -2
  32. package/dist/runtime/session-log.d.ts +22 -0
  33. package/dist/runtime/session-repair.d.ts +26 -3
  34. package/dist/runtime/session-repair.js +33 -32
  35. package/dist/types/agent.d.ts +50 -0
  36. package/dist/types/agent.js +110 -0
  37. package/dist/types.d.ts +23 -0
  38. package/package.json +2 -2
@@ -6,7 +6,7 @@ import type { SessionLog, SessionEvent } from "./session-log.js";
6
6
  import type { ArchiveStore } from "./archive.js";
7
7
  import type { ExecutionPlane } from "./execution-plane.js";
8
8
  import { type MemoryPolicy, type ResourceQuota } from "../kernel.js";
9
- import type { AgentRunSpec, MilestoneCheckResult, MilestoneContract, MilestonePolicy } from "../types/agent.js";
9
+ import type { AgentRunSpec, MilestoneCheckResult, MilestoneContract, MilestonePolicy, WorkflowSpec } from "../types/agent.js";
10
10
  import { type SubAgentOrchestrator } from "./sub-agent-orchestrator.js";
11
11
  import { type GovernancePolicy } from "../governance.js";
12
12
  import { type NativeOsProfile, type OsProfileId } from "./os-profile.js";
@@ -159,6 +159,27 @@ export declare class RuntimeRunner {
159
159
  * Requires an active parent run (`run()` / `wake()` in progress or paused at milestone).
160
160
  */
161
161
  spawnSubAgent(spec: AgentRunSpec): AsyncIterable<StreamEvent>;
162
+ /**
163
+ * W0-ABI: run a declarative workflow DAG. The kernel owns the DAG and gates every node spawn
164
+ * through the syscall trap; this driver runs each kernel-emitted batch of nodes in parallel,
165
+ * feeds their results back, and loops until the kernel reports the workflow complete.
166
+ * Returns the completed / failed node agent-ids.
167
+ */
168
+ runWorkflow(spec: WorkflowSpec, opts?: {
169
+ resumedCompleted?: string[];
170
+ }): Promise<{
171
+ completed: string[];
172
+ failed: string[];
173
+ }>;
174
+ /**
175
+ * Resume a workflow from the parent session's completed nodes.
176
+ * Reads the session log, extracts completed workflow node agent_ids, and
177
+ * calls runWorkflow with resumedCompleted so the kernel skips those nodes.
178
+ */
179
+ resumeWorkflow(spec: WorkflowSpec): Promise<{
180
+ completed: string[];
181
+ failed: string[];
182
+ }>;
162
183
  interrupt(): void;
163
184
  run(req: {
164
185
  sessionId: string;
@@ -3,10 +3,10 @@ import { resolvePermissionRequest } from "./execution-plane.js";
3
3
  import { getKernel } from "../kernel.js";
4
4
  import { peekProviderReplay, seedProviderReplayFromEvents } from "./provider-replay.js";
5
5
  import { sanitizeReplayText } from "./replay-sanitize.js";
6
- import { buildLlmCompletedEvent, buildRunTerminalEvent, repairEventsForRecovery } from "./session-repair.js";
6
+ import { buildLlmCompletedEvent, buildRunTerminalEvent, buildWorkflowNodeCompletedEvent, recoverCompletedWorkflowNodes, repairEventsForRecovery, } from "./session-repair.js";
7
7
  import { KernelPrimitivesDashboard } from "./kernel-primitives-dashboard.js";
8
8
  import { capabilityMarker, capabilitySkill, capabilityTool, capabilityCommandMount, capabilityCommandUnmount, kernelAction, kernelApply, kernelMaybeAction, forceCompact, messageToKernelMessage, skillMetadataToKernel, taskUpdateToKernel, toolResultToKernel, toolSchemaToKernel, } from "./kernel-step.js";
9
- import { agentRunSpecToKernel, findSpawnProcessObservation, milestoneCheckPass, milestoneCheckResultToKernel, spawnObservationToManifest, subAgentResultToKernel, } from "../types/agent.js";
9
+ import { agentRunSpecToKernel, findSpawnProcessObservation, milestoneCheckPass, milestoneCheckResultToKernel, spawnObservationToManifest, subAgentResultToKernel, workflowNodeToManifest, workflowNodeToSpec, workflowSpecToKernel, } from "../types/agent.js";
10
10
  import { defaultSubAgentOrchestrator } from "./sub-agent-orchestrator.js";
11
11
  import { governancePolicyToKernelEvent } from "../governance.js";
12
12
  import { kernelObservationToSessionEvent, withCategory } from "./kernel-event-log.js";
@@ -256,6 +256,72 @@ export class RuntimeRunner {
256
256
  });
257
257
  yield { type: "done", iterations: result.result.turnsUsed, totalTokens: result.result.totalTokensUsed, status: result.result.termination };
258
258
  }
259
+ /**
260
+ * W0-ABI: run a declarative workflow DAG. The kernel owns the DAG and gates every node spawn
261
+ * through the syscall trap; this driver runs each kernel-emitted batch of nodes in parallel,
262
+ * feeds their results back, and loops until the kernel reports the workflow complete.
263
+ * Returns the completed / failed node agent-ids.
264
+ */
265
+ async runWorkflow(spec, opts) {
266
+ if (!this.activeKernel || !this.currentSessionId) {
267
+ throw new Error("runWorkflow requires an active parent run");
268
+ }
269
+ const parentSessionId = this.currentSessionId;
270
+ const runtime = this.activeKernel;
271
+ const orchestrator = this.opts.subAgentOrchestrator ?? defaultSubAgentOrchestrator;
272
+ let observations = kernelApply(runtime, this.pendingObservations, {
273
+ kind: "load_workflow",
274
+ spec: workflowSpecToKernel(spec),
275
+ parent_session_id: parentSessionId,
276
+ // W0-ABI resume: skip nodes already completed before an interruption.
277
+ ...(opts?.resumedCompleted?.length ? { resumed_completed: opts.resumedCompleted } : {}),
278
+ });
279
+ for (;;) {
280
+ const done = observations.find(o => o.kind === "workflow_completed");
281
+ if (done)
282
+ return { completed: done.completed ?? [], failed: done.failed ?? [] };
283
+ const batch = observations.find(o => o.kind === "workflow_batch_spawned");
284
+ const nodes = batch?.nodes ?? [];
285
+ if (nodes.length === 0)
286
+ return { completed: [], failed: [] }; // nothing to run (e.g. all gated)
287
+ // Run the batch's nodes in parallel — each is independent within a round.
288
+ const results = await Promise.all(nodes.map(node => orchestrator.run({
289
+ parentOpts: this.opts,
290
+ parentSessionId,
291
+ spec: workflowNodeToSpec(node, parentSessionId),
292
+ manifest: workflowNodeToManifest(node, parentSessionId),
293
+ sessionLog: this.opts.sessionLog,
294
+ ...(this.opts.subAgentHarness ? { harness: this.opts.subAgentHarness } : {}),
295
+ })));
296
+ // Feed completions back; the draining feed yields the next batch or completion.
297
+ observations = [];
298
+ for (const result of results) {
299
+ observations = kernelApply(runtime, this.pendingObservations, {
300
+ kind: "sub_agent_completed",
301
+ result: subAgentResultToKernel(result),
302
+ });
303
+ // Persist node completion for resume recovery.
304
+ await this.opts.sessionLog.append(parentSessionId, buildWorkflowNodeCompletedEvent({
305
+ turn: runtime.turn(),
306
+ agentId: result.agentId,
307
+ termination: result.result.termination,
308
+ }));
309
+ }
310
+ }
311
+ }
312
+ /**
313
+ * Resume a workflow from the parent session's completed nodes.
314
+ * Reads the session log, extracts completed workflow node agent_ids, and
315
+ * calls runWorkflow with resumedCompleted so the kernel skips those nodes.
316
+ */
317
+ async resumeWorkflow(spec) {
318
+ if (!this.currentSessionId) {
319
+ throw new Error("resumeWorkflow requires an active parent run");
320
+ }
321
+ const events = await this.opts.sessionLog.read(this.currentSessionId);
322
+ const resumedCompleted = recoverCompletedWorkflowNodes(events);
323
+ return this.runWorkflow(spec, { resumedCompleted });
324
+ }
259
325
  interrupt() { this.interrupted = true; }
260
326
  async *run(req) {
261
327
  const prior = req.inheritEvents ?? await this.opts.sessionLog.read(req.sessionId);
@@ -236,6 +236,28 @@ export type SessionEvent = {
236
236
  kind: "memory_retrieval_result";
237
237
  selected_memory_ids: string[];
238
238
  selection_rationale: string;
239
+ } | {
240
+ kind: "workflow_node_completed";
241
+ turn: number;
242
+ category?: KernelEventCategory;
243
+ primitive?: KernelPrimitive;
244
+ agent_id: string;
245
+ termination: string;
246
+ } | {
247
+ kind: "workflow_batch_spawned";
248
+ turn: number;
249
+ category?: KernelEventCategory;
250
+ primitive?: KernelPrimitive;
251
+ node_count: number;
252
+ node_ids: string[];
253
+ } | {
254
+ kind: "workflow_completed";
255
+ turn: number;
256
+ category?: KernelEventCategory;
257
+ primitive?: KernelPrimitive;
258
+ completed: string[];
259
+ failed: string[];
260
+ total_nodes: number;
239
261
  } | {
240
262
  kind: "run_terminal";
241
263
  reason: string;
@@ -1,9 +1,15 @@
1
1
  import type { ProviderReplay, ToolCall } from "../types.js";
2
2
  import type { SessionEvent } from "./session-log.js";
3
3
  export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay-sanitize.js";
4
- /** Minimal native blocks when provider_replay was not persisted. */
5
- export declare function synthesizeProviderReplay(content: string, toolCalls: ToolCall[]): ProviderReplay | undefined;
6
- export declare function effectiveProviderReplay(content: string, toolCalls: ToolCall[], stored?: ProviderReplay): ProviderReplay | undefined;
4
+ /**
5
+ * Normalize a persisted llm_completed event for recovery.
6
+ *
7
+ * Content is sanitized and token_count backfilled, but the stored
8
+ * `provider_replay` envelope is passed through verbatim — this layer is
9
+ * provider-neutral and must never synthesize protocol-specific replay shapes
10
+ * (e.g. Anthropic `native_blocks`). Legacy reconstruction for a given protocol
11
+ * is the responsibility of that provider's `seedProviderReplay`.
12
+ */
7
13
  export declare function normalizeLlmCompleted(event: Extract<SessionEvent, {
8
14
  kind: "llm_completed";
9
15
  }>, maxBytes?: number): Extract<SessionEvent, {
@@ -35,3 +41,20 @@ export declare function buildRunTerminalEvent(input: {
35
41
  }): Extract<SessionEvent, {
36
42
  kind: "run_terminal";
37
43
  }>;
44
+ /** Build workflow_node_completed for persistence after a node finishes. */
45
+ export declare function buildWorkflowNodeCompletedEvent(input: {
46
+ turn: number;
47
+ agentId: string;
48
+ termination: string;
49
+ }): Extract<SessionEvent, {
50
+ kind: "workflow_node_completed";
51
+ }>;
52
+ /**
53
+ * Recover completed workflow node agent_ids from a session event stream.
54
+ * Scans for workflow_node_completed events and returns the agent_ids whose
55
+ * termination was "completed". Used to rebuild resumedCompleted for resumeWorkflow.
56
+ */
57
+ export declare function recoverCompletedWorkflowNodes(events: Array<{
58
+ seq: number;
59
+ event: SessionEvent;
60
+ }>): string[];
@@ -3,41 +3,19 @@ export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay
3
3
  function estimateTokenCount(text) {
4
4
  return Math.max(1, Math.ceil(text.length / 4));
5
5
  }
6
- function parseToolInput(args) {
7
- try {
8
- return JSON.parse(args || "{}");
9
- }
10
- catch {
11
- return {};
12
- }
13
- }
14
- /** Minimal native blocks when provider_replay was not persisted. */
15
- export function synthesizeProviderReplay(content, toolCalls) {
16
- if (!toolCalls.length)
17
- return undefined;
18
- const blocks = [];
19
- if (content)
20
- blocks.push({ type: "text", text: content });
21
- for (const tc of toolCalls) {
22
- blocks.push({
23
- type: "tool_use",
24
- id: tc.id,
25
- name: tc.name,
26
- input: parseToolInput(tc.arguments),
27
- });
28
- }
29
- return { native_blocks: blocks };
30
- }
31
- export function effectiveProviderReplay(content, toolCalls, stored) {
32
- if (stored?.native_blocks?.length || stored?.reasoning_content != null) {
33
- return stored;
34
- }
35
- return synthesizeProviderReplay(content, toolCalls);
36
- }
6
+ /**
7
+ * Normalize a persisted llm_completed event for recovery.
8
+ *
9
+ * Content is sanitized and token_count backfilled, but the stored
10
+ * `provider_replay` envelope is passed through verbatim — this layer is
11
+ * provider-neutral and must never synthesize protocol-specific replay shapes
12
+ * (e.g. Anthropic `native_blocks`). Legacy reconstruction for a given protocol
13
+ * is the responsibility of that provider's `seedProviderReplay`.
14
+ */
37
15
  export function normalizeLlmCompleted(event, maxBytes) {
38
16
  const content = sanitizeReplayText(event.content ?? "", maxBytes);
39
17
  const toolCalls = event.tool_calls ?? [];
40
- const providerReplay = effectiveProviderReplay(content, toolCalls, event.provider_replay);
18
+ const providerReplay = event.provider_replay;
41
19
  return {
42
20
  kind: "llm_completed",
43
21
  turn: event.turn,
@@ -75,3 +53,26 @@ export function buildRunTerminalEvent(input) {
75
53
  total_tokens: Math.max(0, input.totalTokens),
76
54
  };
77
55
  }
56
+ /** Build workflow_node_completed for persistence after a node finishes. */
57
+ export function buildWorkflowNodeCompletedEvent(input) {
58
+ return {
59
+ kind: "workflow_node_completed",
60
+ turn: input.turn,
61
+ agent_id: input.agentId,
62
+ termination: input.termination,
63
+ };
64
+ }
65
+ /**
66
+ * Recover completed workflow node agent_ids from a session event stream.
67
+ * Scans for workflow_node_completed events and returns the agent_ids whose
68
+ * termination was "completed". Used to rebuild resumedCompleted for resumeWorkflow.
69
+ */
70
+ export function recoverCompletedWorkflowNodes(events) {
71
+ const completed = [];
72
+ for (const { event } of events) {
73
+ if (event.kind === "workflow_node_completed" && event.termination === "completed") {
74
+ completed.push(event.agent_id);
75
+ }
76
+ }
77
+ return completed;
78
+ }
@@ -75,3 +75,53 @@ export declare function milestoneCheckResultToKernel(result: MilestoneCheckResul
75
75
  export declare function subAgentResultToKernel(result: SubAgentResult): Record<string, unknown>;
76
76
  export declare function milestoneCheckPass(phaseId: string): MilestoneCheckResult;
77
77
  export declare function milestoneCheckFail(phaseId: string, reason: string): MilestoneCheckResult;
78
+ /** A task for a workflow node: a full object, or a bare goal string. */
79
+ export type WorkflowTaskSpec = {
80
+ goal: string;
81
+ criteria?: string[];
82
+ lane?: string;
83
+ } | string;
84
+ /** W3 trust level for a workflow node. */
85
+ export type NodeTrust = "trusted" | "quarantined";
86
+ /** One node in a declarative workflow DAG (camelCase host shape). */
87
+ export interface WorkflowNodeSpec {
88
+ task: WorkflowTaskSpec;
89
+ role: KernelAgentRole;
90
+ isolation?: AgentIsolation;
91
+ contextInheritance?: ContextInheritance;
92
+ modelHint?: string;
93
+ /** W3: `quarantined` nodes read untrusted content and must run without privileges. */
94
+ trust?: NodeTrust;
95
+ /** Indices of nodes this node depends on. */
96
+ dependsOn?: number[];
97
+ }
98
+ /** A declarative workflow DAG the kernel runs node-by-node, gating each spawn. */
99
+ export interface WorkflowSpec {
100
+ nodes: WorkflowNodeSpec[];
101
+ }
102
+ /** Per-node spawn descriptor carried in the `workflow_batch_spawned` observation. */
103
+ export interface WorkflowSpawnInfo {
104
+ agent_id: string;
105
+ goal: string;
106
+ role: string;
107
+ isolation: string;
108
+ context_inheritance: string;
109
+ model_hint?: string;
110
+ /** W3 trust level: `"trusted"` | `"quarantined"`. */
111
+ trust?: string;
112
+ }
113
+ /** Map a host `WorkflowSpec` to the snake_case kernel JSON (`load_workflow.spec`). */
114
+ export declare function workflowSpecToKernel(spec: WorkflowSpec): Record<string, unknown>;
115
+ /** Build a sub-agent run spec for a kernel-generated workflow node. */
116
+ export declare function workflowNodeToSpec(node: WorkflowSpawnInfo, parentSessionId: string): AgentRunSpec;
117
+ /** Build the host manifest for a kernel-generated workflow node. */
118
+ export declare function workflowNodeToManifest(node: WorkflowSpawnInfo, parentSessionId: string): AgentProcessChangedObservation;
119
+ /** N parallel read-only Explore workers feeding a single Plan synthesizer (barrier). */
120
+ export declare function fanoutSynthesize(workers: WorkflowTaskSpec[], synthesize: WorkflowTaskSpec): WorkflowSpec;
121
+ /** N parallel Implement generators feeding a single Verify filter/dedupe step (barrier). */
122
+ export declare function generateAndFilter(generators: WorkflowTaskSpec[], filter: WorkflowTaskSpec): WorkflowSpec;
123
+ /**
124
+ * One fresh-context verifier per rule/claim (parallel) + optional skeptic that depends on all and
125
+ * re-checks flags. Verifiers run read-only with no inherited author context (bias-resistant).
126
+ */
127
+ export declare function verifyRules(rules: WorkflowTaskSpec[], skeptic?: WorkflowTaskSpec): WorkflowSpec;
@@ -94,3 +94,113 @@ export function milestoneCheckPass(phaseId) {
94
94
  export function milestoneCheckFail(phaseId, reason) {
95
95
  return { phaseId, passed: false, reason };
96
96
  }
97
+ /** Map a host `WorkflowSpec` to the snake_case kernel JSON (`load_workflow.spec`). */
98
+ export function workflowSpecToKernel(spec) {
99
+ return {
100
+ nodes: spec.nodes.map(n => {
101
+ const task = typeof n.task === "string" ? { goal: n.task } : n.task;
102
+ return {
103
+ task: {
104
+ goal: task.goal,
105
+ // `criteria` is required by the kernel's RuntimeTask serde (no default).
106
+ criteria: task.criteria ?? [],
107
+ ...(task.lane ? { lane: task.lane } : {}),
108
+ },
109
+ role: n.role,
110
+ // role/isolation/context_inheritance have no serde default in the kernel — always emit.
111
+ isolation: n.isolation ?? "shared",
112
+ context_inheritance: n.contextInheritance ?? "none",
113
+ ...(n.modelHint ? { model_hint: n.modelHint } : {}),
114
+ ...(n.trust && n.trust !== "trusted" ? { trust: n.trust } : {}),
115
+ ...(n.dependsOn && n.dependsOn.length ? { depends_on: n.dependsOn } : {}),
116
+ };
117
+ }),
118
+ };
119
+ }
120
+ /** Build a sub-agent run spec for a kernel-generated workflow node. */
121
+ export function workflowNodeToSpec(node, parentSessionId) {
122
+ return {
123
+ identity: {
124
+ agentId: node.agent_id,
125
+ sessionId: `${parentSessionId}-${node.agent_id}`,
126
+ isSubAgent: true,
127
+ parentSessionId,
128
+ },
129
+ role: node.role,
130
+ isolation: node.isolation,
131
+ goal: node.goal,
132
+ };
133
+ }
134
+ /** Build the host manifest for a kernel-generated workflow node. */
135
+ export function workflowNodeToManifest(node, parentSessionId) {
136
+ return {
137
+ kind: "agent_process_changed",
138
+ agent_id: node.agent_id,
139
+ parent_session_id: parentSessionId,
140
+ role: node.role,
141
+ isolation: node.isolation,
142
+ context_inheritance: node.context_inheritance,
143
+ };
144
+ }
145
+ // ─── W1/W2 workflow templates (the six patterns as one-liners) ───
146
+ // Roles carry the kernel's role_defaults isolation/inheritance so host-built specs match the
147
+ // core `orchestration::workflow` constructors (e.g. verifiers stay bias-resistant).
148
+ function asTask(t) {
149
+ return typeof t === "string" ? { goal: t } : t;
150
+ }
151
+ /** N parallel read-only Explore workers feeding a single Plan synthesizer (barrier). */
152
+ export function fanoutSynthesize(workers, synthesize) {
153
+ const nodes = workers.map(t => ({
154
+ task: asTask(t),
155
+ role: "explore",
156
+ isolation: "read_only",
157
+ contextInheritance: "system_only",
158
+ }));
159
+ nodes.push({
160
+ task: asTask(synthesize),
161
+ role: "plan",
162
+ isolation: "shared",
163
+ contextInheritance: "full",
164
+ dependsOn: workers.map((_, i) => i),
165
+ });
166
+ return { nodes };
167
+ }
168
+ /** N parallel Implement generators feeding a single Verify filter/dedupe step (barrier). */
169
+ export function generateAndFilter(generators, filter) {
170
+ const nodes = generators.map(t => ({
171
+ task: asTask(t),
172
+ role: "implement",
173
+ isolation: "worktree",
174
+ contextInheritance: "full",
175
+ }));
176
+ nodes.push({
177
+ task: asTask(filter),
178
+ role: "verify",
179
+ isolation: "read_only",
180
+ contextInheritance: "none",
181
+ dependsOn: generators.map((_, i) => i),
182
+ });
183
+ return { nodes };
184
+ }
185
+ /**
186
+ * One fresh-context verifier per rule/claim (parallel) + optional skeptic that depends on all and
187
+ * re-checks flags. Verifiers run read-only with no inherited author context (bias-resistant).
188
+ */
189
+ export function verifyRules(rules, skeptic) {
190
+ const nodes = rules.map(t => ({
191
+ task: asTask(t),
192
+ role: "verify",
193
+ isolation: "read_only",
194
+ contextInheritance: "none",
195
+ }));
196
+ if (skeptic !== undefined) {
197
+ nodes.push({
198
+ task: asTask(skeptic),
199
+ role: "verify",
200
+ isolation: "read_only",
201
+ contextInheritance: "none",
202
+ dependsOn: rules.map((_, i) => i),
203
+ });
204
+ }
205
+ return { nodes };
206
+ }
package/dist/types.d.ts CHANGED
@@ -184,12 +184,34 @@ export interface RetryConfig {
184
184
  * Responses `previous_response_id` without leaking those semantics into the kernel.
185
185
  */
186
186
  export type ProviderRunState = Record<string, unknown>;
187
+ export type ProviderProtocol = "anthropic-messages" | "openai-chat" | "openai-responses" | "gemini";
188
+ export interface ProviderDescriptor {
189
+ provider: string;
190
+ protocol: ProviderProtocol;
191
+ model: string;
192
+ reasoning: {
193
+ supported: boolean;
194
+ preserveAcrossToolTurns: boolean;
195
+ requiresReplayForToolTurns?: boolean;
196
+ };
197
+ toolCalls: {
198
+ supported: boolean;
199
+ requiresStrictPairing: boolean;
200
+ };
201
+ }
187
202
  /** Provider-native fields required to replay a turn across requests (thinking blocks, reasoning_content, etc.). */
188
203
  export interface ProviderReplay {
204
+ schema_version?: 1 | 2;
205
+ provider?: string;
206
+ protocol?: ProviderProtocol;
207
+ model?: string;
189
208
  /** Anthropic-style assistant content blocks (thinking, text, tool_use). */
190
209
  native_blocks?: Array<Record<string, unknown>>;
191
210
  /** OpenAI-compatible reasoning field (DeepSeek, etc.). */
192
211
  reasoning_content?: string;
212
+ reasoning_details?: unknown;
213
+ native_message?: unknown;
214
+ tool_calls?: unknown[];
193
215
  }
194
216
  /** Structured render output produced by the kernel for each LLM call. */
195
217
  export interface RenderedContext {
@@ -214,6 +236,7 @@ export interface RuntimePolicy {
214
236
  }
215
237
  export interface LLMProvider {
216
238
  createRunState?(): ProviderRunState;
239
+ descriptor?(): ProviderDescriptor;
217
240
  /**
218
241
  * Optional: return the recommended runtime policy for this provider's model.
219
242
  * RuntimeRunner uses this as a fallback when the caller has not specified
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepstrike/sdk",
3
- "version": "0.2.6",
3
+ "version": "0.2.7",
4
4
  "description": "DeepStrike Node.js SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -20,7 +20,7 @@
20
20
  },
21
21
  "dependencies": {
22
22
  "@anthropic-ai/sdk": "^0.99.0",
23
- "@deepstrike/core": "0.2.6",
23
+ "@deepstrike/core": "0.2.7",
24
24
  "@google/generative-ai": "^0.24.1",
25
25
  "openai": "^5.23.2"
26
26
  },