@tanstack/ai-code-mode 0.1.23 → 0.2.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.
@@ -1,3 +1,4 @@
1
+ import { ToolExecutionContext } from '@tanstack/ai';
1
2
  import { CodeModeTool, ToolBinding } from '../types.js';
2
3
  /**
3
4
  * Convert an array of TanStack AI tools to a Record of ToolBindings
@@ -21,4 +22,4 @@ export declare function toolToBinding(tool: CodeModeTool, prefix?: string): Tool
21
22
  * @param bindings - Original tool bindings
22
23
  * @param emitCustomEvent - Callback to emit custom events to the stream
23
24
  */
24
- export declare function createEventAwareBindings(bindings: Record<string, ToolBinding>, emitCustomEvent: (eventName: string, data: Record<string, any>) => void): Record<string, ToolBinding>;
25
+ export declare function createEventAwareBindings(bindings: Record<string, ToolBinding>, emitCustomEvent: ToolExecutionContext['emitCustomEvent']): Record<string, ToolBinding>;
@@ -13,21 +13,15 @@ function toolToBinding(tool, prefix = "") {
13
13
  properties: {}
14
14
  };
15
15
  const outputSchema = tool.outputSchema ? convertSchemaToJsonSchema(tool.outputSchema) : void 0;
16
- let execute;
17
- if ("execute" in tool && typeof tool.execute === "function") {
18
- const toolExecute = tool.execute;
19
- execute = (args, context) => {
20
- return Promise.resolve(toolExecute(args, context));
21
- };
22
- } else if ("__toolSide" in tool && tool.__toolSide === "definition") {
23
- throw new Error(
24
- `Tool "${tool.name}" is a ToolDefinition without an execute function. Call .server(fn) to provide an implementation before using with Code Mode.`
25
- );
26
- } else {
16
+ if (typeof tool.execute !== "function") {
27
17
  throw new Error(
28
- `Tool "${tool.name}" does not have an execute function. Code Mode requires tools with implementations.`
18
+ `Tool "${tool.name}" does not have an execute function. Code Mode requires server tools with implementations.`
29
19
  );
30
20
  }
21
+ const toolExecute = tool.execute;
22
+ const execute = (args, context) => {
23
+ return Promise.resolve(toolExecute(args, context));
24
+ };
31
25
  return {
32
26
  name: `${prefix}${tool.name}`,
33
27
  description: tool.description,
@@ -1 +1 @@
1
- {"version":3,"file":"tool-to-binding.js","sources":["../../../src/bindings/tool-to-binding.ts"],"sourcesContent":["import { convertSchemaToJsonSchema } from '@tanstack/ai'\nimport type { ToolExecutionContext } from '@tanstack/ai'\nimport type { CodeModeTool, ToolBinding } from '../types'\n\n/**\n * Convert an array of TanStack AI tools to a Record of ToolBindings\n *\n * @param tools - Array of tools to convert\n * @param prefix - Optional prefix to add to binding names (e.g., 'external_')\n */\nexport function toolsToBindings(\n tools: Array<CodeModeTool>,\n prefix: string = '',\n): Record<string, ToolBinding> {\n const bindings: Record<string, ToolBinding> = {}\n\n for (const tool of tools) {\n const bindingName = `${prefix}${tool.name}`\n bindings[bindingName] = toolToBinding(tool, prefix)\n }\n\n return bindings\n}\n\n/**\n * Convert a single TanStack AI tool to a ToolBinding\n *\n * @param tool - Tool to convert\n * @param prefix - Optional prefix to add to binding name (e.g., 'external_')\n * @throws Error if the tool doesn't have an execute function\n */\nexport function toolToBinding(\n tool: CodeModeTool,\n prefix: string = '',\n): ToolBinding {\n // Convert schemas (Zod or Standard Schema) to JSON Schema\n const inputSchema = convertSchemaToJsonSchema(tool.inputSchema) || {\n type: 'object',\n properties: {},\n }\n\n const outputSchema = tool.outputSchema\n ? convertSchemaToJsonSchema(tool.outputSchema)\n : undefined\n\n // Get execute function\n // ServerTool has execute, ToolDefinition (without .server()) does not\n let execute: (\n args: unknown,\n context?: ToolExecutionContext,\n ) => Promise<unknown>\n\n if ('execute' in tool && typeof tool.execute === 'function') {\n const toolExecute = tool.execute\n execute = (args: unknown, context?: ToolExecutionContext) => {\n // Pass context to the underlying tool so it can emit custom events\n return Promise.resolve(toolExecute(args, context))\n }\n } else if ('__toolSide' in tool && tool.__toolSide === 'definition') {\n throw new Error(\n `Tool \"${tool.name}\" is a ToolDefinition without an execute function. ` +\n `Call .server(fn) to provide an implementation before using with Code Mode.`,\n )\n } else {\n throw new Error(\n `Tool \"${tool.name}\" does not have an execute function. ` +\n `Code Mode requires tools with implementations.`,\n )\n }\n\n return {\n name: `${prefix}${tool.name}`,\n description: tool.description,\n inputSchema,\n outputSchema,\n execute,\n }\n}\n\n/**\n * Create event-aware bindings that emit custom events for each external function call.\n * Wraps each binding's execute function to emit events before and after execution.\n *\n * @param bindings - Original tool bindings\n * @param emitCustomEvent - Callback to emit custom events to the stream\n */\nexport function createEventAwareBindings(\n bindings: Record<string, ToolBinding>,\n emitCustomEvent: (eventName: string, data: Record<string, any>) => void,\n): Record<string, ToolBinding> {\n const wrapped: Record<string, ToolBinding> = {}\n\n for (const [name, binding] of Object.entries(bindings)) {\n wrapped[name] = {\n ...binding,\n execute: async (args: unknown) => {\n // Emit call event\n emitCustomEvent('code_mode:external_call', {\n function: name,\n args,\n timestamp: Date.now(),\n })\n\n const startTime = Date.now()\n try {\n // Create context for the underlying tool so it can also emit events\n const toolContext: ToolExecutionContext = { emitCustomEvent }\n const result = await binding.execute(args, toolContext)\n\n // Emit result event\n emitCustomEvent('code_mode:external_result', {\n function: name,\n result,\n duration: Date.now() - startTime,\n })\n\n return result\n } catch (error) {\n // Emit error event\n emitCustomEvent('code_mode:external_error', {\n function: name,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n })\n throw error\n }\n },\n }\n }\n\n return wrapped\n}\n"],"names":[],"mappings":";AAUO,SAAS,gBACd,OACA,SAAiB,IACY;AAC7B,QAAM,WAAwC,CAAA;AAE9C,aAAW,QAAQ,OAAO;AACxB,UAAM,cAAc,GAAG,MAAM,GAAG,KAAK,IAAI;AACzC,aAAS,WAAW,IAAI,cAAc,MAAM,MAAM;AAAA,EACpD;AAEA,SAAO;AACT;AASO,SAAS,cACd,MACA,SAAiB,IACJ;AAEb,QAAM,cAAc,0BAA0B,KAAK,WAAW,KAAK;AAAA,IACjE,MAAM;AAAA,IACN,YAAY,CAAA;AAAA,EAAC;AAGf,QAAM,eAAe,KAAK,eACtB,0BAA0B,KAAK,YAAY,IAC3C;AAIJ,MAAI;AAKJ,MAAI,aAAa,QAAQ,OAAO,KAAK,YAAY,YAAY;AAC3D,UAAM,cAAc,KAAK;AACzB,cAAU,CAAC,MAAe,YAAmC;AAE3D,aAAO,QAAQ,QAAQ,YAAY,MAAM,OAAO,CAAC;AAAA,IACnD;AAAA,EACF,WAAW,gBAAgB,QAAQ,KAAK,eAAe,cAAc;AACnE,UAAM,IAAI;AAAA,MACR,SAAS,KAAK,IAAI;AAAA,IAAA;AAAA,EAGtB,OAAO;AACL,UAAM,IAAI;AAAA,MACR,SAAS,KAAK,IAAI;AAAA,IAAA;AAAA,EAGtB;AAEA,SAAO;AAAA,IACL,MAAM,GAAG,MAAM,GAAG,KAAK,IAAI;AAAA,IAC3B,aAAa,KAAK;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AASO,SAAS,yBACd,UACA,iBAC6B;AAC7B,QAAM,UAAuC,CAAA;AAE7C,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACtD,YAAQ,IAAI,IAAI;AAAA,MACd,GAAG;AAAA,MACH,SAAS,OAAO,SAAkB;AAEhC,wBAAgB,2BAA2B;AAAA,UACzC,UAAU;AAAA,UACV;AAAA,UACA,WAAW,KAAK,IAAA;AAAA,QAAI,CACrB;AAED,cAAM,YAAY,KAAK,IAAA;AACvB,YAAI;AAEF,gBAAM,cAAoC,EAAE,gBAAA;AAC5C,gBAAM,SAAS,MAAM,QAAQ,QAAQ,MAAM,WAAW;AAGtD,0BAAgB,6BAA6B;AAAA,YAC3C,UAAU;AAAA,YACV;AAAA,YACA,UAAU,KAAK,QAAQ;AAAA,UAAA,CACxB;AAED,iBAAO;AAAA,QACT,SAAS,OAAO;AAEd,0BAAgB,4BAA4B;AAAA,YAC1C,UAAU;AAAA,YACV,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5D,UAAU,KAAK,QAAQ;AAAA,UAAA,CACxB;AACD,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AACT;"}
1
+ {"version":3,"file":"tool-to-binding.js","sources":["../../../src/bindings/tool-to-binding.ts"],"sourcesContent":["import { convertSchemaToJsonSchema } from '@tanstack/ai'\nimport type { ToolExecutionContext } from '@tanstack/ai'\nimport type { CodeModeTool, ToolBinding } from '../types'\n\n/**\n * Convert an array of TanStack AI tools to a Record of ToolBindings\n *\n * @param tools - Array of tools to convert\n * @param prefix - Optional prefix to add to binding names (e.g., 'external_')\n */\nexport function toolsToBindings(\n tools: Array<CodeModeTool>,\n prefix: string = '',\n): Record<string, ToolBinding> {\n const bindings: Record<string, ToolBinding> = {}\n\n for (const tool of tools) {\n const bindingName = `${prefix}${tool.name}`\n bindings[bindingName] = toolToBinding(tool, prefix)\n }\n\n return bindings\n}\n\n/**\n * Convert a single TanStack AI tool to a ToolBinding\n *\n * @param tool - Tool to convert\n * @param prefix - Optional prefix to add to binding name (e.g., 'external_')\n * @throws Error if the tool doesn't have an execute function\n */\nexport function toolToBinding(\n tool: CodeModeTool,\n prefix: string = '',\n): ToolBinding {\n // Convert schemas (Zod or Standard Schema) to JSON Schema\n const inputSchema = convertSchemaToJsonSchema(tool.inputSchema) || {\n type: 'object',\n properties: {},\n }\n\n const outputSchema = tool.outputSchema\n ? convertSchemaToJsonSchema(tool.outputSchema)\n : undefined\n\n if (typeof tool.execute !== 'function') {\n throw new Error(\n `Tool \"${tool.name}\" does not have an execute function. ` +\n `Code Mode requires server tools with implementations.`,\n )\n }\n\n const toolExecute = tool.execute\n const execute = (args: unknown, context?: ToolExecutionContext) => {\n // Pass context to the underlying tool so it can emit custom events\n return Promise.resolve(toolExecute(args, context))\n }\n\n return {\n name: `${prefix}${tool.name}`,\n description: tool.description,\n inputSchema,\n outputSchema,\n execute,\n }\n}\n\n/**\n * Create event-aware bindings that emit custom events for each external function call.\n * Wraps each binding's execute function to emit events before and after execution.\n *\n * @param bindings - Original tool bindings\n * @param emitCustomEvent - Callback to emit custom events to the stream\n */\nexport function createEventAwareBindings(\n bindings: Record<string, ToolBinding>,\n emitCustomEvent: ToolExecutionContext['emitCustomEvent'],\n): Record<string, ToolBinding> {\n const wrapped: Record<string, ToolBinding> = {}\n\n for (const [name, binding] of Object.entries(bindings)) {\n wrapped[name] = {\n ...binding,\n execute: async (args: unknown) => {\n // Emit call event\n emitCustomEvent('code_mode:external_call', {\n function: name,\n args,\n timestamp: Date.now(),\n })\n\n const startTime = Date.now()\n try {\n // Create context for the underlying tool so it can also emit events\n const toolContext: ToolExecutionContext = { emitCustomEvent }\n const result = await binding.execute(args, toolContext)\n\n // Emit result event\n emitCustomEvent('code_mode:external_result', {\n function: name,\n result,\n duration: Date.now() - startTime,\n })\n\n return result\n } catch (error) {\n // Emit error event\n emitCustomEvent('code_mode:external_error', {\n function: name,\n error: error instanceof Error ? error.message : String(error),\n duration: Date.now() - startTime,\n })\n throw error\n }\n },\n }\n }\n\n return wrapped\n}\n"],"names":[],"mappings":";AAUO,SAAS,gBACd,OACA,SAAiB,IACY;AAC7B,QAAM,WAAwC,CAAA;AAE9C,aAAW,QAAQ,OAAO;AACxB,UAAM,cAAc,GAAG,MAAM,GAAG,KAAK,IAAI;AACzC,aAAS,WAAW,IAAI,cAAc,MAAM,MAAM;AAAA,EACpD;AAEA,SAAO;AACT;AASO,SAAS,cACd,MACA,SAAiB,IACJ;AAEb,QAAM,cAAc,0BAA0B,KAAK,WAAW,KAAK;AAAA,IACjE,MAAM;AAAA,IACN,YAAY,CAAA;AAAA,EAAC;AAGf,QAAM,eAAe,KAAK,eACtB,0BAA0B,KAAK,YAAY,IAC3C;AAEJ,MAAI,OAAO,KAAK,YAAY,YAAY;AACtC,UAAM,IAAI;AAAA,MACR,SAAS,KAAK,IAAI;AAAA,IAAA;AAAA,EAGtB;AAEA,QAAM,cAAc,KAAK;AACzB,QAAM,UAAU,CAAC,MAAe,YAAmC;AAEjE,WAAO,QAAQ,QAAQ,YAAY,MAAM,OAAO,CAAC;AAAA,EACnD;AAEA,SAAO;AAAA,IACL,MAAM,GAAG,MAAM,GAAG,KAAK,IAAI;AAAA,IAC3B,aAAa,KAAK;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AASO,SAAS,yBACd,UACA,iBAC6B;AAC7B,QAAM,UAAuC,CAAA;AAE7C,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAG;AACtD,YAAQ,IAAI,IAAI;AAAA,MACd,GAAG;AAAA,MACH,SAAS,OAAO,SAAkB;AAEhC,wBAAgB,2BAA2B;AAAA,UACzC,UAAU;AAAA,UACV;AAAA,UACA,WAAW,KAAK,IAAA;AAAA,QAAI,CACrB;AAED,cAAM,YAAY,KAAK,IAAA;AACvB,YAAI;AAEF,gBAAM,cAAoC,EAAE,gBAAA;AAC5C,gBAAM,SAAS,MAAM,QAAQ,QAAQ,MAAM,WAAW;AAGtD,0BAAgB,6BAA6B;AAAA,YAC3C,UAAU;AAAA,YACV;AAAA,YACA,UAAU,KAAK,QAAQ;AAAA,UAAA,CACxB;AAED,iBAAO;AAAA,QACT,SAAS,OAAO;AAEd,0BAAgB,4BAA4B;AAAA,YAC1C,UAAU;AAAA,YACV,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAAA,YAC5D,UAAU,KAAK,QAAQ;AAAA,UAAA,CACxB;AACD,gBAAM;AAAA,QACR;AAAA,MACF;AAAA,IAAA;AAAA,EAEJ;AAEA,SAAO;AACT;"}
@@ -36,6 +36,6 @@ export declare function createCodeMode(config: CodeModeToolConfig): {
36
36
  name: import('zod').ZodOptional<import('zod').ZodString>;
37
37
  line: import('zod').ZodOptional<import('zod').ZodNumber>;
38
38
  }, import('zod/v4/core').$strip>>;
39
- }, import('zod/v4/core').$strip>, "execute_typescript">;
39
+ }, import('zod/v4/core').$strip>, "execute_typescript", unknown>;
40
40
  systemPrompt: string;
