@tanstack/ai 0.23.1 → 0.24.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.
Files changed (61) hide show
  1. package/dist/esm/activities/chat/index.d.ts +33 -9
  2. package/dist/esm/activities/chat/index.js +19 -9
  3. package/dist/esm/activities/chat/index.js.map +1 -1
  4. package/dist/esm/activities/chat/messages.js +2 -1
  5. package/dist/esm/activities/chat/messages.js.map +1 -1
  6. package/dist/esm/activities/chat/middleware/compose.d.ts +14 -14
  7. package/dist/esm/activities/chat/middleware/compose.js.map +1 -1
  8. package/dist/esm/activities/chat/middleware/types.d.ts +16 -16
  9. package/dist/esm/activities/chat/runtime-context-types.d.ts +43 -0
  10. package/dist/esm/activities/chat/stream/message-updaters.d.ts +2 -2
  11. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  12. package/dist/esm/activities/chat/stream/processor.d.ts +1 -0
  13. package/dist/esm/activities/chat/stream/processor.js +35 -12
  14. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  15. package/dist/esm/activities/chat/tools/tool-calls.d.ts +15 -5
  16. package/dist/esm/activities/chat/tools/tool-calls.js +59 -19
  17. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  18. package/dist/esm/activities/chat/tools/tool-definition.d.ts +12 -8
  19. package/dist/esm/activities/chat/tools/tool-definition.js.map +1 -1
  20. package/dist/esm/activities/error-payload.d.ts +26 -0
  21. package/dist/esm/activities/error-payload.js +12 -1
  22. package/dist/esm/activities/error-payload.js.map +1 -1
  23. package/dist/esm/adapter-internals.d.ts +1 -1
  24. package/dist/esm/adapter-internals.js +3 -2
  25. package/dist/esm/client.d.ts +1 -1
  26. package/dist/esm/client.js +3 -1
  27. package/dist/esm/client.js.map +1 -1
  28. package/dist/esm/index.d.ts +2 -1
  29. package/dist/esm/index.js +7 -1
  30. package/dist/esm/index.js.map +1 -1
  31. package/dist/esm/tool-registry.d.ts +7 -7
  32. package/dist/esm/tool-registry.js +1 -1
  33. package/dist/esm/tool-registry.js.map +1 -1
  34. package/dist/esm/types.d.ts +40 -8
  35. package/dist/esm/utilities/ag-ui-wire.js +1 -1
  36. package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
  37. package/dist/esm/utilities/chat-params.d.ts +8 -3
  38. package/dist/esm/utilities/chat-params.js +6 -2
  39. package/dist/esm/utilities/chat-params.js.map +1 -1
  40. package/dist/esm/utilities/tool-result.d.ts +21 -0
  41. package/dist/esm/utilities/tool-result.js +37 -0
  42. package/dist/esm/utilities/tool-result.js.map +1 -0
  43. package/package.json +2 -2
  44. package/src/activities/chat/index.ts +219 -47
  45. package/src/activities/chat/messages.ts +2 -1
  46. package/src/activities/chat/middleware/compose.ts +23 -17
  47. package/src/activities/chat/middleware/types.ts +16 -16
  48. package/src/activities/chat/runtime-context-types.ts +68 -0
  49. package/src/activities/chat/stream/message-updaters.ts +2 -1
  50. package/src/activities/chat/stream/processor.ts +48 -8
  51. package/src/activities/chat/tools/tool-calls.ts +138 -43
  52. package/src/activities/chat/tools/tool-definition.ts +25 -31
  53. package/src/activities/error-payload.ts +44 -0
  54. package/src/adapter-internals.ts +4 -1
  55. package/src/client.ts +5 -1
  56. package/src/index.ts +7 -0
  57. package/src/tool-registry.ts +16 -14
  58. package/src/types.ts +86 -29
  59. package/src/utilities/ag-ui-wire.ts +4 -1
  60. package/src/utilities/chat-params.ts +22 -7
  61. package/src/utilities/tool-result.ts +60 -0
