Repository navigation
think, agents: work in a @cloudflare/computer Workspace - #2560
mattzcarey wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: 0b4608a The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
| bytes, | ||
| mediaType ?? "application/octet-stream" | ||
| ); | ||
| await files.write(path, bytes); |
There was a problem hiding this comment.
🔴 Evicted images lose their MIME type
When files.write stores an image outside the sniffed formats, its MIME type is discarded. The read tool then labels it unsupported binary, so the model cannot retrieve the evicted image.
Learn more
Media eviction replaces an old image part with a marker pointing to a workspace file. Previously the write carried mediaType, so detectWorkspaceMediaType could identify formats without a magic-byte detector. The new write only supplies bytes. Its detector recognizes PNG, JPEG, GIF, WebP, SVG, and PDF; other legitimate media types become application/octet-stream and createReadTool refuses to return them to the model.
Example: An aged image/avif file part is evicted. Its marker points to a saved AVIF file, but reading that file returns {kind: 'binary', unsupported: true} instead of an image.
Recommended fix: Preserve the original media type alongside the bytes or recover it when reading evicted media. Test a valid image type without an existing signature detector.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Not changing this. The next PR in the stack replaces Think's read tool with Computer's, which attaches PNG, JPEG, GIF, WebP and PDF, the formats model providers accept. The evicted file keeps its extension (.avif), so nothing is lost. Formats outside that list weren't reliably attachable before either.
|
✅ agents import sizes: no significant changes ( |
agents
@cloudflare/ai-chat
@cloudflare/codemode
hono-agents
@cloudflare/shell
@cloudflare/think
@cloudflare/voice
@cloudflare/worker-bundler
commit: |
f6b669d to
6d5042d
Compare
6d5042d to
767f8ec
Compare
767f8ec to
37ffb59
Compare
37ffb59 to
0b4608a
Compare
| return Promise.all( | ||
| matches.map(async (match) => | ||
| match.type === "dir" | ||
| ? { path: match.path, type: "directory", size: 0 } | ||
| : { | ||
| path: match.path, | ||
| type: "file", | ||
| size: (await fs.stat(match.path)).size | ||
| } | ||
| ) |
There was a problem hiding this comment.
🟡 Concurrent deletion aborts skill glob
When a matching file disappears after fs.find, ctx.workspace.glob rejects instead of returning surviving matches. Promise.all propagates the missing file's fs.stat error to the entire skill script.
Learn more
The skill runner exposes ctx.workspace.glob to scripts through SkillScriptHostBridge. A shared workspace can change after fs.find lists its paths. If a matched file is removed before the new metadata lookup, fs.stat rejects with ENOENT and Promise.all discards every result. WorkspaceFiles.glob handles the same race by filtering missing entries after stat.
Example: fs.find returns /workspace/notes/a.md and /workspace/notes/b.md. Another client deletes b.md before its stat. The skill receives an error instead of the surviving a.md entry.
Recommended fix: Resolve each match through access.stat(match.path) and filter out null results. Preserve the existing result shape and let non-ENOENT errors propagate.
Was this helpful? React with 👍 or 👎 to provide feedback.
Think's
workspaceis now aWorkspacefrom@cloudflare/computer. By default Think creates one on the agent's own storage, with no execution backends. Agent Skills take the same shape, and a newlazyWorkspace()covers a Workspace another Durable Object owns.We want one way to give an agent a workspace:
workspace.fs: media eviction, skills projection, fetch spill and the extension host functions. ThewriteFileByteschecks are gone, so media eviction and skills projection work with every workspace./workspace, Computer's working root.@cloudflare/computeris a new peer dependency of Think.WorkspaceandWorkspaceLikeare no longer exported, andcreateExecuteTool(this)no longer buildsstate.*from the workspace.agents) accept only the Computer shape, for both projection andskills.runner().lazyWorkspace(resolve)turns an async resolver into a Workspace. It resolves on first use and keeps the client, and a failed resolution is retried on the next operation.agent-thinkdisposes its client after each turn and assigns a freshlazyWorkspacefor the next one./workspace, and refreshes after each turn instead of on every write, because Computer has no change events. The examples that depend on Think add@cloudflare/computer.docs/think/index.mdgets an "Upgrading to a Computer workspace" section, which the changesets link to.Tests ran: think workers suite, agents skills and skill runner, and the assistant example. Repo typecheck is clean.
Stacked on #2559.
Stack (merge in order, or merge the top to land them all together):