@tanstack/ai 0.36.0 → 0.37.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/adapter.d.ts +163 -0
- package/dist/esm/activities/chat/adapter.js +17 -0
- package/dist/esm/activities/chat/adapter.js.map +1 -0
- package/dist/esm/activities/chat/agent-loop-strategies.d.ts +59 -0
- package/dist/esm/activities/chat/agent-loop-strategies.js +23 -0
- package/dist/esm/activities/chat/agent-loop-strategies.js.map +1 -0
- package/dist/esm/activities/chat/index.d.ts +270 -0
- package/dist/esm/activities/chat/index.js +1724 -0
- package/dist/esm/activities/chat/index.js.map +1 -0
- package/dist/esm/activities/chat/mcp/manager.d.ts +25 -0
- package/dist/esm/activities/chat/mcp/manager.js +71 -0
- package/dist/esm/activities/chat/mcp/manager.js.map +1 -0
- package/dist/esm/activities/chat/mcp/types.d.ts +56 -0
- package/dist/esm/activities/chat/messages.d.ts +78 -0
- package/dist/esm/activities/chat/messages.js +374 -0
- package/dist/esm/activities/chat/messages.js.map +1 -0
- package/dist/esm/activities/chat/middleware/builder.d.ts +46 -0
- package/dist/esm/activities/chat/middleware/builder.js +17 -0
- package/dist/esm/activities/chat/middleware/builder.js.map +1 -0
- package/dist/esm/activities/chat/middleware/capabilities.d.ts +93 -0
- package/dist/esm/activities/chat/middleware/capabilities.js +45 -0
- package/dist/esm/activities/chat/middleware/capabilities.js.map +1 -0
- package/dist/esm/activities/chat/middleware/compose.d.ts +87 -0
- package/dist/esm/activities/chat/middleware/compose.js +510 -0
- package/dist/esm/activities/chat/middleware/compose.js.map +1 -0
- package/dist/esm/activities/chat/middleware/define.d.ts +20 -0
- package/dist/esm/activities/chat/middleware/define.js +7 -0
- package/dist/esm/activities/chat/middleware/define.js.map +1 -0
- package/dist/esm/activities/chat/middleware/index.d.ts +10 -0
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.d.ts +89 -0
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js +76 -0
- package/dist/esm/activities/chat/middleware/tool-cache-middleware.js.map +1 -0
- package/dist/esm/activities/chat/middleware/types.d.ts +405 -0
- package/dist/esm/activities/chat/middleware/validate.d.ts +19 -0
- package/dist/esm/activities/chat/middleware/validate.js +30 -0
- package/dist/esm/activities/chat/middleware/validate.js.map +1 -0
- package/dist/esm/activities/chat/runtime-context-types.d.ts +43 -0
- package/dist/esm/activities/chat/stream/index.d.ts +11 -0
- package/dist/esm/activities/chat/stream/json-parser.d.ts +38 -0
- package/dist/esm/activities/chat/stream/json-parser.js +28 -0
- package/dist/esm/activities/chat/stream/json-parser.js.map +1 -0
- package/dist/esm/activities/chat/stream/message-updaters.d.ts +81 -0
- package/dist/esm/activities/chat/stream/message-updaters.js +253 -0
- package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -0
- package/dist/esm/activities/chat/stream/processor.d.ts +439 -0
- package/dist/esm/activities/chat/stream/processor.js +1426 -0
- package/dist/esm/activities/chat/stream/processor.js.map +1 -0
- package/dist/esm/activities/chat/stream/strategies.d.ts +43 -0
- package/dist/esm/activities/chat/stream/strategies.js +54 -0
- package/dist/esm/activities/chat/stream/strategies.js.map +1 -0
- package/dist/esm/activities/chat/stream/types.d.ts +90 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.d.ts +82 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js +194 -0
- package/dist/esm/activities/chat/tools/lazy-tool-manager.js.map +1 -0
- package/dist/esm/activities/chat/tools/lazy-tools.d.ts +15 -0
- package/dist/esm/activities/chat/tools/lazy-tools.js +16 -0
- package/dist/esm/activities/chat/tools/lazy-tools.js.map +1 -0
- package/dist/esm/activities/chat/tools/schema-converter.d.ts +140 -0
- package/dist/esm/activities/chat/tools/schema-converter.js +167 -0
- package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -0
- package/dist/esm/activities/chat/tools/tool-calls.d.ts +140 -0
- package/dist/esm/activities/chat/tools/tool-calls.js +512 -0
- package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -0
- package/dist/esm/activities/chat/tools/tool-definition.d.ts +135 -0
- package/dist/esm/activities/chat/tools/tool-definition.js +25 -0
- package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -0
- package/dist/esm/activities/error-payload.d.ts +30 -0
- package/dist/esm/activities/error-payload.js +54 -0
- package/dist/esm/activities/error-payload.js.map +1 -0
- package/dist/esm/activities/generateAudio/adapter.d.ts +62 -0
- package/dist/esm/activities/generateAudio/adapter.js +16 -0
- package/dist/esm/activities/generateAudio/adapter.js.map +1 -0
- package/dist/esm/activities/generateAudio/index.d.ts +85 -0
- package/dist/esm/activities/generateAudio/index.js +114 -0
- package/dist/esm/activities/generateAudio/index.js.map +1 -0
- package/dist/esm/activities/generateImage/adapter.d.ts +78 -0
- package/dist/esm/activities/generateImage/adapter.js +16 -0
- package/dist/esm/activities/generateImage/adapter.js.map +1 -0
- package/dist/esm/activities/generateImage/index.d.ts +134 -0
- package/dist/esm/activities/generateImage/index.js +121 -0
- package/dist/esm/activities/generateImage/index.js.map +1 -0
- package/dist/esm/activities/generateSpeech/adapter.d.ts +62 -0
- package/dist/esm/activities/generateSpeech/adapter.js +16 -0
- package/dist/esm/activities/generateSpeech/adapter.js.map +1 -0
- package/dist/esm/activities/generateSpeech/index.d.ts +96 -0
- package/dist/esm/activities/generateSpeech/index.js +119 -0
- package/dist/esm/activities/generateSpeech/index.js.map +1 -0
- package/dist/esm/activities/generateTranscription/adapter.d.ts +62 -0
- package/dist/esm/activities/generateTranscription/adapter.js +16 -0
- package/dist/esm/activities/generateTranscription/adapter.js.map +1 -0
- package/dist/esm/activities/generateTranscription/index.d.ts +109 -0
- package/dist/esm/activities/generateTranscription/index.js +109 -0
- package/dist/esm/activities/generateTranscription/index.js.map +1 -0
- package/dist/esm/activities/generateVideo/adapter.d.ts +145 -0
- package/dist/esm/activities/generateVideo/adapter.js +30 -0
- package/dist/esm/activities/generateVideo/adapter.js.map +1 -0
- package/dist/esm/activities/generateVideo/index.d.ts +223 -0
- package/dist/esm/activities/generateVideo/index.js +295 -0
- package/dist/esm/activities/generateVideo/index.js.map +1 -0
- package/dist/esm/activities/generateVideo/snap.d.ts +14 -0
- package/dist/esm/activities/generateVideo/snap.js +54 -0
- package/dist/esm/activities/generateVideo/snap.js.map +1 -0
- package/dist/esm/activities/index.d.ts +27 -0
- package/dist/esm/activities/index.js +43 -0
- package/dist/esm/activities/index.js.map +1 -0
- package/dist/esm/activities/middleware/index.d.ts +2 -0
- package/dist/esm/activities/middleware/run.d.ts +20 -0
- package/dist/esm/activities/middleware/run.js +42 -0
- package/dist/esm/activities/middleware/run.js.map +1 -0
- package/dist/esm/activities/middleware/types.d.ts +118 -0
- package/dist/esm/activities/stream-generation-result.d.ts +15 -0
- package/dist/esm/activities/stream-generation-result.js +49 -0
- package/dist/esm/activities/stream-generation-result.js.map +1 -0
- package/dist/esm/activities/summarize/adapter.d.ts +74 -0
- package/dist/esm/activities/summarize/adapter.js +16 -0
- package/dist/esm/activities/summarize/adapter.js.map +1 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +45 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js +212 -0
- package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -0
- package/dist/esm/activities/summarize/index.d.ts +108 -0
- package/dist/esm/activities/summarize/index.js +113 -0
- package/dist/esm/activities/summarize/index.js.map +1 -0
- package/dist/esm/adapter-internals.d.ts +5 -0
- package/dist/esm/adapter-internals.js +10 -0
- package/dist/esm/adapter-internals.js.map +1 -0
- package/dist/esm/client.d.ts +44 -0
- package/dist/esm/client.js +67 -0
- package/dist/esm/client.js.map +1 -0
- package/dist/esm/extend-adapter.d.ts +152 -0
- package/dist/esm/extend-adapter.js +21 -0
- package/dist/esm/extend-adapter.js.map +1 -0
- package/dist/esm/index.d.ts +45 -0
- package/dist/esm/index.js +109 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/logger/console-logger.d.ts +29 -0
- package/dist/esm/logger/console-logger.js +83 -0
- package/dist/esm/logger/console-logger.js.map +1 -0
- package/dist/esm/logger/internal-logger.d.ts +41 -0
- package/dist/esm/logger/internal-logger.js +86 -0
- package/dist/esm/logger/internal-logger.js.map +1 -0
- package/dist/esm/logger/resolve.d.ts +14 -0
- package/dist/esm/logger/resolve.js +54 -0
- package/dist/esm/logger/resolve.js.map +1 -0
- package/dist/esm/logger/types.d.ts +75 -0
- package/dist/esm/middlewares/content-guard.d.ts +77 -0
- package/dist/esm/middlewares/content-guard.js +156 -0
- package/dist/esm/middlewares/content-guard.js.map +1 -0
- package/dist/esm/middlewares/index.d.ts +2 -0
- package/dist/esm/middlewares/index.js +7 -0
- package/dist/esm/middlewares/index.js.map +1 -0
- package/dist/esm/middlewares/otel.d.ts +81 -0
- package/dist/esm/middlewares/otel.js +745 -0
- package/dist/esm/middlewares/otel.js.map +1 -0
- package/dist/esm/middlewares/tool-cache.d.ts +1 -0
- package/dist/esm/middlewares/usage-attributes.d.ts +24 -0
- package/dist/esm/middlewares/usage-attributes.js +43 -0
- package/dist/esm/middlewares/usage-attributes.js.map +1 -0
- package/dist/esm/realtime/index.d.ts +28 -0
- package/dist/esm/realtime/index.js +8 -0
- package/dist/esm/realtime/index.js.map +1 -0
- package/dist/esm/realtime/types.d.ts +282 -0
- package/dist/esm/stream-to-response.d.ts +102 -0
- package/dist/esm/stream-to-response.js +121 -0
- package/dist/esm/stream-to-response.js.map +1 -0
- 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/system-prompts.d.ts +66 -0
- package/dist/esm/system-prompts.js +23 -0
- package/dist/esm/system-prompts.js.map +1 -0
- package/dist/esm/tool-registry.d.ts +81 -0
- package/dist/esm/tool-registry.js +49 -0
- package/dist/esm/tool-registry.js.map +1 -0
- package/dist/esm/tools/provider-tool.d.ts +30 -0
- package/dist/esm/tools/provider-tool.js +7 -0
- package/dist/esm/tools/provider-tool.js.map +1 -0
- package/dist/esm/types.d.ts +1594 -0
- package/dist/esm/utilities/ag-ui-wire.d.ts +44 -0
- package/dist/esm/utilities/ag-ui-wire.js +107 -0
- package/dist/esm/utilities/ag-ui-wire.js.map +1 -0
- package/dist/esm/utilities/chat-params.d.ts +85 -0
- package/dist/esm/utilities/chat-params.js +100 -0
- package/dist/esm/utilities/chat-params.js.map +1 -0
- package/dist/esm/utilities/errors.d.ts +13 -0
- package/dist/esm/utilities/errors.js +22 -0
- package/dist/esm/utilities/errors.js.map +1 -0
- package/dist/esm/utilities/media-prompt.d.ts +35 -0
- package/dist/esm/utilities/media-prompt.js +43 -0
- package/dist/esm/utilities/media-prompt.js.map +1 -0
- package/dist/esm/utilities/numbers.d.ts +8 -0
- package/dist/esm/utilities/numbers.js +12 -0
- package/dist/esm/utilities/numbers.js.map +1 -0
- package/dist/esm/utilities/sampling-keys.d.ts +20 -0
- package/dist/esm/utilities/sampling-keys.js +20 -0
- package/dist/esm/utilities/sampling-keys.js.map +1 -0
- package/dist/esm/utilities/tool-result.d.ts +21 -0
- package/dist/esm/utilities/tool-result.js +37 -0
- package/dist/esm/utilities/tool-result.js.map +1 -0
- package/dist/esm/utilities/usage.d.ts +31 -0
- package/dist/esm/utilities/usage.js +11 -0
- package/dist/esm/utilities/usage.js.map +1 -0
- package/dist/esm/utils.d.ts +17 -0
- package/dist/esm/utils.js +20 -0
- package/dist/esm/utils.js.map +1 -0
- package/package.json +3 -3
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
function validateCapabilities(middlewares, adapter) {
|
|
2
|
+
const provided = /* @__PURE__ */ new Set();
|
|
3
|
+
for (const mw of middlewares) {
|
|
4
|
+
for (const handle of mw.provides ?? []) provided.add(handle);
|
|
5
|
+
}
|
|
6
|
+
const providedNames = () => {
|
|
7
|
+
const names = [...provided].map((h) => h.capabilityName);
|
|
8
|
+
return names.length ? names.join(", ") : "none";
|
|
9
|
+
};
|
|
10
|
+
for (const handle of adapter.requires ?? []) {
|
|
11
|
+
if (!provided.has(handle)) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
`Adapter "${adapter.name}" requires capability "${handle.capabilityName}". Provided capabilities: ${providedNames()}. Add a middleware that provides "${handle.capabilityName}".`
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
for (const mw of middlewares) {
|
|
18
|
+
for (const handle of mw.requires ?? []) {
|
|
19
|
+
if (!provided.has(handle)) {
|
|
20
|
+
throw new Error(
|
|
21
|
+
`Middleware "${mw.name ?? "unnamed"}" requires capability "${handle.capabilityName}". Provided capabilities: ${providedNames()}. Add a middleware that provides "${handle.capabilityName}".`
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
validateCapabilities
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sources":["../../../../../src/activities/chat/middleware/validate.ts"],"sourcesContent":["import type { CapabilityHandle } from './capabilities'\nimport type { AnyChatMiddleware } from './types'\n\n/** Minimal adapter shape needed for capability validation. */\ninterface CapabilityRequiringAdapter {\n name: string\n requires?: ReadonlyArray<CapabilityHandle>\n}\n\n/**\n * Runtime validation: every required capability (from middleware `requires` and\n * the adapter's `requires`) must be provided by some middleware's `provides`.\n * `optionalRequires` is never gating. Throws a clear error otherwise.\n *\n * Presence only — ORDER is not validated here (a provider may appear after its\n * consumer in the array and still pass). Use the `createChatMiddleware()`\n * builder for compile-time order enforcement; at runtime, a consumer that reads\n * a not-yet-provided capability during `setup` fails loud via its getter.\n */\nexport function validateCapabilities(\n middlewares: ReadonlyArray<AnyChatMiddleware>,\n adapter: CapabilityRequiringAdapter,\n): void {\n const provided = new Set<CapabilityHandle>()\n for (const mw of middlewares) {\n for (const handle of mw.provides ?? []) provided.add(handle)\n }\n\n const providedNames = (): string => {\n const names = [...provided].map((h) => h.capabilityName)\n return names.length ? names.join(', ') : 'none'\n }\n\n for (const handle of adapter.requires ?? []) {\n if (!provided.has(handle)) {\n throw new Error(\n `Adapter \"${adapter.name}\" requires capability \"${handle.capabilityName}\". ` +\n `Provided capabilities: ${providedNames()}. ` +\n `Add a middleware that provides \"${handle.capabilityName}\".`,\n )\n }\n }\n\n for (const mw of middlewares) {\n for (const handle of mw.requires ?? []) {\n if (!provided.has(handle)) {\n throw new Error(\n `Middleware \"${mw.name ?? 'unnamed'}\" requires capability ` +\n `\"${handle.capabilityName}\". Provided capabilities: ${providedNames()}. ` +\n `Add a middleware that provides \"${handle.capabilityName}\".`,\n )\n }\n }\n }\n}\n"],"names":[],"mappings":"AAmBO,SAAS,qBACd,aACA,SACM;AACN,QAAM,+BAAe,IAAA;AACrB,aAAW,MAAM,aAAa;AAC5B,eAAW,UAAU,GAAG,YAAY,CAAA,EAAI,UAAS,IAAI,MAAM;AAAA,EAC7D;AAEA,QAAM,gBAAgB,MAAc;AAClC,UAAM,QAAQ,CAAC,GAAG,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,cAAc;AACvD,WAAO,MAAM,SAAS,MAAM,KAAK,IAAI,IAAI;AAAA,EAC3C;AAEA,aAAW,UAAU,QAAQ,YAAY,CAAA,GAAI;AAC3C,QAAI,CAAC,SAAS,IAAI,MAAM,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,YAAY,QAAQ,IAAI,0BAA0B,OAAO,cAAc,6BAC3C,cAAA,CAAe,qCACN,OAAO,cAAc;AAAA,MAAA;AAAA,IAE9D;AAAA,EACF;AAEA,aAAW,MAAM,aAAa;AAC5B,eAAW,UAAU,GAAG,YAAY,CAAA,GAAI;AACtC,UAAI,CAAC,SAAS,IAAI,MAAM,GAAG;AACzB,cAAM,IAAI;AAAA,UACR,eAAe,GAAG,QAAQ,SAAS,0BAC7B,OAAO,cAAc,6BAA6B,cAAA,CAAe,qCAClC,OAAO,cAAc;AAAA,QAAA;AAAA,MAE9D;AAAA,IACF;AAAA,EACF;AACF;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { ChatMiddleware } from './middleware/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Shared type-level helpers for inferring the runtime `context` requirement
|
|
4
|
+
* from typed tools and middleware.
|
|
5
|
+
*
|
|
6
|
+
* These primitives are consumed by both the chat activity options
|
|
7
|
+
* (`./index.ts`, which merges tool + middleware requirements) and the tool
|
|
8
|
+
* execution layer (`./tools/tool-calls.ts`, which only sees tools). They live
|
|
9
|
+
* here so the two call sites share one definition instead of maintaining
|
|
10
|
+
* divergent copies.
|
|
11
|
+
*/
|
|
12
|
+
/** True only when `T` is exactly `unknown`. */
|
|
13
|
+
type IsUnknown<T> = unknown extends T ? [T] extends [unknown] ? true : false : false;
|
|
14
|
+
/**
|
|
15
|
+
* Drops an `unknown` context requirement to `never` so that untyped tools and
|
|
16
|
+
* middleware (which default `TContext` to `unknown`) contribute no requirement
|
|
17
|
+
* to the merged context.
|
|
18
|
+
*/
|
|
19
|
+
type KnownContext<T> = IsUnknown<T> extends true ? never : T;
|
|
20
|
+
/**
|
|
21
|
+
* Merge two inferred context requirements, treating `never` as "no
|
|
22
|
+
* requirement". Using this instead of a raw intersection keeps a `never`
|
|
23
|
+
* (untyped) contributor from collapsing the whole merge to `never`.
|
|
24
|
+
*/
|
|
25
|
+
export type MergeContext<TLeft, TRight> = [TLeft] extends [never] ? TRight : [TRight] extends [never] ? TLeft : TLeft & TRight;
|
|
26
|
+
/** Collapse a union of context requirements into their intersection. */
|
|
27
|
+
export type UnionToIntersection<T> = [T] extends [never] ? never : (T extends unknown ? (value: T) => void : never) extends (value: infer TIntersection) => void ? TIntersection : never;
|
|
28
|
+
/** Strip `undefined` from a context requirement. */
|
|
29
|
+
export type DefinedContext<T> = Exclude<T, undefined>;
|
|
30
|
+
/**
|
|
31
|
+
* Extract the `context` requirement declared by a tool execute function's
|
|
32
|
+
* second argument, dropping `unknown` (untyped) contexts to `never`.
|
|
33
|
+
*/
|
|
34
|
+
type ContextFromExecute<T> = T extends (...args: any) => any ? NonNullable<Parameters<T>[1]> extends {
|
|
35
|
+
context: infer TUserContext;
|
|
36
|
+
} ? KnownContext<TUserContext> : never : never;
|
|
37
|
+
/** Extract the context requirement declared by a single tool. */
|
|
38
|
+
export type ContextFromTool<T> = T extends {
|
|
39
|
+
execute?: infer TExecute;
|
|
40
|
+
} ? ContextFromExecute<TExecute> : never;
|
|
41
|
+
/** Extract the context requirement declared by a single middleware. */
|
|
42
|
+
export type ContextFromMiddleware<T> = T extends ChatMiddleware<infer TContext> ? KnownContext<TContext> : never;
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream Processing Module
|
|
3
|
+
*
|
|
4
|
+
* Unified stream processing for both server and client.
|
|
5
|
+
*/
|
|
6
|
+
export { StreamProcessor, createReplayStream } from './processor.js';
|
|
7
|
+
export type { StreamProcessorEvents, StreamProcessorOptions } from './processor.js';
|
|
8
|
+
export { ImmediateStrategy, PunctuationStrategy, BatchStrategy, WordBoundaryStrategy, CompositeStrategy, } from './strategies.js';
|
|
9
|
+
export { PartialJSONParser, defaultJSONParser, parsePartialJSON, } from './json-parser.js';
|
|
10
|
+
export type { JSONParser } from './json-parser.js';
|
|
11
|
+
export type { ChunkStrategy, ChunkRecording, InternalToolCallState, ProcessorResult, ProcessorState, ToolCallState, ToolResultState, } from './types.js';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Parser for partial/incomplete JSON strings
|
|
3
|
+
*
|
|
4
|
+
* Used during streaming to parse tool call arguments that may be incomplete.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* JSON Parser interface - allows for custom parser implementations
|
|
8
|
+
*/
|
|
9
|
+
export interface JSONParser {
|
|
10
|
+
/**
|
|
11
|
+
* Parse a JSON string (may be incomplete/partial)
|
|
12
|
+
* @param jsonString - The JSON string to parse
|
|
13
|
+
* @returns The parsed object, or undefined if parsing fails
|
|
14
|
+
*/
|
|
15
|
+
parse: (jsonString: string) => any;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Partial JSON Parser implementation using the partial-json library
|
|
19
|
+
* This parser can handle incomplete JSON strings during streaming
|
|
20
|
+
*/
|
|
21
|
+
export declare class PartialJSONParser implements JSONParser {
|
|
22
|
+
/**
|
|
23
|
+
* Parse a potentially incomplete JSON string
|
|
24
|
+
* @param jsonString - The JSON string to parse (may be incomplete)
|
|
25
|
+
* @returns The parsed object, or undefined if parsing fails
|
|
26
|
+
*/
|
|
27
|
+
parse(jsonString: string): any;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Default parser instance
|
|
31
|
+
*/
|
|
32
|
+
export declare const defaultJSONParser: PartialJSONParser;
|
|
33
|
+
/**
|
|
34
|
+
* Parse partial JSON string (convenience function)
|
|
35
|
+
* @param jsonString - The JSON string to parse (may be incomplete)
|
|
36
|
+
* @returns The parsed object, or undefined if parsing fails
|
|
37
|
+
*/
|
|
38
|
+
export declare function parsePartialJSON(jsonString: string): any;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { parse } from "partial-json";
|
|
2
|
+
class PartialJSONParser {
|
|
3
|
+
/**
|
|
4
|
+
* Parse a potentially incomplete JSON string
|
|
5
|
+
* @param jsonString - The JSON string to parse (may be incomplete)
|
|
6
|
+
* @returns The parsed object, or undefined if parsing fails
|
|
7
|
+
*/
|
|
8
|
+
parse(jsonString) {
|
|
9
|
+
if (!jsonString || jsonString.trim() === "") {
|
|
10
|
+
return void 0;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
return parse(jsonString);
|
|
14
|
+
} catch {
|
|
15
|
+
return void 0;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const defaultJSONParser = new PartialJSONParser();
|
|
20
|
+
function parsePartialJSON(jsonString) {
|
|
21
|
+
return defaultJSONParser.parse(jsonString);
|
|
22
|
+
}
|
|
23
|
+
export {
|
|
24
|
+
PartialJSONParser,
|
|
25
|
+
defaultJSONParser,
|
|
26
|
+
parsePartialJSON
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=json-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-parser.js","sources":["../../../../../src/activities/chat/stream/json-parser.ts"],"sourcesContent":["/**\n * JSON Parser for partial/incomplete JSON strings\n *\n * Used during streaming to parse tool call arguments that may be incomplete.\n */\n\nimport { parse as parsePartialJSONLib } from 'partial-json'\n\n/**\n * JSON Parser interface - allows for custom parser implementations\n */\nexport interface JSONParser {\n /**\n * Parse a JSON string (may be incomplete/partial)\n * @param jsonString - The JSON string to parse\n * @returns The parsed object, or undefined if parsing fails\n */\n parse: (jsonString: string) => any\n}\n\n/**\n * Partial JSON Parser implementation using the partial-json library\n * This parser can handle incomplete JSON strings during streaming\n */\nexport class PartialJSONParser implements JSONParser {\n /**\n * Parse a potentially incomplete JSON string\n * @param jsonString - The JSON string to parse (may be incomplete)\n * @returns The parsed object, or undefined if parsing fails\n */\n parse(jsonString: string): any {\n if (!jsonString || jsonString.trim() === '') {\n return undefined\n }\n\n try {\n return parsePartialJSONLib(jsonString)\n } catch {\n // If partial parsing fails, return undefined\n // This is expected during early streaming when we have very little data\n return undefined\n }\n }\n}\n\n/**\n * Default parser instance\n */\nexport const defaultJSONParser = new PartialJSONParser()\n\n/**\n * Parse partial JSON string (convenience function)\n * @param jsonString - The JSON string to parse (may be incomplete)\n * @returns The parsed object, or undefined if parsing fails\n */\nexport function parsePartialJSON(jsonString: string): any {\n return defaultJSONParser.parse(jsonString)\n}\n"],"names":["parsePartialJSONLib"],"mappings":";AAwBO,MAAM,kBAAwC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMnD,MAAM,YAAyB;AAC7B,QAAI,CAAC,cAAc,WAAW,KAAA,MAAW,IAAI;AAC3C,aAAO;AAAA,IACT;AAEA,QAAI;AACF,aAAOA,MAAoB,UAAU;AAAA,IACvC,QAAQ;AAGN,aAAO;AAAA,IACT;AAAA,EACF;AACF;AAKO,MAAM,oBAAoB,IAAI,kBAAA;AAO9B,SAAS,iBAAiB,YAAyB;AACxD,SAAO,kBAAkB,MAAM,UAAU;AAC3C;"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ContentPart, UIMessage } from '../../../types.js';
|
|
2
|
+
import { ToolCallState, ToolResultState } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Update or add a text part to a message.
|
|
5
|
+
*
|
|
6
|
+
* If the last part is a text part, update it (continuing the same text segment).
|
|
7
|
+
* Otherwise, create a new text part (starting a new text segment after tool calls).
|
|
8
|
+
*/
|
|
9
|
+
export declare function updateTextPart(messages: Array<UIMessage>, messageId: string, content: string): Array<UIMessage>;
|
|
10
|
+
/**
|
|
11
|
+
* Update or add a tool call part to a message.
|
|
12
|
+
*/
|
|
13
|
+
export declare function updateToolCallPart(messages: Array<UIMessage>, messageId: string, toolCall: {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
arguments: string;
|
|
17
|
+
state: ToolCallState;
|
|
18
|
+
metadata?: Record<string, unknown>;
|
|
19
|
+
}): Array<UIMessage>;
|
|
20
|
+
/**
|
|
21
|
+
* Update or add a tool result part to a message.
|
|
22
|
+
*/
|
|
23
|
+
export declare function updateToolResultPart(messages: Array<UIMessage>, messageId: string, toolCallId: string, content: string | Array<ContentPart>, state: ToolResultState, error?: string): Array<UIMessage>;
|
|
24
|
+
/**
|
|
25
|
+
* Update a tool call part with approval request metadata.
|
|
26
|
+
*/
|
|
27
|
+
export declare function updateToolCallApproval(messages: Array<UIMessage>, messageId: string, toolCallId: string, approvalId: string): Array<UIMessage>;
|
|
28
|
+
/**
|
|
29
|
+
* Update a tool call part's state (e.g., to "input-complete").
|
|
30
|
+
*/
|
|
31
|
+
export declare function updateToolCallState(messages: Array<UIMessage>, messageId: string, toolCallId: string, state: ToolCallState): Array<UIMessage>;
|
|
32
|
+
/**
|
|
33
|
+
* Update a tool call part with output.
|
|
34
|
+
* Searches all messages to find the tool call by ID.
|
|
35
|
+
*/
|
|
36
|
+
export declare function updateToolCallWithOutput(messages: Array<UIMessage>, toolCallId: string, output: any, state?: ToolCallState, errorText?: string): Array<UIMessage>;
|
|
37
|
+
/**
|
|
38
|
+
* Update a tool call part with approval response.
|
|
39
|
+
* Searches all messages to find the tool call by approval ID.
|
|
40
|
+
*/
|
|
41
|
+
export declare function updateToolCallApprovalResponse(messages: Array<UIMessage>, approvalId: string, approved: boolean): Array<UIMessage>;
|
|
42
|
+
/**
|
|
43
|
+
* Append a delta to the structured-output part on `messageId`, or create one
|
|
44
|
+
* if absent. Progressive parse of the accumulated buffer fills `partial`.
|
|
45
|
+
*
|
|
46
|
+
* Callers must only invoke this while the part is still in flight — the
|
|
47
|
+
* helper unconditionally writes `status: 'streaming'`, so feeding it a delta
|
|
48
|
+
* after a `complete`/`error` terminal would regress the part. In practice the
|
|
49
|
+
* processor gates calls via `structuredMessageIds`, which is dropped on
|
|
50
|
+
* terminal events.
|
|
51
|
+
*
|
|
52
|
+
* If the progressive parse returns null/undefined (the buffer is not yet a
|
|
53
|
+
* parseable JSON prefix), the previously-good `partial` is preserved so the
|
|
54
|
+
* UI doesn't flicker back to empty for a single render.
|
|
55
|
+
*/
|
|
56
|
+
export declare function appendStructuredOutputDelta(messages: Array<UIMessage>, messageId: string, delta: string): Array<UIMessage>;
|
|
57
|
+
/**
|
|
58
|
+
* Snap the structured-output part on `messageId` to `complete` with the
|
|
59
|
+
* validated `data`. Picks the freshest available `raw` so the wire
|
|
60
|
+
* round-trip stays internally consistent:
|
|
61
|
+
*
|
|
62
|
+
* 1. Caller-supplied `raw` (the original streamed bytes from the model).
|
|
63
|
+
* 2. The existing part's `raw` (deltas accumulated before this terminal).
|
|
64
|
+
* 3. `JSON.stringify(data)` as a defensive fallback for terminal-only
|
|
65
|
+
* completes that never shipped raw — keeps the part self-consistent
|
|
66
|
+
* so downstream consumers never see a complete part with empty raw.
|
|
67
|
+
*/
|
|
68
|
+
export declare function completeStructuredOutputPart(messages: Array<UIMessage>, messageId: string, data: unknown, raw: string, reasoning?: string): Array<UIMessage>;
|
|
69
|
+
/**
|
|
70
|
+
* Mark the structured-output part on `messageId` as errored. If no part
|
|
71
|
+
* exists yet — RUN_ERROR fired after `structured-output.start` but before
|
|
72
|
+
* any delta — create an empty errored placeholder so consumers have
|
|
73
|
+
* something renderable. Existing complete parts are left alone (an error
|
|
74
|
+
* after a successful complete should not retroactively un-complete it).
|
|
75
|
+
*/
|
|
76
|
+
export declare function errorStructuredOutputPart(messages: Array<UIMessage>, messageId: string, errorMessage: string): Array<UIMessage>;
|
|
77
|
+
/**
|
|
78
|
+
* Update or add a thinking part to a message, keyed by stepId.
|
|
79
|
+
* Each distinct stepId produces its own ThinkingPart.
|
|
80
|
+
*/
|
|
81
|
+
export declare function updateThinkingPart(messages: Array<UIMessage>, messageId: string, stepId: string, content: string, signature?: string): Array<UIMessage>;
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { parsePartialJSON } from "./json-parser.js";
|
|
2
|
+
function updateTextPart(messages, messageId, content) {
|
|
3
|
+
return messages.map((msg) => {
|
|
4
|
+
if (msg.id !== messageId) {
|
|
5
|
+
return msg;
|
|
6
|
+
}
|
|
7
|
+
const parts = [...msg.parts];
|
|
8
|
+
const lastPart = parts.length > 0 ? parts[parts.length - 1] : null;
|
|
9
|
+
if (lastPart && lastPart.type === "text") {
|
|
10
|
+
parts[parts.length - 1] = { type: "text", content };
|
|
11
|
+
} else {
|
|
12
|
+
parts.push({ type: "text", content });
|
|
13
|
+
}
|
|
14
|
+
return { ...msg, parts };
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
function updateToolCallPart(messages, messageId, toolCall) {
|
|
18
|
+
return messages.map((msg) => {
|
|
19
|
+
if (msg.id !== messageId) {
|
|
20
|
+
return msg;
|
|
21
|
+
}
|
|
22
|
+
const parts = [...msg.parts];
|
|
23
|
+
const existing = parts.find(
|
|
24
|
+
(p) => p.type === "tool-call" && p.id === toolCall.id
|
|
25
|
+
);
|
|
26
|
+
const metadata = toolCall.metadata ?? existing?.metadata;
|
|
27
|
+
const toolCallPart = {
|
|
28
|
+
type: "tool-call",
|
|
29
|
+
id: toolCall.id,
|
|
30
|
+
name: toolCall.name,
|
|
31
|
+
arguments: toolCall.arguments,
|
|
32
|
+
state: toolCall.state,
|
|
33
|
+
// Carry forward approval and output from the existing part
|
|
34
|
+
...existing?.approval && { approval: { ...existing.approval } },
|
|
35
|
+
...existing?.output !== void 0 && { output: existing.output },
|
|
36
|
+
...metadata !== void 0 && { metadata }
|
|
37
|
+
};
|
|
38
|
+
if (existing) {
|
|
39
|
+
parts[parts.indexOf(existing)] = toolCallPart;
|
|
40
|
+
} else {
|
|
41
|
+
parts.push(toolCallPart);
|
|
42
|
+
}
|
|
43
|
+
return { ...msg, parts };
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
function updateToolResultPart(messages, messageId, toolCallId, content, state, error) {
|
|
47
|
+
return messages.map((msg) => {
|
|
48
|
+
if (msg.id !== messageId) {
|
|
49
|
+
return msg;
|
|
50
|
+
}
|
|
51
|
+
const parts = [...msg.parts];
|
|
52
|
+
const resultPartIndex = parts.findIndex(
|
|
53
|
+
(p) => p.type === "tool-result" && p.toolCallId === toolCallId
|
|
54
|
+
);
|
|
55
|
+
const toolResultPart = {
|
|
56
|
+
type: "tool-result",
|
|
57
|
+
toolCallId,
|
|
58
|
+
content,
|
|
59
|
+
state,
|
|
60
|
+
...error && { error }
|
|
61
|
+
};
|
|
62
|
+
if (resultPartIndex >= 0) {
|
|
63
|
+
parts[resultPartIndex] = toolResultPart;
|
|
64
|
+
} else {
|
|
65
|
+
parts.push(toolResultPart);
|
|
66
|
+
}
|
|
67
|
+
return { ...msg, parts };
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function updateToolCallApproval(messages, messageId, toolCallId, approvalId) {
|
|
71
|
+
return messages.map((msg) => {
|
|
72
|
+
if (msg.id !== messageId) {
|
|
73
|
+
return msg;
|
|
74
|
+
}
|
|
75
|
+
const parts = [...msg.parts];
|
|
76
|
+
const toolCallPart = parts.find(
|
|
77
|
+
(p) => p.type === "tool-call" && p.id === toolCallId
|
|
78
|
+
);
|
|
79
|
+
if (toolCallPart) {
|
|
80
|
+
const index = parts.indexOf(toolCallPart);
|
|
81
|
+
parts[index] = {
|
|
82
|
+
...toolCallPart,
|
|
83
|
+
state: "approval-requested",
|
|
84
|
+
approval: {
|
|
85
|
+
id: approvalId,
|
|
86
|
+
needsApproval: true
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
return { ...msg, parts };
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
function updateToolCallWithOutput(messages, toolCallId, output, state, errorText) {
|
|
94
|
+
return messages.map((msg) => {
|
|
95
|
+
const parts = [...msg.parts];
|
|
96
|
+
const toolCallPart = parts.find(
|
|
97
|
+
(p) => p.type === "tool-call" && p.id === toolCallId
|
|
98
|
+
);
|
|
99
|
+
if (toolCallPart) {
|
|
100
|
+
const index = parts.indexOf(toolCallPart);
|
|
101
|
+
parts[index] = {
|
|
102
|
+
...toolCallPart,
|
|
103
|
+
output: errorText ? { error: errorText } : output,
|
|
104
|
+
state: state ?? (errorText ? "error" : "complete")
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
return { ...msg, parts };
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
function updateToolCallApprovalResponse(messages, approvalId, approved) {
|
|
111
|
+
return messages.map((msg) => {
|
|
112
|
+
const parts = [...msg.parts];
|
|
113
|
+
const toolCallPart = parts.find(
|
|
114
|
+
(p) => p.type === "tool-call" && p.approval?.id === approvalId
|
|
115
|
+
);
|
|
116
|
+
if (toolCallPart && toolCallPart.approval) {
|
|
117
|
+
const index = parts.indexOf(toolCallPart);
|
|
118
|
+
parts[index] = {
|
|
119
|
+
...toolCallPart,
|
|
120
|
+
approval: { ...toolCallPart.approval, approved },
|
|
121
|
+
state: "approval-responded"
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return { ...msg, parts };
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
function appendStructuredOutputDelta(messages, messageId, delta) {
|
|
128
|
+
return messages.map((msg) => {
|
|
129
|
+
if (msg.id !== messageId) {
|
|
130
|
+
return msg;
|
|
131
|
+
}
|
|
132
|
+
const parts = [...msg.parts];
|
|
133
|
+
const existingIndex = parts.findIndex(
|
|
134
|
+
(p) => p.type === "structured-output"
|
|
135
|
+
);
|
|
136
|
+
const existing = existingIndex >= 0 ? parts[existingIndex] : null;
|
|
137
|
+
const nextRaw = (existing?.raw ?? "") + delta;
|
|
138
|
+
const progressive = parsePartialJSON(nextRaw);
|
|
139
|
+
const nextPartial = progressive !== void 0 && progressive !== null ? progressive : existing?.partial;
|
|
140
|
+
const nextPart = {
|
|
141
|
+
type: "structured-output",
|
|
142
|
+
status: "streaming",
|
|
143
|
+
raw: nextRaw,
|
|
144
|
+
...nextPartial !== void 0 ? { partial: nextPartial } : {},
|
|
145
|
+
...existing?.reasoning !== void 0 ? { reasoning: existing.reasoning } : {}
|
|
146
|
+
};
|
|
147
|
+
if (existingIndex >= 0) {
|
|
148
|
+
parts[existingIndex] = nextPart;
|
|
149
|
+
} else {
|
|
150
|
+
parts.push(nextPart);
|
|
151
|
+
}
|
|
152
|
+
return { ...msg, parts };
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
function completeStructuredOutputPart(messages, messageId, data, raw, reasoning) {
|
|
156
|
+
return messages.map((msg) => {
|
|
157
|
+
if (msg.id !== messageId) {
|
|
158
|
+
return msg;
|
|
159
|
+
}
|
|
160
|
+
const parts = [...msg.parts];
|
|
161
|
+
const existingIndex = parts.findIndex(
|
|
162
|
+
(p) => p.type === "structured-output"
|
|
163
|
+
);
|
|
164
|
+
const existingRaw = existingIndex >= 0 ? parts[existingIndex].raw : "";
|
|
165
|
+
let resolvedRaw = raw || existingRaw;
|
|
166
|
+
if (resolvedRaw === "" && data !== void 0) {
|
|
167
|
+
try {
|
|
168
|
+
resolvedRaw = JSON.stringify(data);
|
|
169
|
+
} catch {
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
const nextPart = {
|
|
173
|
+
type: "structured-output",
|
|
174
|
+
status: "complete",
|
|
175
|
+
data,
|
|
176
|
+
partial: data,
|
|
177
|
+
raw: resolvedRaw,
|
|
178
|
+
...reasoning !== void 0 ? { reasoning } : {}
|
|
179
|
+
};
|
|
180
|
+
if (existingIndex >= 0) {
|
|
181
|
+
parts[existingIndex] = nextPart;
|
|
182
|
+
} else {
|
|
183
|
+
parts.push(nextPart);
|
|
184
|
+
}
|
|
185
|
+
return { ...msg, parts };
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
function errorStructuredOutputPart(messages, messageId, errorMessage) {
|
|
189
|
+
return messages.map((msg) => {
|
|
190
|
+
if (msg.id !== messageId) {
|
|
191
|
+
return msg;
|
|
192
|
+
}
|
|
193
|
+
const parts = [...msg.parts];
|
|
194
|
+
const existingIndex = parts.findIndex(
|
|
195
|
+
(p) => p.type === "structured-output"
|
|
196
|
+
);
|
|
197
|
+
if (existingIndex < 0) {
|
|
198
|
+
parts.push({
|
|
199
|
+
type: "structured-output",
|
|
200
|
+
status: "error",
|
|
201
|
+
raw: "",
|
|
202
|
+
errorMessage
|
|
203
|
+
});
|
|
204
|
+
return { ...msg, parts };
|
|
205
|
+
}
|
|
206
|
+
const existing = parts[existingIndex];
|
|
207
|
+
if (existing.status === "complete") {
|
|
208
|
+
return msg;
|
|
209
|
+
}
|
|
210
|
+
parts[existingIndex] = {
|
|
211
|
+
...existing,
|
|
212
|
+
status: "error",
|
|
213
|
+
errorMessage
|
|
214
|
+
};
|
|
215
|
+
return { ...msg, parts };
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
function updateThinkingPart(messages, messageId, stepId, content, signature) {
|
|
219
|
+
return messages.map((msg) => {
|
|
220
|
+
if (msg.id !== messageId) {
|
|
221
|
+
return msg;
|
|
222
|
+
}
|
|
223
|
+
const parts = [...msg.parts];
|
|
224
|
+
const thinkingPartIndex = parts.findIndex(
|
|
225
|
+
(p) => p.type === "thinking" && p.stepId === stepId
|
|
226
|
+
);
|
|
227
|
+
const thinkingPart = {
|
|
228
|
+
type: "thinking",
|
|
229
|
+
content,
|
|
230
|
+
stepId,
|
|
231
|
+
...signature && { signature }
|
|
232
|
+
};
|
|
233
|
+
if (thinkingPartIndex >= 0) {
|
|
234
|
+
parts[thinkingPartIndex] = thinkingPart;
|
|
235
|
+
} else {
|
|
236
|
+
parts.push(thinkingPart);
|
|
237
|
+
}
|
|
238
|
+
return { ...msg, parts };
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
export {
|
|
242
|
+
appendStructuredOutputDelta,
|
|
243
|
+
completeStructuredOutputPart,
|
|
244
|
+
errorStructuredOutputPart,
|
|
245
|
+
updateTextPart,
|
|
246
|
+
updateThinkingPart,
|
|
247
|
+
updateToolCallApproval,
|
|
248
|
+
updateToolCallApprovalResponse,
|
|
249
|
+
updateToolCallPart,
|
|
250
|
+
updateToolCallWithOutput,
|
|
251
|
+
updateToolResultPart
|
|
252
|
+
};
|
|
253
|
+
//# sourceMappingURL=message-updaters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-updaters.js","sources":["../../../../../src/activities/chat/stream/message-updaters.ts"],"sourcesContent":["/**\n * Message Updaters (Internal)\n *\n * Internal helper functions for updating UIMessage parts.\n * These are used by StreamProcessor to manage the message array.\n */\n\nimport { parsePartialJSON } from './json-parser'\nimport type {\n ContentPart,\n StructuredOutputPart,\n ThinkingPart,\n ToolCallPart,\n ToolResultPart,\n UIMessage,\n} from '../../../types'\nimport type { ToolCallState, ToolResultState } from './types'\n\n/**\n * Update or add a text part to a message.\n *\n * If the last part is a text part, update it (continuing the same text segment).\n * Otherwise, create a new text part (starting a new text segment after tool calls).\n */\nexport function updateTextPart(\n messages: Array<UIMessage>,\n messageId: string,\n content: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const lastPart = parts.length > 0 ? parts[parts.length - 1] : null\n\n if (lastPart && lastPart.type === 'text') {\n // Update the last text part (continuing same text segment)\n parts[parts.length - 1] = { type: 'text', content }\n } else {\n // Create new text part (starting new text segment after tool calls/results)\n parts.push({ type: 'text', content })\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a tool call part to a message.\n */\nexport function updateToolCallPart(\n messages: Array<UIMessage>,\n messageId: string,\n toolCall: {\n id: string\n name: string\n arguments: string\n state: ToolCallState\n metadata?: Record<string, unknown>\n },\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existing = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCall.id,\n )\n\n // Carry forward metadata from either the new toolCall or the existing\n // part. Once the adapter has emitted metadata for a tool call (e.g.\n // Gemini's thoughtSignature on TOOL_CALL_START) we must not lose it on\n // subsequent updates that don't re-supply it.\n const metadata = toolCall.metadata ?? existing?.metadata\n\n const toolCallPart: ToolCallPart = {\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.name,\n arguments: toolCall.arguments,\n state: toolCall.state,\n // Carry forward approval and output from the existing part\n ...(existing?.approval && { approval: { ...existing.approval } }),\n ...(existing?.output !== undefined && { output: existing.output }),\n ...(metadata !== undefined && { metadata }),\n }\n\n if (existing) {\n // Update existing tool call\n parts[parts.indexOf(existing)] = toolCallPart\n } else {\n // Add new tool call at the end (preserve natural streaming order)\n parts.push(toolCallPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a tool result part to a message.\n */\nexport function updateToolResultPart(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n content: string | Array<ContentPart>,\n state: ToolResultState,\n error?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const resultPartIndex = parts.findIndex(\n (p): p is ToolResultPart =>\n p.type === 'tool-result' && p.toolCallId === toolCallId,\n )\n\n const toolResultPart: ToolResultPart = {\n type: 'tool-result',\n toolCallId,\n content,\n state,\n ...(error && { error }),\n }\n\n if (resultPartIndex >= 0) {\n parts[resultPartIndex] = toolResultPart\n } else {\n parts.push(toolResultPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with approval request metadata.\n */\nexport function updateToolCallApproval(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n approvalId: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n state: 'approval-requested',\n approval: {\n id: approvalId,\n needsApproval: true,\n },\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part's state (e.g., to \"input-complete\").\n */\nexport function updateToolCallState(\n messages: Array<UIMessage>,\n messageId: string,\n toolCallId: string,\n state: ToolCallState,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = { ...toolCallPart, state }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with output.\n * Searches all messages to find the tool call by ID.\n */\nexport function updateToolCallWithOutput(\n messages: Array<UIMessage>,\n toolCallId: string,\n output: any,\n state?: ToolCallState,\n errorText?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart => p.type === 'tool-call' && p.id === toolCallId,\n )\n\n if (toolCallPart) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n output: errorText ? { error: errorText } : output,\n state: state ?? (errorText ? 'error' : 'complete'),\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Update a tool call part with approval response.\n * Searches all messages to find the tool call by approval ID.\n */\nexport function updateToolCallApprovalResponse(\n messages: Array<UIMessage>,\n approvalId: string,\n approved: boolean,\n): Array<UIMessage> {\n return messages.map((msg) => {\n const parts = [...msg.parts]\n const toolCallPart = parts.find(\n (p): p is ToolCallPart =>\n p.type === 'tool-call' && p.approval?.id === approvalId,\n )\n\n if (toolCallPart && toolCallPart.approval) {\n const index = parts.indexOf(toolCallPart)\n parts[index] = {\n ...toolCallPart,\n approval: { ...toolCallPart.approval, approved },\n state: 'approval-responded',\n }\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Append a delta to the structured-output part on `messageId`, or create one\n * if absent. Progressive parse of the accumulated buffer fills `partial`.\n *\n * Callers must only invoke this while the part is still in flight — the\n * helper unconditionally writes `status: 'streaming'`, so feeding it a delta\n * after a `complete`/`error` terminal would regress the part. In practice the\n * processor gates calls via `structuredMessageIds`, which is dropped on\n * terminal events.\n *\n * If the progressive parse returns null/undefined (the buffer is not yet a\n * parseable JSON prefix), the previously-good `partial` is preserved so the\n * UI doesn't flicker back to empty for a single render.\n */\nexport function appendStructuredOutputDelta(\n messages: Array<UIMessage>,\n messageId: string,\n delta: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n const existing =\n existingIndex >= 0 ? (parts[existingIndex] as StructuredOutputPart) : null\n\n const nextRaw = (existing?.raw ?? '') + delta\n const progressive = parsePartialJSON(nextRaw)\n const nextPartial =\n progressive !== undefined && progressive !== null\n ? progressive\n : existing?.partial\n\n const nextPart: StructuredOutputPart = {\n type: 'structured-output',\n status: 'streaming',\n raw: nextRaw,\n ...(nextPartial !== undefined ? { partial: nextPartial } : {}),\n ...(existing?.reasoning !== undefined\n ? { reasoning: existing.reasoning }\n : {}),\n }\n\n if (existingIndex >= 0) {\n parts[existingIndex] = nextPart\n } else {\n parts.push(nextPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Snap the structured-output part on `messageId` to `complete` with the\n * validated `data`. Picks the freshest available `raw` so the wire\n * round-trip stays internally consistent:\n *\n * 1. Caller-supplied `raw` (the original streamed bytes from the model).\n * 2. The existing part's `raw` (deltas accumulated before this terminal).\n * 3. `JSON.stringify(data)` as a defensive fallback for terminal-only\n * completes that never shipped raw — keeps the part self-consistent\n * so downstream consumers never see a complete part with empty raw.\n */\nexport function completeStructuredOutputPart(\n messages: Array<UIMessage>,\n messageId: string,\n data: unknown,\n raw: string,\n reasoning?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n\n const existingRaw =\n existingIndex >= 0\n ? (parts[existingIndex] as StructuredOutputPart).raw\n : ''\n let resolvedRaw = raw || existingRaw\n if (resolvedRaw === '' && data !== undefined) {\n try {\n resolvedRaw = JSON.stringify(data)\n } catch {\n // Unserializable (circular, BigInt, throwing toJSON). Leave raw\n // empty. Both downstream paths handle this: `ag-ui-wire.ts`\n // `collectText` skips complete parts with empty raw entirely, and\n // `uiMessageToModelMessages` falls back to a defensive\n // `safeJsonStringify(data)` which itself returns `''` for the same\n // unserializable inputs — so the turn is silently dropped from the\n // next request rather than shipping garbage or crashing the stream.\n }\n }\n\n const nextPart: StructuredOutputPart = {\n type: 'structured-output',\n status: 'complete',\n data,\n partial: data,\n raw: resolvedRaw,\n ...(reasoning !== undefined ? { reasoning } : {}),\n }\n\n if (existingIndex >= 0) {\n parts[existingIndex] = nextPart\n } else {\n parts.push(nextPart)\n }\n\n return { ...msg, parts }\n })\n}\n\n/**\n * Mark the structured-output part on `messageId` as errored. If no part\n * exists yet — RUN_ERROR fired after `structured-output.start` but before\n * any delta — create an empty errored placeholder so consumers have\n * something renderable. Existing complete parts are left alone (an error\n * after a successful complete should not retroactively un-complete it).\n */\nexport function errorStructuredOutputPart(\n messages: Array<UIMessage>,\n messageId: string,\n errorMessage: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const existingIndex = parts.findIndex(\n (p): p is StructuredOutputPart => p.type === 'structured-output',\n )\n\n if (existingIndex < 0) {\n parts.push({\n type: 'structured-output',\n status: 'error',\n raw: '',\n errorMessage,\n })\n return { ...msg, parts }\n }\n\n const existing = parts[existingIndex] as StructuredOutputPart\n if (existing.status === 'complete') {\n return msg\n }\n parts[existingIndex] = {\n ...existing,\n status: 'error',\n errorMessage,\n }\n return { ...msg, parts }\n })\n}\n\n/**\n * Update or add a thinking part to a message, keyed by stepId.\n * Each distinct stepId produces its own ThinkingPart.\n */\nexport function updateThinkingPart(\n messages: Array<UIMessage>,\n messageId: string,\n stepId: string,\n content: string,\n signature?: string,\n): Array<UIMessage> {\n return messages.map((msg) => {\n if (msg.id !== messageId) {\n return msg\n }\n\n const parts = [...msg.parts]\n const thinkingPartIndex = parts.findIndex(\n (p) => p.type === 'thinking' && p.stepId === stepId,\n )\n\n const thinkingPart: ThinkingPart = {\n type: 'thinking',\n content,\n stepId,\n ...(signature && { signature }),\n }\n\n if (thinkingPartIndex >= 0) {\n // Update existing thinking part for this step\n parts[thinkingPartIndex] = thinkingPart\n } else {\n // Add new thinking part at the end (preserve natural streaming order)\n parts.push(thinkingPart)\n }\n\n return { ...msg, parts }\n })\n}\n"],"names":[],"mappings":"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"}
|