@workbench-ai/workbench 0.0.97 → 0.0.99
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.js +51 -25
- package/dist/install-targets.js +2 -2
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1850,6 +1850,9 @@ async function requestDeviceAuthorization(baseUrl) {
|
|
|
1850
1850
|
});
|
|
1851
1851
|
}
|
|
1852
1852
|
if (!response.ok) {
|
|
1853
|
+
if (isRetryableHttpStatus(response.status)) {
|
|
1854
|
+
throw deviceLoginUnavailableError("start", response.status, response.statusText, text);
|
|
1855
|
+
}
|
|
1853
1856
|
const excerpt = readResponseError(text);
|
|
1854
1857
|
throw new WorkbenchCodedError("login_denied", `Device login failed: ${response.status}${excerpt ? ` ${excerpt}` : response.statusText ? ` ${response.statusText}` : ""}`, {
|
|
1855
1858
|
exitCode: 1,
|
|
@@ -1889,6 +1892,9 @@ async function pollDeviceToken(baseUrl, authorization, timeoutSeconds) {
|
|
|
1889
1892
|
if (response.ok) {
|
|
1890
1893
|
return JSON.parse(text);
|
|
1891
1894
|
}
|
|
1895
|
+
if (isRetryableHttpStatus(response.status)) {
|
|
1896
|
+
throw deviceLoginUnavailableError("wait", response.status, response.statusText, text);
|
|
1897
|
+
}
|
|
1892
1898
|
const error = readResponseError(text) ?? "authorization_pending";
|
|
1893
1899
|
if (error === "slow_down") {
|
|
1894
1900
|
intervalMs += 5000;
|
|
@@ -1913,6 +1919,18 @@ async function pollDeviceToken(baseUrl, authorization, timeoutSeconds) {
|
|
|
1913
1919
|
exitCode: 1,
|
|
1914
1920
|
});
|
|
1915
1921
|
}
|
|
1922
|
+
function deviceLoginUnavailableError(phase, status, statusText, text) {
|
|
1923
|
+
const excerpt = readResponseError(text);
|
|
1924
|
+
const detail = `${status}${excerpt ? ` ${excerpt}` : statusText ? ` ${statusText}` : ""}`;
|
|
1925
|
+
const command = phase === "start"
|
|
1926
|
+
? "workbench login --start-only --no-open"
|
|
1927
|
+
: `workbench login --wait --timeout ${LOGIN_WAIT_TIMEOUT_SECONDS}`;
|
|
1928
|
+
return new WorkbenchCodedError("service_unavailable", `Workbench Cloud login is temporarily unavailable: ${detail}`, {
|
|
1929
|
+
retryable: true,
|
|
1930
|
+
remediation: `Retry ${command}.`,
|
|
1931
|
+
exitCode: 1,
|
|
1932
|
+
});
|
|
1933
|
+
}
|
|
1916
1934
|
async function fetchWorkbenchUsername(baseUrl, accessToken) {
|
|
1917
1935
|
const response = await fetch(`${baseUrl}/api/workbench/profile`, {
|
|
1918
1936
|
headers: { authorization: `Bearer ${accessToken}` },
|
|
@@ -2150,7 +2168,10 @@ function isTransientFetchError(error) {
|
|
|
2150
2168
|
return /(?:fetch failed|socket hang up|ECONNRESET|EPIPE|UND_ERR_SOCKET|terminated)/iu.test(errorMessage(error));
|
|
2151
2169
|
}
|
|
2152
2170
|
function isTransientApiRequestError(error) {
|
|
2153
|
-
return error instanceof WorkbenchApiRequestError && (error.status
|
|
2171
|
+
return error instanceof WorkbenchApiRequestError && isRetryableHttpStatus(error.status);
|
|
2172
|
+
}
|
|
2173
|
+
function isRetryableHttpStatus(status) {
|
|
2174
|
+
return status === 429 || status >= 500;
|
|
2154
2175
|
}
|
|
2155
2176
|
function isIdempotentApiRequestMethod(method) {
|
|
2156
2177
|
return method === "GET" || method === "PUT" || method === "DELETE";
|
|
@@ -2246,21 +2267,10 @@ async function collectAdapterAuthBundle(args) {
|
|
|
2246
2267
|
});
|
|
2247
2268
|
}
|
|
2248
2269
|
if (args.method === "oauth") {
|
|
2249
|
-
const profile = await requiredAuthFile(args.profileRoot, ".claude.json", {
|
|
2250
|
-
provider: "Claude auth",
|
|
2251
|
-
remediation: "claude setup-token && workbench login claude --method oauth",
|
|
2252
|
-
});
|
|
2253
|
-
const portableToken = await requiredAnyAuthFile(args.profileRoot, [
|
|
2254
|
-
".claude/oauth-token",
|
|
2255
|
-
".claude/.credentials.json",
|
|
2256
|
-
], {
|
|
2257
|
-
provider: "Claude portable OAuth token",
|
|
2258
|
-
remediation: "claude setup-token && workbench login claude --method oauth",
|
|
2259
|
-
});
|
|
2260
2270
|
return createWorkbenchAdapterAuthBundle({
|
|
2261
2271
|
target: args.target,
|
|
2262
2272
|
method: args.method,
|
|
2263
|
-
files:
|
|
2273
|
+
files: await collectClaudeOAuthFiles(args.profileRoot),
|
|
2264
2274
|
});
|
|
2265
2275
|
}
|
|
2266
2276
|
if (args.method === "bedrock") {
|
|
@@ -2309,15 +2319,25 @@ async function requiredAuthFile(root, relativePath, guidance) {
|
|
|
2309
2319
|
}
|
|
2310
2320
|
return file;
|
|
2311
2321
|
}
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2322
|
+
const CLAUDE_OAUTH_PROFILE_PATH = ".claude.json";
|
|
2323
|
+
const CLAUDE_OAUTH_TOKEN_PATHS = [".claude/oauth-token", ".claude/.credentials.json"];
|
|
2324
|
+
const CLAUDE_OAUTH_REMEDIATION = "claude setup-token && workbench login claude --method oauth";
|
|
2325
|
+
async function collectClaudeOAuthFiles(root) {
|
|
2326
|
+
const [profile] = await optionalAuthFiles(root, [CLAUDE_OAUTH_PROFILE_PATH]);
|
|
2327
|
+
const [portableToken] = await optionalAuthFiles(root, CLAUDE_OAUTH_TOKEN_PATHS);
|
|
2328
|
+
if (profile && portableToken) {
|
|
2329
|
+
return [profile, portableToken];
|
|
2330
|
+
}
|
|
2331
|
+
const missingRelativePaths = [
|
|
2332
|
+
...(!profile ? [CLAUDE_OAUTH_PROFILE_PATH] : []),
|
|
2333
|
+
...(!portableToken ? [...CLAUDE_OAUTH_TOKEN_PATHS] : []),
|
|
2334
|
+
];
|
|
2335
|
+
throw new WorkbenchCodedError("provider_oauth_missing", "Claude OAuth capture requires Claude Code's profile and portable OAuth token.", {
|
|
2336
|
+
remediation: CLAUDE_OAUTH_REMEDIATION,
|
|
2337
|
+
subject: {
|
|
2338
|
+
paths: missingRelativePaths.map((entry) => path.join(root, entry)),
|
|
2339
|
+
relativePaths: missingRelativePaths,
|
|
2340
|
+
},
|
|
2321
2341
|
exitCode: 2,
|
|
2322
2342
|
});
|
|
2323
2343
|
}
|
|
@@ -3026,6 +3046,7 @@ async function statusWithCausalNext(status, auth, core, machine) {
|
|
|
3026
3046
|
};
|
|
3027
3047
|
}
|
|
3028
3048
|
const snapshot = await createWorkbenchReadOnlyInspectionSnapshot(core).catch(() => null);
|
|
3049
|
+
const currentVersionId = status.project.currentVersionId ?? snapshot?.status.currentVersionId ?? snapshot?.refs.current;
|
|
3029
3050
|
const lastRun = snapshot?.runs
|
|
3030
3051
|
.slice()
|
|
3031
3052
|
.sort((left, right) => right.createdAt.localeCompare(left.createdAt))[0];
|
|
@@ -3034,8 +3055,11 @@ async function statusWithCausalNext(status, auth, core, machine) {
|
|
|
3034
3055
|
}
|
|
3035
3056
|
const failedRemote = status.remotes.find((remote) => remote.sync.status === "error");
|
|
3036
3057
|
const hasWorkflowCase = snapshot ? snapshotHasWorkflowCase(snapshot) : false;
|
|
3037
|
-
const
|
|
3038
|
-
|
|
3058
|
+
const hasCurrentScoredProofRun = snapshot?.runs.some((run) => currentVersionId !== undefined &&
|
|
3059
|
+
scoredRunValue(run) !== undefined &&
|
|
3060
|
+
((run.kind === "eval" && run.versionId === currentVersionId) ||
|
|
3061
|
+
(run.kind === "improve" && run.outputVersionId === currentVersionId))) ?? false;
|
|
3062
|
+
const canPublish = hasWorkflowCase && hasCurrentScoredProofRun;
|
|
3039
3063
|
const cloudAuthMissing = auth.workbenchCloud.status !== "authenticated";
|
|
3040
3064
|
const cloudRemoteNeedsAuth = status.remotes.some((remote) => remote.kind === "workbench-cloud" &&
|
|
3041
3065
|
(remote.sync.status !== "up_to_date" || remote.publication.status === "unpublished"));
|
|
@@ -3051,6 +3075,9 @@ async function statusWithCausalNext(status, auth, core, machine) {
|
|
|
3051
3075
|
if (!hasWorkflowCase) {
|
|
3052
3076
|
return { ...status, next: "edit .workbench/cases, then run workbench eval" };
|
|
3053
3077
|
}
|
|
3078
|
+
if (!hasCurrentScoredProofRun) {
|
|
3079
|
+
return { ...status, next: "workbench eval" };
|
|
3080
|
+
}
|
|
3054
3081
|
const cloudRemote = status.remotes.find((remote) => remote.kind === "workbench-cloud");
|
|
3055
3082
|
if (canPublish && !cloudRemote) {
|
|
3056
3083
|
return { ...status, next: "workbench publish" };
|
|
@@ -3061,7 +3088,6 @@ async function statusWithCausalNext(status, auth, core, machine) {
|
|
|
3061
3088
|
if (unpublishedCloudRemote) {
|
|
3062
3089
|
return { ...status, next: "workbench publish" };
|
|
3063
3090
|
}
|
|
3064
|
-
const currentVersionId = status.project.currentVersionId ?? snapshot?.status.currentVersionId ?? snapshot?.refs.current;
|
|
3065
3091
|
const stalePublishedCloudRemote = status.remotes.find((remote) => remote.kind === "workbench-cloud" &&
|
|
3066
3092
|
remote.publication.status === "published" &&
|
|
3067
3093
|
remote.sync.status === "up_to_date" &&
|
package/dist/install-targets.js
CHANGED
|
@@ -45,7 +45,7 @@ export async function installSnapshotToStore(options) {
|
|
|
45
45
|
const previous = existingHash
|
|
46
46
|
? existingHash === contentHash ? "unchanged" : canUpdateExisting ? "updated" : "overwritten"
|
|
47
47
|
: "none";
|
|
48
|
-
if (existingHash && previous === "overwritten" && !options.overwrite) {
|
|
48
|
+
if (!options.dryRun && existingHash && previous === "overwritten" && !options.overwrite) {
|
|
49
49
|
throw new WorkbenchCodedError("install_failed", `Canonical skill already exists: ${destination}`, {
|
|
50
50
|
remediation: "Pass --yes to overwrite the existing canonical store skill.",
|
|
51
51
|
subject: { destination },
|
|
@@ -103,7 +103,7 @@ export async function readInstalledSkillsInventory(options = {}) {
|
|
|
103
103
|
return {
|
|
104
104
|
stores,
|
|
105
105
|
skills,
|
|
106
|
-
next: next ? `workbench install ${next}` :
|
|
106
|
+
next: next ? `workbench install ${next}` : null,
|
|
107
107
|
};
|
|
108
108
|
}
|
|
109
109
|
export function installedInventoryToJson(inventory) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@workbench-ai/workbench",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.99",
|
|
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-
|
|
25
|
-
"@workbench-ai/workbench-protocol": "0.0.
|
|
26
|
-
"@workbench-ai/workbench-
|
|
27
|
-
"@workbench-ai/workbench-contract": "0.0.
|
|
24
|
+
"@workbench-ai/workbench-built-in-adapters": "0.0.99",
|
|
25
|
+
"@workbench-ai/workbench-protocol": "0.0.99",
|
|
26
|
+
"@workbench-ai/workbench-core": "0.0.99",
|
|
27
|
+
"@workbench-ai/workbench-contract": "0.0.99"
|
|
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.
|
|
38
|
+
"@workbench-ai/workbench-ui": "0.0.99"
|
|
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",
|