Stream computer files instead of reading them through the shell

import_file sent a computer's bytes back with base64 over /v1/shell/exec,
whose stdout is capped at 30,047 characters. Every import was therefore
cut at 22,528 bytes and saved anyway, with the tool reporting success: a
1.12 MiB archive became a 22 KB file that would not open, and a crawler's
crawl.json lost half its pages.

The bytes now come from the sandbox's streaming GET /v1/file/download.
The size is read first so nothing over BotFileImportMaxBytes is
transferred, the download asks for change_policy=abort so a file that
changes mid-send is refused rather than half-saved, and the received
length is checked against the size read, so a cut-short transfer fails
loudly. Folders go the same way, as a gzipped tar unpacked into one row
per file.

Bots also name a path as [path:volume:owner:path] now, so what a bot
leaves on a computer is a link into the files browser instead of text.
This commit is contained in:
2026-10-22 07:37:19 +01:00
parent 956942bba9
commit f1b7ba535f
7 changed files with 658 additions and 6 deletions
+26 -2
View File
@@ -1,5 +1,6 @@
import { AppData } from "@/src/data/app-data";
import botRef from "@/src/utils/bot-ref";
import pathRef from "@/src/utils/path-ref";
/**
* Prompts the helper harnesses send. The text model gets their output in
@@ -49,8 +50,31 @@ You have a folder of your own, kept with the app (not on a computer), and it sta
- list_files shows what's in it; read_file opens one (by its [file:ID] ref or path); write_file saves a text file, make_pdf a PDF, generate_image an image. Move and delete with move_file and delete_file when something is out of date, so the folder stays useful.
- Text files are chunked and searchable as soon as they're saved. search_files finds the passages that answer a question, by meaning when an embedding model is set and by words otherwise. Search your files before saying you don't know something they may hold, and when the user asks about a document they gave you.
- Uploaded files land in the same folder, so what the user sent you earlier is searchable later too.
- When you name a file, write its [file:ID] ref: the user sees a link to it.
- A file you only described is not saved. Save it first, then say it's saved.`;
- When you name a file, write its [file:ID] ref: the user sees a link to it. They can also browse everything under Files, in the menu.
- A file you only described is not saved. Save it first, then say it's saved.
- Save what the user will want before the long tail of a run. A step limit ends a run where it stands: write the report first with write_file (or copy it off the computer with import_file), then carry on verifying.`;
/**
* Added to a run that has a computer: what it leaves there is not in its
* files, but the user can still open it. `can_import` is false in a chat
* reply, where the import only happens inside a task.
*/
export const ComputerFilesNote = ({
computer_id,
can_import = true,
}: {
computer_id: number | string;
can_import?: boolean;
}) => `# Files on the computer
What you make on the computer (downloads, screenshots, a crawl, raw evidence, logs) lives in its home, not in your files. It survives restarts of the computer, but it is not searchable and it goes if the computer is rebuilt.
- The user can open any of it: name a path on the computer as a path ref, e.g. ${pathRef({ volume: "computer", owner_id: computer_id, path: "seo/coderank/raw" })}. Point at the folder for evidence they may want to see.
${
can_import
? `- import_file copies a file or a folder off the computer into your own files, in one go, and the copy is searchable straight away. Import the finished work (the report, the spreadsheet, the final document), attach it when it is what they asked for, and name it with its [file:ID] ref.\n- The raw evidence can stay on the computer: import it only when the user needs it kept, or when the computer may be rebuilt.\n`
: `- Work that ends in a file on the computer is a task: start one, and it saves what it made into your files with import_file, so it is kept and searchable.\n`
}- Never say a file is saved if it only exists on the computer. Say where it is, and that it can be imported.`;
/**
* Added to every run, chat replies and tasks alike: check before you