@dbx-tools/appkit-mastra 0.9.32 → 0.9.36

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.
@@ -1,137 +1,6 @@
1
1
  /**
2
- * Repairs traffic between Mastra / the AI SDK and Databricks Model Serving's
3
- * OpenAI-compatible `/chat/completions` route, in both directions.
4
- *
5
- * Outbound ({@link rewriteServingBody}), because the transcript Mastra
6
- * persists is not always a transcript the provider will accept back:
7
- * Databricks-hosted Claude rejects replayed extended-thinking blocks and reads
8
- * a trailing assistant message as a prefill request, while GPT tool calls need
9
- * model-specific reasoning-effort normalization on Chat Completions.
10
- *
11
- * Inbound ({@link rewriteServingResponseBody} and
12
- * {@link rewriteServingResponseStream}), because Databricks-hosted Gemini and
13
- * Claude can answer with native content-parts arrays where the OpenAI contract
14
- * (and therefore the AI SDK's response schema) requires a plain string.
15
- *
16
- * Every repair here is a provider quirk rather than a schema violation, so all
17
- * of them are applied on the wire (see the `globalThis.fetch` wrapper in
18
- * `model.ts`) rather than by changing what the agent stores or what the UI
19
- * shows.
2
+ * Databricks Model Serving wire repairs shared with the model gateway.
20
3
  *
21
4
  * @module
22
5
  */
23
- import { type ChatMessage, type ChatRole } from "@dbx-tools/shared-model";
24
- /**
25
- * A chat message as it arrives on the serving wire, plus the extended-thinking
26
- * fields Databricks-hosted Claude adds. The OpenAI-standard part of the shape
27
- * is {@link ChatMessage} from `@dbx-tools/shared-model`; only the provider
28
- * extensions this module strips are declared here.
29
- */
30
- export interface ServingChatMessage extends ChatMessage {
31
- /** Narrowed to the roles this repair pass reasons about, plus Claude's `reasoning` turn. */
32
- role: ChatRole | "reasoning";
33
- reasoning?: unknown;
34
- reasoning_content?: unknown;
35
- }
36
- /**
37
- * Parse, sanitize, and re-serialize a `/serving-endpoints/...` POST
38
- * body. Returns the original string verbatim when the body is not
39
- * JSON or no rewrite was needed.
40
- */
41
- export declare function rewriteServingBody(body: string): string;
42
- /** Prepared fetch arguments plus the post-sanitize body used for diagnostics. */
43
- export interface RewrittenServingRequest {
44
- input: Parameters<typeof fetch>[0];
45
- init: Parameters<typeof fetch>[1];
46
- body: string;
47
- }
48
- /**
49
- * Read and rewrite a serving POST whether its JSON body lives on `init` or on
50
- * a `Request`. A changed Request is rebuilt without stale byte headers.
51
- */
52
- export declare function rewriteServingRequest(input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]): Promise<RewrittenServingRequest>;
53
- /**
54
- * Normalize Chat Completions reasoning for GPT models carrying function tools.
55
- *
56
- * GPT 5.6 requires reasoning disabled for tool calls on this route, so `none`
57
- * wins over a caller/default effort. Responses-only models are routed away
58
- * from Chat Completions before this sanitizer runs.
59
- */
60
- export declare function applyToolReasoningCompatibility(body: Record<string, unknown>): boolean;
61
- /**
62
- * Drop extended-thinking / reasoning blocks from a replayed transcript.
63
- *
64
- * Hybrid Claude endpoints (e.g. Sonnet 4.5+) may emit `reasoning` content
65
- * parts on the first turn. Mastra persists and replays them on the next
66
- * agent step, but Databricks-hosted Claude rejects those blocks on
67
- * multi-turn tool continuations. The UI already captured reasoning for
68
- * display; stripping here keeps provider replay compatible without
69
- * changing what users see in the chat bubble.
70
- */
71
- export declare function stripReasoningFromServingMessages(messages: ServingChatMessage[]): boolean;
72
- /**
73
- * Repair a Mastra/AI SDK message replay that Databricks-hosted Claude
74
- * rejects with `"This model does not support assistant message
75
- * prefill. The conversation must end with a user message."`.
76
- *
77
- * The bug pattern: when an assistant turn streams text *and* a
78
- * `tool_call`, the AI SDK persists them as two separate assistant
79
- * entries (text-only and tool-call-only). On the next agent step the
80
- * tool-call entry is replayed *before* the tool result and the
81
- * text entry is replayed *after* it, so the conversation ends with a
82
- * trailing assistant text message. Anthropic interprets that as a
83
- * prefill request and rejects it on Databricks (the upstream Bedrock
84
- * route disallows prefill).
85
- *
86
- * Fix: when the last message is an assistant text with no `tool_calls`
87
- * and the chain immediately before it is `assistant(tool_calls=...)`
88
- * followed only by `tool(...)` results, fold the trailing text back
89
- * into the `content` of that opening assistant and drop the duplicate.
90
- */
91
- export declare function repairAssistantPrefill(messages: ServingChatMessage[]): boolean;
92
- /**
93
- * Parse, sanitize, and re-serialize a `/serving-endpoints/...` non-streaming
94
- * JSON RESPONSE body. Returns the original string verbatim when the body is
95
- * not JSON or no rewrite was needed, mirroring
96
- * {@link rewriteServingBody} on the request side.
97
- */
98
- export declare function rewriteServingResponseBody(body: string): string;
99
- /**
100
- * Repair array-valued `choices[].delta.content` inside an OpenAI SSE stream
101
- * without buffering the response. The decoder retains partial lines across
102
- * arbitrary network chunk boundaries; each complete `data:` line is parsed and
103
- * re-encoded only when its content needs normalization.
104
- */
105
- export declare function rewriteServingResponseStream(body: ReadableStream<Uint8Array>): ReadableStream<Uint8Array>;
106
- /**
107
- * Collapse a structured `choices[].message.content` array to the plain string
108
- * the OpenAI Chat Completions contract specifies.
109
- *
110
- * Databricks-hosted Gemini answers a non-streaming `/chat/completions` call
111
- * with the Gemini-native parts shape:
112
- *
113
- * ```json
114
- * "content": [{ "type": "text", "text": "...", "thoughtSignature": "..." }]
115
- * ```
116
- *
117
- * `@ai-sdk/openai-compatible` validates the response against the OpenAI
118
- * schema, where `content` is a nullable string, so it throws
119
- * `Type validation failed: ... expected string, received array` and the whole
120
- * call fails (`AI_APICallError: Invalid JSON response` on an HTTP 200). Mastra
121
- * uses `doGenerate` for its side calls, so the visible symptom is
122
- * `Error generating title` - every thread keeps its placeholder name.
123
- *
124
- * Flattening on the wire keeps the repair in one place: neither the agent's
125
- * stored transcript nor the UI has to know the provider emitted parts. Any
126
- * non-text part (a reasoning block, `thoughtSignature`-only entry, or inline
127
- * image) contributes nothing, matching {@link openaiChat.chatContentToText},
128
- * and an all-parts-empty message flattens to `""` rather than being dropped, so
129
- * `finish_reason` and `usage` still round-trip.
130
- */
131
- export declare function flattenChoiceMessageContent(payload: Record<string, unknown>): boolean;
132
- /**
133
- * Collapse structured streaming `choices[].delta.content` arrays to strings.
134
- * Claude reasoning-only chunks become an empty content delta while text parts
135
- * are concatenated in order.
136
- */
137
- export declare function flattenChoiceDeltaContent(payload: Record<string, unknown>): boolean;
6
+ export { applyToolReasoningCompatibility, flattenChoiceDeltaContent, flattenChoiceMessageContent, repairAssistantPrefill, rewriteServingBody, rewriteServingRequest, rewriteServingResponseBody, rewriteServingResponseStream, stripReasoningFromServingMessages, type RewrittenServingRequest, type ServingChatMessage, } from "@dbx-tools/model/serving-wire";
@@ -1,329 +1,7 @@
1
1
  /**
2
- * Repairs traffic between Mastra / the AI SDK and Databricks Model Serving's
3
- * OpenAI-compatible `/chat/completions` route, in both directions.
4
- *
5
- * Outbound ({@link rewriteServingBody}), because the transcript Mastra
6
- * persists is not always a transcript the provider will accept back:
7
- * Databricks-hosted Claude rejects replayed extended-thinking blocks and reads
8
- * a trailing assistant message as a prefill request, while GPT tool calls need
9
- * model-specific reasoning-effort normalization on Chat Completions.
10
- *
11
- * Inbound ({@link rewriteServingResponseBody} and
12
- * {@link rewriteServingResponseStream}), because Databricks-hosted Gemini and
13
- * Claude can answer with native content-parts arrays where the OpenAI contract
14
- * (and therefore the AI SDK's response schema) requires a plain string.
15
- *
16
- * Every repair here is a provider quirk rather than a schema violation, so all
17
- * of them are applied on the wire (see the `globalThis.fetch` wrapper in
18
- * `model.ts`) rather than by changing what the agent stores or what the UI
19
- * shows.
2
+ * Databricks Model Serving wire repairs shared with the model gateway.
20
3
  *
21
4
  * @module
22
5
  */