41
41
  };
@@ -1,4 +1,4 @@
1
- import { ServerTool, ToolDefinition, ToolExecutionContext } from '@tanstack/ai';
1
+ import { SchemaInput, ServerTool, ToolExecutionContext } from '@tanstack/ai';
2
2
  /**
3
3
  * Interface for isolate/sandbox drivers
4
4
  * Each runtime environment implements this to provide sandboxed code execution
@@ -109,9 +109,13 @@ export interface ToolBinding {
109
109
  }
110
110
  export type { ToolExecutionContext };
111
111
  /**
112
- * Tool types that can be passed to Code Mode
112
+ * Server-side tool types that can be passed to Code Mode.
113
+ *
114
+ * Code Mode executes tools inside a server-managed sandbox. Client tools and
115
+ * bare tool definitions are intentionally excluded because they do not provide
116
+ * a server execution implementation for the sandbox binding.
113
117
  */
114
- export type CodeModeTool = ServerTool<any, any, any> | ToolDefinition<any, any, any>;
118
+ export type CodeModeTool = ServerTool<SchemaInput, SchemaInput, string, unknown>;
115
119
  /**
116
120
  * Configuration for createCodeModeTool
117
121
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai-code-mode",
3
- "version": "0.1.23",
3
+ "version": "0.2.0",
4
4
  "description": "Secure TypeScript Code Mode for TanStack AI agents to execute sandboxed tool orchestration programs.",
5
5
  "author": "",
6
6
  "license": "MIT",
@@ -46,12 +46,12 @@
46
46
  },
47
47
  "peerDependencies": {
48
48
  "zod": "^3.0.0 || ^4.0.0",
49
- "@tanstack/ai": "0.23.0"
49
+ "@tanstack/ai": "0.24.0"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@vitest/coverage-v8": "4.0.14",
53
53
  "zod": "^4.2.0",
54
- "@tanstack/ai": "0.23.0"
54
+ "@tanstack/ai": "0.24.0"
55
55
  },
56
56
  "scripts": {
57
57
  "build": "vite build",
@@ -43,31 +43,19 @@ export function toolToBinding(
43
43
  ? convertSchemaToJsonSchema(tool.outputSchema)
44
44
  : undefined
45
45
 
46
- // Get execute function
47
- // ServerTool has execute, ToolDefinition (without .server()) does not
48
- let execute: (
49
- args: unknown,
50
- context?: ToolExecutionContext,
51
- ) => Promise<unknown>
52
-
53
- if ('execute' in tool && typeof tool.execute === 'function') {
54
- const toolExecute = tool.execute
55
- execute = (args: unknown, context?: ToolExecutionContext) => {
56
- // Pass context to the underlying tool so it can emit custom events
57
- return Promise.resolve(toolExecute(args, context))
58
- }
59
- } else if ('__toolSide' in tool && tool.__toolSide === 'definition') {
60
- throw new Error(
61
- `Tool "${tool.name}" is a ToolDefinition without an execute function. ` +
62
- `Call .server(fn) to provide an implementation before using with Code Mode.`,
63
- )
64
- } else {
46
+ if (typeof tool.execute !== 'function') {
65
47
  throw new Error(
66
48
  `Tool "${tool.name}" does not have an execute function. ` +
67
- `Code Mode requires tools with implementations.`,
49
+ `Code Mode requires server tools with implementations.`,
68
50
  )
69
51
  }
70
52
 
53
+ const toolExecute = tool.execute
54
+ const execute = (args: unknown, context?: ToolExecutionContext) => {
55
+ // Pass context to the underlying tool so it can emit custom events
56
+ return Promise.resolve(toolExecute(args, context))
57
+ }
58
+
71
59
  return {
72
60
  name: `${prefix}${tool.name}`,
73
61
  description: tool.description,
@@ -86,7 +74,7 @@ export function toolToBinding(
86
74
  */
