@dogpile/sdk 0.4.0 → 0.6.0

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 (108) hide show
  1. package/CHANGELOG.md +92 -0
  2. package/dist/browser/index.js +4156 -4611
  3. package/dist/browser/index.js.map +1 -1
  4. package/dist/index.d.ts +3 -1
  5. package/dist/index.d.ts.map +1 -1
  6. package/dist/index.js +1 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/providers/openai-compatible.d.ts.map +1 -1
  9. package/dist/providers/openai-compatible.js +6 -1
  10. package/dist/providers/openai-compatible.js.map +1 -1
  11. package/dist/runtime/audit.d.ts +42 -0
  12. package/dist/runtime/audit.d.ts.map +1 -0
  13. package/dist/runtime/audit.js +73 -0
  14. package/dist/runtime/audit.js.map +1 -0
  15. package/dist/runtime/broadcast.d.ts +1 -0
  16. package/dist/runtime/broadcast.d.ts.map +1 -1
  17. package/dist/runtime/broadcast.js +171 -105
  18. package/dist/runtime/broadcast.js.map +1 -1
  19. package/dist/runtime/coordinator.d.ts +9 -2
  20. package/dist/runtime/coordinator.d.ts.map +1 -1
  21. package/dist/runtime/coordinator.js +164 -78
  22. package/dist/runtime/coordinator.js.map +1 -1
  23. package/dist/runtime/defaults.d.ts.map +1 -1
  24. package/dist/runtime/defaults.js +14 -5
  25. package/dist/runtime/defaults.js.map +1 -1
  26. package/dist/runtime/engine.d.ts +17 -4
  27. package/dist/runtime/engine.d.ts.map +1 -1
  28. package/dist/runtime/engine.js +577 -52
  29. package/dist/runtime/engine.js.map +1 -1
  30. package/dist/runtime/health.d.ts +51 -0
  31. package/dist/runtime/health.d.ts.map +1 -0
  32. package/dist/runtime/health.js +85 -0
  33. package/dist/runtime/health.js.map +1 -0
  34. package/dist/runtime/introspection.d.ts +96 -0
  35. package/dist/runtime/introspection.d.ts.map +1 -0
  36. package/dist/runtime/introspection.js +31 -0
  37. package/dist/runtime/introspection.js.map +1 -0
  38. package/dist/runtime/metrics.d.ts +44 -0
  39. package/dist/runtime/metrics.d.ts.map +1 -0
  40. package/dist/runtime/metrics.js +12 -0
  41. package/dist/runtime/metrics.js.map +1 -0
  42. package/dist/runtime/model.d.ts.map +1 -1
  43. package/dist/runtime/model.js +40 -10
  44. package/dist/runtime/model.js.map +1 -1
  45. package/dist/runtime/provenance.d.ts +25 -0
  46. package/dist/runtime/provenance.d.ts.map +1 -0
  47. package/dist/runtime/provenance.js +13 -0
  48. package/dist/runtime/provenance.js.map +1 -0
  49. package/dist/runtime/redaction.d.ts +13 -0
  50. package/dist/runtime/redaction.d.ts.map +1 -0
  51. package/dist/runtime/redaction.js +278 -0
  52. package/dist/runtime/redaction.js.map +1 -0
  53. package/dist/runtime/sanitization.d.ts +4 -0
  54. package/dist/runtime/sanitization.d.ts.map +1 -0
  55. package/dist/runtime/sanitization.js +63 -0
  56. package/dist/runtime/sanitization.js.map +1 -0
  57. package/dist/runtime/sequential.d.ts.map +1 -1
  58. package/dist/runtime/sequential.js +39 -36
  59. package/dist/runtime/sequential.js.map +1 -1
  60. package/dist/runtime/shared.d.ts +1 -0
  61. package/dist/runtime/shared.d.ts.map +1 -1
  62. package/dist/runtime/shared.js +167 -101
  63. package/dist/runtime/shared.js.map +1 -1
  64. package/dist/runtime/tools/built-in.d.ts +2 -0
  65. package/dist/runtime/tools/built-in.d.ts.map +1 -1
  66. package/dist/runtime/tools/built-in.js +153 -15
  67. package/dist/runtime/tools/built-in.js.map +1 -1
  68. package/dist/runtime/tools.d.ts.map +1 -1
  69. package/dist/runtime/tools.js +29 -7
  70. package/dist/runtime/tools.js.map +1 -1
  71. package/dist/runtime/tracing.d.ts +31 -0
  72. package/dist/runtime/tracing.d.ts.map +1 -0
  73. package/dist/runtime/tracing.js +18 -0
  74. package/dist/runtime/tracing.js.map +1 -0
  75. package/dist/runtime/validation.d.ts.map +1 -1
  76. package/dist/runtime/validation.js +3 -0
  77. package/dist/runtime/validation.js.map +1 -1
  78. package/dist/types/events.d.ts +13 -7
  79. package/dist/types/events.d.ts.map +1 -1
  80. package/dist/types/replay.d.ts +5 -1
  81. package/dist/types/replay.d.ts.map +1 -1
  82. package/dist/types.d.ts +144 -1
  83. package/dist/types.d.ts.map +1 -1
  84. package/dist/types.js.map +1 -1
  85. package/package.json +46 -1
  86. package/src/index.ts +5 -0
  87. package/src/providers/openai-compatible.ts +6 -1
  88. package/src/runtime/audit.ts +121 -0
  89. package/src/runtime/broadcast.ts +195 -108
  90. package/src/runtime/coordinator.ts +197 -86
  91. package/src/runtime/defaults.ts +15 -5
  92. package/src/runtime/engine.ts +725 -58
  93. package/src/runtime/health.ts +136 -0
  94. package/src/runtime/introspection.ts +122 -0
  95. package/src/runtime/metrics.ts +45 -0
  96. package/src/runtime/model.ts +44 -9
  97. package/src/runtime/provenance.ts +43 -0
  98. package/src/runtime/redaction.ts +355 -0
  99. package/src/runtime/sanitization.ts +81 -0
  100. package/src/runtime/sequential.ts +40 -37
  101. package/src/runtime/shared.ts +191 -104
  102. package/src/runtime/tools/built-in.ts +168 -15
  103. package/src/runtime/tools.ts +39 -8
  104. package/src/runtime/tracing.ts +35 -0
  105. package/src/runtime/validation.ts +3 -0
  106. package/src/types/events.ts +13 -7
  107. package/src/types/replay.ts +5 -1
  108. package/src/types.ts +152 -1
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Duck-typed OTEL tracing bridge surface (Phase 9 / OTEL-01..OTEL-03).
3
+ *
4
+ * The SDK does not import `@opentelemetry/*` anywhere in `src/runtime/`,
5
+ * `src/browser/`, or `src/providers/`. Callers wire a real OTEL Tracer to
6
+ * the SDK by providing an object that structurally matches `DogpileTracer`.
7
+ * See `docs/developer-usage.md` for the WeakMap-based bridge pattern.
8
+ *
9
+ * `replay()` and `replayStream()` ignore any tracer on engine options —
10
+ * historical timestamps would confuse OTEL backends.
11
+ */
12
+
13
+ export interface DogpileSpan {
14
+ end(): void;
15
+ setAttribute(key: string, value: string | number | boolean): void;
16
+ setStatus(code: "ok" | "error", message?: string): void;
17
+ }
18
+
19
+ export interface DogpileSpanOptions {
20
+ readonly parent?: DogpileSpan;
21
+ readonly attributes?: Readonly<Record<string, string | number | boolean>>;
22
+ }
23
+
24
+ export interface DogpileTracer {
25
+ startSpan(name: string, options?: DogpileSpanOptions): DogpileSpan;
26
+ }
27
+
28
+ export const DOGPILE_SPAN_NAMES = {
29
+ RUN: "dogpile.run",
30
+ SUB_RUN: "dogpile.sub-run",
31
+ AGENT_TURN: "dogpile.agent-turn",
32
+ MODEL_CALL: "dogpile.model-call"
33
+ } as const;
34
+
35
+ export type DogpileSpanName = (typeof DOGPILE_SPAN_NAMES)[keyof typeof DOGPILE_SPAN_NAMES];
@@ -73,6 +73,7 @@ export function validateDogpileOptions(options: DogpileOptions): void {
73
73
  validateOptionalAbortSignal(options.signal, "signal");
74
74
  validateOptionalNonNegativeInteger(options.maxDepth, "maxDepth");
75
75
  validateOptionalPositiveInteger(options.maxConcurrentChildren, "maxConcurrentChildren");
76
+ validateOptionalPositiveInteger(options.maxConcurrentAgentTurns, "maxConcurrentAgentTurns");
76
77
  validateOptionalPositiveFiniteNumber(options.defaultSubRunTimeoutMs, "defaultSubRunTimeoutMs");
77
78
  validateOptionalOnChildFailure(options.onChildFailure, "onChildFailure");
78
79
  }
