@workbench-ai/workbench 0.0.87 → 0.0.89

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":"AAiEA,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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAiEA,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,CAgNlB"}
package/dist/index.js CHANGED
@@ -420,6 +420,7 @@ export async function runCli(argv, io = {
420
420
  remote: optionalPositional(parsed, 1),
421
421
  dryRun: parsed.flags["dry-run"] === true,
422
422
  });
423
+ const next = result.dryRun ? null : await syncNextCommand(core);
423
424
  return emitResult("workbench.cli.sync.v1", {
424
425
  remote: result.remote,
425
426
  status: result.dryRun ? "dry_run" : "synced",
@@ -427,8 +428,12 @@ export async function runCli(argv, io = {
427
428
  pulled: result.pulled,
428
429
  changed: syncChanged(result),
429
430
  publication: result.publication,
431
+ next: next,
430
432
  ...(result.dryRun ? { dryRun: true } : {}),
431
- }, parsed, io, () => `${result.dryRun ? "Would sync" : "Synced"} ${result.remote.name}: pushed ${result.pushed}, pulled ${result.pulled}${result.upToDate ? " (up to date)" : ""}.`);
433
+ }, parsed, io, () => [
434
+ `${result.dryRun ? "Would sync" : "Synced"} ${result.remote.name}: pushed ${result.pushed}, pulled ${result.pulled}${result.upToDate ? " (up to date)" : ""}.`,
435
+ ...(next ? [`next: ${next}`] : []),
436
+ ].join("\n"));
432
437
  }
433
438
  if (command === "publish") {
434
439
  const preview = parsed.flags["dry-run"] === true
@@ -448,14 +453,21 @@ export async function runCli(argv, io = {
448
453
  `next: workbench install ${preview.installHandle}`,
449
454
  ].join("\n"));
450
455
  }
