@oharness/engine 0.10.0 → 0.12.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.
Files changed (118) hide show
  1. package/dist/acp/claude.d.ts +34 -0
  2. package/dist/acp/claude.js +122 -0
  3. package/dist/acp/claude.js.map +1 -0
  4. package/dist/acp/client.d.ts +193 -0
  5. package/dist/acp/client.js +279 -0
  6. package/dist/acp/client.js.map +1 -0
  7. package/dist/acp/runner.d.ts +80 -0
  8. package/dist/acp/runner.js +159 -0
  9. package/dist/acp/runner.js.map +1 -0
  10. package/dist/agent/agent.d.ts +51 -1
  11. package/dist/agent/agent.js +322 -1
  12. package/dist/agent/agent.js.map +1 -1
  13. package/dist/agent/hooks.js +6 -6
  14. package/dist/agent/hooks.js.map +1 -1
  15. package/dist/agent/session.d.ts +2 -0
  16. package/dist/agent/session.js +19 -2
  17. package/dist/agent/session.js.map +1 -1
  18. package/dist/agent/skills.d.ts +16 -3
  19. package/dist/agent/skills.js +36 -2
  20. package/dist/agent/skills.js.map +1 -1
  21. package/dist/agent/subagent.d.ts +24 -2
  22. package/dist/agent/subagent.js +76 -16
  23. package/dist/agent/subagent.js.map +1 -1
  24. package/dist/auth/index.d.ts +3 -1
  25. package/dist/auth/index.js +3 -1
  26. package/dist/auth/index.js.map +1 -1
  27. package/dist/auth/manager.js +4 -0
  28. package/dist/auth/manager.js.map +1 -1
  29. package/dist/auth/oauth.d.ts +33 -0
  30. package/dist/auth/oauth.js +59 -8
  31. package/dist/auth/oauth.js.map +1 -1
  32. package/dist/auth/providers/anthropic.d.ts +25 -5
  33. package/dist/auth/providers/anthropic.js +47 -6
  34. package/dist/auth/providers/anthropic.js.map +1 -1
  35. package/dist/auth/providers/chatgpt.d.ts +8 -0
  36. package/dist/auth/providers/chatgpt.js +180 -0
  37. package/dist/auth/providers/chatgpt.js.map +1 -0
  38. package/dist/auth/providers/openrouter.d.ts +2 -0
  39. package/dist/auth/providers/openrouter.js +101 -0
  40. package/dist/auth/providers/openrouter.js.map +1 -0
  41. package/dist/auth/types.d.ts +15 -0
  42. package/dist/auth/types.js.map +1 -1
  43. package/dist/browser/index.d.ts +1 -1
  44. package/dist/browser/plugin.d.ts +6 -1
  45. package/dist/browser/plugin.js.map +1 -1
  46. package/dist/browser/session.d.ts +47 -0
  47. package/dist/browser/session.js +177 -2
  48. package/dist/browser/session.js.map +1 -1
  49. package/dist/browser/tools.js +139 -18
  50. package/dist/browser/tools.js.map +1 -1
  51. package/dist/computer/cua-driver.d.ts +60 -1
  52. package/dist/computer/cua-driver.js +149 -5
  53. package/dist/computer/cua-driver.js.map +1 -1
  54. package/dist/computer/helper-client.d.ts +3 -1
  55. package/dist/computer/helper-client.js +3 -0
  56. package/dist/computer/helper-client.js.map +1 -1
  57. package/dist/computer/index.d.ts +3 -2
  58. package/dist/computer/index.js +1 -1
  59. package/dist/computer/index.js.map +1 -1
  60. package/dist/computer/mode.d.ts +15 -0
  61. package/dist/computer/mode.js +11 -1
  62. package/dist/computer/mode.js.map +1 -1
  63. package/dist/computer/session.d.ts +36 -7
  64. package/dist/computer/session.js +118 -17
  65. package/dist/computer/session.js.map +1 -1
  66. package/dist/computer/target.d.ts +19 -0
  67. package/dist/computer/target.js.map +1 -1
  68. package/dist/computer/tools.js +135 -8
  69. package/dist/computer/tools.js.map +1 -1
  70. package/dist/config.d.ts +16 -0
  71. package/dist/config.js +2 -0
  72. package/dist/config.js.map +1 -1
  73. package/dist/foreign.d.ts +81 -0
  74. package/dist/foreign.js +198 -0
  75. package/dist/foreign.js.map +1 -0
  76. package/dist/harness.d.ts +79 -0
  77. package/dist/harness.js +241 -17
  78. package/dist/harness.js.map +1 -1
  79. package/dist/mcp/manager.d.ts +15 -0
  80. package/dist/mcp/manager.js +28 -1
  81. package/dist/mcp/manager.js.map +1 -1
  82. package/dist/mcp/registry.d.ts +2 -0
  83. package/dist/mcp/registry.js +1 -0
  84. package/dist/mcp/registry.js.map +1 -1
  85. package/dist/mcp/registry.json +394 -1
  86. package/dist/paths.d.ts +19 -0
  87. package/dist/paths.js +38 -0
  88. package/dist/paths.js.map +1 -1
  89. package/dist/plugin-market.d.ts +57 -0
  90. package/dist/plugin-market.js +229 -0
  91. package/dist/plugin-market.js.map +1 -0
  92. package/dist/plugin-market.json +1246 -0
  93. package/dist/plugins.d.ts +49 -2
  94. package/dist/plugins.js +252 -10
  95. package/dist/plugins.js.map +1 -1
  96. package/dist/providers/catalog.json +14 -3
  97. package/dist/providers/models-dev.d.ts +15 -0
  98. package/dist/providers/models-dev.js +14 -0
  99. package/dist/providers/models-dev.js.map +1 -1
  100. package/dist/providers/piai.d.ts +38 -1
  101. package/dist/providers/piai.js +70 -2
  102. package/dist/providers/piai.js.map +1 -1
  103. package/dist/providers/registry.d.ts +16 -1
  104. package/dist/providers/registry.js +42 -11
  105. package/dist/providers/registry.js.map +1 -1
  106. package/dist/runtime-plugins/builtin/studio.d.ts +7 -0
  107. package/dist/runtime-plugins/builtin/studio.js +69 -4
  108. package/dist/runtime-plugins/builtin/studio.js.map +1 -1
  109. package/dist/tools/builtin/bash.js +6 -10
  110. package/dist/tools/builtin/bash.js.map +1 -1
  111. package/dist/util/shell.d.ts +30 -0
  112. package/dist/util/shell.js +70 -0
  113. package/dist/util/shell.js.map +1 -1
  114. package/dist/util/toml.d.ts +22 -0
  115. package/dist/util/toml.js +305 -0
  116. package/dist/util/toml.js.map +1 -0
  117. package/package.json +4 -4
  118. package/skills/media-generation/SKILL.md +22 -1
