Skip to content

Commit d01bc34

Browse files
mattzcareyaron-cf
andcommitted
computer: Add pi-ai and TanStack AI tool sets
Split each tool into a framework-neutral core under tools/common (schema, description, executor; zod only) and an adapter per agent library. tools/ai-sdk wraps the core with `tool()` from `ai`; tools/pi-ai and tools/tanstack-ai build their own shapes from the same core without importing their libraries, so each entry point pulls in only what it uses. The exec core is the one #181 and #182 settled on: `exec` takes a backend map, every Workspace backend is offered by default, `backend` appears only when there is a choice, and `input` only when a backend is callable. All three tool sets resolve options through the same resolveToolOptions, so they offer the same tools. The pi and TanStack adapters come from #149. Co-authored-by: aron <263346377+aron-cf@users.noreply.github.com>
1 parent 0970232 commit d01bc34

42 files changed

Lines changed: 2526 additions & 662 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎packages/computer/package.json‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@
5555
"types": "./dist/tools/ai-sdk.d.ts",
5656
"import": "./dist/tools/ai-sdk.js"
5757
},
58+
"./tools/pi-ai": {
59+
"types": "./dist/tools/pi-ai.d.ts",
60+
"import": "./dist/tools/pi-ai.js"
61+
},
62+
"./tools/tanstack-ai": {
63+
"types": "./dist/tools/tanstack-ai.d.ts",
64+
"import": "./dist/tools/tanstack-ai.js"
65+
},
5866
"./backends/container": {
5967
"types": "./dist/backends/container/index.d.ts",
6068
"import": "./dist/backends/container/index.js"

‎packages/computer/rolldown.config.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ export default defineConfig({
3131
"artifacts/index": "src/artifacts/index.ts",
3232
"assets/index": "src/assets/index.ts",
3333
"tools/index": "src/tools/index.ts",
34-
"tools/ai-sdk": "src/tools/ai-sdk.ts",
34+
"tools/ai-sdk": "src/tools/ai-sdk/index.ts",
35+
"tools/pi-ai": "src/tools/pi-ai/index.ts",
36+
"tools/tanstack-ai": "src/tools/tanstack-ai/index.ts",
3537
"modules/container": "src/modules/container.ts",
3638
"modules/git": "src/modules/git.ts",
3739
"modules/artifacts": "src/modules/artifacts.ts",

‎packages/computer/src/client.test.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { WorkerJavaScriptBackend } from "./backends/worker-javascript/worker-jav
1515
import { getWorkspace, type WorkspaceClient } from "./client.js";
1616
import type { WorkspaceBackendInfo } from "./runtime/runtime.js";
1717
import type { WorkspaceModuleBackend } from "./runtime/types.js";
18-
import { createAITools } from "./tools/ai-sdk.js";
18+
import { createAITools } from "./tools/ai-sdk/index.js";
1919
import { WORKSPACE, type WorkspaceStubHost } from "./with-workspace.js";
2020
import { type ThinkWorkspaceCompatibility, Workspace } from "./workspace.js";
2121

‎packages/computer/src/tools/ai-sdk.ts‎

Lines changed: 0 additions & 95 deletions
This file was deleted.

packages/computer/src/tools/ai-sdk.test.ts renamed to packages/computer/src/tools/ai-sdk/index.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { SQLiteTestStorage } from "@cloudflare/dofs/testing";
22
import { describe, expect, it } from "vitest";
33
import { z } from "zod";
4-
import { WorkerJavaScriptBackend } from "../backends/worker-javascript/worker-javascript.js";
5-
import { createGitModule } from "../modules/git.js";
6-
import type { WorkspaceRuntimeExecHandle, WorkspaceRuntimeResult } from "../runtime/types.js";
7-
import { Workspace } from "../workspace.js";
8-
import { createAITools } from "./ai-sdk.js";
4+
import { WorkerJavaScriptBackend } from "../../backends/worker-javascript/worker-javascript.js";
5+
import { createGitModule } from "../../modules/git.js";
6+
import type { WorkspaceRuntimeExecHandle, WorkspaceRuntimeResult } from "../../runtime/types.js";
7+
import { Workspace } from "../../workspace.js";
98
import {
109
createDeleteTool,
1110
createEditTool,
@@ -15,7 +14,8 @@ import {
1514
createWriteTool,
1615
type FileStore,
1716
WorkspaceFileStore,
18-
} from "./index.js";
17+
} from "../index.js";
18+
import { createAITools } from "./index.js";
1919

2020
const toolOptions = { toolCallId: "test-call", messages: [] };
2121

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import type { ToolSet } from "ai";
2+
import { type CreateToolsOptions, resolveToolOptions } from "../common/options.js";
3+
import type { PublishWorkspaceLike } from "../common/publish.js";
4+
import {
5+
createDeleteTool,
6+
createEditTool,
7+
createExecTool,
8+
createFindTool,
9+
createGrepTool,
10+
createListTool,
11+
createPublishTool,
12+
createReadTool,
13+
createWriteTool,
14+
} from "./tools.js";
15+
16+
/** Options for {@link createAITools}. */
17+
export type CreateAIToolsOptions = CreateToolsOptions;
18+
19+
export {
20+
createDeleteTool,
21+
createEditTool,
22+
createExecTool,
23+
createFindTool,
24+
createGrepTool,
25+
createListTool,
26+
createPublishTool,
27+
createReadTool,
28+
createWriteTool,
29+
} from "./tools.js";
30+
31+
/**
32+
* Build the AI SDK tool set for a Workspace: `read`, `ls`, `find`, and
33+
* `grep`, plus `write`, `edit`, `delete`, `exec`, and `publish` unless
34+
* the set is read-only. `exec` offers every backend the Workspace has
35+
* unless `exec` picks them.
36+
*
37+
* @param options - The Workspace and per-tool options.
38+
* @returns An AI SDK `ToolSet` for `generateText`, `streamText`, or an agent's `getTools()`.
39+
*/
40+
export function createAITools(options: CreateAIToolsOptions): ToolSet {
41+
const resolved = resolveToolOptions(options);
42+
const workspace = resolved.workspace;
43+
44+
const tools: ToolSet = {
45+
read: createReadTool(resolved.read),
46+
ls: createListTool({ workspace }),
47+
find: createFindTool({ workspace }),
48+
grep: createGrepTool({ workspace }),
49+
};
50+
51+
if (resolved.readonly) return tools;
52+
53+
tools.write = createWriteTool(resolved.write);
54+
tools.edit = createEditTool(resolved.edit);
55+
tools.delete = createDeleteTool(resolved.delete);
56+
57+
if (resolved.exec !== undefined) {
58+
tools.exec = createExecTool(resolved.exec);
59+
}
60+
61+
if (resolved.publish) {
62+
tools.publish = createPublishTool({ workspace: workspace as PublishWorkspaceLike });
63+
}
64+
65+
return tools;
66+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import type { JSONValue } from "ai";
2+
import type { ModelOutput } from "../common/model-output.js";
3+
4+
export function toAISDKOutput(output: ModelOutput) {
5+
switch (output.type) {
6+
case "text":
7+
return { type: "text" as const, value: output.value };
8+
case "error-text":
9+
return { type: "error-text" as const, value: output.value };
10+
case "json":
11+
return { type: "json" as const, value: toJSONValue(output.value) };
12+
case "media":
13+
return {
14+
type: "content" as const,
15+
value: [
16+
{ type: "text" as const, text: output.text },
17+
{
18+
type: "file" as const,
19+
data: { type: "data" as const, data: output.data },
20+
mediaType: output.mediaType,
21+
filename: output.filename,
22+
},
23+
],
24+
};
25+
}
26+
}
27+
28+
export function toJSONValue(value: unknown): JSONValue {
29+
try {
30+
const json = JSON.stringify(value);
31+
return json === undefined ? null : (JSON.parse(json) as JSONValue);
32+
} catch {
33+
return String(value);
34+
}
35+
}

0 commit comments

Comments
 (0)