@tanstack/ai 0.39.0 → 0.40.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/dist/esm/activities/chat/index.d.ts +2 -2
- package/dist/esm/activities/chat/index.js +24 -3
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.d.ts +2 -2
- 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/sandbox-runtime.d.ts +7 -2
- package/dist/esm/activities/chat/middleware/sandbox-runtime.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +16 -4
- package/dist/esm/activities/chat/stream/processor.d.ts +18 -0
- package/dist/esm/activities/chat/stream/processor.js +86 -4
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/generateTranscription/index.d.ts +2 -2
- package/dist/esm/activities/generateTranscription/index.js.map +1 -1
- package/dist/esm/index.d.ts +2 -1
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types.d.ts +137 -2
- package/dist/esm/utilities/provider-executed.d.ts +18 -0
- package/dist/esm/utilities/provider-executed.js +15 -0
- package/dist/esm/utilities/provider-executed.js.map +1 -0
- package/package.json +1 -1
- package/skills/ai-core/adapter-configuration/SKILL.md +10 -0
- package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +43 -12
- package/skills/ai-core/ag-ui-protocol/SKILL.md +59 -0
- package/skills/ai-core/media-generation/SKILL.md +9 -4
- package/skills/ai-core/middleware/SKILL.md +91 -0
- package/src/activities/chat/index.ts +34 -6
- package/src/activities/chat/middleware/compose.ts +2 -2
- package/src/activities/chat/middleware/index.ts +1 -0
- package/src/activities/chat/middleware/sandbox-runtime.ts +4 -2
- package/src/activities/chat/middleware/types.ts +17 -4
- package/src/activities/chat/stream/processor.ts +141 -3
- package/src/activities/generateTranscription/index.ts +6 -2
- package/src/index.ts +6 -0
- package/src/types.ts +130 -2
- package/src/utilities/provider-executed.ts +32 -0
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { createCapability } from './capabilities'
|
|
9
9
|
import type { InternalLogger } from '../../../logger/internal-logger'
|
|
10
|
-
import type {
|
|
10
|
+
import type { SandboxFileHookEvent } from './types'
|
|
11
11
|
|
|
12
12
|
export interface SandboxRuntime {
|
|
13
|
-
emit: (event:
|
|
13
|
+
emit: (event: SandboxFileHookEvent) => void
|
|
14
|
+
/** Emit an opt-in per-file `sandbox.file.diff` CUSTOM chunk. */
|
|
15
|
+
emitFileDiff: (value: { path: string; diff: string }) => void
|
|
14
16
|
logger: InternalLogger
|
|
15
17
|
}
|
|
16
18
|
|
|
@@ -21,6 +21,19 @@ export interface SandboxFileEvent {
|
|
|
21
21
|
timestamp: number
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
/** The file event a sandbox hook receives: the serializable {@link SandboxFileEvent}
|
|
25
|
+
* plus lazy, git-backed content accessors. Accessors compute on call, so a hook
|
|
26
|
+
* that only reads `path`/`type` pays nothing. Never present on the serialized
|
|
27
|
+
* `sandbox.file` CUSTOM chunk. */
|
|
28
|
+
export interface SandboxFileHookEvent extends SandboxFileEvent {
|
|
29
|
+
/** Content at the session baseline (`''` for a new file or non-git workspace). */
|
|
30
|
+
before: () => Promise<string>
|
|
31
|
+
/** Current content (`''` when the event is a delete). */
|
|
32
|
+
after: () => Promise<string>
|
|
33
|
+
/** Unified patch vs the session baseline (synthesized add-patch when non-git). */
|
|
34
|
+
diff: () => Promise<string>
|
|
35
|
+
}
|
|
36
|
+
|
|
24
37
|
/**
|
|
25
38
|
* Sandbox file-event hooks a chat middleware can declare. Fire server-side for
|
|
26
39
|
* every file create/change/delete observed in the sandbox during the run.
|
|
@@ -28,19 +41,19 @@ export interface SandboxFileEvent {
|
|
|
28
41
|
export interface ChatSandboxHooks<TContext = unknown> {
|
|
29
42
|
onFile?: (
|
|
30
43
|
ctx: ChatMiddlewareContext<TContext>,
|
|
31
|
-
e:
|
|
44
|
+
e: SandboxFileHookEvent,
|
|
32
45
|
) => void | Promise<void>
|
|
33
46
|
onFileCreate?: (
|
|
34
47
|
ctx: ChatMiddlewareContext<TContext>,
|
|
35
|
-
e:
|
|
48
|
+
e: SandboxFileHookEvent,
|
|
36
49
|
) => void | Promise<void>
|
|
37
50
|
onFileChange?: (
|
|
38
51
|
ctx: ChatMiddlewareContext<TContext>,
|
|
39
|
-
e:
|
|
52
|
+
e: SandboxFileHookEvent,
|
|
40
53
|
) => void | Promise<void>
|
|
41
54
|
onFileDelete?: (
|
|
42
55
|
ctx: ChatMiddlewareContext<TContext>,
|
|
43
|
-
e:
|
|
56
|
+
e: SandboxFileHookEvent,
|
|
44
57
|
) => void | Promise<void>
|
|
45
58
|
}
|
|
46
59
|
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
uiMessageToModelMessages,
|
|
24
24
|
} from '../messages.js'
|
|
25
25
|
import { normalizeToolResult } from '../../../utilities/tool-result'
|
|
26
|
+
import { isProviderExecutedToolCall } from '../../../utilities/provider-executed'
|
|
26
27
|
import { defaultJSONParser } from './json-parser'
|
|
27
28
|
import {
|
|
28
29
|
appendStructuredOutputDelta,
|
|
@@ -403,12 +404,15 @@ export class StreamProcessor {
|
|
|
403
404
|
// 1. It was approved/denied (approval-responded state)
|
|
404
405
|
// 2. It has an output field set (client tool completed via addToolResult)
|
|
405
406
|
// 3. It has a corresponding tool-result part (server tool completed)
|
|
407
|
+
// 4. It is provider-executed (e.g. Anthropic web_search) — already run by
|
|
408
|
+
// the provider, so there is no client result to wait for.
|
|
406
409
|
return toolParts.every(
|
|
407
410
|
(part) =>
|
|
408
411
|
part.state === 'complete' ||
|
|
409
412
|
part.state === 'approval-responded' ||
|
|
410
413
|
(part.output !== undefined && !part.approval) ||
|
|
411
|
-
toolResultIds.has(part.id)
|
|
414
|
+
toolResultIds.has(part.id) ||
|
|
415
|
+
isProviderExecutedToolCall(part),
|
|
412
416
|
)
|
|
413
417
|
}
|
|
414
418
|
|
|
@@ -881,10 +885,140 @@ export class StreamProcessor {
|
|
|
881
885
|
// them directly to UIMessage[] is unsafe and causes "Cannot read properties
|
|
882
886
|
// of undefined (reading 'find')" when code later reads message.parts (e.g.
|
|
883
887
|
// the onToolCallStateChange devtools handler).
|
|
884
|
-
|
|
888
|
+
//
|
|
889
|
+
// The AG-UI `MESSAGES_SNAPSHOT` wire shape cannot reconstruct client-side
|
|
890
|
+
// tool-call metadata a server may omit: a `role: 'tool'` message only carries
|
|
891
|
+
// `toolCallId` + `content`, and an assistant message in the snapshot may
|
|
892
|
+
// drop `toolCalls` the client already observed via `TOOL_CALL_*` events.
|
|
893
|
+
// Without the matching `tool-call` part, later `addToolResult(toolCallId)`
|
|
894
|
+
// calls cannot locate the call and warn + no-op (see #859). To keep the
|
|
895
|
+
// UI representation consistent with the streaming fan-out and preserve the
|
|
896
|
+
// unreconstructable metadata, reconcile the normalized snapshot against
|
|
897
|
+
// the pre-snapshot state; see `reconcileSnapshotToolCalls`.
|
|
898
|
+
const prevMessages = this.messages
|
|
899
|
+
const normalized = chunk.messages.map(aguiSnapshotMessageToUIMessage)
|
|
900
|
+
this.messages = this.reconcileSnapshotToolCalls(normalized, prevMessages)
|
|
885
901
|
this.emitMessagesChange()
|
|
886
902
|
}
|
|
887
903
|
|
|
904
|
+
/**
|
|
905
|
+
* Reconcile a freshly normalized snapshot with the pre-snapshot message
|
|
906
|
+
* state so unreconstructable tool-call metadata is preserved.
|
|
907
|
+
*
|
|
908
|
+
* Post-pass (a): anchor `tool-result`-only assistant messages (the shape
|
|
909
|
+
* `aguiSnapshotMessageToUIMessage` emits for AG-UI `role: 'tool'` wire
|
|
910
|
+
* messages) into the message containing the matching `tool-call` part, or —
|
|
911
|
+
* when the snapshot supplies no such part — the nearest earlier anchorable
|
|
912
|
+
* assistant message, matching the in-stream fan-out shape
|
|
913
|
+
* `assistant: [text, tool-call, tool-result, ...]`. Detached messages with
|
|
914
|
+
* no earlier anchorable assistant are kept verbatim.
|
|
915
|
+
*
|
|
916
|
+
* Post-pass (b): when a `tool-result` part references a `toolCallId` whose
|
|
917
|
+
* `tool-call` part is absent from the snapshot, carry the `tool-call` part
|
|
918
|
+
* forward from the pre-snapshot state (state and output untouched) so a
|
|
919
|
+
* subsequent `addToolResult(toolCallId)` can still locate the call.
|
|
920
|
+
*/
|
|
921
|
+
private reconcileSnapshotToolCalls(
|
|
922
|
+
snapshot: Array<UIMessage>,
|
|
923
|
+
prevMessages: Array<UIMessage>,
|
|
924
|
+
): Array<UIMessage> {
|
|
925
|
+
// Index tool-call parts observed before the snapshot by id so we can
|
|
926
|
+
// restore metadata the snapshot cannot re-emit. Duplicate ids resolve
|
|
927
|
+
// last-write-wins: the same tool call can appear in multiple messages
|
|
928
|
+
// across reconnects, and the most recent part carries the freshest state.
|
|
929
|
+
const prevToolCalls = new Map<string, ToolCallPart>()
|
|
930
|
+
for (const msg of prevMessages) {
|
|
931
|
+
for (const part of msg.parts) {
|
|
932
|
+
if (part.type === 'tool-call') {
|
|
933
|
+
prevToolCalls.set(part.id, part)
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
}
|
|
937
|
+
// Index tool-call parts already present in the snapshot so (b) only fills
|
|
938
|
+
// genuine gaps rather than duplicating a tool-call the snapshot supplies.
|
|
939
|
+
const snapshotToolCallIds = new Set<string>()
|
|
940
|
+
for (const msg of snapshot) {
|
|
941
|
+
for (const part of msg.parts) {
|
|
942
|
+
if (part.type === 'tool-call') {
|
|
943
|
+
snapshotToolCallIds.add(part.id)
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
const reconciled: Array<UIMessage> = []
|
|
949
|
+
for (const msg of snapshot) {
|
|
950
|
+
const toolResultPart =
|
|
951
|
+
msg.role === 'assistant' && msg.parts.length === 1
|
|
952
|
+
? msg.parts.find((p): p is ToolResultPart => p.type === 'tool-result')
|
|
953
|
+
: undefined
|
|
954
|
+
|
|
955
|
+
if (!toolResultPart) {
|
|
956
|
+
reconciled.push(msg)
|
|
957
|
+
continue
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// Prefer the message that actually contains the matching tool-call
|
|
961
|
+
// part. AG-UI `reasoning`/`activity` messages also normalize to
|
|
962
|
+
// `role: 'assistant'`, so anchoring into the nearest assistant alone
|
|
963
|
+
// could separate a result from its call (and a later
|
|
964
|
+
// `addToolResult(toolCallId)` would then append a duplicate result
|
|
965
|
+
// next to the call).
|
|
966
|
+
const target =
|
|
967
|
+
reconciled.findLast((m) =>
|
|
968
|
+
m.parts.some(
|
|
969
|
+
(p) => p.type === 'tool-call' && p.id === toolResultPart.toolCallId,
|
|
970
|
+
),
|
|
971
|
+
) ??
|
|
972
|
+
reconciled.findLast(
|
|
973
|
+
(m) =>
|
|
974
|
+
m.role === 'assistant' &&
|
|
975
|
+
!(m.parts.length === 1 && m.parts[0]?.type === 'tool-result'),
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
if (!target) {
|
|
979
|
+
// No assistant to anchor into — keep the detached message intact.
|
|
980
|
+
if (!snapshotToolCallIds.has(toolResultPart.toolCallId)) {
|
|
981
|
+
console.warn(
|
|
982
|
+
`[StreamProcessor] MESSAGES_SNAPSHOT contains a tool-result for "${toolResultPart.toolCallId}" but no matching tool-call exists in the snapshot, and there is no assistant message to anchor into; addToolResult("${toolResultPart.toolCallId}") will not be able to locate this call`,
|
|
983
|
+
)
|
|
984
|
+
}
|
|
985
|
+
reconciled.push(msg)
|
|
986
|
+
continue
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
const parts = [...target.parts]
|
|
990
|
+
// (b) Fill in a missing tool-call part from the pre-snapshot state when
|
|
991
|
+
// the snapshot references its id via a tool-result but supplies no
|
|
992
|
+
// tool-call metadata of its own.
|
|
993
|
+
if (
|
|
994
|
+
!snapshotToolCallIds.has(toolResultPart.toolCallId) &&
|
|
995
|
+
!parts.some(
|
|
996
|
+
(p) => p.type === 'tool-call' && p.id === toolResultPart.toolCallId,
|
|
997
|
+
)
|
|
998
|
+
) {
|
|
999
|
+
const prev = prevToolCalls.get(toolResultPart.toolCallId)
|
|
1000
|
+
if (prev) {
|
|
1001
|
+
// Insert the carried-over tool-call before its tool-result (pushed
|
|
1002
|
+
// below) so call→result ordering matches the streaming fan-out.
|
|
1003
|
+
parts.push({ ...prev })
|
|
1004
|
+
snapshotToolCallIds.add(prev.id)
|
|
1005
|
+
} else {
|
|
1006
|
+
console.warn(
|
|
1007
|
+
`[StreamProcessor] MESSAGES_SNAPSHOT contains a tool-result for "${toolResultPart.toolCallId}" but no matching tool-call exists in the snapshot or the pre-snapshot state; addToolResult("${toolResultPart.toolCallId}") will not be able to locate this call`,
|
|
1008
|
+
)
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
parts.push(toolResultPart)
|
|
1012
|
+
// Replace rather than push into `target.parts`: a snapshot message that
|
|
1013
|
+
// arrived already carrying `parts` (TanStack server echoing UIMessages)
|
|
1014
|
+
// shares its array with the incoming chunk, and mutating it in place
|
|
1015
|
+
// would corrupt the caller's event object.
|
|
1016
|
+
target.parts = parts
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
return reconciled
|
|
1020
|
+
}
|
|
1021
|
+
|
|
888
1022
|
/**
|
|
889
1023
|
* Handle TEXT_MESSAGE_CONTENT event.
|
|
890
1024
|
*
|
|
@@ -1781,8 +1915,12 @@ export class StreamProcessor {
|
|
|
1781
1915
|
* downgrading a failed call back to 'input-complete'.
|
|
1782
1916
|
*/
|
|
1783
1917
|
private isToolCallPartErrored(toolCallId: string): boolean {
|
|
1918
|
+
// `initialMessages` may be ModelMessage-shaped (no `parts`) — e.g. the
|
|
1919
|
+
// common pattern of seeding a processor with the same messages passed to
|
|
1920
|
+
// `chat()`. Guard the access so iterating them never throws.
|
|
1784
1921
|
return this.messages.some((msg) =>
|
|
1785
|
-
|
|
1922
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- `parts` is typed as required, but seeded ModelMessage-shaped messages can lack it at runtime.
|
|
1923
|
+
msg.parts?.some(
|
|
1786
1924
|
(part) =>
|
|
1787
1925
|
part.type === 'tool-call' &&
|
|
1788
1926
|
part.id === toolCallId &&
|
|
@@ -19,7 +19,11 @@ import type { InternalLogger } from '../../logger/internal-logger'
|
|
|
19
19
|
import type { DebugOption } from '../../logger/types'
|
|
20
20
|
import type { GenerationMiddleware } from '../middleware'
|
|
21
21
|
import type { TranscriptionAdapter } from './adapter'
|
|
22
|
-
import type {
|
|
22
|
+
import type {
|
|
23
|
+
StreamChunk,
|
|
24
|
+
TranscriptionResponseFormat,
|
|
25
|
+
TranscriptionResult,
|
|
26
|
+
} from '../../types'
|
|
23
27
|
|
|
24
28
|
// ===========================
|
|
25
29
|
// Activity Kind
|
|
@@ -67,7 +71,7 @@ export interface TranscriptionActivityOptions<
|
|
|
67
71
|
/** An optional prompt to guide the transcription */
|
|
68
72
|
prompt?: string
|
|
69
73
|
/** The format of the transcription output */
|
|
70
|
-
responseFormat?:
|
|
74
|
+
responseFormat?: TranscriptionResponseFormat
|
|
71
75
|
/** Provider-specific options for transcription */
|
|
72
76
|
modelOptions?: TranscriptionProviderOptions<TAdapter>
|
|
73
77
|
/**
|
package/src/index.ts
CHANGED
|
@@ -121,6 +121,7 @@ export type {
|
|
|
121
121
|
AbortInfo,
|
|
122
122
|
ErrorInfo,
|
|
123
123
|
SandboxFileEvent,
|
|
124
|
+
SandboxFileHookEvent,
|
|
124
125
|
ChatSandboxHooks,
|
|
125
126
|
} from './activities/chat/middleware/index'
|
|
126
127
|
|
|
@@ -256,6 +257,11 @@ export {
|
|
|
256
257
|
normalizeToolResult,
|
|
257
258
|
} from './utilities/tool-result'
|
|
258
259
|
|
|
260
|
+
export {
|
|
261
|
+
getProviderExecutedMetadata,
|
|
262
|
+
isProviderExecutedToolCall,
|
|
263
|
+
} from './utilities/provider-executed'
|
|
264
|
+
|
|
259
265
|
// Adapter extension utilities
|
|
260
266
|
export { createModel, extendAdapter } from './extend-adapter'
|
|
261
267
|
export type { ExtendedModelDef, ModelCapabilities } from './extend-adapter'
|
package/src/types.ts
CHANGED
|
@@ -160,6 +160,26 @@ export interface ToolCall<TMetadata = unknown> {
|
|
|
160
160
|
metadata?: TMetadata
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
/**
|
|
164
|
+
* Convention for tool-call `metadata` that marks a call as **provider-executed**
|
|
165
|
+
* — run by the provider's own infrastructure (e.g. Anthropic `web_search` /
|
|
166
|
+
* `web_fetch` server tools) rather than by the agent loop. Adapters set
|
|
167
|
+
* `providerExecuted: true` so that:
|
|
168
|
+
*
|
|
169
|
+
* 1. The agent loop never tries to execute the call client-side (see
|
|
170
|
+
* {@link isProviderExecutedToolCall} usage in the chat engine), and
|
|
171
|
+
* 2. The adapter can stash the raw provider result alongside it so the call —
|
|
172
|
+
* and its evidence — round-trips into the next turn's request.
|
|
173
|
+
*
|
|
174
|
+
* Provider-specific payloads live under a namespaced key (e.g. `anthropic`),
|
|
175
|
+
* keeping this convention opaque to the framework core. The index signature
|
|
176
|
+
* preserves those per-adapter fields.
|
|
177
|
+
*/
|
|
178
|
+
export interface ProviderExecutedToolMetadata {
|
|
179
|
+
providerExecuted?: boolean
|
|
180
|
+
[key: string]: unknown
|
|
181
|
+
}
|
|
182
|
+
|
|
163
183
|
// ============================================================================
|
|
164
184
|
// Multimodal Content Types
|
|
165
185
|
// ============================================================================
|
|
@@ -362,7 +382,9 @@ export interface ToolCallPart<TMetadata = unknown> {
|
|
|
362
382
|
/** Tool execution output (for client tools or after approval) */
|
|
363
383
|
output?: any
|
|
364
384
|
/** Provider-specific metadata that round-trips with the tool call.
|
|
365
|
-
* Typed per-adapter via `TToolCallMetadata`.
|
|
385
|
+
* Typed per-adapter via `TToolCallMetadata`. May follow the
|
|
386
|
+
* {@link ProviderExecutedToolMetadata} convention to mark provider-executed
|
|
387
|
+
* server tools (e.g. Anthropic `web_search`). */
|
|
366
388
|
metadata?: TMetadata
|
|
367
389
|
}
|
|
368
390
|
|
|
@@ -1359,6 +1381,105 @@ export interface UIResourceEvent extends CustomEvent {
|
|
|
1359
1381
|
}
|
|
1360
1382
|
}
|
|
1361
1383
|
|
|
1384
|
+
// ── Sandbox events ──────────────────────────────────────────────────────────
|
|
1385
|
+
export interface SandboxFileCustomEvent extends CustomEvent {
|
|
1386
|
+
name: 'sandbox.file'
|
|
1387
|
+
value: {
|
|
1388
|
+
type: 'create' | 'change' | 'delete'
|
|
1389
|
+
path: string
|
|
1390
|
+
timestamp: number
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
export interface SandboxFileDiffEvent extends CustomEvent {
|
|
1394
|
+
name: 'sandbox.file.diff'
|
|
1395
|
+
value: { path: string; diff: string }
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
// ── Harness events ──────────────────────────────────────────────────────────
|
|
1399
|
+
export interface FileChangedEvent extends CustomEvent {
|
|
1400
|
+
name: 'file.changed'
|
|
1401
|
+
value: { path: string; diff: string }
|
|
1402
|
+
}
|
|
1403
|
+
export interface SessionIdEvent extends CustomEvent {
|
|
1404
|
+
name: `${string}.session-id`
|
|
1405
|
+
value: { sessionId: string }
|
|
1406
|
+
}
|
|
1407
|
+
|
|
1408
|
+
// ── Code-mode events ────────────────────────────────────────────────────────
|
|
1409
|
+
export interface CodeModeExecutionStartedEvent extends CustomEvent {
|
|
1410
|
+
name: 'code_mode:execution_started'
|
|
1411
|
+
value: { timestamp: number; codeLength: number }
|
|
1412
|
+
}
|
|
1413
|
+
export interface CodeModeConsoleEvent extends CustomEvent {
|
|
1414
|
+
name: 'code_mode:console'
|
|
1415
|
+
value: {
|
|
1416
|
+
level: 'log' | 'warn' | 'error' | 'info'
|
|
1417
|
+
message: string
|
|
1418
|
+
timestamp: number
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
export interface CodeModeExternalCallEvent extends CustomEvent {
|
|
1422
|
+
name: 'code_mode:external_call'
|
|
1423
|
+
value: { function: string; args: unknown; timestamp: number }
|
|
1424
|
+
}
|
|
1425
|
+
export interface CodeModeExternalResultEvent extends CustomEvent {
|
|
1426
|
+
name: 'code_mode:external_result'
|
|
1427
|
+
value: { function: string; result: unknown; duration: number }
|
|
1428
|
+
}
|
|
1429
|
+
export interface CodeModeExternalErrorEvent extends CustomEvent {
|
|
1430
|
+
name: 'code_mode:external_error'
|
|
1431
|
+
value: { function: string; error: string; duration: number }
|
|
1432
|
+
}
|
|
1433
|
+
export interface CodeModeSkillCallEvent extends CustomEvent {
|
|
1434
|
+
name: 'code_mode:skill_call'
|
|
1435
|
+
value: { skill: string; input: unknown; timestamp: number }
|
|
1436
|
+
}
|
|
1437
|
+
export interface CodeModeSkillResultEvent extends CustomEvent {
|
|
1438
|
+
name: 'code_mode:skill_result'
|
|
1439
|
+
value: { skill: string; result: unknown; duration: number; timestamp: number }
|
|
1440
|
+
}
|
|
1441
|
+
export interface CodeModeSkillErrorEvent extends CustomEvent {
|
|
1442
|
+
name: 'code_mode:skill_error'
|
|
1443
|
+
value: { skill: string; error: string; duration: number; timestamp: number }
|
|
1444
|
+
}
|
|
1445
|
+
export interface SkillRegisteredEvent extends CustomEvent {
|
|
1446
|
+
name: 'skill:registered'
|
|
1447
|
+
value: { id: string; name: string; description: string; timestamp: number }
|
|
1448
|
+
}
|
|
1449
|
+
|
|
1450
|
+
/**
|
|
1451
|
+
* Every CUSTOM event TanStack AI itself emits, as a discriminated union on
|
|
1452
|
+
* `name`. User-emitted custom events (via `emitCustomEvent` with a custom name)
|
|
1453
|
+
* are intentionally absent — they still flow at runtime.
|
|
1454
|
+
*/
|
|
1455
|
+
export type KnownCustomEvent =
|
|
1456
|
+
| SandboxFileCustomEvent
|
|
1457
|
+
| SandboxFileDiffEvent
|
|
1458
|
+
| FileChangedEvent
|
|
1459
|
+
| SessionIdEvent
|
|
1460
|
+
| CodeModeExecutionStartedEvent
|
|
1461
|
+
| CodeModeConsoleEvent
|
|
1462
|
+
| CodeModeExternalCallEvent
|
|
1463
|
+
| CodeModeExternalResultEvent
|
|
1464
|
+
| CodeModeExternalErrorEvent
|
|
1465
|
+
| CodeModeSkillCallEvent
|
|
1466
|
+
| CodeModeSkillResultEvent
|
|
1467
|
+
| CodeModeSkillErrorEvent
|
|
1468
|
+
| SkillRegisteredEvent
|
|
1469
|
+
| StructuredOutputStartEvent
|
|
1470
|
+
| StructuredOutputCompleteEvent
|
|
1471
|
+
| ApprovalRequestedEvent
|
|
1472
|
+
| ToolInputAvailableEvent
|
|
1473
|
+
| UIResourceEvent
|
|
1474
|
+
|
|
1475
|
+
/** The default chat streaming result: standard chunks plus every typed
|
|
1476
|
+
* framework CUSTOM event, with the `value: any` catch-all excluded so
|
|
1477
|
+
* literal-`name` narrowing types `value`. User-emitted custom names are typed
|
|
1478
|
+
* out (still flow at runtime — branch outside the name narrows or cast). */
|
|
1479
|
+
export type ChatStream = AsyncIterable<
|
|
1480
|
+
Exclude<StreamChunk, CustomEvent> | KnownCustomEvent
|
|
1481
|
+
>
|
|
1482
|
+
|
|
1362
1483
|
/**
|
|
1363
1484
|
* Public type for streams returned by `chat({ outputSchema, stream: true })`.
|
|
1364
1485
|
*
|
|
@@ -1908,6 +2029,13 @@ export interface TTSResult {
|
|
|
1908
2029
|
* Options for audio transcription.
|
|
1909
2030
|
* These are the common options supported across providers.
|
|
1910
2031
|
*/
|
|
2032
|
+
export type TranscriptionResponseFormat =
|
|
2033
|
+
| 'json'
|
|
2034
|
+
| 'text'
|
|
2035
|
+
| 'srt'
|
|
2036
|
+
| 'verbose_json'
|
|
2037
|
+
| 'vtt'
|
|
2038
|
+
|
|
1911
2039
|
export interface TranscriptionOptions<
|
|
1912
2040
|
TProviderOptions extends object = object,
|
|
1913
2041
|
> {
|
|
@@ -1920,7 +2048,7 @@ export interface TranscriptionOptions<
|
|
|
1920
2048
|
/** An optional prompt to guide the transcription */
|
|
1921
2049
|
prompt?: string
|
|
1922
2050
|
/** The format of the transcription output */
|
|
1923
|
-
responseFormat?:
|
|
2051
|
+
responseFormat?: TranscriptionResponseFormat
|
|
1924
2052
|
/** Model-specific options for transcription */
|
|
1925
2053
|
modelOptions?: TProviderOptions
|
|
1926
2054
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ProviderExecutedToolMetadata } from '../types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Narrow a tool call's opaque `metadata` to the provider-executed convention.
|
|
5
|
+
* Returns the typed metadata when the call is provider-executed, else `null`.
|
|
6
|
+
*
|
|
7
|
+
* @see ProviderExecutedToolMetadata
|
|
8
|
+
*/
|
|
9
|
+
export function getProviderExecutedMetadata(
|
|
10
|
+
toolCall: { metadata?: unknown } | null | undefined,
|
|
11
|
+
): ProviderExecutedToolMetadata | null {
|
|
12
|
+
const metadata = toolCall?.metadata
|
|
13
|
+
if (
|
|
14
|
+
typeof metadata === 'object' &&
|
|
15
|
+
metadata !== null &&
|
|
16
|
+
(metadata as ProviderExecutedToolMetadata).providerExecuted === true
|
|
17
|
+
) {
|
|
18
|
+
return metadata as ProviderExecutedToolMetadata
|
|
19
|
+
}
|
|
20
|
+
return null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* True when a tool call was executed by the provider (e.g. Anthropic
|
|
25
|
+
* `web_search` / `web_fetch` server tools) rather than the agent loop. Such
|
|
26
|
+
* calls must not be routed to client-side execution and are already "complete".
|
|
27
|
+
*/
|
|
28
|
+
export function isProviderExecutedToolCall(
|
|
29
|
+
toolCall: { metadata?: unknown } | null | undefined,
|
|
30
|
+
): boolean {
|
|
31
|
+
return getProviderExecutedMetadata(toolCall) !== null
|
|
32
|
+
}
|