@@ -1,11 +1,36 @@
1
1
  import { AnyTextAdapter } from './adapter.js';
2
- import { ConstrainedModelMessage, InferSchemaType, ModelMessage, SchemaInput, StreamChunk, StructuredOutputStream, TextOptions, Tool, UIMessage } from '../../types.js';
2
+ import { AnyTool, ConstrainedModelMessage, InferSchemaType, ModelMessage, SchemaInput, StreamChunk, StructuredOutputStream, TextOptions, UIMessage } from '../../types.js';
3
3
  import { ChatMiddleware } from './middleware/types.js';
4
4
  import { SystemPrompt } from '../../system-prompts.js';
5
5
  import { DebugOption } from '../../logger/types.js';
6
6
  import { ProviderTool } from '../../tools/provider-tool.js';
7
+ import { ContextFromMiddleware, ContextFromTool, DefinedContext, MergeContext, UnionToIntersection } from './runtime-context-types.js';
7
8
  /** The adapter kind this activity handles */
8
9
  export declare const kind: "text";
10
+ type AnyRuntimeTool = AnyTool;
11
+ type ContextFromConsumer<T> = ContextFromTool<T> | ContextFromMiddleware<T>;
12
+ type RequiredContextFromConsumerUnion<T> = T extends unknown ? undefined extends ContextFromConsumer<T> ? never : ContextFromConsumer<T> : never;
13
+ type ContextFromConsumerUnion<T> = [
14
+ UnionToIntersection<DefinedContext<ContextFromConsumer<T>>>
15
+ ] extends [never] ? never : [RequiredContextFromConsumerUnion<T>] extends [never] ? UnionToIntersection<DefinedContext<ContextFromConsumer<T>>> | undefined : UnionToIntersection<DefinedContext<ContextFromConsumer<T>>>;
16
+ type ContextFromArray<T> = T extends readonly [infer THead, ...infer TTail] ? MergeContext<ContextFromConsumer<THead>, ContextFromArray<TTail>> : T extends ReadonlyArray<infer TItem> ? ContextFromConsumerUnion<TItem> : never;
17
+ type ContextFromInputs<TTools, TMiddleware> = MergeContext<ContextFromArray<NonNullable<TTools>>, ContextFromArray<NonNullable<TMiddleware>>>;
18
+ type InferredContext<TTools, TMiddleware> = [
19
+ ContextFromInputs<TTools, TMiddleware>
20
+ ] extends [never] ? unknown : ContextFromInputs<TTools, TMiddleware>;
21
+ type RequiredContextFromInputs<TTools, TMiddleware> = [
22
+ ContextFromInputs<TTools, TMiddleware>
23
+ ] extends [never] ? {
24
+ context?: unknown;
25
+ } : undefined extends ContextFromInputs<TTools, TMiddleware> ? {
26
+ context?: ContextFromInputs<TTools, TMiddleware>;
27
+ } : {
28
+ context: ContextFromInputs<TTools, TMiddleware>;
29
+ };
30
+ type TextActivityOptionsWithContext<TAdapter extends AnyTextAdapter, TSchema extends SchemaInput | undefined, TStream extends boolean, TTools extends TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'], TMiddleware extends TextActivityOptions<TAdapter, TSchema, TStream, any>['middleware']> = Omit<TextActivityOptions<TAdapter, TSchema, TStream, any>, 'tools' | 'middleware' | 'context'> & {
31
+ tools?: TTools;
32
+ middleware?: TMiddleware;
33
+ } & RequiredContextFromInputs<TTools, TMiddleware>;
9
34
  /**
10
35
  * Options for the text activity.
11
36
  * Types are extracted directly from the adapter (which has pre-resolved generics).
@@ -14,7 +39,7 @@ export declare const kind: "text";
14
39
  * @template TSchema - Optional Standard Schema for structured output
15
40
  * @template TStream - Whether to stream the output (default: true)
16
41
  */
