feat(harness): @assistant-ui/harness with tap-based core, useHarness hook, Harness class, and multi-harness manager#5073
feat(harness): @assistant-ui/harness with tap-based core, useHarness hook, Harness class, and multi-harness manager#5073Yonom wants to merge 11 commits intomainassistant-ui/assistant-ui:mainfrom uh-2-harness-packageassistant-ui/assistant-ui:uh-2-harness-packageCopy head branch name to clipboard
Conversation
…hook, Harness class, and multi-harness manager
|
|
Claude finished @Yonom's task in 3m 51s —— View job
|
|
Reviews (1): Last reviewed commit: "feat(harness): @assistant-ui/harness wit..." | Re-trigger Greptile |
There was a problem hiding this comment.
Review completed against the latest diff
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
…rop subagents rooted in discarded branches
…spose, strip null fields in normalizeState
…al transport pipeline duplication in SPEC
There was a problem hiding this comment.
All reported issues were addressed across 6 files (changes from recent commits).
Tip: Review your code locally with the cubic CLI to iterate faster.
Re-trigger cubic

What
A new private package
@assistant-ui/harness: a minimal client for deep-agent backends (todos, files, subagents, PTC, interrupts, queued sends) speaking the assistant-transport wire. Implements task uh-2 from the harness design doc.Architecture
Built on tap, following the harness-sdk pattern: all logic lives in a single tap resource, and every public surface is a thin binding over it.
HarnessResource: the core. A plainHarnessCoreclass owns the command queue, single-flight run loop, optimistic sends, and cooperative cancel; the resource hook wires it to React state and derives views.useHarness(options):useResource(HarnessResource(options)), SSR-safe.new Harness(options): declarative alternative viacreateTapRoot, withgetState/subscribe/disposeandflushTapSync-wrapped methods.HarnessManager: keyed multi-harness lookup with stable identity per id.State and commands
HarnessState: id-keyed message tree,queue,files,todos,status,interrupt,error,title, typedextras. Snapshots replace wholesale.parentIdmay be a tool call id, rooting a nested transcript. Task subagents and programmatic tool-call sub-calls both stream through this path; the client derives a recursivesubagentsrecord. No separate PTC concept.send-message(withqueue/steerbehavior),add-tool-result,resume,cancel,cancel-queued,send-now, plus aHarnessCustomCommandsmodule-augmentation slot.messagesorqueue, or when the carrying batch settles.stop()closes the stream locally and delivers{type:"cancel"}on the immediate follow-up request.Transport
HarnessTransportis two methods (run, optionalresume) yielding state snapshots.HttpHarnessTransportimplements the assistant-transport wire (POST{commands, state, threadId}, data-stream or assistant-transport protocol) via assistant-stream's decoder and accumulator.Deliberately out of scope
ExternalThreadbridge component (separate task per the design doc)Cuts for minimalism
Dropped from the original sketch:
regenerate/edit (no command for it yet),threads/switchToviews (the recursivesubagentsrecord covers nesting),approve()sugar (resumecovers it), separate enqueue/steer commands (send-message.behaviorcarries it), a status-probe endpoint (resume()covers snapshot-on-connect), attachment/image parts,initialExtras, a React subpath export, andTExtrasgenerics on options/transport (generics only where state is read).Testing
pnpm turbo build --filter=@assistant-ui/harness,pnpm --filter @assistant-ui/harness test,pnpm lint, andpnpm check:resource-memoall pass.🤖 Generated with Claude Code