@tanstack/ai 0.10.3 → 0.11.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 +4 -0
- package/dist/esm/activities/chat/index.js +50 -16
- package/dist/esm/activities/chat/index.js.map +1 -1
- package/dist/esm/activities/chat/middleware/compose.js +5 -4
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
- package/dist/esm/activities/chat/stream/processor.d.ts +16 -1
- package/dist/esm/activities/chat/stream/processor.js +120 -21
- package/dist/esm/activities/chat/stream/processor.js.map +1 -1
- package/dist/esm/activities/chat/stream/types.d.ts +1 -0
- package/dist/esm/activities/chat/tools/schema-converter.js +4 -2
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
- package/dist/esm/activities/chat/tools/tool-calls.js +3 -1
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
- package/dist/esm/activities/generateVideo/index.js +6 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -1
- package/dist/esm/activities/stream-generation-result.d.ts +3 -2
- package/dist/esm/activities/stream-generation-result.js +12 -4
- package/dist/esm/activities/stream-generation-result.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/stream-to-response.d.ts +2 -2
- package/dist/esm/stream-to-response.js +0 -1
- package/dist/esm/stream-to-response.js.map +1 -1
- package/dist/esm/strip-to-spec-middleware.d.ts +18 -0
- package/dist/esm/strip-to-spec-middleware.js +20 -0
- package/dist/esm/strip-to-spec-middleware.js.map +1 -0
- package/dist/esm/types.d.ts +229 -95
- package/package.json +3 -2
- package/src/activities/chat/index.ts +90 -25
- package/src/activities/chat/middleware/compose.ts +6 -4
- package/src/activities/chat/stream/processor.ts +152 -25
- package/src/activities/chat/stream/types.ts +1 -0
- package/src/activities/chat/tools/schema-converter.ts +8 -2
- package/src/activities/chat/tools/tool-calls.ts +4 -2
- package/src/activities/generateVideo/index.ts +13 -6
- package/src/activities/stream-generation-result.ts +19 -11
- package/src/stream-to-response.ts +2 -4
- package/src/strip-to-spec-middleware.ts +37 -0
- package/src/types.ts +276 -109
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compose.js","sources":["../../../../../src/activities/chat/middleware/compose.ts"],"sourcesContent":["import { aiEventClient } from '@tanstack/ai-event-client'\nimport type { StreamChunk } from '../../../types'\nimport type {\n AbortInfo,\n AfterToolCallInfo,\n BeforeToolCallDecision,\n ChatMiddleware,\n ChatMiddlewareConfig,\n ChatMiddlewareContext,\n ErrorInfo,\n FinishInfo,\n IterationInfo,\n ToolCallHookContext,\n ToolPhaseCompleteInfo,\n UsageInfo,\n} from './types'\n\n/** Check if a middleware should be skipped for instrumentation events. */\nfunction shouldSkipInstrumentation(mw: ChatMiddleware): boolean {\n return mw.name === 'devtools'\n}\n\n/** Build the base context for middleware instrumentation events. */\nfunction instrumentCtx(ctx: ChatMiddlewareContext) {\n return {\n requestId: ctx.requestId,\n streamId: ctx.streamId,\n clientId: ctx.conversationId,\n timestamp: Date.now(),\n }\n}\n\n/**\n * Internal middleware runner that manages composed execution of middleware hooks.\n * Created once per chat() invocation.\n */\nexport class MiddlewareRunner {\n private readonly middlewares: ReadonlyArray<ChatMiddleware>\n\n constructor(middlewares: ReadonlyArray<ChatMiddleware>) {\n this.middlewares = middlewares\n }\n\n get hasMiddleware(): boolean {\n return this.middlewares.length > 0\n }\n\n /**\n * Pipe config through all middleware onConfig hooks in order.\n * Each middleware receives the merged config from previous middleware.\n * Partial returns are shallow-merged with the current config.\n */\n async runOnConfig(\n ctx: ChatMiddlewareContext,\n config: ChatMiddlewareConfig,\n ): Promise<ChatMiddlewareConfig> {\n let current = config\n for (const mw of this.middlewares) {\n if (mw.onConfig) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n const result = await mw.onConfig(ctx, current)\n const hasTransform = result !== undefined && result !== null\n if (hasTransform) {\n current = { ...current, ...result }\n }\n if (!skip) {\n const base = instrumentCtx(ctx)\n aiEventClient.emit('middleware:hook:executed', {\n ...base,\n middlewareName: mw.name || 'unnamed',\n hookName: 'onConfig',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform,\n })\n if (hasTransform) {\n aiEventClient.emit('middleware:config:transformed', {\n ...base,\n middlewareName: mw.name || 'unnamed',\n iteration: ctx.iteration,\n changes: result as Record<string, unknown>,\n })\n }\n }\n }\n }\n return current\n }\n\n /**\n * Call onStart on all middleware in order.\n */\n async runOnStart(ctx: ChatMiddlewareContext): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onStart) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onStart(ctx)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onStart',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Pipe a single chunk through all middleware onChunk hooks in order.\n * Returns the resulting chunks (0..N) to yield to the consumer.\n *\n * - void: pass through unchanged\n * - chunk: replace with this chunk\n * - chunk[]: expand to multiple chunks\n * - null: drop the chunk entirely\n */\n async runOnChunk(\n ctx: ChatMiddlewareContext,\n chunk: StreamChunk,\n ): Promise<Array<StreamChunk>> {\n let chunks: Array<StreamChunk> = [chunk]\n\n for (const mw of this.middlewares) {\n if (!mw.onChunk) continue\n const skip = shouldSkipInstrumentation(mw)\n\n const nextChunks: Array<StreamChunk> = []\n for (const c of chunks) {\n const result = await mw.onChunk(ctx, c)\n if (result === null) {\n // Drop this chunk\n if (!skip) {\n aiEventClient.emit('middleware:chunk:transformed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n originalChunkType: c.type,\n resultCount: 0,\n wasDropped: true,\n })\n }\n continue\n } else if (result === undefined) {\n // Pass through — no instrumentation for pass-throughs\n nextChunks.push(c)\n } else if (Array.isArray(result)) {\n // Expand\n nextChunks.push(...result)\n if (!skip) {\n aiEventClient.emit('middleware:chunk:transformed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n originalChunkType: c.type,\n resultCount: result.length,\n wasDropped: false,\n })\n }\n } else {\n // Replace\n nextChunks.push(result)\n if (!skip) {\n aiEventClient.emit('middleware:chunk:transformed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n originalChunkType: c.type,\n resultCount: 1,\n wasDropped: false,\n })\n }\n }\n }\n chunks = nextChunks\n }\n\n return chunks\n }\n\n /**\n * Run onBeforeToolCall through middleware in order.\n * Returns the first non-void decision, or undefined to continue normally.\n */\n async runOnBeforeToolCall(\n ctx: ChatMiddlewareContext,\n hookCtx: ToolCallHookContext,\n ): Promise<BeforeToolCallDecision> {\n for (const mw of this.middlewares) {\n if (mw.onBeforeToolCall) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n const decision = await mw.onBeforeToolCall(ctx, hookCtx)\n const hasTransform = decision !== undefined && decision !== null\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onBeforeToolCall',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform,\n })\n }\n if (hasTransform) {\n return decision\n }\n }\n }\n return undefined\n }\n\n /**\n * Run onAfterToolCall on all middleware in order.\n */\n async runOnAfterToolCall(\n ctx: ChatMiddlewareContext,\n info: AfterToolCallInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onAfterToolCall) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onAfterToolCall(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onAfterToolCall',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onUsage on all middleware in order.\n */\n async runOnUsage(\n ctx: ChatMiddlewareContext,\n usage: UsageInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onUsage) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onUsage(ctx, usage)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onUsage',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onFinish on all middleware in order.\n */\n async runOnFinish(\n ctx: ChatMiddlewareContext,\n info: FinishInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onFinish) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onFinish(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onFinish',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onAbort on all middleware in order.\n */\n async runOnAbort(ctx: ChatMiddlewareContext, info: AbortInfo): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onAbort) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onAbort(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onAbort',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onError on all middleware in order.\n */\n async runOnError(ctx: ChatMiddlewareContext, info: ErrorInfo): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onError) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onError(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onError',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onIteration on all middleware in order.\n * Called at the start of each agent loop iteration.\n */\n async runOnIteration(\n ctx: ChatMiddlewareContext,\n info: IterationInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onIteration) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onIteration(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onIteration',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onToolPhaseComplete on all middleware in order.\n * Called after all tool calls in an iteration have been processed.\n */\n async runOnToolPhaseComplete(\n ctx: ChatMiddlewareContext,\n info: ToolPhaseCompleteInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onToolPhaseComplete) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onToolPhaseComplete(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onToolPhaseComplete',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"compose.js","sources":["../../../../../src/activities/chat/middleware/compose.ts"],"sourcesContent":["import { aiEventClient } from '@tanstack/ai-event-client'\nimport type { StreamChunk } from '../../../types'\nimport type {\n AbortInfo,\n AfterToolCallInfo,\n BeforeToolCallDecision,\n ChatMiddleware,\n ChatMiddlewareConfig,\n ChatMiddlewareContext,\n ErrorInfo,\n FinishInfo,\n IterationInfo,\n ToolCallHookContext,\n ToolPhaseCompleteInfo,\n UsageInfo,\n} from './types'\n\n/** Check if a middleware should be skipped for instrumentation events. */\nfunction shouldSkipInstrumentation(mw: ChatMiddleware): boolean {\n return mw.name === 'devtools' || mw.name === 'strip-to-spec'\n}\n\n/** Build the base context for middleware instrumentation events. */\nfunction instrumentCtx(ctx: ChatMiddlewareContext) {\n return {\n requestId: ctx.requestId,\n streamId: ctx.streamId,\n clientId: ctx.conversationId,\n timestamp: Date.now(),\n }\n}\n\n/**\n * Internal middleware runner that manages composed execution of middleware hooks.\n * Created once per chat() invocation.\n */\nexport class MiddlewareRunner {\n private readonly middlewares: ReadonlyArray<ChatMiddleware>\n\n constructor(middlewares: ReadonlyArray<ChatMiddleware>) {\n this.middlewares = middlewares\n }\n\n get hasMiddleware(): boolean {\n return this.middlewares.length > 0\n }\n\n /**\n * Pipe config through all middleware onConfig hooks in order.\n * Each middleware receives the merged config from previous middleware.\n * Partial returns are shallow-merged with the current config.\n */\n async runOnConfig(\n ctx: ChatMiddlewareContext,\n config: ChatMiddlewareConfig,\n ): Promise<ChatMiddlewareConfig> {\n let current = config\n for (const mw of this.middlewares) {\n if (mw.onConfig) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n const result = await mw.onConfig(ctx, current)\n const hasTransform = result !== undefined && result !== null\n if (hasTransform) {\n current = { ...current, ...result }\n }\n if (!skip) {\n const base = instrumentCtx(ctx)\n aiEventClient.emit('middleware:hook:executed', {\n ...base,\n middlewareName: mw.name || 'unnamed',\n hookName: 'onConfig',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform,\n })\n if (hasTransform) {\n aiEventClient.emit('middleware:config:transformed', {\n ...base,\n middlewareName: mw.name || 'unnamed',\n iteration: ctx.iteration,\n changes: result as Record<string, unknown>,\n })\n }\n }\n }\n }\n return current\n }\n\n /**\n * Call onStart on all middleware in order.\n */\n async runOnStart(ctx: ChatMiddlewareContext): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onStart) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onStart(ctx)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onStart',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Pipe a single chunk through all middleware onChunk hooks in order.\n * Returns the resulting chunks (0..N) to yield to the consumer.\n *\n * - void: pass through unchanged\n * - chunk: replace with this chunk\n * - chunk[]: expand to multiple chunks\n * - null: drop the chunk entirely\n */\n async runOnChunk(\n ctx: ChatMiddlewareContext,\n chunk: StreamChunk,\n ): Promise<Array<StreamChunk>> {\n let chunks: Array<StreamChunk> = [chunk]\n\n for (const mw of this.middlewares) {\n if (!mw.onChunk) continue\n const skip = shouldSkipInstrumentation(mw)\n\n const nextChunks: Array<StreamChunk> = []\n for (const c of chunks) {\n // Cast: @ag-ui/core Zod passthrough types prevent direct `.type` access\n const chunkType = (c as StreamChunk & { type: string }).type\n const result = await mw.onChunk(ctx, c)\n if (result === null) {\n // Drop this chunk\n if (!skip) {\n aiEventClient.emit('middleware:chunk:transformed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n originalChunkType: chunkType,\n resultCount: 0,\n wasDropped: true,\n })\n }\n continue\n } else if (result === undefined) {\n // Pass through — no instrumentation for pass-throughs\n nextChunks.push(c)\n } else if (Array.isArray(result)) {\n // Expand\n nextChunks.push(...result)\n if (!skip) {\n aiEventClient.emit('middleware:chunk:transformed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n originalChunkType: chunkType,\n resultCount: result.length,\n wasDropped: false,\n })\n }\n } else {\n // Replace\n nextChunks.push(result)\n if (!skip) {\n aiEventClient.emit('middleware:chunk:transformed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n originalChunkType: chunkType,\n resultCount: 1,\n wasDropped: false,\n })\n }\n }\n }\n chunks = nextChunks\n }\n\n return chunks\n }\n\n /**\n * Run onBeforeToolCall through middleware in order.\n * Returns the first non-void decision, or undefined to continue normally.\n */\n async runOnBeforeToolCall(\n ctx: ChatMiddlewareContext,\n hookCtx: ToolCallHookContext,\n ): Promise<BeforeToolCallDecision> {\n for (const mw of this.middlewares) {\n if (mw.onBeforeToolCall) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n const decision = await mw.onBeforeToolCall(ctx, hookCtx)\n const hasTransform = decision !== undefined && decision !== null\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onBeforeToolCall',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform,\n })\n }\n if (hasTransform) {\n return decision\n }\n }\n }\n return undefined\n }\n\n /**\n * Run onAfterToolCall on all middleware in order.\n */\n async runOnAfterToolCall(\n ctx: ChatMiddlewareContext,\n info: AfterToolCallInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onAfterToolCall) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onAfterToolCall(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onAfterToolCall',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onUsage on all middleware in order.\n */\n async runOnUsage(\n ctx: ChatMiddlewareContext,\n usage: UsageInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onUsage) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onUsage(ctx, usage)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onUsage',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onFinish on all middleware in order.\n */\n async runOnFinish(\n ctx: ChatMiddlewareContext,\n info: FinishInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onFinish) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onFinish(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onFinish',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onAbort on all middleware in order.\n */\n async runOnAbort(ctx: ChatMiddlewareContext, info: AbortInfo): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onAbort) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onAbort(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onAbort',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onError on all middleware in order.\n */\n async runOnError(ctx: ChatMiddlewareContext, info: ErrorInfo): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onError) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onError(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onError',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onIteration on all middleware in order.\n * Called at the start of each agent loop iteration.\n */\n async runOnIteration(\n ctx: ChatMiddlewareContext,\n info: IterationInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onIteration) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onIteration(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onIteration',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n\n /**\n * Run onToolPhaseComplete on all middleware in order.\n * Called after all tool calls in an iteration have been processed.\n */\n async runOnToolPhaseComplete(\n ctx: ChatMiddlewareContext,\n info: ToolPhaseCompleteInfo,\n ): Promise<void> {\n for (const mw of this.middlewares) {\n if (mw.onToolPhaseComplete) {\n const skip = shouldSkipInstrumentation(mw)\n const start = Date.now()\n await mw.onToolPhaseComplete(ctx, info)\n if (!skip) {\n aiEventClient.emit('middleware:hook:executed', {\n ...instrumentCtx(ctx),\n middlewareName: mw.name || 'unnamed',\n hookName: 'onToolPhaseComplete',\n iteration: ctx.iteration,\n duration: Date.now() - start,\n hasTransform: false,\n })\n }\n }\n }\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -159,7 +159,7 @@ export declare class StreamProcessor {
|
|
|
159
159
|
*
|
|
160
160
|
* Central dispatch for all AG-UI events. Each event type maps to a specific
|
|
161
161
|
* handler. Events not listed in the switch are intentionally ignored
|
|
162
|
-
* (
|
|
162
|
+
* (STEP_STARTED, STATE_SNAPSHOT, STATE_DELTA).
|
|
163
163
|
*
|
|
164
164
|
* @see docs/chat-architecture.md#adapter-contract — Expected event types and ordering
|
|
165
165
|
*/
|
|
@@ -253,6 +253,14 @@ export declare class StreamProcessor {
|
|
|
253
253
|
* @see docs/chat-architecture.md#single-shot-tool-call-response — End-to-end flow
|
|
254
254
|
*/
|
|
255
255
|
private handleToolCallEndEvent;
|
|
256
|
+
/**
|
|
257
|
+
* Handle TOOL_CALL_RESULT event (AG-UI spec).
|
|
258
|
+
*
|
|
259
|
+
* Creates a tool-result part and updates the tool-call output field,
|
|
260
|
+
* mirroring the logic from TOOL_CALL_END when it carries a result.
|
|
261
|
+
* This is the spec-compliant path for delivering tool results to the client.
|
|
262
|
+
*/
|
|
263
|
+
private handleToolCallResultEvent;
|
|
256
264
|
/**
|
|
257
265
|
* Handle RUN_STARTED event.
|
|
258
266
|
*
|
|
@@ -284,6 +292,13 @@ export declare class StreamProcessor {
|
|
|
284
292
|
* @see docs/chat-architecture.md#thinkingreasoning-content — Thinking flow
|
|
285
293
|
*/
|
|
286
294
|
private handleStepFinishedEvent;
|
|
295
|
+
/**
|
|
296
|
+
* Handle REASONING_MESSAGE_CONTENT event (AG-UI reasoning protocol).
|
|
297
|
+
*
|
|
298
|
+
* Accumulates reasoning delta into thinkingContent and updates the ThinkingPart
|
|
299
|
+
* in the UIMessage.
|
|
300
|
+
*/
|
|
301
|
+
private handleReasoningMessageContentEvent;
|
|
287
302
|
/**
|
|
288
303
|
* Handle CUSTOM event.
|
|
289
304
|
*
|
|
@@ -229,7 +229,7 @@ class StreamProcessor {
|
|
|
229
229
|
*
|
|
230
230
|
* Central dispatch for all AG-UI events. Each event type maps to a specific
|
|
231
231
|
* handler. Events not listed in the switch are intentionally ignored
|
|
232
|
-
* (
|
|
232
|
+
* (STEP_STARTED, STATE_SNAPSHOT, STATE_DELTA).
|
|
233
233
|
*
|
|
234
234
|
* @see docs/chat-architecture.md#adapter-contract — Expected event types and ordering
|
|
235
235
|
*/
|
|
@@ -241,43 +241,83 @@ class StreamProcessor {
|
|
|
241
241
|
index: this.recording.chunks.length
|
|
242
242
|
});
|
|
243
243
|
}
|
|
244
|
-
|
|
244
|
+
const c = chunk;
|
|
245
|
+
switch (c.type) {
|
|
245
246
|
// AG-UI Events
|
|
246
247
|
case "TEXT_MESSAGE_START":
|
|
247
|
-
this.handleTextMessageStartEvent(
|
|
248
|
+
this.handleTextMessageStartEvent(
|
|
249
|
+
chunk
|
|
250
|
+
);
|
|
248
251
|
break;
|
|
249
252
|
case "TEXT_MESSAGE_CONTENT":
|
|
250
|
-
this.handleTextMessageContentEvent(
|
|
253
|
+
this.handleTextMessageContentEvent(
|
|
254
|
+
chunk
|
|
255
|
+
);
|
|
251
256
|
break;
|
|
252
257
|
case "TEXT_MESSAGE_END":
|
|
253
|
-
this.handleTextMessageEndEvent(
|
|
258
|
+
this.handleTextMessageEndEvent(
|
|
259
|
+
chunk
|
|
260
|
+
);
|
|
254
261
|
break;
|
|
255
262
|
case "TOOL_CALL_START":
|
|
256
|
-
this.handleToolCallStartEvent(
|
|
263
|
+
this.handleToolCallStartEvent(
|
|
264
|
+
chunk
|
|
265
|
+
);
|
|
257
266
|
break;
|
|
258
267
|
case "TOOL_CALL_ARGS":
|
|
259
|
-
this.handleToolCallArgsEvent(
|
|
268
|
+
this.handleToolCallArgsEvent(
|
|
269
|
+
chunk
|
|
270
|
+
);
|
|
260
271
|
break;
|
|
261
272
|
case "TOOL_CALL_END":
|
|
262
|
-
this.handleToolCallEndEvent(
|
|
273
|
+
this.handleToolCallEndEvent(
|
|
274
|
+
chunk
|
|
275
|
+
);
|
|
263
276
|
break;
|
|
264
277
|
case "RUN_FINISHED":
|
|
265
|
-
this.handleRunFinishedEvent(
|
|
278
|
+
this.handleRunFinishedEvent(
|
|
279
|
+
chunk
|
|
280
|
+
);
|
|
266
281
|
break;
|
|
267
282
|
case "RUN_ERROR":
|
|
268
|
-
this.handleRunErrorEvent(
|
|
283
|
+
this.handleRunErrorEvent(
|
|
284
|
+
chunk
|
|
285
|
+
);
|
|
269
286
|
break;
|
|
270
287
|
case "STEP_FINISHED":
|
|
271
|
-
this.handleStepFinishedEvent(
|
|
288
|
+
this.handleStepFinishedEvent(
|
|
289
|
+
chunk
|
|
290
|
+
);
|
|
272
291
|
break;
|
|
273
292
|
case "MESSAGES_SNAPSHOT":
|
|
274
|
-
this.handleMessagesSnapshotEvent(
|
|
293
|
+
this.handleMessagesSnapshotEvent(
|
|
294
|
+
chunk
|
|
295
|
+
);
|
|
275
296
|
break;
|
|
276
297
|
case "CUSTOM":
|
|
277
|
-
this.handleCustomEvent(
|
|
298
|
+
this.handleCustomEvent(
|
|
299
|
+
chunk
|
|
300
|
+
);
|
|
278
301
|
break;
|
|
279
302
|
case "RUN_STARTED":
|
|
280
|
-
this.handleRunStartedEvent(
|
|
303
|
+
this.handleRunStartedEvent(
|
|
304
|
+
chunk
|
|
305
|
+
);
|
|
306
|
+
break;
|
|
307
|
+
case "REASONING_START":
|
|
308
|
+
case "REASONING_MESSAGE_START":
|
|
309
|
+
case "REASONING_MESSAGE_END":
|
|
310
|
+
case "REASONING_END":
|
|
311
|
+
break;
|
|
312
|
+
case "REASONING_MESSAGE_CONTENT":
|
|
313
|
+
this.handleReasoningMessageContentEvent(
|
|
314
|
+
chunk
|
|
315
|
+
);
|
|
316
|
+
break;
|
|
317
|
+
case "TOOL_CALL_RESULT":
|
|
318
|
+
this.handleToolCallResultEvent(
|
|
319
|
+
chunk
|
|
320
|
+
);
|
|
281
321
|
break;
|
|
282
322
|
}
|
|
283
323
|
}
|
|
@@ -295,6 +335,7 @@ class StreamProcessor {
|
|
|
295
335
|
currentSegmentText: "",
|
|
296
336
|
lastEmittedText: "",
|
|
297
337
|
thinkingContent: "",
|
|
338
|
+
hasSeenReasoningEvents: false,
|
|
298
339
|
toolCalls: /* @__PURE__ */ new Map(),
|
|
299
340
|
toolCallOrder: [],
|
|
300
341
|
hasToolCallsSinceTextStart: false,
|
|
@@ -380,7 +421,7 @@ class StreamProcessor {
|
|
|
380
421
|
*/
|
|
381
422
|
handleTextMessageStartEvent(chunk) {
|
|
382
423
|
const { messageId, role } = chunk;
|
|
383
|
-
const uiRole = role === "
|
|
424
|
+
const uiRole = role === "user" || role === "system" ? role : "assistant";
|
|
384
425
|
if (this.pendingManualMessageId) {
|
|
385
426
|
const pendingId = this.pendingManualMessageId;
|
|
386
427
|
this.pendingManualMessageId = null;
|
|
@@ -528,9 +569,10 @@ class StreamProcessor {
|
|
|
528
569
|
const existingToolCall = state.toolCalls.get(toolCallId);
|
|
529
570
|
if (!existingToolCall) {
|
|
530
571
|
const initialState = "awaiting-input";
|
|
572
|
+
const toolName = chunk.toolCallName;
|
|
531
573
|
const newToolCall = {
|
|
532
574
|
id: chunk.toolCallId,
|
|
533
|
-
name:
|
|
575
|
+
name: toolName,
|
|
534
576
|
arguments: "",
|
|
535
577
|
state: initialState,
|
|
536
578
|
parsedArguments: void 0,
|
|
@@ -541,7 +583,7 @@ class StreamProcessor {
|
|
|
541
583
|
this.toolCallToMessage.set(toolCallId, messageId);
|
|
542
584
|
this.messages = updateToolCallPart(this.messages, messageId, {
|
|
543
585
|
id: chunk.toolCallId,
|
|
544
|
-
name:
|
|
586
|
+
name: toolName,
|
|
545
587
|
arguments: "",
|
|
546
588
|
state: initialState
|
|
547
589
|
});
|
|
@@ -649,6 +691,37 @@ class StreamProcessor {
|
|
|
649
691
|
this.emitMessagesChange();
|
|
650
692
|
}
|
|
651
693
|
}
|
|
694
|
+
/**
|
|
695
|
+
* Handle TOOL_CALL_RESULT event (AG-UI spec).
|
|
696
|
+
*
|
|
697
|
+
* Creates a tool-result part and updates the tool-call output field,
|
|
698
|
+
* mirroring the logic from TOOL_CALL_END when it carries a result.
|
|
699
|
+
* This is the spec-compliant path for delivering tool results to the client.
|
|
700
|
+
*/
|
|
701
|
+
handleToolCallResultEvent(chunk) {
|
|
702
|
+
const messageId = this.toolCallToMessage.get(chunk.toolCallId);
|
|
703
|
+
if (!messageId) return;
|
|
704
|
+
let output;
|
|
705
|
+
try {
|
|
706
|
+
output = JSON.parse(chunk.content);
|
|
707
|
+
} catch {
|
|
708
|
+
output = chunk.content;
|
|
709
|
+
}
|
|
710
|
+
this.messages = updateToolCallWithOutput(
|
|
711
|
+
this.messages,
|
|
712
|
+
chunk.toolCallId,
|
|
713
|
+
output
|
|
714
|
+
);
|
|
715
|
+
const resultState = "complete";
|
|
716
|
+
this.messages = updateToolResultPart(
|
|
717
|
+
this.messages,
|
|
718
|
+
messageId,
|
|
719
|
+
chunk.toolCallId,
|
|
720
|
+
chunk.content,
|
|
721
|
+
resultState
|
|
722
|
+
);
|
|
723
|
+
this.emitMessagesChange();
|
|
724
|
+
}
|
|
652
725
|
/**
|
|
653
726
|
* Handle RUN_STARTED event.
|
|
654
727
|
*
|
|
@@ -669,7 +742,7 @@ class StreamProcessor {
|
|
|
669
742
|
* @see docs/chat-architecture.md#adapter-contract — Why RUN_FINISHED is mandatory
|
|
670
743
|
*/
|
|
671
744
|
handleRunFinishedEvent(chunk) {
|
|
672
|
-
this.finishReason = chunk.finishReason;
|
|
745
|
+
this.finishReason = chunk.finishReason ?? null;
|
|
673
746
|
this.activeRuns.delete(chunk.runId);
|
|
674
747
|
if (this.activeRuns.size === 0) {
|
|
675
748
|
this.isDone = true;
|
|
@@ -682,13 +755,15 @@ class StreamProcessor {
|
|
|
682
755
|
*/
|
|
683
756
|
handleRunErrorEvent(chunk) {
|
|
684
757
|
this.hasError = true;
|
|
685
|
-
|
|
686
|
-
|
|
758
|
+
const runId = chunk.runId;
|
|
759
|
+
if (runId) {
|
|
760
|
+
this.activeRuns.delete(runId);
|
|
687
761
|
} else {
|
|
688
762
|
this.activeRuns.clear();
|
|
689
763
|
}
|
|
690
764
|
this.ensureAssistantMessage();
|
|
691
|
-
|
|
765
|
+
const errorMessage = chunk.message || chunk.error?.message || "An error occurred";
|
|
766
|
+
this.events.onError?.(new Error(errorMessage));
|
|
692
767
|
}
|
|
693
768
|
/**
|
|
694
769
|
* Handle STEP_FINISHED event (for thinking/reasoning content).
|
|
@@ -702,6 +777,9 @@ class StreamProcessor {
|
|
|
702
777
|
const { messageId, state } = this.ensureAssistantMessage(
|
|
703
778
|
this.getActiveAssistantMessageId() ?? void 0
|
|
704
779
|
);
|
|
780
|
+
if (state.hasSeenReasoningEvents) {
|
|
781
|
+
return;
|
|
782
|
+
}
|
|
705
783
|
const previous = state.thinkingContent;
|
|
706
784
|
let nextThinking = previous;
|
|
707
785
|
if (chunk.delta && chunk.delta !== "") {
|
|
@@ -724,6 +802,27 @@ class StreamProcessor {
|
|
|
724
802
|
this.emitMessagesChange();
|
|
725
803
|
this.events.onThinkingUpdate?.(messageId, state.thinkingContent);
|
|
726
804
|
}
|
|
805
|
+
/**
|
|
806
|
+
* Handle REASONING_MESSAGE_CONTENT event (AG-UI reasoning protocol).
|
|
807
|
+
*
|
|
808
|
+
* Accumulates reasoning delta into thinkingContent and updates the ThinkingPart
|
|
809
|
+
* in the UIMessage.
|
|
810
|
+
*/
|
|
811
|
+
handleReasoningMessageContentEvent(chunk) {
|
|
812
|
+
const { messageId, state } = this.ensureAssistantMessage(
|
|
813
|
+
this.getActiveAssistantMessageId() ?? void 0
|
|
814
|
+
);
|
|
815
|
+
state.hasSeenReasoningEvents = true;
|
|
816
|
+
const delta = chunk.delta || "";
|
|
817
|
+
state.thinkingContent = state.thinkingContent + delta;
|
|
818
|
+
this.messages = updateThinkingPart(
|
|
819
|
+
this.messages,
|
|
820
|
+
messageId,
|
|
821
|
+
state.thinkingContent
|
|
822
|
+
);
|
|
823
|
+
this.emitMessagesChange();
|
|
824
|
+
this.events.onThinkingUpdate?.(messageId, state.thinkingContent);
|
|
825
|
+
}
|
|
727
826
|
/**
|
|
728
827
|
* Handle CUSTOM event.
|
|
729
828
|
*
|