Retire CuaAgent and CuaAgentHarness in favor of the handle - #80
Merged
Conversation
The CLI now builds a stock pi AgentHarness from attach() and keeps the live (model, tools) selection in its own CuaCliCatalog. With no class owning mutable agent state, setTools/setModel/setModelAndTools and the tool manager's prepare/commit machinery go away: a change compiles a new pair and applies it. compile() throws before anything reaches pi and apply() restores the previous pair if pi rejects the new one, so the atomicity the mutation methods provided is preserved without a second copy of the state. The handle now owns one Models collection serving whichever pair is active. pi fixes models at construction while the headers, payload transforms and tool plan it carries are per-catalog, so a per-compile collection would have left a swapped harness streaming the first catalog's plan for the rest of the session.
The published-artifact check imported CuaAgent, which this branch deletes.
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.
Phase 4b: the CLI builds a stock pi
AgentHarnessfromattach(), andCuaAgent/CuaAgentHarnessare gone. Net −869 lines.What replaces the classes
The CLI keeps the live selection in its own
CuaCliCatalog— about 40 lines holding the handle, the model input, and the requested tool list:That is the whole mutation story now.
compile()throws before anything reaches pi, andapply()restores the previous pair if pi rejects the new one, so the atomicitysetTools()provided survives — but there is no longer a second copy of the state to drift from pi's.buildCuaHarness()returns{ harness, catalog }. The 18 TUI call sites that use pi's own lifecycle (prompt,subscribe,abort,compact, thinking level) were untouched; only the 5 selection sites moved.The bug this turned up
withCatalogModelsreadsmanager.cataloglazily, at stream time. The classes got away with that because their manager was mutable andcommit()updated it in place. A per-compile manager does not move, and pi fixesmodelsat construction with no setter — so the naive migration leaves a swapped harness streaming the first catalog's headers, payload transforms and tool plan for the rest of the session, silently.So the handle now owns one
Modelscollection that serves whichever pair is active, andactivate()is what redirects it.apply()calls it. The test fails against a per-compile collection:Two smaller ones found while reviewing my own diff: a stale
release()cleared the handle's grip on the pair that was live, so the nextactivate()could not release it (asserted by counting net live handler registrations — 8 instead of 4), andinstall()is renamedactivate()because it no longer only installs handlers.Capability removed, deliberately
Deleting the mutation path also deletes cache-preserving deferred tool addition: a tool that added tools mid-execution had those names recorded on its result as
addedToolNames, letting pi extend an OpenAI request without invalidating the prompt-cache prefix. Nothing in the repo produced them outside that path, and with an immutable manager the code could no longer fire — keeping it would have been dead code, not a preserved feature. The transport still consumesaddedToolNameson a transcript that carries them, and cua-ai keeps its own coverage of the namespace replay (reaches the CUA adapter when the transcript carries a deferred tool-search addition,pairs replayed namespaces by call id, not ordinal). If we want the capability back it should return as a first-class handle feature rather than a side effect of mutation.Coverage
agent.test.ts(634 lines) andopenai-deferred-tools.test.tsare deleted, but the behaviors that survive were ported to drive a handle plus stock pi rather than dropped: the OpenAI native-computer screenshot exemption, exact catalog composition, registry fallback for an unlisted ref, failed-turn state clearing, transport-follows-selection, and the model-change accounting for both a tools-only change and a transport-moving switch.harness-context.test.ts,published-declarations.test.ts,tool-manager.test.tsand the live e2e suite are ported rather than deleted.published-declarations.test.tscaught a real constraint while being ported: a swap must compile for the same tool context the harness delivers, or the tool types do not line up. That is now asserted in the consumer.Verified by exit status, not by grepping output: typecheck 0, cua-ai 94, cua-agent 281, cua-cli 143, all three builds 0.
Follow-ups, not in this PR
packages/agent/README.md,docs/architecture.mdand both design records are updated; the two records get a superseded banner rather than a rewrite, since they are the record of decisions that have now been superseded.typeof m.CuaAgent === "function"; it needs a new smoke symbol before the next release.CuaAgentremoval reaches anyone outside this repo.Note
High Risk
Major breaking public API removal and refactor of how model transport, tool catalogs, and streaming metadata stay in sync across runtime swaps.
Overview
Breaking: Removes
CuaAgentandCuaAgentHarness. Consumers bind a Kernel browser withattach(), callcompile({ model, tools })for plain pimodel/tools/models, constructAgentorAgentHarnessthemselves, and useactivate()/apply()to swap catalogs on a running harness.The handle keeps one shared
Modelscollection (pi fixesmodelsat construction while headers and payload transforms are per-catalog).activate()points it at the live compiled pair;apply()swaps model/tools atomically and rolls back if pi rejects the change.install()is renamed toactivate().CuaToolManageris immutable per compile—getTools/setTools/setModel/ execution-scope mutation and cache-preserving mid-turnaddedToolNamesproduction are gone. The CLI composes a stock pi harness viabuildCuaHarness()→{ harness, catalog }, withCuaCliCatalogowning/modeland/toolsrecompiles.Docs, changelogs, release smoke check (
attachinstead ofCuaAgent), and tests are updated; largeCuaAgent-centric suites are removed or ported to the handle + pi path.Reviewed by Cursor Bugbot for commit 9f03fa3. Bugbot is set up for automated code reviews on this repo. Configure here.