@tanstack/ai 0.20.1 → 0.21.1
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/dist/esm/activities/chat/index.d.ts +1 -1
- package/dist/esm/activities/chat/index.js +357 -258
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.d.ts +10 -1
- package/dist/esm/activities/chat/middleware/compose.js +55 -0
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/middleware/index.d.ts +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +35 -3
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.d.ts +12 -1
- package/dist/esm/activities/chat/tools/schema-converter.js +13 -4
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/extend-adapter.js.map +1 -1
- package/dist/esm/index.d.ts +2 -2
- package/dist/esm/index.js +2 -1
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/middlewares/otel.js +1 -4
- package/dist/esm/middlewares/otel.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/utilities/ag-ui-wire.js +4 -1
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/package.json +3 -3
- package/skills/ai-core/middleware/SKILL.md +124 -18
- package/skills/ai-core/structured-outputs/SKILL.md +13 -0
- package/src/activities/chat/index.ts +653 -370
- package/src/activities/chat/messages.ts +1 -1
- package/src/activities/chat/middleware/compose.ts +65 -5
- package/src/activities/chat/middleware/index.ts +1 -0
- package/src/activities/chat/middleware/types.ts +53 -2
- package/src/activities/chat/stream/processor.ts +2 -2
- package/src/activities/chat/tools/schema-converter.ts +22 -7
- package/src/activities/generateImage/index.ts +3 -3
- package/src/extend-adapter.ts +1 -1
- package/src/index.ts +5 -1
- package/src/middlewares/content-guard.ts +1 -1
- package/src/middlewares/otel.ts +7 -10
- package/src/strip-to-spec-middleware.ts +1 -4
- package/src/utilities/ag-ui-wire.ts +2 -1
|
@@ -11,6 +11,7 @@ import type {
|
|
|
11
11
|
ErrorInfo,
|
|
12
12
|
FinishInfo,
|
|
13
13
|
IterationInfo,
|
|
14
|
+
StructuredOutputMiddlewareConfig,
|
|
14
15
|
ToolCallHookContext,
|
|
15
16
|
ToolPhaseCompleteInfo,
|
|
16
17
|
UsageInfo,
|
|
@@ -71,7 +72,7 @@ export class MiddlewareRunner {
|
|
|
71
72
|
current = { ...current, ...result }
|
|
72
73
|
if (!skip) {
|
|
73
74
|
this.logger.config(
|
|
74
|
-
`middleware=${mw.name ?? 'unnamed'} keys=${Object.keys(result
|
|
75
|
+
`middleware=${mw.name ?? 'unnamed'} keys=${Object.keys(result).join(',')}`,
|
|
75
76
|
{
|
|
76
77
|
middleware: mw.name ?? 'unnamed',
|
|
77
78
|
changes: result,
|
|
@@ -94,7 +95,66 @@ export class MiddlewareRunner {
|
|
|
94
95
|
...base,
|
|
95
96
|
middlewareName: mw.name || 'unnamed',
|
|
96
97
|
iteration: ctx.iteration,
|
|
97
|
-
changes: result
|
|
98
|
+
changes: result,
|
|
99
|
+
})
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return current
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Pipe config through all middleware onStructuredOutputConfig hooks in order.
|
|
109
|
+
* Each middleware receives the merged config from previous middleware.
|
|
110
|
+
* Partial returns are shallow-merged with the current config.
|
|
111
|
+
*
|
|
112
|
+
* Called once at the structured-output boundary, before runOnConfig at the
|
|
113
|
+
* same boundary (which receives a ChatMiddlewareConfig view, no outputSchema).
|
|
114
|
+
*/
|
|
115
|
+
async runOnStructuredOutputConfig(
|
|
116
|
+
ctx: ChatMiddlewareContext,
|
|
117
|
+
config: StructuredOutputMiddlewareConfig,
|
|
118
|
+
): Promise<StructuredOutputMiddlewareConfig> {
|
|
119
|
+
let current = config
|
|
120
|
+
for (const mw of this.middlewares) {
|
|
121
|
+
if (mw.onStructuredOutputConfig) {
|
|
122
|
+
const skip = shouldSkipInstrumentation(mw)
|
|
123
|
+
const start = Date.now()
|
|
124
|
+
const result = await mw.onStructuredOutputConfig(ctx, current)
|
|
125
|
+
const hasTransform = result !== undefined && result !== null
|
|
126
|
+
if (hasTransform) {
|
|
127
|
+
current = { ...current, ...result }
|
|
128
|
+
if (!skip) {
|
|
129
|
+
this.logger.config(
|
|
130
|
+
`middleware=${mw.name ?? 'unnamed'} keys=${Object.keys(result).join(',')}`,
|
|
131
|
+
{
|
|
132
|
+
middleware: mw.name ?? 'unnamed',
|
|
133
|
+
changes: result,
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (!skip) {
|
|
139
|
+
const base = instrumentCtx(ctx)
|
|
140
|
+
aiEventClient.emit('middleware:hook:executed', {
|
|
141
|
+
...base,
|
|
142
|
+
middlewareName: mw.name || 'unnamed',
|
|
143
|
+
hookName: 'onStructuredOutputConfig',
|
|
144
|
+
iteration: ctx.iteration,
|
|
145
|
+
duration: Date.now() - start,
|
|
146
|
+
hasTransform,
|
|
147
|
+
})
|
|
148
|
+
if (hasTransform) {
|
|
149
|
+
aiEventClient.emit('middleware:config:transformed', {
|
|
150
|
+
...base,
|
|
151
|
+
middlewareName: mw.name || 'unnamed',
|
|
152
|
+
iteration: ctx.iteration,
|
|
153
|
+
// `result` is `Partial<StructuredOutputMiddlewareConfig>` —
|
|
154
|
+
// Object.fromEntries(Object.entries(result)) yields the
|
|
155
|
+
// structural `Record<string, unknown>` the event emitter wants
|
|
156
|
+
// without an `as` cast.
|
|
157
|
+
changes: Object.fromEntries(Object.entries(result)),
|
|
98
158
|
})
|
|
99
159
|
}
|
|
100
160
|
}
|
|
@@ -152,7 +212,7 @@ export class MiddlewareRunner {
|
|
|
152
212
|
const nextChunks: Array<StreamChunk> = []
|
|
153
213
|
for (const c of chunks) {
|
|
154
214
|
// Cast: @ag-ui/core Zod passthrough types prevent direct `.type` access
|
|
155
|
-
const chunkType =
|
|
215
|
+
const chunkType = c.type
|
|
156
216
|
if (!skip) {
|
|
157
217
|
this.logger.middleware(
|
|
158
218
|
`hook=onChunk middleware=${mw.name ?? 'unnamed'} in=${chunkType}`,
|
|
@@ -188,7 +248,7 @@ export class MiddlewareRunner {
|
|
|
188
248
|
nextChunks.push(...result)
|
|
189
249
|
if (!skip) {
|
|
190
250
|
this.logger.middleware(
|
|
191
|
-
`hook=onChunk middleware=${mw.name ?? 'unnamed'} in=${chunkType} out=[${result.map((r: StreamChunk) =>
|
|
251
|
+
`hook=onChunk middleware=${mw.name ?? 'unnamed'} in=${chunkType} out=[${result.map((r: StreamChunk) => r.type).join(',')}]`,
|
|
192
252
|
{
|
|
193
253
|
middleware: mw.name ?? 'unnamed',
|
|
194
254
|
hook: 'onChunk',
|
|
@@ -209,7 +269,7 @@ export class MiddlewareRunner {
|
|
|
209
269
|
nextChunks.push(result)
|
|
210
270
|
if (!skip) {
|
|
211
271
|
this.logger.middleware(
|
|
212
|
-
`hook=onChunk middleware=${mw.name ?? 'unnamed'} in=${chunkType} out=${
|
|
272
|
+
`hook=onChunk middleware=${mw.name ?? 'unnamed'} in=${chunkType} out=${result.type}`,
|
|
213
273
|
{
|
|
214
274
|
middleware: mw.name ?? 'unnamed',
|
|
215
275
|
hook: 'onChunk',
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
JSONSchema,
|
|
3
|
+
ModelMessage,
|
|
4
|
+
StreamChunk,
|
|
5
|
+
Tool,
|
|
6
|
+
ToolCall,
|
|
7
|
+
} from '../../../types'
|
|
2
8
|
import type { SystemPrompt } from '../../../system-prompts'
|
|
3
9
|
|
|
4
10
|
// ===========================
|
|
@@ -12,6 +18,8 @@ import type { SystemPrompt } from '../../../system-prompts'
|
|
|
12
18
|
* - 'modelStream': During model streaming
|
|
13
19
|
* - 'beforeTools': Before tool execution phase
|
|
14
20
|
* - 'afterTools': After tool execution phase
|
|
21
|
+
* - 'structuredOutput': During the final structured-output adapter call (set
|
|
22
|
+
* for chunks from adapter.structuredOutputStream or the synthesized fallback)
|
|
15
23
|
*/
|
|
16
24
|
export type ChatMiddlewarePhase =
|
|
17
25
|
| 'init'
|
|
@@ -19,6 +27,7 @@ export type ChatMiddlewarePhase =
|
|
|
19
27
|
| 'modelStream'
|
|
20
28
|
| 'beforeTools'
|
|
21
29
|
| 'afterTools'
|
|
30
|
+
| 'structuredOutput'
|
|
22
31
|
|
|
23
32
|
/**
|
|
24
33
|
* Stable context object passed to all middleware hooks.
|
|
@@ -125,6 +134,24 @@ export interface ChatMiddlewareConfig {
|
|
|
125
134
|
modelOptions?: Record<string, unknown> | undefined
|
|
126
135
|
}
|
|
127
136
|
|
|
137
|
+
/**
|
|
138
|
+
* Config passed to onStructuredOutputConfig.
|
|
139
|
+
*
|
|
140
|
+
* Mirrors ChatMiddlewareConfig minus `tools` (the final structured-output call
|
|
141
|
+
* is a single typed-response request, not an agentic loop — tools cannot be
|
|
142
|
+
* forwarded to it), plus the `outputSchema` being sent to the provider.
|
|
143
|
+
* Middleware may transform the schema (e.g., inject $defs, strip
|
|
144
|
+
* vendor-incompatible keywords) by returning a partial that includes
|
|
145
|
+
* `outputSchema`.
|
|
146
|
+
*/
|
|
147
|
+
export interface StructuredOutputMiddlewareConfig extends Omit<
|
|
148
|
+
ChatMiddlewareConfig,
|
|
149
|
+
'tools'
|
|
150
|
+
> {
|
|
151
|
+
/** JSON Schema being sent to the provider for structured output. */
|
|
152
|
+
outputSchema: JSONSchema
|
|
153
|
+
}
|
|
154
|
+
|
|
128
155
|
// ===========================
|
|
129
156
|
// Tool Call Hook Context
|
|
130
157
|
// ===========================
|
|
@@ -337,7 +364,31 @@ export interface ChatMiddleware {
|
|
|
337
364
|
| void
|
|
338
365
|
| null
|
|
339
366
|
| Partial<ChatMiddlewareConfig>
|
|
340
|
-
| Promise<void | Partial<ChatMiddlewareConfig>>
|
|
367
|
+
| Promise<void | null | Partial<ChatMiddlewareConfig>>
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Called at the start of the final structured-output call (when the chat
|
|
371
|
+
* was invoked with outputSchema). Pipes through middleware in order, like
|
|
372
|
+
* onConfig, but with access to the JSON Schema being sent to the provider.
|
|
373
|
+
*
|
|
374
|
+
* Return a partial to shallow-merge into the current config, or void to
|
|
375
|
+
* pass through.
|
|
376
|
+
*
|
|
377
|
+
* Fires BEFORE onConfig at the structured-output boundary. onConfig also
|
|
378
|
+
* re-fires at the same boundary with ctx.phase === 'structuredOutput',
|
|
379
|
+
* receiving the post-onStructuredOutputConfig view of the config (minus
|
|
380
|
+
* outputSchema). Use onConfig for general-purpose transforms that apply
|
|
381
|
+
* to every adapter call; use this hook when you need to transform the
|
|
382
|
+
* outputSchema or apply structured-output-specific behavior.
|
|
383
|
+
*/
|
|
384
|
+
onStructuredOutputConfig?: (
|
|
385
|
+
ctx: ChatMiddlewareContext,
|
|
386
|
+
config: StructuredOutputMiddlewareConfig,
|
|
387
|
+
) =>
|
|
388
|
+
| void
|
|
389
|
+
| null
|
|
390
|
+
| Partial<StructuredOutputMiddlewareConfig>
|
|
391
|
+
| Promise<void | null | Partial<StructuredOutputMiddlewareConfig>>
|
|
341
392
|
|
|
342
393
|
/**
|
|
343
394
|
* Called when the chat run starts (after initial onConfig).
|
|
@@ -216,7 +216,7 @@ export class StreamProcessor {
|
|
|
216
216
|
? [{ type: 'text', content }]
|
|
217
217
|
: content.map((part) => {
|
|
218
218
|
// ContentPart types (text, image, audio, video, document) are compatible with MessagePart
|
|
219
|
-
return part
|
|
219
|
+
return part
|
|
220
220
|
})
|
|
221
221
|
|
|
222
222
|
const userMessage: UIMessage = {
|
|
@@ -479,7 +479,7 @@ export class StreamProcessor {
|
|
|
479
479
|
|
|
480
480
|
// Cast needed: @ag-ui/core Zod passthrough types add `& { [k: string]: unknown }`
|
|
481
481
|
// which prevents TypeScript from narrowing the `type` discriminant in switch.
|
|
482
|
-
const c = chunk
|
|
482
|
+
const c = chunk
|
|
483
483
|
// eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- AG-UI EventType enum members vs string-literal case labels; default branch handles untraced events.
|
|
484
484
|
switch (c.type) {
|
|
485
485
|
// AG-UI Events
|
|
@@ -58,7 +58,6 @@ export function isStandardSchema(schema: unknown): schema is StandardSchemaV1 {
|
|
|
58
58
|
typeof schema['~standard'] === 'object' &&
|
|
59
59
|
schema['~standard'] !== null &&
|
|
60
60
|
'version' in schema['~standard'] &&
|
|
61
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- runtime guard for caller-provided unknown; in-operator narrows but doesn't validate the wire payload
|
|
62
61
|
schema['~standard'].version === 1 &&
|
|
63
62
|
'validate' in schema['~standard'] &&
|
|
64
63
|
typeof schema['~standard'].validate === 'function'
|
|
@@ -340,6 +339,25 @@ export async function validateWithStandardSchema<T>(
|
|
|
340
339
|
}
|
|
341
340
|
}
|
|
342
341
|
|
|
342
|
+
/**
|
|
343
|
+
* Error thrown when Standard Schema validation fails. Carries the original
|
|
344
|
+
* `issues` array so consumers (middleware `onError`, callers catching from
|
|
345
|
+
* `chat({ outputSchema })`) can programmatically inspect each failure.
|
|
346
|
+
*/
|
|
347
|
+
export class StandardSchemaValidationError extends Error {
|
|
348
|
+
override readonly name = 'StandardSchemaValidationError'
|
|
349
|
+
readonly issues: ReadonlyArray<StandardSchemaV1.Issue>
|
|
350
|
+
|
|
351
|
+
constructor(issues: ReadonlyArray<StandardSchemaV1.Issue>) {
|
|
352
|
+
super(
|
|
353
|
+
`Validation failed: ${issues
|
|
354
|
+
.map((i) => i.message || 'Validation failed')
|
|
355
|
+
.join(', ')}`,
|
|
356
|
+
)
|
|
357
|
+
this.issues = issues
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
|
|
343
361
|
/**
|
|
344
362
|
* Synchronously validates data against a Standard Schema compliant schema.
|
|
345
363
|
* Note: Some Standard Schema implementations may only support async validation.
|
|
@@ -348,7 +366,8 @@ export async function validateWithStandardSchema<T>(
|
|
|
348
366
|
* @param schema - Standard Schema compliant schema
|
|
349
367
|
* @param data - Data to validate
|
|
350
368
|
* @returns Parsed/validated data
|
|
351
|
-
* @throws
|
|
369
|
+
* @throws StandardSchemaValidationError if validation fails; Error if the
|
|
370
|
+
* schema only supports async validation.
|
|
352
371
|
*/
|
|
353
372
|
export function parseWithStandardSchema<T>(schema: unknown, data: unknown): T {
|
|
354
373
|
if (!isStandardSchema(schema)) {
|
|
@@ -369,9 +388,5 @@ export function parseWithStandardSchema<T>(schema: unknown, data: unknown): T {
|
|
|
369
388
|
return result.value as T
|
|
370
389
|
}
|
|
371
390
|
|
|
372
|
-
|
|
373
|
-
const errorMessages = result.issues
|
|
374
|
-
.map((issue) => issue.message || 'Validation failed')
|
|
375
|
-
.join(', ')
|
|
376
|
-
throw new Error(`Validation failed: ${errorMessages}`)
|
|
391
|
+
throw new StandardSchemaValidationError(result.issues)
|
|
377
392
|
}
|
|
@@ -210,7 +210,7 @@ async function runGenerateImage<
|
|
|
210
210
|
prompt: rest.prompt,
|
|
211
211
|
numberOfImages: rest.numberOfImages,
|
|
212
212
|
size: rest.size,
|
|
213
|
-
modelOptions: rest.modelOptions
|
|
213
|
+
modelOptions: rest.modelOptions,
|
|
214
214
|
timestamp: startTime,
|
|
215
215
|
})
|
|
216
216
|
|
|
@@ -237,7 +237,7 @@ async function runGenerateImage<
|
|
|
237
237
|
b64Json: image.b64Json,
|
|
238
238
|
})),
|
|
239
239
|
duration,
|
|
240
|
-
modelOptions: rest.modelOptions
|
|
240
|
+
modelOptions: rest.modelOptions,
|
|
241
241
|
timestamp: Date.now(),
|
|
242
242
|
})
|
|
243
243
|
|
|
@@ -246,7 +246,7 @@ async function runGenerateImage<
|
|
|
246
246
|
requestId,
|
|
247
247
|
model,
|
|
248
248
|
usage: result.usage,
|
|
249
|
-
modelOptions: rest.modelOptions
|
|
249
|
+
modelOptions: rest.modelOptions,
|
|
250
250
|
timestamp: Date.now(),
|
|
251
251
|
})
|
|
252
252
|
}
|
package/src/extend-adapter.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -53,7 +53,10 @@ export {
|
|
|
53
53
|
} from './activities/chat/tools/tool-definition'
|
|
54
54
|
|
|
55
55
|
// Schema conversion (Standard JSON Schema compliant)
|
|
56
|
-
export {
|
|
56
|
+
export {
|
|
57
|
+
convertSchemaToJsonSchema,
|
|
58
|
+
StandardSchemaValidationError,
|
|
59
|
+
} from './activities/chat/tools/schema-converter'
|
|
57
60
|
|
|
58
61
|
// Stream utilities
|
|
59
62
|
export {
|
|
@@ -91,6 +94,7 @@ export type {
|
|
|
91
94
|
ChatMiddlewareContext,
|
|
92
95
|
ChatMiddlewarePhase,
|
|
93
96
|
ChatMiddlewareConfig,
|
|
97
|
+
StructuredOutputMiddlewareConfig,
|
|
94
98
|
ToolCallHookContext,
|
|
95
99
|
BeforeToolCallDecision,
|
|
96
100
|
AfterToolCallInfo,
|
package/src/middlewares/otel.ts
CHANGED
|
@@ -256,10 +256,7 @@ export function otelMiddleware(options: OtelMiddlewareOptions): ChatMiddleware {
|
|
|
256
256
|
const span = state.currentIterationSpan
|
|
257
257
|
const iteration = state.iterationCount - 1
|
|
258
258
|
safeCall('otel.onSpanEnd', () =>
|
|
259
|
-
onSpanEnd?.(
|
|
260
|
-
{ kind: 'iteration', ctx, iteration } as OtelSpanInfo<'iteration'>,
|
|
261
|
-
span,
|
|
262
|
-
),
|
|
259
|
+
onSpanEnd?.({ kind: 'iteration', ctx, iteration }, span),
|
|
263
260
|
)
|
|
264
261
|
span.end()
|
|
265
262
|
state.currentIterationSpan = null
|
|
@@ -676,7 +673,7 @@ export function otelMiddleware(options: OtelMiddlewareOptions): ChatMiddleware {
|
|
|
676
673
|
toolName: info.toolName,
|
|
677
674
|
toolCallId: info.toolCallId,
|
|
678
675
|
iteration: state.iterationCount - 1,
|
|
679
|
-
}
|
|
676
|
+
},
|
|
680
677
|
toolSpan,
|
|
681
678
|
),
|
|
682
679
|
)
|
|
@@ -709,7 +706,7 @@ export function otelMiddleware(options: OtelMiddlewareOptions): ChatMiddleware {
|
|
|
709
706
|
kind: 'iteration',
|
|
710
707
|
ctx,
|
|
711
708
|
iteration: state.iterationCount - 1,
|
|
712
|
-
}
|
|
709
|
+
},
|
|
713
710
|
iterationSpan,
|
|
714
711
|
),
|
|
715
712
|
)
|
|
@@ -729,7 +726,7 @@ export function otelMiddleware(options: OtelMiddlewareOptions): ChatMiddleware {
|
|
|
729
726
|
toolCallId: id,
|
|
730
727
|
toolName,
|
|
731
728
|
iteration: state.iterationCount - 1,
|
|
732
|
-
}
|
|
729
|
+
},
|
|
733
730
|
span,
|
|
734
731
|
),
|
|
735
732
|
)
|
|
@@ -782,7 +779,7 @@ export function otelMiddleware(options: OtelMiddlewareOptions): ChatMiddleware {
|
|
|
782
779
|
kind: 'iteration',
|
|
783
780
|
ctx,
|
|
784
781
|
iteration: state.iterationCount - 1,
|
|
785
|
-
}
|
|
782
|
+
},
|
|
786
783
|
iterationSpan,
|
|
787
784
|
),
|
|
788
785
|
)
|
|
@@ -800,7 +797,7 @@ export function otelMiddleware(options: OtelMiddlewareOptions): ChatMiddleware {
|
|
|
800
797
|
toolCallId: id,
|
|
801
798
|
toolName,
|
|
802
799
|
iteration: state.iterationCount - 1,
|
|
803
|
-
}
|
|
800
|
+
},
|
|
804
801
|
span,
|
|
805
802
|
),
|
|
806
803
|
)
|
|
@@ -845,7 +842,7 @@ export function otelMiddleware(options: OtelMiddlewareOptions): ChatMiddleware {
|
|
|
845
842
|
toolCallId: id,
|
|
846
843
|
toolName,
|
|
847
844
|
iteration: state.iterationCount - 1,
|
|
848
|
-
}
|
|
845
|
+
},
|
|
849
846
|
span,
|
|
850
847
|
),
|
|
851
848
|
)
|
|
@@ -12,10 +12,7 @@ import type { StreamChunk } from './types'
|
|
|
12
12
|
*/
|
|
13
13
|
export function stripToSpec(chunk: StreamChunk): StreamChunk {
|
|
14
14
|
// Only strip the deprecated nested error object from RUN_ERROR
|
|
15
|
-
if (
|
|
16
|
-
(chunk as StreamChunk & { type: string }).type === 'RUN_ERROR' &&
|
|
17
|
-
'error' in chunk
|
|
18
|
-
) {
|
|
15
|
+
if (chunk.type === 'RUN_ERROR' && 'error' in chunk) {
|
|
19
16
|
const { error: _deprecated, ...rest } = chunk as Record<string, unknown>
|
|
20
17
|
return rest as StreamChunk
|
|
21
18
|
}
|
|
@@ -53,6 +53,7 @@ export function uiMessagesToWire(
|
|
|
53
53
|
// Defensive: if parts is missing (ModelMessage-shaped input), pass through as-is.
|
|
54
54
|
// UIMessage always has parts; ModelMessage uses content directly.
|
|
55
55
|
const parts: ReadonlyArray<MessagePart> =
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion -- runtime input may be ModelMessage-shaped (no `parts`); cast forces the optional-chain fallback below to remain in scope
|
|
56
57
|
(msg.parts as ReadonlyArray<MessagePart> | undefined) ?? []
|
|
57
58
|
|
|
58
59
|
if (msg.role === 'system') {
|
|
@@ -161,7 +162,7 @@ function collectUserContent(
|
|
|
161
162
|
p.type === 'video' ||
|
|
162
163
|
p.type === 'document'
|
|
163
164
|
) {
|
|
164
|
-
out.push(p
|
|
165
|
+
out.push(p)
|
|
165
166
|
}
|
|
166
167
|
}
|
|
167
168
|
return out
|