@workbench-ai/workbench 0.0.82 → 0.0.84

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.
@@ -1 +1 @@
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"}
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,CAqMlB"}
package/dist/index.js CHANGED
@@ -423,9 +423,10 @@ export async function runCli(argv, io = {
423
423
  });
424
424
  return emitResult("workbench.cli.sync.v1", {
425
425
  remote: result.remote,
426
+ status: result.dryRun ? "dry_run" : "synced",
426
427
  pushed: result.pushed,
427
428
  pulled: result.pulled,
428
- upToDate: result.upToDate,
429
+ changed: syncChanged(result),
429
430
  publication: result.publication,
430
431
  ...(result.dryRun ? { dryRun: true } : {}),
431
432
  }, parsed, io, () => `${result.dryRun ? "Would sync" : "Synced"} ${result.remote.name}: pushed ${result.pushed}, pulled ${result.pulled}${result.upToDate ? " (up to date)" : ""}.`);
@@ -973,10 +974,9 @@ async function handleCloudImprove(parsed, io) {
973
974
  if (started.detached) {
974
975
  const next = cloudDetachedNextCommand(started.runs);
975
976
  emitResult("workbench.cli.improve.v1", {
976
- result: started.runs.map((run) => runSummary(run, artifactIds.get(run.id) ?? [])),
977
+ result: hostedImproveResult(started, artifactIds),
977
978
  detached: true,
978
979
  next: next,
979
- cloud: cloudExecutionSummary(started),
980
980
  }, parsed, io, () => [
981
981
  `Detached from hosted improve on ${started.remote.url}.`,
982
982
  started.runs.map(formatRun).join("\n"),
@@ -996,17 +996,15 @@ async function handleCloudImprove(parsed, io) {
996
996
  exitCode: 1,
997
997
  });
998
998
  }
999
- const switchedVersionId = await switchHostedImproveVersionIfPromoted(started);
999
+ const switchedVersion = await switchHostedImproveVersionIfPromoted(started);
1000
1000
  const next = cloudImproveNextCommand(started.runs);
1001
1001
  return emitResult("workbench.cli.improve.v1", {
1002
- result: started.runs.map((run) => runSummary(run, artifactIds.get(run.id) ?? [])),
1002
+ result: hostedImproveResult(started, artifactIds, switchedVersion),
1003
1003
  next: next,
1004
- cloud: cloudExecutionSummary(started),
1005
- ...(switchedVersionId ? { switchedVersionId } : {}),
1006
1004
  }, parsed, io, () => [
1007
1005
  `Completed hosted improve on ${started.remote.url}.`,
1008
1006
  started.runs.map(formatRun).join("\n"),
1009
- ...(switchedVersionId ? [`Switched local source to ${displayRef(switchedVersionId)}.`] : []),
1007
+ ...(switchedVersion ? [`Switched local source to ${displayRef(switchedVersion.id)}.`] : []),
1010
1008
  ...(next ? [`next: ${next}`] : []),
1011
1009
  ].filter(Boolean).join("\n"));
1012
1010
  }
@@ -1409,7 +1407,7 @@ async function switchHostedImproveVersionIfPromoted(started) {
1409
1407
  });
1410
1408
  }
1411
1409
  const version = await switchWorkbenchVersion(outputVersionId, started.core);
1412
- return version.id;
1410
+ return version;
1413
1411
  }
1414
1412
  async function fetchCloudObjectRefs(started) {
1415
1413
  const response = await apiRequest(`/api/workbench/skills/${encodeURIComponent(started.skillId)}/objects`, {}, started.source.baseUrl);
@@ -1529,9 +1527,34 @@ function cloudExecutionSummary(started) {
1529
1527
  skillId: started.skillId,
1530
1528
  initialRunIds: started.initialRunIds,
1531
1529
  ...(started.detached ? { detached: true } : {}),
1532
- sync: started.sync,
1530
+ sync: {
1531
+ before: cloudSyncSummary(started.sync.before),
1532
+ after: cloudSyncSummary(started.sync.after),
1533
+ },
1533
1534
  };
1534
1535
  }
