@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.
- package/CHANGELOG.md +92 -0
- package/dist/browser/index.js +4156 -4611
- package/dist/browser/index.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/openai-compatible.d.ts.map +1 -1
- package/dist/providers/openai-compatible.js +6 -1
- package/dist/providers/openai-compatible.js.map +1 -1
- package/dist/runtime/audit.d.ts +42 -0
- package/dist/runtime/audit.d.ts.map +1 -0
- package/dist/runtime/audit.js +73 -0
- package/dist/runtime/audit.js.map +1 -0
- package/dist/runtime/broadcast.d.ts +1 -0
- package/dist/runtime/broadcast.d.ts.map +1 -1
- package/dist/runtime/broadcast.js +171 -105
- package/dist/runtime/broadcast.js.map +1 -1
- package/dist/runtime/coordinator.d.ts +9 -2
- package/dist/runtime/coordinator.d.ts.map +1 -1
- package/dist/runtime/coordinator.js +164 -78
- package/dist/runtime/coordinator.js.map +1 -1
- package/dist/runtime/defaults.d.ts.map +1 -1
- package/dist/runtime/defaults.js +14 -5
- package/dist/runtime/defaults.js.map +1 -1
- package/dist/runtime/engine.d.ts +17 -4
- package/dist/runtime/engine.d.ts.map +1 -1
- package/dist/runtime/engine.js +577 -52
- package/dist/runtime/engine.js.map +1 -1
- package/dist/runtime/health.d.ts +51 -0
- package/dist/runtime/health.d.ts.map +1 -0
- package/dist/runtime/health.js +85 -0
- package/dist/runtime/health.js.map +1 -0
- package/dist/runtime/introspection.d.ts +96 -0
- package/dist/runtime/introspection.d.ts.map +1 -0
- package/dist/runtime/introspection.js +31 -0
- package/dist/runtime/introspection.js.map +1 -0
- package/dist/runtime/metrics.d.ts +44 -0
- package/dist/runtime/metrics.d.ts.map +1 -0
- package/dist/runtime/metrics.js +12 -0
- package/dist/runtime/metrics.js.map +1 -0
- package/dist/runtime/model.d.ts.map +1 -1
- package/dist/runtime/model.js +40 -10
- package/dist/runtime/model.js.map +1 -1
- package/dist/runtime/provenance.d.ts +25 -0
- package/dist/runtime/provenance.d.ts.map +1 -0
- package/dist/runtime/provenance.js +13 -0
- package/dist/runtime/provenance.js.map +1 -0
- package/dist/runtime/redaction.d.ts +13 -0
- package/dist/runtime/redaction.d.ts.map +1 -0
- package/dist/runtime/redaction.js +278 -0
- package/dist/runtime/redaction.js.map +1 -0
- package/dist/runtime/sanitization.d.ts +4 -0
- package/dist/runtime/sanitization.d.ts.map +1 -0
- package/dist/runtime/sanitization.js +63 -0
- package/dist/runtime/sanitization.js.map +1 -0
- package/dist/runtime/sequential.d.ts.map +1 -1
- package/dist/runtime/sequential.js +39 -36
- package/dist/runtime/sequential.js.map +1 -1
- package/dist/runtime/shared.d.ts +1 -0
- package/dist/runtime/shared.d.ts.map +1 -1
- package/dist/runtime/shared.js +167 -101
- package/dist/runtime/shared.js.map +1 -1
- package/dist/runtime/tools/built-in.d.ts +2 -0
- package/dist/runtime/tools/built-in.d.ts.map +1 -1
- package/dist/runtime/tools/built-in.js +153 -15
- package/dist/runtime/tools/built-in.js.map +1 -1
- package/dist/runtime/tools.d.ts.map +1 -1
- package/dist/runtime/tools.js +29 -7
- package/dist/runtime/tools.js.map +1 -1
- package/dist/runtime/tracing.d.ts +31 -0
- package/dist/runtime/tracing.d.ts.map +1 -0
- package/dist/runtime/tracing.js +18 -0
- package/dist/runtime/tracing.js.map +1 -0
- package/dist/runtime/validation.d.ts.map +1 -1
- package/dist/runtime/validation.js +3 -0
- package/dist/runtime/validation.js.map +1 -1
- package/dist/types/events.d.ts +13 -7
- 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 +144 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +46 -1
- package/src/index.ts +5 -0
- package/src/providers/openai-compatible.ts +6 -1
- package/src/runtime/audit.ts +121 -0
- package/src/runtime/broadcast.ts +195 -108
- package/src/runtime/coordinator.ts +197 -86
- package/src/runtime/defaults.ts +15 -5
- package/src/runtime/engine.ts +725 -58
- package/src/runtime/health.ts +136 -0
- package/src/runtime/introspection.ts +122 -0
- package/src/runtime/metrics.ts +45 -0
- package/src/runtime/model.ts +44 -9
- package/src/runtime/provenance.ts +43 -0
- package/src/runtime/redaction.ts +355 -0
- package/src/runtime/sanitization.ts +81 -0
- package/src/runtime/sequential.ts +40 -37
- package/src/runtime/shared.ts +191 -104
- package/src/runtime/tools/built-in.ts +168 -15
- package/src/runtime/tools.ts +39 -8
- package/src/runtime/tracing.ts +35 -0
- package/src/runtime/validation.ts +3 -0
- package/src/types/events.ts +13 -7
- package/src/types/replay.ts +5 -1
- 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
|
-
|