17
- export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema extends SchemaInput | undefined, TStream extends boolean> {
42
+ export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema extends SchemaInput | undefined, TStream extends boolean, TContext = unknown> {
18
43
  /** The text adapter to use (created by a provider function like openaiText('gpt-4o')) */
19
44
  adapter: TAdapter;
20
45
  /**
@@ -49,7 +74,7 @@ export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema ex
49
74
  * `supports.tools` list. Passing an unsupported tool produces a
50
75
  * compile-time error on the array element.
51
76
  */
52
- tools?: Array<(Tool & {
77
+ tools?: Array<(AnyRuntimeTool & {
53
78
  readonly '~toolKind'?: never;
54
79
  }) | ProviderTool<string, TAdapter['~types']['toolCapabilities'][number]>> | undefined;
55
80
  /** Controls the randomness of the output. Higher values make output more random. Range: [0.0, 2.0] */
@@ -127,12 +152,11 @@ export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema ex
127
152
  * })
128
153
  * ```
129
154
  */
130
- middleware?: Array<ChatMiddleware>;
155
+ middleware?: Array<ChatMiddleware<TContext>>;
131
156
  /**
132
- * Opaque user-provided context value passed to middleware hooks.
133
- * Can be used to pass request-scoped data (e.g., user ID, request context).
157
+ * Runtime context value passed to middleware hooks and server tools.
134
158
  */
135
- context?: unknown;
159
+ context?: TContext;
136
160
  /**
137
161
  * Enable debug logging. Pass `true` to enable all categories with the default
138
162
  * console logger, `false` to silence everything, or a `DebugConfig` object for
@@ -154,7 +178,7 @@ export interface TextActivityOptions<TAdapter extends AnyTextAdapter, TSchema ex
154
178
  * const stream = chat({ ...chatOptions, messages })
155
179
  * ```
156
180
  */
157
- export declare function createChatOptions<TAdapter extends AnyTextAdapter, TSchema extends SchemaInput | undefined = undefined, TStream extends boolean = true>(options: TextActivityOptions<TAdapter, TSchema, TStream>): TextActivityOptions<TAdapter, TSchema, TStream>;
181
+ export declare function createChatOptions<TAdapter extends AnyTextAdapter, TSchema extends SchemaInput | undefined = undefined, TStream extends boolean = true, const TTools extends TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'] = TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'], const TMiddleware extends TextActivityOptions<TAdapter, TSchema, TStream, any>['middleware'] = TextActivityOptions<TAdapter, TSchema, TStream, any>['middleware']>(options: TextActivityOptionsWithContext<TAdapter, TSchema, TStream, TTools, TMiddleware>): TextActivityOptions<TAdapter, TSchema, TStream, InferredContext<TTools, TMiddleware>>;
158
182
  /**
159
183
  * Result type for the text activity.
160
184
  * - If outputSchema is provided AND stream is explicitly true:
@@ -233,6 +257,6 @@ export type TextActivityResult<TSchema extends SchemaInput | undefined, TStream
233
257
  * // result is { summary: string, keyPoints: string[] }
234
258
  * ```
235
259
  */
236
- export declare function chat<TAdapter extends AnyTextAdapter, TSchema extends SchemaInput | undefined = undefined, TStream extends boolean = boolean>(options: TextActivityOptions<TAdapter, TSchema, TStream>): TextActivityResult<TSchema, TStream>;
260
+ export declare function chat<TAdapter extends AnyTextAdapter, TSchema extends SchemaInput | undefined = undefined, TStream extends boolean = boolean, const TTools extends TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'] = TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'], const TMiddleware extends TextActivityOptions<TAdapter, TSchema, TStream, any>['middleware'] = TextActivityOptions<TAdapter, TSchema, TStream, any>['middleware']>(options: TextActivityOptionsWithContext<TAdapter, TSchema, TStream, TTools, TMiddleware>): TextActivityResult<TSchema, TStream>;
237
261
  export type { TextAdapter, TextAdapterConfig, StructuredOutputOptions, StructuredOutputResult, } from './adapter.js';
