@bang404/openagent-harness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BANG404
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # OpenAgent Harness Client
2
+
3
+ Thin TypeScript client for the private OpenAgent runtime. The package contains
4
+ only the public wire contract and process-management helpers; the agent loop,
5
+ prompts, providers, tools, persistence, and checkpoint implementation remain in
6
+ the private `openagent-server` binary.
7
+
8
+ ```ts
9
+ import { spawnOpenAgent } from "@bang404/openagent-harness/node";
10
+
11
+ const agent = await spawnOpenAgent({ workspace: process.cwd() });
12
+ const [workspace] = await agent.client.listWorkspaces();
13
+ const session = await agent.client.createSession(workspace.id);
14
+ const result = await agent.client.runToCompletion(session.session_id, {
15
+ input: "Fix the failing tests",
16
+ });
17
+ console.log(result.status);
18
+ await agent.stop();
19
+ ```
20
+
21
+ The daemon listens on an ephemeral loopback port and uses a process-scoped
22
+ Bearer token. Do not expose the endpoint or token to untrusted code.
@@ -0,0 +1,28 @@
1
+ import { type CreateRunRequest, type HarnessCapabilities, type HarnessClientOptions, type HarnessEventEnvelope, type HarnessRunAccepted, type HarnessRunState, type HarnessSession, type HarnessWorkspace, type RunEventOptions, type UploadedAttachment } from "./types.js";
2
+ export declare class OpenAgentHarnessError extends Error {
3
+ readonly status?: number | undefined;
4
+ constructor(message: string, status?: number | undefined);
5
+ }
6
+ export declare class OpenAgentHarnessClient {
7
+ private readonly endpoint;
8
+ private readonly token;
9
+ private readonly fetchRequest;
10
+ constructor(options: HarnessClientOptions);
11
+ capabilities(): Promise<HarnessCapabilities>;
12
+ listWorkspaces(): Promise<HarnessWorkspace[]>;
13
+ createSession(workspaceId: string, roleId?: string): Promise<HarnessSession>;
14
+ getSession(sessionId: string): Promise<HarnessSession>;
15
+ deleteSession(sessionId: string): Promise<void>;
16
+ uploadAttachment(name: string, contentBase64: string): Promise<UploadedAttachment>;
17
+ createRun(sessionId: string, input: CreateRunRequest): Promise<HarnessRunAccepted>;
18
+ getRun(runId: string): Promise<HarnessRunState>;
19
+ cancelRun(runId: string): Promise<void>;
20
+ respondToInterrupt(runId: string, interruptId: string, response: unknown): Promise<void>;
21
+ events(runId: string, options?: RunEventOptions): AsyncGenerator<HarnessEventEnvelope>;
22
+ runToCompletion(sessionId: string, input: CreateRunRequest, options?: RunEventOptions): Promise<HarnessRunState>;
23
+ private request;
24
+ private headers;
25
+ private url;
26
+ private responseError;
27
+ }
28
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EAEzB,KAAK,kBAAkB,EACvB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACxB,MAAM,YAAY,CAAC;AAEpB,qBAAa,qBAAsB,SAAQ,KAAK;IAG5C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM;gBADxB,OAAO,EAAE,MAAM,EACN,MAAM,CAAC,EAAE,MAAM,YAAA;CAK3B;AAED,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;gBAEhC,OAAO,EAAE,oBAAoB;IAMnC,YAAY,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAUlD,cAAc,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAI7C,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAO5E,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAIhD,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrD,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAOlF,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAYlF,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAIzC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAOvF,MAAM,CACX,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,eAAoB,GAC5B,cAAc,CAAC,oBAAoB,CAAC;IAyCjC,eAAe,CACnB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,gBAAgB,EACvB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,eAAe,CAAC;YAUb,OAAO;IAcrB,OAAO,CAAC,OAAO;IAIf,OAAO,CAAC,GAAG;YAIG,aAAa;CAO5B"}
package/dist/client.js ADDED
@@ -0,0 +1,140 @@
1
+ import { OPENAGENT_HARNESS_PROTOCOL_VERSION, } from "./types.js";
2
+ export class OpenAgentHarnessError extends Error {
3
+ status;
4
+ constructor(message, status) {
5
+ super(message);
6
+ this.status = status;
7
+ this.name = "OpenAgentHarnessError";
8
+ }
9
+ }
10
+ export class OpenAgentHarnessClient {
11
+ endpoint;
12
+ token;
13
+ fetchRequest;
14
+ constructor(options) {
15
+ this.endpoint = options.endpoint.replace(/\/$/, "");
16
+ this.token = options.token;
17
+ this.fetchRequest = options.fetch ?? globalThis.fetch.bind(globalThis);
18
+ }
19
+ async capabilities() {
20
+ const capabilities = await this.request("/v1/capabilities");
21
+ if (capabilities.protocol_version !== OPENAGENT_HARNESS_PROTOCOL_VERSION) {
22
+ throw new OpenAgentHarnessError(`OpenAgent protocol mismatch: server ${capabilities.protocol_version}, client ${OPENAGENT_HARNESS_PROTOCOL_VERSION}`);
23
+ }
24
+ return capabilities;
25
+ }
26
+ listWorkspaces() {
27
+ return this.request("/v1/workspaces");
28
+ }
29
+ createSession(workspaceId, roleId) {
30
+ return this.request("/v1/sessions", {
31
+ method: "POST",
32
+ body: JSON.stringify({ workspace_id: workspaceId, role_id: roleId }),
33
+ });
34
+ }
35
+ getSession(sessionId) {
36
+ return this.request(`/v1/sessions/${encodeURIComponent(sessionId)}`);
37
+ }
38
+ async deleteSession(sessionId) {
39
+ await this.request(`/v1/sessions/${encodeURIComponent(sessionId)}`, { method: "DELETE" });
40
+ }
41
+ uploadAttachment(name, contentBase64) {
42
+ return this.request("/v1/attachments", {
43
+ method: "POST",
44
+ body: JSON.stringify({ name, content_base64: contentBase64 }),
45
+ });
46
+ }
47
+ createRun(sessionId, input) {
48
+ return this.request(`/v1/sessions/${encodeURIComponent(sessionId)}/runs`, {
49
+ method: "POST",
50
+ body: JSON.stringify({
51
+ input: input.input,
52
+ attachments: input.attachments ?? [],
53
+ model: input.model,
54
+ idempotency_key: input.idempotencyKey,
55
+ }),
56
+ });
57
+ }
58
+ getRun(runId) {
59
+ return this.request(`/v1/runs/${encodeURIComponent(runId)}`);
60
+ }
61
+ async cancelRun(runId) {
62
+ await this.request(`/v1/runs/${encodeURIComponent(runId)}/cancel`, { method: "POST" });
63
+ }
64
+ async respondToInterrupt(runId, interruptId, response) {
65
+ await this.request(`/v1/runs/${encodeURIComponent(runId)}/interrupts/${encodeURIComponent(interruptId)}/response`, { method: "POST", body: JSON.stringify({ response }) });
66
+ }
67
+ async *events(runId, options = {}) {
68
+ const response = await this.fetchRequest(this.url(`/v1/runs/${encodeURIComponent(runId)}/events`), { headers: this.headers(), signal: options.signal });
69
+ if (!response.ok || !response.body) {
70
+ throw await this.responseError(response);
71
+ }
72
+ const reader = response.body.getReader();
73
+ const decoder = new TextDecoder();
74
+ let buffer = "";
75
+ try {
76
+ while (true) {
77
+ const { value, done } = await reader.read();
78
+ buffer += decoder.decode(value, { stream: !done });
79
+ buffer = buffer.replace(/\r\n/g, "\n");
80
+ let boundary;
81
+ while ((boundary = buffer.indexOf("\n\n")) >= 0) {
82
+ const block = buffer.slice(0, boundary).replace(/\r/g, "");
83
+ buffer = buffer.slice(boundary + 2);
84
+ const data = block
85
+ .split("\n")
86
+ .filter((line) => line.startsWith("data:"))
87
+ .map((line) => line.slice(5).trimStart())
88
+ .join("\n");
89
+ if (!data)
90
+ continue;
91
+ const event = JSON.parse(data);
92
+ if (event.protocol_version !== OPENAGENT_HARNESS_PROTOCOL_VERSION) {
93
+ throw new OpenAgentHarnessError(`OpenAgent event protocol mismatch: ${event.protocol_version}`);
94
+ }
95
+ yield event;
96
+ }
97
+ if (done)
98
+ break;
99
+ }
100
+ }
101
+ finally {
102
+ await reader.cancel().catch(() => undefined);
103
+ }
104
+ }
105
+ async runToCompletion(sessionId, input, options = {}) {
106
+ const accepted = await this.createRun(sessionId, input);
107
+ for await (const event of this.events(accepted.run_id, options)) {
108
+ if (["completed", "cancelled", "failed"].includes(event.data.status)) {
109
+ return event.data;
110
+ }
111
+ }
112
+ return this.getRun(accepted.run_id);
113
+ }
114
+ async request(path, init = {}) {
115
+ const response = await this.fetchRequest(this.url(path), {
116
+ ...init,
117
+ headers: {
118
+ ...this.headers(),
119
+ ...(init.body ? { "content-type": "application/json" } : {}),
120
+ ...init.headers,
121
+ },
122
+ });
123
+ if (!response.ok)
124
+ throw await this.responseError(response);
125
+ if (response.status === 204)
126
+ return undefined;
127
+ return response.json();
128
+ }
129
+ headers() {
130
+ return { authorization: `Bearer ${this.token}` };
131
+ }
132
+ url(path) {
133
+ return `${this.endpoint}${path}`;
134
+ }
135
+ async responseError(response) {
136
+ const payload = (await response.json().catch(() => null));
137
+ return new OpenAgentHarnessError(payload?.error ?? `${response.status} ${response.statusText}`, response.status);
138
+ }
139
+ }
140
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,GAYnC,MAAM,YAAY,CAAC;AAEpB,MAAM,OAAO,qBAAsB,SAAQ,KAAK;IAGnC;IAFX,YACE,OAAe,EACN,MAAe;QAExB,KAAK,CAAC,OAAO,CAAC,CAAC;QAFN,WAAM,GAAN,MAAM,CAAS;QAGxB,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,sBAAsB;IAChB,QAAQ,CAAS;IACjB,KAAK,CAAS;IACd,YAAY,CAAe;IAE5C,YAAY,OAA6B;QACvC,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC3B,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACzE,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,OAAO,CAAsB,kBAAkB,CAAC,CAAC;QACjF,IAAI,YAAY,CAAC,gBAAgB,KAAK,kCAAkC,EAAE,CAAC;YACzE,MAAM,IAAI,qBAAqB,CAC7B,uCAAuC,YAAY,CAAC,gBAAgB,YAAY,kCAAkC,EAAE,CACrH,CAAC;QACJ,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,cAAc;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACxC,CAAC;IAED,aAAa,CAAC,WAAmB,EAAE,MAAe;QAChD,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE;YAClC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;SACrE,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,SAAiB;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB;QACnC,MAAM,IAAI,CAAC,OAAO,CAAC,gBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5F,CAAC;IAED,gBAAgB,CAAC,IAAY,EAAE,aAAqB;QAClD,OAAO,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE;YACrC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC;SAC9D,CAAC,CAAC;IACL,CAAC;IAED,SAAS,CAAC,SAAiB,EAAE,KAAuB;QAClD,OAAO,IAAI,CAAC,OAAO,CAAC,gBAAgB,kBAAkB,CAAC,SAAS,CAAC,OAAO,EAAE;YACxE,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;gBACpC,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,eAAe,EAAE,KAAK,CAAC,cAAc;aACtC,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAED,MAAM,CAAC,KAAa;QAClB,OAAO,IAAI,CAAC,OAAO,CAAC,YAAY,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,KAAa;QAC3B,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,kBAAkB,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACzF,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAa,EAAE,WAAmB,EAAE,QAAiB;QAC5E,MAAM,IAAI,CAAC,OAAO,CAChB,YAAY,kBAAkB,CAAC,KAAK,CAAC,eAAe,kBAAkB,CAAC,WAAW,CAAC,WAAW,EAC9F,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CACvD,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,CAAC,MAAM,CACX,KAAa,EACb,UAA2B,EAAE;QAE7B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CACtC,IAAI,CAAC,GAAG,CAAC,YAAY,kBAAkB,CAAC,KAAK,CAAC,SAAS,CAAC,EACxD,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CACpD,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;QAClC,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,IAAI,CAAC;YACH,OAAO,IAAI,EAAE,CAAC;gBACZ,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5C,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;gBACnD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBACvC,IAAI,QAAgB,CAAC;gBACrB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;oBAChD,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;oBAC3D,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;oBACpC,MAAM,IAAI,GAAG,KAAK;yBACf,KAAK,CAAC,IAAI,CAAC;yBACX,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;yBAC1C,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;yBACxC,IAAI,CAAC,IAAI,CAAC,CAAC;oBACd,IAAI,CAAC,IAAI;wBAAE,SAAS;oBACpB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyB,CAAC;oBACvD,IAAI,KAAK,CAAC,gBAAgB,KAAK,kCAAkC,EAAE,CAAC;wBAClE,MAAM,IAAI,qBAAqB,CAC7B,sCAAsC,KAAK,CAAC,gBAAgB,EAAE,CAC/D,CAAC;oBACJ,CAAC;oBACD,MAAM,KAAK,CAAC;gBACd,CAAC;gBACD,IAAI,IAAI;oBAAE,MAAM;YAClB,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CACnB,SAAiB,EACjB,KAAuB,EACvB,UAA2B,EAAE;QAE7B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACxD,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC;YAChE,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;gBACrE,OAAO,KAAK,CAAC,IAAI,CAAC;YACpB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,OAAoB,EAAE;QAC3D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACvD,GAAG,IAAI;YACP,OAAO,EAAE;gBACP,GAAG,IAAI,CAAC,OAAO,EAAE;gBACjB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5D,GAAG,IAAI,CAAC,OAAO;aAChB;SACF,CAAC,CAAC;QACH,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,MAAM,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QAC3D,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG;YAAE,OAAO,SAAc,CAAC;QACnD,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAC;IACvC,CAAC;IAEO,OAAO;QACb,OAAO,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;IACnD,CAAC;IAEO,GAAG,CAAC,IAAY;QACtB,OAAO,GAAG,IAAI,CAAC,QAAQ,GAAG,IAAI,EAAE,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,aAAa,CAAC,QAAkB;QAC5C,MAAM,OAAO,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAA8B,CAAC;QACvF,OAAO,IAAI,qBAAqB,CAC9B,OAAO,EAAE,KAAK,IAAI,GAAG,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,EAC7D,QAAQ,CAAC,MAAM,CAChB,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ export { OpenAgentHarnessClient, OpenAgentHarnessError } from "./client.js";
2
+ export * from "./types.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC5E,cAAc,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export { OpenAgentHarnessClient, OpenAgentHarnessError } from "./client.js";
2
+ export * from "./types.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAC5E,cAAc,YAAY,CAAC"}
package/dist/node.d.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { type ChildProcessWithoutNullStreams } from "node:child_process";
2
+ import { OpenAgentHarnessClient } from "./client.js";
3
+ export interface SpawnOpenAgentOptions {
4
+ binaryPath?: string;
5
+ workspace: string;
6
+ listen?: string;
7
+ env?: NodeJS.ProcessEnv;
8
+ startupTimeoutMs?: number;
9
+ }
10
+ export interface SpawnedOpenAgent {
11
+ client: OpenAgentHarnessClient;
12
+ endpoint: string;
13
+ /** Process-scoped credential. Keep it out of logs and untrusted child processes. */
14
+ token: string;
15
+ process: ChildProcessWithoutNullStreams;
16
+ stop(): Promise<void>;
17
+ }
18
+ export declare function spawnOpenAgent(options: SpawnOpenAgentOptions): Promise<SpawnedOpenAgent>;
19
+ //# sourceMappingURL=node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"AACA,OAAO,EAAS,KAAK,8BAA8B,EAAE,MAAM,oBAAoB,CAAC;AAEhF,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,sBAAsB,CAAC;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,8BAA8B,CAAC;IACxC,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAUD,wBAAsB,cAAc,CAClC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAyE3B"}
package/dist/node.js ADDED
@@ -0,0 +1,75 @@
1
+ import { randomBytes } from "node:crypto";
2
+ import { spawn } from "node:child_process";
3
+ import { createInterface } from "node:readline";
4
+ import { OpenAgentHarnessClient } from "./client.js";
5
+ export async function spawnOpenAgent(options) {
6
+ const binaryPath = options.binaryPath ?? "openagent-server";
7
+ const token = randomBytes(32).toString("hex");
8
+ const tokenEnv = `OPENAGENT_HARNESS_TOKEN_${process.pid}_${Date.now()}`;
9
+ const child = spawn(binaryPath, [
10
+ "--workspace",
11
+ options.workspace,
12
+ "--listen",
13
+ options.listen ?? "127.0.0.1:0",
14
+ "--token-env",
15
+ tokenEnv,
16
+ "--output",
17
+ "json",
18
+ ], {
19
+ env: { ...process.env, ...options.env, [tokenEnv]: token },
20
+ stdio: ["pipe", "pipe", "pipe"],
21
+ windowsHide: true,
22
+ });
23
+ const timeoutMs = options.startupTimeoutMs ?? 30_000;
24
+ const ready = await new Promise((resolve, reject) => {
25
+ const timeout = setTimeout(() => {
26
+ child.kill();
27
+ reject(new Error(`OpenAgent server did not become ready within ${timeoutMs}ms`));
28
+ }, timeoutMs);
29
+ const lines = createInterface({ input: child.stdout });
30
+ const fail = (error) => {
31
+ clearTimeout(timeout);
32
+ lines.close();
33
+ reject(error);
34
+ };
35
+ child.once("error", fail);
36
+ child.once("exit", (code) => fail(new Error(`OpenAgent server exited before ready (${code})`)));
37
+ lines.on("line", (line) => {
38
+ try {
39
+ const message = JSON.parse(line);
40
+ if (message.type !== "ready")
41
+ return;
42
+ clearTimeout(timeout);
43
+ child.removeListener("error", fail);
44
+ lines.close();
45
+ resolve(message);
46
+ }
47
+ catch {
48
+ // Tracing output may precede the machine-readable ready message.
49
+ }
50
+ });
51
+ });
52
+ const stop = async () => {
53
+ if (child.exitCode !== null)
54
+ return;
55
+ child.kill("SIGTERM");
56
+ await new Promise((resolve) => {
57
+ const timeout = setTimeout(() => {
58
+ child.kill("SIGKILL");
59
+ resolve();
60
+ }, 5_000);
61
+ child.once("exit", () => {
62
+ clearTimeout(timeout);
63
+ resolve();
64
+ });
65
+ });
66
+ };
67
+ return {
68
+ client: new OpenAgentHarnessClient({ endpoint: ready.endpoint, token }),
69
+ endpoint: ready.endpoint,
70
+ token,
71
+ process: child,
72
+ stop,
73
+ };
74
+ }
75
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ export declare const OPENAGENT_HARNESS_PROTOCOL_VERSION = 2;
2
+ export interface HarnessCapabilities {
3
+ protocol_version: number;
4
+ server_version: string;
5
+ capabilities: string[];
6
+ }
7
+ export interface HarnessWorkspace {
8
+ id: string;
9
+ name: string;
10
+ }
11
+ export interface HarnessSession {
12
+ session_id: string;
13
+ title?: string | null;
14
+ status?: "idle" | "running" | "interrupted";
15
+ }
16
+ export interface ModelBinding {
17
+ provider_id: string;
18
+ model: string;
19
+ }
20
+ export interface CreateRunRequest {
21
+ input: string;
22
+ attachments?: string[];
23
+ model?: ModelBinding;
24
+ idempotencyKey?: string;
25
+ }
26
+ export interface HarnessRunAccepted {
27
+ run_id: string;
28
+ session_id: string;
29
+ status: "accepted";
30
+ }
31
+ export type HarnessRunStatus = "accepted" | "running" | "interrupted" | "completed" | "cancelled" | "failed";
32
+ export interface HarnessMessage {
33
+ id: string;
34
+ role: "user" | "assistant" | string;
35
+ text: string;
36
+ status: "completed" | "aborted";
37
+ timestamp: number;
38
+ }
39
+ export interface HarnessInterrupt {
40
+ id: string;
41
+ kind: "ask_user" | "tool_approval" | "render_mermaid" | string;
42
+ tool_name: string;
43
+ arguments: unknown;
44
+ fields: unknown[];
45
+ }
46
+ export interface HarnessRunState {
47
+ run_id: string;
48
+ session_id: string;
49
+ status: HarnessRunStatus;
50
+ checkpoint_id?: string | null;
51
+ messages: HarnessMessage[];
52
+ interrupts: HarnessInterrupt[];
53
+ created_at: number;
54
+ }
55
+ export interface HarnessEventEnvelope {
56
+ protocol_version: number;
57
+ run_id: string;
58
+ sequence: number;
59
+ event_type: "run.state";
60
+ data: HarnessRunState;
61
+ }
62
+ export interface UploadedAttachment {
63
+ path: string;
64
+ name: string;
65
+ kind: "image" | "document";
66
+ mime_type: string;
67
+ }
68
+ export interface HarnessClientOptions {
69
+ endpoint: string;
70
+ token: string;
71
+ fetch?: HarnessFetch;
72
+ }
73
+ export type HarnessFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
74
+ export interface RunEventOptions {
75
+ signal?: AbortSignal;
76
+ }
77
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kCAAkC,IAAI,CAAC;AAEpD,MAAM,WAAW,mBAAmB;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;CAC7C;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GACxB,UAAU,GACV,SAAS,GACT,aAAa,GACb,WAAW,GACX,WAAW,GACX,QAAQ,CAAC;AAEb,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,GAAG,SAAS,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,eAAe,GAAG,gBAAgB,GAAG,MAAM,CAAC;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,UAAU,EAAE,gBAAgB,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,EAAE,MAAM,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,WAAW,CAAC;IACxB,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,GAAG,UAAU,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAE/F,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export const OPENAGENT_HARNESS_PROTOCOL_VERSION = 2;
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kCAAkC,GAAG,CAAC,CAAC"}
package/openapi.yaml ADDED
@@ -0,0 +1,294 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: OpenAgent Harness API
4
+ version: 0.1.0
5
+ description: >-
6
+ Behavior-free public contract for a private OpenAgent runtime process.
7
+ All endpoints require a process-scoped Bearer token and are served only on
8
+ loopback interfaces.
9
+ servers:
10
+ - url: http://127.0.0.1:{port}
11
+ variables:
12
+ port:
13
+ default: "32123"
14
+ security:
15
+ - bearerAuth: []
16
+ paths:
17
+ /v1/capabilities:
18
+ get:
19
+ operationId: getCapabilities
20
+ responses:
21
+ "200":
22
+ description: Supported protocol and runtime capabilities
23
+ content:
24
+ application/json:
25
+ schema:
26
+ $ref: "#/components/schemas/Capabilities"
27
+ /v1/workspaces:
28
+ get:
29
+ operationId: listWorkspaces
30
+ responses:
31
+ "200":
32
+ description: Workspaces authorized when the daemon started
33
+ content:
34
+ application/json:
35
+ schema:
36
+ type: array
37
+ items:
38
+ $ref: "#/components/schemas/Workspace"
39
+ /v1/attachments:
40
+ post:
41
+ operationId: uploadAttachment
42
+ requestBody:
43
+ required: true
44
+ content:
45
+ application/json:
46
+ schema:
47
+ type: object
48
+ required: [name, content_base64]
49
+ properties:
50
+ name: { type: string, maxLength: 255 }
51
+ content_base64: { type: string }
52
+ responses:
53
+ "200":
54
+ description: Stored attachment locator
55
+ content:
56
+ application/json:
57
+ schema:
58
+ $ref: "#/components/schemas/Attachment"
59
+ /v1/sessions:
60
+ post:
61
+ operationId: createSession
62
+ requestBody:
63
+ required: true
64
+ content:
65
+ application/json:
66
+ schema:
67
+ type: object
68
+ required: [workspace_id]
69
+ properties:
70
+ workspace_id: { type: string }
71
+ role_id: { type: [string, "null"] }
72
+ responses:
73
+ "201":
74
+ description: Created harness session
75
+ content:
76
+ application/json:
77
+ schema:
78
+ $ref: "#/components/schemas/Session"
79
+ /v1/sessions/{session_id}:
80
+ parameters:
81
+ - $ref: "#/components/parameters/SessionId"
82
+ get:
83
+ operationId: getSession
84
+ responses:
85
+ "200":
86
+ description: Session state without private transcript records
87
+ content:
88
+ application/json:
89
+ schema:
90
+ $ref: "#/components/schemas/SessionState"
91
+ delete:
92
+ operationId: deleteSession
93
+ responses:
94
+ "204": { description: Session deleted }
95
+ /v1/sessions/{session_id}/runs:
96
+ parameters:
97
+ - $ref: "#/components/parameters/SessionId"
98
+ post:
99
+ operationId: createRun
100
+ requestBody:
101
+ required: true
102
+ content:
103
+ application/json:
104
+ schema:
105
+ $ref: "#/components/schemas/CreateRun"
106
+ responses:
107
+ "202":
108
+ description: Run accepted
109
+ content:
110
+ application/json:
111
+ schema:
112
+ $ref: "#/components/schemas/RunAccepted"
113
+ /v1/runs/{run_id}:
114
+ parameters:
115
+ - $ref: "#/components/parameters/RunId"
116
+ get:
117
+ operationId: getRun
118
+ responses:
119
+ "200":
120
+ description: Public projection of one run
121
+ content:
122
+ application/json:
123
+ schema:
124
+ $ref: "#/components/schemas/RunState"
125
+ /v1/runs/{run_id}/events:
126
+ parameters:
127
+ - $ref: "#/components/parameters/RunId"
128
+ get:
129
+ operationId: streamRunEvents
130
+ responses:
131
+ "200":
132
+ description: SSE stream of run.state envelopes
133
+ content:
134
+ text/event-stream:
135
+ schema:
136
+ $ref: "#/components/schemas/EventEnvelope"
137
+ /v1/runs/{run_id}/cancel:
138
+ parameters:
139
+ - $ref: "#/components/parameters/RunId"
140
+ post:
141
+ operationId: cancelRun
142
+ responses:
143
+ "202": { description: Cancellation accepted }
144
+ /v1/runs/{run_id}/interrupts/{interrupt_id}/response:
145
+ parameters:
146
+ - $ref: "#/components/parameters/RunId"
147
+ - name: interrupt_id
148
+ in: path
149
+ required: true
150
+ schema: { type: string }
151
+ post:
152
+ operationId: respondToInterrupt
153
+ requestBody:
154
+ required: true
155
+ content:
156
+ application/json:
157
+ schema:
158
+ type: object
159
+ required: [response]
160
+ properties:
161
+ response: {}
162
+ responses:
163
+ "202": { description: Response accepted }
164
+ components:
165
+ securitySchemes:
166
+ bearerAuth:
167
+ type: http
168
+ scheme: bearer
169
+ parameters:
170
+ SessionId:
171
+ name: session_id
172
+ in: path
173
+ required: true
174
+ schema: { type: string, format: uuid }
175
+ RunId:
176
+ name: run_id
177
+ in: path
178
+ required: true
179
+ schema: { type: string, format: uuid }
180
+ schemas:
181
+ Capabilities:
182
+ type: object
183
+ required: [protocol_version, server_version, capabilities]
184
+ properties:
185
+ protocol_version: { type: integer, const: 2 }
186
+ server_version: { type: string }
187
+ capabilities:
188
+ type: array
189
+ items: { type: string }
190
+ Workspace:
191
+ type: object
192
+ required: [id, name]
193
+ properties:
194
+ id: { type: string }
195
+ name: { type: string }
196
+ Session:
197
+ type: object
198
+ required: [session_id]
199
+ properties:
200
+ session_id: { type: string, format: uuid }
201
+ SessionState:
202
+ allOf:
203
+ - $ref: "#/components/schemas/Session"
204
+ - type: object
205
+ required: [status]
206
+ properties:
207
+ title: { type: [string, "null"] }
208
+ status: { enum: [idle, running, interrupted] }
209
+ ModelBinding:
210
+ type: object
211
+ required: [provider_id, model]
212
+ properties:
213
+ provider_id: { type: string }
214
+ model: { type: string }
215
+ CreateRun:
216
+ type: object
217
+ required: [input]
218
+ properties:
219
+ input: { type: string, maxLength: 65536 }
220
+ attachments:
221
+ type: array
222
+ maxItems: 8
223
+ items: { type: string }
224
+ model:
225
+ $ref: "#/components/schemas/ModelBinding"
226
+ idempotency_key: { type: string, minLength: 1, maxLength: 128 }
227
+ RunAccepted:
228
+ type: object
229
+ required: [run_id, session_id, status]
230
+ properties:
231
+ run_id: { type: string, format: uuid }
232
+ session_id: { type: string, format: uuid }
233
+ status: { const: accepted }
234
+ Message:
235
+ type: object
236
+ required: [id, role, text, status, timestamp]
237
+ properties:
238
+ id: { type: string }
239
+ role: { type: string }
240
+ text: { type: string }
241
+ status: { enum: [completed, aborted] }
242
+ timestamp: { type: integer }
243
+ Interrupt:
244
+ type: object
245
+ required: [id, kind, tool_name, arguments, fields]
246
+ properties:
247
+ id: { type: string }
248
+ kind: { type: string }
249
+ tool_name: { type: string }
250
+ arguments: {}
251
+ fields:
252
+ type: array
253
+ items: {}
254
+ RunState:
255
+ type: object
256
+ required: [run_id, session_id, status, messages, interrupts, created_at]
257
+ properties:
258
+ run_id: { type: string, format: uuid }
259
+ session_id: { type: string, format: uuid }
260
+ status:
261
+ enum: [accepted, running, interrupted, completed, cancelled, failed]
262
+ checkpoint_id: { type: [string, "null"] }
263
+ messages:
264
+ type: array
265
+ items:
266
+ $ref: "#/components/schemas/Message"
267
+ interrupts:
268
+ type: array
269
+ items:
270
+ $ref: "#/components/schemas/Interrupt"
271
+ created_at: { type: integer }
272
+ Attachment:
273
+ type: object
274
+ required: [path, name, kind, mime_type]
275
+ properties:
276
+ path: { type: string }
277
+ name: { type: string }
278
+ kind: { enum: [image, document] }
279
+ mime_type: { type: string }
280
+ EventEnvelope:
281
+ type: object
282
+ required: [protocol_version, run_id, sequence, event_type, data]
283
+ properties:
284
+ protocol_version: { type: integer, const: 2 }
285
+ run_id: { type: string, format: uuid }
286
+ sequence: { type: integer, minimum: 1 }
287
+ event_type: { const: run.state }
288
+ data:
289
+ $ref: "#/components/schemas/RunState"
290
+ Error:
291
+ type: object
292
+ required: [error]
293
+ properties:
294
+ error: { type: string }
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@bang404/openagent-harness",
3
+ "version": "0.1.0",
4
+ "description": "Thin client for the private OpenAgent harness runtime",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/BANG404/openagent-sdk.git",
9
+ "directory": "harness-typescript"
10
+ },
11
+ "type": "module",
12
+ "files": [
13
+ "dist",
14
+ "README.md",
15
+ "LICENSE",
16
+ "openapi.yaml"
17
+ ],
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ },
23
+ "./node": {
24
+ "types": "./dist/node.d.ts",
25
+ "import": "./dist/node.js"
26
+ }
27
+ },
28
+ "scripts": {
29
+ "build": "tsc -p tsconfig.build.json",
30
+ "check": "tsc -p tsconfig.json --noEmit",
31
+ "check:openapi": "bun scripts/verify-openapi.ts",
32
+ "test": "bun test",
33
+ "prepack": "bun run build"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "devDependencies": {
39
+ "@types/bun": "latest",
40
+ "@types/node": "^24.0.0",
41
+ "typescript": "~5.6.2"
42
+ }
43
+ }