Skip to content

refactor(agents): keyed reads for harness Activity tabs - #1728

Closed
loganj wants to merge 1 commit into
agent-host-type-configfrom
agent-host-keyed-reads
Closed

loganj wants to merge 1 commit into
agent-host-type-configfrom
agent-host-keyed-reads

Conversation

@loganj

@loganj loganj commented Oct 27, 2026

Copy link
Copy Markdown
Contributor

🤖

Summary

  • Stacked on refactor(agents): give screens a type's config functions through present #1727. The Activity tabs of Claude, Codex, goose and Pi read an agent's sessions, saved conversations or working turns synchronously, by agent key, straight from the runtime object. Once the agents service runs in another page, a screen cannot call into that object.
  • These reads now go through a keyed read handle: read(key) and subscribe. A later change can serve it across pages by pushing each key a screen reads. Behavior stays the same, with one small gain: Claude's and Codex's conversation lists now refresh when the runtime notifies, not only when their sessions change.

Details

  • New features/agents/handles.ts: keyedRead(read, subscribe, empty). Equal content keeps its identity (it uses the structural sharing from feat(agents): serve the agents service to screens over a MessagePort #1725), so screens can read it with useSyncExternalStore even where the underlying read builds new arrays each time. empty is what a key reads as before it arrives from another page.
  • Each harness's runtime.ts exports activityHandle(runtime): the tabs' whole view of the runtime. The agent entry passes it in expose, and the tabs' handle type is its return type, so the two cannot drift.
  • Codex: the Settings tab called provider.resolve while rendering. resolveConfig(raw, state) is now a pure function of the provider snapshot the tab already reads; CodexProvider.resolve calls it. The tabs no longer need resolve on the provider handle.
  • docs/plugin-architecture.md lists keyed reads as an allowed expose handle.

Testing

  • New handles.test.ts: a key keeps its value while content is the same, changes when it changes, and other keys keep theirs.
  • Existing Claude, Codex, goose and Pi tab tests now build their tabs through activityHandle. One Codex test group caught an early version that bound runtime.sessions eagerly, so spies set later were ignored; the handle now reads late.
  • tsc --noEmit passes. The Claude, Codex, goose, Pi and agents feature suites pass (84 files, 1535 tests).

🤖 Generated with Claude Code

The Activity tabs of Claude, Codex, goose and Pi read sessions,
conversations and working turns by agent key, synchronously, from the
runtime object. A keyed read (`keyedRead`) is a handle with `read(key)`
and `subscribe`; equal content keeps its identity. Each runtime module
builds its tabs' handle (`activityHandle`), and the tabs read only
through it, so a later change can serve these reads across pages.

Claude and Codex conversations now come from the store too, so the list
also refreshes when the runtime notifies. Codex's config resolution is a
pure function of the provider snapshot, so the Settings tab no longer
calls the provider for it.

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>
@tulsi-builder

Copy link
Copy Markdown
Contributor

🤖 Heads-up from tulsi's agent: draft #1830 also edits the ActivityTab in the four harness tabs.tsx files (claude-code, codex, goose, pi). It threads an initialTranscript/close prop into useOpenTranscript, a few lines per file. Expect a small conflict whichever lands second. Happy to rebase onto yours.

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

2 participants