chore: fix bad merge

This commit is contained in:
Nathan Flurry 2026-02-11 07:52:48 -08:00
parent 1dd45908a3
commit 94353f7696
205 changed files with 19244 additions and 14866 deletions

View file

@ -5,183 +5,130 @@ sidebarTitle: "File System"
icon: "folder"
---
The filesystem API lets you list, read, write, move, and delete files inside the sandbox, plus upload batches of files via tar archives.
Control operations (`list`, `mkdir`, `move`, `stat`, `delete`) are ACP extensions on `/v2/rpc` and require an active ACP connection in the SDK.
The filesystem API lets you list, read, write, move, and delete files inside the sandbox, plus upload tar archives in batch.
Binary transfer is intentionally a separate HTTP API (not ACP extension methods):
- `GET /v2/fs/file`
- `PUT /v2/fs/file`
- `POST /v2/fs/upload-batch`
Reason: these are host/runtime capabilities implemented by Sandbox Agent for cross-agent-consistent behavior, and they may require streaming very large binary payloads that ACP JSON-RPC is not suited to transport efficiently.
This is intentionally separate from ACP native `fs/read_text_file` and `fs/write_text_file`.
ACP extension variants may exist in parallel for compatibility, but SDK defaults should use the HTTP endpoints above for binary transfer.
## Path Resolution
## Path resolution
- Absolute paths are used as-is.
- Relative paths use the session working directory when `sessionId` is provided.
- Without `sessionId`, relative paths resolve against the server home directory.
- Relative paths cannot contain `..` or absolute prefixes; requests that attempt to escape the root are rejected.
- Relative paths resolve from the server process working directory.
- Requests that attempt to escape allowed roots are rejected by the server.
The session working directory is the server process current working directory at the moment the session is created.
## List Entries
`listFsEntries()` uses ACP extension method `_sandboxagent/fs/list_entries`.
## List entries
<CodeGroup>
```ts TypeScript
import { SandboxAgentClient } from "sandbox-agent";
import { SandboxAgent } from "sandbox-agent";
const client = new SandboxAgentClient({ baseUrl: "http://127.0.0.1:2468",
token: process.env.SANDBOX_TOKEN,
agent: "mock" });
const sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",
});
const entries = await client.listFsEntries({
const entries = await sdk.listFsEntries({
path: "./workspace",
sessionId: "my-session",
});
console.log(entries);
```
```bash cURL
curl -X POST "http://127.0.0.1:2468/v2/rpc" \
-H "Authorization: Bearer $SANDBOX_TOKEN" \
-H "x-acp-connection-id: acp_conn_1" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"_sandboxagent/fs/list_entries","params":{"path":"./workspace","sessionId":"my-session"}}'
curl -X GET "http://127.0.0.1:2468/v1/fs/entries?path=./workspace"
```
</CodeGroup>
## Read And Write Files
## Read and write files
`PUT /v2/fs/file` writes raw bytes. `GET /v2/fs/file` returns raw bytes.
`PUT /v1/fs/file` writes raw bytes. `GET /v1/fs/file` returns raw bytes.
<CodeGroup>
```ts TypeScript
import { SandboxAgentClient } from "sandbox-agent";
import { SandboxAgent } from "sandbox-agent";
const client = new SandboxAgentClient({ baseUrl: "http://127.0.0.1:2468",
token: process.env.SANDBOX_TOKEN,
agent: "mock" });
await client.writeFsFile({ path: "./notes.txt", sessionId: "my-session" }, "hello");
const bytes = await client.readFsFile({
path: "./notes.txt",
sessionId: "my-session",
const sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",
});
await sdk.writeFsFile({ path: "./notes.txt" }, "hello");
const bytes = await sdk.readFsFile({ path: "./notes.txt" });
const text = new TextDecoder().decode(bytes);
console.log(text);
```
```bash cURL
curl -X PUT "http://127.0.0.1:2468/v2/fs/file?path=./notes.txt&sessionId=my-session" \
-H "Authorization: Bearer $SANDBOX_TOKEN" \
curl -X PUT "http://127.0.0.1:2468/v1/fs/file?path=./notes.txt" \
--data-binary "hello"
curl -X GET "http://127.0.0.1:2468/v2/fs/file?path=./notes.txt&sessionId=my-session" \
-H "Authorization: Bearer $SANDBOX_TOKEN" \
curl -X GET "http://127.0.0.1:2468/v1/fs/file?path=./notes.txt" \
--output ./notes.txt
```
</CodeGroup>
## Create Directories
`mkdirFs()` uses ACP extension method `_sandboxagent/fs/mkdir`.
## Create directories
<CodeGroup>
```ts TypeScript
import { SandboxAgentClient } from "sandbox-agent";
import { SandboxAgent } from "sandbox-agent";
const client = new SandboxAgentClient({ baseUrl: "http://127.0.0.1:2468",
token: process.env.SANDBOX_TOKEN,
agent: "mock" });
await client.mkdirFs({
path: "./data",
sessionId: "my-session",
const sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",
});
await sdk.mkdirFs({ path: "./data" });
```
```bash cURL
curl -X POST "http://127.0.0.1:2468/v2/rpc" \
-H "Authorization: Bearer $SANDBOX_TOKEN" \
-H "x-acp-connection-id: acp_conn_1" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"_sandboxagent/fs/mkdir","params":{"path":"./data","sessionId":"my-session"}}'
curl -X POST "http://127.0.0.1:2468/v1/fs/mkdir?path=./data"
```
</CodeGroup>
## Move, Delete, And Stat
`moveFs()`, `statFs()`, and `deleteFsEntry()` use ACP extension methods (`_sandboxagent/fs/move`, `_sandboxagent/fs/stat`, `_sandboxagent/fs/delete_entry`).
## Move, delete, and stat
<CodeGroup>
```ts TypeScript
import { SandboxAgentClient } from "sandbox-agent";
import { SandboxAgent } from "sandbox-agent";
const client = new SandboxAgentClient({ baseUrl: "http://127.0.0.1:2468",
token: process.env.SANDBOX_TOKEN,
agent: "mock" });
await client.moveFs(
{ from: "./notes.txt", to: "./notes-old.txt", overwrite: true },
{ sessionId: "my-session" },
);
const stat = await client.statFs({
path: "./notes-old.txt",
sessionId: "my-session",
const sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",
});
await client.deleteFsEntry({
path: "./notes-old.txt",
sessionId: "my-session",
await sdk.moveFs({
from: "./notes.txt",
to: "./notes-old.txt",
overwrite: true,
});
const stat = await sdk.statFs({ path: "./notes-old.txt" });
await sdk.deleteFsEntry({ path: "./notes-old.txt" });
console.log(stat);
```
```bash cURL
curl -X POST "http://127.0.0.1:2468/v2/rpc" \
-H "Authorization: Bearer $SANDBOX_TOKEN" \
-H "x-acp-connection-id: acp_conn_1" \
curl -X POST "http://127.0.0.1:2468/v1/fs/move" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":3,"method":"_sandboxagent/fs/move","params":{"from":"./notes.txt","to":"./notes-old.txt","overwrite":true,"sessionId":"my-session"}}'
-d '{"from":"./notes.txt","to":"./notes-old.txt","overwrite":true}'
curl -X POST "http://127.0.0.1:2468/v2/rpc" \
-H "Authorization: Bearer $SANDBOX_TOKEN" \
-H "x-acp-connection-id: acp_conn_1" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":4,"method":"_sandboxagent/fs/stat","params":{"path":"./notes-old.txt","sessionId":"my-session"}}'
curl -X GET "http://127.0.0.1:2468/v1/fs/stat?path=./notes-old.txt"
curl -X POST "http://127.0.0.1:2468/v2/rpc" \
-H "Authorization: Bearer $SANDBOX_TOKEN" \
-H "x-acp-connection-id: acp_conn_1" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":5,"method":"_sandboxagent/fs/delete_entry","params":{"path":"./notes-old.txt","sessionId":"my-session"}}'
curl -X DELETE "http://127.0.0.1:2468/v1/fs/entry?path=./notes-old.txt"
```
</CodeGroup>
## Batch Upload (Tar)
## Batch upload (tar)
Batch upload accepts `application/x-tar` only and extracts into the destination directory. The response returns absolute paths for extracted files, capped at 1024 entries.
Batch upload accepts `application/x-tar` and extracts into the destination directory.
<CodeGroup>
```ts TypeScript
import { SandboxAgentClient } from "sandbox-agent";
import { SandboxAgent } from "sandbox-agent";
import fs from "node:fs";
import path from "node:path";
import tar from "tar";
const client = new SandboxAgentClient({ baseUrl: "http://127.0.0.1:2468",
token: process.env.SANDBOX_TOKEN,
agent: "mock" });
const sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",
});
const archivePath = path.join(process.cwd(), "skills.tar");
await tar.c({
@ -190,9 +137,8 @@ await tar.c({
}, ["."]);
const tarBuffer = await fs.promises.readFile(archivePath);
const result = await client.uploadFsBatch(tarBuffer, {
const result = await sdk.uploadFsBatch(tarBuffer, {
path: "./skills",
sessionId: "my-session",
});
console.log(result);
@ -201,8 +147,7 @@ console.log(result);
```bash cURL
tar -cf skills.tar -C ./skills .
curl -X POST "http://127.0.0.1:2468/v2/fs/upload-batch?path=./skills&sessionId=my-session" \
-H "Authorization: Bearer $SANDBOX_TOKEN" \
curl -X POST "http://127.0.0.1:2468/v1/fs/upload-batch?path=./skills" \
-H "Content-Type: application/x-tar" \
--data-binary @skills.tar
```