@tanstack/ai 0.42.0 → 0.43.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 +15 -1
- package/dist/esm/activities/chat/adapter.js +23 -16
- package/dist/esm/activities/chat/adapter.js.map +1 -1
- package/dist/esm/activities/chat/agent-loop-strategies.d.ts +5 -36
- package/dist/esm/activities/chat/agent-loop-strategies.js +75 -21
- package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -1
- package/dist/esm/activities/chat/cancel.d.ts +40 -0
- package/dist/esm/activities/chat/cancel.js +54 -0
- package/dist/esm/activities/chat/cancel.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +28 -21
- package/dist/esm/activities/chat/index.js +2100 -1813
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/mcp/manager.d.ts +2 -2
- package/dist/esm/activities/chat/mcp/manager.js +90 -77
- package/dist/esm/activities/chat/mcp/manager.js.map +1 -1
- package/dist/esm/activities/chat/mcp/types.d.ts +2 -2
- package/dist/esm/activities/chat/messages.js +397 -346
- package/dist/esm/activities/chat/messages.js.map +1 -1
- package/dist/esm/activities/chat/middleware/builder.js +17 -15
- package/dist/esm/activities/chat/middleware/builder.js.map +1 -1
- package/dist/esm/activities/chat/middleware/capabilities.js +78 -43
- package/dist/esm/activities/chat/middleware/capabilities.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.d.ts +94 -1
- package/dist/esm/activities/chat/middleware/compose.js +623 -531
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/middleware/define.js +12 -5
- package/dist/esm/activities/chat/middleware/define.js.map +1 -1
- package/dist/esm/activities/chat/middleware/index.d.ts +5 -1
- package/dist/esm/activities/chat/middleware/locks.d.ts +50 -0
- package/dist/esm/activities/chat/middleware/locks.js +71 -0
- package/dist/esm/activities/chat/middleware/locks.js.map +1 -0
- package/dist/esm/activities/chat/middleware/pending-turn.d.ts +15 -0
- package/dist/esm/activities/chat/middleware/pending-turn.js +35 -0
- package/dist/esm/activities/chat/middleware/pending-turn.js.map +1 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.d.ts +23 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.js +42 -0
- package/dist/esm/activities/chat/middleware/run-disconnect.js.map +1 -0
- package/dist/esm/activities/chat/middleware/run-store.d.ts +283 -0
- package/dist/esm/activities/chat/middleware/run-store.js +176 -0
- package/dist/esm/activities/chat/middleware/run-store.js.map +1 -0
- package/dist/esm/activities/chat/middleware/sandbox-runtime.js +14 -8
- package/dist/esm/activities/chat/middleware/sandbox-runtime.js.map +1 -1
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +79 -70
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +1 -1
- package/dist/esm/activities/chat/middleware/types.d.ts +59 -2
- package/dist/esm/activities/chat/middleware/validate.js +23 -28
- package/dist/esm/activities/chat/middleware/validate.js.map +1 -1
- package/dist/esm/activities/chat/stream/json-parser.js +39 -25
- package/dist/esm/activities/chat/stream/json-parser.js.map +1 -1
- package/dist/esm/activities/chat/stream/message-updaters.js +275 -234
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +24 -4
- package/dist/esm/activities/chat/stream/processor.js +1341 -1542
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/stream/strategies.js +69 -53
- package/dist/esm/activities/chat/stream/strategies.js.map +1 -1
- package/dist/esm/activities/chat/tools/approval-schema.d.ts +19 -0
- package/dist/esm/activities/chat/tools/approval-schema.js +117 -0
- package/dist/esm/activities/chat/tools/approval-schema.js.map +1 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js +164 -191
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -1
- package/dist/esm/activities/chat/tools/lazy-tools.js +24 -12
- package/dist/esm/activities/chat/tools/lazy-tools.js.map +1 -1
- package/dist/esm/activities/chat/tools/schema-converter.js +293 -146
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +18 -2
- package/dist/esm/activities/chat/tools/tool-calls.js +522 -531
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +75 -16
- package/dist/esm/activities/chat/tools/tool-definition.js +95 -23
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
- package/dist/esm/activities/error-payload.js +85 -47
- package/dist/esm/activities/error-payload.js.map +1 -1
- package/dist/esm/activities/generateAudio/adapter.js +22 -15
- package/dist/esm/activities/generateAudio/adapter.js.map +1 -1
- package/dist/esm/activities/generateAudio/index.d.ts +4 -0
- package/dist/esm/activities/generateAudio/index.js +141 -105
- package/dist/esm/activities/generateAudio/index.js.map +1 -1
- package/dist/esm/activities/generateImage/adapter.js +22 -15
- package/dist/esm/activities/generateImage/adapter.js.map +1 -1
- package/dist/esm/activities/generateImage/index.d.ts +4 -0
- package/dist/esm/activities/generateImage/index.js +155 -111
- package/dist/esm/activities/generateImage/index.js.map +1 -1
- package/dist/esm/activities/generateSpeech/adapter.js +22 -15
- package/dist/esm/activities/generateSpeech/adapter.js.map +1 -1
- package/dist/esm/activities/generateSpeech/index.d.ts +4 -0
- package/dist/esm/activities/generateSpeech/index.js +159 -110
- package/dist/esm/activities/generateSpeech/index.js.map +1 -1
- package/dist/esm/activities/generateTranscription/adapter.js +22 -15
- package/dist/esm/activities/generateTranscription/adapter.js.map +1 -1
- package/dist/esm/activities/generateTranscription/index.d.ts +4 -0
- package/dist/esm/activities/generateTranscription/index.js +159 -100
- package/dist/esm/activities/generateTranscription/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/adapter.js +36 -29
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.d.ts +143 -19
- package/dist/esm/activities/generateVideo/index.js +456 -279
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/generateVideo/snap.js +60 -48
- package/dist/esm/activities/generateVideo/snap.js.map +1 -1
- package/dist/esm/activities/index.js +8 -34
- package/dist/esm/activities/middleware/index.d.ts +1 -1
- package/dist/esm/activities/middleware/run.d.ts +10 -0
- package/dist/esm/activities/middleware/run.js +53 -29
- package/dist/esm/activities/middleware/run.js.map +1 -1
- package/dist/esm/activities/middleware/types.d.ts +44 -6
- package/dist/esm/activities/stream-generation-result.d.ts +4 -1
- package/dist/esm/activities/stream-generation-result.js +79 -44
- package/dist/esm/activities/stream-generation-result.js.map +1 -1
- package/dist/esm/activities/summarize/adapter.js +22 -15
- package/dist/esm/activities/summarize/adapter.js.map +1 -1
- package/dist/esm/activities/summarize/chat-stream-summarize.js +252 -202
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -1
- package/dist/esm/activities/summarize/index.d.ts +27 -0
- package/dist/esm/activities/summarize/index.js +268 -102
- package/dist/esm/activities/summarize/index.js.map +1 -1
- package/dist/esm/adapter-internals.d.ts +2 -1
- package/dist/esm/adapter-internals.js +4 -11
- package/dist/esm/client.d.ts +25 -3
- package/dist/esm/client.js +131 -64
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/custom-events.d.ts +76 -0
- package/dist/esm/custom-events.js +37 -0
- package/dist/esm/custom-events.js.map +1 -0
- package/dist/esm/delivery-detach.d.ts +50 -0
- package/dist/esm/delivery-detach.js +71 -0
- package/dist/esm/delivery-detach.js.map +1 -0
- package/dist/esm/delivery-disconnect.d.ts +62 -0
- package/dist/esm/delivery-disconnect.js +81 -0
- package/dist/esm/delivery-disconnect.js.map +1 -0
- package/dist/esm/extend-adapter.js +19 -17
- package/dist/esm/extend-adapter.js.map +1 -1
- package/dist/esm/index.d.ts +24 -6
- package/dist/esm/index.js +30 -98
- package/dist/esm/interrupt-resume.d.ts +71 -0
- package/dist/esm/interrupt-resume.js +438 -0
- package/dist/esm/interrupt-resume.js.map +1 -0
- package/dist/esm/interrupt-serialization.d.ts +12 -0
- package/dist/esm/interrupt-serialization.js +178 -0
- package/dist/esm/interrupt-serialization.js.map +1 -0
- package/dist/esm/interrupts.d.ts +84 -0
- package/dist/esm/interrupts.js +31 -0
- package/dist/esm/interrupts.js.map +1 -0
- package/dist/esm/locks.d.ts +10 -0
- package/dist/esm/locks.js +2 -0
- package/dist/esm/logger/console-logger.js +101 -78
- package/dist/esm/logger/console-logger.js.map +1 -1
- package/dist/esm/logger/internal-logger.js +104 -89
- package/dist/esm/logger/internal-logger.js.map +1 -1
- package/dist/esm/logger/resolve.js +54 -49
- package/dist/esm/logger/resolve.js.map +1 -1
- package/dist/esm/logger/types.d.ts +1 -1
- package/dist/esm/middlewares/content-guard.js +142 -148
- package/dist/esm/middlewares/content-guard.js.map +1 -1
- package/dist/esm/middlewares/index.js +2 -6
- package/dist/esm/middlewares/otel.d.ts +3 -1
- package/dist/esm/middlewares/otel.js +599 -732
- package/dist/esm/middlewares/otel.js.map +1 -1
- package/dist/esm/middlewares/usage-attributes.js +47 -40
- package/dist/esm/middlewares/usage-attributes.js.map +1 -1
- package/dist/esm/realtime/event-emitter.js +24 -25
- package/dist/esm/realtime/event-emitter.js.map +1 -1
- package/dist/esm/realtime/index.d.ts +5 -9
- package/dist/esm/realtime/index.js +29 -6
- package/dist/esm/realtime/index.js.map +1 -1
- package/dist/esm/scope.d.ts +47 -0
- package/dist/esm/stream-durability.d.ts +171 -0
- package/dist/esm/stream-durability.js +295 -0
- package/dist/esm/stream-durability.js.map +1 -0
- package/dist/esm/stream-to-response.d.ts +178 -13
- package/dist/esm/stream-to-response.js +663 -115
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.js +30 -16
- package/dist/esm/strip-to-spec-middleware.js.map +1 -1
- package/dist/esm/system-prompts.js +27 -21
- package/dist/esm/system-prompts.js.map +1 -1
- package/dist/esm/tool-registry.js +72 -45
- package/dist/esm/tool-registry.js.map +1 -1
- package/dist/esm/tools/provider-tool.js +14 -5
- package/dist/esm/tools/provider-tool.js.map +1 -1
- package/dist/esm/types.d.ts +321 -42
- package/dist/esm/types.js +2 -0
- package/dist/esm/utilities/ag-ui-wire.js +79 -93
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
- package/dist/esm/utilities/chat-params.d.ts +26 -4
- package/dist/esm/utilities/chat-params.js +218 -92
- package/dist/esm/utilities/chat-params.js.map +1 -1
- package/dist/esm/utilities/errors.js +28 -18
- package/dist/esm/utilities/errors.js.map +1 -1
- package/dist/esm/utilities/media-prompt.js +46 -41
- package/dist/esm/utilities/media-prompt.js.map +1 -1
- package/dist/esm/utilities/numbers.js +13 -10
- package/dist/esm/utilities/numbers.js.map +1 -1
- package/dist/esm/utilities/provider-executed.js +20 -11
- package/dist/esm/utilities/provider-executed.js.map +1 -1
- package/dist/esm/utilities/sampling-keys.js +31 -19
- package/dist/esm/utilities/sampling-keys.js.map +1 -1
- package/dist/esm/utilities/tool-result.js +42 -30
- package/dist/esm/utilities/tool-result.js.map +1 -1
- package/dist/esm/utilities/usage.js +27 -9
- package/dist/esm/utilities/usage.js.map +1 -1
- package/dist/esm/utils.js +26 -18
- package/dist/esm/utils.js.map +1 -1
- package/package.json +10 -6
- package/skills/ai-core/SKILL.md +69 -18
- package/skills/ai-core/adapter-configuration/SKILL.md +44 -21
- package/skills/ai-core/adapter-configuration/references/anthropic-adapter.md +1 -3
- package/skills/ai-core/adapter-configuration/references/byteplus-adapter.md +148 -0
- package/skills/ai-core/adapter-configuration/references/gemini-adapter.md +2 -6
- package/skills/ai-core/adapter-configuration/references/groq-adapter.md +2 -6
- package/skills/ai-core/adapter-configuration/references/openai-adapter.md +1 -3
- package/skills/ai-core/ag-ui-protocol/SKILL.md +1 -1
- package/skills/ai-core/chat-experience/SKILL.md +98 -11
- package/skills/ai-core/client-persistence/SKILL.md +277 -0
- package/skills/ai-core/custom-backend-integration/SKILL.md +1 -1
- package/skills/ai-core/debug-logging/SKILL.md +1 -1
- package/skills/ai-core/locks/SKILL.md +143 -0
- package/skills/ai-core/media-generation/SKILL.md +144 -12
- package/skills/ai-core/middleware/SKILL.md +258 -33
- package/skills/ai-core/structured-outputs/SKILL.md +1 -1
- package/skills/ai-core/tool-calling/SKILL.md +54 -61
- package/src/activities/chat/agent-loop-strategies.ts +5 -39
- package/src/activities/chat/cancel.ts +81 -0
- package/src/activities/chat/index.ts +1091 -200
- package/src/activities/chat/mcp/manager.ts +4 -4
- package/src/activities/chat/mcp/types.ts +2 -2
- package/src/activities/chat/messages.ts +5 -3
- package/src/activities/chat/middleware/builder.ts +1 -1
- package/src/activities/chat/middleware/compose.ts +186 -9
- package/src/activities/chat/middleware/index.ts +26 -0
- package/src/activities/chat/middleware/locks.ts +102 -0
- package/src/activities/chat/middleware/pending-turn.ts +47 -0
- package/src/activities/chat/middleware/run-disconnect.ts +62 -0
- package/src/activities/chat/middleware/run-store.ts +412 -0
- package/src/activities/chat/middleware/types.ts +62 -1
- package/src/activities/chat/stream/processor.ts +189 -5
- package/src/activities/chat/tools/approval-schema.ts +205 -0
- package/src/activities/chat/tools/tool-calls.ts +106 -13
- package/src/activities/chat/tools/tool-definition.ts +210 -39
- package/src/activities/generateAudio/index.ts +20 -3
- package/src/activities/generateImage/index.ts +20 -3
- package/src/activities/generateSpeech/index.ts +25 -3
- package/src/activities/generateTranscription/index.ts +26 -3
- package/src/activities/generateVideo/index.ts +345 -82
- package/src/activities/middleware/index.ts +2 -0
- package/src/activities/middleware/run.ts +31 -0
- package/src/activities/middleware/types.ts +49 -5
- package/src/activities/stream-generation-result.ts +30 -2
- package/src/activities/summarize/chat-stream-summarize.ts +5 -0
- package/src/activities/summarize/index.ts +200 -10
- package/src/adapter-internals.ts +10 -1
- package/src/client.ts +244 -0
- package/src/custom-events.ts +107 -0
- package/src/delivery-detach.ts +72 -0
- package/src/delivery-disconnect.ts +84 -0
- package/src/index.ts +138 -1
- package/src/interrupt-resume.ts +824 -0
- package/src/interrupt-serialization.ts +183 -0
- package/src/interrupts.ts +146 -0
- package/src/locks.ts +17 -0
- package/src/logger/types.ts +1 -1
- package/src/middlewares/otel.ts +23 -5
- package/src/realtime/index.ts +5 -9
- package/src/scope.ts +47 -0
- package/src/stream-durability.ts +598 -0
- package/src/stream-to-response.ts +1051 -95
- package/src/strip-to-spec-middleware.ts +3 -3
- package/src/types.ts +405 -45
- package/src/utilities/chat-params.ts +245 -55
- package/dist/esm/activities/index.js.map +0 -1
- package/dist/esm/adapter-internals.js.map +0 -1
- package/dist/esm/index.js.map +0 -1
- package/dist/esm/middlewares/index.js.map +0 -1
package/src/client.ts
CHANGED
|
@@ -1,3 +1,194 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AudioGenerationOptions,
|
|
3
|
+
ImageGenerationOptions,
|
|
4
|
+
TTSOptions,
|
|
5
|
+
TranscriptionOptions,
|
|
6
|
+
VideoGenerationOptions,
|
|
7
|
+
} from './types'
|
|
8
|
+
|
|
9
|
+
export type GenerationKind =
|
|
10
|
+
| 'image'
|
|
11
|
+
| 'audio'
|
|
12
|
+
| 'tts'
|
|
13
|
+
| 'video'
|
|
14
|
+
| 'transcription'
|
|
15
|
+
|
|
16
|
+
type GenerationInputByKind = {
|
|
17
|
+
image: Omit<ImageGenerationOptions, 'logger' | 'model'>
|
|
18
|
+
audio: Omit<AudioGenerationOptions, 'logger' | 'model'>
|
|
19
|
+
tts: Omit<TTSOptions, 'logger' | 'model'>
|
|
20
|
+
video: Omit<VideoGenerationOptions, 'logger' | 'model'>
|
|
21
|
+
transcription: Omit<TranscriptionOptions, 'logger' | 'model'>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface GenerationParams<TKind extends GenerationKind> {
|
|
25
|
+
input: GenerationInputByKind[TKind]
|
|
26
|
+
forwardedProps: Record<string, unknown>
|
|
27
|
+
threadId?: string
|
|
28
|
+
runId?: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const generationKinds = [
|
|
32
|
+
'image',
|
|
33
|
+
'audio',
|
|
34
|
+
'tts',
|
|
35
|
+
'video',
|
|
36
|
+
'transcription',
|
|
37
|
+
] as const satisfies ReadonlyArray<GenerationKind>
|
|
38
|
+
|
|
39
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
40
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function hasOwnKey(value: Record<string, unknown>, key: string): boolean {
|
|
44
|
+
return Object.prototype.hasOwnProperty.call(value, key)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function isGenerationEnvelope(body: unknown): body is Record<string, unknown> {
|
|
48
|
+
return (
|
|
49
|
+
isRecord(body) &&
|
|
50
|
+
(hasOwnKey(body, 'data') || hasOwnKey(body, 'forwardedProps'))
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function assertGenerationKind(kind: unknown): asserts kind is GenerationKind {
|
|
55
|
+
if (!generationKinds.includes(kind as GenerationKind)) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Unsupported generation kind: ${String(
|
|
58
|
+
kind,
|
|
59
|
+
)}. Expected one of ${generationKinds.join(', ')}.`,
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function assertInputForKind(
|
|
65
|
+
kind: GenerationKind,
|
|
66
|
+
input: unknown,
|
|
67
|
+
): asserts input is GenerationInputByKind[GenerationKind] {
|
|
68
|
+
if (!isRecord(input)) {
|
|
69
|
+
throw new Error(`Generation ${kind} input must be an object.`)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const requiredKey =
|
|
73
|
+
kind === 'tts' ? 'text' : kind === 'transcription' ? 'audio' : 'prompt'
|
|
74
|
+
|
|
75
|
+
if (!hasOwnKey(input, requiredKey)) {
|
|
76
|
+
throw new Error(`Generation ${kind} input must include ${requiredKey}.`)
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function isInputForKind(kind: GenerationKind, input: unknown): boolean {
|
|
81
|
+
if (!isRecord(input)) return false
|
|
82
|
+
|
|
83
|
+
const requiredKey =
|
|
84
|
+
kind === 'tts' ? 'text' : kind === 'transcription' ? 'audio' : 'prompt'
|
|
85
|
+
|
|
86
|
+
return hasOwnKey(input, requiredKey)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function forwardedPropsFromEnvelope(
|
|
90
|
+
envelope: Record<string, unknown>,
|
|
91
|
+
): Record<string, unknown> {
|
|
92
|
+
if (!hasOwnKey(envelope, 'forwardedProps')) {
|
|
93
|
+
return {}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!isRecord(envelope.forwardedProps)) {
|
|
97
|
+
throw new Error('Generation envelope forwardedProps must be an object.')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return envelope.forwardedProps
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function optionalStringField(
|
|
104
|
+
envelope: Record<string, unknown>,
|
|
105
|
+
key: 'threadId' | 'runId',
|
|
106
|
+
): string | undefined {
|
|
107
|
+
if (!hasOwnKey(envelope, key)) {
|
|
108
|
+
return undefined
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const value = envelope[key]
|
|
112
|
+
if (typeof value !== 'string') {
|
|
113
|
+
throw new Error(`Generation envelope ${key} must be a string.`)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return value
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function generationIdentityFields(envelope: Record<string, unknown>): {
|
|
120
|
+
threadId?: string
|
|
121
|
+
runId?: string
|
|
122
|
+
} {
|
|
123
|
+
const identity: {
|
|
124
|
+
threadId?: string
|
|
125
|
+
runId?: string
|
|
126
|
+
} = {}
|
|
127
|
+
const threadId = optionalStringField(envelope, 'threadId')
|
|
128
|
+
const runId = optionalStringField(envelope, 'runId')
|
|
129
|
+
|
|
130
|
+
if (threadId !== undefined) identity.threadId = threadId
|
|
131
|
+
if (runId !== undefined) identity.runId = runId
|
|
132
|
+
|
|
133
|
+
return identity
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function generationParamsFromBody<TKind extends GenerationKind>(
|
|
137
|
+
kind: TKind,
|
|
138
|
+
body: unknown,
|
|
139
|
+
): GenerationParams<TKind> {
|
|
140
|
+
assertGenerationKind(kind)
|
|
141
|
+
|
|
142
|
+
if (isInputForKind(kind, body)) {
|
|
143
|
+
assertInputForKind(kind, body)
|
|
144
|
+
return {
|
|
145
|
+
input: body as GenerationInputByKind[TKind],
|
|
146
|
+
forwardedProps: {},
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!isGenerationEnvelope(body)) {
|
|
151
|
+
assertInputForKind(kind, body)
|
|
152
|
+
return {
|
|
153
|
+
input: body as GenerationInputByKind[TKind],
|
|
154
|
+
forwardedProps: {},
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (!hasOwnKey(body, 'data')) {
|
|
159
|
+
throw new Error(`Generation ${kind} envelope must include data.`)
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const input = body.data
|
|
163
|
+
assertInputForKind(kind, input)
|
|
164
|
+
|
|
165
|
+
const forwardedProps = forwardedPropsFromEnvelope(body)
|
|
166
|
+
|
|
167
|
+
return {
|
|
168
|
+
input: input as GenerationInputByKind[TKind],
|
|
169
|
+
forwardedProps,
|
|
170
|
+
...generationIdentityFields(body),
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export async function generationParamsFromRequest<TKind extends GenerationKind>(
|
|
175
|
+
kind: TKind,
|
|
176
|
+
request: Request,
|
|
177
|
+
): Promise<GenerationParams<TKind>> {
|
|
178
|
+
let body: unknown
|
|
179
|
+
try {
|
|
180
|
+
body = await request.json()
|
|
181
|
+
} catch (error) {
|
|
182
|
+
throw new Error('Invalid JSON request body.', { cause: error })
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (!isRecord(body)) {
|
|
186
|
+
throw new Error('Generation request body must be a JSON object.')
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return generationParamsFromBody(kind, body)
|
|
190
|
+
}
|
|
191
|
+
|
|
1
192
|
export enum EventType {
|
|
2
193
|
TEXT_MESSAGE_START = 'TEXT_MESSAGE_START',
|
|
3
194
|
TEXT_MESSAGE_CONTENT = 'TEXT_MESSAGE_CONTENT',
|
|
@@ -41,15 +232,35 @@ export {
|
|
|
41
232
|
type InferToolInput,
|
|
42
233
|
type InferToolName,
|
|
43
234
|
type InferToolOutput,
|
|
235
|
+
type ApprovalCapabilityOf,
|
|
236
|
+
type ApprovalSchemaConfig,
|
|
237
|
+
type ApprovalSchemaOf,
|
|
238
|
+
type InputSchemaOf,
|
|
239
|
+
type OutputSchemaOf,
|
|
240
|
+
type NoSchema,
|
|
44
241
|
type ToolDefinition,
|
|
45
242
|
type ToolDefinitionConfig,
|
|
46
243
|
type ToolDefinitionInstance,
|
|
47
244
|
} from './activities/chat/tools/tool-definition'
|
|
48
245
|
|
|
246
|
+
export {
|
|
247
|
+
hashSchemaInput,
|
|
248
|
+
normalizeApprovalSchema,
|
|
249
|
+
type NormalizedApprovalSchema,
|
|
250
|
+
type NormalizedSchemaInput,
|
|
251
|
+
} from './activities/chat/tools/approval-schema'
|
|
252
|
+
|
|
253
|
+
export {
|
|
254
|
+
canonicalInterruptJson,
|
|
255
|
+
cloneAndDeepFreezeJson,
|
|
256
|
+
digestInterruptJson,
|
|
257
|
+
} from './interrupt-serialization'
|
|
258
|
+
|
|
49
259
|
export {
|
|
50
260
|
convertSchemaToJsonSchema,
|
|
51
261
|
isStandardSchema,
|
|
52
262
|
parseWithStandardSchema,
|
|
263
|
+
validateWithStandardSchema,
|
|
53
264
|
} from './activities/chat/tools/schema-converter'
|
|
54
265
|
|
|
55
266
|
export {
|
|
@@ -103,8 +314,14 @@ export type {
|
|
|
103
314
|
MediaPromptPart,
|
|
104
315
|
MessagePart,
|
|
105
316
|
ModelMessage,
|
|
317
|
+
PersistedArtifactActivity,
|
|
318
|
+
PersistedArtifactRef,
|
|
319
|
+
PersistedArtifactRole,
|
|
320
|
+
Interrupt,
|
|
321
|
+
RunAgentResumeItem,
|
|
106
322
|
RunErrorEvent,
|
|
107
323
|
RunFinishedEvent,
|
|
324
|
+
RunFinishedOutcome,
|
|
108
325
|
SchemaInput,
|
|
109
326
|
StreamChunk,
|
|
110
327
|
StructuredOutputPart,
|
|
@@ -119,6 +336,33 @@ export type {
|
|
|
119
336
|
InferSchemaType,
|
|
120
337
|
} from './types'
|
|
121
338
|
|
|
339
|
+
// Enumerated, not `export *` — see the matching note in `index.ts`. The
|
|
340
|
+
// interrupt protocol surface is a commitment, so it is published field by
|
|
341
|
+
// field.
|
|
342
|
+
export {
|
|
343
|
+
INTERRUPT_BINDING_VERSION,
|
|
344
|
+
canonicalizeInterruptResolutions,
|
|
345
|
+
} from './interrupts'
|
|
346
|
+
export type {
|
|
347
|
+
BatchInterruptError,
|
|
348
|
+
BatchInterruptErrorCode,
|
|
349
|
+
InterruptBinding,
|
|
350
|
+
InterruptCorrelation,
|
|
351
|
+
InterruptSubmissionError,
|
|
352
|
+
ItemInterruptError,
|
|
353
|
+
ItemInterruptErrorCode,
|
|
354
|
+
ToolApprovalResolution,
|
|
355
|
+
UnopenedInterruptBinding,
|
|
356
|
+
} from './interrupts'
|
|
357
|
+
|
|
358
|
+
export {
|
|
359
|
+
INTERRUPT_BINDING_METADATA_KEY,
|
|
360
|
+
readInterruptBinding,
|
|
361
|
+
readUnopenedInterruptBinding,
|
|
362
|
+
withInterruptBinding,
|
|
363
|
+
withoutInterruptBinding,
|
|
364
|
+
} from './interrupt-resume'
|
|
365
|
+
|
|
122
366
|
export type {
|
|
123
367
|
AudioVisualization,
|
|
124
368
|
RealtimeAdapter,
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Catalog of well-known AG-UI `CUSTOM` event names used by the sandbox/agent
|
|
3
|
+
* layers, plus their payload shapes.
|
|
4
|
+
*
|
|
5
|
+
* The persisted run log is the AG-UI `StreamChunk` stream itself — there is no
|
|
6
|
+
* separate `RunEvent` type. Agent activity that has no first-class AG-UI event
|
|
7
|
+
* (process output, file diffs, ports, approvals, artifacts, sandbox lifecycle)
|
|
8
|
+
* rides on `CUSTOM` events carrying one of these names. Centralizing the names +
|
|
9
|
+
* payloads here keeps emitters (harness adapters, sandbox) and consumers
|
|
10
|
+
* (persistence projections, devtools, diff/terminal panels) in agreement without
|
|
11
|
+
* inventing a parallel event union.
|
|
12
|
+
*/
|
|
13
|
+
import { EventType } from './types'
|
|
14
|
+
import type { CustomEvent, StreamChunk } from './types'
|
|
15
|
+
|
|
16
|
+
/** Well-known CUSTOM event names. */
|
|
17
|
+
export const CUSTOM_EVENT = {
|
|
18
|
+
FILE_CHANGED: 'file.changed',
|
|
19
|
+
PROCESS_STDOUT: 'process.stdout',
|
|
20
|
+
PROCESS_STDERR: 'process.stderr',
|
|
21
|
+
PORT_OPENED: 'port.opened',
|
|
22
|
+
APPROVAL_REQUESTED: 'approval.requested',
|
|
23
|
+
APPROVAL_RESOLVED: 'approval.resolved',
|
|
24
|
+
ARTIFACT_CREATED: 'artifact.created',
|
|
25
|
+
SANDBOX_CREATED: 'sandbox.created',
|
|
26
|
+
SANDBOX_RESUMED: 'sandbox.resumed',
|
|
27
|
+
} as const
|
|
28
|
+
|
|
29
|
+
/** Union of the well-known CUSTOM event name literals. */
|
|
30
|
+
export type WellKnownCustomEventName =
|
|
31
|
+
(typeof CUSTOM_EVENT)[keyof typeof CUSTOM_EVENT]
|
|
32
|
+
|
|
33
|
+
// ---- Payload shapes ----
|
|
34
|
+
|
|
35
|
+
export interface FileChangedPayload {
|
|
36
|
+
type: 'create' | 'change' | 'delete'
|
|
37
|
+
/** Absolute path inside the sandbox (under the workspace root). */
|
|
38
|
+
path: string
|
|
39
|
+
/** Unified diff, when the harness can produce one. */
|
|
40
|
+
diff?: string
|
|
41
|
+
timestamp: number
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ProcessOutputPayload {
|
|
45
|
+
/** Stable id for the spawned process whose output this is. */
|
|
46
|
+
processId: string
|
|
47
|
+
/** A chunk of stdout/stderr text. */
|
|
48
|
+
chunk: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface PortOpenedPayload {
|
|
52
|
+
port: number
|
|
53
|
+
/** Externally reachable URL, when the provider exposes one. */
|
|
54
|
+
url?: string
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ApprovalRequestedPayload {
|
|
58
|
+
approvalId: string
|
|
59
|
+
title: string
|
|
60
|
+
/** Free-form detail describing the action awaiting approval. */
|
|
61
|
+
[key: string]: unknown
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface ApprovalResolvedPayload {
|
|
65
|
+
approvalId: string
|
|
66
|
+
granted: boolean
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export interface ArtifactCreatedPayload {
|
|
70
|
+
artifactId: string
|
|
71
|
+
name: string
|
|
72
|
+
mimeType: string
|
|
73
|
+
size: number
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface SandboxLifecyclePayload {
|
|
77
|
+
sandboxId: string
|
|
78
|
+
provider: string
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Maps each well-known name to its payload type. */
|
|
82
|
+
export interface CustomEventPayloads {
|
|
83
|
+
[CUSTOM_EVENT.FILE_CHANGED]: FileChangedPayload
|
|
84
|
+
[CUSTOM_EVENT.PROCESS_STDOUT]: ProcessOutputPayload
|
|
85
|
+
[CUSTOM_EVENT.PROCESS_STDERR]: ProcessOutputPayload
|
|
86
|
+
[CUSTOM_EVENT.PORT_OPENED]: PortOpenedPayload
|
|
87
|
+
[CUSTOM_EVENT.APPROVAL_REQUESTED]: ApprovalRequestedPayload
|
|
88
|
+
[CUSTOM_EVENT.APPROVAL_RESOLVED]: ApprovalResolvedPayload
|
|
89
|
+
[CUSTOM_EVENT.ARTIFACT_CREATED]: ArtifactCreatedPayload
|
|
90
|
+
[CUSTOM_EVENT.SANDBOX_CREATED]: SandboxLifecyclePayload
|
|
91
|
+
[CUSTOM_EVENT.SANDBOX_RESUMED]: SandboxLifecyclePayload
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** A CUSTOM event narrowed to a specific well-known name and its payload. */
|
|
95
|
+
export type WellKnownCustomEvent<TName extends WellKnownCustomEventName> =
|
|
96
|
+
CustomEvent & { name: TName; value: CustomEventPayloads[TName] }
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Type guard: is `chunk` a CUSTOM event with the given well-known `name`?
|
|
100
|
+
* Narrows the payload type when true, so consumers read `chunk.value` typed.
|
|
101
|
+
*/
|
|
102
|
+
export function isCustomEvent<TName extends WellKnownCustomEventName>(
|
|
103
|
+
chunk: StreamChunk,
|
|
104
|
+
name: TName,
|
|
105
|
+
): chunk is WellKnownCustomEvent<TName> {
|
|
106
|
+
return chunk.type === EventType.CUSTOM && chunk.name === name
|
|
107
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one-way channel from a chat run to the durable DELIVERY sink that is
|
|
3
|
+
* persisting it.
|
|
4
|
+
*
|
|
5
|
+
* The sink (`durableStreamSource` in `./stream-to-response.ts`) has to answer one
|
|
6
|
+
* question on the abort path: was this disconnect a DETACH — the agent keeps
|
|
7
|
+
* running and a later attach will continue the log — or the end of the run? Only
|
|
8
|
+
* the run's own middleware can answer it (`withSandbox`'s `onAbort` resolves both
|
|
9
|
+
* out-of-band cancel bands and `detachOnDisconnect`), and the sink cannot reach
|
|
10
|
+
* the middleware capability bus: it lives one layer up, in the transport, and is
|
|
11
|
+
* handed nothing but the stream and a durability adapter.
|
|
12
|
+
*
|
|
13
|
+
* So the fact travels on the STREAM ITSELF, keyed by the exact object `chat()`
|
|
14
|
+
* returned. That is the seam an application cannot forget to wire: passing the
|
|
15
|
+
* stream to `toServerSentEventsResponse(stream, { durability })` is already
|
|
16
|
+
* mandatory, and it is the same object both sides hold. The alternative — a
|
|
17
|
+
* `detachable` flag on the response options — has to be re-wired correctly at
|
|
18
|
+
* every durable call site, and a forgotten one silently terminalizes a healthy
|
|
19
|
+
* detached run's log, which is the exact defect this channel exists to fix.
|
|
20
|
+
*
|
|
21
|
+
* The value is a THUNK, not a boolean: the verdict is only known during the run's
|
|
22
|
+
* teardown, long after the response object was built.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Per-stream detach predicates. Keyed weakly by the stream object, so a stream
|
|
27
|
+
* that is dropped without ever being consumed takes its entry with it.
|
|
28
|
+
*/
|
|
29
|
+
const detachSignals = new WeakMap<object, () => boolean>()
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Publish `stream`'s detach predicate. Called by `chat()` on the object it hands
|
|
33
|
+
* back, once per stream.
|
|
34
|
+
*
|
|
35
|
+
* Wired on BOTH streaming paths — `runStreamingText` and
|
|
36
|
+
* `runStreamingStructuredOutput` — since either can be handed to a durable
|
|
37
|
+
* transport helper. The non-streaming paths (`stream: false`, and the
|
|
38
|
+
* `Promise<T>` structured-output variant) resolve a value rather than yielding a
|
|
39
|
+
* stream, so there is no delivery sink to inform and nothing to publish.
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
export function publishRunDetachedSignal(
|
|
44
|
+
stream: object,
|
|
45
|
+
wasDetached: () => boolean,
|
|
46
|
+
): void {
|
|
47
|
+
detachSignals.set(stream, wasDetached)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Whether the run behind `stream` declared its abort a detach.
|
|
52
|
+
*
|
|
53
|
+
* `false` for anything that never published a predicate — a hand-rolled
|
|
54
|
+
* iterable, a `chat()` from an older build, a non-object source — so an unknown
|
|
55
|
+
* stream keeps the terminalize-and-close behavior rather than being spared it.
|
|
56
|
+
*
|
|
57
|
+
* A throwing predicate is also `false`, for the same reason: this is consulted on
|
|
58
|
+
* a teardown path where the only safe default is to terminalize. Leaving a log
|
|
59
|
+
* open because a probe threw would park every tailer forever.
|
|
60
|
+
*
|
|
61
|
+
* @internal
|
|
62
|
+
*/
|
|
63
|
+
export function wasRunDetached(stream: unknown): boolean {
|
|
64
|
+
if (typeof stream !== 'object' || stream === null) return false
|
|
65
|
+
const signal = detachSignals.get(stream)
|
|
66
|
+
if (signal === undefined) return false
|
|
67
|
+
try {
|
|
68
|
+
return signal()
|
|
69
|
+
} catch {
|
|
70
|
+
return false
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one-way channel from the durable DELIVERY sink back to the chat run: "your
|
|
3
|
+
* viewer is gone, but you are not."
|
|
4
|
+
*
|
|
5
|
+
* This is the MIRROR of `./delivery-detach.ts`. That module answers a question the
|
|
6
|
+
* sink asks the run (was this abort a detach?); this one delivers a fact the sink
|
|
7
|
+
* learns first and the run cannot observe at all — the response body was
|
|
8
|
+
* cancelled. Both are keyed weakly by the exact stream object `chat()` returned,
|
|
9
|
+
* for the same reason: passing that object to
|
|
10
|
+
* `toServerSentEventsResponse(stream, { durability })` is already mandatory, so it
|
|
11
|
+
* is the one seam an application cannot forget to wire.
|
|
12
|
+
*
|
|
13
|
+
* WHY THE RUN CANNOT JUST WATCH AN ABORT SIGNAL. Before this channel existed, the
|
|
14
|
+
* only way a disconnect reached a run's middleware was for the application to
|
|
15
|
+
* mirror `request.signal` into `chat()`'s `abortController` — which ABORTS THE RUN.
|
|
16
|
+
* For a durable run that is precisely wrong, and wrong in the most expensive
|
|
17
|
+
* direction: `chat()` returns at its `isCancelled()` check immediately after
|
|
18
|
+
* middleware setup, so the harness adapter's `chatStream` is never called and the
|
|
19
|
+
* agent in the freshly-created sandbox is NEVER LAUNCHED. The user re-attaches to
|
|
20
|
+
* an empty log belonging to a run that did nothing, and no takeover can recover it
|
|
21
|
+
* because there is no journal to replay. The application was forced to choose
|
|
22
|
+
* between "the middleware learns about the disconnect" and "the run survives it".
|
|
23
|
+
*
|
|
24
|
+
* So the disconnect travels as a NOTIFICATION rather than a cancellation. The run
|
|
25
|
+
* hands it to whatever subscribed through `RunDisconnectCapability` — bookkeeping
|
|
26
|
+
* only, no teardown — and keeps producing into its still-open durable log, which
|
|
27
|
+
* is exactly what a re-attaching client tails to catch up.
|
|
28
|
+
*
|
|
29
|
+
* DISPATCHED FROM THE TRANSPORT, NOT FROM THE RUN'S UNWINDING. That is what makes
|
|
30
|
+
* it prompt. A run suspended inside a minutes-wide `setup` (cloning a repo into a
|
|
31
|
+
* sandbox) cannot dispatch anything from its own `finally`, because the `finally`
|
|
32
|
+
* is reached only once the generator unwinds — which is what made `detachedSince`
|
|
33
|
+
* land three minutes late instead of immediately.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Per-stream disconnect handlers. Keyed weakly by the stream object, so a stream
|
|
38
|
+
* dropped without ever being consumed takes its entry with it.
|
|
39
|
+
*/
|
|
40
|
+
const disconnectHandlers = new WeakMap<object, () => void>()
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Publish `stream`'s disconnect handler. Called by `chat()` on the object it hands
|
|
44
|
+
* back, once per stream.
|
|
45
|
+
*
|
|
46
|
+
* Wired on BOTH streaming paths — `runStreamingText` and
|
|
47
|
+
* `runStreamingStructuredOutput` — since either can be handed to a durable
|
|
48
|
+
* transport helper, matching `publishRunDetachedSignal`.
|
|
49
|
+
*
|
|
50
|
+
* @internal
|
|
51
|
+
*/
|
|
52
|
+
export function publishRunDisconnectHandler(
|
|
53
|
+
stream: object,
|
|
54
|
+
onDisconnect: () => void,
|
|
55
|
+
): void {
|
|
56
|
+
disconnectHandlers.set(stream, onDisconnect)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Tell the run behind `stream` that its delivery socket closed.
|
|
61
|
+
*
|
|
62
|
+
* A NO-OP for anything that never published a handler — a hand-rolled iterable, a
|
|
63
|
+
* `chat()` from an older build, a non-object source — so an unknown stream simply
|
|
64
|
+
* keeps today's behavior.
|
|
65
|
+
*
|
|
66
|
+
* NEVER THROWS and never returns a promise to await. This is called from
|
|
67
|
+
* `ReadableStream.cancel()`, whose rejection would surface as an unhandled error
|
|
68
|
+
* on a path where the consumer has already gone away; and the handler's own work
|
|
69
|
+
* is tracked by the run (which awaits it before finishing), not by this call. A
|
|
70
|
+
* throwing handler is swallowed for the same reason `wasRunDetached` swallows: the
|
|
71
|
+
* disconnect path has no second channel to report on.
|
|
72
|
+
*
|
|
73
|
+
* @internal
|
|
74
|
+
*/
|
|
75
|
+
export function notifyRunDisconnected(stream: unknown): void {
|
|
76
|
+
if (typeof stream !== 'object' || stream === null) return
|
|
77
|
+
const handler = disconnectHandlers.get(stream)
|
|
78
|
+
if (handler === undefined) return
|
|
79
|
+
try {
|
|
80
|
+
handler()
|
|
81
|
+
} catch {
|
|
82
|
+
// Intentionally empty: see above.
|
|
83
|
+
}
|
|
84
|
+
}
|