@@ -0,0 +1,34 @@
1
+ import type { SubagentDefinition } from "../agent/subagent.ts";
2
+ /**
3
+ * Claude Code as a subagent, through the ACP adapter.
4
+ *
5
+ * The rules this follows are Anthropic's, and they are the design:
6
+ *
7
+ * - It is the user's own `claude`, unmodified, signed in through Claude
8
+ * Code's own login. The adapter is pointed at that binary
9
+ * (`CLAUDE_CODE_EXECUTABLE`) rather than at a copy bundled here.
10
+ * - OHarness offers no Claude login and reads no token. The ACP client
11
+ * advertises no auth capability, so the adapter cannot ask it to run one;
12
+ * a Claude Code that is not signed in gets a sentence pointing at the
13
+ * terminal hand-off, where the user signs in to Claude Code themselves.
14
+ * - Never `--hide-claude-auth`, never an auth method stripped.
15
+ * - Called "Claude Agent", the name Anthropic allows for this, not
16
+ * "Claude Code".
17
+ *
18
+ * Whatever it spends is spent on the user's own Claude account.
19
+ */
20
+ /** The adapter, pinned: it ships often and leans on protocol extensions. */
21
+ export declare const CLAUDE_ACP_PACKAGE = "@agentclientprotocol/claude-agent-acp@0.89.0";
22
+ /** The oldest Node the adapter runs on (its `engines.node`). */
23
+ export declare const ADAPTER_MIN_NODE = 22;
24
+ /** The first executable of these names on PATH or in the usual places. */
25
+ export declare function findExecutable(names: string[], env?: NodeJS.ProcessEnv, extra?: string[]): Promise<string | undefined>;
26
+ /**
27
+ * The Claude Agent subagent, or nothing when this machine cannot run it.
28
+ *
29
+ * Offered only when both halves are present: the user's `claude`, and `npx`
30
+ * to fetch the adapter on first use. Whether Claude Code is signed in is not
31
+ * checked here — that would mean reading its credentials — and is found out
32
+ * the honest way, by the adapter refusing to start a session.
33
+ */
34
+ export declare function claudeAgent(env?: NodeJS.ProcessEnv, extra?: string[]): Promise<SubagentDefinition | undefined>;
@@ -0,0 +1,122 @@
1
+ import { execFile } from "node:child_process";
2
+ import { access, constants } from "node:fs/promises";
3
+ import { homedir } from "node:os";
4
+ import path from "node:path";
5
+ /**
6
+ * Claude Code as a subagent, through the ACP adapter.
7
+ *
8
+ * The rules this follows are Anthropic's, and they are the design:
9
+ *
10
+ * - It is the user's own `claude`, unmodified, signed in through Claude
11
+ * Code's own login. The adapter is pointed at that binary
12
+ * (`CLAUDE_CODE_EXECUTABLE`) rather than at a copy bundled here.
13
+ * - OHarness offers no Claude login and reads no token. The ACP client
14
+ * advertises no auth capability, so the adapter cannot ask it to run one;
15
+ * a Claude Code that is not signed in gets a sentence pointing at the
16
+ * terminal hand-off, where the user signs in to Claude Code themselves.
17
+ * - Never `--hide-claude-auth`, never an auth method stripped.
18
+ * - Called "Claude Agent", the name Anthropic allows for this, not
19
+ * "Claude Code".
20
+ *
21
+ * Whatever it spends is spent on the user's own Claude account.
22
+ */
23
+ /** The adapter, pinned: it ships often and leans on protocol extensions. */
24
+ export const CLAUDE_ACP_PACKAGE = "@agentclientprotocol/claude-agent-acp@0.89.0";
25
+ const EXE = process.platform === "win32" ? ["claude.exe", "claude.cmd"] : ["claude"];
26
+ const NPX = process.platform === "win32" ? ["npx.cmd", "npx.exe"] : ["npx"];
27
+ const NODE = process.platform === "win32" ? ["node.exe"] : ["node"];
28
+ /** The oldest Node the adapter runs on (its `engines.node`). */
29
+ export const ADAPTER_MIN_NODE = 22;
30
+ /**
31
+ * Where to look beyond PATH. A desktop app started from the Dock inherits a
32
+ * PATH without the user's shell profile, which is exactly where a CLI
33
+ * installer puts itself.
34
+ */
35
+ function extraDirs() {
36
+ const home = homedir();
37
+ return process.platform === "win32"
38
+ ? [path.join(process.env["APPDATA"] ?? home, "npm"), path.join(home, ".local", "bin")]
39
+ : [
40
+ path.join(home, ".local", "bin"),
41
+ path.join(home, ".claude", "local"),
42
+ "/opt/homebrew/bin",
43
+ "/usr/local/bin",
44
+ path.join(home, ".npm-global", "bin"),
45
+ ];
46
+ }
47
+ /** The first executable of these names on PATH or in the usual places. */
48
+ export async function findExecutable(names, env = process.env, extra = extraDirs()) {
49
+ const dirs = [...(env["PATH"] ?? "").split(path.delimiter).filter(Boolean), ...extra];
50
+ for (const dir of dirs) {
51
+ for (const name of names) {
52
+ const candidate = path.join(dir, name);
53
+ try {
54
+ await access(candidate, constants.X_OK);
55
+ return candidate;
56
+ }
57
+ catch {
58
+ // Not here.
59
+ }
60
+ }
61
+ }
62
+ return undefined;
63
+ }
64
+ /**
65
+ * The Claude Agent subagent, or nothing when this machine cannot run it.
66
+ *
67
+ * Offered only when both halves are present: the user's `claude`, and `npx`
68
+ * to fetch the adapter on first use. Whether Claude Code is signed in is not
69
+ * checked here — that would mean reading its credentials — and is found out
70
+ * the honest way, by the adapter refusing to start a session.
71
+ */
72
+ export async function claudeAgent(env = process.env, extra = extraDirs()) {
73
+ const claude = await findExecutable(EXE, env, extra);
74
+ if (!claude)
75
+ return undefined;
76
+ const npx = await findExecutable(NPX, env, extra);
77
+ if (!npx)
78
+ return undefined;
79
+ // npx finds node beside itself; a stripped PATH would not.
80
+ const pathWithTools = [path.dirname(npx), path.dirname(claude), env["PATH"] ?? ""].filter(Boolean).join(path.delimiter);
81
+ const unavailable = await nodeProblem({ ...env, PATH: pathWithTools });
82
+ return {
83
+ name: "claude",
84
+ description: "Claude Agent: hands the task to the user's own Claude Code install, signed in with their own Claude account, " +
85
+ "which pays for it. Use only when the user asks for Claude Code or their Claude plan to do the work.",
86
+ // Unused: the agent runs on its own prompt and its own CLAUDE.md.
87
+ systemPrompt: "",
88
+ runtime: {
89
+ kind: "acp",
90
+ command: npx,
91
+ args: ["-y", CLAUDE_ACP_PACKAGE],
92
+ env: { CLAUDE_CODE_EXECUTABLE: claude, PATH: pathWithTools },
93
+ signInHint: "Claude Code is not signed in. Open Claude Code from the project menu (or run `claude` in a terminal), " +
94
+ "sign in there with your own Claude account, then try again.",
95
+ ...(unavailable ? { unavailable } : {}),
96
+ },
97
+ };
98
+ }
99
+ /**
100
+ * Why the adapter cannot run on this machine's Node, if it cannot.
101
+ *
102
+ * Checked up front because the failure otherwise arrives as the adapter
103
+ * exiting with an engine error halfway through a task, which reads like a
104
+ * bug in Claude Code. The agent is still offered when Node is too old — left
105
+ * out, nobody would learn why it was missing — and answers with this instead.
106
+ */
107
+ async function nodeProblem(env) {
108
+ const node = await findExecutable(NODE, env, []);
109
+ const need = `Claude Agent needs Node.js ${ADAPTER_MIN_NODE} or newer`;
110
+ if (!node)
111
+ return `${need}, and none was found on PATH. Install it from https://nodejs.org, then restart OHarness.`;
112
+ const version = await new Promise((resolve) => {
113
+ execFile(node, ["--version"], { timeout: 5_000, env }, (err, stdout) => resolve(err ? undefined : String(stdout).trim()));
114
+ });
115
+ const major = Number(/^v?(\d+)\./.exec(version ?? "")?.[1]);
116
+ // A version that cannot be read is let through: the adapter will say
117
+ // whatever is wrong more precisely than a guess here could.
118
+ if (!Number.isFinite(major) || major >= ADAPTER_MIN_NODE)
119
+ return undefined;
120
+ return `${need}; this machine has ${version} (${node}). Update Node, then restart OHarness.`;
121
+ }
122
+ //# sourceMappingURL=claude.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude.js","sourceRoot":"","sources":["../../src/acp/claude.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,193 @@
1
+ /**
2
+ * A client for the Agent Client Protocol (agentclientprotocol.com).
3
+ *
4
+ * ACP is how an editor drives an agent it did not write: the agent runs as a
5
+ * child process and the two exchange JSON-RPC 2.0 messages, one per line, over
6
+ * its stdin and stdout. This is the client half, written against the baseline
7
+ * methods only — `initialize`, `session/new`, `session/prompt`,
8
+ * `session/cancel`, the `session/update` stream and
9
+ * `session/request_permission` — because the agents that speak it add
10
+ * extensions faster than any one client should chase.
11
+ *
12
+ * Deliberately small and dependency-free rather than built on the SDK: the
13
+ * surface used here is a few hundred lines of protocol, and owning it keeps
14
+ * the fake agent in the tests and the real one on the same footing.
15
+ *
16
+ * What it advertises is a choice. `fs`, when the caller supplies a file
17
+ * system, so the agent's reads and writes pass through this harness's
18
+ * workspace policy instead of around it. No `terminal`: the agent runs its
19
+ * own commands. And no `auth` capability: an
20
+ * agent that needs signing in is told so and left to its own login, never
21
+ * offered one from here — for Claude Code that is the difference between the
22
+ * user signing in to Claude Code and OHarness brokering a Claude login.
23
+ */
24
+ export declare const ACP_PROTOCOL_VERSION = 1;
25
+ /** JSON-RPC error code ACP uses for "this agent needs signing in". */
26
+ export declare const ACP_AUTH_REQUIRED = -32000;
27
+ export type AcpStopReason = "end_turn" | "max_tokens" | "max_turn_requests" | "refusal" | "cancelled";
28
+ export interface AcpToolCall {
29
+ toolCallId: string;
30
+ title?: string | null;
31
+ kind?: string | null;
32
+ status?: "pending" | "in_progress" | "completed" | "failed" | null;
33
+ rawInput?: unknown;
34
+ }
35
+ /** The `session/update` variants this client acts on; the rest are ignored. */
36
+ export type AcpUpdate = {
37
+ sessionUpdate: "agent_message_chunk";
38
+ content: {
39
+ type: string;
40
+ text?: string;
41
+ };
42
+ } | {
43
+ sessionUpdate: "agent_thought_chunk";
44
+ content: {
45
+ type: string;
46
+ text?: string;
47
+ };
48
+ } | ({
49
+ sessionUpdate: "tool_call";
50
+ } & AcpToolCall) | ({
51
+ sessionUpdate: "tool_call_update";
52
+ } & AcpToolCall) | {
53
+ sessionUpdate: "plan";
54
+ entries: Array<{
55
+ content: string;
56
+ status?: string;
57
+ }>;
58
+ } | {
59
+ sessionUpdate: "notice";
60
+ severity?: string;
61
+ title: string;
62
+ } | {
63
+ sessionUpdate: string;
64
+ [key: string]: unknown;
65
+ };
66
+ export interface AcpPermissionOption {
67
+ optionId: string;
68
+ name: string;
69
+ kind: "allow_once" | "allow_always" | "reject_once" | "reject_always";
70
+ }
71
+ export interface AcpPermissionRequest {
72
+ sessionId: string;
73
+ toolCall: AcpToolCall;
74
+ options: AcpPermissionOption[];
75
+ }
76
+ export type AcpPermissionOutcome = {
77
+ outcome: "cancelled";
78
+ } | {
79
+ outcome: "selected";
80
+ optionId: string;
81
+ };
82
+ export interface AcpLaunch {
83
+ command: string;
84
+ args?: string[];
85
+ env?: Record<string, string>;
86
+ cwd?: string;
87
+ /**
88
+ * Answer the agent's file reads and writes. Supplied, the `fs` capability
89
+ * is advertised; absent, the agent uses its own tools for files.
90
+ */
91
+ fs?: AcpFileSystem;
92
+ }
93
+ export interface AcpFileSystem {
94
+ /** `line` is 1-based; `limit` caps the lines returned. */
95
+ read(path: string, line?: number, limit?: number): Promise<string>;
96
+ write(path: string, content: string): Promise<void>;
97
+ }
98
+ /** An MCP server as ACP's `session/new` takes it. */
99
+ export type AcpMcpServer = {
100
+ name: string;
101
+ command: string;
102
+ args: string[];
103
+ env: Array<{
104
+ name: string;
105
+ value: string;
106
+ }>;
107
+ } | {
108
+ type: "http";
109
+ name: string;
110
+ url: string;
111
+ headers: Array<{
112
+ name: string;
113
+ value: string;
114
+ }>;
115
+ };
116
+ export interface AcpHandlers {
117
+ onUpdate?(update: AcpUpdate): void;
118
+ /** Answer a permission question. With no handler, every question is refused. */
119
+ onPermission?(request: AcpPermissionRequest): Promise<AcpPermissionOutcome>;
120
+ }
121
+ /** An error the agent returned, with its JSON-RPC code. */
122
+ export declare class AcpError extends Error {
123
+ readonly code: number;
124
+ readonly data?: unknown;
125
+ constructor(message: string, code: number, data?: unknown);
126
+ }
127
+ export declare class AcpClient {
128
+ private readonly proc;
129
+ private readonly pending;
130
+ private seq;
131
+ private stderr;
132
+ private closed;
133
+ private exitError?;
134
+ /** Prompt-scoped handlers; `session/update` belongs to whoever is prompting. */
135
+ private handlers;
136
+ private readonly fs?;
137
+ authMethods: Array<{
138
+ id: string;
139
+ name?: string;
140
+ }>;
141
+ /** What the agent said it can do, from `initialize`. */
142
+ capabilities: {
143
+ loadSession?: boolean;
144
+ mcpCapabilities?: {
145
+ http?: boolean;
146
+ };
147
+ };
148
+ constructor(launch: AcpLaunch);
149
+ /** Handshake. Resolves with the agent's advertised login methods. */
150
+ initialize(clientName?: string, clientVersion?: string): Promise<void>;
151
+ newSession(cwd: string, mcpServers?: AcpMcpServer[]): Promise<string>;
152
+ /**
153
+ * Pick up an earlier session where it left off, for a follow-up. The agent
154
+ * replays the conversation as updates first; nobody is prompting yet, so
155
+ * those land on no handler and are dropped.
156
+ */
157
+ loadSession(sessionId: string, cwd: string, mcpServers?: AcpMcpServer[]): Promise<void>;
158
+ /** HTTP servers only for an agent that said it takes them. */
159
+ private supported;
160
+ /**
161
+ * One turn: the prompt in, the agent's updates out through `handlers`, and
162
+ * its stop reason when the turn ends. Aborting sends `session/cancel`, after
163
+ * which the agent is expected to finish the turn with `cancelled`.
164
+ */
165
+ prompt(sessionId: string, text: string, handlers: AcpHandlers, signal?: AbortSignal): Promise<AcpStopReason>;
166
+ close(): void;
167
+ private request;
168
+ private notify;
169
+ private send;
170
+ private receive;
171
+ private answer;
172
+ private fail;
173
+ private stderrTail;
174
+ }
175
+ /**
176
+ * How to start a command on this platform.
177
+ *
178
+ * On Windows `npx` is `npx.cmd`, a batch file, and Node refuses to spawn one
179
+ * without a shell (CVE-2024-27980). Through `cmd` it goes, then — quoted,
180
+ * since the shell joins the line itself and a path under "Program Files"
181
+ * would otherwise split in two. The arguments are fixed by the caller (a
182
+ * flag and a pinned package name), never text from a request, and quoted the
183
+ * same way all the same.
184
+ */
185
+ export declare function spawnTarget(command: string, args: string[], platform?: NodeJS.Platform): {
186
+ command: string;
187
+ args: string[];
188
+ shell: boolean;
189
+ };
190
+ /** The refusing answer among an agent's options: once, never "always". */
191
+ export declare function refuse(options: AcpPermissionOption[]): AcpPermissionOutcome;
192
+ /** The allowing answer among an agent's options, once rather than always. */
193
+ export declare function allowOnce(options: AcpPermissionOption[]): AcpPermissionOutcome;
@@ -0,0 +1,279 @@
1
+ import { spawn } from "node:child_process";
2
+ /**
3
+ * A client for the Agent Client Protocol (agentclientprotocol.com).
4
+ *
5
+ * ACP is how an editor drives an agent it did not write: the agent runs as a
6
+ * child process and the two exchange JSON-RPC 2.0 messages, one per line, over
7
+ * its stdin and stdout. This is the client half, written against the baseline
8
+ * methods only — `initialize`, `session/new`, `session/prompt`,
9
+ * `session/cancel`, the `session/update` stream and
10
+ * `session/request_permission` — because the agents that speak it add
11
+ * extensions faster than any one client should chase.
12
+ *
13
+ * Deliberately small and dependency-free rather than built on the SDK: the
14
+ * surface used here is a few hundred lines of protocol, and owning it keeps
15
+ * the fake agent in the tests and the real one on the same footing.
16
+ *
17
+ * What it advertises is a choice. `fs`, when the caller supplies a file
18
+ * system, so the agent's reads and writes pass through this harness's
19
+ * workspace policy instead of around it. No `terminal`: the agent runs its
20
+ * own commands. And no `auth` capability: an
21
+ * agent that needs signing in is told so and left to its own login, never
22
+ * offered one from here — for Claude Code that is the difference between the
23
+ * user signing in to Claude Code and OHarness brokering a Claude login.
24
+ */
25
+ export const ACP_PROTOCOL_VERSION = 1;
26
+ /** JSON-RPC error code ACP uses for "this agent needs signing in". */
27
+ export const ACP_AUTH_REQUIRED = -32000;
28
+ /** An error the agent returned, with its JSON-RPC code. */
29
+ export class AcpError extends Error {
30
+ code;
31
+ data;
32
+ constructor(message, code, data) {
33
+ super(message);
34
+ this.name = "AcpError";
35
+ this.code = code;
36
+ this.data = data;
37
+ }
38
+ }
39
+ export class AcpClient {
40
+ proc;
41
+ pending = new Map();
42
+ seq = 0;
43
+ stderr = "";
44
+ closed = false;
45
+ exitError;
46
+ /** Prompt-scoped handlers; `session/update` belongs to whoever is prompting. */
47
+ handlers = {};
48
+ fs;
49
+ authMethods = [];
50
+ /** What the agent said it can do, from `initialize`. */
51
+ capabilities = {};
52
+ constructor(launch) {
53
+ if (launch.fs)
54
+ this.fs = launch.fs;
55
+ const target = spawnTarget(launch.command, launch.args ?? []);
56
+ this.proc = spawn(target.command, target.args, {
57
+ cwd: launch.cwd,
58
+ env: { ...process.env, ...launch.env },
59
+ stdio: ["pipe", "pipe", "pipe"],
60
+ ...(target.shell ? { shell: true, windowsHide: true } : {}),
61
+ });
62
+ this.proc.stderr.setEncoding("utf8");
63
+ // Kept for the error a failed start reports; logs are the agent's own.
64
+ this.proc.stderr.on("data", (chunk) => {
65
+ this.stderr = (this.stderr + chunk).slice(-4_000);
66
+ });
67
+ this.proc.on("error", (err) => this.fail(err));
68
+ this.proc.on("exit", (code, signal) => {
69
+ this.fail(new Error(`the agent exited (${signal ?? `code ${code}`})${this.stderrTail()}`));
70
+ });
71
+ // One message per line. Split by hand: a chunk can end mid-message.
72
+ let buffered = "";
73
+ this.proc.stdout.setEncoding("utf8");
74
+ this.proc.stdout.on("data", (chunk) => {
75
+ buffered += chunk;
76
+ let newline;
77
+ while ((newline = buffered.indexOf("\n")) !== -1) {
78
+ const line = buffered.slice(0, newline);
79
+ buffered = buffered.slice(newline + 1);
80
+ this.receive(line);
81
+ }
82
+ });
83
+ }
84
+ /** Handshake. Resolves with the agent's advertised login methods. */
85
+ async initialize(clientName = "OHarness", clientVersion = "0") {
86
+ const files = Boolean(this.fs);
87
+ const result = (await this.request("initialize", {
88
+ protocolVersion: ACP_PROTOCOL_VERSION,
89
+ clientCapabilities: { fs: { readTextFile: files, writeTextFile: files }, terminal: false },
90
+ clientInfo: { name: clientName, version: clientVersion },
91
+ }));
92
+ if (result.protocolVersion !== undefined && result.protocolVersion !== ACP_PROTOCOL_VERSION) {
93
+ throw new Error(`the agent speaks ACP version ${result.protocolVersion}, not ${ACP_PROTOCOL_VERSION}`);
94
+ }
95
+ this.authMethods = result.authMethods ?? [];
96
+ this.capabilities = result.agentCapabilities ?? {};
97
+ }
98
+ async newSession(cwd, mcpServers = []) {
99
+ const result = (await this.request("session/new", { cwd, mcpServers: this.supported(mcpServers) }));
100
+ if (!result.sessionId)
101
+ throw new Error("the agent started no session");
102
+ return result.sessionId;
103
+ }
104
+ /**
105
+ * Pick up an earlier session where it left off, for a follow-up. The agent
106
+ * replays the conversation as updates first; nobody is prompting yet, so
107
+ * those land on no handler and are dropped.
108
+ */
109
+ async loadSession(sessionId, cwd, mcpServers = []) {
110
+ if (!this.capabilities.loadSession)
111
+ throw new Error("the agent cannot load sessions");
112
+ this.handlers = {};
113
+ await this.request("session/load", { sessionId, cwd, mcpServers: this.supported(mcpServers) });
114
+ }
115
+ /** HTTP servers only for an agent that said it takes them. */
116
+ supported(servers) {
117
+ return this.capabilities.mcpCapabilities?.http ? servers : servers.filter((server) => !("type" in server));
118
+ }
119
+ /**
120
+ * One turn: the prompt in, the agent's updates out through `handlers`, and
121
+ * its stop reason when the turn ends. Aborting sends `session/cancel`, after
122
+ * which the agent is expected to finish the turn with `cancelled`.
123
+ */
124
+ async prompt(sessionId, text, handlers, signal) {
125
+ this.handlers = handlers;
126
+ const cancel = () => this.notify("session/cancel", { sessionId });
127
+ signal?.addEventListener("abort", cancel, { once: true });
128
+ try {
129
+ const result = (await this.request("session/prompt", {
130
+ sessionId,
131
+ prompt: [{ type: "text", text }],
132
+ }));
133
+ return result.stopReason ?? "end_turn";
134
+ }
135
+ finally {
136
+ signal?.removeEventListener("abort", cancel);
137
+ this.handlers = {};
138
+ }
139
+ }
140
+ close() {
141
+ if (this.closed)
142
+ return;
143
+ this.closed = true;
144
+ this.proc.stdin.end();
145
+ // A grace period to exit on its own, then a firmer word.
146
+ const timer = setTimeout(() => this.proc.kill("SIGKILL"), 2_000);
147
+ timer.unref?.();
148
+ this.proc.kill("SIGTERM");
149
+ }
150
+ request(method, params) {
151
+ if (this.exitError)
152
+ return Promise.reject(this.exitError);
153
+ const id = ++this.seq;
154
+ return new Promise((resolve, reject) => {
155
+ this.pending.set(id, { resolve, reject });
156
+ this.send({ jsonrpc: "2.0", id, method, params });
157
+ });
158
+ }
159
+ notify(method, params) {
160
+ if (!this.exitError)
161
+ this.send({ jsonrpc: "2.0", method, params });
162
+ }
163
+ send(message) {
164
+ this.proc.stdin.write(`${JSON.stringify(message)}\n`);
165
+ }
166
+ receive(line) {
167
+ if (!line.trim())
168
+ return;
169
+ let message;
170
+ try {
171
+ message = JSON.parse(line);
172
+ }
173
+ catch {
174
+ // Not a protocol line — an agent printing to stdout by mistake.
175
+ return;
176
+ }
177
+ // A response to one of ours.
178
+ if (message.method === undefined && message.id !== undefined) {
179
+ const waiting = this.pending.get(Number(message.id));
180
+ if (!waiting)
181
+ return;
182
+ this.pending.delete(Number(message.id));
183
+ if (message.error)
184
+ waiting.reject(new AcpError(message.error.message, message.error.code, message.error.data));
185
+ else
186
+ waiting.resolve(message.result ?? {});
187
+ return;
188
+ }
189
+ // A notification from the agent.
190
+ if (message.id === undefined) {
191
+ if (message.method === "session/update") {
192
+ const update = message.params?.update;
193
+ if (update)
194
+ this.handlers.onUpdate?.(update);
195
+ }
196
+ return;
197
+ }
198
+ // A request from the agent.
199
+ void this.answer(message.id, message.method ?? "", message.params);
200
+ }
201
+ async answer(id, method, params) {
202
+ if (method === "session/request_permission") {
203
+ let outcome = { outcome: "cancelled" };
204
+ try {
205
+ const request = params;
206
+ outcome = this.handlers.onPermission
207
+ ? await this.handlers.onPermission(request)
208
+ : refuse(request.options);
209
+ }
210
+ catch {
211
+ // A question nobody could answer is a no.
212
+ }
213
+ this.send({ jsonrpc: "2.0", id, result: { outcome } });
214
+ return;
215
+ }
216
+ if (this.fs && (method === "fs/read_text_file" || method === "fs/write_text_file")) {
217
+ const request = params;
218
+ try {
219
+ if (typeof request.path !== "string")
220
+ throw new Error("no path");
221
+ if (method === "fs/read_text_file") {
222
+ const content = await this.fs.read(request.path, request.line ?? undefined, request.limit ?? undefined);
223
+ this.send({ jsonrpc: "2.0", id, result: { content } });
224
+ }
225
+ else {
226
+ await this.fs.write(request.path, request.content ?? "");
227
+ this.send({ jsonrpc: "2.0", id, result: {} });
228
+ }
229
+ }
230
+ catch (err) {
231
+ // The workspace policy refusing, a missing file: the agent is told why.
232
+ this.send({ jsonrpc: "2.0", id, error: { code: -32603, message: err instanceof Error ? err.message : String(err) } });
233
+ }
234
+ return;
235
+ }
236
+ // terminal/* and the rest were not advertised, so asking is an error.
237
+ this.send({ jsonrpc: "2.0", id, error: { code: -32601, message: `method not supported: ${method}` } });
238
+ }
239
+ fail(err) {
240
+ if (this.exitError)
241
+ return;
242
+ this.exitError = err;
243
+ for (const waiting of this.pending.values())
244
+ waiting.reject(err);
245
+ this.pending.clear();
246
+ }
247
+ stderrTail() {
248
+ const tail = this.stderr.trim().split("\n").slice(-3).join(" ").trim();
249
+ return tail ? `: ${tail}` : "";
250
+ }
251
+ }
252
+ /**
253
+ * How to start a command on this platform.
254
+ *
255
+ * On Windows `npx` is `npx.cmd`, a batch file, and Node refuses to spawn one
256
+ * without a shell (CVE-2024-27980). Through `cmd` it goes, then — quoted,
257
+ * since the shell joins the line itself and a path under "Program Files"
258
+ * would otherwise split in two. The arguments are fixed by the caller (a
259
+ * flag and a pinned package name), never text from a request, and quoted the
260
+ * same way all the same.
261
+ */
262
+ export function spawnTarget(command, args, platform = process.platform) {
263
+ if (platform === "win32" && /\.(cmd|bat)$/i.test(command)) {
264
+ const quote = (value) => (/[\s"&|<>^]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value);
265
+ return { command: quote(command), args: args.map(quote), shell: true };
266
+ }
267
+ return { command, args, shell: false };
268
+ }
269
+ /** The refusing answer among an agent's options: once, never "always". */
270
+ export function refuse(options) {
271
+ const reject = options.find((option) => option.kind === "reject_once") ?? options.find((option) => option.kind === "reject_always");
272
+ return reject ? { outcome: "selected", optionId: reject.optionId } : { outcome: "cancelled" };
273
+ }
274
+ /** The allowing answer among an agent's options, once rather than always. */
275
+ export function allowOnce(options) {
276
+ const allow = options.find((option) => option.kind === "allow_once") ?? options.find((option) => option.kind === "allow_always");
277
+ return allow ? { outcome: "selected", optionId: allow.optionId } : { outcome: "cancelled" };
278
+ }
279
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/acp/client.ts"],"names":[],"mappings":"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"}