11# @qoder-ai/harness-ui
22
3- The AG-UI protocol adapter for [ ` @qoder-ai/harness ` ] ( ../harness/README.md ) .
4- It turns a ` .harness ` assembly into an [ AG-UI] ( https://docs.ag-ui.com/ )
5- endpoint: any AG-UI-compatible frontend (CopilotKit, a TUI, or the companion
6- [ ` @qoder-ai/harness-studio ` ] ( ../harness-studio/README.md ) ) can start runs and
7- render them live.
3+ The reusable live-run bridge between [ ` @qoder-ai/harness ` ] ( ../harness/README.md )
4+ and browser-facing [ AG-UI] ( https://docs.ag-ui.com/ ) clients.
5+
6+ Despite the historical package name, this package does ** not** contain visual
7+ components or an end-user application. It owns the bounded protocol boundary
8+ that compiles and resolves one Harness run, projects neutral ` HarnessRunEvent `
9+ values into AG-UI events, and optionally serves them over local HTTP/SSE.
10+
11+ Most users should start with
12+ [ ` @qoder-ai/harness-studio ` ] ( ../harness-studio/README.md ) , the actual React
13+ control plane. Studio embeds this bridge under ` /agui ` and adds the Debugger,
14+ run timeline, Tool Call inspection, permissions, cancellation, evidence, and
15+ workspace experience. Use ` @qoder-ai/harness-ui ` directly when building a
16+ custom AG-UI client or embedding the run bridge in another local server.
817
918## How it fits
1019
1120``` text
1221.harness ── @qoder-ai/harness ── HarnessRunEvent (neutral lifecycle)
1322 │
14- translate.ts: neutral → AG-UI events
23+ @qoder-ai/harness-ui: AG-UI projection + SSE
1524 │
16- server.ts: POST /agui → SSE stream
25+ custom AG-UI client ◄─────┴─────► Harness Studio
1726```
1827
1928The executor's ` HarnessRunEmitter ` already guarantees a well-formed
@@ -25,14 +34,48 @@ run ends with either `RUN_FINISHED` or `RUN_ERROR`, never both.
2534
2635Retained tool output is bounded to 64 KiB. Failed or truncated results emit a
2736namespaced ` harness.tool-result-meta ` custom event after ` TOOL_CALL_RESULT ` ;
28- browser clients can import its constant and value type from the browser-safe
37+ bounded runtime-protocol evidence uses ` harness.protocol-event ` . Browser
38+ clients can import both constants and their value types from the browser-safe
2939` @qoder-ai/harness-ui/protocol ` entrypoint.
3040
3141This package implements the AG-UI ** wire format** with local types instead of
3242depending on the pre-stable ` @ag-ui/core ` ; conformance is asserted by tests
3343on the emitted JSON.
3444
35- ## Serve a harness
45+ ## Scope
46+
47+ This package owns:
48+
49+ - deterministic ` HarnessRunEvent ` to AG-UI event translation;
50+ - a browser-safe AG-UI wire contract and Harness custom-event types;
51+ - SSE encoding and incremental decoding;
52+ - compile, source-lock, resolve, execute, and terminal-event orchestration with
53+ an injected executor factory;
54+ - a local ` POST /agui ` handler with bounded requests, origin checks, and
55+ fail-closed remote-bind policy.
56+
57+ It does not own React components, Studio state or layout, persisted sessions,
58+ multi-turn conversation state, Agent discovery, remote authentication, or a
59+ production gateway. ` RunAgentInput ` is intentionally used as a bounded one-run
60+ request: the latest user message supplies the prompt, while Studio or another
61+ embedding host owns the surrounding workspace and interaction lifecycle.
62+
63+ ## Use Harness Studio
64+
65+ For the supported visual workflow, run Studio with a Harness file:
66+
67+ ``` sh
68+ npx @qoder-ai/harness-studio --harness my-agent.harness
69+ ```
70+
71+ Studio serves its own UI and embeds this package's handler on the same local
72+ origin. See the [ Harness Studio README] ( ../harness-studio/README.md ) for its
73+ Debugger, evidence, workspace, and ACP Agent routes.
74+
75+ ## Serve the bridge directly
76+
77+ The standalone command is an advanced integration surface for a custom
78+ AG-UI-compatible frontend; it is not a separate Better Harness UI:
3679
3780``` sh
3881npx @qoder-ai/harness-ui serve my-agent.harness --port 3210
@@ -42,10 +85,9 @@ npx @qoder-ai/harness-ui serve my-agent.harness --port 3210
4285 The prompt is the latest user message.
4386- ` GET /healthz ` — liveness probe.
4487
45- The server binds to ` 127.0.0.1 ` and is a local development surface. Runs
46- execute through the same v0.3 executors as the core package (Qoder SDK by
47- default), so the executor honesty rules and redaction guarantees apply
48- unchanged.
88+ The server binds to ` 127.0.0.1 ` and is a local integration surface. Its CLI
89+ selects the same v0.3 Qoder or Pi executors as the core package, so the executor
90+ honesty rules and redaction guarantees apply unchanged.
4991
5092A skill declared with ` source "./skills/x" ` is delivered from disk, not
5193merely referenced: the server locks and reads it against ` --source-root ` ,
@@ -68,22 +110,28 @@ a non-loopback Host just because the Origin matches it. Keep the default
68110loopback bind unless a trusted gateway supplies authentication and transport
69111security.
70112
71- ## Embed in code
113+ ## Embed the run bridge
72114
73115``` ts
74116import { runHarnessAgui } from " @qoder-ai/harness-ui" ;
117+ import { QoderSdkExecutor } from " @qoder-ai/harness/exec" ;
75118
76119await runHarnessAgui ({
77120 source , // .harness source text
78121 prompt: " Explain the repository in one sentence." ,
79122 threadId: " thread-1" ,
80123 runId: " run-1" ,
81124 onEvent : (event ) => console .log (event .type ),
125+ executorFactory : ({ onRunEvent }) =>
126+ new QoderSdkExecutor ({ onRunEvent }),
82127});
83128```
84129
85- ` executorFactory ` injects a custom or scripted executor — that is also how
86- the tests run without a live SDK.
130+ The library entrypoint never selects a concrete host executor implicitly.
131+ ` executorFactory ` keeps host wiring with the embedding application and also
132+ allows deterministic scripted executors in tests. Server embedders can mount
133+ ` handleAguiRun ` on an existing Node HTTP server instead of opening a second
134+ listener.
87135
88136## Development
89137
0 commit comments