@workbench-ai/workbench 0.0.79 → 0.0.80
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/index.d.ts.map +1 -1
- package/dist/index.js +137 -12
- package/package.json +6 -6
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAkEA,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;CAC/B;AAuTD,wBAAsB,MAAM,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,EAAE,GAAE,KAGzD,GAAG,OAAO,CAAC,MAAM,CAAC,CAoMlB"}
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import os from "node:os";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { gzipSync } from "node:zlib";
|
|
7
|
-
import { addWorkbenchRemote, addWorkbenchAgent, compareWorkbench, createWorkbenchInspectionSnapshot, createWorkbenchAdapterAuthBundle, createWorkbenchReadOnlyInspectionSnapshot, diffWorkbenchVersions, evalWorkbenchSkill, improveWorkbenchSkill, initWorkbenchSkill, listWorkbenchAgents, listWorkbenchVersions, localWorkbenchAdapterAuthStore, parseWorkbenchAdapterAuthTarget, prepareWorkbenchCloudEvalRequest, prepareWorkbenchCloudImproveRequest, publishWorkbenchVersion, removeWorkbenchAgent, showWorkbenchRef, switchWorkbenchVersion, syncWorkbenchRemote, workbenchJobEvidenceForSnapshot, workbenchStatusSnapshot, WorkbenchCodedError, WorkbenchUserError, } from "@workbench-ai/workbench-core";
|
|
7
|
+
import { addWorkbenchRemote, addWorkbenchAgent, compareWorkbench, createWorkbenchVersionRuntimeSnapshot, createWorkbenchInspectionSnapshot, createWorkbenchAdapterAuthBundle, createWorkbenchReadOnlyInspectionSnapshot, diffWorkbenchVersions, evalWorkbenchSkill, improveWorkbenchSkill, initWorkbenchSkill, listWorkbenchAgents, listWorkbenchVersions, localWorkbenchAdapterAuthStore, parseWorkbenchAdapterAuthTarget, prepareWorkbenchCloudEvalRequest, prepareWorkbenchCloudImproveRequest, publishWorkbenchVersion, removeWorkbenchAgent, showWorkbenchRef, switchWorkbenchVersion, syncWorkbenchRemote, workbenchJobEvidenceForSnapshot, workbenchStatusSnapshot, WorkbenchCodedError, WorkbenchUserError, } from "@workbench-ai/workbench-core";
|
|
8
8
|
import { normalizeWorkbenchSkillName } from "@workbench-ai/workbench-contract";
|
|
9
9
|
import { emitError, emitResult } from "./output.js";
|
|
10
10
|
import { fanOutSkill, manualFanOutCommand } from "./fanout.js";
|
|
@@ -582,13 +582,15 @@ async function handleShow(parsed, io) {
|
|
|
582
582
|
if (artifact) {
|
|
583
583
|
return output(fileListing("artifact", artifact.id, artifact.files), parsed, io, () => formatFileListing("artifact", artifact.id, artifact.files));
|
|
584
584
|
}
|
|
585
|
-
const
|
|
586
|
-
const
|
|
587
|
-
|
|
585
|
+
const selection = runOrJobEvidenceSelection(snapshot, objectRef);
|
|
586
|
+
const details = evidenceDetailsForSelection(snapshot, selection);
|
|
587
|
+
const evidenceFiles = evidenceFilesForSelection(snapshot, selection);
|
|
588
|
+
if (selection.run || selection.jobs.length > 0 || details.length > 0 || evidenceFiles.length > 0) {
|
|
588
589
|
return output({
|
|
590
|
+
jobs: selection.jobs.map(jobEvidenceSummary),
|
|
589
591
|
details: details.map(evidenceDetailSummary),
|
|
590
592
|
files: evidenceFiles.map(fileSummary),
|
|
591
|
-
}, parsed, io, () => formatRunOrJobEvidence(details, evidenceFiles));
|
|
593
|
+
}, parsed, io, () => formatRunOrJobEvidence(selection.jobs, details, evidenceFiles));
|
|
592
594
|
}
|
|
593
595
|
const value = await showWorkbenchRef(ref, core);
|
|
594
596
|
return output(value, parsed, io, () => formatShow(value));
|
|
@@ -744,7 +746,8 @@ async function handleLogin(parsed, io) {
|
|
|
744
746
|
exitCode: 2,
|
|
745
747
|
});
|
|
746
748
|
}
|
|
747
|
-
const startOnly = parsed.flags["start-only"] === true
|
|
749
|
+
const startOnly = parsed.flags["start-only"] === true ||
|
|
750
|
+
(parsed.flags["no-open"] === true && parsed.flags.wait !== true && parsed.flags.timeout === undefined);
|
|
748
751
|
const waitOnly = parsed.flags.wait === true;
|
|
749
752
|
const timeoutSeconds = intFlag(parsed, "timeout");
|
|
750
753
|
if (startOnly && timeoutSeconds !== undefined) {
|
|
@@ -1019,6 +1022,9 @@ function installNextCommand(fanout) {
|
|
|
1019
1022
|
}
|
|
1020
1023
|
function formatInstallOutcome(result, dryRun) {
|
|
1021
1024
|
if (dryRun) {
|
|
1025
|
+
if (result.result === "unchanged") {
|
|
1026
|
+
return `Already installed ${result.directoryName} at ${result.destination} (unchanged; dry run made no changes).`;
|
|
1027
|
+
}
|
|
1022
1028
|
return `Would install ${result.directoryName} to ${result.destination} (${formatFileCount(result.filesCopied)}).`;
|
|
1023
1029
|
}
|
|
1024
1030
|
if (result.result === "unchanged") {
|
|
@@ -1082,7 +1088,7 @@ function withTimeout(promise, timeoutMs) {
|
|
|
1082
1088
|
}
|
|
1083
1089
|
async function startCloudExecution(command, parsed, io) {
|
|
1084
1090
|
const root = dirFlag(parsed) ?? process.cwd();
|
|
1085
|
-
const showProgress =
|
|
1091
|
+
const showProgress = true;
|
|
1086
1092
|
const interrupt = createCloudInterruptController(command, io, showProgress);
|
|
1087
1093
|
try {
|
|
1088
1094
|
writeCloudProgress(io, `workbench cloud: preparing hosted ${command}.`, showProgress);
|
|
@@ -1118,6 +1124,14 @@ async function startCloudExecution(command, parsed, io) {
|
|
|
1118
1124
|
samples: intFlag(parsed, "samples"),
|
|
1119
1125
|
budget: intFlag(parsed, "budget"),
|
|
1120
1126
|
}));
|
|
1127
|
+
writeCloudProgress(io, "workbench cloud: checking provider auth.", showProgress);
|
|
1128
|
+
await cloudPreScheduleStep(command, interrupt, preflightCloudAdapterAuth({
|
|
1129
|
+
root,
|
|
1130
|
+
versionId: request.versionId,
|
|
1131
|
+
parsed,
|
|
1132
|
+
baseUrl: source.baseUrl,
|
|
1133
|
+
authToken: token,
|
|
1134
|
+
}));
|
|
1121
1135
|
writeCloudProgress(io, "workbench cloud: syncing source to cloud.", showProgress);
|
|
1122
1136
|
const syncBefore = await cloudPreScheduleStep(command, interrupt, syncWorkbenchRemote({ ...core, remote: remote.name }));
|
|
1123
1137
|
writeCloudProgress(io, `workbench cloud: scheduling hosted ${command}.`, showProgress);
|
|
@@ -1216,6 +1230,79 @@ function cloudCanceledBeforeRunIdError(command) {
|
|
|
1216
1230
|
exitCode: 130,
|
|
1217
1231
|
});
|
|
1218
1232
|
}
|
|
1233
|
+
async function preflightCloudAdapterAuth(input) {
|
|
1234
|
+
const snapshot = await createWorkbenchReadOnlyInspectionSnapshot({ dir: input.root, authToken: input.authToken });
|
|
1235
|
+
const version = snapshotVersionByRef(snapshot, input.versionId);
|
|
1236
|
+
if (!version) {
|
|
1237
|
+
throw new WorkbenchCodedError("version_not_found", `Version not found: ${input.versionId}`, {
|
|
1238
|
+
remediation: "Run workbench status.",
|
|
1239
|
+
subject: { versionId: input.versionId },
|
|
1240
|
+
exitCode: 1,
|
|
1241
|
+
});
|
|
1242
|
+
}
|
|
1243
|
+
const runtime = await createWorkbenchVersionRuntimeSnapshot(version, {
|
|
1244
|
+
skill: stringFlag(input.parsed, "skills"),
|
|
1245
|
+
agent: stringFlag(input.parsed, "agents"),
|
|
1246
|
+
authToken: input.authToken,
|
|
1247
|
+
});
|
|
1248
|
+
const targets = uniqueAdapterAuthTargets(runtime.selectedAgents.flatMap(cloudAdapterAuthTargetsForAgent));
|
|
1249
|
+
if (targets.length === 0) {
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
const statuses = await fetchCloudAdapterAuthStatuses(input.baseUrl);
|
|
1253
|
+
const missing = targets.find((target) => !statuses.some((status) => adapterAuthStatusMatchesTarget(status, target)));
|
|
1254
|
+
if (!missing) {
|
|
1255
|
+
return;
|
|
1256
|
+
}
|
|
1257
|
+
throw new WorkbenchCodedError("adapter_auth_required", `${formatCloudAdapterAuthTarget(missing)} disconnected. Run workbench login ${missing.adapterId}.`, {
|
|
1258
|
+
remediation: `Run workbench login ${missing.adapterId}.`,
|
|
1259
|
+
subject: {
|
|
1260
|
+
adapterId: missing.adapterId,
|
|
1261
|
+
profile: missing.profile,
|
|
1262
|
+
...(missing.slot ? { slot: missing.slot } : {}),
|
|
1263
|
+
},
|
|
1264
|
+
exitCode: 1,
|
|
1265
|
+
});
|
|
1266
|
+
}
|
|
1267
|
+
function cloudAdapterAuthTargetsForAgent(agent) {
|
|
1268
|
+
const adapterId = agent.adapter.trim().toLowerCase();
|
|
1269
|
+
if (adapterId !== "codex" && adapterId !== "claude") {
|
|
1270
|
+
return [];
|
|
1271
|
+
}
|
|
1272
|
+
const auth = agent.config.auth;
|
|
1273
|
+
if (typeof auth === "string" && auth.trim()) {
|
|
1274
|
+
return [{ adapterId, profile: auth.trim() }];
|
|
1275
|
+
}
|
|
1276
|
+
if (auth && typeof auth === "object" && !Array.isArray(auth)) {
|
|
1277
|
+
return Object.entries(auth)
|
|
1278
|
+
.filter((entry) => typeof entry[1] === "string" && entry[1].trim().length > 0)
|
|
1279
|
+
.map(([slot, profile]) => ({ adapterId, slot, profile: profile.trim() }));
|
|
1280
|
+
}
|
|
1281
|
+
return [{ adapterId, profile: "default" }];
|
|
1282
|
+
}
|
|
1283
|
+
function uniqueAdapterAuthTargets(targets) {
|
|
1284
|
+
const byKey = new Map();
|
|
1285
|
+
for (const target of targets) {
|
|
1286
|
+
byKey.set(adapterAuthTargetKey(target), target);
|
|
1287
|
+
}
|
|
1288
|
+
return [...byKey.values()].sort((left, right) => adapterAuthTargetKey(left).localeCompare(adapterAuthTargetKey(right)));
|
|
1289
|
+
}
|
|
1290
|
+
async function fetchCloudAdapterAuthStatuses(baseUrl) {
|
|
1291
|
+
const response = await apiRequest("/api/workbench/auth/adapters", {}, baseUrl);
|
|
1292
|
+
return response.adapters ?? [];
|
|
1293
|
+
}
|
|
1294
|
+
function adapterAuthStatusMatchesTarget(status, target) {
|
|
1295
|
+
return status.status === "connected" &&
|
|
1296
|
+
status.adapterId === target.adapterId &&
|
|
1297
|
+
status.profile === target.profile &&
|
|
1298
|
+
(status.slot ?? undefined) === (target.slot ?? undefined);
|
|
1299
|
+
}
|
|
1300
|
+
function adapterAuthTargetKey(target) {
|
|
1301
|
+
return `${target.adapterId}/${target.slot ?? "_"}/${target.profile}`;
|
|
1302
|
+
}
|
|
1303
|
+
function formatCloudAdapterAuthTarget(target) {
|
|
1304
|
+
return `${target.adapterId}${target.slot ? `/${target.slot}` : ""}`;
|
|
1305
|
+
}
|
|
1219
1306
|
async function waitForCloudRuns(input) {
|
|
1220
1307
|
const runIds = input.runs
|
|
1221
1308
|
.map((run) => run.id)
|
|
@@ -2876,6 +2963,16 @@ function displayRef(id) {
|
|
|
2876
2963
|
function shortenCommandRefs(command) {
|
|
2877
2964
|
return command.replace(/\b(?:v_[0-9a-f]{8,}|(?:run|job|trace|artifact)_[a-z0-9_-]+)/giu, (match) => displayRef(match));
|
|
2878
2965
|
}
|
|
2966
|
+
function displayCandidateRefs(ids) {
|
|
2967
|
+
const uniqueIds = [...ids];
|
|
2968
|
+
for (let length = 8; length <= 32; length += 1) {
|
|
2969
|
+
const refs = uniqueIds.map((id) => id.length > length ? id.slice(0, length) : id);
|
|
2970
|
+
if (new Set(refs).size === refs.length) {
|
|
2971
|
+
return refs;
|
|
2972
|
+
}
|
|
2973
|
+
}
|
|
2974
|
+
return uniqueIds;
|
|
2975
|
+
}
|
|
2879
2976
|
function snapshotVersionByRef(snapshot, ref) {
|
|
2880
2977
|
const requested = ref.trim();
|
|
2881
2978
|
const normalized = requested === "current" ? snapshot.refs.current ?? "" : requested;
|
|
@@ -2884,7 +2981,7 @@ function snapshotVersionByRef(snapshot, ref) {
|
|
|
2884
2981
|
}
|
|
2885
2982
|
const candidates = snapshot.versions.filter((version) => snapshotVersionRefMatches(version, normalized));
|
|
2886
2983
|
if (candidates.length > 1) {
|
|
2887
|
-
throw new WorkbenchCodedError("ref_ambiguous", `Version ref is ambiguous: ${ref}. Candidates: ${candidates.map((version) =>
|
|
2984
|
+
throw new WorkbenchCodedError("ref_ambiguous", `Version ref is ambiguous: ${ref}. Candidates: ${displayCandidateRefs(candidates.map((version) => version.id)).join(", ")}.`, {
|
|
2888
2985
|
subject: { ref, candidates: candidates.map((version) => version.id) },
|
|
2889
2986
|
exitCode: 2,
|
|
2890
2987
|
});
|
|
@@ -2907,7 +3004,7 @@ function snapshotObjectByRef(entries, ref, kind) {
|
|
|
2907
3004
|
}
|
|
2908
3005
|
const candidates = entries.filter((entry) => objectRefMatches(entry.id, normalized));
|
|
2909
3006
|
if (candidates.length > 1) {
|
|
2910
|
-
throw new WorkbenchCodedError("ref_ambiguous", `${capitalize(kind)} ref is ambiguous: ${ref}. Candidates: ${candidates.map((entry) =>
|
|
3007
|
+
throw new WorkbenchCodedError("ref_ambiguous", `${capitalize(kind)} ref is ambiguous: ${ref}. Candidates: ${displayCandidateRefs(candidates.map((entry) => entry.id)).slice(0, 8).join(", ")}.`, {
|
|
2911
3008
|
subject: { ref, candidates: candidates.map((entry) => entry.id).slice(0, 20) },
|
|
2912
3009
|
exitCode: 2,
|
|
2913
3010
|
});
|
|
@@ -2928,7 +3025,7 @@ function runOrJobEvidenceSelection(snapshot, ref) {
|
|
|
2928
3025
|
const run = snapshotObjectByRef(snapshot.runs, ref, "run");
|
|
2929
3026
|
const job = snapshotObjectByRef(snapshot.jobs, ref, "job");
|
|
2930
3027
|
if (run && job) {
|
|
2931
|
-
throw new WorkbenchCodedError("ref_ambiguous", `Run/job ref is ambiguous: ${ref}. Candidates: ${
|
|
3028
|
+
throw new WorkbenchCodedError("ref_ambiguous", `Run/job ref is ambiguous: ${ref}. Candidates: ${displayCandidateRefs([run.id, job.id]).join(", ")}.`, {
|
|
2932
3029
|
subject: { ref, candidates: [run.id, job.id] },
|
|
2933
3030
|
exitCode: 2,
|
|
2934
3031
|
});
|
|
@@ -2943,6 +3040,9 @@ function runOrJobEvidenceSelection(snapshot, ref) {
|
|
|
2943
3040
|
}
|
|
2944
3041
|
function evidenceFilesForRunOrJob(snapshot, ref) {
|
|
2945
3042
|
const selection = runOrJobEvidenceSelection(snapshot, ref);
|
|
3043
|
+
return evidenceFilesForSelection(snapshot, selection);
|
|
3044
|
+
}
|
|
3045
|
+
function evidenceFilesForSelection(snapshot, selection) {
|
|
2946
3046
|
if (!selection.run && selection.jobs.length === 0) {
|
|
2947
3047
|
return [];
|
|
2948
3048
|
}
|
|
@@ -3024,10 +3124,32 @@ function isUserFacingTraceEvidenceFile(file) {
|
|
|
3024
3124
|
function evidencePathSegment(value) {
|
|
3025
3125
|
return value.replace(/[^A-Za-z0-9._-]+/gu, "-") || "_";
|
|
3026
3126
|
}
|
|
3027
|
-
function formatRunOrJobEvidence(details, files) {
|
|
3127
|
+
function formatRunOrJobEvidence(jobs, details, files) {
|
|
3128
|
+
const jobLines = jobs.length > 0 ? ["Jobs:", ...jobs.map(formatJobEvidenceSummary)] : [];
|
|
3028
3129
|
const detailLines = details.map(formatTraceDetail).filter(Boolean);
|
|
3029
3130
|
const fileLines = files.length > 0 ? ["Files:", ...files.map((file) => file.path)] : [];
|
|
3030
|
-
return [...detailLines, ...fileLines].join("\n") || "No evidence.";
|
|
3131
|
+
return [...jobLines, ...detailLines, ...fileLines].join("\n") || "No evidence.";
|
|
3132
|
+
}
|
|
3133
|
+
function jobEvidenceSummary(job) {
|
|
3134
|
+
return {
|
|
3135
|
+
id: job.id,
|
|
3136
|
+
runId: job.runId,
|
|
3137
|
+
caseId: job.caseId,
|
|
3138
|
+
sample: job.sample,
|
|
3139
|
+
status: job.status,
|
|
3140
|
+
...(job.score !== undefined ? { score: job.score } : {}),
|
|
3141
|
+
...(job.error ? { error: job.error } : {}),
|
|
3142
|
+
};
|
|
3143
|
+
}
|
|
3144
|
+
function formatJobEvidenceSummary(job) {
|
|
3145
|
+
return [
|
|
3146
|
+
displayRef(job.id),
|
|
3147
|
+
`case=${job.caseId}`,
|
|
3148
|
+
`sample=${job.sample}`,
|
|
3149
|
+
job.status,
|
|
3150
|
+
job.score !== undefined ? `score=${job.score.toFixed(3)}` : undefined,
|
|
3151
|
+
job.error ? `error=${singleLine(job.error)}` : undefined,
|
|
3152
|
+
].filter(Boolean).join("\t");
|
|
3031
3153
|
}
|
|
3032
3154
|
function evidenceDetailSummary(detail) {
|
|
3033
3155
|
return {
|
|
@@ -3103,6 +3225,9 @@ async function fileForRunOrJobRef(core, objectRef, requestedPath) {
|
|
|
3103
3225
|
}
|
|
3104
3226
|
function evidenceDetailsForRunOrJob(snapshot, ref) {
|
|
3105
3227
|
const selection = runOrJobEvidenceSelection(snapshot, ref);
|
|
3228
|
+
return evidenceDetailsForSelection(snapshot, selection);
|
|
3229
|
+
}
|
|
3230
|
+
function evidenceDetailsForSelection(snapshot, selection) {
|
|
3106
3231
|
return selection.jobs.flatMap((entry) => {
|
|
3107
3232
|
const detail = workbenchJobEvidenceForSnapshot(snapshot, {
|
|
3108
3233
|
runId: entry.runId,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workbench-ai/workbench",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.80",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/workbench-ai/workbench.git",
|
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"skills": "1.5.11",
|
|
24
24
|
"yaml": "^2.8.2",
|
|
25
|
-
"@workbench-ai/workbench-built-in-adapters": "0.0.
|
|
26
|
-
"@workbench-ai/workbench-
|
|
27
|
-
"@workbench-ai/workbench-contract": "0.0.
|
|
28
|
-
"@workbench-ai/workbench-
|
|
25
|
+
"@workbench-ai/workbench-built-in-adapters": "0.0.80",
|
|
26
|
+
"@workbench-ai/workbench-protocol": "0.0.80",
|
|
27
|
+
"@workbench-ai/workbench-contract": "0.0.80",
|
|
28
|
+
"@workbench-ai/workbench-core": "0.0.80"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@tailwindcss/postcss": "^4.2.2",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"react-dom": "^19.2.0",
|
|
37
37
|
"typescript": "^5.9.2",
|
|
38
38
|
"vitest": "^3.2.4",
|
|
39
|
-
"@workbench-ai/workbench-ui": "0.0.
|
|
39
|
+
"@workbench-ai/workbench-ui": "0.0.80"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "rm -rf dist && tsc -p tsconfig.json && chmod 755 dist/workbench.js && node ./scripts/build-dev-open-assets.mjs",
|