@tanstack/ai 0.47.3 → 0.49.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/README.md +2 -1
- package/dist/esm/activities/chat/adapter.d.ts +5 -4
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- package/dist/esm/activities/chat/index.d.ts +4 -7
- package/dist/esm/activities/chat/index.js +201 -243
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/messages.js +115 -25
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +38 -17
- package/dist/esm/activities/chat/stream/processor.js +186 -101
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +3 -2
- package/dist/esm/activities/chat/tools/tool-calls.js +15 -10
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.js +6 -6
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/stream-generation-result.js +7 -8
- package/dist/esm/activities/stream-generation-result.js.map +1 -1
- package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +2 -1
- package/dist/esm/activities/summarize/chat-stream-summarize.js +56 -53
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
- package/dist/esm/adapter-internals.d.ts +2 -0
- package/dist/esm/adapter-internals.js +3 -1
- package/dist/esm/byok/define-provider.d.ts +23 -0
- package/dist/esm/byok/define-provider.js +19 -0
- package/dist/esm/byok/define-provider.js.map +1 -0
- package/dist/esm/byok/errors.d.ts +13 -0
- package/dist/esm/byok/errors.js +29 -0
- package/dist/esm/byok/errors.js.map +1 -0
- package/dist/esm/byok/get-key.d.ts +10 -0
- package/dist/esm/byok/get-key.js +26 -0
- package/dist/esm/byok/get-key.js.map +1 -0
- package/dist/esm/byok/missing.d.ts +11 -0
- package/dist/esm/byok/missing.js +30 -0
- package/dist/esm/byok/missing.js.map +1 -0
- package/dist/esm/byok/providers.d.ts +13 -0
- package/dist/esm/byok/providers.js +18 -0
- package/dist/esm/byok/providers.js.map +1 -0
- package/dist/esm/byok/scrub.d.ts +2 -0
- package/dist/esm/byok/scrub.js +17 -0
- package/dist/esm/byok/scrub.js.map +1 -0
- package/dist/esm/byok/server.d.ts +3 -0
- package/dist/esm/byok/server.js +3 -0
- package/dist/esm/byok.d.ts +8 -0
- package/dist/esm/byok.js +6 -0
- package/dist/esm/client.d.ts +8 -1
- package/dist/esm/client.js +7 -2
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/index.d.ts +6 -0
- package/dist/esm/index.js +6 -2
- package/dist/esm/interrupt-resume.js +4 -4
- package/dist/esm/interrupt-resume.js.map +1 -1
- package/dist/esm/middlewares/otel.js +11 -4
- package/dist/esm/middlewares/otel.js.map +1 -1
- package/dist/esm/stream-to-response.js +8 -5
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/stream-to-websocket.js +4 -2
- package/dist/esm/stream-to-websocket.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.d.ts +10 -13
- package/dist/esm/strip-to-spec-middleware.js +24 -22
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/types.d.ts +82 -305
- package/dist/esm/utilities/adapter-yield-chunk.d.ts +31 -0
- package/dist/esm/utilities/ag-ui-usage.d.ts +24 -0
- package/dist/esm/utilities/ag-ui-usage.js +66 -0
- package/dist/esm/utilities/ag-ui-usage.js.map +1 -0
- package/dist/esm/utilities/ag-ui-wire.d.ts +14 -7
- package/dist/esm/utilities/ag-ui-wire.js +71 -30
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/chat-params.d.ts +3 -3
- package/dist/esm/utilities/chat-params.js +10 -30
- package/dist/esm/utilities/chat-params.js.map +1 -1
- package/dist/esm/utilities/chunk-ids.d.ts +5 -0
- package/dist/esm/utilities/chunk-ids.js +25 -0
- package/dist/esm/utilities/chunk-ids.js.map +1 -0
- package/dist/esm/utilities/merge-metadata.d.ts +14 -0
- package/dist/esm/utilities/merge-metadata.js +43 -0
- package/dist/esm/utilities/merge-metadata.js.map +1 -0
- package/dist/esm/utilities/normalize-stream-chunk.d.ts +3 -0
- package/dist/esm/utilities/normalize-stream-chunk.js +100 -0
- package/dist/esm/utilities/normalize-stream-chunk.js.map +1 -0
- package/dist/esm/utilities/reasoning-encrypted-value.d.ts +8 -0
- package/dist/esm/utilities/reasoning-encrypted-value.js +16 -0
- package/dist/esm/utilities/reasoning-encrypted-value.js.map +1 -0
- package/dist/esm/utilities/restore-inbound-chunk.d.ts +15 -0
- package/dist/esm/utilities/restore-inbound-chunk.js +43 -0
- package/dist/esm/utilities/restore-inbound-chunk.js.map +1 -0
- package/dist/esm/utilities/spec-event-keys.d.ts +2 -0
- package/dist/esm/utilities/spec-event-keys.js +56 -0
- package/dist/esm/utilities/spec-event-keys.js.map +1 -0
- package/dist/esm/utilities/structured-output-events.d.ts +3 -3
- package/dist/esm/utilities/structured-output-events.js.map +1 -1
- package/package.json +10 -2
- package/skills/ai-core/chat-experience/SKILL.md +2 -2
- package/src/activities/chat/adapter.ts +4 -4
- package/src/activities/chat/index.ts +398 -400
- package/src/activities/chat/messages.ts +174 -34
- package/src/activities/chat/stream/processor.ts +289 -218
- package/src/activities/chat/tools/tool-calls.ts +23 -22
- package/src/activities/generateVideo/index.ts +7 -6
- package/src/activities/stream-generation-result.ts +8 -12
- package/src/activities/summarize/chat-stream-summarize.ts +94 -70
- package/src/adapter-internals.ts +2 -0
- package/src/byok/define-provider.ts +46 -0
- package/src/byok/errors.ts +36 -0
- package/src/byok/get-key.ts +27 -0
- package/src/byok/missing.ts +43 -0
- package/src/byok/providers.ts +27 -0
- package/src/byok/scrub.ts +16 -0
- package/src/byok/server.ts +3 -0
- package/src/byok.ts +17 -0
- package/src/client.ts +13 -0
- package/src/index.ts +6 -0
- package/src/interrupt-resume.ts +14 -13
- package/src/middlewares/otel.ts +16 -8
- package/src/stream-to-response.ts +11 -4
- package/src/stream-to-websocket.ts +3 -1
- package/src/strip-to-spec-middleware.ts +48 -24
- package/src/types.ts +109 -393
- package/src/utilities/adapter-yield-chunk.ts +30 -0
- package/src/utilities/ag-ui-usage.test.ts +194 -0
- package/src/utilities/ag-ui-usage.ts +148 -0
- package/src/utilities/ag-ui-wire.ts +149 -31
- package/src/utilities/chat-params.ts +22 -39
- package/src/utilities/chunk-ids.ts +24 -0
- package/src/utilities/merge-metadata.test.ts +117 -0
- package/src/utilities/merge-metadata.ts +59 -0
- package/src/utilities/normalize-stream-chunk.test.ts +423 -0
- package/src/utilities/normalize-stream-chunk.ts +186 -0
- package/src/utilities/reasoning-encrypted-value.ts +18 -0
- package/src/utilities/restore-inbound-chunk.test.ts +133 -0
- package/src/utilities/restore-inbound-chunk.ts +72 -0
- package/src/utilities/spec-event-keys.test.ts +34 -0
- package/src/utilities/spec-event-keys.ts +74 -0
- package/src/utilities/structured-output-events.ts +3 -3
package/src/index.ts
CHANGED
|
@@ -459,6 +459,12 @@ export { generationParamsFromBody, generationParamsFromRequest } from './client'
|
|
|
459
459
|
|
|
460
460
|
// AG-UI wire serialization (used internally by @tanstack/ai-client)
|
|
461
461
|
export { uiMessagesToWire } from './utilities/ag-ui-wire'
|
|
462
|
+
export { mergeMetadata, withTanstackMetadata } from './utilities/merge-metadata'
|
|
463
|
+
export { fromSpecTokenUsage, toSpecTokenUsage } from './utilities/ag-ui-usage'
|
|
464
|
+
export type { SpecTokenUsage } from './utilities/ag-ui-usage'
|
|
465
|
+
export { normalizeStreamChunk } from './utilities/normalize-stream-chunk'
|
|
466
|
+
export type { AdapterYieldChunk } from './utilities/adapter-yield-chunk'
|
|
467
|
+
export { getChunkRunId, getChunkThreadId } from './utilities/chunk-ids'
|
|
462
468
|
export type { WireMessage } from './utilities/ag-ui-wire'
|
|
463
469
|
export {
|
|
464
470
|
isContentPart,
|
package/src/interrupt-resume.ts
CHANGED
|
@@ -445,6 +445,20 @@ export async function validateInterruptResumeBatch(
|
|
|
445
445
|
continue
|
|
446
446
|
}
|
|
447
447
|
|
|
448
|
+
if (entry.status === 'cancelled') {
|
|
449
|
+
if (entry.payload !== undefined) {
|
|
450
|
+
errors.push(
|
|
451
|
+
interruptItemError(
|
|
452
|
+
input,
|
|
453
|
+
record.interruptId,
|
|
454
|
+
'invalid-payload',
|
|
455
|
+
`Cancelled interrupt ${record.interruptId} must not include a payload.`,
|
|
456
|
+
),
|
|
457
|
+
)
|
|
458
|
+
}
|
|
459
|
+
continue
|
|
460
|
+
}
|
|
461
|
+
|
|
448
462
|
const tool = runtimeTool(input.tools, binding.toolName)
|
|
449
463
|
if (!tool) {
|
|
450
464
|
errors.push(
|
|
@@ -511,19 +525,6 @@ export async function validateInterruptResumeBatch(
|
|
|
511
525
|
}
|
|
512
526
|
}
|
|
513
527
|
|
|
514
|
-
if (entry.status === 'cancelled') {
|
|
515
|
-
if (entry.payload !== undefined) {
|
|
516
|
-
errors.push(
|
|
517
|
-
interruptItemError(
|
|
518
|
-
input,
|
|
519
|
-
record.interruptId,
|
|
520
|
-
'invalid-payload',
|
|
521
|
-
`Cancelled interrupt ${record.interruptId} must not include a payload.`,
|
|
522
|
-
),
|
|
523
|
-
)
|
|
524
|
-
}
|
|
525
|
-
continue
|
|
526
|
-
}
|
|
527
528
|
if (schemaDrifted) continue
|
|
528
529
|
|
|
529
530
|
if (binding.kind === 'client-tool-execution') {
|
package/src/middlewares/otel.ts
CHANGED
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
} from '../utilities/sampling-keys'
|
|
11
11
|
import { firstNumber } from '../utilities/numbers'
|
|
12
12
|
import { errorMessage, errorTypeName } from '../utilities/errors'
|
|
13
|
+
import { rebuildTokenUsage } from '../utilities/ag-ui-usage'
|
|
14
|
+
import { tanstackMetadata } from '../utilities/merge-metadata'
|
|
13
15
|
import { usageAttributes } from './usage-attributes'
|
|
14
16
|
import type {
|
|
15
17
|
AttributeValue,
|
|
@@ -631,26 +633,32 @@ export function otelMiddleware(
|
|
|
631
633
|
}
|
|
632
634
|
|
|
633
635
|
if (chunk.type !== 'RUN_FINISHED') return
|
|
636
|
+
const tanstack = tanstackMetadata(chunk)
|
|
637
|
+
const extra = chunk as {
|
|
638
|
+
finishReason?: string | null
|
|
639
|
+
model?: string
|
|
640
|
+
}
|
|
641
|
+
const finishReason = extra.finishReason ?? tanstack?.finishReason
|
|
642
|
+
const model = extra.model ?? tanstack?.model
|
|
634
643
|
// Capture for the root-span finish_reasons attribute set in onFinish,
|
|
635
644
|
// which receives base-shaped info without a finishReason field.
|
|
636
|
-
if (
|
|
645
|
+
if (finishReason) state.lastFinishReason = finishReason
|
|
637
646
|
const span = state.currentIterationSpan
|
|
638
647
|
if (!span) return
|
|
639
648
|
|
|
640
|
-
if (
|
|
641
|
-
span.setAttribute('gen_ai.response.finish_reasons', [
|
|
642
|
-
chunk.finishReason,
|
|
643
|
-
])
|
|
649
|
+
if (finishReason) {
|
|
650
|
+
span.setAttribute('gen_ai.response.finish_reasons', [finishReason])
|
|
644
651
|
}
|
|
645
|
-
if (
|
|
652
|
+
if (model) span.setAttribute('gen_ai.response.model', model)
|
|
646
653
|
|
|
647
654
|
// Set usage attributes on the iteration span directly from the chunk
|
|
648
655
|
// so they're available before `onUsage` fires. Histogram recording is
|
|
649
656
|
// deliberately NOT done here — the chat runner always invokes
|
|
650
657
|
// `runOnUsage` when `chunk.usage` is present, and `onUsage` is the
|
|
651
658
|
// canonical place for the metric. Recording in both would double-count.
|
|
652
|
-
|
|
653
|
-
|
|
659
|
+
const tokenUsage = rebuildTokenUsage(chunk.usage, tanstack?.usage)
|
|
660
|
+
if (tokenUsage) {
|
|
661
|
+
span.setAttributes(usageAttributes(tokenUsage))
|
|
654
662
|
}
|
|
655
663
|
|
|
656
664
|
if (captureContent && state.assistantTextBuffer.length > 0) {
|
|
@@ -8,6 +8,7 @@ import { wasRunDetached } from './delivery-detach'
|
|
|
8
8
|
import { notifyRunDisconnected } from './delivery-disconnect'
|
|
9
9
|
import { resolveResumeRunId } from './stream-durability'
|
|
10
10
|
import { EventType } from './types'
|
|
11
|
+
import { toWireChunk } from './strip-to-spec-middleware'
|
|
11
12
|
import { resolveDebugOption } from './logger/resolve'
|
|
12
13
|
import { runErrorEventToError } from './utilities/errors'
|
|
13
14
|
import type { LockStore } from './activities/chat/middleware/locks'
|
|
@@ -287,10 +288,13 @@ function sseEncoders(
|
|
|
287
288
|
encodeChunk: (chunk, index) => {
|
|
288
289
|
const id = getId?.(chunk, index)
|
|
289
290
|
const idLine = id === undefined ? '' : `id: ${id}\n`
|
|
290
|
-
|
|
291
|
+
const wire = toWireChunk(chunk)
|
|
292
|
+
return encoder.encode(`${idLine}data: ${JSON.stringify(wire)}\n\n`)
|
|
291
293
|
},
|
|
292
294
|
encodeError: (error) =>
|
|
293
|
-
encoder.encode(
|
|
295
|
+
encoder.encode(
|
|
296
|
+
`data: ${JSON.stringify(toWireChunk(runErrorChunk(error)))}\n\n`,
|
|
297
|
+
),
|
|
294
298
|
}
|
|
295
299
|
}
|
|
296
300
|
|
|
@@ -1069,12 +1073,15 @@ function ndjsonEncoders(
|
|
|
1069
1073
|
return {
|
|
1070
1074
|
encodeChunk: (chunk, index) => {
|
|
1071
1075
|
const id = getId?.(chunk, index)
|
|
1076
|
+
const wire = toWireChunk(chunk)
|
|
1072
1077
|
const line =
|
|
1073
|
-
id === undefined
|
|
1078
|
+
id === undefined
|
|
1079
|
+
? JSON.stringify(wire)
|
|
1080
|
+
: JSON.stringify({ id, chunk: wire })
|
|
1074
1081
|
return encoder.encode(`${line}\n`)
|
|
1075
1082
|
},
|
|
1076
1083
|
encodeError: (error) =>
|
|
1077
|
-
encoder.encode(`${JSON.stringify(runErrorChunk(error))}\n`),
|
|
1084
|
+
encoder.encode(`${JSON.stringify(toWireChunk(runErrorChunk(error)))}\n`),
|
|
1078
1085
|
}
|
|
1079
1086
|
}
|
|
1080
1087
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { chatParamsFromRequestBody } from './utilities/chat-params'
|
|
2
2
|
import { durableStreamSource, runErrorChunk } from './stream-to-response'
|
|
3
|
+
import { toWireChunk } from './strip-to-spec-middleware'
|
|
3
4
|
import { resolveDebugOption } from './logger/resolve'
|
|
4
5
|
import type { StreamDurability } from './stream-durability'
|
|
5
6
|
import type { DebugOption } from './logger/types'
|
|
@@ -35,7 +36,8 @@ export function encodeWsFrame(
|
|
|
35
36
|
chunk: StreamChunk,
|
|
36
37
|
id: string | undefined,
|
|
37
38
|
): string {
|
|
38
|
-
|
|
39
|
+
const wire = toWireChunk(chunk)
|
|
40
|
+
return JSON.stringify(id === undefined ? wire : { id, chunk: wire })
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
/**
|
|
@@ -1,34 +1,58 @@
|
|
|
1
|
-
import type { ChatMiddleware } from './activities/chat/middleware/types'
|
|
2
1
|
import type { StreamChunk } from './types'
|
|
2
|
+
import { EventType } from './types'
|
|
3
|
+
import type { AdapterYieldChunk } from './utilities/adapter-yield-chunk'
|
|
4
|
+
import { isTanstackUsage, toSpecTokenUsage } from './utilities/ag-ui-usage'
|
|
5
|
+
import {
|
|
6
|
+
tanstackMetadata,
|
|
7
|
+
withTanstackMetadata,
|
|
8
|
+
} from './utilities/merge-metadata'
|
|
9
|
+
import { normalizeStreamChunk } from './utilities/normalize-stream-chunk'
|
|
10
|
+
import { isSpecTopLevelKey } from './utilities/spec-event-keys'
|
|
3
11
|
|
|
4
12
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* All other fields pass through unchanged. @ag-ui/core's BaseEventSchema
|
|
9
|
-
* uses `.passthrough()`, so extra fields (model, content, usage,
|
|
10
|
-
* finishReason, toolName, stepId, etc.) are allowed and won't break
|
|
11
|
-
* spec validation or verifyEvents.
|
|
13
|
+
* Delete unknown top-level keys from a stream chunk.
|
|
14
|
+
* Keep only AG-UI spec keys for this event type.
|
|
15
|
+
* Convert TanStack TokenUsage objects to the spec `usage[]` array.
|
|
12
16
|
*/
|
|
13
|
-
export function stripToSpec(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
export function stripToSpec(
|
|
18
|
+
chunk: StreamChunk | AdapterYieldChunk,
|
|
19
|
+
): StreamChunk {
|
|
20
|
+
const out: Record<string, unknown> = {}
|
|
21
|
+
for (const [key, value] of Object.entries(chunk)) {
|
|
22
|
+
if (isSpecTopLevelKey(chunk.type, key) && value !== undefined) {
|
|
23
|
+
out[key] = value
|
|
24
|
+
}
|
|
18
25
|
}
|
|
19
|
-
|
|
26
|
+
|
|
27
|
+
if (
|
|
28
|
+
(chunk.type === EventType.RUN_FINISHED ||
|
|
29
|
+
chunk.type === EventType.RUN_ERROR) &&
|
|
30
|
+
isTanstackUsage(out.usage)
|
|
31
|
+
) {
|
|
32
|
+
const model = tanstackMetadata(chunk)?.model
|
|
33
|
+
const { usage, leftover } = toSpecTokenUsage(out.usage, {
|
|
34
|
+
model: typeof model === 'string' ? model : undefined,
|
|
35
|
+
})
|
|
36
|
+
out.usage = usage
|
|
37
|
+
if (leftover !== undefined) {
|
|
38
|
+
return withTanstackMetadata(out as StreamChunk, {
|
|
39
|
+
usage: leftover,
|
|
40
|
+
}) as StreamChunk
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return out as StreamChunk
|
|
20
45
|
}
|
|
21
46
|
|
|
22
47
|
/**
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
48
|
+
* Move TanStack extras into `metadata.tanstack`, then keep only spec keys.
|
|
49
|
+
* Custom servers that skip `chat()` still round-trip `finishReason` on SSE/HTTP/WS.
|
|
50
|
+
* Fan-out extras (encrypted-value, TOOL_CALL_RESULT) stay on the `chat()` path;
|
|
51
|
+
* this encoder is 1:1 with the durability log offset.
|
|
26
52
|
*/
|
|
27
|
-
export function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
},
|
|
33
|
-
}
|
|
53
|
+
export function toWireChunk(
|
|
54
|
+
chunk: StreamChunk | AdapterYieldChunk,
|
|
55
|
+
): StreamChunk {
|
|
56
|
+
const [normalized] = normalizeStreamChunk(chunk)
|
|
57
|
+
return stripToSpec(normalized ?? chunk)
|
|
34
58
|
}
|