1536
+ function hostedImproveResult(started, artifactIds, switchedVersion) {
1537
+ const runs = started.runs.map((run) => runSummary(run, artifactIds.get(run.id) ?? []));
1538
+ return {
1539
+ run: runs[0] ?? null,
1540
+ runs,
1541
+ switched: Boolean(switchedVersion),
1542
+ promoted: Boolean(switchedVersion),
1543
+ ...(switchedVersion ? { version: versionSummary(switchedVersion) } : {}),
1544
+ cloud: cloudExecutionSummary(started),
1545
+ };
1546
+ }
1547
+ function cloudSyncSummary(sync) {
1548
+ return {
1549
+ status: "synced",
1550
+ pushed: sync.pushed,
1551
+ pulled: sync.pulled,
1552
+ changed: syncChanged(sync),
1553
+ };
1554
+ }
1555
+ function syncChanged(sync) {
1556
+ return sync.pushed > 0 || sync.pulled > 0;
1557
+ }
1535
1558
  function writeCloudProgress(io, message, enabled = true) {
1536
1559
  if (!enabled) {
1537
1560
  return;
@@ -2152,7 +2175,7 @@ async function collectAdapterAuthBundle(args) {
2152
2175
  return createWorkbenchAdapterAuthBundle({
2153
2176
  target: args.target,
2154
2177
  method: args.method,
2155
- env: requiredEnvVars(["OPENAI_API_KEY"]),
2178
+ env: requiredEnvVars(["OPENAI_API_KEY"], [], "Set OPENAI_API_KEY, then run workbench login codex --method api-key."),
2156
2179
  });
2157
2180
  }
2158
2181
  if (args.method === "oauth") {
@@ -2168,7 +2191,7 @@ async function collectAdapterAuthBundle(args) {
2168
2191
  return createWorkbenchAdapterAuthBundle({
2169
2192
  target: args.target,
2170
2193
  method: args.method,
2171
- env: requiredEnvVars(["ANTHROPIC_API_KEY"]),
2194
+ env: requiredEnvVars(["ANTHROPIC_API_KEY"], [], "Set ANTHROPIC_API_KEY, then run workbench login claude --method api-key."),
2172
2195
  });
2173
2196
  }
2174
2197
  if (args.method === "oauth") {
@@ -2202,10 +2225,14 @@ async function collectAdapterAuthBundle(args) {
2202
2225
  }
2203
2226
  throw new WorkbenchUserError(`Adapter ${adapterId} does not support local ${args.method} auth capture in this CLI.`);
2204
2227
  }
2205
- function requiredEnvVars(required, optional = []) {
2228
+ function requiredEnvVars(required, optional = [], remediation) {
2206
2229
  const missing = required.filter((name) => !process.env[name]?.trim());
2207
2230
  if (missing.length > 0) {
2208
- throw new WorkbenchUserError(`Missing required environment variable(s): ${missing.join(", ")}`);
2231
+ throw new WorkbenchCodedError("usage", `Missing required environment variable(s): ${missing.join(", ")}`, {
2232
+ ...(remediation ? { remediation } : {}),
2233
+ subject: { missingEnvVars: missing },
2234
+ exitCode: 2,
2235
+ });
2209
2236
  }
2210
2237
  return Object.fromEntries([...required, ...optional].flatMap((name) => {
2211
2238
  const value = process.env[name]?.trim();
@@ -2963,17 +2990,30 @@ function versionHasAncestor(snapshot, versionId, ancestorId) {
2963
2990
  return false;
2964
2991
  }
2965
2992
  function displayRef(id) {
2993
+ return displayRefWithMinLength(id, 8);
2994
+ }
2995
+ function displayRefWithMinLength(id, minLength) {
2966
2996
  const version = /^v_([0-9a-f]{8,})$/iu.exec(id);
2967
2997
  if (version?.[1]) {
2968
- return version[1].slice(0, 8);
2998
+ return version[1].slice(0, minLength);
2969
2999
  }
2970
3000
  const separator = id.indexOf("_");
2971
3001
  if (separator > 0 && separator < id.length - 1) {
2972
3002
  const prefix = id.slice(0, separator);
2973
3003
  const suffix = id.slice(separator + 1);
2974
- return `${prefix}_${suffix.slice(0, 8)}`;
3004
+ return `${prefix}_${suffix.slice(0, minLength)}`;
2975
3005
  }
2976
- return id.length > 8 ? id.slice(0, 8) : id;
3006
+ return id.length > minLength ? id.slice(0, minLength) : id;
3007
+ }
3008
+ function displayRefsForIds(ids) {
3009
+ const uniqueIds = [...new Set(ids)];
3010
+ for (let length = 8; length <= 32; length += 1) {
3011
+ const refs = uniqueIds.map((id) => displayRefWithMinLength(id, length));
3012
+ if (new Set(refs).size === refs.length) {
3013
+ return new Map(uniqueIds.map((id, index) => [id, refs[index]]));
3014
+ }
3015
+ }
3016
+ return new Map(uniqueIds.map((id) => [id, id]));
2977
3017
  }
2978
3018
  function shortenCommandRefs(command) {
2979
3019
  return command.replace(/\b(?:v_[0-9a-f]{8,}|(?:run|job|trace|artifact)_[a-z0-9_-]+)/giu, (match) => displayRef(match));
@@ -3140,8 +3180,16 @@ function evidencePathSegment(value) {
3140
3180
  return value.replace(/[^A-Za-z0-9._-]+/gu, "-") || "_";
3141
3181
  }
3142
3182
  function formatRunOrJobEvidence(jobs, details, files) {
3143
- const jobLines = jobs.length > 0 ? ["Jobs:", ...jobs.map(formatJobEvidenceSummary)] : [];
3144
- const detailLines = details.map(formatTraceDetail).filter(Boolean);
3183
+ const jobRefs = displayRefsForIds([
3184
+ ...jobs.map((job) => job.id),
3185
+ ...details.flatMap((detail) => detail.executions.flatMap((execution) => execution.jobIds)),
3186
+ ]);
3187
+ const runRefs = displayRefsForIds([
3188
+ ...jobs.map((job) => job.runId),
3189
+ ...details.map((detail) => detail.runId),
3190
+ ]);
3191
+ const jobLines = jobs.length > 0 ? ["Jobs:", ...jobs.map((job) => formatJobEvidenceSummary(job, jobRefs))] : [];
3192
+ const detailLines = details.map((detail) => formatTraceDetail(detail, { jobRefs, runRefs })).filter(Boolean);
3145
3193
  const fileLines = files.length > 0 ? ["Files:", ...files.map((file) => file.path)] : [];
3146
3194
  return [...jobLines, ...detailLines, ...fileLines].join("\n") || "No evidence.";
3147
3195
  }
@@ -3156,9 +3204,9 @@ function jobEvidenceSummary(job) {
3156
3204
  ...(job.error ? { error: job.error } : {}),
3157
3205
  };
3158
3206
  }
3159
- function formatJobEvidenceSummary(job) {
3207
+ function formatJobEvidenceSummary(job, refs = new Map()) {
3160
3208
  return [
3161
- displayRef(job.id),
3209
+ refs.get(job.id) ?? displayRef(job.id),
3162
3210
  `case=${job.caseId}`,
3163
3211
  `sample=${job.sample}`,
3164
3212
  job.status,
@@ -3277,17 +3325,9 @@ function findShowFile(files, requestedPath, objectRef) {
3277
3325
  if (candidates.length === 1) {
3278
3326
  return candidates[0];
3279
3327
  }
3280
- const equivalentCandidate = singleEquivalentShowFile(candidates);
3281
- if (equivalentCandidate) {
3282
- return equivalentCandidate;
3283
- }
3284
3328
  if (candidates.length === 0 && suffixCandidates.length === 1) {
3285
3329
  return suffixCandidates[0];
3286
3330
  }
3287
- const equivalentSuffixCandidate = singleEquivalentShowFile(suffixCandidates);
3288
- if (equivalentSuffixCandidate) {
3289
- return equivalentSuffixCandidate;
3290
- }
3291
3331
  throw ambiguousShowPath(objectRef, requestedPath, candidates.length > 0 ? candidates : suffixCandidates);
3292
3332
  }
3293
3333
  function singleEquivalentShowFile(files) {
@@ -3645,11 +3685,11 @@ function traceSummary(trace) {
3645
3685
  files: trace.files.map(fileSummary),
3646
3686
  };
3647
3687
  }
3648
- function formatTraceDetail(detail) {
3688
+ function formatTraceDetail(detail, refs = {}) {
3649
3689
  return detail.executions.map((execution) => {
3650
3690
  const sessionLabels = execution.sessions.map((session) => session.label).join(",");
3651
3691
  return [
3652
- `${execution.id}\trun=${displayRef(detail.runId)}\tjobs=${execution.jobIds.map(displayRef).join(",")}\tstatus=${execution.status}`,
3692
+ `${execution.id}\trun=${refs.runRefs?.get(detail.runId) ?? displayRef(detail.runId)}\tjobs=${execution.jobIds.map((id) => refs.jobRefs?.get(id) ?? displayRef(id)).join(",")}\tstatus=${execution.status}`,
3653
3693
  `events=${execution.trace.events.length}`,
3654
3694
  `spans=${execution.trace.spans.length}`,
3655
3695
  `summaries=${execution.trace.summaries.length}`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workbench-ai/workbench",
3
- "version": "0.0.82",
3
+ "version": "0.0.84",
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.82",
26
- "@workbench-ai/workbench-contract": "0.0.82",
27
- "@workbench-ai/workbench-protocol": "0.0.82",
28
- "@workbench-ai/workbench-core": "0.0.82"
25
+ "@workbench-ai/workbench-built-in-adapters": "0.0.84",
26
+ "@workbench-ai/workbench-contract": "0.0.84",
27
+ "@workbench-ai/workbench-protocol": "0.0.84",
28
+ "@workbench-ai/workbench-core": "0.0.84"
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.82"
39
+ "@workbench-ai/workbench-ui": "0.0.84"
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",