23
- import { policy } from "@dbx-tools/model";
24
- import { json, stringUtils } from "@dbx-tools/shared-core";
25
- import { openaiChat } from "@dbx-tools/shared-model";
26
- /** Signed Claude reasoning blocks that cannot be replayed after mutation. */
27
- const REASONING_PART_TYPES = new Set([
28
- "reasoning",
29
- "thinking",
30
- "redacted_thinking",
31
- ]);
32
- /**
33
- * Parse, sanitize, and re-serialize a `/serving-endpoints/...` POST
34
- * body. Returns the original string verbatim when the body is not
35
- * JSON or no rewrite was needed.
36
- */
37
- export function rewriteServingBody(body) {
38
- const parsed = json.parseRecord(body);
39
- if (!parsed)
40
- return body;
41
- // Runs regardless of `messages`: Databricks refuses to parse a body carrying
42
- // an unknown top-level field, so this failure is not specific to a transcript.
43
- const toolReasoning = applyToolReasoningCompatibility(parsed);
44
- let changed = openaiChat.stripUnsupportedChatFields(parsed).length > 0 || toolReasoning;
45
- if (Array.isArray(parsed.messages)) {
46
- const messages = parsed.messages;
47
- // Evaluated eagerly, not short-circuited: one transcript can need both
48
- // reasoning blocks stripped AND a trailing assistant prefill folded back.
49
- const stripped = stripReasoningFromServingMessages(messages);
50
- const repaired = repairAssistantPrefill(messages);
51
- changed = changed || stripped || repaired;
52
- }
53
- return changed ? JSON.stringify(parsed) : body;
54
- }
55
- /**
56
- * Read and rewrite a serving POST whether its JSON body lives on `init` or on
57
- * a `Request`. A changed Request is rebuilt without stale byte headers.
58
- */
59
- export async function rewriteServingRequest(input, init) {
60
- const request = new Request(input, init);
61
- const body = await request.clone().text();
62
- const rewritten = rewriteServingBody(body);
63
- if (rewritten === body)
64
- return { input, init, body };
65
- const headers = new Headers(request.headers);
66
- headers.delete("content-length");
67
- headers.delete("content-encoding");
68
- return {
69
- input: new Request(request, { body: rewritten, headers }),
70
- init: undefined,
71
- body: rewritten,
72
- };
73
- }
74
- /**
75
- * Normalize Chat Completions reasoning for GPT models carrying function tools.
76
- *
77
- * GPT 5.6 requires reasoning disabled for tool calls on this route, so `none`
78
- * wins over a caller/default effort. Responses-only models are routed away
79
- * from Chat Completions before this sanitizer runs.
80
- */
81
- export function applyToolReasoningCompatibility(body) {
82
- if (!Array.isArray(body.tools) || body.tools.length === 0) {
83
- return false;
84
- }
85
- const model = stringUtils.trimToNull(body.model);
86
- if (!model)
87
- return false;
88
- if (policy.chatToolReasoningEffort(model) !== "none")
89
- return false;
90
- if (body.reasoning_effort === "none")
91
- return false;
92
- body.reasoning_effort = "none";
93
- return true;
94
- }
95
- /**
96
- * Drop extended-thinking / reasoning blocks from a replayed transcript.
97
- *
98
- * Hybrid Claude endpoints (e.g. Sonnet 4.5+) may emit `reasoning` content
99
- * parts on the first turn. Mastra persists and replays them on the next
100
- * agent step, but Databricks-hosted Claude rejects those blocks on
101
- * multi-turn tool continuations. The UI already captured reasoning for
102
- * display; stripping here keeps provider replay compatible without
103
- * changing what users see in the chat bubble.
104
- */
105
- export function stripReasoningFromServingMessages(messages) {
106
- let changed = false;
107
- for (let i = messages.length - 1; i >= 0; i--) {
108
- const msg = messages[i];
109
- if (!msg)
110
- continue;
111
- if (msg.role === "reasoning") {
112
- messages.splice(i, 1);
113
- changed = true;
114
- continue;
115
- }
116
- if (msg.reasoning !== undefined) {
117
- delete msg.reasoning;
118
- changed = true;
119
- }
120
- if (msg.reasoning_content !== undefined) {
121
- delete msg.reasoning_content;
122
- changed = true;
123
- }
124
- const parts = openaiChat.chatContentParts(msg.content);
125
- if (!parts)
126
- continue;
127
- const filtered = parts.filter((part) => {
128
- const type = part?.type;
129
- if (typeof type === "string" && REASONING_PART_TYPES.has(type)) {
130
- changed = true;
131
- return false;
132
- }
133
- return true;
134
- });
135
- if (filtered.length !== parts.length) {
136
- msg.content = filtered;
137
- }
138
- const hasToolCalls = Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0;
139
- if (msg.role === "assistant" && !hasToolCalls && isEmptyServingContent(msg.content)) {
140
- messages.splice(i, 1);
141
- changed = true;
142
- }
143
- }
144
- return changed;
145
- }
146
- /**
147
- * Repair a Mastra/AI SDK message replay that Databricks-hosted Claude
148
- * rejects with `"This model does not support assistant message
149
- * prefill. The conversation must end with a user message."`.
150
- *
151
- * The bug pattern: when an assistant turn streams text *and* a
152
- * `tool_call`, the AI SDK persists them as two separate assistant
153
- * entries (text-only and tool-call-only). On the next agent step the
154
- * tool-call entry is replayed *before* the tool result and the
155
- * text entry is replayed *after* it, so the conversation ends with a
156
- * trailing assistant text message. Anthropic interprets that as a
157
- * prefill request and rejects it on Databricks (the upstream Bedrock
158
- * route disallows prefill).
159
- *
160
- * Fix: when the last message is an assistant text with no `tool_calls`
161
- * and the chain immediately before it is `assistant(tool_calls=...)`
162
- * followed only by `tool(...)` results, fold the trailing text back
163
- * into the `content` of that opening assistant and drop the duplicate.
164
- */
165
- export function repairAssistantPrefill(messages) {
166
- if (messages.length < 2)
167
- return false;
168
- const last = messages[messages.length - 1];
169
- if (!last || last.role !== "assistant" || (last.tool_calls && last.tool_calls.length > 0)) {
170
- return false;
171
- }
172
- let i = messages.length - 2;
173
- while (i >= 0 && messages[i]?.role === "tool")
174
- i--;
175
- if (i < 0)
176
- return false;
177
- const opener = messages[i];
178
- if (!opener ||
179
- opener.role !== "assistant" ||
180
- !opener.tool_calls ||
181
- opener.tool_calls.length === 0) {
182
- return false;
183
- }
184
- const merged = [
185
- stringUtils.trimToNull(textFromServingContent(opener.content)),
186
- stringUtils.trimToNull(textFromServingContent(last.content)),
187
- ]
188
- .filter((s) => s !== null)
189
- .join("\n\n");
190
- opener.content = merged;
191
- messages.pop();
192
- return true;
193
- }
194
- /**
195
- * Flatten content to the prose a human would read: text parts only, separated
196
- * by blank lines, since the result is spliced into another turn's message body.
197
- */
198
- function textFromServingContent(content) {
199
- return openaiChat.chatContentToText(content, { separator: "\n\n", types: ["text"] });
200
- }
201
- /**
202
- * Whether a turn carries nothing worth replaying. Deliberately stricter than
203
- * "has no text": a part of any other type (an image, a cache marker) counts as
204
- * content, so a message holding one is kept even though it has no prose.
205
- */
206
- function isEmptyServingContent(content) {
207
- if (content === undefined)
208
- return true;
209
- if (typeof content === "string")
210
- return content.trim().length === 0;
211
- const parts = openaiChat.chatContentParts(content);
212
- if (!parts)
213
- return true;
214
- return parts.every((part) => {
215
- if (part?.type === "text") {
216
- return typeof part.text !== "string" || part.text.trim().length === 0;
217
- }
218
- return false;
219
- });
220
- }
221
- /**
222
- * Parse, sanitize, and re-serialize a `/serving-endpoints/...` non-streaming
223
- * JSON RESPONSE body. Returns the original string verbatim when the body is
224
- * not JSON or no rewrite was needed, mirroring
225
- * {@link rewriteServingBody} on the request side.
226
- */
227
- export function rewriteServingResponseBody(body) {
228
- const parsed = json.parseRecord(body);
229
- if (!parsed)
230
- return body;
231
- return flattenChoiceMessageContent(parsed) ? JSON.stringify(parsed) : body;
232
- }
233
- /**
234
- * Repair array-valued `choices[].delta.content` inside an OpenAI SSE stream
235
- * without buffering the response. The decoder retains partial lines across
236
- * arbitrary network chunk boundaries; each complete `data:` line is parsed and
237
- * re-encoded only when its content needs normalization.
238
- */
239
- export function rewriteServingResponseStream(body) {
240
- const decoder = new TextDecoder();
241
- const encoder = new TextEncoder();
242
- let buffer = "";
243
- return body.pipeThrough(new TransformStream({
244
- transform(chunk, controller) {
245
- buffer += decoder.decode(chunk, { stream: true });
246
- let newline = buffer.indexOf("\n");
247
- while (newline >= 0) {
248
- const line = buffer.slice(0, newline + 1);
249
- buffer = buffer.slice(newline + 1);
250
- controller.enqueue(encoder.encode(rewriteServingResponseStreamLine(line)));
251
- newline = buffer.indexOf("\n");
252
- }
253
- },
254
- flush(controller) {
255
- buffer += decoder.decode();
256
- if (buffer)
257
- controller.enqueue(encoder.encode(rewriteServingResponseStreamLine(buffer)));
258
- },
259
- }));
260
- }
261
- /** Normalize one SSE line while preserving its `data:` spacing and line ending. */
262
- function rewriteServingResponseStreamLine(line) {
263
- const lineEnding = line.endsWith("\r\n") ? "\r\n" : line.endsWith("\n") ? "\n" : "";
264
- const content = lineEnding ? line.slice(0, -lineEnding.length) : line;
265
- const match = /^(data:\s*)(.*)$/.exec(content);
266
- if (!match || match[2] === "[DONE]")
267
- return line;
268
- const parsed = json.parseRecord(match[2]);
269
- if (!parsed || !flattenChoiceDeltaContent(parsed))
270
- return line;
271
- return `${match[1]}${JSON.stringify(parsed)}${lineEnding}`;
272
- }
273
- /**
274
- * Collapse a structured `choices[].message.content` array to the plain string
275
- * the OpenAI Chat Completions contract specifies.
276
- *
277
- * Databricks-hosted Gemini answers a non-streaming `/chat/completions` call
278
- * with the Gemini-native parts shape:
279
- *
280
- * ```json
281
- * "content": [{ "type": "text", "text": "...", "thoughtSignature": "..." }]
282
- * ```
283
- *
284
- * `@ai-sdk/openai-compatible` validates the response against the OpenAI
285
- * schema, where `content` is a nullable string, so it throws
286
- * `Type validation failed: ... expected string, received array` and the whole
287
- * call fails (`AI_APICallError: Invalid JSON response` on an HTTP 200). Mastra
288
- * uses `doGenerate` for its side calls, so the visible symptom is
289
- * `Error generating title` - every thread keeps its placeholder name.
290
- *
291
- * Flattening on the wire keeps the repair in one place: neither the agent's
292
- * stored transcript nor the UI has to know the provider emitted parts. Any
293
- * non-text part (a reasoning block, `thoughtSignature`-only entry, or inline
294
- * image) contributes nothing, matching {@link openaiChat.chatContentToText},
295
- * and an all-parts-empty message flattens to `""` rather than being dropped, so
296
- * `finish_reason` and `usage` still round-trip.
297
- */
298
- export function flattenChoiceMessageContent(payload) {
299
- return flattenChoiceContent(payload, "message");
300
- }
301
- /**
302
- * Collapse structured streaming `choices[].delta.content` arrays to strings.
303
- * Claude reasoning-only chunks become an empty content delta while text parts
304
- * are concatenated in order.
305
- */
306
- export function flattenChoiceDeltaContent(payload) {
307
- return flattenChoiceContent(payload, "delta");
308
- }
309
- /** Shared choice walker for buffered `message` and streaming `delta` payloads. */
310
- function flattenChoiceContent(payload, field) {
311
- if (!Array.isArray(payload.choices))
312
- return false;
313
- let changed = false;
314
- for (const choice of payload.choices) {
315
- if (!choice || typeof choice !== "object")
316
- continue;
317
- const container = choice[field];
318
- if (!container || typeof container !== "object")
319
- continue;
320
- const target = container;
321
- const parts = openaiChat.chatContentParts(target.content);
322
- if (!parts)
323
- continue;
324
- target.content = openaiChat.chatContentToText(parts, { types: ["text"] });
325
- changed = true;
326
- }
327
- return changed;
328
- }
329
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmluZy1zYW5pdGl6ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aW5nLXNhbml0aXplLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDMUMsT0FBTyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMzRCxPQUFPLEVBQW1DLFVBQVUsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBZXRGLDZFQUE2RTtBQUM3RSxNQUFNLG9CQUFvQixHQUF3QixJQUFJLEdBQUcsQ0FBQztJQUN4RCxXQUFXO0lBQ1gsVUFBVTtJQUNWLG1CQUFtQjtDQUNwQixDQUFDLENBQUM7QUFFSDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUFDLElBQVk7SUFDN0MsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN0QyxJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBRXpCLDZFQUE2RTtJQUM3RSwrRUFBK0U7SUFDL0UsTUFBTSxhQUFhLEdBQUcsK0JBQStCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDOUQsSUFBSSxPQUFPLEdBQUcsVUFBVSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksYUFBYSxDQUFDO0lBRXhGLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUNuQyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBZ0MsQ0FBQztRQUN6RCx1RUFBdUU7UUFDdkUsMEVBQTBFO1FBQzFFLE1BQU0sUUFBUSxHQUFHLGlDQUFpQyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQzdELE1BQU0sUUFBUSxHQUFHLHNC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RSxPQUFPLEdBQUcsSUFBSSxDQUFDO0lBQ2pCLENBQUM7SUFDRCxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSZXBhaXJzIHRyYWZmaWMgYmV0d2VlbiBNYXN0cmEgLyB0aGUgQUkgU0RLIGFuZCBEYXRhYnJpY2tzIE1vZGVsIFNlcnZpbmcnc1xuICogT3BlbkFJLWNvbXBhdGlibGUgYC9jaGF0L2NvbXBsZXRpb25zYCByb3V0ZSwgaW4gYm90aCBkaXJlY3Rpb25zLlxuICpcbiAqIE91dGJvdW5kICh7QGxpbmsgcmV3cml0ZVNlcnZpbmdCb2R5fSksIGJlY2F1c2UgdGhlIHRyYW5zY3JpcHQgTWFzdHJhXG4gKiBwZXJzaXN0cyBpcyBub3QgYWx3YXlzIGEgdHJhbnNjcmlwdCB0aGUgcHJvdmlkZXIgd2lsbCBhY2NlcHQgYmFjazpcbiAqIERhdGFicmlja3MtaG9zdGVkIENsYXVkZSByZWplY3RzIHJlcGxheWVkIGV4dGVuZGVkLXRoaW5raW5nIGJsb2NrcyBhbmQgcmVhZHNcbiAqIGEgdHJhaWxpbmcgYXNzaXN0YW50IG1lc3NhZ2UgYXMgYSBwcmVmaWxsIHJlcXVlc3QsIHdoaWxlIEdQVCB0b29sIGNhbGxzIG5lZWRcbiAqIG1vZGVsLXNwZWNpZmljIHJlYXNvbmluZy1lZmZvcnQgbm9ybWFsaXphdGlvbiBvbiBDaGF0IENvbXBsZXRpb25zLlxuICpcbiAqIEluYm91bmQgKHtAbGluayByZXdyaXRlU2VydmluZ1Jlc3BvbnNlQm9keX0gYW5kXG4gKiB7QGxpbmsgcmV3cml0ZVNlcnZpbmdSZXNwb25zZVN0cmVhbX0pLCBiZWNhdXNlIERhdGFicmlja3MtaG9zdGVkIEdlbWluaSBhbmRcbiAqIENsYXVkZSBjYW4gYW5zd2VyIHdpdGggbmF0aXZlIGNvbnRlbnQtcGFydHMgYXJyYXlzIHdoZXJlIHRoZSBPcGVuQUkgY29udHJhY3RcbiAqIChhbmQgdGhlcmVmb3JlIHRoZSBBSSBTREsncyByZXNwb25zZSBzY2hlbWEpIHJlcXVpcmVzIGEgcGxhaW4gc3RyaW5nLlxuICpcbiAqIEV2ZXJ5IHJlcGFpciBoZXJlIGlzIGEgcHJvdmlkZXIgcXVpcmsgcmF0aGVyIHRoYW4gYSBzY2hlbWEgdmlvbGF0aW9uLCBzbyBhbGxcbiAqIG9mIHRoZW0gYXJlIGFwcGxpZWQgb24gdGhlIHdpcmUgKHNlZSB0aGUgYGdsb2JhbFRoaXMuZmV0Y2hgIHdyYXBwZXIgaW5cbiAqIGBtb2RlbC50c2ApIHJhdGhlciB0aGFuIGJ5IGNoYW5naW5nIHdoYXQgdGhlIGFnZW50IHN0b3JlcyBvciB3aGF0IHRoZSBVSVxuICogc2hvd3MuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHBvbGljeSB9IGZyb20gXCJAZGJ4LXRvb2xzL21vZGVsXCI7XG5pbXBvcnQgeyBqc29uLCBzdHJpbmdVdGlscyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyB0eXBlIENoYXRNZXNzYWdlLCB0eXBlIENoYXRSb2xlLCBvcGVuYWlDaGF0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsXCI7XG5cbi8qKlxuICogQSBjaGF0IG1lc3NhZ2UgYXMgaXQgYXJyaXZlcyBvbiB0aGUgc2VydmluZyB3aXJlLCBwbHVzIHRoZSBleHRlbmRlZC10aGlua2luZ1xuICogZmllbGRzIERhdGFicmlja3MtaG9zdGVkIENsYXVkZSBhZGRzLiBUaGUgT3BlbkFJLXN0YW5kYXJkIHBhcnQgb2YgdGhlIHNoYXBlXG4gKiBpcyB7QGxpbmsgQ2hhdE1lc3NhZ2V9IGZyb20gYEBkYngtdG9vbHMvc2hhcmVkLW1vZGVsYDsgb25seSB0aGUgcHJvdmlkZXJcbiAqIGV4dGVuc2lvbnMgdGhpcyBtb2R1bGUgc3RyaXBzIGFyZSBkZWNsYXJlZCBoZXJlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpbmdDaGF0TWVzc2FnZSBleHRlbmRzIENoYXRNZXNzYWdlIHtcbiAgLyoqIE5hcnJvd2VkIHRvIHRoZSByb2xlcyB0aGlzIHJlcGFpciBwYXNzIHJlYXNvbnMgYWJvdXQsIHBsdXMgQ2xhdWRlJ3MgYHJlYXNvbmluZ2AgdHVybi4gKi9cbiAgcm9sZTogQ2hhdFJvbGUgfCBcInJlYXNvbmluZ1wiO1xuICByZWFzb25pbmc/OiB1bmtub3duO1xuICByZWFzb25pbmdfY29udGVudD86IHVua25vd247XG59XG5cbi8qKiBTaWduZWQgQ2xhdWRlIHJlYXNvbmluZyBibG9ja3MgdGhhdCBjYW5ub3QgYmUgcmVwbGF5ZWQgYWZ0ZXIgbXV0YXRpb24uICovXG5jb25zdCBSRUFTT05JTkdfUEFSVF9UWVBFUzogUmVhZG9ubHlTZXQ8c3RyaW5nPiA9IG5ldyBTZXQoW1xuICBcInJlYXNvbmluZ1wiLFxuICBcInRoaW5raW5nXCIsXG4gIFwicmVkYWN0ZWRfdGhpbmtpbmdcIixcbl0pO1xuXG4vKipcbiAqIFBhcnNlLCBzYW5pdGl6ZSwgYW5kIHJlLXNlcmlhbGl6ZSBhIGAvc2VydmluZy1lbmRwb2ludHMvLi4uYCBQT1NUXG4gKiBib2R5LiBSZXR1cm5zIHRoZSBvcmlnaW5hbCBzdHJpbmcgdmVyYmF0aW0gd2hlbiB0aGUgYm9keSBpcyBub3RcbiAqIEpTT04gb3Igbm8gcmV3cml0ZSB3YXMgbmVlZGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmV3cml0ZVNlcnZpbmdCb2R5KGJvZHk6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IHBhcnNlZCA9IGpzb24ucGFyc2VSZWNvcmQoYm9keSk7XG4gIGlmICghcGFyc2VkKSByZXR1cm4gYm9keTtcblxuICAvLyBSdW5zIHJlZ2FyZGxlc3Mgb2YgYG1lc3NhZ2VzYDogRGF0YWJyaWNrcyByZWZ1c2VzIHRvIHBhcnNlIGEgYm9keSBjYXJyeWluZ1xuICAvLyBhbiB1bmtub3duIHRvcC1sZXZlbCBmaWVsZCwgc28gdGhpcyBmYWlsdXJlIGlzIG5vdCBzcGVjaWZpYyB0byBhIHRyYW5zY3JpcHQuXG4gIGNvbnN0IHRvb2xSZWFzb25pbmcgPSBhcHBseVRvb2xSZWFzb25pbmdDb21wYXRpYmlsaXR5KHBhcnNlZCk7XG4gIGxldCBjaGFuZ2VkID0gb3BlbmFpQ2hhdC5zdHJpcFVuc3VwcG9ydGVkQ2hhdEZpZWxkcyhwYXJzZWQpLmxlbmd0aCA+IDAgfHwgdG9vbFJlYXNvbmluZztcblxuICBpZiAoQXJyYXkuaXNBcnJheShwYXJzZWQubWVzc2FnZXMpKSB7XG4gICAgY29uc3QgbWVzc2FnZXMgPSBwYXJzZWQubWVzc2FnZXMgYXMgU2VydmluZ0NoYXRNZXNzYWdlW107XG4gICAgLy8gRXZhbHVhdGVkIGVhZ2VybHksIG5vdCBzaG9ydC1jaXJjdWl0ZWQ6IG9uZSB0cmFuc2NyaXB0IGNhbiBuZWVkIGJvdGhcbiAgICAvLyByZWFzb25pbmcgYmxvY2tzIHN0cmlwcGVkIEFORCBhIHRyYWlsaW5nIGFzc2lzdGFudCBwcmVmaWxsIGZvbGRlZCBiYWNrLlxuICAgIGNvbnN0IHN0cmlwcGVkID0gc3RyaXBSZWFzb25pbmdGcm9tU2VydmluZ01lc3NhZ2VzKG1lc3NhZ2VzKTtcbiAgICBjb25zdCByZXBhaXJlZCA9IHJlcGFpckFzc2lzdGFudFByZWZpbGwobWVzc2FnZXMpO1xuICAgIGNoYW5nZWQgPSBjaGFuZ2VkIHx8IHN0cmlwcGVkIHx8IHJlcGFpcmVkO1xuICB9XG5cbiAgcmV0dXJuIGNoYW5nZWQgPyBKU09OLnN0cmluZ2lmeShwYXJzZWQpIDogYm9keTtcbn1cblxuLyoqIFByZXBhcmVkIGZldGNoIGFyZ3VtZW50cyBwbHVzIHRoZSBwb3N0LXNhbml0aXplIGJvZHkgdXNlZCBmb3IgZGlhZ25vc3RpY3MuICovXG5leHBvcnQgaW50ZXJmYWNlIFJld3JpdHRlblNlcnZpbmdSZXF1ZXN0IHtcbiAgaW5wdXQ6IFBhcmFtZXRlcnM8dHlwZW9mIGZldGNoPlswXTtcbiAgaW5pdDogUGFyYW1ldGVyczx0eXBlb2YgZmV0Y2g+WzFdO1xuICBib2R5OiBzdHJpbmc7XG59XG5cbi8qKlxuICogUmVhZCBhbmQgcmV3cml0ZSBhIHNlcnZpbmcgUE9TVCB3aGV0aGVyIGl0cyBKU09OIGJvZHkgbGl2ZXMgb24gYGluaXRgIG9yIG9uXG4gKiBhIGBSZXF1ZXN0YC4gQSBjaGFuZ2VkIFJlcXVlc3QgaXMgcmVidWlsdCB3aXRob3V0IHN0YWxlIGJ5dGUgaGVhZGVycy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJld3JpdGVTZXJ2aW5nUmVxdWVzdChcbiAgaW5wdXQ6IFBhcmFtZXRlcnM8dHlwZW9mIGZldGNoPlswXSxcbiAgaW5pdD86IFBhcmFtZXRlcnM8dHlwZW9mIGZldGNoPlsxXSxcbik6IFByb21pc2U8UmV3cml0dGVuU2VydmluZ1JlcXVlc3Q+IHtcbiAgY29uc3QgcmVxdWVzdCA9IG5ldyBSZXF1ZXN0KGlucHV0LCBpbml0KTtcbiAgY29uc3QgYm9keSA9IGF3YWl0IHJlcXVlc3QuY2xvbmUoKS50ZXh0KCk7XG4gIGNvbnN0IHJld3JpdHRlbiA9IHJld3JpdGVTZXJ2aW5nQm9keShib2R5KTtcbiAgaWYgKHJld3JpdHRlbiA9PT0gYm9keSkgcmV0dXJuIHsgaW5wdXQsIGluaXQsIGJvZHkgfTtcblxuICBjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMocmVxdWVzdC5oZWFkZXJzKTtcbiAgaGVhZGVycy5kZWxldGUoXCJjb250ZW50LWxlbmd0aFwiKTtcbiAgaGVhZGVycy5kZWxldGUoXCJjb250ZW50LWVuY29kaW5nXCIpO1xuICByZXR1cm4ge1xuICAgIGlucHV0OiBuZXcgUmVxdWVzdChyZXF1ZXN0LCB7IGJvZHk6IHJld3JpdHRlbiwgaGVhZGVycyB9KSxcbiAgICBpbml0OiB1bmRlZmluZWQsXG4gICAgYm9keTogcmV3cml0dGVuLFxuICB9O1xufVxuXG4vKipcbiAqIE5vcm1hbGl6ZSBDaGF0IENvbXBsZXRpb25zIHJlYXNvbmluZyBmb3IgR1BUIG1vZGVscyBjYXJyeWluZyBmdW5jdGlvbiB0b29scy5cbiAqXG4gKiBHUFQgNS42IHJlcXVpcmVzIHJlYXNvbmluZyBkaXNhYmxlZCBmb3IgdG9vbCBjYWxscyBvbiB0aGlzIHJvdXRlLCBzbyBgbm9uZWBcbiAqIHdpbnMgb3ZlciBhIGNhbGxlci9kZWZhdWx0IGVmZm9ydC4gUmVzcG9uc2VzLW9ubHkgbW9kZWxzIGFyZSByb3V0ZWQgYXdheVxuICogZnJvbSBDaGF0IENvbXBsZXRpb25zIGJlZm9yZSB0aGlzIHNhbml0aXplciBydW5zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlUb29sUmVhc29uaW5nQ29tcGF0aWJpbGl0eShib2R5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IGJvb2xlYW4ge1xuICBpZiAoIUFycmF5LmlzQXJyYXkoYm9keS50b29scykgfHwgYm9keS50b29scy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgY29uc3QgbW9kZWwgPSBzdHJpbmdVdGlscy50cmltVG9OdWxsKGJvZHkubW9kZWwpO1xuICBpZiAoIW1vZGVsKSByZXR1cm4gZmFsc2U7XG4gIGlmIChwb2xpY3kuY2hhdFRvb2xSZWFzb25pbmdFZmZvcnQobW9kZWwpICE9PSBcIm5vbmVcIikgcmV0dXJuIGZhbHNlO1xuICBpZiAoYm9keS5yZWFzb25pbmdfZWZmb3J0ID09PSBcIm5vbmVcIikgcmV0dXJuIGZhbHNlO1xuICBib2R5LnJlYXNvbmluZ19lZmZvcnQgPSBcIm5vbmVcIjtcbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogRHJvcCBleHRlbmRlZC10aGlua2luZyAvIHJlYXNvbmluZyBibG9ja3MgZnJvbSBhIHJlcGxheWVkIHRyYW5zY3JpcHQuXG4gKlxuICogSHlicmlkIENsYXVkZSBlbmRwb2ludHMgKGUuZy4gU29ubmV0IDQuNSspIG1heSBlbWl0IGByZWFzb25pbmdgIGNvbnRlbnRcbiAqIHBhcnRzIG9uIHRoZSBmaXJzdCB0dXJuLiBNYXN0cmEgcGVyc2lzdHMgYW5kIHJlcGxheXMgdGhlbSBvbiB0aGUgbmV4dFxuICogYWdlbnQgc3RlcCwgYnV0IERhdGFicmlja3MtaG9zdGVkIENsYXVkZSByZWplY3RzIHRob3NlIGJsb2NrcyBvblxuICogbXVsdGktdHVybiB0b29sIGNvbnRpbnVhdGlvbnMuIFRoZSBVSSBhbHJlYWR5IGNhcHR1cmVkIHJlYXNvbmluZyBmb3JcbiAqIGRpc3BsYXk7IHN0cmlwcGluZyBoZXJlIGtlZXBzIHByb3ZpZGVyIHJlcGxheSBjb21wYXRpYmxlIHdpdGhvdXRcbiAqIGNoYW5naW5nIHdoYXQgdXNlcnMgc2VlIGluIHRoZSBjaGF0IGJ1YmJsZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0cmlwUmVhc29uaW5nRnJvbVNlcnZpbmdNZXNzYWdlcyhtZXNzYWdlczogU2VydmluZ0NoYXRNZXNzYWdlW10pOiBib29sZWFuIHtcbiAgbGV0IGNoYW5nZWQgPSBmYWxzZTtcbiAgZm9yIChsZXQgaSA9IG1lc3NhZ2VzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgY29uc3QgbXNnID0gbWVzc2FnZXNbaV07XG4gICAgaWYgKCFtc2cpIGNvbnRpbnVlO1xuICAgIGlmIChtc2cucm9sZSA9PT0gXCJyZWFzb25pbmdcIikge1xuICAgICAgbWVzc2FnZXMuc3BsaWNlKGksIDEpO1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKG1zZy5yZWFzb25pbmcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgZGVsZXRlIG1zZy5yZWFzb25pbmc7XG4gICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKG1zZy5yZWFzb25pbmdfY29udGVudCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBkZWxldGUgbXNnLnJlYXNvbmluZ19jb250ZW50O1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgfVxuICAgIGNvbnN0IHBhcnRzID0gb3BlbmFpQ2hhdC5jaGF0Q29udGVudFBhcnRzKG1zZy5jb250ZW50KTtcbiAgICBpZiAoIXBhcnRzKSBjb250aW51ZTtcbiAgICBjb25zdCBmaWx0ZXJlZCA9IHBhcnRzLmZpbHRlcigocGFydCkgPT4ge1xuICAgICAgY29uc3QgdHlwZSA9IHBhcnQ/LnR5cGU7XG4gICAgICBpZiAodHlwZW9mIHR5cGUgPT09IFwic3RyaW5nXCIgJiYgUkVBU09OSU5HX1BBUlRfVFlQRVMuaGFzKHR5cGUpKSB7XG4gICAgICAgIGNoYW5nZWQgPSB0cnVlO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9KTtcbiAgICBpZiAoZmlsdGVyZWQubGVuZ3RoICE9PSBwYXJ0cy5sZW5ndGgpIHtcbiAgICAgIG1zZy5jb250ZW50ID0gZmlsdGVyZWQ7XG4gICAgfVxuICAgIGNvbnN0IGhhc1Rvb2xDYWxscyA9IEFycmF5LmlzQXJyYXkobXNnLnRvb2xfY2FsbHMpICYmIG1zZy50b29sX2NhbGxzLmxlbmd0aCA+IDA7XG4gICAgaWYgKG1zZy5yb2xlID09PSBcImFzc2lzdGFudFwiICYmICFoYXNUb29sQ2FsbHMgJiYgaXNFbXB0eVNlcnZpbmdDb250ZW50KG1zZy5jb250ZW50KSkge1xuICAgICAgbWVzc2FnZXMuc3BsaWNlKGksIDEpO1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBjaGFuZ2VkO1xufVxuXG4vKipcbiAqIFJlcGFpciBhIE1hc3RyYS9BSSBTREsgbWVzc2FnZSByZXBsYXkgdGhhdCBEYXRhYnJpY2tzLWhvc3RlZCBDbGF1ZGVcbiAqIHJlamVjdHMgd2l0aCBgXCJUaGlzIG1vZGVsIGRvZXMgbm90IHN1cHBvcnQgYXNzaXN0YW50IG1lc3NhZ2VcbiAqIHByZWZpbGwuIFRoZSBjb252ZXJzYXRpb24gbXVzdCBlbmQgd2l0aCBhIHVzZXIgbWVzc2FnZS5cImAuXG4gKlxuICogVGhlIGJ1ZyBwYXR0ZXJuOiB3aGVuIGFuIGFzc2lzdGFudCB0dXJuIHN0cmVhbXMgdGV4dCAqYW5kKiBhXG4gKiBgdG9vbF9jYWxsYCwgdGhlIEFJIFNESyBwZXJzaXN0cyB0aGVtIGFzIHR3byBzZXBhcmF0ZSBhc3Npc3RhbnRcbiAqIGVudHJpZXMgKHRleHQtb25seSBhbmQgdG9vbC1jYWxsLW9ubHkpLiBPbiB0aGUgbmV4dCBhZ2VudCBzdGVwIHRoZVxuICogdG9vbC1jYWxsIGVudHJ5IGlzIHJlcGxheWVkICpiZWZvcmUqIHRoZSB0b29sIHJlc3VsdCBhbmQgdGhlXG4gKiB0ZXh0IGVudHJ5IGlzIHJlcGxheWVkICphZnRlciogaXQsIHNvIHRoZSBjb252ZXJzYXRpb24gZW5kcyB3aXRoIGFcbiAqIHRyYWlsaW5nIGFzc2lzdGFudCB0ZXh0IG1lc3NhZ2UuIEFudGhyb3BpYyBpbnRlcnByZXRzIHRoYXQgYXMgYVxuICogcHJlZmlsbCByZXF1ZXN0IGFuZCByZWplY3RzIGl0IG9uIERhdGFicmlja3MgKHRoZSB1cHN0cmVhbSBCZWRyb2NrXG4gKiByb3V0ZSBkaXNhbGxvd3MgcHJlZmlsbCkuXG4gKlxuICogRml4OiB3aGVuIHRoZSBsYXN0IG1lc3NhZ2UgaXMgYW4gYXNzaXN0YW50IHRleHQgd2l0aCBubyBgdG9vbF9jYWxsc2BcbiAqIGFuZCB0aGUgY2hhaW4gaW1tZWRpYXRlbHkgYmVmb3JlIGl0IGlzIGBhc3Npc3RhbnQodG9vbF9jYWxscz0uLi4pYFxuICogZm9sbG93ZWQgb25seSBieSBgdG9vbCguLi4pYCByZXN1bHRzLCBmb2xkIHRoZSB0cmFpbGluZyB0ZXh0IGJhY2tcbiAqIGludG8gdGhlIGBjb250ZW50YCBvZiB0aGF0IG9wZW5pbmcgYXNzaXN0YW50IGFuZCBkcm9wIHRoZSBkdXBsaWNhdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXBhaXJBc3Npc3RhbnRQcmVmaWxsKG1lc3NhZ2VzOiBTZXJ2aW5nQ2hhdE1lc3NhZ2VbXSk6IGJvb2xlYW4ge1xuICBpZiAobWVzc2FnZXMubGVuZ3RoIDwgMikgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBsYXN0ID0gbWVzc2FnZXNbbWVzc2FnZXMubGVuZ3RoIC0gMV07XG4gIGlmICghbGFzdCB8fCBsYXN0LnJvbGUgIT09IFwiYXNzaXN0YW50XCIgfHwgKGxhc3QudG9vbF9jYWxscyAmJiBsYXN0LnRvb2xfY2FsbHMubGVuZ3RoID4gMCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBsZXQgaSA9IG1lc3NhZ2VzLmxlbmd0aCAtIDI7XG4gIHdoaWxlIChpID49IDAgJiYgbWVzc2FnZXNbaV0/LnJvbGUgPT09IFwidG9vbFwiKSBpLS07XG4gIGlmIChpIDwgMCkgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBvcGVuZXIgPSBtZXNzYWdlc1tpXTtcbiAgaWYgKFxuICAgICFvcGVuZXIgfHxcbiAgICBvcGVuZXIucm9sZSAhPT0gXCJhc3Npc3RhbnRcIiB8fFxuICAgICFvcGVuZXIudG9vbF9jYWxscyB8fFxuICAgIG9wZW5lci50b29sX2NhbGxzLmxlbmd0aCA9PT0gMFxuICApIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBjb25zdCBtZXJnZWQgPSBbXG4gICAgc3RyaW5nVXRpbHMudHJpbVRvTnVsbCh0ZXh0RnJvbVNlcnZpbmdDb250ZW50KG9wZW5lci5jb250ZW50KSksXG4gICAgc3RyaW5nVXRpbHMudHJpbVRvTnVsbCh0ZXh0RnJvbVNlcnZpbmdDb250ZW50KGxhc3QuY29udGVudCkpLFxuICBdXG4gICAgLmZpbHRlcigocyk6IHMgaXMgc3RyaW5nID0+IHMgIT09IG51bGwpXG4gICAgLmpvaW4oXCJcXG5cXG5cIik7XG4gIG9wZW5lci5jb250ZW50ID0gbWVyZ2VkO1xuICBtZXNzYWdlcy5wb3AoKTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKlxuICogRmxhdHRlbiBjb250ZW50IHRvIHRoZSBwcm9zZSBhIGh1bWFuIHdvdWxkIHJlYWQ6IHRleHQgcGFydHMgb25seSwgc2VwYXJhdGVkXG4gKiBieSBibGFuayBsaW5lcywgc2luY2UgdGhlIHJlc3VsdCBpcyBzcGxpY2VkIGludG8gYW5vdGhlciB0dXJuJ3MgbWVzc2FnZSBib2R5LlxuICovXG5mdW5jdGlvbiB0ZXh0RnJvbVNlcnZpbmdDb250ZW50KGNvbnRlbnQ6IFNlcnZpbmdDaGF0TWVzc2FnZVtcImNvbnRlbnRcIl0pOiBzdHJpbmcge1xuICByZXR1cm4gb3BlbmFpQ2hhdC5jaGF0Q29udGVudFRvVGV4dChjb250ZW50LCB7IHNlcGFyYXRvcjogXCJcXG5cXG5cIiwgdHlwZXM6IFtcInRleHRcIl0gfSk7XG59XG5cbi8qKlxuICogV2hldGhlciBhIHR1cm4gY2FycmllcyBub3RoaW5nIHdvcnRoIHJlcGxheWluZy4gRGVsaWJlcmF0ZWx5IHN0cmljdGVyIHRoYW5cbiAqIFwiaGFzIG5vIHRleHRcIjogYSBwYXJ0IG9mIGFueSBvdGhlciB0eXBlIChhbiBpbWFnZSwgYSBjYWNoZSBtYXJrZXIpIGNvdW50cyBhc1xuICogY29udGVudCwgc28gYSBtZXNzYWdlIGhvbGRpbmcgb25lIGlzIGtlcHQgZXZlbiB0aG91Z2ggaXQgaGFzIG5vIHByb3NlLlxuICovXG5mdW5jdGlvbiBpc0VtcHR5U2VydmluZ0NvbnRlbnQoY29udGVudDogU2VydmluZ0NoYXRNZXNzYWdlW1wiY29udGVudFwiXSk6IGJvb2xlYW4ge1xuICBpZiAoY29udGVudCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKHR5cGVvZiBjb250ZW50ID09PSBcInN0cmluZ1wiKSByZXR1cm4gY29udGVudC50cmltKCkubGVuZ3RoID09PSAwO1xuICBjb25zdCBwYXJ0cyA9IG9wZW5haUNoYXQuY2hhdENvbnRlbnRQYXJ0cyhjb250ZW50KTtcbiAgaWYgKCFwYXJ0cykgcmV0dXJuIHRydWU7XG4gIHJldHVybiBwYXJ0cy5ldmVyeSgocGFydCkgPT4ge1xuICAgIGlmIChwYXJ0Py50eXBlID09PSBcInRleHRcIikge1xuICAgICAgcmV0dXJuIHR5cGVvZiBwYXJ0LnRleHQgIT09IFwic3RyaW5nXCIgfHwgcGFydC50ZXh0LnRyaW0oKS5sZW5ndGggPT09IDA7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbiAgfSk7XG59XG5cbi8qKlxuICogUGFyc2UsIHNhbml0aXplLCBhbmQgcmUtc2VyaWFsaXplIGEgYC9zZXJ2aW5nLWVuZHBvaW50cy8uLi5gIG5vbi1zdHJlYW1pbmdcbiAqIEpTT04gUkVTUE9OU0UgYm9keS4gUmV0dXJucyB0aGUgb3JpZ2luYWwgc3RyaW5nIHZlcmJhdGltIHdoZW4gdGhlIGJvZHkgaXNcbiAqIG5vdCBKU09OIG9yIG5vIHJld3JpdGUgd2FzIG5lZWRlZCwgbWlycm9yaW5nXG4gKiB7QGxpbmsgcmV3cml0ZVNlcnZpbmdCb2R5fSBvbiB0aGUgcmVxdWVzdCBzaWRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmV3cml0ZVNlcnZpbmdSZXNwb25zZUJvZHkoYm9keTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcGFyc2VkID0ganNvbi5wYXJzZVJlY29yZChib2R5KTtcbiAgaWYgKCFwYXJzZWQpIHJldHVybiBib2R5O1xuICByZXR1cm4gZmxhdHRlbkNob2ljZU1lc3NhZ2VDb250ZW50KHBhcnNlZCkgPyBKU09OLnN0cmluZ2lmeShwYXJzZWQpIDogYm9keTtcbn1cblxuLyoqXG4gKiBSZXBhaXIgYXJyYXktdmFsdWVkIGBjaG9pY2VzW10uZGVsdGEuY29udGVudGAgaW5zaWRlIGFuIE9wZW5BSSBTU0Ugc3RyZWFtXG4gKiB3aXRob3V0IGJ1ZmZlcmluZyB0aGUgcmVzcG9uc2UuIFRoZSBkZWNvZGVyIHJldGFpbnMgcGFydGlhbCBsaW5lcyBhY3Jvc3NcbiAqIGFyYml0cmFyeSBuZXR3b3JrIGNodW5rIGJvdW5kYXJpZXM7IGVhY2ggY29tcGxldGUgYGRhdGE6YCBsaW5lIGlzIHBhcnNlZCBhbmRcbiAqIHJlLWVuY29kZWQgb25seSB3aGVuIGl0cyBjb250ZW50IG5lZWRzIG5vcm1hbGl6YXRpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXdyaXRlU2VydmluZ1Jlc3BvbnNlU3RyZWFtKFxuICBib2R5OiBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5Pixcbik6IFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+IHtcbiAgY29uc3QgZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpO1xuICBjb25zdCBlbmNvZGVyID0gbmV3IFRleHRFbmNvZGVyKCk7XG4gIGxldCBidWZmZXIgPSBcIlwiO1xuXG4gIHJldHVybiBib2R5LnBpcGVUaHJvdWdoKFxuICAgIG5ldyBUcmFuc2Zvcm1TdHJlYW08VWludDhBcnJheSwgVWludDhBcnJheT4oe1xuICAgICAgdHJhbnNmb3JtKGNodW5rLCBjb250cm9sbGVyKSB7XG4gICAgICAgIGJ1ZmZlciArPSBkZWNvZGVyLmRlY29kZShjaHVuaywgeyBzdHJlYW06IHRydWUgfSk7XG4gICAgICAgIGxldCBuZXdsaW5lID0gYnVmZmVyLmluZGV4T2YoXCJcXG5cIik7XG4gICAgICAgIHdoaWxlIChuZXdsaW5lID49IDApIHtcbiAgICAgICAgICBjb25zdCBsaW5lID0gYnVmZmVyLnNsaWNlKDAsIG5ld2xpbmUgKyAxKTtcbiAgICAgICAgICBidWZmZXIgPSBidWZmZXIuc2xpY2UobmV3bGluZSArIDEpO1xuICAgICAgICAgIGNvbnRyb2xsZXIuZW5xdWV1ZShlbmNvZGVyLmVuY29kZShyZXdyaXRlU2VydmluZ1Jlc3BvbnNlU3RyZWFtTGluZShsaW5lKSkpO1xuICAgICAgICAgIG5ld2xpbmUgPSBidWZmZXIuaW5kZXhPZihcIlxcblwiKTtcbiAgICAgICAgfVxuICAgICAgfSxcbiAgICAgIGZsdXNoKGNvbnRyb2xsZXIpIHtcbiAgICAgICAgYnVmZmVyICs9IGRlY29kZXIuZGVjb2RlKCk7XG4gICAgICAgIGlmIChidWZmZXIpIGNvbnRyb2xsZXIuZW5xdWV1ZShlbmNvZGVyLmVuY29kZShyZXdyaXRlU2VydmluZ1Jlc3BvbnNlU3RyZWFtTGluZShidWZmZXIpKSk7XG4gICAgICB9LFxuICAgIH0pLFxuICApO1xufVxuXG4vKiogTm9ybWFsaXplIG9uZSBTU0UgbGluZSB3aGlsZSBwcmVzZXJ2aW5nIGl0cyBgZGF0YTpgIHNwYWNpbmcgYW5kIGxpbmUgZW5kaW5nLiAqL1xuZnVuY3Rpb24gcmV3cml0ZVNlcnZpbmdSZXNwb25zZVN0cmVhbUxpbmUobGluZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgbGluZUVuZGluZyA9IGxpbmUuZW5kc1dpdGgoXCJcXHJcXG5cIikgPyBcIlxcclxcblwiIDogbGluZS5lbmRzV2l0aChcIlxcblwiKSA/IFwiXFxuXCIgOiBcIlwiO1xuICBjb25zdCBjb250ZW50ID0gbGluZUVuZGluZyA/IGxpbmUuc2xpY2UoMCwgLWxpbmVFbmRpbmcubGVuZ3RoKSA6IGxpbmU7XG4gIGNvbnN0IG1hdGNoID0gL14oZGF0YTpcXHMqKSguKikkLy5leGVjKGNvbnRlbnQpO1xuICBpZiAoIW1hdGNoIHx8IG1hdGNoWzJdID09PSBcIltET05FXVwiKSByZXR1cm4gbGluZTtcblxuICBjb25zdCBwYXJzZWQgPSBqc29uLnBhcnNlUmVjb3JkKG1hdGNoWzJdKTtcbiAgaWYgKCFwYXJzZWQgfHwgIWZsYXR0ZW5DaG9pY2VEZWx0YUNvbnRlbnQocGFyc2VkKSkgcmV0dXJuIGxpbmU7XG4gIHJldHVybiBgJHttYXRjaFsxXX0ke0pTT04uc3RyaW5naWZ5KHBhcnNlZCl9JHtsaW5lRW5kaW5nfWA7XG59XG5cbi8qKlxuICogQ29sbGFwc2UgYSBzdHJ1Y3R1cmVkIGBjaG9pY2VzW10ubWVzc2FnZS5jb250ZW50YCBhcnJheSB0byB0aGUgcGxhaW4gc3RyaW5nXG4gKiB0aGUgT3BlbkFJIENoYXQgQ29tcGxldGlvbnMgY29udHJhY3Qgc3BlY2lmaWVzLlxuICpcbiAqIERhdGFicmlja3MtaG9zdGVkIEdlbWluaSBhbnN3ZXJzIGEgbm9uLXN0cmVhbWluZyBgL2NoYXQvY29tcGxldGlvbnNgIGNhbGxcbiAqIHdpdGggdGhlIEdlbWluaS1uYXRpdmUgcGFydHMgc2hhcGU6XG4gKlxuICogYGBganNvblxuICogXCJjb250ZW50XCI6IFt7IFwidHlwZVwiOiBcInRleHRcIiwgXCJ0ZXh0XCI6IFwiLi4uXCIsIFwidGhvdWdodFNpZ25hdHVyZVwiOiBcIi4uLlwiIH1dXG4gKiBgYGBcbiAqXG4gKiBgQGFpLXNkay9vcGVuYWktY29tcGF0aWJsZWAgdmFsaWRhdGVzIHRoZSByZXNwb25zZSBhZ2FpbnN0IHRoZSBPcGVuQUlcbiAqIHNjaGVtYSwgd2hlcmUgYGNvbnRlbnRgIGlzIGEgbnVsbGFibGUgc3RyaW5nLCBzbyBpdCB0aHJvd3NcbiAqIGBUeXBlIHZhbGlkYXRpb24gZmFpbGVkOiAuLi4gZXhwZWN0ZWQgc3RyaW5nLCByZWNlaXZlZCBhcnJheWAgYW5kIHRoZSB3aG9sZVxuICogY2FsbCBmYWlscyAoYEFJX0FQSUNhbGxFcnJvcjogSW52YWxpZCBKU09OIHJlc3BvbnNlYCBvbiBhbiBIVFRQIDIwMCkuIE1hc3RyYVxuICogdXNlcyBgZG9HZW5lcmF0ZWAgZm9yIGl0cyBzaWRlIGNhbGxzLCBzbyB0aGUgdmlzaWJsZSBzeW1wdG9tIGlzXG4gKiBgRXJyb3IgZ2VuZXJhdGluZyB0aXRsZWAgLSBldmVyeSB0aHJlYWQga2VlcHMgaXRzIHBsYWNlaG9sZGVyIG5hbWUuXG4gKlxuICogRmxhdHRlbmluZyBvbiB0aGUgd2lyZSBrZWVwcyB0aGUgcmVwYWlyIGluIG9uZSBwbGFjZTogbmVpdGhlciB0aGUgYWdlbnQnc1xuICogc3RvcmVkIHRyYW5zY3JpcHQgbm9yIHRoZSBVSSBoYXMgdG8ga25vdyB0aGUgcHJvdmlkZXIgZW1pdHRlZCBwYXJ0cy4gQW55XG4gKiBub24tdGV4dCBwYXJ0IChhIHJlYXNvbmluZyBibG9jaywgYHRob3VnaHRTaWduYXR1cmVgLW9ubHkgZW50cnksIG9yIGlubGluZVxuICogaW1hZ2UpIGNvbnRyaWJ1dGVzIG5vdGhpbmcsIG1hdGNoaW5nIHtAbGluayBvcGVuYWlDaGF0LmNoYXRDb250ZW50VG9UZXh0fSxcbiAqIGFuZCBhbiBhbGwtcGFydHMtZW1wdHkgbWVzc2FnZSBmbGF0dGVucyB0byBgXCJcImAgcmF0aGVyIHRoYW4gYmVpbmcgZHJvcHBlZCwgc29cbiAqIGBmaW5pc2hfcmVhc29uYCBhbmQgYHVzYWdlYCBzdGlsbCByb3VuZC10cmlwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmxhdHRlbkNob2ljZU1lc3NhZ2VDb250ZW50KHBheWxvYWQ6IFJlY29yZDxzdHJpbmcsIHVua25vd24+KTogYm9vbGVhbiB7XG4gIHJldHVybiBmbGF0dGVuQ2hvaWNlQ29udGVudChwYXlsb2FkLCBcIm1lc3NhZ2VcIik7XG59XG5cbi8qKlxuICogQ29sbGFwc2Ugc3RydWN0dXJlZCBzdHJlYW1pbmcgYGNob2ljZXNbXS5kZWx0YS5jb250ZW50YCBhcnJheXMgdG8gc3RyaW5ncy5cbiAqIENsYXVkZSByZWFzb25pbmctb25seSBjaHVua3MgYmVjb21lIGFuIGVtcHR5IGNvbnRlbnQgZGVsdGEgd2hpbGUgdGV4dCBwYXJ0c1xuICogYXJlIGNvbmNhdGVuYXRlZCBpbiBvcmRlci5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsYXR0ZW5DaG9pY2VEZWx0YUNvbnRlbnQocGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4pOiBib29sZWFuIHtcbiAgcmV0dXJuIGZsYXR0ZW5DaG9pY2VDb250ZW50KHBheWxvYWQsIFwiZGVsdGFcIik7XG59XG5cbi8qKiBTaGFyZWQgY2hvaWNlIHdhbGtlciBmb3IgYnVmZmVyZWQgYG1lc3NhZ2VgIGFuZCBzdHJlYW1pbmcgYGRlbHRhYCBwYXlsb2Fkcy4gKi9cbmZ1bmN0aW9uIGZsYXR0ZW5DaG9pY2VDb250ZW50KFxuICBwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbiAgZmllbGQ6IFwibWVzc2FnZVwiIHwgXCJkZWx0YVwiLFxuKTogYm9vbGVhbiB7XG4gIGlmICghQXJyYXkuaXNBcnJheShwYXlsb2FkLmNob2ljZXMpKSByZXR1cm4gZmFsc2U7XG4gIGxldCBjaGFuZ2VkID0gZmFsc2U7XG4gIGZvciAoY29uc3QgY2hvaWNlIG9mIHBheWxvYWQuY2hvaWNlcykge1xuICAgIGlmICghY2hvaWNlIHx8IHR5cGVvZiBjaG9pY2UgIT09IFwib2JqZWN0XCIpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGNvbnRhaW5lciA9IChjaG9pY2UgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW2ZpZWxkXTtcbiAgICBpZiAoIWNvbnRhaW5lciB8fCB0eXBlb2YgY29udGFpbmVyICE9PSBcIm9iamVjdFwiKSBjb250aW51ZTtcbiAgICBjb25zdCB0YXJnZXQgPSBjb250YWluZXIgYXMgeyBjb250ZW50PzogdW5rbm93biB9O1xuICAgIGNvbnN0IHBhcnRzID0gb3BlbmFpQ2hhdC5jaGF0Q29udGVudFBhcnRzKHRhcmdldC5jb250ZW50KTtcbiAgICBpZiAoIXBhcnRzKSBjb250aW51ZTtcbiAgICB0YXJnZXQuY29udGVudCA9IG9wZW5haUNoYXQuY2hhdENvbnRlbnRUb1RleHQocGFydHMsIHsgdHlwZXM6IFtcInRleHRcIl0gfSk7XG4gICAgY2hhbmdlZCA9IHRydWU7XG4gIH1cbiAgcmV0dXJuIGNoYW5nZWQ7XG59XG4iXX0=
6
+ export { applyToolReasoningCompatibility, flattenChoiceDeltaContent, flattenChoiceMessageContent, repairAssistantPrefill, rewriteServingBody, rewriteServingRequest, rewriteServingResponseBody, rewriteServingResponseStream, stripReasoningFromServingMessages, } from "@dbx-tools/model/serving-wire";
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmluZy1zYW5pdGl6ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aW5nLXNhbml0aXplLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSCxPQUFPLEVBQ0wsK0JBQStCLEVBQy9CLHlCQUF5QixFQUN6QiwyQkFBMkIsRUFDM0Isc0JBQXNCLEVBQ3RCLGtCQUFrQixFQUNsQixxQkFBcUIsRUFDckIsMEJBQTBCLEVBQzFCLDRCQUE0QixFQUM1QixpQ0FBaUMsR0FHbEMsTUFBTSwrQkFBK0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRGF0YWJyaWNrcyBNb2RlbCBTZXJ2aW5nIHdpcmUgcmVwYWlycyBzaGFyZWQgd2l0aCB0aGUgbW9kZWwgZ2F0ZXdheS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuZXhwb3J0IHtcbiAgYXBwbHlUb29sUmVhc29uaW5nQ29tcGF0aWJpbGl0eSxcbiAgZmxhdHRlbkNob2ljZURlbHRhQ29udGVudCxcbiAgZmxhdHRlbkNob2ljZU1lc3NhZ2VDb250ZW50LFxuICByZXBhaXJBc3Npc3RhbnRQcmVmaWxsLFxuICByZXdyaXRlU2VydmluZ0JvZHksXG4gIHJld3JpdGVTZXJ2aW5nUmVxdWVzdCxcbiAgcmV3cml0ZVNlcnZpbmdSZXNwb25zZUJvZHksXG4gIHJld3JpdGVTZXJ2aW5nUmVzcG9uc2VTdHJlYW0sXG4gIHN0cmlwUmVhc29uaW5nRnJvbVNlcnZpbmdNZXNzYWdlcyxcbiAgdHlwZSBSZXdyaXR0ZW5TZXJ2aW5nUmVxdWVzdCxcbiAgdHlwZSBTZXJ2aW5nQ2hhdE1lc3NhZ2UsXG59IGZyb20gXCJAZGJ4LXRvb2xzL21vZGVsL3NlcnZpbmctd2lyZVwiO1xuIl19
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Copy each Mastra chat turn's request/response onto the active OTel
3
- * root span so Databricks-managed MLflow can display them.
2
+ * Copy each Mastra chat turn's request/response onto its OTel root span
3
+ * so Databricks-managed MLflow can display them.
4
4
  *
5
5
  * Why this exists: MLflow's UC `<target>_trace_unified` view picks the
6
6
  * one span whose `parent_span_id` is empty and reads request/response
@@ -10,10 +10,10 @@
10
10
  * the view never reads, so chat traces arrive with both columns null
11
11
  * even when the spans themselves look healthy.
12
12
  *
13
- * The active span inside the Mastra sub-app is still AppKit's HTTP
14
- * server span (OTel context is async-local). With `OTEL_PROPAGATORS=none`
15
- * that span is the trace root - see the package README's observability
16
- * section for why Apps ingress `traceparent` otherwise hides every turn.
13
+ * AppKit's HTTP instrumentation records the server span in OTel RPC metadata,
14
+ * which remains available even when Express makes a middleware-layer child
15
+ * active. When instrumentation is unavailable, this module creates one
16
+ * request-lifetime server span and runs Mastra under it.
17
17
  *
18
18
  * @module
19
19
  */
@@ -32,12 +32,14 @@ export declare const MLFLOW_SPAN_OUTPUTS_ATTR = "mlflow.spanOutputs";
32
32
  * reassembled here.
33
33
  */
34
34
  export declare function assistantTextFromSse(body: string): string;
35
+ /** Read the final assistant text from a non-streaming Mastra response. */
36
+ export declare function assistantTextFromJson(body: unknown): string;
35
37
  /**
36
- * Express middleware that stamps chat turn I/O onto the active OTel span.
38
+ * Express middleware that stamps chat turn I/O onto the exported OTel root.
37
39
  *
38
- * Tee `res.write` / `res.end` instead of listening for `finish`: the HTTP
39
- * instrumentation ends the root span on finish, and an attribute set after
40
- * a span ends never reaches the exporter.
40
+ * Tee `res.write`, `res.json`, and `res.end` instead of listening for `finish`:
41
+ * HTTP instrumentation ends its server span on finish, and attributes set
42
+ * after a span ends never reach the exporter.
41
43
  *
42
44
  * `path` is mount-relative (what the Mastra sub-app sees), e.g.
43
45
  * `/agents/support/stream`.
@@ -47,7 +49,7 @@ export declare function chatTurnTraceIoMiddleware(req: express.Request, res: exp
47
49
  * Install {@link chatTurnTraceIoMiddleware} on a Mastra Express sub-app.
48
50
  *
49
51
  * Call before `MastraServer.init()` so the layer sits ahead of the agent
50
- * routes. Safe to call unconditionally: with no active span (local, no
51
- * OTLP) the middleware is a no-op.
52
+ * routes. Safe to call unconditionally: when no recording tracer is registered,
53
+ * the middleware is a no-op.
52
54
  */
53
55
  export declare function attachChatTurnTraceIo(app: express.Express): void;