@fusionkit/ensemble 0.1.5 → 0.1.6
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/cursorkit-path.d.ts +17 -0
- package/dist/cursorkit-path.js +21 -0
- package/dist/harness.d.ts +7 -0
- package/dist/harness.js +51 -1
- package/dist/index.d.ts +5 -8
- package/dist/index.js +3 -4
- package/dist/run.js +2 -1
- package/dist/test/ensemble.test.js +0 -227
- package/dist/unified.d.ts +27 -3
- package/dist/unified.js +31 -36
- package/package.json +8 -7
- package/dist/claude-code.d.ts +0 -25
- package/dist/claude-code.js +0 -398
- package/dist/codex.d.ts +0 -69
- package/dist/codex.js +0 -467
- package/dist/cursor.d.ts +0 -42
- package/dist/cursor.js +0 -440
- package/dist/dashboard.d.ts +0 -62
- package/dist/dashboard.js +0 -762
- package/dist/test/codex.test.d.ts +0 -1
- package/dist/test/codex.test.js +0 -237
- package/dist/test/cursor.test.d.ts +0 -1
- package/dist/test/cursor.test.js +0 -97
- package/dist/test/dashboard.test.d.ts +0 -1
- package/dist/test/dashboard.test.js +0 -214
package/dist/cursor.js
DELETED
|
@@ -1,440 +0,0 @@
|
|
|
1
|
-
import { spawn, spawnSync } from "node:child_process";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { delimiter, join } from "node:path";
|
|
4
|
-
import { artifactHash } from "@fusionkit/protocol";
|
|
5
|
-
const DEFAULT_CURSOR_COMMAND = "cursor-agent";
|
|
6
|
-
const DEFAULT_BRIDGE_MODEL_NAME = "local-fusion";
|
|
7
|
-
const DEFAULT_BRIDGE_PROVIDER_MODEL = "fusion-panel";
|
|
8
|
-
const BRIDGE_START_TIMEOUT_MS = 20_000;
|
|
9
|
-
function definedEnv(env) {
|
|
10
|
-
const result = {};
|
|
11
|
-
for (const [key, value] of Object.entries(env)) {
|
|
12
|
-
if (value !== undefined)
|
|
13
|
-
result[key] = value;
|
|
14
|
-
}
|
|
15
|
-
return result;
|
|
16
|
-
}
|
|
17
|
-
function normalizeModelBaseUrl(fusionBackendUrl) {
|
|
18
|
-
const trimmed = fusionBackendUrl.replace(/\/+$/, "");
|
|
19
|
-
return trimmed.endsWith("/v1") ? trimmed : `${trimmed}/v1`;
|
|
20
|
-
}
|
|
21
|
-
function commandOnPath(command, env) {
|
|
22
|
-
if (command.includes("/")) {
|
|
23
|
-
return existsSync(command);
|
|
24
|
-
}
|
|
25
|
-
const pathValue = env.PATH ?? process.env.PATH ?? "";
|
|
26
|
-
return pathValue
|
|
27
|
-
.split(delimiter)
|
|
28
|
-
.filter((entry) => entry.length > 0)
|
|
29
|
-
.some((dir) => existsSync(join(dir, command)));
|
|
30
|
-
}
|
|
31
|
-
function resolveCursorKitDir(options, env) {
|
|
32
|
-
return (options.cursorKitDir ??
|
|
33
|
-
env.WARRANT_CURSORKIT_DIR ??
|
|
34
|
-
env.FUSIONKIT_CURSORKIT_DIR);
|
|
35
|
-
}
|
|
36
|
-
function resolveAvailability(options, env) {
|
|
37
|
-
const command = options.command ?? DEFAULT_CURSOR_COMMAND;
|
|
38
|
-
if (options.runner !== undefined) {
|
|
39
|
-
return {
|
|
40
|
-
available: true,
|
|
41
|
-
cursorKitDir: resolveCursorKitDir(options, env) ?? ".",
|
|
42
|
-
command
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
const cursorKitDir = resolveCursorKitDir(options, env);
|
|
46
|
-
if (cursorKitDir === undefined) {
|
|
47
|
-
return {
|
|
48
|
-
available: false,
|
|
49
|
-
reason: "Cursorkit checkout is not configured; set WARRANT_CURSORKIT_DIR or pass cursorKitDir."
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
if (!existsSync(join(cursorKitDir, "dist/src/cli.js"))) {
|
|
53
|
-
return {
|
|
54
|
-
available: false,
|
|
55
|
-
reason: `Cursorkit bridge build was not found at ${join(cursorKitDir, "dist/src/cli.js")}; run pnpm build in the Cursorkit checkout.`
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
if (!commandOnPath(command, env)) {
|
|
59
|
-
return {
|
|
60
|
-
available: false,
|
|
61
|
-
reason: `Cursor CLI "${command}" was not found on PATH; install the Cursor CLI (https://cursor.com/cli) and log in.`
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
return { available: true, cursorKitDir, command };
|
|
65
|
-
}
|
|
66
|
-
export function cursorHarnessUnavailableReason(env = process.env, options = {}) {
|
|
67
|
-
const availability = resolveAvailability(options, definedEnv(env));
|
|
68
|
-
return availability.available ? undefined : availability.reason;
|
|
69
|
-
}
|
|
70
|
-
function modeFor(descriptor, override) {
|
|
71
|
-
if (override !== undefined)
|
|
72
|
-
return override;
|
|
73
|
-
switch (descriptor.policy.sideEffects) {
|
|
74
|
-
case "none":
|
|
75
|
-
case "read_only":
|
|
76
|
-
return "ask";
|
|
77
|
-
case "writes_workspace":
|
|
78
|
-
case "network":
|
|
79
|
-
case "tool_execution":
|
|
80
|
-
case "unknown":
|
|
81
|
-
return "agent";
|
|
82
|
-
default: {
|
|
83
|
-
const exhausted = descriptor.policy.sideEffects;
|
|
84
|
-
throw new Error(`unsupported side effects policy: ${String(exhausted)}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
function skippedCandidate(input) {
|
|
89
|
-
const transcript = `Cursor adapter skipped: ${input.reason}`;
|
|
90
|
-
const hash = artifactHash(transcript);
|
|
91
|
-
return {
|
|
92
|
-
candidateId: `${input.descriptor.id}_${input.model.id}_${input.ordinal}`,
|
|
93
|
-
model: input.model,
|
|
94
|
-
status: "skipped",
|
|
95
|
-
transcript,
|
|
96
|
-
log: transcript,
|
|
97
|
-
artifacts: [
|
|
98
|
-
{
|
|
99
|
-
artifact_id: `artifact_${input.descriptor.id}_${input.model.id}_cursor_skip`,
|
|
100
|
-
kind: "log",
|
|
101
|
-
hash,
|
|
102
|
-
redaction_status: "synthetic"
|
|
103
|
-
}
|
|
104
|
-
],
|
|
105
|
-
verification: {
|
|
106
|
-
status: "skipped",
|
|
107
|
-
evidence: [input.reason]
|
|
108
|
-
},
|
|
109
|
-
error: {
|
|
110
|
-
kind: "capability_missing",
|
|
111
|
-
message: input.reason,
|
|
112
|
-
retryable: false
|
|
113
|
-
},
|
|
114
|
-
metadata: {
|
|
115
|
-
adapter: "cursor",
|
|
116
|
-
skip_reason: input.reason
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Drives the real cursor-agent CLI in ACP mode against a freshly spawned
|
|
122
|
-
* Cursorkit bridge whose local-model backend points at the fusion gateway.
|
|
123
|
-
* The bridge runs with BRIDGE_AGENT_TOOL_POLICY=all so Cursor can read, edit
|
|
124
|
-
* (apply_patch/write_file), and run shell commands inside the worktree.
|
|
125
|
-
*/
|
|
126
|
-
async function defaultCursorRunner(input) {
|
|
127
|
-
const bridgePort = 9700 + Math.floor(Math.random() * 250);
|
|
128
|
-
const bridgeEnv = { ...input.env };
|
|
129
|
-
for (const key of Object.keys(bridgeEnv)) {
|
|
130
|
-
if (key.startsWith("BRIDGE_") ||
|
|
131
|
-
key.startsWith("MODEL_") ||
|
|
132
|
-
key.startsWith("CURSOR_UPSTREAM")) {
|
|
133
|
-
delete bridgeEnv[key];
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
Object.assign(bridgeEnv, {
|
|
137
|
-
BRIDGE_PORT: String(bridgePort),
|
|
138
|
-
BRIDGE_ROUTE_INVENTORY: "true",
|
|
139
|
-
BRIDGE_AGENT_TOOL_POLICY: "all",
|
|
140
|
-
BRIDGE_AGENT_TOOL_MAX_ITERATIONS: "24",
|
|
141
|
-
CURSOR_UPSTREAM_BASE_URL: "https://api2.cursor.sh",
|
|
142
|
-
MODEL_BASE_URL: normalizeModelBaseUrl(input.fusionBackendUrl),
|
|
143
|
-
MODEL_API_KEY: input.apiKey ?? "local",
|
|
144
|
-
MODEL_NAME: input.modelName,
|
|
145
|
-
MODEL_PROVIDER_MODEL: input.providerModel,
|
|
146
|
-
MODEL_CONTEXT_TOKEN_LIMIT: "128000"
|
|
147
|
-
});
|
|
148
|
-
let bridgeOut = "";
|
|
149
|
-
const bridge = spawn(process.execPath, ["dist/src/cli.js", "serve"], {
|
|
150
|
-
cwd: input.cursorKitDir,
|
|
151
|
-
env: bridgeEnv,
|
|
152
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
153
|
-
});
|
|
154
|
-
bridge.stdout.on("data", (chunk) => {
|
|
155
|
-
bridgeOut += chunk.toString("utf8");
|
|
156
|
-
});
|
|
157
|
-
bridge.stderr.on("data", (chunk) => {
|
|
158
|
-
bridgeOut += chunk.toString("utf8");
|
|
159
|
-
});
|
|
160
|
-
const timeoutMs = input.timeoutMs ?? 180_000;
|
|
161
|
-
try {
|
|
162
|
-
const deadline = Date.now() + BRIDGE_START_TIMEOUT_MS;
|
|
163
|
-
while (!/bridge listening/.test(bridgeOut) && Date.now() < deadline) {
|
|
164
|
-
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
165
|
-
}
|
|
166
|
-
if (!/bridge listening/.test(bridgeOut)) {
|
|
167
|
-
return {
|
|
168
|
-
status: "failed",
|
|
169
|
-
transcript: bridgeOut,
|
|
170
|
-
toolEvents: 0,
|
|
171
|
-
reason: "Cursorkit bridge did not start in time."
|
|
172
|
-
};
|
|
173
|
-
}
|
|
174
|
-
const printResult = await driveCursorAgentPrint({
|
|
175
|
-
command: input.command,
|
|
176
|
-
bridgePort,
|
|
177
|
-
modelName: input.modelName,
|
|
178
|
-
mode: input.mode,
|
|
179
|
-
cwd: input.cwd,
|
|
180
|
-
prompt: input.prompt,
|
|
181
|
-
timeoutMs
|
|
182
|
-
});
|
|
183
|
-
const diff = captureWorktreeDiff(input.cwd);
|
|
184
|
-
return {
|
|
185
|
-
status: printResult.status,
|
|
186
|
-
transcript: printResult.transcript,
|
|
187
|
-
toolEvents: diff !== undefined && diff.length > 0 ? 1 : 0,
|
|
188
|
-
...(printResult.exitCode !== undefined ? { exitCode: printResult.exitCode } : {}),
|
|
189
|
-
...(diff !== undefined ? { diff } : {}),
|
|
190
|
-
...(printResult.reason !== undefined ? { reason: printResult.reason } : {})
|
|
191
|
-
};
|
|
192
|
-
}
|
|
193
|
-
finally {
|
|
194
|
-
bridge.kill("SIGTERM");
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
/**
|
|
198
|
-
* Drives cursor-agent in headless print mode (`-p`), which "has access to all
|
|
199
|
-
* tools, including write and shell". The bridge runs the Cursor tool loop over
|
|
200
|
-
* the SSE/BidiAppend transport, so the agent can read, apply_patch/write, and
|
|
201
|
-
* run shell inside the worktree. `--trust` skips the workspace-trust prompt and
|
|
202
|
-
* `--force` auto-approves tool actions. For read-only tasks we pass `--mode ask`.
|
|
203
|
-
*/
|
|
204
|
-
async function driveCursorAgentPrint(input) {
|
|
205
|
-
const args = [
|
|
206
|
-
"-p",
|
|
207
|
-
"--force",
|
|
208
|
-
"--trust",
|
|
209
|
-
"--output-format",
|
|
210
|
-
"text",
|
|
211
|
-
"--model",
|
|
212
|
-
input.modelName,
|
|
213
|
-
"--endpoint",
|
|
214
|
-
`http://127.0.0.1:${input.bridgePort}`
|
|
215
|
-
];
|
|
216
|
-
if (input.mode === "ask") {
|
|
217
|
-
args.push("--mode", "ask");
|
|
218
|
-
}
|
|
219
|
-
args.push(input.prompt);
|
|
220
|
-
return await new Promise((resolve) => {
|
|
221
|
-
const child = spawn(input.command, args, {
|
|
222
|
-
cwd: input.cwd,
|
|
223
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
224
|
-
});
|
|
225
|
-
let stdout = "";
|
|
226
|
-
let stderr = "";
|
|
227
|
-
let timedOut = false;
|
|
228
|
-
const timer = setTimeout(() => {
|
|
229
|
-
timedOut = true;
|
|
230
|
-
child.kill("SIGTERM");
|
|
231
|
-
}, input.timeoutMs);
|
|
232
|
-
child.stdout.on("data", (chunk) => {
|
|
233
|
-
stdout += chunk.toString("utf8");
|
|
234
|
-
});
|
|
235
|
-
child.stderr.on("data", (chunk) => {
|
|
236
|
-
stderr += chunk.toString("utf8");
|
|
237
|
-
});
|
|
238
|
-
child.on("error", (error) => {
|
|
239
|
-
clearTimeout(timer);
|
|
240
|
-
resolve({
|
|
241
|
-
status: "failed",
|
|
242
|
-
transcript: stdout,
|
|
243
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
child.on("exit", (code) => {
|
|
247
|
-
clearTimeout(timer);
|
|
248
|
-
const transcript = [stdout, stderr].filter(Boolean).join("\n");
|
|
249
|
-
if (timedOut) {
|
|
250
|
-
resolve({
|
|
251
|
-
status: "failed",
|
|
252
|
-
transcript,
|
|
253
|
-
reason: "cursor-agent timed out"
|
|
254
|
-
});
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
resolve({
|
|
258
|
-
status: code === 0 ? "succeeded" : "failed",
|
|
259
|
-
transcript,
|
|
260
|
-
exitCode: code ?? 0,
|
|
261
|
-
...(code === 0 ? {} : { reason: stderr.slice(0, 500) })
|
|
262
|
-
});
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
}
|
|
266
|
-
function captureWorktreeDiff(cwd) {
|
|
267
|
-
try {
|
|
268
|
-
const result = spawnSync("git", ["-C", cwd, "diff"], { encoding: "utf8" });
|
|
269
|
-
const stdout = result.stdout ?? "";
|
|
270
|
-
return result.status === 0 && stdout.length > 0 ? stdout : undefined;
|
|
271
|
-
}
|
|
272
|
-
catch {
|
|
273
|
-
return undefined;
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
export function createCursorHarness(options = {}) {
|
|
277
|
-
const id = options.id ?? "cursor";
|
|
278
|
-
const runner = options.runner ?? defaultCursorRunner;
|
|
279
|
-
const skipWhenUnavailable = options.skipWhenUnavailable ?? true;
|
|
280
|
-
return {
|
|
281
|
-
id,
|
|
282
|
-
harnessKind: "cursor",
|
|
283
|
-
prepare: () => {
|
|
284
|
-
const env = definedEnv(options.env ?? process.env);
|
|
285
|
-
return { env, availability: resolveAvailability(options, env) };
|
|
286
|
-
},
|
|
287
|
-
capabilities: () => {
|
|
288
|
-
const env = definedEnv(options.env ?? process.env);
|
|
289
|
-
const available = resolveAvailability(options, env).available;
|
|
290
|
-
const status = available ? "supported" : "degraded";
|
|
291
|
-
return {
|
|
292
|
-
workspace_read: status,
|
|
293
|
-
workspace_write: status,
|
|
294
|
-
apply_patch: status,
|
|
295
|
-
tool_call_loop: status,
|
|
296
|
-
tool_records: status,
|
|
297
|
-
verification: status,
|
|
298
|
-
route_observation: "supported",
|
|
299
|
-
adapter_available: available ? "supported" : "unsupported"
|
|
300
|
-
};
|
|
301
|
-
},
|
|
302
|
-
verificationProfile: () => ({
|
|
303
|
-
id: `${id}-verification`,
|
|
304
|
-
requiredEvidence: [
|
|
305
|
-
"cursor-agent transcript",
|
|
306
|
-
"session status",
|
|
307
|
-
"worktree diff or skip reason"
|
|
308
|
-
]
|
|
309
|
-
}),
|
|
310
|
-
run: async ({ descriptor, model, ordinal, prepared, worktree }) => {
|
|
311
|
-
const state = prepared;
|
|
312
|
-
if (!state.availability.available) {
|
|
313
|
-
if (!skipWhenUnavailable) {
|
|
314
|
-
throw new Error(state.availability.reason);
|
|
315
|
-
}
|
|
316
|
-
return skippedCandidate({
|
|
317
|
-
descriptor,
|
|
318
|
-
model,
|
|
319
|
-
ordinal,
|
|
320
|
-
reason: state.availability.reason
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
const fusionBackendUrl = options.fusionBackendUrl ?? state.env.FUSIONKIT_BASE_URL;
|
|
324
|
-
if (fusionBackendUrl === undefined || fusionBackendUrl.length === 0) {
|
|
325
|
-
return skippedCandidate({
|
|
326
|
-
descriptor,
|
|
327
|
-
model,
|
|
328
|
-
ordinal,
|
|
329
|
-
reason: "Fusion backend URL is not configured for the Cursor harness."
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
|
-
const cwd = worktree?.path ?? descriptor.workspace ?? process.cwd();
|
|
333
|
-
let result;
|
|
334
|
-
try {
|
|
335
|
-
result = await runner({
|
|
336
|
-
prompt: descriptor.prompt,
|
|
337
|
-
cwd,
|
|
338
|
-
fusionBackendUrl,
|
|
339
|
-
...(options.apiKey !== undefined ? { apiKey: options.apiKey } : {}),
|
|
340
|
-
model,
|
|
341
|
-
cursorKitDir: state.availability.cursorKitDir,
|
|
342
|
-
command: state.availability.command,
|
|
343
|
-
modelName: options.modelName ?? DEFAULT_BRIDGE_MODEL_NAME,
|
|
344
|
-
providerModel: options.providerModel ?? model.model ?? DEFAULT_BRIDGE_PROVIDER_MODEL,
|
|
345
|
-
mode: modeFor(descriptor, options.mode),
|
|
346
|
-
...(options.timeoutMs !== undefined
|
|
347
|
-
? { timeoutMs: options.timeoutMs }
|
|
348
|
-
: descriptor.policy.timeoutMs !== undefined
|
|
349
|
-
? { timeoutMs: descriptor.policy.timeoutMs }
|
|
350
|
-
: {}),
|
|
351
|
-
env: state.env
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
catch (error) {
|
|
355
|
-
return skippedCandidate({
|
|
356
|
-
descriptor,
|
|
357
|
-
model,
|
|
358
|
-
ordinal,
|
|
359
|
-
reason: error instanceof Error ? error.message : String(error)
|
|
360
|
-
});
|
|
361
|
-
}
|
|
362
|
-
const transcript = result.transcript;
|
|
363
|
-
const outputHash = artifactHash(transcript.length > 0 ? transcript : `cursor:${descriptor.id}`);
|
|
364
|
-
const status = result.status;
|
|
365
|
-
const candidateId = `${descriptor.id}_${model.id}_${ordinal}`;
|
|
366
|
-
const artifacts = [
|
|
367
|
-
{
|
|
368
|
-
artifact_id: `artifact_${descriptor.id}_${model.id}_cursor_transcript`,
|
|
369
|
-
kind: "transcript",
|
|
370
|
-
hash: outputHash,
|
|
371
|
-
redaction_status: "synthetic"
|
|
372
|
-
}
|
|
373
|
-
];
|
|
374
|
-
if (result.diff !== undefined && result.diff.length > 0) {
|
|
375
|
-
artifacts.push({
|
|
376
|
-
artifact_id: `artifact_${descriptor.id}_${model.id}_cursor_patch`,
|
|
377
|
-
kind: "patch",
|
|
378
|
-
hash: artifactHash(result.diff),
|
|
379
|
-
redaction_status: "synthetic"
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
return {
|
|
383
|
-
candidateId,
|
|
384
|
-
model,
|
|
385
|
-
status,
|
|
386
|
-
...(worktree
|
|
387
|
-
? { branchName: worktree.branchName, worktreePath: worktree.path }
|
|
388
|
-
: {}),
|
|
389
|
-
transcript,
|
|
390
|
-
...(result.diff !== undefined ? { diff: result.diff } : {}),
|
|
391
|
-
log: transcript,
|
|
392
|
-
artifacts,
|
|
393
|
-
toolRecords: [
|
|
394
|
-
{
|
|
395
|
-
execution_id: `exec_${candidateId}_cursor`,
|
|
396
|
-
plan_id: `plan_${candidateId}_cursor`,
|
|
397
|
-
status,
|
|
398
|
-
output_hash: outputHash,
|
|
399
|
-
...(status === "failed"
|
|
400
|
-
? {
|
|
401
|
-
error: {
|
|
402
|
-
kind: "provider_error",
|
|
403
|
-
message: result.reason ?? "Cursor run failed.",
|
|
404
|
-
retryable: false
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
: {})
|
|
408
|
-
}
|
|
409
|
-
],
|
|
410
|
-
verification: {
|
|
411
|
-
status,
|
|
412
|
-
evidence: [
|
|
413
|
-
`tool_events=${result.toolEvents}`,
|
|
414
|
-
outputHash,
|
|
415
|
-
...(result.diff !== undefined ? ["worktree_diff"] : [])
|
|
416
|
-
],
|
|
417
|
-
...(result.exitCode !== undefined ? { exitCode: result.exitCode } : {})
|
|
418
|
-
},
|
|
419
|
-
...(status === "failed"
|
|
420
|
-
? {
|
|
421
|
-
error: {
|
|
422
|
-
kind: "provider_error",
|
|
423
|
-
message: result.reason ?? "Cursor run failed.",
|
|
424
|
-
retryable: false
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
: {}),
|
|
428
|
-
metadata: {
|
|
429
|
-
adapter: "cursor",
|
|
430
|
-
mode: modeFor(descriptor, options.mode),
|
|
431
|
-
tool_events: result.toolEvents,
|
|
432
|
-
has_diff: result.diff !== undefined && result.diff.length > 0
|
|
433
|
-
}
|
|
434
|
-
};
|
|
435
|
-
},
|
|
436
|
-
collectArtifacts: () => [],
|
|
437
|
-
cleanup: () => undefined
|
|
438
|
-
};
|
|
439
|
-
}
|
|
440
|
-
export const cursorHarness = createCursorHarness;
|
package/dist/dashboard.d.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { HarnessRunResultV1, ModelFusionHarnessKind } from "@fusionkit/protocol";
|
|
2
|
-
import type { HarnessAdapter, HarnessCapabilities } from "./harness.js";
|
|
3
|
-
declare const LIVE_SMOKE_TARGETS: readonly ["claude-code", "codex", "cursor"];
|
|
4
|
-
export type HarnessCapabilityTarget = "cursor" | "claude-code" | "codex" | "command" | "mock";
|
|
5
|
-
export type HarnessAvailability = "available" | "credential_gated" | "missing";
|
|
6
|
-
export type HarnessLiveSmokeTarget = (typeof LIVE_SMOKE_TARGETS)[number];
|
|
7
|
-
export type HarnessSmokePurpose = "contract" | "credential-skip" | "live" | "missing";
|
|
8
|
-
export type HarnessAdapterReadiness = {
|
|
9
|
-
harnessId: HarnessCapabilityTarget;
|
|
10
|
-
displayName: string;
|
|
11
|
-
contractReadiness: string;
|
|
12
|
-
credentialState: string;
|
|
13
|
-
liveSmoke: string;
|
|
14
|
-
evidence: string[];
|
|
15
|
-
artifactRefs: string[];
|
|
16
|
-
};
|
|
17
|
-
export type HarnessCapabilityMatrixRow = {
|
|
18
|
-
harnessId: HarnessCapabilityTarget;
|
|
19
|
-
harnessKind: ModelFusionHarnessKind;
|
|
20
|
-
displayName: string;
|
|
21
|
-
availability: HarnessAvailability;
|
|
22
|
-
capabilities: HarnessCapabilities;
|
|
23
|
-
notes: string[];
|
|
24
|
-
};
|
|
25
|
-
export type HarnessCapabilityMatrix = {
|
|
26
|
-
capabilities: string[];
|
|
27
|
-
rows: HarnessCapabilityMatrixRow[];
|
|
28
|
-
};
|
|
29
|
-
export type HarnessSmokeOutcome = "success" | "failure" | "missing" | "skipped";
|
|
30
|
-
export type HarnessSmokeRecord = {
|
|
31
|
-
taskId: string;
|
|
32
|
-
harnessId: HarnessCapabilityTarget;
|
|
33
|
-
purpose: HarnessSmokePurpose;
|
|
34
|
-
outcome: HarnessSmokeOutcome;
|
|
35
|
-
result: HarnessRunResultV1;
|
|
36
|
-
resultPath: string;
|
|
37
|
-
};
|
|
38
|
-
export type HarnessSmokeDashboard = {
|
|
39
|
-
outputRoot: string;
|
|
40
|
-
dashboardPath: string;
|
|
41
|
-
matrix: HarnessCapabilityMatrix;
|
|
42
|
-
records: HarnessSmokeRecord[];
|
|
43
|
-
readiness: HarnessAdapterReadiness[];
|
|
44
|
-
};
|
|
45
|
-
export type HarnessSmokeDashboardOptions = {
|
|
46
|
-
repo?: string;
|
|
47
|
-
outputRoot?: string;
|
|
48
|
-
timeoutMs?: number;
|
|
49
|
-
createdAt?: string;
|
|
50
|
-
env?: Record<string, string | undefined>;
|
|
51
|
-
commandSuccess?: string;
|
|
52
|
-
commandFailure?: string;
|
|
53
|
-
liveSmoke?: readonly HarnessLiveSmokeTarget[];
|
|
54
|
-
liveSmokeHarnesses?: Partial<Record<HarnessLiveSmokeTarget, HarnessAdapter>>;
|
|
55
|
-
};
|
|
56
|
-
export declare function createHarnessCapabilityMatrix(options?: HarnessSmokeDashboardOptions): HarnessCapabilityMatrix;
|
|
57
|
-
export declare function runHarnessSmokeDashboard(options?: HarnessSmokeDashboardOptions): Promise<HarnessSmokeDashboard>;
|
|
58
|
-
export declare const harnessDashboard: {
|
|
59
|
-
readonly capabilities: typeof createHarnessCapabilityMatrix;
|
|
60
|
-
readonly run: typeof runHarnessSmokeDashboard;
|
|
61
|
-
};
|
|
62
|
-
export {};
|