@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,355 @@
1
+ import type {
2
+ AgentDecision,
3
+ DelegateAgentDecision,
4
+ JsonObject,
5
+ ModelRequest,
6
+ ModelResponse,
7
+ ReplayTraceProtocolDecision,
8
+ ReplayTraceProviderCall,
9
+ RunEvent,
10
+ RunEventLog,
11
+ RunResult,
12
+ RuntimeToolExecutionRequest,
13
+ RuntimeToolResult,
14
+ Trace,
15
+ TranscriptEntry,
16
+ TranscriptToolCall
17
+ } from "../types.js";
18
+
19
+ export interface TraceRedactionOptions {
20
+ readonly replacementText?: string;
21
+ readonly redactPrompts?: boolean;
22
+ readonly redactOutputs?: boolean;
23
+ readonly redactToolInputs?: boolean;
24
+ readonly redactToolOutputs?: boolean;
25
+ readonly redactProviderResponses?: boolean;
26
+ readonly redactEmbeddedChildTraces?: boolean;
27
+ }
28
+
29
+ const DEFAULT_REPLACEMENT_TEXT = "[REDACTED]";
30
+ const REDACTED_JSON_OBJECT: JsonObject = { redacted: true };
31
+
32
+ export function redactTrace(trace: Trace, options: TraceRedactionOptions = {}): Trace {
33
+ return {
34
+ ...trace,
35
+ inputs: shouldRedactPrompts(options)
36
+ ? {
37
+ ...trace.inputs,
38
+ intent: replacement(options)
39
+ }
40
+ : trace.inputs,
41
+ protocolDecisions: trace.protocolDecisions.map((decision) => redactProtocolDecision(decision, options)),
42
+ providerCalls: trace.providerCalls.map((call) => redactProviderCall(call, options)),
43
+ finalOutput: shouldRedactOutputs(options)
44
+ ? {
45
+ ...trace.finalOutput,
46
+ output: replacement(options)
47
+ }
48
+ : trace.finalOutput,
49
+ events: trace.events.map((event) => redactRunEvent(event, options)),
50
+ transcript: trace.transcript.map((entry) => redactTranscriptEntry(entry, options))
51
+ };
52
+ }
53
+
54
+ export function redactRunResult(result: RunResult, options: TraceRedactionOptions = {}): RunResult {
55
+ const trace = redactTrace(result.trace, options);
56
+ const eventLog: RunEventLog = {
57
+ ...result.eventLog,
58
+ events: trace.events,
59
+ eventTypes: trace.events.map((event) => event.type),
60
+ eventCount: trace.events.length
61
+ };
62
+
63
+ return {
64
+ ...result,
65
+ output: shouldRedactOutputs(options) ? replacement(options) : result.output,
66
+ eventLog,
67
+ trace,
68
+ transcript: trace.transcript
69
+ };
70
+ }
71
+
72
+ function redactRunEvent(event: RunEvent, options: TraceRedactionOptions): RunEvent {
73
+ switch (event.type) {
74
+ case "model-request":
75
+ return {
76
+ ...event,
77
+ request: redactModelRequest(event.request, options)
78
+ };
79
+ case "model-response":
80
+ return {
81
+ ...event,
82
+ response: redactModelResponse(event.response, options)
83
+ };
84
+ case "model-output-chunk":
85
+ return shouldRedactOutputs(options)
86
+ ? {
87
+ ...event,
88
+ text: replacement(options),
89
+ outputLength: 0
90
+ }
91
+ : event;
92
+ case "tool-call":
93
+ return shouldRedactToolInputs(options)
94
+ ? {
95
+ ...event,
96
+ input: REDACTED_JSON_OBJECT
97
+ }
98
+ : event;
99
+ case "tool-result":
100
+ return {
101
+ ...event,
102
+ result: redactRuntimeToolResult(event.result, options)
103
+ };
104
+ case "agent-turn":
105
+ return {
106
+ ...event,
107
+ ...(shouldRedactPrompts(options) ? { input: replacement(options) } : {}),
108
+ ...(shouldRedactOutputs(options) ? { output: replacement(options) } : {}),
109
+ ...(event.decision !== undefined ? { decision: redactDecision(event.decision, options) } : {})
110
+ };
111
+ case "broadcast":
112
+ return {
113
+ ...event,
114
+ contributions: event.contributions.map((contribution) => ({
115
+ ...contribution,
116
+ ...(shouldRedactOutputs(options) ? { output: replacement(options) } : {}),
117
+ ...(contribution.decision !== undefined
118
+ ? { decision: redactDecision(contribution.decision, options) }
119
+ : {})
120
+ }))
121
+ };
122
+ case "sub-run-completed":
123
+ return shouldRedactEmbeddedChildTraces(options)
124
+ ? {
125
+ ...event,
126
+ subResult: redactRunResult(event.subResult, options)
127
+ }
128
+ : event;
129
+ case "sub-run-failed":
130
+ return shouldRedactEmbeddedChildTraces(options)
131
+ ? {
132
+ ...event,
133
+ error: {
134
+ ...event.error,
135
+ ...(event.error.detail !== undefined
136
+ ? { detail: redactErrorDetail(event.error.detail, options) }
137
+ : {})
138
+ },
139
+ partialTrace: redactTrace(event.partialTrace, options)
140
+ }
141
+ : event;
142
+ case "final":
143
+ return shouldRedactOutputs(options)
144
+ ? {
145
+ ...event,
146
+ output: replacement(options)
147
+ }
148
+ : event;
149
+ case "role-assignment":
150
+ case "budget-stop":
151
+ case "sub-run-started":
152
+ case "sub-run-parent-aborted":
153
+ case "sub-run-budget-clamped":
154
+ case "sub-run-queued":
155
+ case "sub-run-concurrency-clamped":
156
+ return event;
157
+ }
158
+ }
159
+
160
+ function redactProviderCall(
161
+ call: ReplayTraceProviderCall,
162
+ options: TraceRedactionOptions
163
+ ): ReplayTraceProviderCall {
164
+ return {
165
+ ...call,
166
+ request: redactModelRequest(call.request, options),
167
+ response: redactModelResponse(call.response, options)
168
+ };
169
+ }
170
+
171
+ function redactProtocolDecision(
172
+ decision: ReplayTraceProtocolDecision,
173
+ options: TraceRedactionOptions
174
+ ): ReplayTraceProtocolDecision {
175
+ return {
176
+ ...decision,
177
+ ...(decision.input !== undefined && shouldRedactPrompts(options) ? { input: replacement(options) } : {}),
178
+ ...(decision.output !== undefined && shouldRedactOutputs(options) ? { output: replacement(options) } : {})
179
+ };
180
+ }
181
+
182
+ function redactModelRequest(request: ModelRequest, options: TraceRedactionOptions): ModelRequest {
183
+ return shouldRedactPrompts(options)
184
+ ? {
185
+ ...request,
186
+ messages: request.messages.map((message) => ({
187
+ ...message,
188
+ content: replacement(options)
189
+ }))
190
+ }
191
+ : request;
192
+ }
193
+
194
+ function redactModelResponse(response: ModelResponse, options: TraceRedactionOptions): ModelResponse {
195
+ const redactedToolRequests = response.toolRequests?.map((request) => redactToolRequest(request, options));
196
+
197
+ if (shouldRedactProviderResponses(options)) {
198
+ return {
199
+ text: replacement(options),
200
+ ...(response.finishReason !== undefined ? { finishReason: response.finishReason } : {}),
201
+ ...(redactedToolRequests !== undefined && redactedToolRequests.length > 0 ? { toolRequests: redactedToolRequests } : {}),
202
+ ...(response.usage !== undefined ? { usage: response.usage } : {}),
203
+ ...(response.costUsd !== undefined ? { costUsd: response.costUsd } : {})
204
+ };
205
+ }
206
+
207
+ return {
208
+ ...response,
209
+ ...(shouldRedactOutputs(options) ? { text: replacement(options) } : {}),
210
+ ...(redactedToolRequests !== undefined ? { toolRequests: redactedToolRequests } : {})
211
+ };
212
+ }
213
+
214
+ function redactToolRequest(
215
+ request: RuntimeToolExecutionRequest,
216
+ options: TraceRedactionOptions
217
+ ): RuntimeToolExecutionRequest {
218
+ return shouldRedactToolInputs(options)
219
+ ? {
220
+ ...request,
221
+ input: REDACTED_JSON_OBJECT
222
+ }
223
+ : request;
224
+ }
225
+
226
+ function redactTranscriptEntry(entry: TranscriptEntry, options: TraceRedactionOptions): TranscriptEntry {
227
+ return {
228
+ ...entry,
229
+ ...(shouldRedactPrompts(options) ? { input: replacement(options) } : {}),
230
+ ...(shouldRedactOutputs(options) ? { output: replacement(options) } : {}),
231
+ ...(entry.decision !== undefined ? { decision: redactDecision(entry.decision, options) } : {}),
232
+ ...(entry.toolCalls !== undefined
233
+ ? { toolCalls: entry.toolCalls.map((toolCall) => redactTranscriptToolCall(toolCall, options)) }
234
+ : {})
235
+ };
236
+ }
237
+
238
+ function redactTranscriptToolCall(
239
+ toolCall: TranscriptToolCall,
240
+ options: TraceRedactionOptions
241
+ ): TranscriptToolCall {
242
+ return {
243
+ ...toolCall,
244
+ ...(shouldRedactToolInputs(options) ? { input: REDACTED_JSON_OBJECT } : {}),
245
+ result: redactRuntimeToolResult(toolCall.result, options)
246
+ };
247
+ }
248
+
249
+ function redactRuntimeToolResult(result: RuntimeToolResult, options: TraceRedactionOptions): RuntimeToolResult {
250
+ if (!shouldRedactToolOutputs(options)) {
251
+ return result;
252
+ }
253
+
254
+ if (result.type === "success") {
255
+ return {
256
+ ...result,
257
+ output: REDACTED_JSON_OBJECT
258
+ };
259
+ }
260
+
261
+ return {
262
+ ...result,
263
+ error: {
264
+ ...result.error,
265
+ ...(result.error.detail !== undefined ? { detail: REDACTED_JSON_OBJECT } : {})
266
+ }
267
+ };
268
+ }
269
+
270
+ function redactDecision(
271
+ decision: AgentDecision | readonly DelegateAgentDecision[],
272
+ options: TraceRedactionOptions
273
+ ): AgentDecision | readonly DelegateAgentDecision[] {
274
+ if (isDelegateDecisionArray(decision)) {
275
+ return decision.map((delegate) => redactDelegateDecision(delegate, options));
276
+ }
277
+ if (decision.type === "delegate") {
278
+ return redactDelegateDecision(decision, options);
279
+ }
280
+ return {
281
+ ...decision,
282
+ ...(shouldRedactOutputs(options)
283
+ ? {
284
+ rationale: replacement(options),
285
+ contribution: replacement(options)
286
+ }
287
+ : {})
288
+ };
289
+ }
290
+
291
+ function isDelegateDecisionArray(
292
+ decision: AgentDecision | readonly DelegateAgentDecision[]
293
+ ): decision is readonly DelegateAgentDecision[] {
294
+ return Array.isArray(decision);
295
+ }
296
+
297
+ function redactDelegateDecision(
298
+ decision: DelegateAgentDecision,
299
+ options: TraceRedactionOptions
300
+ ): DelegateAgentDecision {
301
+ return shouldRedactPrompts(options)
302
+ ? {
303
+ ...decision,
304
+ intent: replacement(options)
305
+ }
306
+ : decision;
307
+ }
308
+
309
+ function redactErrorDetail(detail: JsonObject, options: TraceRedactionOptions): JsonObject {
310
+ const failedDecision = detail["failedDecision"];
311
+ if (
312
+ !shouldRedactPrompts(options) ||
313
+ typeof failedDecision !== "object" ||
314
+ failedDecision === null ||
315
+ Array.isArray(failedDecision)
316
+ ) {
317
+ return detail;
318
+ }
319
+
320
+ return {
321
+ ...detail,
322
+ failedDecision: {
323
+ ...failedDecision,
324
+ intent: replacement(options)
325
+ }
326
+ };
327
+ }
328
+
329
+ function shouldRedactPrompts(options: TraceRedactionOptions): boolean {
330
+ return options.redactPrompts ?? true;
331
+ }
332
+
333
+ function shouldRedactOutputs(options: TraceRedactionOptions): boolean {
334
+ return options.redactOutputs ?? true;
335
+ }
336
+
337
+ function shouldRedactToolInputs(options: TraceRedactionOptions): boolean {
338
+ return options.redactToolInputs ?? true;
339
+ }
340
+
341
+ function shouldRedactToolOutputs(options: TraceRedactionOptions): boolean {
342
+ return options.redactToolOutputs ?? true;
343
+ }
344
+
345
+ function shouldRedactProviderResponses(options: TraceRedactionOptions): boolean {
346
+ return options.redactProviderResponses ?? true;
347
+ }
348
+
349
+ function shouldRedactEmbeddedChildTraces(options: TraceRedactionOptions): boolean {
350
+ return options.redactEmbeddedChildTraces ?? true;
351
+ }
352
+
353
+ function replacement(options: TraceRedactionOptions): string {
354
+ return options.replacementText ?? DEFAULT_REPLACEMENT_TEXT;
355
+ }
@@ -0,0 +1,81 @@
1
+ import type { JsonObject, JsonValue } from "../types.js";
2
+
3
+ const safeResponseHeaderNames = new Set([
4
+ "content-type",
5
+ "date",
6
+ "request-id",
7
+ "retry-after",
8
+ "x-ratelimit-limit",
9
+ "x-ratelimit-remaining",
10
+ "x-ratelimit-reset",
11
+ "x-request-id",
12
+ "x-stream-request-id"
13
+ ]);
14
+
15
+ const authLikeKeyPattern =
16
+ /^(?:authorization|proxy-authorization|cookie|set-cookie|x-api-key|api-key|apikey|api_key|x-auth-token|x-access-token|x-goog-api-key)$/i;
17
+
18
+ export function sanitizeProviderJsonValue(value: unknown): JsonValue | undefined {
19
+ if (value === null || typeof value === "string" || typeof value === "boolean") {
20
+ return value;
21
+ }
22
+
23
+ if (typeof value === "number") {
24
+ return Number.isFinite(value) ? value : null;
25
+ }
26
+
27
+ if (value instanceof Date) {
28
+ return value.toISOString();
29
+ }
30
+
31
+ if (Array.isArray(value)) {
32
+ return value.map((child) => sanitizeProviderJsonValue(child) ?? null);
33
+ }
34
+
35
+ if (isRecord(value)) {
36
+ const result: Record<string, JsonValue> = {};
37
+
38
+ for (const [key, child] of Object.entries(value)) {
39
+ if (isAuthLikeKey(key)) {
40
+ continue;
41
+ }
42
+ const jsonValue = sanitizeProviderJsonValue(child);
43
+ if (jsonValue !== undefined) {
44
+ result[key] = jsonValue;
45
+ }
46
+ }
47
+
48
+ return result;
49
+ }
50
+
51
+ return undefined;
52
+ }
53
+
54
+ export function sanitizeProviderResponseHeaders(headers: Headers | Record<string, unknown> | undefined): JsonObject | undefined {
55
+ if (headers === undefined) {
56
+ return undefined;
57
+ }
58
+
59
+ const result: Record<string, JsonValue> = {};
60
+ const entries =
61
+ typeof Headers !== "undefined" && headers instanceof Headers
62
+ ? Array.from(headers.entries())
63
+ : Object.entries(headers).map(([key, value]) => [key, String(value)] as const);
64
+
65
+ for (const [key, value] of entries) {
66
+ const normalizedKey = key.toLowerCase();
67
+ if (safeResponseHeaderNames.has(normalizedKey) && value !== undefined) {
68
+ result[normalizedKey] = String(value);
69
+ }
70
+ }
71
+
72
+ return Object.keys(result).length > 0 ? result : undefined;
73
+ }
74
+
75
+ function isAuthLikeKey(key: string): boolean {
76
+ return authLikeKeyPattern.test(key);
77
+ }
78
+
79
+ function isRecord(value: unknown): value is Record<string, unknown> {
80
+ return value !== null && typeof value === "object" && !Array.isArray(value);
81
+ }
@@ -16,6 +16,7 @@ import type {
16
16
  TerminationCondition,
17
17
  TerminationStopRecord,
18
18
  Tier,
19
+ Trace,
19
20
  TranscriptEntry
20
21
  } from "../types.js";
21
22
  import { createRunId, elapsedMs, nowMs } from "./ids.js";
@@ -35,6 +36,7 @@ import {
35
36
  emptyCost,
36
37
  nextProviderCallId
37
38
  } from "./defaults.js";
39
+ import { computeHealth, DEFAULT_HEALTH_THRESHOLDS } from "./health.js";
38
40
  import { throwIfAborted } from "./cancellation.js";
39
41
  import { isParticipatingDecision, parseAgentDecision } from "./decisions.js";
40
42
  import { generateModelTurn } from "./model.js";
@@ -242,45 +244,46 @@ export async function runSequential(options: SequentialRunOptions): Promise<RunR
242
244
  transcriptEntryCount: transcript.length
243
245
  });
244
246
  const finalEvent = events.at(-1);
247
+ const trace: Trace = {
248
+ schemaVersion: "1.0",
249
+ runId,
250
+ protocol: "sequential",
251
+ tier: options.tier,
252
+ modelProviderId: options.model.id,
253
+ agentsUsed: activeAgents,
254
+ inputs: createReplayTraceRunInputs({
255
+ intent: options.intent,
256
+ protocol: options.protocol,
257
+ tier: options.tier,
258
+ modelProviderId: options.model.id,
259
+ agents: activeAgents,
260
+ temperature: options.temperature
261
+ }),
262
+ budget: createReplayTraceBudget({
263
+ tier: options.tier,
264
+ ...(options.budget ? { caps: options.budget } : {}),
265
+ ...(options.terminate ? { termination: options.terminate } : {})
266
+ }),
267
+ budgetStateChanges: createReplayTraceBudgetStateChanges(events),
268
+ seed: createReplayTraceSeed(options.seed),
269
+ protocolDecisions,
270
+ providerCalls,
271
+ finalOutput: createReplayTraceFinalOutput(output, finalEvent ?? events[0] ?? {
272
+ type: "final",
273
+ runId,
274
+ at: "",
275
+ output,
276
+ cost: totalCost,
277
+ transcript: createTranscriptLink(transcript)
278
+ }),
279
+ events,
280
+ transcript
281
+ };
245
282
 
246
283
  return {
247
284
  output,
248
285
  eventLog: createRunEventLog(runId, "sequential", events),
249
- trace: {
250
- schemaVersion: "1.0",
251
- runId,
252
- protocol: "sequential",
253
- tier: options.tier,
254
- modelProviderId: options.model.id,
255
- agentsUsed: activeAgents,
256
- inputs: createReplayTraceRunInputs({
257
- intent: options.intent,
258
- protocol: options.protocol,
259
- tier: options.tier,
260
- modelProviderId: options.model.id,
261
- agents: activeAgents,
262
- temperature: options.temperature
263
- }),
264
- budget: createReplayTraceBudget({
265
- tier: options.tier,
266
- ...(options.budget ? { caps: options.budget } : {}),
267
- ...(options.terminate ? { termination: options.terminate } : {})
268
- }),
269
- budgetStateChanges: createReplayTraceBudgetStateChanges(events),
270
- seed: createReplayTraceSeed(options.seed),
271
- protocolDecisions,
272
- providerCalls,
273
- finalOutput: createReplayTraceFinalOutput(output, finalEvent ?? events[0] ?? {
274
- type: "final",
275
- runId,
276
- at: "",
277
- output,
278
- cost: totalCost,
279
- transcript: createTranscriptLink(transcript)
280
- }),
281
- events,
282
- transcript
283
- },
286
+ trace,
284
287
  transcript,
285
288
  usage: createRunUsage(totalCost),
286
289
  metadata: createRunMetadata({
@@ -298,7 +301,8 @@ export async function runSequential(options: SequentialRunOptions): Promise<RunR
298
301
  cost: totalCost,
299
302
  events
300
303
  }),
301
- cost: totalCost
304
+ cost: totalCost,
305
+ health: computeHealth(trace, DEFAULT_HEALTH_THRESHOLDS)
302
306
  };
303
307
 
304
308
  function stopIfNeeded(): boolean {
@@ -377,4 +381,3 @@ function responseCost(response: ModelResponse): CostSummary {
377
381
  totalTokens: response.usage?.totalTokens ?? 0
378
382
  };
379
383
  }
380
-