@deepstrike/sdk 0.2.52 → 0.2.61

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 (151) hide show
  1. package/README.md +28 -28
  2. package/dist/agent-ir.d.ts +103 -0
  3. package/dist/agent-ir.js +134 -0
  4. package/dist/agent.d.ts +67 -0
  5. package/dist/agent.js +36 -0
  6. package/dist/collaboration/harness.js +1 -1
  7. package/dist/collaboration/modes/creator-verifier.d.ts +2 -7
  8. package/dist/collaboration/modes/creator-verifier.js +4 -6
  9. package/dist/collaboration/pool.d.ts +8 -20
  10. package/dist/collaboration/pool.js +27 -97
  11. package/dist/compat/anthropic/mcp.d.ts +15 -0
  12. package/dist/compat/anthropic/mcp.js +10 -0
  13. package/dist/compat/openai/agent.d.ts +34 -0
  14. package/dist/compat/openai/agent.js +24 -0
  15. package/dist/governance.d.ts +1 -17
  16. package/dist/governance.js +1 -34
  17. package/dist/guardrail.d.ts +6 -0
  18. package/dist/guardrail.js +1 -0
  19. package/dist/handoff-target.d.ts +12 -0
  20. package/dist/handoff-target.js +1 -0
  21. package/dist/harness/manifest.js +0 -4
  22. package/dist/index.d.ts +19 -7
  23. package/dist/index.js +8 -5
  24. package/dist/kernel.d.ts +2 -20
  25. package/dist/knowledge/public.d.ts +29 -0
  26. package/dist/knowledge/public.js +1 -0
  27. package/dist/mcp-server.d.ts +28 -0
  28. package/dist/mcp-server.js +1 -0
  29. package/dist/memory/agent.d.ts +2 -2
  30. package/dist/memory/agent.js +2 -2
  31. package/dist/memory/durable.d.ts +16 -0
  32. package/dist/memory/durable.js +46 -0
  33. package/dist/memory/in-memory-store.d.ts +9 -7
  34. package/dist/memory/in-memory-store.js +8 -2
  35. package/dist/memory/protocols.d.ts +22 -4
  36. package/dist/memory/public.d.ts +4 -3
  37. package/dist/memory/public.js +3 -2
  38. package/dist/os/public.d.ts +1 -1
  39. package/dist/os/public.js +1 -1
  40. package/dist/providers/anthropic-adapter.d.ts +59 -0
  41. package/dist/providers/anthropic-adapter.js +530 -0
  42. package/dist/providers/anthropic-compatible.d.ts +2 -3
  43. package/dist/providers/anthropic-compatible.js +8 -5
  44. package/dist/providers/anthropic.d.ts +20 -23
  45. package/dist/providers/anthropic.js +176 -395
  46. package/dist/providers/base.d.ts +2 -2
  47. package/dist/providers/base.js +50 -8
  48. package/dist/providers/capability-router.d.ts +29 -0
  49. package/dist/providers/capability-router.js +43 -0
  50. package/dist/providers/catalog.d.ts +16 -4
  51. package/dist/providers/catalog.js +112 -36
  52. package/dist/providers/content-normalization.d.ts +57 -0
  53. package/dist/providers/content-normalization.js +238 -0
  54. package/dist/providers/content-policy.d.ts +16 -0
  55. package/dist/providers/content-policy.js +39 -0
  56. package/dist/providers/credentials.d.ts +83 -0
  57. package/dist/providers/credentials.js +190 -0
  58. package/dist/providers/endpoints.d.ts +137 -0
  59. package/dist/providers/endpoints.js +128 -0
  60. package/dist/providers/factories.js +25 -9
  61. package/dist/providers/gemini-adapter.d.ts +33 -0
  62. package/dist/providers/gemini-adapter.js +264 -0
  63. package/dist/providers/gemini.d.ts +16 -3
  64. package/dist/providers/gemini.js +97 -195
  65. package/dist/providers/model-catalog.d.ts +37 -0
  66. package/dist/providers/model-catalog.js +62 -0
  67. package/dist/providers/model-registry.d.ts +119 -0
  68. package/dist/providers/model-registry.js +379 -0
  69. package/dist/providers/ollama-adapter.d.ts +65 -0
  70. package/dist/providers/ollama-adapter.js +188 -0
  71. package/dist/providers/ollama.d.ts +9 -4
  72. package/dist/providers/ollama.js +96 -109
  73. package/dist/providers/openai-chat-dialects.d.ts +154 -0
  74. package/dist/providers/openai-chat-dialects.js +179 -0
  75. package/dist/providers/openai-chat.d.ts +46 -18
  76. package/dist/providers/openai-chat.js +416 -51
  77. package/dist/providers/openai-responses-adapter.d.ts +42 -0
  78. package/dist/providers/openai-responses-adapter.js +343 -0
  79. package/dist/providers/openai-responses.d.ts +19 -33
  80. package/dist/providers/openai-responses.js +164 -264
  81. package/dist/providers/openai.d.ts +29 -76
  82. package/dist/providers/openai.js +195 -292
  83. package/dist/providers/protocol-adapter.d.ts +39 -0
  84. package/dist/providers/protocol-adapter.js +13 -0
  85. package/dist/providers/protocol-capabilities.d.ts +34 -0
  86. package/dist/providers/protocol-capabilities.js +44 -0
  87. package/dist/providers/provider-error.d.ts +31 -0
  88. package/dist/providers/provider-error.js +153 -0
  89. package/dist/providers/public.d.ts +26 -3
  90. package/dist/providers/public.js +13 -1
  91. package/dist/providers/registry.d.ts +7 -6
  92. package/dist/providers/registry.js +47 -20
  93. package/dist/providers/request-plan.d.ts +89 -0
  94. package/dist/providers/request-plan.js +199 -0
  95. package/dist/providers/usage-normalizer.d.ts +48 -0
  96. package/dist/providers/usage-normalizer.js +139 -0
  97. package/dist/providers/vendor-profiles.d.ts +2 -15
  98. package/dist/providers/vendor-profiles.js +14 -60
  99. package/dist/runtime/canonical-kernel-step.d.ts +1 -2
  100. package/dist/runtime/canonical-kernel-step.js +47 -12
  101. package/dist/runtime/context-policy.d.ts +10 -12
  102. package/dist/runtime/context-policy.js +6 -8
  103. package/dist/runtime/durable-content.d.ts +50 -0
  104. package/dist/runtime/durable-content.js +159 -0
  105. package/dist/runtime/execution-plane.d.ts +2 -2
  106. package/dist/runtime/execution-plane.js +2 -2
  107. package/dist/runtime/kernel-event-log.js +0 -1
  108. package/dist/runtime/kernel-step.d.ts +0 -1
  109. package/dist/runtime/kernel-step.js +4 -2
  110. package/dist/runtime/mcp-proxy-plane.d.ts +25 -1
  111. package/dist/runtime/mcp-proxy-plane.js +44 -6
  112. package/dist/runtime/output-schema.d.ts +1 -2
  113. package/dist/runtime/provider-replay.d.ts +5 -1
  114. package/dist/runtime/provider-replay.js +26 -27
  115. package/dist/runtime/reactive-session.d.ts +1 -1
  116. package/dist/runtime/reactive-session.js +2 -3
  117. package/dist/runtime/run-group.d.ts +1 -1
  118. package/dist/runtime/runner.d.ts +31 -45
  119. package/dist/runtime/runner.js +178 -63
  120. package/dist/runtime/session-log.d.ts +8 -1
  121. package/dist/runtime/session-log.js +42 -2
  122. package/dist/runtime/session-repair.d.ts +1 -1
  123. package/dist/runtime/session-repair.js +1 -1
  124. package/dist/runtime/sub-agent-orchestrator.d.ts +1 -1
  125. package/dist/runtime/sub-agent-orchestrator.js +8 -11
  126. package/dist/runtime/workflow-control-flow.d.ts +0 -4
  127. package/dist/runtime/workflow-control-flow.js +0 -16
  128. package/dist/session.d.ts +11 -0
  129. package/dist/session.js +1 -0
  130. package/dist/skill.d.ts +17 -0
  131. package/dist/skill.js +16 -0
  132. package/dist/skills/loader.d.ts +3 -0
  133. package/dist/tools/errors.d.ts +1 -3
  134. package/dist/tools/errors.js +1 -3
  135. package/dist/tools/index.d.ts +3 -0
  136. package/dist/types/agent.d.ts +21 -9
  137. package/dist/types/agent.js +30 -4
  138. package/dist/types.d.ts +135 -17
  139. package/package.json +4 -4
  140. package/dist/providers/deepseek.d.ts +0 -46
  141. package/dist/providers/deepseek.js +0 -97
  142. package/dist/providers/glm.d.ts +0 -25
  143. package/dist/providers/glm.js +0 -48
  144. package/dist/providers/kimi.d.ts +0 -23
  145. package/dist/providers/kimi.js +0 -30
  146. package/dist/providers/minimax.d.ts +0 -49
  147. package/dist/providers/minimax.js +0 -98
  148. package/dist/providers/profiles.d.ts +0 -1992
  149. package/dist/providers/profiles.js +0 -796
  150. package/dist/providers/qwen.d.ts +0 -38
  151. package/dist/providers/qwen.js +0 -97
