Repository navigation
Conversation
A type's `present` now gets its `expose` the way it would get it from another page: each call returns a promise, and stores and keyed reads stay synchronous (`Remote<T>`). The service checks that `expose` holds only plain objects, arrays, JSON, stores, keyed reads and calls; a type exposing anything else, such as a class instance, is not shown. Claude, Codex, goose and Pi expose `handle(object, names)` of their setup, defaults, provider and history objects instead of the objects, so screens reach only the methods their tabs use. The tabs' handle types accept the remote form, so a tab that needed a call's synchronous result would no longer typecheck. Co-authored-by: Larry <627498bd4bd1f281a16431e3c6cce3b5c25b6692798c78672298aefbf2f8f8b5@buzz.block.builderlab.xyz> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Logan Johnson <loganj@squareup.com>
This was referenced Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖
Summary
present. Once agents run in another page, those handles will arrive over a port, where every call answers later. Todaypresentgets the runtime's own objects, so a tab could rely on a synchronous answer, or reach a method it was never meant to, without anyone noticing.presentnow gets the handles the way it will from another page: each call returns a promise, and stores and keyed reads stay synchronous. The harness tabs typecheck against that form. Behavior in the app stays the same: a call still runs at once; only its answer is wrapped.Details
features/agents/handles.ts:Remote<T>: the type a screen gets. Calls return promises;snapshot,subscribe,readandemptystay as they are.local(expose): the in-page version of what a port client will give. It walks plain objects and arrays, wraps calls, and throws on any other object (for example a class instance), naming the path.handle(object, names): a plain handle with only the named methods of an object.service.ts:presenttakes(exposed: Remote<Exposed>) => ..., and the merge passeslocal(type.expose). A type whoseexposefails the check still runs; it is listed without what it shows, and the error is logged, like apresentthat throws.handle(...)of their setup, defaults, provider and history objects, with the methods their tabs'Picktypes already named.Testing
service.test.ts: the presented type gets the count as JSON, the store's ownsnapshot, and a call that resolves with a promise. On the old code the call returned2directly, so the test fails there. New case: a type that exposes a class instance is listed but not shown, andpresentis not called.handles.test.ts:localkeeps stores and keyed reads synchronous and identical, turns a throwing call into a rejection, walks arrays, and refuses a class instance by path.handlecalls through to the object.tsc --noEmitpasses. Fullvitest run src: 11456 passed. The only failures are 4 emoji-related files (the Agents page avatar picker, emoji-mart, EmojiPicker appearance, StatusEditor emoji draft). Each fails because the emoji picker does not render, which happens in this worktree because itsnode_modulesis a symlink. None of them touches agent code. I confirmed the Agents page and emoji-mart failures on the base branch earlier; CI runs all four.🤖 Generated with Claude Code