@rarebit-one/harness-kernel 0.6.0 → 0.7.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/dist/engines/acp.d.ts +99 -0
- package/dist/engines/acp.d.ts.map +1 -0
- package/dist/engines/acp.js +184 -0
- package/dist/engines/acp.js.map +1 -0
- package/dist/engines/acpDriver.d.ts +26 -0
- package/dist/engines/acpDriver.d.ts.map +1 -0
- package/dist/engines/acpDriver.js +107 -0
- package/dist/engines/acpDriver.js.map +1 -0
- package/dist/engines/index.d.ts.map +1 -1
- package/dist/engines/index.js +8 -0
- package/dist/engines/index.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { McpServer } from "@zed-industries/agent-client-protocol";
|
|
2
|
+
import type { AgentEngine, EngineContext, EngineResult, EngineSupport, RunSpec } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* A named external agent this engine can drive over the Agent Client Protocol.
|
|
5
|
+
* ACP is a JSON-RPC-over-stdio protocol between a *client* (this engine) and a
|
|
6
|
+
* coding *agent* running as a separate process, so every ACP agent reduces to
|
|
7
|
+
* "which subprocess to spawn, with what argv and env". The capability MCP server
|
|
8
|
+
* and the run's connectors are handed to the agent through `session/new`, so a
|
|
9
|
+
* spec never has to describe those — only its own launch.
|
|
10
|
+
*
|
|
11
|
+
* External agent product names appearing here follow the existing `claude-code`
|
|
12
|
+
* / `codex` precedent: an adapter's honest identity is the tool it drives, not a
|
|
13
|
+
* consumer's brand.
|
|
14
|
+
*/
|
|
15
|
+
export interface AcpAgentSpec {
|
|
16
|
+
/** Engine name; also the `provider.engine` value that selects it. */
|
|
17
|
+
readonly name: string;
|
|
18
|
+
/** Env var that must equal `"1"` for {@link AcpEngine.supports} to allow this agent. */
|
|
19
|
+
readonly enableEnv: string;
|
|
20
|
+
/** The executable to spawn — an ACP server over stdio. */
|
|
21
|
+
readonly command: string;
|
|
22
|
+
/** The process argv for a run (e.g. the ACP subcommand). */
|
|
23
|
+
args(spec: RunSpec): string[];
|
|
24
|
+
/** Extra process env — e.g. the provider credentials the agent reads for itself. */
|
|
25
|
+
env(spec: RunSpec): Record<string, string>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Driver-neutral options the engine derives from a {@link RunSpec} and hands to
|
|
29
|
+
* the ACP driver. The default driver spawns `command`+`args` and speaks ACP over
|
|
30
|
+
* its stdio; tests inject a fake driver and assert this mapping.
|
|
31
|
+
*/
|
|
32
|
+
export interface AcpOptions {
|
|
33
|
+
command: string;
|
|
34
|
+
args: string[];
|
|
35
|
+
env: Record<string, string>;
|
|
36
|
+
/** The prepared sandbox working tree — the agent's cwd and ACP `session/new` cwd. */
|
|
37
|
+
cwd: string;
|
|
38
|
+
/** The run's MCP servers (connectors + the capability server) for `session/new`. */
|
|
39
|
+
mcpServers: McpServer[];
|
|
40
|
+
/** The task prompt (workflow prompt + inputs). */
|
|
41
|
+
prompt: string;
|
|
42
|
+
/** Wall-clock budget in ms; undefined means no engine-imposed limit. */
|
|
43
|
+
maxDurationMs?: number;
|
|
44
|
+
/** Append a line to the run log (the driver surfaces the agent's stderr here). */
|
|
45
|
+
log: (line: string) => void;
|
|
46
|
+
}
|
|
47
|
+
/** Streaming callbacks the driver invokes as ACP `session/update`s arrive. */
|
|
48
|
+
export interface AcpClientEvents {
|
|
49
|
+
/** An `agent_message_chunk` — accumulated into the run's prose result. */
|
|
50
|
+
onAssistantChunk(text: string): void;
|
|
51
|
+
/** A human-readable line for the run log (thoughts, tool-call titles). */
|
|
52
|
+
onLog(line: string): void;
|
|
53
|
+
}
|
|
54
|
+
/** What one ACP prompt turn resolved to. */
|
|
55
|
+
export interface AcpOutcome {
|
|
56
|
+
/** The ACP `stopReason` (`end_turn`, `cancelled`, `refusal`, …). */
|
|
57
|
+
stopReason: string;
|
|
58
|
+
}
|
|
59
|
+
/** The injectable boundary to the ACP transport. Tests supply a fake. */
|
|
60
|
+
export type AcpDriver = (opts: AcpOptions, events: AcpClientEvents) => Promise<AcpOutcome>;
|
|
61
|
+
/**
|
|
62
|
+
* Drives a run with any ACP-speaking coding agent (Claude Code, Codex, eve, …)
|
|
63
|
+
* against the sandbox working tree. One engine, one transport: where the codex
|
|
64
|
+
* engine wrote a `config.toml` and the Claude Code engine mounted an in-process
|
|
65
|
+
* SDK MCP server, this hands the run's connectors + the runner-hosted capability
|
|
66
|
+
* server to the agent through the ACP `session/new` `mcpServers` field, and reads
|
|
67
|
+
* back the capability server's emissions file — so an ACP agent reaches emit
|
|
68
|
+
* parity with native.
|
|
69
|
+
*
|
|
70
|
+
* Because an ACP agent runs arbitrary code, `supports()` refuses unless the
|
|
71
|
+
* operator enabled this specific agent AND the run is on the ephemeral runner
|
|
72
|
+
* profile (one throwaway container per run is the safety boundary). File edits
|
|
73
|
+
* are out-of-band: the agent edits `cwd` directly and the caller's change-set
|
|
74
|
+
* diff captures them, so this engine advertises no client filesystem capability.
|
|
75
|
+
*/
|
|
76
|
+
export declare class AcpEngine implements AgentEngine {
|
|
77
|
+
readonly name: string;
|
|
78
|
+
private readonly agent;
|
|
79
|
+
private readonly capabilityServerScript;
|
|
80
|
+
private readonly drive;
|
|
81
|
+
/**
|
|
82
|
+
* `capabilityServerScript` is REQUIRED, exactly as for codex: the capability
|
|
83
|
+
* surface is injected, and a child process cannot be handed a closure, so the
|
|
84
|
+
* application must supply the entrypoint that serves its own tools over stdio.
|
|
85
|
+
*/
|
|
86
|
+
constructor(agent: AcpAgentSpec, capabilityServerScript: string, drive?: AcpDriver);
|
|
87
|
+
supports(spec: RunSpec): EngineSupport;
|
|
88
|
+
run(spec: RunSpec, ctx: EngineContext): Promise<EngineResult>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* The eve agent (Vercel's open-source framework), driven over `eve acp` — its
|
|
92
|
+
* stdio ACP server surface. eve reads its own model/provider from the authored
|
|
93
|
+
* eve application in the workdir; we pass through whatever provider credentials
|
|
94
|
+
* the run carries so a BYO key reaches it. (Open: an eve "agent" is an authored
|
|
95
|
+
* app, so the workdir must contain one — a workflow-declared app path with an
|
|
96
|
+
* `agent/`-root default is the follow-up; today it runs the app at the workdir root.)
|
|
97
|
+
*/
|
|
98
|
+
export declare const EVE_AGENT: AcpAgentSpec;
|
|
99
|
+
//# sourceMappingURL=acp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp.d.ts","sourceRoot":"","sources":["../../src/engines/acp.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uCAAuC,CAAA;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAQlG;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,YAAY;IAC3B,qEAAqE;IACrE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,wFAAwF;IACxF,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,0DAA0D;IAC1D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,4DAA4D;IAC5D,IAAI,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,CAAA;IAC7B,oFAAoF;IACpF,GAAG,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAC3C;AAED;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3B,qFAAqF;IACrF,GAAG,EAAE,MAAM,CAAA;IACX,oFAAoF;IACpF,UAAU,EAAE,SAAS,EAAE,CAAA;IACvB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAA;IACd,wEAAwE;IACxE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kFAAkF;IAClF,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5B;AAED,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,0EAA0E;IAC1E,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,4CAA4C;AAC5C,MAAM,WAAW,UAAU;IACzB,oEAAoE;IACpE,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,yEAAyE;AACzE,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,KAAK,OAAO,CAAC,UAAU,CAAC,CAAA;AAE1F;;;;;;;;;;;;;;GAcG;AACH,qBAAa,SAAU,YAAW,WAAW;IAC3C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IAErB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAc;IACpC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAQ;IAC/C,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;IAEjC;;;;OAIG;gBAED,KAAK,EAAE,YAAY,EACnB,sBAAsB,EAAE,MAAM,EAC9B,KAAK,GAAE,SAA4B;IAQrC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa;IAgBhC,GAAG,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;CAuEpE;AA8CD;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,EAAE,YAavB,CAAA"}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { mkdtemp, rm, stat } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { CAPABILITY_SERVER_NAME } from "./capabilityMcp.js";
|
|
5
|
+
import { connectorServers } from "./connectorMcp.js";
|
|
6
|
+
import { readEmissions } from "./capabilityEmissions.js";
|
|
7
|
+
import { defaultAcpDriver } from "./acpDriver.js";
|
|
8
|
+
const LOG_TRUNCATE = 2000;
|
|
9
|
+
/**
|
|
10
|
+
* Drives a run with any ACP-speaking coding agent (Claude Code, Codex, eve, …)
|
|
11
|
+
* against the sandbox working tree. One engine, one transport: where the codex
|
|
12
|
+
* engine wrote a `config.toml` and the Claude Code engine mounted an in-process
|
|
13
|
+
* SDK MCP server, this hands the run's connectors + the runner-hosted capability
|
|
14
|
+
* server to the agent through the ACP `session/new` `mcpServers` field, and reads
|
|
15
|
+
* back the capability server's emissions file — so an ACP agent reaches emit
|
|
16
|
+
* parity with native.
|
|
17
|
+
*
|
|
18
|
+
* Because an ACP agent runs arbitrary code, `supports()` refuses unless the
|
|
19
|
+
* operator enabled this specific agent AND the run is on the ephemeral runner
|
|
20
|
+
* profile (one throwaway container per run is the safety boundary). File edits
|
|
21
|
+
* are out-of-band: the agent edits `cwd` directly and the caller's change-set
|
|
22
|
+
* diff captures them, so this engine advertises no client filesystem capability.
|
|
23
|
+
*/
|
|
24
|
+
export class AcpEngine {
|
|
25
|
+
name;
|
|
26
|
+
agent;
|
|
27
|
+
capabilityServerScript;
|
|
28
|
+
drive;
|
|
29
|
+
/**
|
|
30
|
+
* `capabilityServerScript` is REQUIRED, exactly as for codex: the capability
|
|
31
|
+
* surface is injected, and a child process cannot be handed a closure, so the
|
|
32
|
+
* application must supply the entrypoint that serves its own tools over stdio.
|
|
33
|
+
*/
|
|
34
|
+
constructor(agent, capabilityServerScript, drive = defaultAcpDriver) {
|
|
35
|
+
this.agent = agent;
|
|
36
|
+
this.name = agent.name;
|
|
37
|
+
this.capabilityServerScript = capabilityServerScript;
|
|
38
|
+
this.drive = drive;
|
|
39
|
+
}
|
|
40
|
+
supports(spec) {
|
|
41
|
+
if (process.env[this.agent.enableEnv] !== "1") {
|
|
42
|
+
return {
|
|
43
|
+
ok: false,
|
|
44
|
+
reason: `${this.name} engine is disabled (set ${this.agent.enableEnv}=1)`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
if (spec.workflow.runner?.profile !== "ephemeral") {
|
|
48
|
+
return {
|
|
49
|
+
ok: false,
|
|
50
|
+
reason: `${this.name} engine requires the ephemeral runner profile (per-run container isolation)`,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return { ok: true };
|
|
54
|
+
}
|
|
55
|
+
async run(spec, ctx) {
|
|
56
|
+
// Emissions land OUTSIDE the sandbox so the bookkeeping file is never captured
|
|
57
|
+
// by the change set; the capability server (an external process) writes here and
|
|
58
|
+
// we read it back after the run.
|
|
59
|
+
const emissionsDir = await mkdtemp(path.join(tmpdir(), "harness-emit-"));
|
|
60
|
+
const emissionsFile = path.join(emissionsDir, "emissions.json");
|
|
61
|
+
const capabilityEnv = {
|
|
62
|
+
HARNESS_WORKSPACE_ID: spec.workspaceId,
|
|
63
|
+
HARNESS_WORKDIR: spec.workdir,
|
|
64
|
+
HARNESS_EMISSIONS_FILE: emissionsFile,
|
|
65
|
+
};
|
|
66
|
+
const servers = {
|
|
67
|
+
...connectorServers(spec.connectors),
|
|
68
|
+
[CAPABILITY_SERVER_NAME]: {
|
|
69
|
+
type: "stdio",
|
|
70
|
+
command: process.execPath,
|
|
71
|
+
args: [this.capabilityServerScript],
|
|
72
|
+
env: capabilityEnv,
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
const options = {
|
|
76
|
+
command: this.agent.command,
|
|
77
|
+
args: this.agent.args(spec),
|
|
78
|
+
// The capability env also rides on the process env so the stdio capability
|
|
79
|
+
// server inherits it regardless of how the agent forwards `session/new` env.
|
|
80
|
+
env: { ...this.agent.env(spec), ...capabilityEnv },
|
|
81
|
+
cwd: spec.workdir,
|
|
82
|
+
mcpServers: toAcpMcpServers(servers),
|
|
83
|
+
prompt: buildPrompt(spec),
|
|
84
|
+
...(spec.limits?.maxDurationMs !== undefined
|
|
85
|
+
? { maxDurationMs: spec.limits.maxDurationMs }
|
|
86
|
+
: {}),
|
|
87
|
+
log: ctx.log,
|
|
88
|
+
};
|
|
89
|
+
ctx.log(`${this.name}: driving ACP agent in ${spec.workdir}`);
|
|
90
|
+
const chunks = [];
|
|
91
|
+
const outcome = await this.drive(options, {
|
|
92
|
+
onAssistantChunk: (text) => {
|
|
93
|
+
if (text)
|
|
94
|
+
chunks.push(text);
|
|
95
|
+
},
|
|
96
|
+
onLog: (line) => {
|
|
97
|
+
if (line)
|
|
98
|
+
ctx.log(`${this.name}: ${truncate(line, LOG_TRUNCATE)}`);
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
if (outcome.stopReason && outcome.stopReason !== "end_turn") {
|
|
102
|
+
ctx.log(`${this.name}: stopped (${outcome.stopReason})`);
|
|
103
|
+
}
|
|
104
|
+
// Report whether the emissions round trip HAPPENED, not what it carried —
|
|
105
|
+
// presence plus size separates "the server never wrote" from "it wrote and the
|
|
106
|
+
// run emitted nothing"; the byte count comes from the file (see codex engine).
|
|
107
|
+
const emissionsStat = await stat(emissionsFile).then((st) => st, () => undefined);
|
|
108
|
+
const emissions = await readEmissions(emissionsFile);
|
|
109
|
+
ctx.log(`${this.name}: capability emissions — file ${emissionsStat ? `present (${emissionsStat.size} bytes)` : "absent"}` +
|
|
110
|
+
`${emissionsStat && emissions === undefined ? ", unreadable" : ""}`);
|
|
111
|
+
await rm(emissionsDir, { recursive: true, force: true });
|
|
112
|
+
return {
|
|
113
|
+
text: chunks.join("").trim() || "(no output)",
|
|
114
|
+
...(emissions !== undefined ? { emissions } : {}),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Translate the run's serializable MCP servers into ACP's `McpServer[]`. Same
|
|
120
|
+
* source data every other engine consumes (`connectorServers`), reshaped to the
|
|
121
|
+
* ACP wire form: env and headers become `{ name, value }` arrays.
|
|
122
|
+
*/
|
|
123
|
+
function toAcpMcpServers(servers) {
|
|
124
|
+
return Object.entries(servers).map(([name, server]) => {
|
|
125
|
+
if (server.type === "stdio") {
|
|
126
|
+
return {
|
|
127
|
+
name,
|
|
128
|
+
command: server.command,
|
|
129
|
+
args: server.args ?? [],
|
|
130
|
+
env: Object.entries(server.env ?? {}).map(([key, value]) => ({ name: key, value })),
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
name,
|
|
135
|
+
type: server.type,
|
|
136
|
+
url: server.url,
|
|
137
|
+
headers: Object.entries(server.headers ?? {}).map(([key, value]) => ({ name: key, value })),
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function buildPrompt(spec) {
|
|
142
|
+
const inputs = JSON.stringify(spec.inputs ?? {}, null, 2);
|
|
143
|
+
return [
|
|
144
|
+
spec.workflow.prompt ?? `Execute the "${spec.workflow.name ?? spec.workflowPath}" workflow.`,
|
|
145
|
+
"",
|
|
146
|
+
"## Inputs",
|
|
147
|
+
"```json",
|
|
148
|
+
inputs,
|
|
149
|
+
"```",
|
|
150
|
+
"",
|
|
151
|
+
"You are running as an autonomous workflow. The current working directory is the",
|
|
152
|
+
"workspace — inspect and edit its files directly with your tools. When finished,",
|
|
153
|
+
"reply with the workflow's output as Markdown.",
|
|
154
|
+
].join("\n");
|
|
155
|
+
}
|
|
156
|
+
function truncate(text, max) {
|
|
157
|
+
return text.length <= max ? text : `${text.slice(0, max)}…`;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* The eve agent (Vercel's open-source framework), driven over `eve acp` — its
|
|
161
|
+
* stdio ACP server surface. eve reads its own model/provider from the authored
|
|
162
|
+
* eve application in the workdir; we pass through whatever provider credentials
|
|
163
|
+
* the run carries so a BYO key reaches it. (Open: an eve "agent" is an authored
|
|
164
|
+
* app, so the workdir must contain one — a workflow-declared app path with an
|
|
165
|
+
* `agent/`-root default is the follow-up; today it runs the app at the workdir root.)
|
|
166
|
+
*/
|
|
167
|
+
export const EVE_AGENT = {
|
|
168
|
+
name: "eve",
|
|
169
|
+
enableEnv: "RUNNER_ENABLE_EVE",
|
|
170
|
+
command: "eve",
|
|
171
|
+
args: () => ["acp"],
|
|
172
|
+
env: (spec) => {
|
|
173
|
+
const env = {};
|
|
174
|
+
const creds = spec.provider.credentials;
|
|
175
|
+
if (creds?.anthropic)
|
|
176
|
+
env.ANTHROPIC_API_KEY = creds.anthropic;
|
|
177
|
+
if (creds?.openai)
|
|
178
|
+
env.OPENAI_API_KEY = creds.openai;
|
|
179
|
+
if (creds?.openrouter)
|
|
180
|
+
env.OPENROUTER_API_KEY = creds.openrouter;
|
|
181
|
+
return env;
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
//# sourceMappingURL=acp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp.js","sourceRoot":"","sources":["../../src/engines/acp.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { AcpClientEvents, AcpOptions, AcpOutcome } from "./acp.js";
|
|
2
|
+
/**
|
|
3
|
+
* The default ACP driver: the single integration boundary to an ACP agent
|
|
4
|
+
* subprocess, mirroring `defaultCodexDriver`'s injectable shape. It spawns the
|
|
5
|
+
* agent, wires an {@link ClientSideConnection} over its stdio via
|
|
6
|
+
* {@link ndJsonStream}, and runs one ACP turn: `initialize` → `session/new`
|
|
7
|
+
* (with the run's cwd + MCP servers) → `session/prompt`.
|
|
8
|
+
*
|
|
9
|
+
* The host `Client` it implements is deliberately minimal:
|
|
10
|
+
* - `sessionUpdate` accumulates `agent_message_chunk`s (the run's prose) and
|
|
11
|
+
* surfaces thoughts / tool-call titles to the log.
|
|
12
|
+
* - `requestPermission` AUTO-APPROVES (selects an `allow_*` option). This is
|
|
13
|
+
* the ACP equivalent of the codex driver's `--dangerously-bypass-approvals`
|
|
14
|
+
* and the Claude Code driver's `bypassPermissions`, justified the same way:
|
|
15
|
+
* an ACP agent only runs inside a throwaway ephemeral container, so the
|
|
16
|
+
* container — not an approval prompt — is the safety boundary.
|
|
17
|
+
* - No `readTextFile`/`writeTextFile`/terminal capability is advertised, so the
|
|
18
|
+
* agent edits `cwd` directly and the caller's change-set diff is the sole
|
|
19
|
+
* edit path (no second, protocol-level way for a file to change).
|
|
20
|
+
*
|
|
21
|
+
* Exercised only when the operator enables the agent (per-agent env flag) on the
|
|
22
|
+
* ephemeral profile; every test injects a fake driver, so no binary/network is
|
|
23
|
+
* touched in CI.
|
|
24
|
+
*/
|
|
25
|
+
export declare function defaultAcpDriver(opts: AcpOptions, events: AcpClientEvents): Promise<AcpOutcome>;
|
|
26
|
+
//# sourceMappingURL=acpDriver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acpDriver.d.ts","sourceRoot":"","sources":["../../src/engines/acpDriver.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEvE;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,UAAU,CAAC,CAiFrB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { Readable, Writable } from "node:stream";
|
|
3
|
+
import { ClientSideConnection, ndJsonStream, PROTOCOL_VERSION, } from "@zed-industries/agent-client-protocol";
|
|
4
|
+
/**
|
|
5
|
+
* The default ACP driver: the single integration boundary to an ACP agent
|
|
6
|
+
* subprocess, mirroring `defaultCodexDriver`'s injectable shape. It spawns the
|
|
7
|
+
* agent, wires an {@link ClientSideConnection} over its stdio via
|
|
8
|
+
* {@link ndJsonStream}, and runs one ACP turn: `initialize` → `session/new`
|
|
9
|
+
* (with the run's cwd + MCP servers) → `session/prompt`.
|
|
10
|
+
*
|
|
11
|
+
* The host `Client` it implements is deliberately minimal:
|
|
12
|
+
* - `sessionUpdate` accumulates `agent_message_chunk`s (the run's prose) and
|
|
13
|
+
* surfaces thoughts / tool-call titles to the log.
|
|
14
|
+
* - `requestPermission` AUTO-APPROVES (selects an `allow_*` option). This is
|
|
15
|
+
* the ACP equivalent of the codex driver's `--dangerously-bypass-approvals`
|
|
16
|
+
* and the Claude Code driver's `bypassPermissions`, justified the same way:
|
|
17
|
+
* an ACP agent only runs inside a throwaway ephemeral container, so the
|
|
18
|
+
* container — not an approval prompt — is the safety boundary.
|
|
19
|
+
* - No `readTextFile`/`writeTextFile`/terminal capability is advertised, so the
|
|
20
|
+
* agent edits `cwd` directly and the caller's change-set diff is the sole
|
|
21
|
+
* edit path (no second, protocol-level way for a file to change).
|
|
22
|
+
*
|
|
23
|
+
* Exercised only when the operator enables the agent (per-agent env flag) on the
|
|
24
|
+
* ephemeral profile; every test injects a fake driver, so no binary/network is
|
|
25
|
+
* touched in CI.
|
|
26
|
+
*/
|
|
27
|
+
export async function defaultAcpDriver(opts, events) {
|
|
28
|
+
const child = spawn(opts.command, opts.args, {
|
|
29
|
+
cwd: opts.cwd,
|
|
30
|
+
env: { ...process.env, ...opts.env },
|
|
31
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
32
|
+
});
|
|
33
|
+
let stderr = "";
|
|
34
|
+
child.stderr?.setEncoding("utf8");
|
|
35
|
+
child.stderr?.on("data", (chunk) => {
|
|
36
|
+
stderr += chunk;
|
|
37
|
+
});
|
|
38
|
+
// A spawn failure (e.g. the agent binary is absent) surfaces here; the awaited
|
|
39
|
+
// protocol calls below then reject and we rethrow with the stderr tail.
|
|
40
|
+
child.on("error", (err) => {
|
|
41
|
+
stderr += `\n${String(err)}`;
|
|
42
|
+
});
|
|
43
|
+
const client = {
|
|
44
|
+
// Not `async`: these return a resolved promise directly (the ACP `Client`
|
|
45
|
+
// methods are `Promise`-typed, but there is nothing to await).
|
|
46
|
+
sessionUpdate({ update }) {
|
|
47
|
+
switch (update.sessionUpdate) {
|
|
48
|
+
case "agent_message_chunk":
|
|
49
|
+
if (update.content.type === "text")
|
|
50
|
+
events.onAssistantChunk(update.content.text);
|
|
51
|
+
break;
|
|
52
|
+
case "agent_thought_chunk":
|
|
53
|
+
if (update.content.type === "text")
|
|
54
|
+
events.onLog(`thought: ${update.content.text}`);
|
|
55
|
+
break;
|
|
56
|
+
case "tool_call":
|
|
57
|
+
events.onLog(`tool: ${update.title}`);
|
|
58
|
+
break;
|
|
59
|
+
default:
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
return Promise.resolve();
|
|
63
|
+
},
|
|
64
|
+
requestPermission({ options }) {
|
|
65
|
+
const allow = options.find((o) => o.kind === "allow_always") ??
|
|
66
|
+
options.find((o) => o.kind === "allow_once");
|
|
67
|
+
return Promise.resolve(allow
|
|
68
|
+
? { outcome: { outcome: "selected", optionId: allow.optionId } }
|
|
69
|
+
: { outcome: { outcome: "cancelled" } });
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
const stream = ndJsonStream(Writable.toWeb(child.stdin), Readable.toWeb(child.stdout));
|
|
73
|
+
const conn = new ClientSideConnection(() => client, stream);
|
|
74
|
+
let timedOut = false;
|
|
75
|
+
let sessionId = "";
|
|
76
|
+
const timer = opts.maxDurationMs && opts.maxDurationMs > 0
|
|
77
|
+
? setTimeout(() => {
|
|
78
|
+
timedOut = true;
|
|
79
|
+
if (sessionId)
|
|
80
|
+
void conn.cancel({ sessionId }).catch(() => { });
|
|
81
|
+
}, opts.maxDurationMs)
|
|
82
|
+
: undefined;
|
|
83
|
+
try {
|
|
84
|
+
await conn.initialize({ protocolVersion: PROTOCOL_VERSION, clientCapabilities: {} });
|
|
85
|
+
const session = await conn.newSession({ cwd: opts.cwd, mcpServers: opts.mcpServers });
|
|
86
|
+
sessionId = session.sessionId;
|
|
87
|
+
const res = await conn.prompt({
|
|
88
|
+
sessionId,
|
|
89
|
+
prompt: [{ type: "text", text: opts.prompt }],
|
|
90
|
+
});
|
|
91
|
+
return { stopReason: timedOut ? "cancelled" : res.stopReason };
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
if (stderr.trim()) {
|
|
95
|
+
const tail = stderr.length > 4000 ? `…${stderr.slice(-4000)}` : stderr;
|
|
96
|
+
opts.log(`${opts.command} stderr:\n${tail}`);
|
|
97
|
+
}
|
|
98
|
+
throw err;
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
if (timer)
|
|
102
|
+
clearTimeout(timer);
|
|
103
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
104
|
+
child.kill();
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=acpDriver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acpDriver.js","sourceRoot":"","sources":["../../src/engines/acpDriver.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engines/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAClE,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engines/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAClE,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAG9E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AAElG;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,0EAA0E;IAC1E,WAAW,CAAC,EAAE,iBAAiB,CAAA;IAC/B,oFAAoF;IACpF,eAAe,CAAC,EAAE,qBAAqB,CAAA;IACvC;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAA;CAChC;AAED;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,GAAE,eAAoB,GAAG,WAAW,CAyB/F"}
|
package/dist/engines/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { NativeEngine } from "./native.js";
|
|
2
2
|
import { ClaudeCodeEngine } from "./claudeCode.js";
|
|
3
3
|
import { CodexEngine } from "./codex.js";
|
|
4
|
+
import { AcpEngine, EVE_AGENT } from "./acp.js";
|
|
4
5
|
/**
|
|
5
6
|
* Resolve the agent harness for a run from the workflow's `provider.engine`.
|
|
6
7
|
* Defaults to the native loop; an unknown name also falls back to native (the
|
|
@@ -22,6 +23,13 @@ export function selectEngine(name, selection = {}) {
|
|
|
22
23
|
}
|
|
23
24
|
return new CodexEngine(undefined, selection.capabilityServerScript);
|
|
24
25
|
}
|
|
26
|
+
case "eve": {
|
|
27
|
+
if (!selection.capabilityServerScript) {
|
|
28
|
+
throw new Error("the eve engine requires selection.capabilityServerScript — the capability surface is " +
|
|
29
|
+
"injected, and an external process cannot be handed one implicitly");
|
|
30
|
+
}
|
|
31
|
+
return new AcpEngine(EVE_AGENT, selection.capabilityServerScript);
|
|
32
|
+
}
|
|
25
33
|
default:
|
|
26
34
|
return new NativeEngine(selection.domainTools ? { domainTools: selection.domainTools } : {});
|
|
27
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engines/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0B,MAAM,aAAa,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAA8B,MAAM,iBAAiB,CAAA;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/engines/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA0B,MAAM,aAAa,CAAA;AAClE,OAAO,EAAE,gBAAgB,EAA8B,MAAM,iBAAiB,CAAA;AAC9E,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AACxC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAuB/C;;;;;;;;;GASG;AACH,MAAM,UAAU,YAAY,CAAC,IAAoB,EAAE,YAA6B,EAAE;IAChF,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,aAAa;YAChB,OAAO,IAAI,gBAAgB,CAAC,SAAS,EAAE,SAAS,CAAC,eAAe,CAAC,CAAA;QACnE,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,SAAS,CAAC,sBAAsB,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CACb,yFAAyF;oBACvF,mEAAmE,CACtE,CAAA;YACH,CAAC;YACD,OAAO,IAAI,WAAW,CAAC,SAAS,EAAE,SAAS,CAAC,sBAAsB,CAAC,CAAA;QACrE,CAAC;QACD,KAAK,KAAK,CAAC,CAAC,CAAC;YACX,IAAI,CAAC,SAAS,CAAC,sBAAsB,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CACb,uFAAuF;oBACrF,mEAAmE,CACtE,CAAA;YACH,CAAC;YACD,OAAO,IAAI,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC,sBAAsB,CAAC,CAAA;QACnE,CAAC;QACD;YACE,OAAO,IAAI,YAAY,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;IAChG,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rarebit-one/harness-kernel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Provider-neutral AI-harness kernel — LLM adapters, tool-use loop, MCP connectors, and a pluggable agent-engine seam",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Jaryl Sim <code@jaryl.dev>",
|
|
@@ -51,8 +51,9 @@
|
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@anthropic-ai/claude-agent-sdk": "^0.3.228",
|
|
54
|
-
"@anthropic-ai/sdk": "^0.
|
|
54
|
+
"@anthropic-ai/sdk": "^0.124.0",
|
|
55
55
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
56
|
+
"@zed-industries/agent-client-protocol": "^0.4.5",
|
|
56
57
|
"openai": "^7.4.0",
|
|
57
58
|
"undici": "^8.10.0",
|
|
58
59
|
"zod": "^4.4.3"
|