451
- const remote = await ensurePublishRemote(parsed);
452
- const result = await publishWorkbenchVersion({
453
- ...core,
454
- version: optionalPositional(parsed, 1),
455
- remote,
456
- dryRun: parsed.flags["dry-run"] === true,
457
- visibility: parsePublishVisibilityFlags(parsed),
458
- });
456
+ let remote;
457
+ let result;
458
+ try {
459
+ remote = await ensurePublishRemote(parsed);
460
+ result = await publishWorkbenchVersion({
461
+ ...core,
462
+ version: optionalPositional(parsed, 1),
463
+ remote,
464
+ dryRun: parsed.flags["dry-run"] === true,
465
+ visibility: parsePublishVisibilityFlags(parsed),
466
+ });
467
+ }
468
+ catch (error) {
469
+ throw await publishErrorWithCliContext(error, parsed, remote);
470
+ }
459
471
  return emitResult("workbench.cli.publish.v1", {
460
472
  remote: result.remote,
461
473
  version: versionSummary(result.version),
@@ -607,12 +619,14 @@ async function handleAgent(parsed, io) {
607
619
  if (!adapter) {
608
620
  throw new WorkbenchUserError("workbench agent add requires --adapter ADAPTER.");
609
621
  }
622
+ const config = parseWithFlags(parsed);
623
+ validateAgentCommandConfig(config);
610
624
  const agent = await addWorkbenchAgent({
611
625
  ...(await coreOptions(parsed)),
612
626
  name,
613
627
  adapter,
614
628
  model: stringFlag(parsed, "model"),
615
- config: parseWithFlags(parsed),
629
+ config,
616
630
  });
617
631
  return output(agent, parsed, io, () => `Added agent ${formatAgent(agent)}.`);
618
632
  }
@@ -649,7 +663,17 @@ async function handleAdapterLogin(provider, parsed, io) {
649
663
  async function handleAdapterLogout(provider, parsed, io) {
650
664
  const target = parseAuthTarget(provider, authProfileFlag(parsed));
651
665
  await localWorkbenchAdapterAuthStore(adapterAuthStoreRoot()).disconnect(target);
652
- const remote = await deleteAdapterConnectionRemote(target, parsed);
666
+ const remote = await deleteAdapterConnectionRemote(target, parsed).catch((error) => {
667
+ if (error instanceof WorkbenchCodedError && error.code === "auth_required") {
668
+ return {
669
+ status: "not_authenticated",
670
+ sync: "skipped",
671
+ reason: "not_authenticated",
672
+ remediation: "Run workbench login.",
673
+ };
674
+ }
675
+ throw error;
676
+ });
653
677
  return emitResult("workbench.cli.logout.v1", {
654
678
  provider: target.adapterId,
655
679
  localAdapter: {
@@ -1054,7 +1078,6 @@ async function startCloudExecution(command, parsed, io) {
1054
1078
  const showProgress = true;
1055
1079
  const interrupt = createCloudInterruptController(command, io, showProgress);
1056
1080
  try {
1057
- writeCloudProgress(io, `workbench cloud: preparing hosted ${command}.`, showProgress);
1058
1081
  const remote = await cloudPreScheduleStep(command, interrupt, ensureCloudRemoteForExecution(root, parsed));
1059
1082
  const source = parseWorkbenchInstallSource(remote.url);
1060
1083
  if (!source) {
@@ -1072,6 +1095,7 @@ async function startCloudExecution(command, parsed, io) {
1072
1095
  });
1073
1096
  }
1074
1097
  const core = { dir: root, authToken: token };
1098
+ writeCloudProgress(io, `workbench cloud: preparing hosted ${command}.`, showProgress);
1075
1099
  writeCloudProgress(io, "workbench cloud: preparing current source.", showProgress);
1076
1100
  const request = command === "eval"
1077
1101
  ? await cloudPreScheduleStep(command, interrupt, prepareWorkbenchCloudEvalRequest({
@@ -1517,6 +1541,16 @@ function cloudSyncSummary(sync) {
1517
1541
  function syncChanged(sync) {
1518
1542
  return sync.pushed > 0 || sync.pulled > 0;
1519
1543
  }
1544
+ async function syncNextCommand(core) {
1545
+ const status = await workbenchStatusSnapshot(core);
1546
+ const auth = await workbenchCliAuthStatus();
1547
+ const cliStatus = await statusWithCausalNext(status, auth, core, {
1548
+ installedSkillCount: 0,
1549
+ stores: [],
1550
+ connectedProviders: [],
1551
+ });
1552
+ return cliStatus.next ?? null;
1553
+ }
1520
1554
  function writeCloudProgress(io, message, enabled = true) {
1521
1555
  if (!enabled) {
1522
1556
  return;
@@ -2638,6 +2672,33 @@ function installHandleFromCloudRemote(remote) {
2638
2672
  }
2639
2673
  return `${source.owner}/${source.skill}`;
2640
2674
  }
2675
+ async function publishErrorWithCliContext(error, parsed, remoteName) {
2676
+ if (!(error instanceof WorkbenchCodedError) || error.code !== "auth_required") {
2677
+ return error;
2678
+ }
2679
+ if (error.message.startsWith("workbench publish")) {
2680
+ return error;
2681
+ }
2682
+ return new WorkbenchCodedError("auth_required", "workbench publish requires Workbench Cloud auth.", {
2683
+ remediation: await publishAuthRemediation(parsed, remoteName, error.remediation),
2684
+ ...(error.subject ? { subject: error.subject } : {}),
2685
+ exitCode: error.exitCode,
2686
+ });
2687
+ }
2688
+ async function publishAuthRemediation(parsed, remoteName, fallback) {
2689
+ const root = path.resolve(dirFlag(parsed) ?? process.cwd());
2690
+ try {
2691
+ const snapshot = await createWorkbenchReadOnlyInspectionSnapshot({ dir: root });
2692
+ const remote = remoteName
2693
+ ? snapshot.remotes.find((entry) => entry.name === remoteName)
2694
+ : cloudRemoteLinkTargetFromRemotes(snapshot.remotes).existing;
2695
+ const source = remote ? parseWorkbenchInstallSource(remote.url) : undefined;
2696
+ return workbenchLoginRemediation(source?.baseUrl);
2697
+ }
2698
+ catch {
2699
+ return fallback ?? "Run workbench login.";
2700
+ }
2701
+ }
2641
2702
  function parseOwnerSkillHandle(input) {
2642
2703
  const handle = normalizedOwnerSkillHandle(input);
2643
2704
  if (!handle) {
@@ -2707,6 +2768,33 @@ function parseWithFlags(parsed) {
2707
2768
  return [entry.slice(0, eq), parseScalar(entry.slice(eq + 1))];
2708
2769
  }));
2709
2770
  }
2771
+ function validateAgentCommandConfig(config) {
2772
+ for (const key of ["command", "improveCommand"]) {
2773
+ const value = config[key];
2774
+ if (typeof value !== "string") {
2775
+ continue;
2776
+ }
2777
+ const expanded = expandedRuntimeEnvPath(value);
2778
+ if (!expanded) {
2779
+ continue;
2780
+ }
2781
+ throw new WorkbenchCodedError("usage", `--with ${key}=... contains ${expanded.path}, which usually means the shell expanded a Workbench runtime variable before Workbench received it.`, {
2782
+ remediation: `Wrap the assignment in single quotes, for example --with '${key}=... >> "${expanded.replacement}"'.`,
2783
+ exitCode: 2,
2784
+ });
2785
+ }
2786
+ }
2787
+ function expandedRuntimeEnvPath(value) {
2788
+ for (const entry of [
2789
+ { path: "/SKILL.md", replacement: "$SKILL_DIR/SKILL.md", pattern: /(^|[\s"'=])\/SKILL\.md(?=$|[\s"'])/u },
2790
+ { path: "/result.json", replacement: "$OUTPUT_DIR/result.json", pattern: /(^|[\s"'=])\/result\.json(?=$|[\s"'])/u },
2791
+ ]) {
2792
+ if (entry.pattern.test(value)) {
2793
+ return entry;
2794
+ }
2795
+ }
2796
+ return null;
2797
+ }
2710
2798
  function parseScalar(value) {
2711
2799
  if (value === "true") {
2712
2800
  return true;
@@ -3658,7 +3746,7 @@ function formatTraceDetail(detail, refs = {}) {
3658
3746
  return detail.executions.map((execution) => {
3659
3747
  const sessionLabels = execution.sessions.map((session) => session.label).join(",");
3660
3748
  return [
3661
- `${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}`,
3749
+ `${formatExecutionEvidenceLabel(detail, execution)}\trun=${refs.runRefs?.get(detail.runId) ?? displayRef(detail.runId)}\tjobs=${execution.jobIds.map((id) => refs.jobRefs?.get(id) ?? displayRef(id)).join(",")}\tstatus=${execution.status}`,
3662
3750
  `events=${execution.trace.events.length}`,
3663
3751
  `spans=${execution.trace.spans.length}`,
3664
3752
  `summaries=${execution.trace.summaries.length}`,
@@ -3666,6 +3754,11 @@ function formatTraceDetail(detail, refs = {}) {
3666
3754
  ].filter(Boolean).join("\t");
3667
3755
  }).join("\n");
3668
3756
  }
3757
+ function formatExecutionEvidenceLabel(detail, execution) {
3758
+ return execution.jobIds.length === 1 && execution.id === `job:${detail.runId}:${execution.jobIds[0]}`
3759
+ ? "evidence"
3760
+ : execution.id;
3761
+ }
3669
3762
  function formatArtifact(artifact) {
3670
3763
  return `${displayRef(artifact.id)}\trun=${displayRef(artifact.runId)}\tjob=${displayRef(artifact.jobId)}\t${artifact.kind}\tfiles=${artifact.files.length}`;
3671
3764
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@workbench-ai/workbench",
3
- "version": "0.0.87",
3
+ "version": "0.0.89",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/workbench-ai/workbench.git",
@@ -21,10 +21,10 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "yaml": "^2.8.2",
24
- "@workbench-ai/workbench-built-in-adapters": "0.0.87",
25
- "@workbench-ai/workbench-contract": "0.0.87",
26
- "@workbench-ai/workbench-protocol": "0.0.87",
27
- "@workbench-ai/workbench-core": "0.0.87"
24
+ "@workbench-ai/workbench-built-in-adapters": "0.0.89",
25
+ "@workbench-ai/workbench-core": "0.0.89",
26
+ "@workbench-ai/workbench-contract": "0.0.89",
27
+ "@workbench-ai/workbench-protocol": "0.0.89"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@tailwindcss/postcss": "^4.2.2",
@@ -35,7 +35,7 @@
35
35
  "react-dom": "^19.2.0",
36
36
  "typescript": "^5.9.2",
37
37
  "vitest": "^3.2.4",
38
- "@workbench-ai/workbench-ui": "0.0.87"
38
+ "@workbench-ai/workbench-ui": "0.0.89"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "rm -rf dist && tsc -p tsconfig.json && chmod 755 dist/workbench.js && node ./scripts/build-dev-open-assets.mjs",