238
262
  export { BaseTextAdapter } from './adapter.js';
@@ -2,6 +2,7 @@ import { devtoolsMiddleware } from "@tanstack/ai-event-client";
2
2
  import { stripToSpecMiddleware } from "../../strip-to-spec-middleware.js";
3
3
  import { streamToText } from "../../stream-to-response.js";
4
4
  import { resolveDebugOption } from "../../logger/resolve.js";
5
+ import { normalizeToolResult } from "../../utilities/tool-result.js";
5
6
  import { LazyToolManager } from "./tools/lazy-tool-manager.js";
6
7
  import { ToolCallManager, MiddlewareAbortError, executeToolCalls } from "./tools/tool-calls.js";
7
8
  import { convertSchemaToJsonSchema, isStandardSchema, parseWithStandardSchema } from "./tools/schema-converter.js";
@@ -567,7 +568,8 @@ class TextEngine {
567
568
  info
568
569
  );
569
570
  }
570
- }
571
+ },
572
+ this.middlewareCtx.context
571
573
  );
572
574
  const executionResult = yield* this.drainToolCallGenerator(generator);
573
575
  if (this.isMiddlewareAborted()) {
@@ -697,7 +699,8 @@ class TextEngine {
697
699
  info
698
700
  );
699
701
  }
700
- }
702
+ },
703
+ this.middlewareCtx.context
701
704
  );
702
705
  const executionResult = yield* this.drainToolCallGenerator(generator);
703
706
  this.middlewareCtx.phase = "afterTools";
@@ -798,10 +801,14 @@ class TextEngine {
798
801
  for (const message of this.messages) {
799
802
  if (message.role === "tool" && message.toolCallId) {
800
803
  let output;
801
- try {
802
- output = JSON.parse(message.content);
803
- } catch {
804
+ if (Array.isArray(message.content)) {
804
805
  output = message.content;
806
+ } else {
807
+ try {
808
+ output = JSON.parse(message.content);
809
+ } catch {
810
+ output = message.content;
811
+ }
805
812
  }
806
813
  if (output && typeof output === "object" && output.pendingExecution === true) {
807
814
  continue;
@@ -852,7 +859,8 @@ class TextEngine {
852
859
  buildToolResultChunks(results, finishEvent, argsMap) {
853
860
  const chunks = [];
854
861
  for (const result of results) {
855
- const content = JSON.stringify(result.result);
862
+ const content = normalizeToolResult(result.result);
863
+ const wireContent = typeof content === "string" ? content : JSON.stringify(content);
856
864
  if (argsMap) {
857
865
  chunks.push({
858
866
  type: "TOOL_CALL_START",
@@ -879,7 +887,8 @@ class TextEngine {
879
887
  toolCallId: result.toolCallId,
880
888
  toolCallName: result.toolName,
881
889
  toolName: result.toolName,
882
- result: content
890
+ result: wireContent,
891
+ ...result.state !== void 0 && { state: result.state }
883
892
  });
884
893
  chunks.push({
885
894
  type: "TOOL_CALL_RESULT",
@@ -887,8 +896,9 @@ class TextEngine {
887
896
  model: finishEvent.model,
888
897
  messageId: this.createId("tool-result"),
889
898
  toolCallId: result.toolCallId,
890
- content,
891
- role: "tool"
899
+ content: wireContent,
900
+ role: "tool",
901
+ ...result.state !== void 0 && { state: result.state }
892
902
  });
893
903
  const placeholderIdx = this.messages.findIndex((m) => {
894
904
  if (m.role !== "tool" || m.toolCallId !== result.toolCallId) {