87
75
  export function createEventAwareBindings(
88
76
  bindings: Record<string, ToolBinding>,
89
- emitCustomEvent: (eventName: string, data: Record<string, any>) => void,
77
+ emitCustomEvent: ToolExecutionContext['emitCustomEvent'],
90
78
  ): Record<string, ToolBinding> {
91
79
  const wrapped: Record<string, ToolBinding> = {}
92
80
 
package/src/types.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type {
2
+ SchemaInput,
2
3
  ServerTool,
3
- ToolDefinition,
4
4
  ToolExecutionContext,
5
5
  } from '@tanstack/ai'
6
6
 
@@ -147,11 +147,13 @@ export type { ToolExecutionContext }
147
147
  // ============================================================================
148
148
 
149
149
  /**
150
- * Tool types that can be passed to Code Mode
150
+ * Server-side tool types that can be passed to Code Mode.
151
+ *
152
+ * Code Mode executes tools inside a server-managed sandbox. Client tools and
153
+ * bare tool definitions are intentionally excluded because they do not provide
154
+ * a server execution implementation for the sandbox binding.
151
155
  */
152
- export type CodeModeTool =
153
- | ServerTool<any, any, any>
154
- | ToolDefinition<any, any, any>
156
+ export type CodeModeTool = ServerTool<SchemaInput, SchemaInput, string, unknown>
155
157
 
156
158
  /**
157
159
  * Configuration for createCodeModeTool