@@ -8,7 +8,7 @@ export { REPLAY_CONTENT_MAX_BYTES as RECOVERY_CONTENT_MAX_BYTES } from "./replay
8
8
  * Content is sanitized and token_count backfilled, but the stored
9
9
  * `provider_replay` envelope is passed through verbatim — this layer is
10
10
  * provider-neutral and must never synthesize protocol-specific replay shapes
11
- * (e.g. Anthropic `native_blocks`). Legacy reconstruction for a given protocol
11
+ * (e.g. Anthropic `native_blocks`). Canonical replay seeding for a given protocol
12
12
  * is the responsibility of that provider's `seedProviderReplay`.
13
13
  */
14
14
  export declare function normalizeLlmCompleted(event: Extract<SessionEvent, {
@@ -9,7 +9,7 @@ function estimateTokenCount(text) {
9
9
  * Content is sanitized and token_count backfilled, but the stored
10
10
  * `provider_replay` envelope is passed through verbatim — this layer is
11
11
  * provider-neutral and must never synthesize protocol-specific replay shapes
12
- * (e.g. Anthropic `native_blocks`). Legacy reconstruction for a given protocol
12
+ * (e.g. Anthropic `native_blocks`). Canonical replay seeding for a given protocol
13
13
  * is the responsibility of that provider's `seedProviderReplay`.
14
14
  */
15
15
  export function normalizeLlmCompleted(event, maxBytes) {
@@ -13,7 +13,7 @@ export interface SubAgentRunContext {
13
13
  evalProvider: import("../types.js").LLMProvider;
14
14
  maxAttempts?: number;
15
15
  };
16
- /** M5 v2.1: set when this child is a workflow node (spawned by the workflow driver). Propagated to
16
+ /** workflow-node: set when this child is a workflow node (spawned by the workflow driver). Propagated to
17
17
  * the child runner so a nested `start_workflow` FLATTENS to the parent kernel rather than
18
18
  * auto-pivoting into its own bootstrap (which would fragment the one-kernel/one-quota governance). */
19
19
  isWorkflowNode?: boolean;
@@ -53,7 +53,7 @@ function deriveMetaTools(permitted, opts) {
53
53
  const metaTools = new Set();
54
54
  if (permitted.has("skill") && opts.skillDir)
55
55
  metaTools.add("skill");
56
- if (permitted.has("memory") && opts.dreamStore)
56
+ if (permitted.has("memory") && opts.memoryStore)
57
57
  metaTools.add("memory");
58
58
  if (permitted.has("knowledge") && opts.knowledgeSource)
59
59
  metaTools.add("knowledge");
@@ -67,7 +67,7 @@ function availableMetaTools(opts) {
67
67
  const metaTools = new Set();
68
68
  if (opts.skillDir)
69
69
  metaTools.add("skill");
70
- if (opts.dreamStore)
70
+ if (opts.memoryStore)
71
71
  metaTools.add("memory");
72
72
  if (opts.knowledgeSource)
73
73
  metaTools.add("knowledge");
@@ -129,20 +129,16 @@ export class SubAgentOrchestrator {
129
129
  systemPrompt,
130
130
  sessionLog: ctx.sessionLog,
131
131
  skillDir: metaTools.has("skill") ? ctx.parentOpts.skillDir : undefined,
132
- dreamStore: metaTools.has("memory") ? ctx.parentOpts.dreamStore : undefined,
132
+ memoryStore: metaTools.has("memory") ? ctx.parentOpts.memoryStore : undefined,
133
133
  knowledgeSource: metaTools.has("knowledge") ? ctx.parentOpts.knowledgeSource : undefined,
134
134
  enablePlanTool: metaTools.has("update_plan") ? ctx.parentOpts.enablePlanTool : undefined,
135
135
  // Nested vehicle: the child joins the inherited runGroup for lineage/settlement only — it
136
136
  // must NOT re-reserve budget axes the parent already holds (that double-reserve squeezed the
137
137
  // child's grant to 0 and the kernel stripped its first-turn tools).
138
138
  nestedGroupVehicle: true,
139
- // The child runs under ITS OWN spec, never the parent's: the spread above would otherwise
140
- // leak the parent's `runSpec` (identity, capability filter and a LoopDriver's armed
141
- // `loopRound`, giving every child a phantom pace tool). A loop-node iteration carries its
142
- // own minimal spec to arm the pacing trap (DW-3); everything else runs spec-less as before.
143
- runSpec: ctx.spec.loopRound
144
- ? { identity: ctx.spec.identity, role: ctx.spec.role, goal: ctx.spec.goal, loopRound: ctx.spec.loopRound }
145
- : undefined,
139
+ // The child always runs under its own canonical spec, never the parent's. This preserves its
140
+ // capability ceiling, exposure baseline, identity, and optional loop pacing in one shape.
141
+ runSpec: ctx.spec,
146
142
  });
147
143
  // #2-B-ii: when the parent preempts this node (kernel `AgentPreempted`), interrupt the child —
148
144
  // cancelling its in-flight LLM call. Handle an already-aborted signal too (creation race).
@@ -258,7 +254,7 @@ export function attemptOutcomeToLoopResult(outcome) {
258
254
  /** Canonical single-node root workflow for harness / coordinator use. */
259
255
  export async function spawnStandalone(parentOpts, parentSessionId, spec, orchestrator = defaultSubAgentOrchestrator, contextInput) {
260
256
  if (spec.tokenBudget !== undefined || spec.maxTurns !== undefined || spec.maxWallMs !== undefined) {
261
- throw new Error("spawnStandalone cannot represent per-node resource caps under canonical ABI v3");
257
+ throw new Error("spawnStandalone cannot represent per-node resource caps under the canonical ABI");
262
258
  }
263
259
  const { RuntimeRunner } = await import("./runner.js");
264
260
  let captured;
@@ -272,6 +268,7 @@ export async function spawnStandalone(parentOpts, parentSessionId, spec, orchest
272
268
  ...ctx.manifest,
273
269
  agent_id: spec.identity.agentId,
274
270
  parent_session_id: parentSessionId,
271
+ permitted_capability_ids: spec.capabilityFilter?.allowedIds ?? [],
275
272
  },
276
273
  ...(contextInput ? { contextInput } : {}),
277
274
  });
@@ -12,10 +12,6 @@ export declare function dependencyOutputsNote(inputAgentIds: string[] | undefine
12
12
  export declare function classifyInstruction(labels: string[]): string;
13
13
  /** Build a tournament judge's goal: the controller's criterion + the two candidates to compare. */
14
14
  export declare function judgeGoal(criterion: string, leftOutput: string, rightOutput: string): string;
15
- /** Extract a loop stop signal from a loop iteration's output. Returns the `loopContinue` value, or
16
- * `undefined` when the agent gave no clear signal (⇒ the kernel runs the loop to `max_iters`).
17
- * Accepts `{loop_continue: bool}` or, leniently, `{done: bool}` (continue = !done). */
18
- export declare function extractLoopContinue(text: string): boolean | undefined;
19
15
  /** Extract the chosen branch label from a classifier's output. Prefers `{branch: "..."}`; falls back
20
16
  * to a bare label string that exactly matches one of the valid labels. Returns `undefined` when no
21
17
  * recognizable choice was made (the kernel then prunes every branch — a safe "none matched"). */
@@ -45,22 +45,6 @@ export function judgeGoal(criterion, leftOutput, rightOutput) {
45
45
  `criterion above.\n\n[CANDIDATE left]\n${leftOutput}\n\n[CANDIDATE right]\n${rightOutput}\n\n` +
46
46
  `Respond with ONLY a JSON object: {"winner": "left"} or {"winner": "right"}.`);
47
47
  }
48
- /** Extract a loop stop signal from a loop iteration's output. Returns the `loopContinue` value, or
49
- * `undefined` when the agent gave no clear signal (⇒ the kernel runs the loop to `max_iters`).
50
- * Accepts `{loop_continue: bool}` or, leniently, `{done: bool}` (continue = !done). */
51
- export function extractLoopContinue(text) {
52
- const v = extractJsonValue(text);
53
- if (v && typeof v === "object" && !Array.isArray(v)) {
54
- const o = v;
55
- if (typeof o.loop_continue === "boolean")
56
- return o.loop_continue;
57
- if (typeof o.loopContinue === "boolean")
58
- return o.loopContinue;
59
- if (typeof o.done === "boolean")
60
- return !o.done;
61
- }
62
- return undefined;
63
- }
64
48
  /** Extract the chosen branch label from a classifier's output. Prefers `{branch: "..."}`; falls back
65
49
  * to a bare label string that exactly matches one of the valid labels. Returns `undefined` when no
66
50
  * recognizable choice was made (the kernel then prunes every branch — a safe "none matched"). */
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Public user-session descriptor. This is distinct from persisted `SessionData` and the runtime
3
+ * `SessionLog`: it carries caller-visible continuity metadata, not messages or journal events.
4
+ */
5
+ export interface Session {
6
+ id: string;
7
+ userId?: string;
8
+ state?: Record<string, unknown>;
9
+ metadata?: Record<string, unknown>;
10
+ providerOptions?: Record<string, unknown>;
11
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ /** spc_001 §2.4: public Skill contract, built directly on `SKILL.md`-style frontmatter files. */
2
+ export interface Skill {
3
+ name: string;
4
+ description?: string;
5
+ instructions?: string;
6
+ resources?: unknown[];
7
+ scripts?: unknown[];
8
+ tools?: unknown[];
9
+ mcpServers?: unknown[];
10
+ knowledge?: unknown[];
11
+ metadata?: Record<string, unknown>;
12
+ providerOptions?: Record<string, unknown>;
13
+ }
14
+ /** Loads one skill by name from a skill directory, reusing the existing frontmatter scanner and
15
+ * body reader — does not reimplement directory scanning. Returns `null` if the skill file is
16
+ * absent (mirrors `readSkillFile`'s own not-found signal). */
17
+ export declare function loadSkill(skillDir: string, name: string): Promise<Skill | null>;
package/dist/skill.js ADDED
@@ -0,0 +1,16 @@
1
+ import { readSkillFile, scanSkillDir } from "./skills/loader.js";
2
+ /** Loads one skill by name from a skill directory, reusing the existing frontmatter scanner and
3
+ * body reader — does not reimplement directory scanning. Returns `null` if the skill file is
4
+ * absent (mirrors `readSkillFile`'s own not-found signal). */
5
+ export async function loadSkill(skillDir, name) {
6
+ const body = await readSkillFile(skillDir, name);
7
+ if (body === null)
8
+ return null;
9
+ const metas = await scanSkillDir(skillDir);
10
+ const meta = metas.find(m => m.name === name);
11
+ return {
12
+ name: meta?.name ?? name,
13
+ description: meta?.description,
14
+ instructions: body,
15
+ };
16
+ }
@@ -4,6 +4,9 @@ export interface SkillMetadata {
4
4
  whenToUse?: string;
5
5
  effort?: number;
6
6
  estimatedTokens?: number;
7
+ /** Optional structured grants supplied by the SDK caller. They are not parsed from simple
8
+ * SKILL.md frontmatter: the canonical kernel validates their attenuation at activation. */
9
+ capabilityGrants?: Array<Record<string, unknown>>;
7
10
  /** P1-B tool gating: tool ids this skill needs. When the skill is active, the kernel narrows the
8
11
  * exposed toolset to `stable-core ∪ allowedTools`. Parsed from `allowed_tools:` frontmatter
9
12
  * (comma-separated or `[a, b]`). Absent ⇒ the skill does not narrow (back-compat). */
@@ -52,8 +52,6 @@ export declare function formatToolError(err: unknown): string;
52
52
  * - body throws any other `Error` → `{success:false, code: error.code ?? "internal", error: error.message}`
53
53
  * - body throws a non-Error → `{success:false, code:"internal", error: formatToolError(...)}`
54
54
  *
55
- * The classic `tool()` factory is unchanged. `safeTool` is opt-in: import and switch one tool at
56
- * a time. Designed for the consumer-side pattern users had to hand-roll to escape the legacy
57
- * `String(err)` foot-gun.
55
+ * `safeTool` is opt-in and returns a structured error envelope instead of `String(err)`.
58
56
  */
59
57
  export declare function safeTool<T = unknown>(name: string, description: string, parameters: Record<string, unknown>, fn: (args: Record<string, unknown>, ctx?: ToolExecContext) => Promise<ToolEnvelope<T> | T> | ToolEnvelope<T> | T): RegisteredTool;
@@ -84,9 +84,7 @@ export function formatToolError(err) {
84
84
  * - body throws any other `Error` → `{success:false, code: error.code ?? "internal", error: error.message}`
85
85
  * - body throws a non-Error → `{success:false, code:"internal", error: formatToolError(...)}`
86
86
  *
87
- * The classic `tool()` factory is unchanged. `safeTool` is opt-in: import and switch one tool at
88
- * a time. Designed for the consumer-side pattern users had to hand-roll to escape the legacy
89
- * `String(err)` foot-gun.
87
+ * `safeTool` is opt-in and returns a structured error envelope instead of `String(err)`.
90
88
  */
91
89
  export function safeTool(name, description, parameters, fn) {
92
90
  const wrapped = async (args, ctx) => {
@@ -17,6 +17,9 @@ export interface ToolExecContext {
17
17
  export interface RegisteredTool {
18
18
  schema: ToolSchema;
19
19
  execute(args: Record<string, unknown>, ctx?: ToolExecContext): Promise<string> | AsyncIterable<ToolChunk>;
20
+ /** spc_001: vendor-specific extension bag, keyed by provider name. Preserved through
21
+ * normalization/lowering, never flattened into portable fields. */
22
+ providerOptions?: Record<string, unknown>;
20
23
  }
21
24
  export declare function tool(name: string, description: string, parameters: Record<string, unknown>, fn: (args: Record<string, unknown>, ctx?: ToolExecContext) => Promise<string> | string): RegisteredTool;
22
25
  export declare function streamingTool(name: string, description: string, parameters: Record<string, unknown>, fn: (args: Record<string, unknown>, ctx?: ToolExecContext) => AsyncIterable<ToolChunk>): RegisteredTool;
@@ -46,8 +46,7 @@ export interface AgentRunSpec {
46
46
  * advertised before any skill activates, so `exposed = meta ∪ ((baseline ∪ stableCore ∪
47
47
  * ⋃ activeSkills.allowed_tools) ∩ ceiling)`. That makes narrow→wide progressive disclosure
48
48
  * expressible: a tool can be reachable after `skill(x)` without being advertised beforehand.
49
- * Absent legacy behavior (ceiling + errs-open skill narrowing). `[]` is meaningful and
50
- * distinct from absent: the minimal surface (meta-tools + stable-core only). Entries outside
49
+ * Absent and `[]` both mean the minimal surface (meta-tools + stable-core only). Entries outside
51
50
  * the ceiling silently intersect away. Lowered from `RuntimeOptions.baselineToolIds`. */
52
51
  exposureBaseline?: string[];
53
52
  /** M1/G3: per-agent model preference (e.g. "opus"/"sonnet"/"haiku"); the host resolves it to a
@@ -68,6 +67,9 @@ export interface AgentRunSpec {
68
67
  * parent's meta-tool availability (same mechanism trusted workflow nodes use) — the child's surface
69
68
  * is a subset of the parent's, never a privilege escalation. */
70
69
  toolAccess?: "inherit" | "filtered";
70
+ /** spc_001: vendor-specific extension bag, keyed by provider name (e.g. `{ openai: {...} }`).
71
+ * Preserved through normalization/lowering, never flattened into portable fields. */
72
+ providerOptions?: Record<string, unknown>;
71
73
  }
72
74
  /** Kernel process-table observation (Phase 3 canonical spawn signal). */
73
75
  export interface AgentProcessChangedObservation {
@@ -87,7 +89,7 @@ export interface LoopResult {
87
89
  finalMessage?: Message;
88
90
  turnsUsed: number;
89
91
  totalTokensUsed: number;
90
- /** A#2 v2 loop stop signal: a loop iteration sets `false` to end the loop before `max_iters`.
92
+ /** loop-control loop stop signal: a loop iteration sets `false` to end the loop before `max_iters`.
91
93
  * `undefined` (every non-loop result) ⇒ no opinion → run to the cap. Sent only when set. */
92
94
  loopContinue?: boolean;
93
95
  /** A#2 classify routing: a classifier node reports the chosen branch label here; the kernel runs
@@ -96,8 +98,8 @@ export interface LoopResult {
96
98
  /** A#2 tournament verdict: a judge reports the winning entrant's agent id here. Sent only when set. */
97
99
  tournamentWinner?: string;
98
100
  /** ③ loop-agent pacing: the kernel-adjudicated after-round decision, surfaced by the orchestrator
99
- * from the child's done event. For a loop-node iteration this is the PRIMARY continuation
100
- * vocabulary (stop → loopContinue=false); the legacy text-sniffed signal is the fallback.
101
+ * from the child's done event. For a loop-node iteration this is the only continuation
102
+ * vocabulary (stop → loopContinue=false).
101
103
  * SDK-internal — stripped by `subAgentResultToKernel`. */
102
104
  paceDecision?: import("../runtime/kernel-step.js").PaceDecision;
103
105
  /** Two-axis AttemptLoop result. Serialized alongside `termination` so hosts can observe judge
@@ -162,6 +164,14 @@ export type WorkflowTaskSpec = {
162
164
  export type NodeTrust = "trusted" | "quarantined";
163
165
  export type WorkflowDependencyPolicy = "all_success" | "accept_partial" | "all_terminal" | "optional";
164
166
  export type WorkflowNodeStatus = "completed" | "completed_partial" | "failed" | "skipped_upstream_failed";
167
+ /** Host-observed, deterministic scheduling inputs for one workflow node. They never originate
168
+ * from model-authored workflow tools. */
169
+ export interface SchedulingFactors {
170
+ deadlineUrgency?: number;
171
+ processPriority?: number;
172
+ resourcePressure?: number;
173
+ budgetPressure?: number;
174
+ }
165
175
  export declare function workflowNodeStatusFromTermination(termination: TerminationReason | string): WorkflowNodeStatus;
166
176
  /** One node in a declarative workflow DAG (camelCase host shape). */
167
177
  export interface WorkflowNodeSpec {
@@ -178,7 +188,7 @@ export interface WorkflowNodeSpec {
178
188
  /** G2: make this a deterministic *reduce* node — it runs no LLM agent. The runner routes it to the
179
189
  * registered reducer of this name, over its `dependsOn` nodes' outputs (dedupe / filter / merge). */
180
190
  reducer?: string;
181
- /** A#2 v2: make this a *loop* node — re-run its agent up to `maxIters` times. An iteration may end
191
+ /** loop-control: make this a *loop* node — re-run its agent up to `maxIters` times. An iteration may end
182
192
  * the loop early by reporting `loopContinue: false` (the runner solicits this from the agent). */
183
193
  loop?: {
184
194
  maxIters: number;
@@ -202,6 +212,8 @@ export interface WorkflowNodeSpec {
202
212
  maxTurns?: number;
203
213
  /** O3: cap this node's child run at `maxWallMs` wall-clock milliseconds. */
204
214
  maxWallMs?: number;
215
+ /** Host-only scheduling facts used with the configured deterministic scheduler policy. */
216
+ schedulingFactors?: SchedulingFactors;
205
217
  /** Indices of nodes this node depends on. */
206
218
  dependsOn?: number[];
207
219
  /** How dependency terminal states gate this node. Defaults to `all_success`. */
@@ -270,7 +282,7 @@ export interface WorkflowSpawnInfo {
270
282
  left: string;
271
283
  right: string;
272
284
  };
273
- /** A#2 v2: present only for a *loop* iteration spawn — the loop's `max_iters`. Marks the spawn as a
285
+ /** loop-control: present only for a *loop* iteration spawn — the loop's `max_iters`. Marks the spawn as a
274
286
  * loop iteration so the runner solicits + reports a `loopContinue` stop signal. */
275
287
  loop_max_iters?: number;
276
288
  /** A#2: present only for a *classify* spawn — the branch labels the classifier must choose among.
@@ -315,10 +327,10 @@ export declare function workflowSpecToKernel(spec: WorkflowSpec): Record<string,
315
327
  * (true loop-until-done / dynamic fan-out). Give it to nodes meant to fan out; the runner intercepts
316
328
  * the call and routes the nodes to the parent kernel (the child's own kernel holds no workflow). */
317
329
  export declare const submitWorkflowNodesTool: ToolSchema;
318
- /** M5 v1 (flatten): the tool an agent calls to **author a sub-workflow** — a cohesive DAG of nodes
330
+ /** workflow authoring: the tool an agent calls to **author a sub-workflow** — a cohesive DAG of nodes
319
331
  * (incl. loop/classify/tournament/reduce) composed onto the running workflow. Mechanically it lowers
320
332
  * to the same append path as `submit_workflow_nodes` (a `WorkflowSpec` is a node batch), but reads as
321
- * "write a harness" rather than "append nodes". v2 adds top-level bootstrap (the `LoadWorkflow`
333
+ * "write a harness" rather than "append nodes". Top-level bootstrap uses (the `LoadWorkflow`
322
334
  * kernel syscall) so a plain run can start a workflow from scratch. */
323
335
  export declare const startWorkflowTool: ToolSchema;
324
336
  /** Build a sub-agent run spec for a kernel-generated workflow node. */
@@ -36,7 +36,7 @@ export function agentRunSpecToKernel(spec) {
36
36
  ...(spec.loopRound.defaultAction !== undefined ? { default_action: spec.loopRound.defaultAction } : {}),
37
37
  };
38
38
  }
39
- // Exposure baseline: `undefined` ⇒ omit the field entirely (kernel `None` = legacy behavior);
39
+ // Exposure baseline: `undefined` ⇒ omit the field entirely (kernel canonical default);
40
40
  // `[]` ⇒ send `[]` (kernel `Some([])` = the minimal surface). The unset/minimal distinction is
41
41
  // load-bearing, so this is deliberately NOT the `length > 0` idiom `allowedToolIds` uses.
42
42
  if (spec.exposureBaseline !== undefined)
@@ -240,6 +240,7 @@ function nodeKindToKernel(n) {
240
240
  * whole spec) and `submit_workflow_nodes` (R3-1 runtime append) so the two encodings never drift. */
241
241
  export function workflowNodeSpecToKernel(n) {
242
242
  const kind = nodeKindToKernel(n);
243
+ const schedulingFactors = schedulingFactorsToKernel(n.schedulingFactors);
243
244
  return {
244
245
  task: workflowTaskToKernel(n.task),
245
246
  role: n.role,
@@ -256,16 +257,41 @@ export function workflowNodeSpecToKernel(n) {
256
257
  // O3: per-node turn / wall-clock caps (additive; omitted when unset).
257
258
  ...(n.maxTurns != null ? { max_turns: n.maxTurns } : {}),
258
259
  ...(n.maxWallMs != null ? { max_wall_ms: n.maxWallMs } : {}),
260
+ ...(schedulingFactors ? { scheduling_factors: schedulingFactors } : {}),
259
261
  ...(n.dependsOn && n.dependsOn.length ? { depends_on: n.dependsOn } : {}),
260
262
  dep_policy: n.depPolicy ?? "all_success",
261
263
  };
262
264
  }
265
+ function schedulingFactorsToKernel(factors) {
266
+ if (factors === undefined)
267
+ return undefined;
268
+ const allowed = new Set(["deadlineUrgency", "processPriority", "resourcePressure", "budgetPressure"]);
269
+ const unknown = Object.keys(factors).filter(key => !allowed.has(key));
270
+ if (unknown.length > 0)
271
+ throw new TypeError(`unknown scheduling factor(s): ${unknown.join(", ")}`);
272
+ const out = {};
273
+ for (const [host, kernel] of Object.entries({
274
+ deadlineUrgency: "deadline_urgency",
275
+ processPriority: "process_priority",
276
+ resourcePressure: "resource_pressure",
277
+ budgetPressure: "budget_pressure",
278
+ })) {
279
+ const value = factors[host];
280
+ if (value !== undefined) {
281
+ if (!Number.isSafeInteger(value) || value < 0) {
282
+ throw new RangeError(`schedulingFactors.${host} must be a non-negative safe integer`);
283
+ }
284
+ out[kernel] = value;
285
+ }
286
+ }
287
+ return out;
288
+ }
263
289
  /** Map a host `WorkflowSpec` to the canonical workflow-root JSON. */
264
290
  export function workflowSpecToKernel(spec) {
265
291
  return { nodes: spec.nodes.map(workflowNodeSpecToKernel) };
266
292
  }
267
293
  /** Shared JSON-Schema for a workflow-node batch (a DAG). Used by both `submit_workflow_nodes`
268
- * (append) and `start_workflow` (M5 v1: author a sub-workflow), so the two tools never drift. */
294
+ * (append) and `start_workflow` (workflow authoring: author a sub-workflow), so the two tools never drift. */
269
295
  const workflowNodesArraySchema = {
270
296
  type: "array",
271
297
  description: "Workflow nodes (a DAG); each runs as a gated sub-agent. A node may declare ONE control-flow kind " +
@@ -391,10 +417,10 @@ export const submitWorkflowNodesTool = {
391
417
  required: ["nodes"],
392
418
  }),
393
419
  };
394
- /** M5 v1 (flatten): the tool an agent calls to **author a sub-workflow** — a cohesive DAG of nodes
420
+ /** workflow authoring: the tool an agent calls to **author a sub-workflow** — a cohesive DAG of nodes
395
421
  * (incl. loop/classify/tournament/reduce) composed onto the running workflow. Mechanically it lowers
396
422
  * to the same append path as `submit_workflow_nodes` (a `WorkflowSpec` is a node batch), but reads as
397
- * "write a harness" rather than "append nodes". v2 adds top-level bootstrap (the `LoadWorkflow`
423
+ * "write a harness" rather than "append nodes". Top-level bootstrap uses (the `LoadWorkflow`
398
424
  * kernel syscall) so a plain run can start a workflow from scratch. */
399
425
  export const startWorkflowTool = {
400
426
  name: "start_workflow",
package/dist/types.d.ts CHANGED
@@ -26,8 +26,70 @@ export interface ToolResultPart {
26
26
  callId: string;
27
27
  output: string;
28
28
  isError: boolean;
29
+ /** Structured tool output. Provider boundaries normalize this into one canonical block list
30
+ * and reject `output` when it disagrees with the deterministic text projection. */
31
+ contentParts?: ToolOutputBlock[];
29
32
  }
30
33
  export type ContentPart = TextPart | ImagePart | AudioPart | ToolResultPart;
34
+ /**
35
+ * spc_011-B-05: canonical multimodal content, additive alongside `ContentPart` during the
36
+ * migration. `ContentBlockImage`/`ContentBlockAudio`/etc.
37
+ * are distinctly named (not reusing `ImagePart`/`AudioPart`) since those names are already taken
38
+ * by `ContentPart`'s variants with a different shape (`url?/data?` inline vs `source: MediaSource`).
39
+ */
40
+ export type MediaSource = {
41
+ kind: "url";
42
+ url: string;
43
+ } | {
44
+ kind: "base64";
45
+ data: string;
46
+ } | {
47
+ kind: "fileId";
48
+ id: string;
49
+ /** Endpoint that issued this provider-owned reference. An omitted affinity constrains the
50
+ * reference to the already-resolved current endpoint. */
51
+ affinity?: {
52
+ providerId: string;
53
+ endpointId: string;
54
+ };
55
+ } | {
56
+ kind: "object";
57
+ handle: string;
58
+ owner?: string;
59
+ payloadRef?: string;
60
+ };
61
+ export interface ContentBlockText {
62
+ type: "text";
63
+ text: string;
64
+ }
65
+ export interface ContentBlockImage {
66
+ type: "image";
67
+ source: MediaSource;
68
+ mediaType?: string;
69
+ providerOptions?: Record<string, unknown>;
70
+ }
71
+ export interface ContentBlockAudio {
72
+ type: "audio";
73
+ source: MediaSource;
74
+ mediaType?: string;
75
+ providerOptions?: Record<string, unknown>;
76
+ }
77
+ export interface ContentBlockVideo {
78
+ type: "video";
79
+ source: MediaSource;
80
+ mediaType?: string;
81
+ providerOptions?: Record<string, unknown>;
82
+ }
83
+ export interface ContentBlockFile {
84
+ type: "file";
85
+ source: MediaSource;
86
+ filename?: string;
87
+ mediaType?: string;
88
+ providerOptions?: Record<string, unknown>;
89
+ }
90
+ /** Legal content returned by a tool. Deliberately excludes ToolResult, so nesting is
91
+ * unrepresentable in the canonical type. */
92
+ export type ToolOutputBlock = ContentBlockText | ContentBlockImage | ContentBlockAudio | ContentBlockVideo | ContentBlockFile;
31
93
  export interface Message {
32
94
  role: "system" | "user" | "assistant" | "tool";
33
95
  /** Plain-text content. When `contentParts` is present, this holds only the text segments. */
@@ -50,11 +112,16 @@ export interface ToolResult {
50
112
  isFatal?: boolean;
51
113
  errorKind?: ToolErrorKind;
52
114
  tokenCount?: number;
115
+ /** spc_012-N-01: same additive contract as `ToolResultPart.contentParts` (see there). */
116
+ contentParts?: ToolOutputBlock[];
53
117
  }
54
118
  export interface ToolSchema {
55
119
  name: string;
56
120
  description: string;
57
121
  parameters: string;
122
+ /** spc_001: vendor-specific extension bag, keyed by provider name. Preserved through
123
+ * normalization/lowering, never flattened into portable fields. */
124
+ providerOptions?: Record<string, unknown>;
58
125
  }
59
126
  export interface StreamEvent {
60
127
  type: string;
@@ -84,19 +151,20 @@ export interface UsageEvent extends StreamEvent {
84
151
  cacheReadInputTokens?: number;
85
152
  /** Prompt tokens written to cache this request (billed ~1.25x). Subset of inputTokens. */
86
153
  cacheCreationInputTokens?: number;
87
- /** I1: per-slot pro-rata attribution of `cacheReadInputTokens`. Estimated, not authoritative —
88
- * Anthropic returns a single cache-read total, so the SDK divides it evenly across the slots
89
- * that carried a `cache_control` breakpoint on the request. Missing when the provider doesn't
90
- * honor `cache_control` (OpenAI-family auto-cache) or when no breakpoints were placed. */
154
+ cacheTelemetryStatus?: CacheTelemetryStatus;
155
+ cacheTelemetrySource?: CacheTelemetrySource;
156
+ /** Reserved for provider-authoritative per-slot data. DeepStrike does not estimate this field. */
91
157
  cacheReadInputTokensBySlot?: {
92
158
  system?: number;
93
159
  tools?: number;
94
160
  messages?: number;
95
161
  };
96
- /** Provider stop reason for the response — `max_tokens` (Anthropic) / `length` (OpenAI) flag an
97
- * output-cap truncation, which drives the kernel's max-output-tokens recovery. Absent when the
98
- * provider doesn't report one. */
99
- stopReason?: string;
162
+ /** Canonical provider stop reason. `max_tokens` drives the kernel's output-cap recovery. */
163
+ stopReason?: "end_turn" | "tool_use" | "max_tokens" | "stop_sequence" | "content_filter" | "other";
164
+ /** Original provider spelling for diagnostics only. RuntimeRunner never forwards it to Kernel. */
165
+ rawStopReason?: string;
166
+ /** Normalized postflight usage parsed from this same raw provider response. */
167
+ providerUsage?: ProviderUsage;
100
168
  }
101
169
  export type ToolChunk = string | {
102
170
  type: "text";
@@ -122,7 +190,7 @@ export interface ToolDeltaEvent extends StreamEvent {
122
190
  type: "tool_delta";
123
191
  callId: string;
124
192
  name: string;
125
- /** Backward-compatible text projection when the chunk carries text. */
193
+ /** Text projection when the chunk carries text. */
126
194
  delta?: string;
127
195
  chunk: Exclude<ToolChunk, string>;
128
196
  }
@@ -141,6 +209,9 @@ export interface ToolResultEvent extends StreamEvent {
141
209
  isError: boolean;
142
210
  isFatal?: boolean;
143
211
  errorKind?: ToolErrorKind;
212
+ /** spc_012-N-02: structured multimodal blocks when the tool returned non-text content
213
+ * (e.g. an MCP screenshot). `content` stays the text projection; see `ToolResultPart.contentParts`. */
214
+ contentParts?: ToolOutputBlock[];
144
215
  }
145
216
  /** R3-1: a workflow node's agent called the `submit_workflow_nodes` tool. The runner intercepts it
146
217
  * (it cannot apply to the child's own kernel — the workflow lives in the parent) and surfaces the
@@ -206,12 +277,11 @@ export interface ToolAuditFailedEvent extends StreamEvent {
206
277
  }
207
278
  /** Kernel session-entropy measurement at a completed turn boundary. "Entropy" = session
208
279
  * disorder: repetition, tool failures, rollbacks, context pressure. The component vector is
209
- * the contract; `score` is a versioned default fold (`scoreVersion`). All normalized
280
+ * the contract; `score` is the canonical default fold. All normalized
210
281
  * components are in [0, 1]. */
211
282
  export interface EntropySample {
212
283
  turn: number;
213
284
  score: number;
214
- scoreVersion: number;
215
285
  /** Context pressure after this boundary's eviction pass. */
216
286
  rho: number;
217
287
  /** Consecutive-identical-turn streak, normalized against the RepeatFuse deny rung. */
@@ -262,6 +332,44 @@ export interface TokenUsage {
262
332
  /** Prompt tokens written to cache (billed ~1.25x). Subset of inputTokens. */
263
333
  cacheCreationInputTokens?: number;
264
334
  }
335
+ /** Raw postflight token facts normalized across provider wire shapes. */
336
+ export interface ProviderUsage {
337
+ inputTokens: number;
338
+ outputTokens: number;
339
+ cacheReadInputTokens?: number;
340
+ cacheCreationInputTokens?: number;
341
+ cacheTelemetryStatus?: CacheTelemetryStatus;
342
+ cacheTelemetrySource?: CacheTelemetrySource;
343
+ /** Output tokens spent on hidden reasoning (OpenAI `completion_tokens_details.reasoning_tokens` /
344
+ * Responses `output_tokens_details.reasoning_tokens`). A SUBSET of `outputTokens`, not additional
345
+ * — vendors that don't report a separate count (Anthropic, Gemini via this SDK) leave this unset
346
+ * rather than guessing. */
347
+ reasoningTokens?: number;
348
+ }
349
+ export type CacheTelemetryStatus = "measured" | "unavailable";
350
+ export type CacheTelemetrySource = "anthropic_usage" | "openai_prompt_details" | "deepseek_prompt_cache" | "gemini_usage";
351
+ /** Node-side mirror of the reserved Rust `context::measurement` types — where a
352
+ * preflight token count came from. Field names/shape intentionally match the Rust
353
+ * `MeasurementSource` enum (`kind`-tagged, snake_case variant names) so the two sides can be
354
+ * compared/round-tripped without a translation layer. A-00R removed the non-durable adaptive
355
+ * scheduler producer; the shape remains for the native provider meter implementations. */
356
+ export type MeasurementSource = {
357
+ kind: "native";
358
+ provider: string;
359
+ } | {
360
+ kind: "local_exact";
361
+ tokenizer: string;
362
+ } | {
363
+ kind: "heuristic";
364
+ };
365
+ export type MeasurementConfidence = "exact" | "high_confidence" | "low_confidence";
366
+ /** A single preflight token-count fact for a candidate render, for a specific provider/model —
367
+ * the Node counterpart of Rust's `PromptMeasurement` (spc_011-C-02). */
368
+ export interface PromptMeasurement {
369
+ inputTokens: number;
370
+ source: MeasurementSource;
371
+ confidence: MeasurementConfidence;
372
+ }
265
373
  export interface ProviderToolSpec {
266
374
  name: string;
267
375
  description: string;
@@ -326,9 +434,8 @@ export interface ProviderDescriptor {
326
434
  }
327
435
  /** Provider-native fields required to replay a turn across requests (thinking blocks, reasoning_content, etc.). */
328
436
  export interface ProviderReplay {
329
- schema_version?: 1 | 2;
330
437
  provider?: string;
331
- protocol?: ProviderProtocol;
438
+ protocol: ProviderProtocol;
332
439
  model?: string;
333
440
  /** Anthropic-style assistant content blocks (thinking, text, tool_use). */
334
441
  native_blocks?: Array<Record<string, unknown>>;
@@ -409,12 +516,23 @@ export interface LLMProvider {
409
516
  * candidate) before issuing the request. Seed any persisted replay first.
410
517
  */
411
518
  assessReplayability?(context: RenderedContext, extensions?: Record<string, unknown>): ReplayabilityAssessment;
519
+ /**
520
+ * spc_011-C-02/03: preflight token count via the provider's own native counting endpoint
521
+ * (Anthropic `messages.countTokens` and Gemini `countTokens`),
522
+ * where the vendor offers one. Optional — providers without a native endpoint simply omit it,
523
+ * and callers fall back to `FallbackEstimator` (Rust `context::token_engine`, spc_011-C-01) or
524
+ * a local tokenizer. Not currently invoked by any dispatch loop (nothing in the Rust kernel
525
+ * emits `EffectKind::MeasurePrompt` yet — see its doc comment); this method exists so the
526
+ * capability remains directly callable, but no dispatch trigger is enabled until request
527
+ * fingerprinting and durable measurement semantics are defined.
528
+ */
529
+ countTokens?(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState): Promise<PromptMeasurement>;
412
530
  complete(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>): Promise<Message>;
413
531
  stream(context: RenderedContext, tools: ToolSchema[], extensions?: Record<string, unknown>, state?: ProviderRunState,
414
532
  /** #2-B-ii: when provided, a preempting `InterruptNow` (or `interrupt()`) aborts the in-flight
415
533
  * request. SDK-client providers should forward it to the client (`{ signal }`); the runner also
416
534
  * breaks the consume loop on abort, so providers that ignore it still stop processing immediately
417
- * (only the socket lingers). Optional ⇒ backward-compatible; providers may ignore it. */
535
+ * (only the socket lingers). */
418
536
  signal?: AbortSignal): AsyncIterable<StreamEvent>;
419
537
  }
420
538
  /**
@@ -425,10 +543,10 @@ export interface AsyncSummarizer {
425
543
  summarize(archived: Message[], action: string): Promise<string>;
426
544
  }
427
545
  /**
428
- * Long-term memory summarizer for semantic `page_out` events (Layer 5 contract).
429
- * The kernel emits `page_out { tier_hint: "semantic" }`; the SDK persists an LLM summary to DreamStore.
546
+ * Durable-memory summarizer for semantic `page_out` events (Layer 5 contract).
547
+ * The kernel emits `page_out { tier_hint: "semantic" }`; the SDK persists an LLM summary to MemoryStore.
430
548
  */
431
- export interface DreamSummarizer {
549
+ export interface MemorySummarizer {
432
550
  summarize(archived: Message[], context: {
433
551
  action?: string;
434
552
  }): Promise<string>;