Skip to content

Commit 16b0dd8

Browse files
committed
Refactor startup to be faster
1 parent 927884c commit 16b0dd8

File tree

11 files changed

+52
-29
lines changed

11 files changed

+52
-29
lines changed

src/sandbox/just-bash.test.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ describe("wrapJustBash", () => {
7171
expect(content).toBe("content of /test.txt");
7272
});
7373

74-
it("wraps writeFile via fs.writeFile", async () => {
74+
it("wraps writeFiles via fs.writeFile", async () => {
7575
const writtenFiles: Array<{ path: string; content: string }> = [];
7676
const mockBash = {
7777
exec: async () => ({ stdout: "", stderr: "", exitCode: 0 }),
@@ -84,10 +84,14 @@ describe("wrapJustBash", () => {
8484
};
8585

8686
const sandbox = wrapJustBash(mockBash);
87-
await sandbox.writeFile("/dir/test.txt", "my content");
87+
await sandbox.writeFiles([
88+
{ path: "/dir/test.txt", content: "my content" },
89+
{ path: "/other/file.txt", content: "other content" },
90+
]);
8891

8992
expect(writtenFiles).toEqual([
9093
{ path: "/dir/test.txt", content: "my content" },
94+
{ path: "/other/file.txt", content: "other content" },
9195
]);
9296
});
9397
});
@@ -121,7 +125,7 @@ describe("duck-typing disambiguation", () => {
121125
const customSandbox = {
122126
executeCommand: async () => ({ stdout: "", stderr: "", exitCode: 0 }),
123127
readFile: async () => "",
124-
writeFile: async () => {},
128+
writeFiles: async () => {},
125129
};
126130

127131
expect(isJustBash(customSandbox)).toBe(false);

src/sandbox/just-bash.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,12 @@ export async function createJustBashSandbox(
6363
return bashEnv.fs.readFile(filePath);
6464
},
6565

66-
async writeFile(filePath: string, content: string): Promise<void> {
67-
await bashEnv.fs.writeFile(filePath, content);
66+
async writeFiles(
67+
files: Array<{ path: string; content: string }>,
68+
): Promise<void> {
69+
for (const file of files) {
70+
await bashEnv.fs.writeFile(file.path, file.content);
71+
}
6872
},
6973
};
7074
}
@@ -97,8 +101,12 @@ export function wrapJustBash(bashInstance: JustBashLike): Sandbox {
97101
return bashInstance.fs.readFile(filePath);
98102
},
99103

100-
async writeFile(filePath: string, content: string): Promise<void> {
101-
await bashInstance.fs.writeFile(filePath, content);
104+
async writeFiles(
105+
files: Array<{ path: string; content: string }>,
106+
): Promise<void> {
107+
for (const file of files) {
108+
await bashInstance.fs.writeFile(file.path, file.content);
109+
}
102110
},
103111
};
104112
}

src/sandbox/type-compatibility.test-d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function acceptsVercelSandbox(sandbox: VercelSandbox) {
2222
function ourSandboxIsValid(sandbox: Sandbox) {
2323
sandbox.executeCommand("ls");
2424
sandbox.readFile("/file");
25-
sandbox.writeFile("/file", "content");
25+
sandbox.writeFiles([{ path: "/file", content: "content" }]);
2626
}
2727

2828
// Suppress unused variable warnings

src/sandbox/vercel.test.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ describe("wrapVercelSandbox", () => {
9292
);
9393
});
9494

95-
it("wraps writeFile using writeFiles with Buffer", async () => {
95+
it("wraps writeFiles using native writeFiles with Buffer", async () => {
9696
const mockWriteFiles = vi.fn().mockResolvedValue(undefined);
9797

9898
const mockVercelSandbox: VercelSandboxLike = {
@@ -103,10 +103,14 @@ describe("wrapVercelSandbox", () => {
103103
};
104104

105105
const sandbox = wrapVercelSandbox(mockVercelSandbox);
106-
await sandbox.writeFile("/test.txt", "content");
106+
await sandbox.writeFiles([
107+
{ path: "/test.txt", content: "content" },
108+
{ path: "/other.txt", content: "other" },
109+
]);
107110

108111
expect(mockWriteFiles).toHaveBeenCalledWith([
109112
{ path: "/test.txt", content: Buffer.from("content", "utf-8") },
113+
{ path: "/other.txt", content: Buffer.from("other", "utf-8") },
110114
]);
111115
});
112116
});

src/sandbox/vercel.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,15 @@ export function wrapVercelSandbox(vercelSandbox: VercelSandboxLike): Sandbox {
7070
return streamToString(stream);
7171
},
7272

73-
async writeFile(filePath: string, content: string): Promise<void> {
74-
await vercelSandbox.writeFiles([
75-
{ path: filePath, content: Buffer.from(content, "utf-8") },
76-
]);
73+
async writeFiles(
74+
files: Array<{ path: string; content: string }>,
75+
): Promise<void> {
76+
await vercelSandbox.writeFiles(
77+
files.map((f) => ({
78+
path: f.path,
79+
content: Buffer.from(f.content, "utf-8"),
80+
})),
81+
);
7782
},
7883
};
7984
}

src/tool.test.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ describe("createBashTool", () => {
8686
expect(sandbox).toBeDefined();
8787
expect(typeof sandbox.executeCommand).toBe("function");
8888
expect(typeof sandbox.readFile).toBe("function");
89-
expect(typeof sandbox.writeFile).toBe("function");
89+
expect(typeof sandbox.writeFiles).toBe("function");
9090
});
9191

9292
it("writes inline files to destination", async () => {
@@ -295,7 +295,7 @@ describe("createBashTool", () => {
295295
.fn()
296296
.mockResolvedValue({ stdout: "custom", stderr: "", exitCode: 0 }),
297297
readFile: vi.fn().mockResolvedValue("custom content"),
298-
writeFile: vi.fn().mockResolvedValue(undefined),
298+
writeFiles: vi.fn().mockResolvedValue(undefined),
299299
stop: vi.fn().mockResolvedValue(undefined),
300300
};
301301

@@ -306,11 +306,10 @@ describe("createBashTool", () => {
306306

307307
expect(sandbox).toBe(customSandbox);
308308

309-
// Files should be written to custom sandbox
310-
expect(customSandbox.writeFile).toHaveBeenCalledWith(
311-
"/workspace/test.txt",
312-
"content",
313-
);
309+
// Files should be written to custom sandbox in a single call
310+
expect(customSandbox.writeFiles).toHaveBeenCalledWith([
311+
{ path: "/workspace/test.txt", content: "content" },
312+
]);
314313

315314
// Tools should use custom sandbox
316315
assert(tools.bash.execute, "bash.execute should be defined");

src/tool.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,12 @@ export async function createBashTool(
7979
sandbox = options.sandbox as Sandbox;
8080
}
8181

82-
// Write files to existing sandbox
83-
for (const [filePath, content] of Object.entries(filesWithDestination)) {
84-
await sandbox.writeFile(filePath, content);
82+
// Write files to existing sandbox in one call
83+
const filesToWrite = Object.entries(filesWithDestination).map(
84+
([filePath, content]) => ({ path: filePath, content }),
85+
);
86+
if (filesToWrite.length > 0) {
87+
await sandbox.writeFiles(filesToWrite);
8588
}
8689
} else {
8790
// Create just-bash sandbox with files

src/tools-prompt.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ function createMockSandbox(tools: string[]): Sandbox {
2222
return { stdout: "", stderr: "Unknown command", exitCode: 1 };
2323
},
2424
readFile: async () => "",
25-
writeFile: async () => {},
25+
writeFiles: async () => {},
2626
};
2727
}
2828

@@ -129,7 +129,7 @@ describe("discoverAvailableTools", () => {
129129
exitCode: 0,
130130
}),
131131
readFile: async () => "",
132-
writeFile: async () => {},
132+
writeFiles: async () => {},
133133
};
134134

135135
const tools = await discoverAvailableTools(sandbox);

src/tools/bash.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ vi.mock("ai", () => ({
1313
const mockSandbox = {
1414
executeCommand: vi.fn(),
1515
readFile: vi.fn(),
16-
writeFile: vi.fn(),
16+
writeFiles: vi.fn(),
1717
stop: vi.fn(),
1818
};
1919

src/tools/write-file.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export function createWriteFileTool(options: CreateWriteFileToolOptions) {
2323
inputSchema: writeFileSchema,
2424
execute: async ({ path, content }) => {
2525
const resolvedPath = nodePath.posix.resolve(cwd, path);
26-
await sandbox.writeFile(resolvedPath, content);
26+
await sandbox.writeFiles([{ path: resolvedPath, content }]);
2727
return { success: true };
2828
},
2929
});

0 commit comments

Comments
 (0)