@tanstack/ai-code-mode 0.2.13 → 0.3.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 (36) hide show
  1. package/package.json +3 -3
  2. package/skills/ai-code-mode/SKILL.md +79 -0
  3. package/src/create-code-mode-tool.ts +8 -2
  4. package/src/create-code-mode.ts +23 -13
  5. package/src/create-discovery-tool.ts +108 -0
  6. package/src/create-system-prompt.ts +25 -10
  7. package/src/index.ts +2 -0
  8. package/src/types.ts +25 -0
  9. package/dist/esm/agent-store.d.ts +0 -21
  10. package/dist/esm/agent-store.js +0 -29
  11. package/dist/esm/agent-store.js.map +0 -1
  12. package/dist/esm/bindings/tool-to-binding.d.ts +0 -25
  13. package/dist/esm/bindings/tool-to-binding.js +0 -94
  14. package/dist/esm/bindings/tool-to-binding.js.map +0 -1
  15. package/dist/esm/code-wrapper.d.ts +0 -9
  16. package/dist/esm/code-wrapper.js +0 -18
  17. package/dist/esm/code-wrapper.js.map +0 -1
  18. package/dist/esm/create-code-mode-tool.d.ts +0 -50
  19. package/dist/esm/create-code-mode-tool.js +0 -143
  20. package/dist/esm/create-code-mode-tool.js.map +0 -1
  21. package/dist/esm/create-code-mode.d.ts +0 -41
  22. package/dist/esm/create-code-mode.js +0 -12
  23. package/dist/esm/create-code-mode.js.map +0 -1
  24. package/dist/esm/create-system-prompt.d.ts +0 -24
  25. package/dist/esm/create-system-prompt.js +0 -66
  26. package/dist/esm/create-system-prompt.js.map +0 -1
  27. package/dist/esm/index.d.ts +0 -10
  28. package/dist/esm/index.js +0 -23
  29. package/dist/esm/index.js.map +0 -1
  30. package/dist/esm/strip-typescript.d.ts +0 -44
  31. package/dist/esm/strip-typescript.js +0 -49
  32. package/dist/esm/strip-typescript.js.map +0 -1
  33. package/dist/esm/type-generator/json-schema-to-ts.d.ts +0 -31
  34. package/dist/esm/type-generator/json-schema-to-ts.js +0 -100
  35. package/dist/esm/type-generator/json-schema-to-ts.js.map +0 -1
  36. package/dist/esm/types.d.ts +0 -216
