Skip to content

feat(agents): carry agent types and their handles over the agents port - #1733

Closed
loganj wants to merge 1 commit into
agent-host-type-viewfrom
agent-host-types-port
Closed

loganj wants to merge 1 commit into
agent-host-type-viewfrom
agent-host-types-port

Conversation

@loganj

@loganj loganj commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

🤖

Summary

Details

  • New features/agents/type-port.ts:
    • serveTypes(agents) describes each type as data: its identity, title and description, its defaults(), its migration warning, and whether it is hosted. It also says which calls the type answers (models, usage, provider check and attention action) and gives the shape of its expose. With each push it reads every exposed store's snapshot, the provider snapshot, each keyed read a screen asked for, and each shown agent's session scope.
    • typesClient(...) builds an AgentTypeView from a descriptor. The screens' page's presentation is merged through the service's own presented(), and the result is cached, so a type keeps its identity while its stores change. Exposed handles become a proxy:
      • snapshot reads the pushed value;
      • subscribe is the client's change notice;
      • read(key) asks the service for that key once, and answers empty until the key arrives;
      • any other function is a call by path.
    • An AbortSignal argument crosses as a stand-in. Its abort is sent over the port, and the service aborts a signal of its own, so a screen that stops a transcript read stops it in the service.
    • A type whose expose is not plain handles is listed but not shown, and the error is logged. This matches refactor(agents): give present the exposed handles as another page would #1731 in the service's page.
  • port.ts:
    • The service subscribes to each type's provider, session controls and exposed stores, so their changes are pushed. It still pushes before each answer.
    • New message kinds: type (a call), watch (a keyed read) and abort.
    • AgentsPortClient now has types and present. sessionState and previewRetype stay out of the client; they come next.

Testing

  • New port.test.ts cases, over a real MessageChannel (structured clone):
    • A type and its handles cross. A store reads synchronously and keeps its identity across an unchanged push. A call answers after the change it made. The provider's check, its attention action and models work, and the type keeps its identity.
    • A keyed read reads as empty, then follows the service's value after it changes.
    • Aborting an exposed call's signal aborts the service's signal.
    • A type that exposes a class instance is listed without what it shows.
  • service.test.ts: over the real service, the client lists the same types with the same defaults.
  • Mutation checks: each of these makes the named test fail.
    • Not sending aborts: the abort test times out.
    • Not subscribing to the types' stores: the type test and the keyed read test fail.
    • Not pushing after a watch: the keyed read test fails.
  • tsc --noEmit passes. The agents, Agents page and huddle suites pass (986 tests), except the Agents page avatar-picker test, which also fails on the base branch in this worktree (its node_modules is a symlink).

🤖 Generated with Claude Code

The port client now answers types() and takes present(key, ...), as the
service does in one page. The service pushes each type as data: its
identity, title, defaults, which calls it answers (models, usage,
provider check and attention action), whether it is hosted, the shape
of what it exposes, each exposed store's snapshot, and each keyed read a
screen asked for. Its session scope for each shown agent is pushed too.

On the screens' side each type is built from that and from what the
page presents, through the same merge the service uses. Exposed calls
go over the port by path; an AbortSignal argument becomes a stand-in
whose abort is sent, so the service's call sees its own signal abort.
The service subscribes to the types' own stores, so their changes are
pushed, and still pushes before each answer. A type whose handles are
not plain is listed but not shown, as in the service's page.

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>
@loganj

loganj commented Oct 28, 2026

Copy link
Copy Markdown
Contributor Author

🤖 Closing: the Manager/Runner split replaces this design (#1748 → #1839, with more to come). The branch stays in place because #1737, #1743 and #1744 are still stacked on it. They will move onto the new stack in the hidden-page step.

@loganj loganj closed this Oct 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant