Skip to content

Commit 8292495

Browse files
phodalcodex
andcommitted
docs(harness-ui): clarify live-run bridge positioning
Reframe the package as Studio’s reusable AG-UI live-run bridge and distinguish the standalone CLI as an advanced integration surface. Document its scope and non-goals, direct visual users to Studio, and fix the embedded example to provide the required executor factory. Validated with git diff --check and npx vitest run test/skills-docs/doc-link-graph.test.mjs. Co-authored-by: Codex (GPT 5.6 Sol) <codex@openai.com>
1 parent 84e32b7 commit 8292495

1 file changed

Lines changed: 64 additions & 16 deletions

File tree

packages/harness-ui/README.md

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
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

1928
The executor's `HarnessRunEmitter` already guarantees a well-formed
@@ -25,14 +34,48 @@ run ends with either `RUN_FINISHED` or `RUN_ERROR`, never both.
2534

2635
Retained tool output is bounded to 64 KiB. Failed or truncated results emit a
2736
namespaced `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

3141
This package implements the AG-UI **wire format** with local types instead of
3242
depending on the pre-stable `@ag-ui/core`; conformance is asserted by tests
3343
on 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
3881
npx @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

5092
A skill declared with `source "./skills/x"` is delivered from disk, not
5193
merely 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
68110
loopback bind unless a trusted gateway supplies authentication and transport
69111
security.
70112

71-
## Embed in code
113+
## Embed the run bridge
72114

73115
```ts
74116
import { runHarnessAgui } from "@qoder-ai/harness-ui";
117+
import { QoderSdkExecutor } from "@qoder-ai/harness/exec";
75118

76119
await 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

Comments
 (0)