@@ -91,6 +92,7 @@ export function validateRunCallOptions(options: unknown, path = "options"): void
91
92
  const record = requireRecord(options, path);
92
93
  validateOptionalNonNegativeInteger(record.maxDepth, `${path}.maxDepth`);
93
94
  validateOptionalPositiveInteger(record.maxConcurrentChildren, `${path}.maxConcurrentChildren`);
95
+ validateOptionalPositiveInteger(record.maxConcurrentAgentTurns, `${path}.maxConcurrentAgentTurns`);
94
96
  validateOptionalOnChildFailure(record.onChildFailure, `${path}.onChildFailure`);
95
97
  }
96
98
 
@@ -113,6 +115,7 @@ export function validateEngineOptions(options: EngineOptions): void {
113
115
  validateOptionalAbortSignal(options.signal, "signal");
114
116
  validateOptionalNonNegativeInteger(options.maxDepth, "maxDepth");
115
117
  validateOptionalPositiveInteger(options.maxConcurrentChildren, "maxConcurrentChildren");
118
+ validateOptionalPositiveInteger(options.maxConcurrentAgentTurns, "maxConcurrentAgentTurns");
116
119
  validateOptionalPositiveFiniteNumber(options.defaultSubRunTimeoutMs, "defaultSubRunTimeoutMs");
117
120
  validateOptionalOnChildFailure(options.onChildFailure, "onChildFailure");
118
121
  }
