@cloudflare/codemode 0.0.8 → 0.1.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/CHANGELOG.md +16 -0
- package/README.md +174 -247
- package/dist/ai.d.ts +27 -27
- package/dist/ai.js +67 -136
- package/dist/ai.js.map +1 -1
- package/dist/executor-Czw9jKZH.d.ts +96 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +109 -0
- package/dist/index.js.map +1 -0
- package/dist/types-B9g5T2nd.js +138 -0
- package/dist/types-B9g5T2nd.js.map +1 -0
- package/e2e/codemode.spec.ts +124 -0
- package/e2e/playwright.config.ts +24 -0
- package/e2e/worker.ts +144 -0
- package/e2e/wrangler.jsonc +14 -0
- package/package.json +15 -4
- package/scripts/build.ts +1 -2
- package/src/ai.ts +1 -247
- package/src/executor.ts +170 -0
- package/src/index.ts +13 -0
- package/src/tests/cloudflare-test.d.ts +5 -0
- package/src/tests/executor.test.ts +224 -0
- package/src/tests/tool.test.ts +454 -0
- package/src/tests/tsconfig.json +10 -0
- package/src/tests/types.test.ts +171 -0
- package/src/tool.ts +131 -0
- package/src/types.ts +202 -0
- package/vitest.config.ts +17 -0
- package/wrangler.jsonc +16 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @cloudflare/codemode
|
|
2
2
|
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#879](https://github.com/cloudflare/agents/pull/879) [`90e54da`](https://github.com/cloudflare/agents/commit/90e54dab21f7c2c783aac117693918765e8b254b) Thanks [@mattzcarey](https://github.com/mattzcarey)! - Remove experimental_codemode() and CodeModeProxy. Replace with createCodeTool() from @cloudflare/codemode/ai which returns a standard AI SDK Tool. The package no longer owns an LLM call or model choice. Users call streamText/generateText with their own model and pass the codemode tool.
|
|
8
|
+
|
|
9
|
+
The AI-dependent export (createCodeTool) is now at @cloudflare/codemode/ai. The root export (@cloudflare/codemode) contains the executor, type generation, and utilities which do not require the ai peer dependency.
|
|
10
|
+
|
|
11
|
+
ToolDispatcher (extends RpcTarget) replaces CodeModeProxy (extends WorkerEntrypoint) for dispatching tool calls from the sandbox back to the host. It is passed as a parameter to the dynamic worker's evaluate() method instead of being injected as an env binding, removing the need for CodeModeProxy and globalOutbound service bindings. Only a WorkerLoader binding is required now. globalOutbound on DynamicWorkerExecutor defaults to null which blocks fetch/connect at the runtime level. New Executor interface (execute(code, fns) => ExecuteResult) allows custom sandbox implementations. DynamicWorkerExecutor is the Cloudflare Workers implementation. Console output captured in ExecuteResult.logs. Configurable execution timeout.
|
|
12
|
+
|
|
13
|
+
AST-based code normalization via acorn replaces regex. sanitizeToolName() exported for converting MCP-style tool names to valid JS identifiers.
|
|
14
|
+
|
|
15
|
+
### Patch Changes
|
|
16
|
+
|
|
17
|
+
- [#954](https://github.com/cloudflare/agents/pull/954) [`943c407`](https://github.com/cloudflare/agents/commit/943c4070992bb836625abb5bf4e3271a6f52f7a2) Thanks [@threepointone](https://github.com/threepointone)! - update dependencies
|
|
18
|
+
|
|
3
19
|
## 0.0.8
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,75 +1,33 @@
|
|
|
1
|
-
|
|
1
|
+
# `@cloudflare/codemode`
|
|
2
2
|
|
|
3
|
-
Instead of asking LLMs to call tools directly, Code Mode lets them write executable code that orchestrates multiple operations.
|
|
3
|
+
Instead of asking LLMs to call tools directly, Code Mode lets them write executable code that orchestrates multiple operations. LLMs are better at writing code than calling tools — they've seen millions of lines of real-world TypeScript but only contrived tool-calling examples.
|
|
4
4
|
|
|
5
|
-
Code Mode converts your tools
|
|
5
|
+
Code Mode converts your tools into TypeScript APIs and executes the generated code in secure, isolated sandboxes with millisecond startup times.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
> **Experimental** — may have breaking changes. Use with caution in production.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
---
|
|
12
|
-
|
|
13
|
-
### 🌱 Installation
|
|
9
|
+
## Installation
|
|
14
10
|
|
|
15
11
|
```sh
|
|
16
|
-
npm install @cloudflare/codemode agents ai
|
|
12
|
+
npm install @cloudflare/codemode agents ai zod
|
|
17
13
|
```
|
|
18
14
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Transform your tool-calling agent into a code-generating one:
|
|
15
|
+
## Quick Start
|
|
22
16
|
|
|
23
|
-
|
|
17
|
+
`createCodeTool` takes your tools and an executor, and returns a single AI SDK tool that lets the LLM write code instead of making individual tool calls.
|
|
24
18
|
|
|
25
19
|
```ts
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
20
|
+
import { createCodeTool } from "@cloudflare/codemode/ai";
|
|
21
|
+
import { DynamicWorkerExecutor } from "@cloudflare/codemode";
|
|
22
|
+
import { streamText, tool } from "ai";
|
|
28
23
|
import { z } from "zod";
|
|
29
24
|
|
|
30
|
-
|
|
31
|
-
model: openai("gpt-4o"),
|
|
32
|
-
messages,
|
|
33
|
-
tools: {
|
|
34
|
-
getWeather: tool({
|
|
35
|
-
description: "Get weather for a location",
|
|
36
|
-
inputSchema: z.object({ location: z.string() }),
|
|
37
|
-
execute: async ({ location }) => {
|
|
38
|
-
return `Weather in ${location}: 72°F, sunny`;
|
|
39
|
-
}
|
|
40
|
-
}),
|
|
41
|
-
sendEmail: tool({
|
|
42
|
-
description: "Send an email",
|
|
43
|
-
inputSchema: z.object({
|
|
44
|
-
to: z.string(),
|
|
45
|
-
subject: z.string(),
|
|
46
|
-
body: z.string()
|
|
47
|
-
}),
|
|
48
|
-
execute: async ({ to, subject, body }) => {
|
|
49
|
-
// Send email logic
|
|
50
|
-
return `Email sent to ${to}`;
|
|
51
|
-
}
|
|
52
|
-
})
|
|
53
|
-
}
|
|
54
|
-
});
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
#### After (With Code Mode)
|
|
58
|
-
|
|
59
|
-
```ts
|
|
60
|
-
import { experimental_codemode as codemode } from "@cloudflare/codemode/ai";
|
|
61
|
-
import { streamText } from "ai";
|
|
62
|
-
import { tool } from "ai";
|
|
63
|
-
import { z } from "zod";
|
|
64
|
-
|
|
65
|
-
// Define your tools as usual
|
|
25
|
+
// 1. Define your tools using the AI SDK tool() wrapper
|
|
66
26
|
const tools = {
|
|
67
27
|
getWeather: tool({
|
|
68
28
|
description: "Get weather for a location",
|
|
69
29
|
inputSchema: z.object({ location: z.string() }),
|
|
70
|
-
execute: async ({ location }) => {
|
|
71
|
-
return `Weather in ${location}: 72°F, sunny`;
|
|
72
|
-
}
|
|
30
|
+
execute: async ({ location }) => `Weather in ${location}: 72°F, sunny`
|
|
73
31
|
}),
|
|
74
32
|
sendEmail: tool({
|
|
75
33
|
description: "Send an email",
|
|
@@ -78,259 +36,228 @@ const tools = {
|
|
|
78
36
|
subject: z.string(),
|
|
79
37
|
body: z.string()
|
|
80
38
|
}),
|
|
81
|
-
execute: async ({ to, subject, body }) => {
|
|
82
|
-
// Send email logic
|
|
83
|
-
return `Email sent to ${to}`;
|
|
84
|
-
}
|
|
39
|
+
execute: async ({ to, subject, body }) => `Email sent to ${to}`
|
|
85
40
|
})
|
|
86
41
|
};
|
|
87
42
|
|
|
88
|
-
//
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
prompt: "You are a helpful assistant...",
|
|
92
|
-
tools,
|
|
93
|
-
globalOutbound: env.globalOutbound,
|
|
94
|
-
loader: env.LOADER,
|
|
95
|
-
proxy: this.ctx.exports.CodeModeProxy({
|
|
96
|
-
props: {
|
|
97
|
-
binding: "MyAgent",
|
|
98
|
-
name: this.name,
|
|
99
|
-
callback: "callTool"
|
|
100
|
-
}
|
|
101
|
-
})
|
|
43
|
+
// 2. Create an executor (runs code in an isolated Worker)
|
|
44
|
+
const executor = new DynamicWorkerExecutor({
|
|
45
|
+
loader: env.LOADER
|
|
102
46
|
});
|
|
103
47
|
|
|
104
|
-
//
|
|
48
|
+
// 3. Create the codemode tool
|
|
49
|
+
const codemode = createCodeTool({ tools, executor });
|
|
50
|
+
|
|
51
|
+
// 4. Use it with streamText — the LLM writes code that calls your tools
|
|
105
52
|
const result = streamText({
|
|
106
|
-
model
|
|
107
|
-
system:
|
|
53
|
+
model,
|
|
54
|
+
system: "You are a helpful assistant.",
|
|
108
55
|
messages,
|
|
109
|
-
tools:
|
|
56
|
+
tools: { codemode }
|
|
110
57
|
});
|
|
111
58
|
```
|
|
112
59
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
### 🏰 Configuration
|
|
116
|
-
|
|
117
|
-
Define the required bindings in your `wrangler.toml`:
|
|
60
|
+
The LLM sees a typed `codemode` object and writes code like:
|
|
118
61
|
|
|
119
|
-
```
|
|
120
|
-
{
|
|
121
|
-
|
|
122
|
-
"
|
|
123
|
-
{
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
"entrypoint": "globalOutbound"
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
"binding": "CodeModeProxy",
|
|
135
|
-
"service": "your-service",
|
|
136
|
-
"entrypoint": "CodeModeProxy"
|
|
137
|
-
}
|
|
138
|
-
]
|
|
139
|
-
}
|
|
62
|
+
```js
|
|
63
|
+
async () => {
|
|
64
|
+
const weather = await codemode.getWeather({ location: "London" });
|
|
65
|
+
if (weather.includes("sunny")) {
|
|
66
|
+
await codemode.sendEmail({
|
|
67
|
+
to: "team@example.com",
|
|
68
|
+
subject: "Nice day!",
|
|
69
|
+
body: `It's ${weather}`
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return { weather, notified: true };
|
|
73
|
+
};
|
|
140
74
|
```
|
|
141
75
|
|
|
142
|
-
|
|
76
|
+
## Architecture
|
|
143
77
|
|
|
144
|
-
|
|
78
|
+
### How it works
|
|
145
79
|
|
|
146
|
-
```
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
80
|
+
```
|
|
81
|
+
┌─────────────┐ ┌──────────────────────────────────────┐
|
|
82
|
+
│ │ │ Dynamic Worker (isolated sandbox) │
|
|
83
|
+
│ Host │ RPC │ │
|
|
84
|
+
│ Worker │◄──────►│ LLM-generated code runs here │
|
|
85
|
+
│ │ │ codemode.myTool() → dispatcher.call()│
|
|
86
|
+
│ ToolDispatcher │ │
|
|
87
|
+
│ holds tool fns │ fetch() blocked by default │
|
|
88
|
+
└─────────────┘ └──────────────────────────────────────┘
|
|
89
|
+
```
|
|
151
90
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const { prompt, tools: wrappedTools } = await codemode({
|
|
160
|
-
model: openai("gpt-4o"), // optional, defaults to openai("gpt-4.1")
|
|
161
|
-
prompt: "You are a helpful assistant...",
|
|
162
|
-
tools: allTools,
|
|
163
|
-
globalOutbound: env.globalOutbound,
|
|
164
|
-
loader: env.LOADER,
|
|
165
|
-
proxy: this.ctx.exports.CodeModeProxy({
|
|
166
|
-
props: {
|
|
167
|
-
binding: "CodeModeAgent",
|
|
168
|
-
name: this.name,
|
|
169
|
-
callback: "callTool"
|
|
170
|
-
}
|
|
171
|
-
})
|
|
172
|
-
});
|
|
91
|
+
1. `createCodeTool` generates TypeScript type definitions from your tools and builds a description the LLM can read
|
|
92
|
+
2. The LLM writes an async arrow function that calls `codemode.toolName(args)`
|
|
93
|
+
3. Code is normalized via AST parsing (acorn) and sent to the executor
|
|
94
|
+
4. `DynamicWorkerExecutor` spins up an isolated Worker via `WorkerLoader`
|
|
95
|
+
5. Inside the sandbox, a `Proxy` intercepts `codemode.*` calls and routes them back to the host via Workers RPC (`ToolDispatcher extends RpcTarget`)
|
|
96
|
+
6. Console output is captured and returned alongside the result
|
|
173
97
|
|
|
174
|
-
|
|
175
|
-
model: openai("gpt-4o"),
|
|
176
|
-
system: prompt,
|
|
177
|
-
messages: await convertToModelMessages(this.messages),
|
|
178
|
-
tools: wrappedTools
|
|
179
|
-
});
|
|
98
|
+
### Network isolation
|
|
180
99
|
|
|
181
|
-
|
|
182
|
-
}
|
|
100
|
+
External `fetch()` and `connect()` are **blocked by default** — enforced at the Workers runtime level via `globalOutbound: null`. Sandboxed code can only interact with the host through `codemode.*` tool calls.
|
|
183
101
|
|
|
184
|
-
|
|
185
|
-
return this.tools[functionName]?.execute?.(args, {
|
|
186
|
-
abortSignal: new AbortController().signal,
|
|
187
|
-
toolCallId: "codemode",
|
|
188
|
-
messages: []
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
}
|
|
102
|
+
To allow controlled outbound access, pass a `Fetcher`:
|
|
192
103
|
|
|
193
|
-
|
|
104
|
+
```ts
|
|
105
|
+
const executor = new DynamicWorkerExecutor({
|
|
106
|
+
loader: env.LOADER,
|
|
107
|
+
globalOutbound: null // default — fully isolated
|
|
108
|
+
// globalOutbound: env.MY_OUTBOUND_SERVICE, // route through a Fetcher
|
|
109
|
+
});
|
|
194
110
|
```
|
|
195
111
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
Code Mode enables complex workflows that chain multiple operations:
|
|
112
|
+
## The Executor Interface
|
|
199
113
|
|
|
200
|
-
|
|
201
|
-
// Example generated code orchestrating multiple MCP servers:
|
|
202
|
-
async function executeTask() {
|
|
203
|
-
const files = await codemode.listFiles({ path: "/projects" });
|
|
204
|
-
const recentProject = files
|
|
205
|
-
.filter((f) => f.type === "directory")
|
|
206
|
-
.sort((a, b) => new Date(b.modified) - new Date(a.modified))[0];
|
|
114
|
+
The `Executor` interface is deliberately minimal — implement it to run code in any sandbox:
|
|
207
115
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
title: `Review project: ${recentProject.name}`,
|
|
216
|
-
priority: "high"
|
|
217
|
-
});
|
|
218
|
-
await codemode.sendEmail({
|
|
219
|
-
to: "team@company.com",
|
|
220
|
-
subject: "Project Review Needed"
|
|
221
|
-
});
|
|
222
|
-
}
|
|
116
|
+
```ts
|
|
117
|
+
interface Executor {
|
|
118
|
+
execute(
|
|
119
|
+
code: string,
|
|
120
|
+
fns: Record<string, (...args: unknown[]) => Promise<unknown>>
|
|
121
|
+
): Promise<ExecuteResult>;
|
|
122
|
+
}
|
|
223
123
|
|
|
224
|
-
|
|
124
|
+
interface ExecuteResult {
|
|
125
|
+
result: unknown;
|
|
126
|
+
error?: string;
|
|
127
|
+
logs?: string[];
|
|
225
128
|
}
|
|
226
129
|
```
|
|
227
130
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
Code runs in isolated Workers with millisecond startup times. No network access by default - only through explicit bindings. API keys are hidden in bindings, preventing leaks.
|
|
131
|
+
`DynamicWorkerExecutor` is the Cloudflare Workers implementation, but you can build your own for Node VM, QuickJS, containers, or anything else.
|
|
231
132
|
|
|
232
133
|
```ts
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
134
|
+
// Example: a simple Node VM executor
|
|
135
|
+
class NodeVMExecutor implements Executor {
|
|
136
|
+
async execute(code, fns): Promise<ExecuteResult> {
|
|
137
|
+
try {
|
|
138
|
+
const fn = new AsyncFunction("codemode", `return await (${code})()`);
|
|
139
|
+
const result = await fn(fns);
|
|
140
|
+
return { result };
|
|
141
|
+
} catch (err) {
|
|
142
|
+
return { result: undefined, error: err.message };
|
|
238
143
|
}
|
|
239
|
-
return fetch(input, init);
|
|
240
144
|
}
|
|
241
|
-
}
|
|
145
|
+
}
|
|
242
146
|
```
|
|
243
147
|
|
|
244
|
-
|
|
148
|
+
## Configuration
|
|
245
149
|
|
|
246
|
-
|
|
150
|
+
### Wrangler bindings
|
|
247
151
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
152
|
+
```jsonc
|
|
153
|
+
// wrangler.jsonc
|
|
154
|
+
{
|
|
155
|
+
"worker_loaders": [{ "binding": "LOADER" }],
|
|
156
|
+
"compatibility_flags": ["nodejs_compat"]
|
|
157
|
+
}
|
|
158
|
+
```
|
|
251
159
|
|
|
252
|
-
|
|
160
|
+
### DynamicWorkerExecutor options
|
|
253
161
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
};
|
|
162
|
+
| Option | Type | Default | Description |
|
|
163
|
+
| ---------------- | ----------------- | -------- | ------------------------------------------------------------ |
|
|
164
|
+
| `loader` | `WorkerLoader` | required | Worker Loader binding from `env.LOADER` |
|
|
165
|
+
| `timeout` | `number` | `30000` | Execution timeout in ms |
|
|
166
|
+
| `globalOutbound` | `Fetcher \| null` | `null` | Network access control. `null` = blocked, `Fetcher` = routed |
|
|
261
167
|
|
|
262
|
-
|
|
263
|
-
```
|
|
168
|
+
### createCodeTool options
|
|
264
169
|
|
|
265
|
-
|
|
170
|
+
| Option | Type | Default | Description |
|
|
171
|
+
| ------------- | ---------------------------- | -------------- | ------------------------------------------------------ |
|
|
172
|
+
| `tools` | `ToolSet \| ToolDescriptors` | required | Your tools (AI SDK `tool()` or raw descriptors) |
|
|
173
|
+
| `executor` | `Executor` | required | Where to run the generated code |
|
|
174
|
+
| `description` | `string` | auto-generated | Custom tool description. Use `{{types}}` for type defs |
|
|
266
175
|
|
|
267
|
-
|
|
268
|
-
proxy: this.ctx.exports.CodeModeProxy({
|
|
269
|
-
props: {
|
|
270
|
-
binding: "YourAgentClass",
|
|
271
|
-
name: this.name,
|
|
272
|
-
callback: "callTool"
|
|
273
|
-
}
|
|
274
|
-
});
|
|
275
|
-
```
|
|
176
|
+
## Agent Integration
|
|
276
177
|
|
|
277
|
-
|
|
178
|
+
The user sends a message, the agent passes it to an LLM with the codemode tool, and the LLM writes and executes code to fulfill the request.
|
|
278
179
|
|
|
279
|
-
|
|
180
|
+
```ts
|
|
181
|
+
import { Agent } from "agents";
|
|
182
|
+
import { createCodeTool } from "@cloudflare/codemode/ai";
|
|
183
|
+
import { DynamicWorkerExecutor } from "@cloudflare/codemode";
|
|
184
|
+
import { streamText, convertToModelMessages, stepCountIs } from "ai";
|
|
280
185
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
186
|
+
export class MyAgent extends Agent<Env, State> {
|
|
187
|
+
async onChatMessage() {
|
|
188
|
+
const executor = new DynamicWorkerExecutor({
|
|
189
|
+
loader: this.env.LOADER
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
const codemode = createCodeTool({
|
|
193
|
+
tools: myTools,
|
|
194
|
+
executor
|
|
195
|
+
});
|
|
284
196
|
|
|
285
|
-
|
|
197
|
+
const result = streamText({
|
|
198
|
+
model,
|
|
199
|
+
system: "You are a helpful assistant.",
|
|
200
|
+
messages: await convertToModelMessages(this.state.messages),
|
|
201
|
+
tools: { codemode },
|
|
202
|
+
stopWhen: stepCountIs(10)
|
|
203
|
+
});
|
|
286
204
|
|
|
287
|
-
|
|
205
|
+
// Stream response back to client...
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
```
|
|
288
209
|
|
|
289
|
-
|
|
210
|
+
### With MCP tools
|
|
290
211
|
|
|
291
|
-
|
|
212
|
+
MCP tools work the same way — just merge them into the tool set:
|
|
292
213
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
214
|
+
```ts
|
|
215
|
+
const codemode = createCodeTool({
|
|
216
|
+
tools: {
|
|
217
|
+
...myTools,
|
|
218
|
+
...this.mcp.getAITools()
|
|
219
|
+
},
|
|
220
|
+
executor
|
|
221
|
+
});
|
|
222
|
+
```
|
|
299
223
|
|
|
300
|
-
|
|
224
|
+
## Utilities
|
|
301
225
|
|
|
302
|
-
|
|
303
|
-
- `tools: ToolSet` - Wrapped tools (single "codemode" tool)
|
|
226
|
+
### `generateTypes(tools)`
|
|
304
227
|
|
|
305
|
-
|
|
228
|
+
Generates TypeScript type definitions from your tools. Used internally by `createCodeTool` but exported for custom use (e.g. displaying types in a frontend).
|
|
306
229
|
|
|
307
|
-
|
|
230
|
+
```ts
|
|
231
|
+
import { generateTypes } from "@cloudflare/codemode";
|
|
308
232
|
|
|
309
|
-
|
|
233
|
+
const types = generateTypes(myTools);
|
|
234
|
+
// Returns TypeScript declarations like:
|
|
235
|
+
// type CreateProjectInput = { name: string; description?: string }
|
|
236
|
+
// declare const codemode: { createProject: (input: CreateProjectInput) => Promise<...>; }
|
|
237
|
+
```
|
|
310
238
|
|
|
311
|
-
|
|
312
|
-
- `name: string` - Agent instance name
|
|
313
|
-
- `callback: string` - Method name to call for tool execution
|
|
239
|
+
### `sanitizeToolName(name)`
|
|
314
240
|
|
|
315
|
-
|
|
241
|
+
Converts tool names into valid JavaScript identifiers. Handles hyphens, dots, digits, reserved words.
|
|
316
242
|
|
|
317
|
-
|
|
243
|
+
```ts
|
|
244
|
+
import { sanitizeToolName } from "@cloudflare/codemode";
|
|
318
245
|
|
|
319
|
-
|
|
246
|
+
sanitizeToolName("my-tool"); // "my_tool"
|
|
247
|
+
sanitizeToolName("3d-render"); // "_3d_render"
|
|
248
|
+
sanitizeToolName("delete"); // "delete_"
|
|
249
|
+
```
|
|
320
250
|
|
|
321
|
-
|
|
322
|
-
- **Requires Cloudflare Workers**: Uses Worker Loader API (beta)
|
|
323
|
-
- **JavaScript Only**: Python support planned
|
|
251
|
+
## Limitations
|
|
324
252
|
|
|
325
|
-
|
|
253
|
+
- **Tool approval (`needsApproval`) is not supported yet.** Tools with `needsApproval: true` execute immediately inside the sandbox without pausing for approval. Support for approval flows within codemode is planned. For now, do not pass approval-required tools to `createCodeTool` — use them through standard AI SDK tool calling instead.
|
|
254
|
+
- Requires Cloudflare Workers environment for `DynamicWorkerExecutor`
|
|
255
|
+
- Limited to JavaScript execution
|
|
326
256
|
|
|
327
|
-
|
|
257
|
+
## Examples
|
|
328
258
|
|
|
329
|
-
|
|
330
|
-
2. Ensure your changes align with the package's goals
|
|
331
|
-
3. Include tests for new features
|
|
332
|
-
4. Update documentation as needed
|
|
259
|
+
- [`examples/codemode/`](../../examples/codemode/) — Full working example with task management tools
|
|
333
260
|
|
|
334
|
-
|
|
261
|
+
## License
|
|
335
262
|
|
|
336
|
-
MIT
|
|
263
|
+
MIT
|
package/dist/ai.d.ts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { i as Executor, s as ToolDescriptors } from "./executor-Czw9jKZH.js";
|
|
2
|
+
import { Tool, ToolSet } from "ai";
|
|
3
|
+
import { z } from "zod";
|
|
3
4
|
|
|
4
|
-
//#region src/
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
> {
|
|
13
|
-
callFunction(options: {
|
|
14
|
-
functionName: string;
|
|
15
|
-
args: unknown[];
|
|
16
|
-
}): Promise<any>;
|
|
5
|
+
//#region src/tool.d.ts
|
|
6
|
+
interface CreateCodeToolOptions {
|
|
7
|
+
tools: ToolDescriptors | ToolSet;
|
|
8
|
+
executor: Executor;
|
|
9
|
+
/**
|
|
10
|
+
* Custom tool description. Use {{types}} as a placeholder for the generated type definitions.
|
|
11
|
+
*/
|
|
12
|
+
description?: string;
|
|
17
13
|
}
|
|
18
|
-
declare
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
declare const codeSchema: z.ZodObject<
|
|
15
|
+
{
|
|
16
|
+
code: z.ZodString;
|
|
17
|
+
},
|
|
18
|
+
z.core.$strip
|
|
19
|
+
>;
|
|
20
|
+
type CodeInput = z.infer<typeof codeSchema>;
|
|
21
|
+
type CodeOutput = {
|
|
22
|
+
code: string;
|
|
23
|
+
result: unknown;
|
|
24
|
+
logs?: string[];
|
|
25
|
+
};
|
|
26
|
+
declare function createCodeTool(
|
|
27
|
+
options: CreateCodeToolOptions
|
|
28
|
+
): Tool<CodeInput, CodeOutput>;
|
|
29
29
|
//#endregion
|
|
30
|
-
export {
|
|
30
|
+
export { type CreateCodeToolOptions, createCodeTool };
|
|
31
31
|
//# sourceMappingURL=ai.d.ts.map
|