@@ -1 +0,0 @@
1
- {"version":3,"file":"json-schema-to-ts.js","sources":["../../../src/type-generator/json-schema-to-ts.ts"],"sourcesContent":["import type { ToolBinding } from '../types'\n\n/**\n * Options for type stub generation\n */\nexport interface TypeGeneratorOptions {\n /**\n * Include JSDoc comments with descriptions\n * @default true\n */\n includeDescriptions?: boolean\n}\n\n/**\n * Generate TypeScript type stubs for all tool bindings\n *\n * These stubs are included in the LLM system prompt so it knows\n * the exact type signatures of available tools.\n *\n * Tool names match the actual function names injected into the sandbox.\n */\nexport function generateTypeStubs(\n bindings: Record<string, ToolBinding>,\n options: TypeGeneratorOptions = {},\n): string {\n const { includeDescriptions = true } = options\n\n const declarations: Array<string> = []\n\n for (const [name, binding] of Object.entries(bindings)) {\n const inputTypeName = `${capitalize(name)}Input`\n const outputTypeName = `${capitalize(name)}Output`\n\n // Generate input type\n const inputType = jsonSchemaToTypeScript(binding.inputSchema, inputTypeName)\n if (inputType.declaration) {\n declarations.push(inputType.declaration)\n }\n\n // Generate output type if present\n let outputTypeRef = 'unknown'\n if (binding.outputSchema) {\n const outputType = jsonSchemaToTypeScript(\n binding.outputSchema,\n outputTypeName,\n )\n if (outputType.declaration) {\n declarations.push(outputType.declaration)\n }\n outputTypeRef = outputType.name\n }\n\n // Generate function declaration matching the actual sandbox function name\n const description =\n includeDescriptions && binding.description\n ? `/** ${binding.description} */\\n`\n : ''\n\n declarations.push(\n `${description}declare function ${name}(input: ${inputType.name}): Promise<${outputTypeRef}>;`,\n )\n }\n\n return declarations.join('\\n\\n')\n}\n\ninterface TypeResult {\n name: string\n declaration: string\n}\n\n/**\n * Convert a JSON Schema to a TypeScript type\n *\n * Supports basic types: string, number, boolean, object, array\n */\nexport function jsonSchemaToTypeScript(\n schema: Record<string, unknown>,\n typeName: string,\n): TypeResult {\n const type = schemaToType(schema)\n\n // For object schemas with properties, create a named interface\n if (\n schema.type === 'object' &&\n schema.properties &&\n Object.keys(schema.properties).length > 0\n ) {\n return {\n name: typeName,\n declaration: `interface ${typeName} ${type}`,\n }\n }\n\n // For simple types or empty objects, create a type alias\n return {\n name: type,\n declaration: '',\n }\n}\n\n/**\n * Convert a JSON Schema to a TypeScript type string\n */\nfunction schemaToType(schema: Record<string, unknown>): string {\n if (typeof schema !== 'object') {\n return 'unknown'\n }\n\n const schemaType = schema.type\n\n // Handle basic types\n if (schemaType === 'string') return 'string'\n if (schemaType === 'number' || schemaType === 'integer') return 'number'\n if (schemaType === 'boolean') return 'boolean'\n if (schemaType === 'null') return 'null'\n\n // Handle arrays\n if (schemaType === 'array') {\n const items = schema.items as Record<string, unknown> | undefined\n const itemType = items ? schemaToType(items) : 'unknown'\n return `Array<${itemType}>`\n }\n\n // Handle objects with properties\n if (schemaType === 'object' && schema.properties) {\n const properties = schema.properties as Record<\n string,\n Record<string, unknown>\n >\n const required = new Set(\n (schema.required as Array<string> | undefined) ?? [],\n )\n\n const props = Object.entries(properties)\n .map(([key, propSchema]) => {\n const optional = required.has(key) ? '' : '?'\n const propType = schemaToType(propSchema)\n // Handle property names that need quoting\n const safeName = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(key)\n ? key\n : `\"${key}\"`\n return ` ${safeName}${optional}: ${propType};`\n })\n .join('\\n')\n\n return `{\\n${props}\\n}`\n }\n\n // Handle enums\n if (schema.enum) {\n const enumValues = schema.enum as Array<unknown>\n return enumValues.map((v) => JSON.stringify(v)).join(' | ')\n }\n\n // Handle union types (anyOf, oneOf)\n if (schema.anyOf || schema.oneOf) {\n const variants = (schema.anyOf || schema.oneOf) as Array<\n Record<string, unknown>\n >\n return variants.map((v) => schemaToType(v)).join(' | ')\n }\n\n // Handle type arrays (e.g., [\"string\", \"null\"])\n if (Array.isArray(schemaType)) {\n return schemaType\n .map((t) => {\n if (t === 'string') return 'string'\n if (t === 'number' || t === 'integer') return 'number'\n if (t === 'boolean') return 'boolean'\n if (t === 'null') return 'null'\n if (t === 'array') return 'Array<unknown>'\n if (t === 'object') return 'object'\n return 'unknown'\n })\n .join(' | ')\n }\n\n // Fallback for unknown schemas\n return 'unknown'\n}\n\n/**\n * Capitalize the first letter of a string\n */\nfunction capitalize(str: string): string {\n return str.charAt(0).toUpperCase() + str.slice(1)\n}\n"],"names":[],"mappings":"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"}
@@ -1,216 +0,0 @@
1
- import { SchemaInput, ServerTool, ToolExecutionContext } from '@tanstack/ai';
2
- /**
3
- * Interface for isolate/sandbox drivers
4
- * Each runtime environment implements this to provide sandboxed code execution
5
- */
6
- export interface IsolateDriver {
7
- /**
8
- * Create a new isolated execution context with tool bindings
9
- */
10
- createContext: (config: IsolateConfig) => Promise<IsolateContext>;
11
- }
12
- /**
13
- * Configuration for creating an isolate context
14
- */
15
- export interface IsolateConfig {
16
- /**
17
- * Tools transformed into callable bindings for the sandbox
18
- */
19
- bindings: Record<string, ToolBinding>;
20
- /**
21
- * Execution timeout in milliseconds (default: 30000)
22
- */
23
- timeout?: number;
24
- /**
25
- * Memory limit in MB (default: 128)
26
- */
27
- memoryLimit?: number;
28
- }
29
- /**
30
- * Isolated execution context with tool bindings injected
31
- */
32
- export interface IsolateContext {
33
- /**
34
- * Execute generated code and return results
35
- */
36
- execute: <T = unknown>(code: string) => Promise<ExecutionResult<T>>;
37
- /**
38
- * Clean up sandbox resources
39
- */
40
- dispose: () => Promise<void>;
41
- }
42
- /**
43
- * Result of code execution in the sandbox
44
- */
45
- export interface ExecutionResult<T = unknown> {
46
- /**
47
- * Whether execution completed without errors
48
- */
49
- success: boolean;
50
- /**
51
- * Return value from the executed code (if successful)
52
- */
53
- value?: T;
54
- /**
55
- * Normalized error information (if failed)
56
- */
57
- error?: NormalizedError;
58
- /**
59
- * Console output captured during execution
60
- */
61
- logs?: Array<string>;
62
- }
63
- /**
64
- * Normalized error format for cross-runtime compatibility
65
- */
66
- export interface NormalizedError {
67
- /**
68
- * Error name/type
69
- */
70
- name: string;
71
- /**
72
- * Error message
73
- */
74
- message: string;
75
- /**
76
- * Stack trace (if available)
77
- */
78
- stack?: string;
79
- /**
80
- * Error code (if available)
81
- */
82
- code?: string;
83
- }
84
- /**
85
- * A tool transformed into a format suitable for sandbox injection
86
- */
87
- export interface ToolBinding {
88
- /**
89
- * Unique tool identifier
90
- */
91
- name: string;
92
- /**
93
- * Human-readable description for the LLM
94
- */
95
- description: string;
96
- /**
97
- * JSON Schema for tool input parameters
98
- */
99
- inputSchema: Record<string, unknown>;
100
- /**
101
- * JSON Schema for tool output (optional)
102
- */
103
- outputSchema?: Record<string, unknown> | undefined;
104
- /**
105
- * The execute function that will be injected into the sandbox.
106
- * Accepts optional context for emitting custom events.
107
- */
108
- execute: (args: unknown, context?: ToolExecutionContext) => Promise<unknown>;
109
- }
110
- export type { ToolExecutionContext };
111
- /**
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.
117
- */
118
- export type CodeModeTool = ServerTool<SchemaInput, SchemaInput, string, unknown>;
119
- /**
120
- * Configuration for createCodeModeTool
121
- */
122
- export interface CodeModeToolConfig {
123
- /**
124
- * Isolate driver for sandboxed code execution
125
- */
126
- driver: IsolateDriver;
127
- /**
128
- * Tools to expose as external_* functions in the sandbox
129
- */
130
- tools: Array<CodeModeTool>;
131
- /**
132
- * Execution timeout in milliseconds (default: 30000)
133
- */
134
- timeout?: number;
135
- /**
136
- * Memory limit for isolate in MB (default: 128)
137
- */
138
- memoryLimit?: number;
139
- /**
140
- * Optional function to get additional bindings dynamically.
141
- * Called at execution time (each execute_typescript call) to get current skill bindings.
142
- * These are merged with the static external_* bindings.
143
- *
144
- * @returns Record of skill bindings with skill_ prefix
145
- *
146
- * @example
147
- * ```typescript
148
- * getSkillBindings: async () => {
149
- * const skills = await storage.loadAll()
150
- * return skillsToBindings(skills, 'skill_')
151
- * }
152
- * ```
153
- */
154
- getSkillBindings?: () => Promise<Record<string, ToolBinding>>;
155
- /**
156
- * Optional escape hatch to swap out the TypeScript-stripping step.
157
- *
158
- * Receives the raw model-generated code and must return runnable JavaScript
159
- * with all TypeScript syntax removed. Defaults to the built-in
160
- * {@link stripTypeScript}, which uses sucrase and is safe to bundle for
161
- * browsers and edge runtimes (Cloudflare Workers/Pages etc.).
162
- *
163
- * Provide your own only to trade the edge-safe default for a faster
164
- * Node-only transpiler. A custom transpiler MUST tolerate top-level `return`
165
- * and `await` in its input (the default wraps the code in an async function
166
- * internally to allow this).
167
- *
168
- * NOTE: This only affects `createCodeModeTool`. The skills helpers
169
- * (`skillsToTools`, `codeModeWithSkills` in `@tanstack/ai-code-mode-skills`)
170
- * call the exported `stripTypeScript` directly, so they ignore this hook — but
171
- * they still get the edge-safe sucrase default, so #487 is fixed for them too;
172
- * they just can't be pointed at a different transpiler.
173
- *
174
- * @example
175
- * ```typescript
176
- * // Node-only fast path using esbuild (NOT edge-safe — Node only). esbuild
177
- * // rejects top-level `return`, so reuse the same async-function wrapper the
178
- * // default uses, then slice the body back out. `keepNames: false` stops
179
- * // esbuild injecting `__name()` helpers the sandbox can't resolve.
180
- * import { transformSync } from 'esbuild'
181
- * transpile: (code) => {
182
- * const out = transformSync(`async function _w(){\n${code}\n}`, {
183
- * loader: 'ts',
184
- * keepNames: false,
185
- * }).code
186
- * return out.slice(out.indexOf('{') + 1, out.lastIndexOf('}'))
187
- * }
188
- * ```
189
- */
190
- transpile?: (code: string) => string | Promise<string>;
191
- }
192
- /**
193
- * Result returned by the execute_typescript tool
194
- */
195
- export interface CodeModeToolResult {
196
- /**
197
- * Whether execution completed without errors
198
- */
199
- success: boolean;
200
- /**
201
- * Return value from the executed code (if successful)
202
- */
203
- result?: unknown;
204
- /**
205
- * Console output captured during execution
206
- */
207
- logs?: Array<string>;
208
- /**
209
- * Error details if execution failed
210
- */
211
- error?: {
212
- message: string;
213
- name?: string | undefined;
214
- line?: number | undefined;
215
- } | undefined;
216
- }