@@ -71,12 +71,14 @@ export interface ModelRequestEvent {
71
71
  readonly runId: string;
72
72
  /** Root-first ancestry chain when bubbled through a parent stream. */
73
73
  readonly parentRunIds?: readonly string[];
74
- /** ISO-8601 event timestamp. */
75
- readonly at: string;
74
+ /** ISO-8601 timestamp immediately before the provider call began. */
75
+ readonly startedAt: string;
76
76
  /** Stable provider call id within the run. */
77
77
  readonly callId: string;
78
78
  /** Configured model provider id receiving the request. */
79
79
  readonly providerId: string;
80
+ /** Resolved model identifier; falls back to provider id when adapter does not set modelId. */
81
+ readonly modelId: string;
80
82
  /** Agent requesting the model call. */
81
83
  readonly agentId: string;
82
84
  /** Agent role for the active model call. */
@@ -101,12 +103,16 @@ export interface ModelResponseEvent {
101
103
  readonly runId: string;
102
104
  /** Root-first ancestry chain when bubbled through a parent stream. */
103
105
  readonly parentRunIds?: readonly string[];
104
- /** ISO-8601 event timestamp. */
105
- readonly at: string;
106
+ /** ISO-8601 timestamp when the provider call started (same value as the paired ModelRequestEvent). */
107
+ readonly startedAt: string;
108
+ /** ISO-8601 timestamp after the provider call completed. Duration = completedAt minus startedAt. */
109
+ readonly completedAt: string;
106
110
  /** Stable provider call id within the run. */
107
111
  readonly callId: string;
108
112
  /** Configured model provider id that produced the response. */
109
113
  readonly providerId: string;
114
+ /** Resolved model identifier; falls back to provider id when adapter does not set modelId. */
115
+ readonly modelId: string;
110
116
  /** Agent that requested the model call. */
111
117
  readonly agentId: string;
112
118
  /** Agent role for the completed model call. */
@@ -134,7 +140,7 @@ export interface ModelResponseEvent {
134
140
  * - `input`: prompt text visible to that agent for this turn.
135
141
  * - `chunkIndex`: zero-based chunk index within this model turn.
136
142
  * - `text`: text delta from the provider.
137
- * - `output`: accumulated output for this turn after applying the chunk.
143
+ * - `outputLength`: accumulated output character length after applying the chunk.
138
144
  */
139
145
  export interface ModelOutputChunkEvent {
140
146
  /** Discriminant for event rendering and exhaustive switches. */
@@ -155,8 +161,8 @@ export interface ModelOutputChunkEvent {
155
161
  readonly chunkIndex: number;
156
162
  /** Text delta produced by the model provider. */
157
163
  readonly text: string;
158
- /** Accumulated output for this turn after applying this chunk. */
159
- readonly output: string;
164
+ /** Accumulated output character length after applying this chunk. */
165
+ readonly outputLength: number;
160
166
  }
161
167
 
162
168
  /**
@@ -163,8 +163,10 @@ export interface ReplayTraceProtocolDecision {
163
163
  readonly contributionCount?: number;
164
164
  /** Prompt/input associated with turn decisions. */
165
165
  readonly input?: string;
166
- /** Output associated with turn or final decisions. */
166
+ /** Output associated with turn/final decisions, or a streaming text delta. */
167
167
  readonly output?: string;
168
+ /** Accumulated output character length for streaming output observations. */
169
+ readonly outputLength?: number;
168
170
  /** Cumulative cost visible at this decision point. */
169
171
  readonly cost?: CostSummary;
170
172
  /** Normalized budget stop reason for budget-stop decisions. */
@@ -181,6 +183,8 @@ export interface ReplayTraceProviderCall {
181
183
  readonly callId: string;
182
184
  /** Configured model provider id. */
183
185
  readonly providerId: string;
186
+ /** Resolved model identifier (same fallback as provenance events). */
187
+ readonly modelId: string;
184
188
  /** ISO-8601 timestamp before the provider call started. */
185
189
  readonly startedAt: string;
186
190
  /** ISO-8601 timestamp after the provider call completed. */
package/src/types.ts CHANGED
@@ -1,3 +1,7 @@
1
+ import type { DogpileTracer } from "./runtime/tracing.js";
2
+ import type { Logger } from "./runtime/logger.js";
3
+ import type { MetricsHook } from "./runtime/metrics.js";
4
+
1
5
  /**
2
6
  * Primitive JSON value accepted in serializable trace metadata.
3
7
  */
@@ -884,6 +888,8 @@ export interface ModelOutputChunk {
884
888
  export interface ConfiguredModelProvider {
885
889
  /** Stable provider id recorded in traces. */
886
890
  readonly id: string;
891
+ /** Optional resolved model identifier. When set, provenance events carry this value; when absent, the SDK falls back to `id`. */
892
+ readonly modelId?: string;
887
893
  /** Generate a response for one protocol-managed model request. */
888
894
  generate(request: ModelRequest): Promise<ModelResponse>;
889
895
  /**
@@ -1652,7 +1658,7 @@ export interface RunMetadata {
1652
1658
  * Result returned by high-level single-call APIs.
1653
1659
  *
1654
1660
  * The returned shape is
1655
- * `{ output, eventLog, transcript, usage, metadata, accounting, trace, cost, quality, evaluation }`.
1661
+ * `{ output, eventLog, transcript, usage, metadata, accounting, trace, cost, quality, evaluation, health }`.
1656
1662
  * `output` is the final synthesized answer, `eventLog` is the complete ordered
1657
1663
  * coordination log, `transcript` is the complete agent-turn transcript,
1658
1664
  * `usage` reports token and dollar accounting, and `metadata` exposes stable
@@ -1661,6 +1667,7 @@ export interface RunMetadata {
1661
1667
  * serializable replay artifact, `cost` is retained as a compatibility alias
1662
1668
  * for `usage`, and `quality` and `evaluation` are present when a judge or
1663
1669
  * benchmark supplies a normalized score and serializable evaluation payload.
1670
+ * `health` exposes machine-readable diagnostics once computed by the runtime.
1664
1671
  */
1665
1672
  export interface RunResult {
1666
1673
  /** Final synthesized answer for the supplied intent. */
@@ -1688,6 +1695,15 @@ export interface RunResult {
1688
1695
  readonly quality?: NormalizedQualityScore;
1689
1696
  /** Optional serializable evaluation data supplied by a caller-owned evaluator. */
1690
1697
  readonly evaluation?: RunEvaluation;
1698
+ /**
1699
+ * Machine-readable health summary for the run, auto-computed from trace events.
1700
+ *
1701
+ * Always present. Re-computed identically by `replay()` from the same trace —
1702
+ * contains no information beyond what the trace events carry. Use
1703
+ * `computeHealth(trace, thresholds)` from `@dogpile/sdk/runtime/health` to
1704
+ * re-compute with custom thresholds on a stored trace.
1705
+ */
1706
+ readonly health: RunHealthSummary;
1691
1707
  }
1692
1708
 
1693
1709
  /**
@@ -1696,6 +1712,69 @@ export interface RunResult {
1696
1712
  */
1697
1713
  export type RunEvaluator = (result: Omit<RunResult, "quality" | "evaluation">) => RunEvaluation | Promise<RunEvaluation>;
1698
1714
 
1715
+ /**
1716
+ * Machine-readable code identifying a health anomaly detected in a completed run.
1717
+ *
1718
+ * - `"runaway-turns"`: an agent exceeded the configured per-agent turn threshold.
1719
+ * - `"budget-near-miss"`: budget utilization exceeded the configured near-miss threshold.
1720
+ * - `"empty-contribution"`: an agent produced an empty (blank/whitespace) output turn.
1721
+ * - `"provider-error-recovered"`: a provider call failed and was retried successfully.
1722
+ * Detection is deferred — computeHealth never emits this code in Phase 7 because no
1723
+ * trace signal exists without an event-shape change. The code is reserved for future use.
1724
+ */
1725
+ export type AnomalyCode =
1726
+ | "runaway-turns"
1727
+ | "budget-near-miss"
1728
+ | "empty-contribution"
1729
+ | "provider-error-recovered";
1730
+
1731
+ /**
1732
+ * A single health anomaly detected in a completed run trace.
1733
+ *
1734
+ * All fields are required except `agentId`, which is present for per-agent anomalies
1735
+ * (`"runaway-turns"`, `"empty-contribution"`, `"provider-error-recovered"`) and absent
1736
+ * for global anomalies (`"budget-near-miss"`).
1737
+ */
1738
+ export interface HealthAnomaly {
1739
+ /** Machine-readable anomaly identifier. */
1740
+ readonly code: AnomalyCode;
1741
+ /** Severity level: `"error"` for runaway turns and empty contributions; `"warning"` for near-miss and recovered patterns. */
1742
+ readonly severity: "warning" | "error";
1743
+ /** Actual measured value that triggered the anomaly (turn count, utilization %, etc.). */
1744
+ readonly value: number;
1745
+ /** Threshold value that was exceeded (for comparison in UIs and alerting). */
1746
+ readonly threshold: number;
1747
+ /** Agent that triggered the anomaly, present for per-agent anomaly codes. */
1748
+ readonly agentId?: string;
1749
+ }
1750
+
1751
+ /**
1752
+ * Machine-readable health summary for a completed run, auto-computed from trace events.
1753
+ *
1754
+ * Always present on {@link RunResult}. Re-computed identically by `replay()` from the
1755
+ * same trace — no information is stored beyond what the trace events contain.
1756
+ *
1757
+ * Use `computeHealth(trace, thresholds)` from `@dogpile/sdk/runtime/health` to re-compute
1758
+ * with custom thresholds.
1759
+ */
1760
+ export interface RunHealthSummary {
1761
+ /** Detected health anomalies. Empty array when no anomalies are found. */
1762
+ readonly anomalies: readonly HealthAnomaly[];
1763
+ /** Derived stats computed from trace events. */
1764
+ readonly stats: {
1765
+ /** Total number of agent-turn events in the trace. */
1766
+ readonly totalTurns: number;
1767
+ /** Number of unique agents that produced at least one turn. */
1768
+ readonly agentCount: number;
1769
+ /**
1770
+ * Budget utilization as a percentage (0–100+).
1771
+ * `null` when no USD cap was configured for the run.
1772
+ * Computed as `(finalCost / maxUsd) * 100`.
1773
+ */
1774
+ readonly budgetUtilizationPct: number | null;
1775
+ };
1776
+ }
1777
+
1699
1778
  /**
1700
1779
  * Mission supplied to a high-level Dogpile workflow call.
1701
1780
  *
@@ -1807,6 +1886,32 @@ export interface DogpileOptions extends BudgetCostTierOptions {
1807
1886
  readonly seed?: string | number;
1808
1887
  /** Optional caller cancellation signal passed to provider-facing model requests. */
1809
1888
  readonly signal?: AbortSignal;
1889
+ /**
1890
+ * Optional duck-typed OTEL-compatible tracer. When provided, the SDK emits
1891
+ * spans for run start/end, sub-run start/end, agent-turn start/end, and
1892
+ * model-call start/end with correct parent-child ancestry. When absent the
1893
+ * run completes with zero span overhead — no allocations, no branch cost.
1894
+ * `replay()` and `replayStream()` ignore this field entirely.
1895
+ * See {@link DogpileTracer} in `@dogpile/sdk/runtime/tracing`.
1896
+ */
1897
+ readonly tracer?: DogpileTracer;
1898
+ /**
1899
+ * Optional callback object for run-completion metrics. When provided,
1900
+ * `onRunComplete` fires with a `RunMetricsSnapshot` at every terminal state
1901
+ * (completed, budget-stopped, or aborted). `onSubRunComplete` fires for each
1902
+ * coordinator-dispatched child run that completes. Hook errors are routed to
1903
+ * `logger.error` (or `console.error` when no logger is provided) and never
1904
+ * propagate into the run result. When absent, zero overhead — no allocations.
1905
+ * See `@dogpile/sdk/runtime/metrics` for the interface.
1906
+ */
1907
+ readonly metricsHook?: MetricsHook;
1908
+ /**
1909
+ * Optional structured logger for SDK-internal diagnostics (hook errors and
1910
+ * future debug/info events). Implement against pino, winston, or any other
1911
+ * logger by satisfying the `Logger` interface from `@dogpile/sdk/runtime/logger`.
1912
+ * When absent, hook errors fall back to `console.error`.
1913
+ */
1914
+ readonly logger?: Logger;
1810
1915
  /**
1811
1916
  * Maximum coordinator → sub-run recursion depth.
1812
1917
  *
@@ -1824,6 +1929,14 @@ export interface DogpileOptions extends BudgetCostTierOptions {
1824
1929
  * ceiling; the effective value is `min(engine, run ?? Infinity, decision ?? Infinity)`.
1825
1930
  */
1826
1931
  readonly maxConcurrentChildren?: number;
1932
+ /**
1933
+ * Maximum agent model turns that may execute in parallel for shared,
1934
+ * broadcast, and coordinator worker fan-out.
1935
+ *
1936
+ * Defaults to 4. Per-run values can only lower the engine ceiling.
1937
+ * This is independent from delegated child-run concurrency.
1938
+ */
1939
+ readonly maxConcurrentAgentTurns?: number;
1827
1940
  /**
1828
1941
  * Fallback timeout (milliseconds) applied to delegated sub-runs when neither
1829
1942
  * the parent's `budget.timeoutMs` nor the decision-level
@@ -1911,6 +2024,32 @@ export interface EngineOptions {
1911
2024
  readonly seed?: string | number;
1912
2025
  /** Optional caller cancellation signal passed to provider-facing model requests. */
1913
2026
  readonly signal?: AbortSignal;
2027
+ /**
2028
+ * Optional duck-typed OTEL-compatible tracer. When provided, the SDK emits
2029
+ * spans for run start/end, sub-run start/end, agent-turn start/end, and
2030
+ * model-call start/end with correct parent-child ancestry. When absent the
2031
+ * run completes with zero span overhead — no allocations, no branch cost.
2032
+ * `replay()` and `replayStream()` ignore this field entirely.
2033
+ * See {@link DogpileTracer} in `@dogpile/sdk/runtime/tracing`.
2034
+ */
2035
+ readonly tracer?: DogpileTracer;
2036
+ /**
2037
+ * Optional callback object for run-completion metrics. When provided,
2038
+ * `onRunComplete` fires with a `RunMetricsSnapshot` at every terminal state
2039
+ * (completed, budget-stopped, or aborted). `onSubRunComplete` fires for each
2040
+ * coordinator-dispatched child run that completes. Hook errors are routed to
2041
+ * `logger.error` (or `console.error` when no logger is provided) and never
2042
+ * propagate into the run result. When absent, zero overhead — no allocations.
2043
+ * See `@dogpile/sdk/runtime/metrics` for the interface.
2044
+ */
2045
+ readonly metricsHook?: MetricsHook;
2046
+ /**
2047
+ * Optional structured logger for SDK-internal diagnostics (hook errors and
2048
+ * future debug/info events). Implement against pino, winston, or any other
2049
+ * logger by satisfying the `Logger` interface from `@dogpile/sdk/runtime/logger`.
2050
+ * When absent, hook errors fall back to `console.error`.
2051
+ */
2052
+ readonly logger?: Logger;
1914
2053
  /**
1915
2054
  * Maximum coordinator → sub-run recursion depth ceiling.
1916
2055
  *
@@ -1927,6 +2066,14 @@ export interface EngineOptions {
1927
2066
  * call sites via {@link RunCallOptions.maxConcurrentChildren}.
1928
2067
  */
1929
2068
  readonly maxConcurrentChildren?: number;
2069
+ /**
2070
+ * Maximum agent model turns that may execute in parallel for shared,
2071
+ * broadcast, and coordinator worker fan-out.
2072
+ *
2073
+ * Defaults to 4. Per-run lowering happens at `engine.run` / `engine.stream`
2074
+ * call sites via {@link RunCallOptions.maxConcurrentAgentTurns}.
2075
+ */
2076
+ readonly maxConcurrentAgentTurns?: number;
1930
2077
  /**
1931
2078
  * Fallback timeout (milliseconds) applied to delegated sub-runs when neither
1932
2079
  * the parent's `budget.timeoutMs` nor the decision-level
@@ -1966,6 +2113,10 @@ export interface RunCallOptions {
1966
2113
  * ceiling.
1967
2114
  */
1968
2115
  readonly maxConcurrentChildren?: number;
2116
+ /**
2117
+ * Per-run agent-turn fan-out ceiling. Cannot raise the engine's ceiling.
2118
+ */
2119
+ readonly maxConcurrentAgentTurns?: number;
1969
2120
  /** Per-run child-failure behavior. Overrides the engine default. */
1970
2121
  readonly onChildFailure?: OnChildFailureMode;
1971
2122
  }