theclawbay 0.3.50 → 0.3.51

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.
@@ -970,6 +970,23 @@ function summarizeModelFetchFailure(detail) {
970
970
  return normalized;
971
971
  return `${normalized.slice(0, 137).trimEnd()}...`;
972
972
  }
973
+ function isCredentialRejectedFailure(detail) {
974
+ if (!detail)
975
+ return false;
976
+ const normalized = detail.toLowerCase();
977
+ return (normalized.includes("http 401") ||
978
+ normalized.includes("invalid api key") ||
979
+ normalized.includes("missing bearer token") ||
980
+ normalized.includes("device session not found") ||
981
+ normalized.includes("billing access required"));
982
+ }
983
+ function describeCredentialRejection(authType, failure) {
984
+ const detail = failure?.trim() || "credential rejected by backend";
985
+ if (authType === "device-session") {
986
+ return `The saved device-session credential was rejected by the backend (${detail}). Re-link this machine in the browser or run \`theclawbay logout\` before rerunning setup.`;
987
+ }
988
+ return `The provided API key was rejected by the backend (${detail}). Update the key and rerun setup.`;
989
+ }
973
990
  async function fetchBackendModelIds(backendUrl, apiKey) {
974
991
  const url = `${openAiCompatibleProxyUrl(backendUrl)}/models`;
975
992
  try {
@@ -1194,6 +1211,7 @@ async function resolveModels(backendUrl, apiKey) {
1194
1211
  const available = new Set(ids ?? []);
1195
1212
  let selected = DEFAULT_CODEX_MODEL;
1196
1213
  let note;
1214
+ const authRejected = isCredentialRejectedFailure(failure);
1197
1215
  for (const preferred of PREFERRED_MODELS) {
1198
1216
  if (available.has(preferred)) {
1199
1217
  selected = preferred;
@@ -1224,20 +1242,27 @@ async function resolveModels(backendUrl, apiKey) {
1224
1242
  model: selected,
1225
1243
  models: unique.map((modelId) => ({ id: modelId, name: modelDisplayName(modelId) })),
1226
1244
  note,
1245
+ failure,
1246
+ authRejected,
1227
1247
  };
1228
1248
  }
1229
1249
  async function resolveClaudeAccess(backendUrl, apiKey) {
1230
1250
  const { ids, failure } = await fetchClaudeModelIds(backendUrl, apiKey);
1251
+ const authRejected = isCredentialRejectedFailure(failure);
1231
1252
  if (!ids?.length) {
1232
1253
  return {
1233
1254
  enabled: false,
1234
1255
  models: [],
1235
1256
  note: failure ? `Claude Code auto-setup skipped (${failure}).` : undefined,
1257
+ failure,
1258
+ authRejected,
1236
1259
  };
1237
1260
  }
1238
1261
  return {
1239
1262
  enabled: true,
1240
1263
  models: ids,
1264
+ failure,
1265
+ authRejected,
1241
1266
  };
1242
1267
  }
1243
1268
  async function writeCodexConfig(params) {
@@ -2112,7 +2137,7 @@ class SetupCommand extends base_command_1.BaseCommand {
2112
2137
  if (flags["migrate-conversations"] !== undefined && !selectedSetupClients.has("codex")) {
2113
2138
  throw new Error("--migrate-conversations requires Codex to be selected for setup.");
2114
2139
  }
2115
- if (!authCredential) {
2140
+ const linkFreshDeviceSession = async () => {
2116
2141
  deviceLabel = await resolveDeviceLabel({
2117
2142
  flagValue: flags["device-name"],
2118
2143
  managedValue: managed?.deviceLabel,
@@ -2128,6 +2153,16 @@ class SetupCommand extends base_command_1.BaseCommand {
2128
2153
  authCredential = browserAuth.credential;
2129
2154
  deviceSessionId = browserAuth.deviceSessionId;
2130
2155
  deviceLabel = browserAuth.deviceLabel;
2156
+ };
2157
+ if (!authCredential) {
2158
+ await linkFreshDeviceSession();
2159
+ }
2160
+ else if (!explicitApiKey && managedAuthType === "device-session") {
2161
+ const managedProbe = await fetchBackendModelIds(backendUrl, authCredential);
2162
+ if (isCredentialRejectedFailure(managedProbe.failure)) {
2163
+ this.log(`Saved device-session credential was rejected by the backend (${managedProbe.failure}). Re-linking this machine now.`);
2164
+ await linkFreshDeviceSession();
2165
+ }
2131
2166
  }
2132
2167
  const progress = this.createProgressHandle(!debugOutput);
2133
2168
  let resolved = null;
@@ -2156,9 +2191,15 @@ class SetupCommand extends base_command_1.BaseCommand {
2156
2191
  if (selectedSetupClients.size > 0) {
2157
2192
  progress.update("Resolving supported models");
2158
2193
  resolved = await resolveModels(backendUrl, authCredential);
2194
+ if (resolved.authRejected) {
2195
+ throw new Error(describeCredentialRejection(authType, resolved.failure));
2196
+ }
2159
2197
  }
2160
2198
  progress.update("Checking Claude access");
2161
2199
  claudeAccess = await resolveClaudeAccess(backendUrl, authCredential);
2200
+ if (!resolved?.authRejected && claudeAccess.authRejected) {
2201
+ throw new Error(describeCredentialRejection(authType, claudeAccess.failure));
2202
+ }
2162
2203
  progress.update("Saving shared machine config");
2163
2204
  await (0, config_1.writeManagedConfig)({
2164
2205
  backendUrl,
@@ -2470,6 +2511,7 @@ class SetupCommand extends base_command_1.BaseCommand {
2470
2511
  const openCodeDetected = setupClients.find((client) => client.id === "opencode")?.detected ?? false;
2471
2512
  if (selectedSetupClients.has("opencode")) {
2472
2513
  this.log(`- OpenCode: configured (${openCodeConfigPaths.join(", ")})`);
2514
+ this.log("- OpenCode note: plain OpenAI-compatible config is preferred. If you add a quota/auth plugin manually, use /api/codex-auth/v1/quota?format=legacy_codex for legacy Codex-style quota responses.");
2473
2515
  const openCodeProjectConfig = findOpenCodeProjectConfigFile();
2474
2516
  const openCodeConfigEnv = process.env.OPENCODE_CONFIG?.trim() || "";
2475
2517
  if (openCodeConfigEnv) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "theclawbay",
3
- "version": "0.3.50",
3
+ "version": "0.3.51",
4
4
  "description": "CLI for connecting Codex, Continue, Cline, OpenClaw, OpenCode, Kilo, Roo Code, Aider, experimental Trae, and experimental Zo to The Claw Bay.",
5
5
  "license": "MIT",
6
6
  "bin": {