@dogpile/sdk 0.3.1 → 0.4.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.
- package/CHANGELOG.md +136 -0
- package/README.md +1 -0
- package/dist/browser/index.js +1595 -54
- package/dist/browser/index.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/providers/openai-compatible.d.ts +11 -0
- package/dist/providers/openai-compatible.d.ts.map +1 -1
- package/dist/providers/openai-compatible.js +87 -2
- package/dist/providers/openai-compatible.js.map +1 -1
- package/dist/runtime/cancellation.d.ts +26 -0
- package/dist/runtime/cancellation.d.ts.map +1 -1
- package/dist/runtime/cancellation.js +38 -1
- package/dist/runtime/cancellation.js.map +1 -1
- package/dist/runtime/coordinator.d.ts +74 -1
- package/dist/runtime/coordinator.d.ts.map +1 -1
- package/dist/runtime/coordinator.js +932 -25
- package/dist/runtime/coordinator.js.map +1 -1
- package/dist/runtime/decisions.d.ts +25 -3
- package/dist/runtime/decisions.d.ts.map +1 -1
- package/dist/runtime/decisions.js +241 -3
- package/dist/runtime/decisions.js.map +1 -1
- package/dist/runtime/defaults.d.ts +37 -1
- package/dist/runtime/defaults.d.ts.map +1 -1
- package/dist/runtime/defaults.js +347 -0
- package/dist/runtime/defaults.js.map +1 -1
- package/dist/runtime/engine.d.ts.map +1 -1
- package/dist/runtime/engine.js +254 -24
- package/dist/runtime/engine.js.map +1 -1
- package/dist/runtime/sequential.d.ts.map +1 -1
- package/dist/runtime/sequential.js +8 -1
- package/dist/runtime/sequential.js.map +1 -1
- package/dist/runtime/validation.d.ts +10 -0
- package/dist/runtime/validation.d.ts.map +1 -1
- package/dist/runtime/validation.js +73 -0
- package/dist/runtime/validation.js.map +1 -1
- package/dist/types/events.d.ts +329 -8
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/replay.d.ts +5 -1
- package/dist/types/replay.d.ts.map +1 -1
- package/dist/types.d.ts +131 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
- package/src/index.ts +10 -0
- package/src/providers/openai-compatible.ts +82 -3
- package/src/runtime/cancellation.ts +59 -1
- package/src/runtime/coordinator.ts +1170 -25
- package/src/runtime/decisions.ts +307 -4
- package/src/runtime/defaults.ts +376 -0
- package/src/runtime/engine.ts +363 -24
- package/src/runtime/sequential.ts +9 -1
- package/src/runtime/validation.ts +81 -0
- package/src/types/events.ts +359 -8
- package/src/types/replay.ts +12 -1
- package/src/types.ts +147 -3
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
|
|
18
18
|
const protocolNames = ["coordinator", "sequential", "broadcast", "shared"] as const;
|
|
19
19
|
const budgetTiers = ["fast", "balanced", "quality"] as const;
|
|
20
|
+
const onChildFailureModes = ["continue", "abort"] as const;
|
|
20
21
|
|
|
21
22
|
type ValidationRule =
|
|
22
23
|
| "required"
|
|
@@ -24,6 +25,7 @@ type ValidationRule =
|
|
|
24
25
|
| "finite-number"
|
|
25
26
|
| "non-negative-number"
|
|
26
27
|
| "positive-integer"
|
|
28
|
+
| "positive-finite-number"
|
|
27
29
|
| "non-negative-integer"
|
|
28
30
|
| "range"
|
|
29
31
|
| "enum"
|
|
@@ -69,12 +71,29 @@ export function validateDogpileOptions(options: DogpileOptions): void {
|
|
|
69
71
|
validateOptionalFunction(options.evaluate, "evaluate");
|
|
70
72
|
validateOptionalSeed(options.seed, "seed");
|
|
71
73
|
validateOptionalAbortSignal(options.signal, "signal");
|
|
74
|
+
validateOptionalNonNegativeInteger(options.maxDepth, "maxDepth");
|
|
75
|
+
validateOptionalPositiveInteger(options.maxConcurrentChildren, "maxConcurrentChildren");
|
|
76
|
+
validateOptionalPositiveFiniteNumber(options.defaultSubRunTimeoutMs, "defaultSubRunTimeoutMs");
|
|
77
|
+
validateOptionalOnChildFailure(options.onChildFailure, "onChildFailure");
|
|
72
78
|
}
|
|
73
79
|
|
|
74
80
|
export function validateMissionIntent(intent: unknown, path = "intent"): void {
|
|
75
81
|
validateNonEmptyString(intent, path, "intent is required.");
|
|
76
82
|
}
|
|
77
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Validate per-call run/stream options (`Engine.run(intent, options)` / `Engine.stream(...)`).
|
|
86
|
+
*/
|
|
87
|
+
export function validateRunCallOptions(options: unknown, path = "options"): void {
|
|
88
|
+
if (options === undefined) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const record = requireRecord(options, path);
|
|
92
|
+
validateOptionalNonNegativeInteger(record.maxDepth, `${path}.maxDepth`);
|
|
93
|
+
validateOptionalPositiveInteger(record.maxConcurrentChildren, `${path}.maxConcurrentChildren`);
|
|
94
|
+
validateOptionalOnChildFailure(record.onChildFailure, `${path}.onChildFailure`);
|
|
95
|
+
}
|
|
96
|
+
|
|
78
97
|
/**
|
|
79
98
|
* Validate low-level engine configuration before normalizing reusable controls.
|
|
80
99
|
*/
|
|
@@ -92,6 +111,10 @@ export function validateEngineOptions(options: EngineOptions): void {
|
|
|
92
111
|
validateOptionalFunction(options.evaluate, "evaluate");
|
|
93
112
|
validateOptionalSeed(options.seed, "seed");
|
|
94
113
|
validateOptionalAbortSignal(options.signal, "signal");
|
|
114
|
+
validateOptionalNonNegativeInteger(options.maxDepth, "maxDepth");
|
|
115
|
+
validateOptionalPositiveInteger(options.maxConcurrentChildren, "maxConcurrentChildren");
|
|
116
|
+
validateOptionalPositiveFiniteNumber(options.defaultSubRunTimeoutMs, "defaultSubRunTimeoutMs");
|
|
117
|
+
validateOptionalOnChildFailure(options.onChildFailure, "onChildFailure");
|
|
95
118
|
}
|
|
96
119
|
|
|
97
120
|
/**
|
|
@@ -195,6 +218,28 @@ function validateBudgetTier(value: BudgetTier, path: string): void {
|
|
|
195
218
|
}
|
|
196
219
|
}
|
|
197
220
|
|
|
221
|
+
function validateOptionalOnChildFailure(value: unknown, path: string): void {
|
|
222
|
+
if (value === undefined) {
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
if (value === "continue" || value === "abort") {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
throw new DogpileError({
|
|
229
|
+
code: "invalid-configuration",
|
|
230
|
+
message: `Invalid onChildFailure: expected "continue" or "abort", got ${JSON.stringify(value)}`,
|
|
231
|
+
retryable: false,
|
|
232
|
+
detail: {
|
|
233
|
+
kind: "configuration-validation",
|
|
234
|
+
path,
|
|
235
|
+
rule: "enum",
|
|
236
|
+
expected: onChildFailureModes.join(" | "),
|
|
237
|
+
received: describeValue(value),
|
|
238
|
+
reason: "invalid-on-child-failure"
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
|
|
198
243
|
/**
|
|
199
244
|
* Validate configured model provider definitions at registration boundaries.
|
|
200
245
|
*/
|
|
@@ -205,6 +250,27 @@ export function validateModelProviderRegistration(value: unknown, path = "model"
|
|
|
205
250
|
validateOptionalFunction(record.stream, `${path}.stream`);
|
|
206
251
|
}
|
|
207
252
|
|
|
253
|
+
/**
|
|
254
|
+
* Engine-time defense-in-depth check that a provider's optional
|
|
255
|
+
* `metadata.locality` is one of the two valid values when present (Phase 3 D-03).
|
|
256
|
+
* Catches user-implemented providers that bypass TypeScript checks.
|
|
257
|
+
*/
|
|
258
|
+
export function validateProviderLocality(
|
|
259
|
+
provider: ConfiguredModelProvider,
|
|
260
|
+
pathPrefix: string = "model"
|
|
261
|
+
): void {
|
|
262
|
+
const loc = provider.metadata?.locality;
|
|
263
|
+
if (loc !== undefined && loc !== "local" && loc !== "remote") {
|
|
264
|
+
invalidConfiguration({
|
|
265
|
+
path: `${pathPrefix}.metadata.locality`,
|
|
266
|
+
rule: "enum",
|
|
267
|
+
message: `${pathPrefix}.metadata.locality must be "local" or "remote" when provided.`,
|
|
268
|
+
expected: "\"local\" | \"remote\"",
|
|
269
|
+
actual: loc
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
208
274
|
function validateVercelAILanguageModel(value: unknown, path: string): void {
|
|
209
275
|
const record = requireRecord(value, path);
|
|
210
276
|
|
|
@@ -704,6 +770,21 @@ function validateOptionalNonNegativeInteger(value: unknown, path: string): void
|
|
|
704
770
|
}
|
|
705
771
|
}
|
|
706
772
|
|
|
773
|
+
function validateOptionalPositiveFiniteNumber(value: unknown, path: string): void {
|
|
774
|
+
if (value === undefined) {
|
|
775
|
+
return;
|
|
776
|
+
}
|
|
777
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
|
|
778
|
+
invalidConfiguration({
|
|
779
|
+
path,
|
|
780
|
+
rule: "positive-finite-number",
|
|
781
|
+
message: "value must be a positive finite number.",
|
|
782
|
+
expected: "finite number > 0",
|
|
783
|
+
actual: value
|
|
784
|
+
});
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
|
|
707
788
|
function validateOptionalNonNegativeNumber(value: unknown, path: string): void {
|
|
708
789
|
if (value === undefined) {
|
|
709
790
|
return;
|
package/src/types/events.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type {
|
|
2
|
+
BudgetCaps,
|
|
2
3
|
BudgetStopReason,
|
|
3
4
|
CostSummary,
|
|
4
5
|
JsonObject,
|
|
@@ -9,11 +10,14 @@ import type {
|
|
|
9
10
|
ModelResponse,
|
|
10
11
|
NormalizedQualityScore,
|
|
11
12
|
Protocol,
|
|
13
|
+
ProtocolName,
|
|
12
14
|
RunEvaluation,
|
|
15
|
+
RunResult,
|
|
13
16
|
RuntimeToolIdentity,
|
|
14
17
|
RuntimeToolPermission,
|
|
15
18
|
RuntimeToolResult,
|
|
16
|
-
TerminationStopRecord
|
|
19
|
+
TerminationStopRecord,
|
|
20
|
+
Trace
|
|
17
21
|
} from "../types.js";
|
|
18
22
|
|
|
19
23
|
|
|
@@ -39,6 +43,8 @@ export interface RoleAssignmentEvent {
|
|
|
39
43
|
readonly type: "role-assignment";
|
|
40
44
|
/** Stable run id shared by all events in one workflow. */
|
|
41
45
|
readonly runId: string;
|
|
46
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
47
|
+
readonly parentRunIds?: readonly string[];
|
|
42
48
|
/** ISO-8601 event timestamp. */
|
|
43
49
|
readonly at: string;
|
|
44
50
|
/** Agent receiving the role assignment. */
|
|
@@ -63,6 +69,8 @@ export interface ModelRequestEvent {
|
|
|
63
69
|
readonly type: "model-request";
|
|
64
70
|
/** Stable run id shared by all events in one workflow. */
|
|
65
71
|
readonly runId: string;
|
|
72
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
73
|
+
readonly parentRunIds?: readonly string[];
|
|
66
74
|
/** ISO-8601 event timestamp. */
|
|
67
75
|
readonly at: string;
|
|
68
76
|
/** Stable provider call id within the run. */
|
|
@@ -91,6 +99,8 @@ export interface ModelResponseEvent {
|
|
|
91
99
|
readonly type: "model-response";
|
|
92
100
|
/** Stable run id shared by all events in one workflow. */
|
|
93
101
|
readonly runId: string;
|
|
102
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
103
|
+
readonly parentRunIds?: readonly string[];
|
|
94
104
|
/** ISO-8601 event timestamp. */
|
|
95
105
|
readonly at: string;
|
|
96
106
|
/** Stable provider call id within the run. */
|
|
@@ -131,6 +141,8 @@ export interface ModelOutputChunkEvent {
|
|
|
131
141
|
readonly type: "model-output-chunk";
|
|
132
142
|
/** Stable run id shared by all events in one workflow. */
|
|
133
143
|
readonly runId: string;
|
|
144
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
145
|
+
readonly parentRunIds?: readonly string[];
|
|
134
146
|
/** ISO-8601 event timestamp. */
|
|
135
147
|
readonly at: string;
|
|
136
148
|
/** Agent currently producing output. */
|
|
@@ -160,6 +172,8 @@ export interface ToolCallEvent {
|
|
|
160
172
|
readonly type: "tool-call";
|
|
161
173
|
/** Stable run id shared by all events in one workflow. */
|
|
162
174
|
readonly runId: string;
|
|
175
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
176
|
+
readonly parentRunIds?: readonly string[];
|
|
163
177
|
/** ISO-8601 event timestamp. */
|
|
164
178
|
readonly at: string;
|
|
165
179
|
/** Stable tool call id within the run. */
|
|
@@ -187,6 +201,8 @@ export interface ToolResultEvent {
|
|
|
187
201
|
readonly type: "tool-result";
|
|
188
202
|
/** Stable run id shared by all events in one workflow. */
|
|
189
203
|
readonly runId: string;
|
|
204
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
205
|
+
readonly parentRunIds?: readonly string[];
|
|
190
206
|
/** ISO-8601 event timestamp. */
|
|
191
207
|
readonly at: string;
|
|
192
208
|
/** Stable tool call id within the run. */
|
|
@@ -211,7 +227,9 @@ export interface ToolResultEvent {
|
|
|
211
227
|
* metadata so reproduction harnesses can distinguish contribution from
|
|
212
228
|
* voluntary abstention without reparsing raw text.
|
|
213
229
|
*/
|
|
214
|
-
export interface
|
|
230
|
+
export interface ParticipateAgentDecision {
|
|
231
|
+
/** Discriminant marking this as a participate-style decision. */
|
|
232
|
+
readonly type: "participate";
|
|
215
233
|
/** Task-specific role selected by the agent for this turn. */
|
|
216
234
|
readonly selectedRole: string;
|
|
217
235
|
/** Whether the agent contributed or voluntarily abstained. */
|
|
@@ -222,6 +240,46 @@ export interface AgentDecision {
|
|
|
222
240
|
readonly contribution: string;
|
|
223
241
|
}
|
|
224
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Decision emitted by a coordinator agent that delegates a sub-mission to a
|
|
245
|
+
* coordination protocol rather than contributing directly. The runtime
|
|
246
|
+
* dispatches a child run when this decision is returned.
|
|
247
|
+
*/
|
|
248
|
+
export interface DelegateAgentDecision {
|
|
249
|
+
/** Discriminant marking this as a delegate-style decision. */
|
|
250
|
+
readonly type: "delegate";
|
|
251
|
+
/** Coordination protocol the child sub-run will execute. */
|
|
252
|
+
readonly protocol: ProtocolName;
|
|
253
|
+
/** Mission text passed to the child sub-run. */
|
|
254
|
+
readonly intent: string;
|
|
255
|
+
/**
|
|
256
|
+
* Optional model provider id assertion. When set, the runtime requires the
|
|
257
|
+
* value to match the parent's `ConfiguredModelProvider.id` (D-11) — child
|
|
258
|
+
* runs always inherit the parent provider instance verbatim.
|
|
259
|
+
*/
|
|
260
|
+
readonly model?: string;
|
|
261
|
+
/** Optional per-decision budget caps applied to the child run. */
|
|
262
|
+
readonly budget?: BudgetCaps;
|
|
263
|
+
/**
|
|
264
|
+
* Optional per-decision child concurrency ceiling. This can only lower the
|
|
265
|
+
* engine/run effective max for the current coordinator fan-out turn (D-05).
|
|
266
|
+
*/
|
|
267
|
+
readonly maxConcurrentChildren?: number;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Discriminated union of structured agent decisions parsed from model output.
|
|
272
|
+
*
|
|
273
|
+
* - `participate`: paper-style turn contribution; carries the four labeled
|
|
274
|
+
* fields (`selectedRole`, `participation`, `rationale`, `contribution`).
|
|
275
|
+
* - `delegate`: coordinator-only delegation to a child sub-run. The runtime
|
|
276
|
+
* dispatches a sub-mission when this branch is returned.
|
|
277
|
+
*
|
|
278
|
+
* Consumers MUST narrow on `decision.type === "participate"` before reading
|
|
279
|
+
* paper-style fields.
|
|
280
|
+
*/
|
|
281
|
+
export type AgentDecision = ParticipateAgentDecision | DelegateAgentDecision;
|
|
282
|
+
|
|
225
283
|
/**
|
|
226
284
|
* Agent participation state for a paper-style turn decision.
|
|
227
285
|
*/
|
|
@@ -256,6 +314,8 @@ export interface TurnEvent {
|
|
|
256
314
|
readonly type: "agent-turn";
|
|
257
315
|
/** Stable run id shared by all events in one workflow. */
|
|
258
316
|
readonly runId: string;
|
|
317
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
318
|
+
readonly parentRunIds?: readonly string[];
|
|
259
319
|
/** ISO-8601 event timestamp. */
|
|
260
320
|
readonly at: string;
|
|
261
321
|
/** Agent that produced this turn. */
|
|
@@ -267,7 +327,7 @@ export interface TurnEvent {
|
|
|
267
327
|
/** Model output produced by the agent. */
|
|
268
328
|
readonly output: string;
|
|
269
329
|
/** Optional structured role/participation decision parsed from model output. */
|
|
270
|
-
readonly decision?: AgentDecision;
|
|
330
|
+
readonly decision?: AgentDecision | readonly DelegateAgentDecision[];
|
|
271
331
|
/** Cumulative cost after this turn. */
|
|
272
332
|
readonly cost: CostSummary;
|
|
273
333
|
}
|
|
@@ -296,7 +356,7 @@ export interface BroadcastContribution {
|
|
|
296
356
|
/** Independent model output produced for the shared mission. */
|
|
297
357
|
readonly output: string;
|
|
298
358
|
/** Optional structured role/participation decision parsed from model output. */
|
|
299
|
-
readonly decision?: AgentDecision;
|
|
359
|
+
readonly decision?: AgentDecision | readonly DelegateAgentDecision[];
|
|
300
360
|
}
|
|
301
361
|
|
|
302
362
|
/**
|
|
@@ -323,6 +383,8 @@ export interface BroadcastEvent {
|
|
|
323
383
|
readonly type: "broadcast";
|
|
324
384
|
/** Stable run id shared by all events in one workflow. */
|
|
325
385
|
readonly runId: string;
|
|
386
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
387
|
+
readonly parentRunIds?: readonly string[];
|
|
326
388
|
/** ISO-8601 event timestamp. */
|
|
327
389
|
readonly at: string;
|
|
328
390
|
/** One-based broadcast round number. */
|
|
@@ -346,6 +408,8 @@ export interface BudgetStopEvent {
|
|
|
346
408
|
readonly type: "budget-stop";
|
|
347
409
|
/** Stable run id shared by all events in one workflow. */
|
|
348
410
|
readonly runId: string;
|
|
411
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
412
|
+
readonly parentRunIds?: readonly string[];
|
|
349
413
|
/** ISO-8601 event timestamp. */
|
|
350
414
|
readonly at: string;
|
|
351
415
|
/** Normalized machine-readable budget stop reason. */
|
|
@@ -418,6 +482,259 @@ export interface FinalEvent {
|
|
|
418
482
|
readonly termination?: TerminationStopRecord;
|
|
419
483
|
}
|
|
420
484
|
|
|
485
|
+
/**
|
|
486
|
+
* Event emitted when the coordinator dispatches a delegated sub-run.
|
|
487
|
+
*
|
|
488
|
+
* @remarks
|
|
489
|
+
* Recorded immediately before the child run starts executing. Carries the
|
|
490
|
+
* child's run id, the parent decision id that triggered the dispatch, and the
|
|
491
|
+
* resolved protocol/intent/depth. The `recursive` flag marks the diagnostic
|
|
492
|
+
* case where a coordinator delegates to another coordinator (D-16).
|
|
493
|
+
*
|
|
494
|
+
* The event's `runId` is the PARENT run id, matching the existing trace
|
|
495
|
+
* convention; `parentRunId` duplicates it for explicit cross-reference.
|
|
496
|
+
*/
|
|
497
|
+
export interface SubRunStartedEvent {
|
|
498
|
+
/** Discriminant for event rendering and exhaustive switches. */
|
|
499
|
+
readonly type: "sub-run-started";
|
|
500
|
+
/** Parent run id; matches the surrounding trace runId. */
|
|
501
|
+
readonly runId: string;
|
|
502
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
503
|
+
readonly parentRunIds?: readonly string[];
|
|
504
|
+
/** ISO-8601 event timestamp. */
|
|
505
|
+
readonly at: string;
|
|
506
|
+
/** Child run id assigned to the dispatched sub-run. */
|
|
507
|
+
readonly childRunId: string;
|
|
508
|
+
/** Parent run id (duplicates `runId` for explicit cross-reference). */
|
|
509
|
+
readonly parentRunId: string;
|
|
510
|
+
/** Replay decision id of the parent decision that triggered this sub-run. */
|
|
511
|
+
readonly parentDecisionId: string;
|
|
512
|
+
/**
|
|
513
|
+
* 0-indexed position of this delegate within the fan-out array of its
|
|
514
|
+
* originating coordinator plan-turn (Phase 3 D-10). Single-delegate turns
|
|
515
|
+
* use `0` for backward compatibility. Together with `parentDecisionId`, this
|
|
516
|
+
* uniquely identifies the delegate within a fan-out.
|
|
517
|
+
*/
|
|
518
|
+
readonly parentDecisionArrayIndex: number;
|
|
519
|
+
/** Coordination protocol the child run will execute. */
|
|
520
|
+
readonly protocol: ProtocolName;
|
|
521
|
+
/** Mission intent passed to the child run. */
|
|
522
|
+
readonly intent: string;
|
|
523
|
+
/** Recursion depth of the child run (1 for first-level sub-run). */
|
|
524
|
+
readonly depth: number;
|
|
525
|
+
/**
|
|
526
|
+
* Diagnostic flag set when a coordinator delegates to another coordinator
|
|
527
|
+
* (parent protocol === "coordinator" and child protocol === "coordinator").
|
|
528
|
+
*/
|
|
529
|
+
readonly recursive?: boolean;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Event emitted when a delegated sub-run completes successfully.
|
|
534
|
+
*
|
|
535
|
+
* @remarks
|
|
536
|
+
* Carries the full {@link RunResult} as `subResult`, including the embedded
|
|
537
|
+
* child {@link Trace}. Replay walks the parent event sequence and recurses on
|
|
538
|
+
* `subResult.trace` to rehydrate sub-run accounting without re-invoking the
|
|
539
|
+
* provider (D-08).
|
|
540
|
+
*/
|
|
541
|
+
export interface SubRunCompletedEvent {
|
|
542
|
+
/** Discriminant for event rendering and exhaustive switches. */
|
|
543
|
+
readonly type: "sub-run-completed";
|
|
544
|
+
/** Parent run id; matches the surrounding trace runId. */
|
|
545
|
+
readonly runId: string;
|
|
546
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
547
|
+
readonly parentRunIds?: readonly string[];
|
|
548
|
+
/** ISO-8601 event timestamp. */
|
|
549
|
+
readonly at: string;
|
|
550
|
+
/** Child run id that produced this result. */
|
|
551
|
+
readonly childRunId: string;
|
|
552
|
+
/** Parent run id (duplicates `runId` for explicit cross-reference). */
|
|
553
|
+
readonly parentRunId: string;
|
|
554
|
+
/** Replay decision id of the parent decision that triggered the sub-run. */
|
|
555
|
+
readonly parentDecisionId: string;
|
|
556
|
+
/**
|
|
557
|
+
* 0-indexed position of this delegate within the fan-out array of its
|
|
558
|
+
* originating coordinator plan-turn (Phase 3 D-10). Single-delegate turns
|
|
559
|
+
* use `0` for backward compatibility. Together with `parentDecisionId`, this
|
|
560
|
+
* uniquely identifies the delegate within a fan-out.
|
|
561
|
+
*/
|
|
562
|
+
readonly parentDecisionArrayIndex: number;
|
|
563
|
+
/** Full child {@link RunResult}, including the embedded child {@link Trace}. */
|
|
564
|
+
readonly subResult: RunResult;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
/**
|
|
568
|
+
* Event emitted when a delegated sub-run fails before completion.
|
|
569
|
+
*
|
|
570
|
+
* @remarks
|
|
571
|
+
* Captures a structured `error` plus the partial {@link Trace} accumulated
|
|
572
|
+
* before failure. The same `Trace` shape used by completed runs is preserved
|
|
573
|
+
* — consumers can replay or inspect the partial child events without bespoke
|
|
574
|
+
* deserialization logic.
|
|
575
|
+
*/
|
|
576
|
+
export interface SubRunFailedEvent {
|
|
577
|
+
/** Discriminant for event rendering and exhaustive switches. */
|
|
578
|
+
readonly type: "sub-run-failed";
|
|
579
|
+
/** Parent run id; matches the surrounding trace runId. */
|
|
580
|
+
readonly runId: string;
|
|
581
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
582
|
+
readonly parentRunIds?: readonly string[];
|
|
583
|
+
/** ISO-8601 event timestamp. */
|
|
584
|
+
readonly at: string;
|
|
585
|
+
/** Child run id that failed. */
|
|
586
|
+
readonly childRunId: string;
|
|
587
|
+
/** Parent run id (duplicates `runId` for explicit cross-reference). */
|
|
588
|
+
readonly parentRunId: string;
|
|
589
|
+
/** Replay decision id of the parent decision that triggered the sub-run. */
|
|
590
|
+
readonly parentDecisionId: string;
|
|
591
|
+
/**
|
|
592
|
+
* 0-indexed position of this delegate within the fan-out array of its
|
|
593
|
+
* originating coordinator plan-turn (Phase 3 D-10). Single-delegate turns
|
|
594
|
+
* use `0` for backward compatibility. Together with `parentDecisionId`, this
|
|
595
|
+
* uniquely identifies the delegate within a fan-out.
|
|
596
|
+
*/
|
|
597
|
+
readonly parentDecisionArrayIndex: number;
|
|
598
|
+
/** Structured failure description. */
|
|
599
|
+
readonly error: {
|
|
600
|
+
/** Stable error code (matches DogpileError code shape). */
|
|
601
|
+
readonly code: string;
|
|
602
|
+
/** Human-readable failure description. */
|
|
603
|
+
readonly message: string;
|
|
604
|
+
/** Provider id when the failure originated in a model call. */
|
|
605
|
+
readonly providerId?: string;
|
|
606
|
+
/** Optional structured detail (e.g., the failed delegate decision payload). */
|
|
607
|
+
readonly detail?: JsonObject;
|
|
608
|
+
};
|
|
609
|
+
/** Partial child {@link Trace} accumulated up to the failure point. */
|
|
610
|
+
readonly partialTrace: Trace;
|
|
611
|
+
/**
|
|
612
|
+
* Cost from provider calls completed before the child threw (BUDGET-03 / D-02).
|
|
613
|
+
*
|
|
614
|
+
* Equals `lastCostBearingEventCost(partialTrace.events) ?? emptyCost()`. The
|
|
615
|
+
* parent rolls this into its own `accounting.cost` so failed children
|
|
616
|
+
* contribute their real wallet spend.
|
|
617
|
+
*/
|
|
618
|
+
readonly partialCost: CostSummary;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Event emitted when the parent's `signal` aborts AFTER a sub-run has already
|
|
623
|
+
* completed successfully but BEFORE the parent advances to its next coordinator
|
|
624
|
+
* turn (BUDGET-01 / D-10).
|
|
625
|
+
*
|
|
626
|
+
* @remarks
|
|
627
|
+
* Provides replay/streaming provenance for "parent gave up after a successful
|
|
628
|
+
* child finished." The marker is observable on `Dogpile.stream()` subscribers
|
|
629
|
+
* before the run errors with `code: "aborted"`. Non-streaming `run()` rejects
|
|
630
|
+
* with the abort error and does NOT expose the marker — `engine.ts` does not
|
|
631
|
+
* attach the parent events array to the rejected error (verified at
|
|
632
|
+
* `engine.ts:230-239`). Streaming-subscriber observability is the contract.
|
|
633
|
+
*/
|
|
634
|
+
export interface SubRunParentAbortedEvent {
|
|
635
|
+
/** Discriminant for event rendering and exhaustive switches. */
|
|
636
|
+
readonly type: "sub-run-parent-aborted";
|
|
637
|
+
/** Parent run id; matches the surrounding trace runId. */
|
|
638
|
+
readonly runId: string;
|
|
639
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
640
|
+
readonly parentRunIds?: readonly string[];
|
|
641
|
+
/** ISO-8601 event timestamp. */
|
|
642
|
+
readonly at: string;
|
|
643
|
+
/** Most-recent completed child run id whose completion preceded the abort. */
|
|
644
|
+
readonly childRunId: string;
|
|
645
|
+
/** Parent run id (duplicates `runId` for explicit cross-reference). */
|
|
646
|
+
readonly parentRunId: string;
|
|
647
|
+
/** Discriminator (currently always "parent-aborted"; reserved for future variants). */
|
|
648
|
+
readonly reason: "parent-aborted";
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Event emitted when a delegated sub-run's requested `budget.timeoutMs`
|
|
653
|
+
* exceeds the parent's remaining deadline and is therefore clamped to the
|
|
654
|
+
* parent's remaining time (BUDGET-02 / D-12).
|
|
655
|
+
*
|
|
656
|
+
* @remarks
|
|
657
|
+
* Emitted on the parent trace BEFORE `sub-run-started`. When the requested
|
|
658
|
+
* decision-level timeout fits within the parent's remaining deadline, the
|
|
659
|
+
* event is NOT emitted (zero-overhead happy path). The parent's deadline is
|
|
660
|
+
* a hard ceiling for the whole tree, so any decision-level override that
|
|
661
|
+
* exceeds it is silently clamped rather than throwing — recording the
|
|
662
|
+
* requested-vs-clamped pair on the trace preserves provenance for replay.
|
|
663
|
+
*/
|
|
664
|
+
export interface SubRunBudgetClampedEvent {
|
|
665
|
+
/** Discriminant for event rendering and exhaustive switches. */
|
|
666
|
+
readonly type: "sub-run-budget-clamped";
|
|
667
|
+
/** Parent run id; matches the surrounding trace runId. */
|
|
668
|
+
readonly runId: string;
|
|
669
|
+
/** Root-first ancestry chain when bubbled through a parent stream. */
|
|
670
|
+
readonly parentRunIds?: readonly string[];
|
|
671
|
+
/** ISO-8601 event timestamp. */
|
|
672
|
+
readonly at: string;
|
|
673
|
+
/** Child run id whose budget was clamped. */
|
|
674
|
+
readonly childRunId: string;
|
|
675
|
+
/** Parent run id (duplicates `runId` for explicit cross-reference). */
|
|
676
|
+
readonly parentRunId: string;
|
|
677
|
+
/** Replay decision id of the parent decision that triggered the sub-run. */
|
|
678
|
+
readonly parentDecisionId: string;
|
|
679
|
+
/** The decision's originally requested `budget.timeoutMs` value (milliseconds). */
|
|
680
|
+
readonly requestedTimeoutMs: number;
|
|
681
|
+
/** The clamped child timeout actually applied (parent's remaining deadline, in milliseconds). */
|
|
682
|
+
readonly clampedTimeoutMs: number;
|
|
683
|
+
/** Discriminator for the clamp cause (currently always "exceeded-parent-remaining"). */
|
|
684
|
+
readonly reason: "exceeded-parent-remaining";
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Event emitted when a delegated sub-run is enqueued because the
|
|
689
|
+
* coordinator's effective `maxConcurrentChildren` budget is fully in flight
|
|
690
|
+
* (Phase 3 D-07). Emitted ONLY when the slot is not immediately free —
|
|
691
|
+
* no-pressure runs do NOT emit this event.
|
|
692
|
+
*
|
|
693
|
+
* Three-event timeline under pressure: sub-run-queued → sub-run-started →
|
|
694
|
+
* sub-run-completed (or sub-run-failed). Without pressure: sub-run-started
|
|
695
|
+
* → completion (no queued event).
|
|
696
|
+
*/
|
|
697
|
+
export interface SubRunQueuedEvent {
|
|
698
|
+
readonly type: "sub-run-queued";
|
|
699
|
+
readonly runId: string;
|
|
700
|
+
readonly parentRunIds?: readonly string[];
|
|
701
|
+
readonly at: string;
|
|
702
|
+
readonly childRunId: string;
|
|
703
|
+
readonly parentRunId: string;
|
|
704
|
+
readonly parentDecisionId: string;
|
|
705
|
+
readonly parentDecisionArrayIndex: number;
|
|
706
|
+
readonly protocol: ProtocolName;
|
|
707
|
+
readonly intent: string;
|
|
708
|
+
readonly depth: number;
|
|
709
|
+
readonly queuePosition: number;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* Event emitted ONCE per run when the runtime detects a `"local"` provider
|
|
714
|
+
* in the coordinator's active tree and clamps `maxConcurrentChildren` to 1
|
|
715
|
+
* (Phase 3 CONCURRENCY-02 / D-12). Emitted at the FIRST delegate dispatch
|
|
716
|
+
* where the local-provider check trips. Subsequent dispatches in the same
|
|
717
|
+
* run do NOT re-emit. Runs with no delegates, or runs with delegates but
|
|
718
|
+
* no local provider, never emit this event.
|
|
719
|
+
*
|
|
720
|
+
* The clamp is silent (no throw, no console output) per D-13 — this event
|
|
721
|
+
* IS the warning surface; subscribers can react via the engine's `emit`
|
|
722
|
+
* callback.
|
|
723
|
+
*/
|
|
724
|
+
export interface SubRunConcurrencyClampedEvent {
|
|
725
|
+
readonly type: "sub-run-concurrency-clamped";
|
|
726
|
+
readonly runId: string;
|
|
727
|
+
readonly parentRunIds?: readonly string[];
|
|
728
|
+
readonly at: string;
|
|
729
|
+
/** The pre-clamp effective max that would have applied (engine/run/decision min). */
|
|
730
|
+
readonly requestedMax: number;
|
|
731
|
+
/** Always 1 — locality-clamp is a fixed cap. */
|
|
732
|
+
readonly effectiveMax: 1;
|
|
733
|
+
readonly reason: "local-provider-detected";
|
|
734
|
+
/** Stable id of the FIRST local provider found during the active-tree walk. */
|
|
735
|
+
readonly providerId: string;
|
|
736
|
+
}
|
|
737
|
+
|
|
421
738
|
/**
|
|
422
739
|
* Successful coordination event emitted by Dogpile and persisted in traces.
|
|
423
740
|
*
|
|
@@ -434,6 +751,11 @@ export interface FinalEvent {
|
|
|
434
751
|
* - `tool-result`: one runtime tool invocation completed.
|
|
435
752
|
* - `agent-turn`: one agent completed a prompt/response turn.
|
|
436
753
|
* - `broadcast`: a broadcast round gathered independent contributions.
|
|
754
|
+
* - `sub-run-started`: a delegated sub-run was dispatched.
|
|
755
|
+
* - `sub-run-completed`: a delegated sub-run completed and embedded its full result.
|
|
756
|
+
* - `sub-run-failed`: a delegated sub-run failed before completion.
|
|
757
|
+
* - `sub-run-queued`: a delegated sub-run waited for a concurrency slot.
|
|
758
|
+
* - `sub-run-concurrency-clamped`: a local provider forced child concurrency to 1.
|
|
437
759
|
* - `budget-stop`: a configured budget cap halted further model turns.
|
|
438
760
|
* - `final`: the run completed and produced the final output.
|
|
439
761
|
*
|
|
@@ -464,6 +786,13 @@ export type RunEvent =
|
|
|
464
786
|
| ToolResultEvent
|
|
465
787
|
| TurnEvent
|
|
466
788
|
| BroadcastEvent
|
|
789
|
+
| SubRunStartedEvent
|
|
790
|
+
| SubRunCompletedEvent
|
|
791
|
+
| SubRunFailedEvent
|
|
792
|
+
| SubRunParentAbortedEvent
|
|
793
|
+
| SubRunBudgetClampedEvent
|
|
794
|
+
| SubRunQueuedEvent
|
|
795
|
+
| SubRunConcurrencyClampedEvent
|
|
467
796
|
| BudgetStopEvent
|
|
468
797
|
| FinalEvent;
|
|
469
798
|
|
|
@@ -483,10 +812,33 @@ export type ToolActivityEvent = ToolCallEvent | ToolResultEvent;
|
|
|
483
812
|
* Lifecycle event yielded by `stream()`.
|
|
484
813
|
*
|
|
485
814
|
* These events describe workflow coordination state rather than model text.
|
|
486
|
-
* Role assignment establishes the participant roster,
|
|
487
|
-
*
|
|
815
|
+
* Role assignment establishes the participant roster, `budget-stop` records a
|
|
816
|
+
* lifecycle halt before the terminal completion event, and the `sub-run-*`
|
|
817
|
+
* variants surface delegated child-run dispatch boundaries.
|
|
488
818
|
*/
|
|
489
|
-
export type StreamLifecycleEvent =
|
|
819
|
+
export type StreamLifecycleEvent =
|
|
820
|
+
| RoleAssignmentEvent
|
|
821
|
+
| BudgetStopEvent
|
|
822
|
+
| SubRunStartedEvent
|
|
823
|
+
| SubRunCompletedEvent
|
|
824
|
+
| SubRunFailedEvent
|
|
825
|
+
| SubRunParentAbortedEvent
|
|
826
|
+
| SubRunBudgetClampedEvent
|
|
827
|
+
| SubRunQueuedEvent
|
|
828
|
+
| SubRunConcurrencyClampedEvent
|
|
829
|
+
| AbortedEvent;
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Lifecycle event yielded by `stream()` when a run is aborted.
|
|
833
|
+
*/
|
|
834
|
+
export interface AbortedEvent {
|
|
835
|
+
readonly type: "aborted";
|
|
836
|
+
readonly runId: string;
|
|
837
|
+
readonly at: string;
|
|
838
|
+
readonly reason: "parent-aborted" | "timeout";
|
|
839
|
+
readonly detail?: JsonObject;
|
|
840
|
+
readonly parentRunIds?: readonly string[];
|
|
841
|
+
}
|
|
490
842
|
|
|
491
843
|
/**
|
|
492
844
|
* Output event yielded by `stream()`.
|
|
@@ -541,4 +893,3 @@ export type StreamCompletionEvent = FinalEvent;
|
|
|
541
893
|
* {@link RunResult} trace to return.
|
|
542
894
|
*/
|
|
543
895
|
export type StreamEvent = StreamLifecycleEvent | StreamOutputEvent | StreamErrorEvent | StreamCompletionEvent;
|
|
544
|
-
|
package/src/types/replay.ts
CHANGED
|
@@ -110,7 +110,14 @@ export type ReplayTraceProtocolDecisionType =
|
|
|
110
110
|
| "complete-tool-call"
|
|
111
111
|
| "collect-broadcast-round"
|
|
112
112
|
| "stop-for-budget"
|
|
113
|
-
| "finalize-output"
|
|
113
|
+
| "finalize-output"
|
|
114
|
+
| "start-sub-run"
|
|
115
|
+
| "complete-sub-run"
|
|
116
|
+
| "fail-sub-run"
|
|
117
|
+
| "mark-sub-run-parent-aborted"
|
|
118
|
+
| "mark-sub-run-budget-clamped"
|
|
119
|
+
| "queue-sub-run"
|
|
120
|
+
| "mark-sub-run-concurrency-clamped";
|
|
114
121
|
|
|
115
122
|
/**
|
|
116
123
|
* Protocol-level decision appended during execution.
|
|
@@ -136,6 +143,10 @@ export interface ReplayTraceProtocolDecision {
|
|
|
136
143
|
readonly callId?: string;
|
|
137
144
|
/** Provider involved in the decision, when model-scoped. */
|
|
138
145
|
readonly providerId?: string;
|
|
146
|
+
/** Child run involved in a delegated sub-run decision. */
|
|
147
|
+
readonly childRunId?: string;
|
|
148
|
+
/** FIFO queue position for sub-run queue decisions. */
|
|
149
|
+
readonly queuePosition?: number;
|
|
139
150
|
/** Tool call involved in the decision, when tool-scoped. */
|
|
140
151
|
readonly toolCallId?: string;
|
|
141
152
|
/** Tool identity involved in the decision, when tool-scoped. */
|