@cortexkit/opencode-claustrum-auth 0.1.1 → 0.1.2

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 CHANGED
@@ -94,6 +94,26 @@ function transitionActivation(previous, event) {
94
94
  }
95
95
  return result;
96
96
  }
97
+ // ../core/src/balance.ts
98
+ var balanceProbeMs = 5 * 60 * 1000;
99
+ function isBalanceFailure(service, body) {
100
+ if (service === "deepseek")
101
+ return true;
102
+ if (service !== "openrouter")
103
+ return false;
104
+ try {
105
+ const value = JSON.parse(body ?? "");
106
+ if (typeof value !== "object" || value === null || !("error" in value))
107
+ return false;
108
+ const error = value.error;
109
+ if (typeof error !== "object" || error === null || !("metadata" in error))
110
+ return false;
111
+ const metadata = error.metadata;
112
+ return typeof metadata === "object" && metadata !== null && "limit_source" in metadata && metadata.limit_source === "openrouter_credits" && (!("reason" in metadata) || metadata.reason !== "weight_exceeds_budget");
113
+ } catch {
114
+ return false;
115
+ }
116
+ }
97
117
  // ../../node_modules/.bun/@cortexkit+common-auth@0.29.1+e881539e648aba62/node_modules/@cortexkit/common-auth/dist/redaction/index.js
98
118
  import { types } from "node:util";
99
119
 
@@ -1076,7 +1096,7 @@ function retryExpiry(response, now) {
1076
1096
  if (Number.isFinite(date) && date > now)
1077
1097
  return date;
1078
1098
  }
1079
- return now + 60000;
1099
+ return now + (response.status === 402 ? balanceProbeMs : 60000);
1080
1100
  }
1081
1101
  function limited(marks, now) {
1082
1102
  const expiries = [...marks.values()].filter((expiry) => expiry > now);
@@ -1109,6 +1129,7 @@ function createFetch(options) {
1109
1129
  const tried = new Set;
1110
1130
  const secrets = [];
1111
1131
  let saw429 = false;
1132
+ let saw402 = false;
1112
1133
  try {
1113
1134
  for (;; ) {
1114
1135
  signal.throwIfAborted();
@@ -1119,6 +1140,7 @@ function createFetch(options) {
1119
1140
  throw new ClaustrumAuthError("no-vault-account");
1120
1141
  }
1121
1142
  tried.add(route);
1143
+ const previousMark = rateLimitMarks.get(route);
1122
1144
  let target = url;
1123
1145
  let method = template.method;
1124
1146
  let bytes = body;
@@ -1168,11 +1190,26 @@ function createFetch(options) {
1168
1190
  }
1169
1191
  target = next;
1170
1192
  }
1171
- if (response.status !== 429 && response.status !== 401)
1193
+ let balance402 = false;
1194
+ if (response.status === 402) {
1195
+ let text;
1196
+ if (options.entry.service === "openrouter") {
1197
+ try {
1198
+ text = await response.clone().text();
1199
+ } catch {}
1200
+ }
1201
+ balance402 = isBalanceFailure(options.entry.service, text);
1202
+ }
1203
+ if ((response.ok || response.status === 402 && !balance402) && previousMark !== undefined && previousMark <= now() && rateLimitMarks.get(route) === previousMark)
1204
+ rateLimitMarks.delete(route);
1205
+ if (response.status !== 401 && response.status !== 429 && !balance402)
1172
1206
  return await redactResponse(response, secrets);
1173
1207
  signal.throwIfAborted();
1174
- if (response.status === 429) {
1175
- saw429 = true;
1208
+ if (response.status === 429 || balance402) {
1209
+ if (response.status === 429)
1210
+ saw429 = true;
1211
+ else
1212
+ saw402 = true;
1176
1213
  rateLimitMarks.set(route, retryExpiry(response, now()));
1177
1214
  }
1178
1215
  const next = orderedRoutes(routing, tried)[0];
@@ -1180,7 +1217,7 @@ function createFetch(options) {
1180
1217
  await response.body?.cancel().catch(() => {});
1181
1218
  continue;
1182
1219
  }
1183
- if (response.status === 401 && saw429) {
1220
+ if (saw429 && (response.status === 401 || saw402)) {
1184
1221
  await response.body?.cancel().catch(() => {});
1185
1222
  return limited(rateLimitMarks, now());
1186
1223
  }
@@ -7185,6 +7222,13 @@ var supportedProviders = [
7185
7222
  class: "A",
7186
7223
  origins: ["https://api.kimi.com", "https://api.kimi.ai"]
7187
7224
  },
7225
+ {
7226
+ service: "minimax-coding-plan",
7227
+ ids: ["minimax-coding-plan"],
7228
+ hosts: { opencode2: "minimax-coding-plan" },
7229
+ class: "A",
7230
+ origins: ["https://api.minimax.io"]
7231
+ },
7188
7232
  {
7189
7233
  service: "openrouter",
7190
7234
  ids: ["openrouter"],
@@ -7196,6 +7240,13 @@ var supportedProviders = [
7196
7240
  class: "A",
7197
7241
  origins: ["https://openrouter.ai"]
7198
7242
  },
7243
+ {
7244
+ service: "synthetic",
7245
+ ids: ["synthetic"],
7246
+ hosts: { opencode1: "synthetic", opencode2: "synthetic" },
7247
+ class: "A",
7248
+ origins: ["https://api.synthetic.new"]
7249
+ },
7199
7250
  {
7200
7251
  service: "typesafe",
7201
7252
  ids: ["typesafe"],
package/dist/server.js CHANGED
@@ -94,6 +94,26 @@ function transitionActivation(previous, event) {
94
94
  }
95
95
  return result;
96
96
  }
97
+ // ../core/src/balance.ts
98
+ var balanceProbeMs = 5 * 60 * 1000;
99
+ function isBalanceFailure(service, body) {
100
+ if (service === "deepseek")
101
+ return true;
102
+ if (service !== "openrouter")
103
+ return false;
104
+ try {
105
+ const value = JSON.parse(body ?? "");
106
+ if (typeof value !== "object" || value === null || !("error" in value))
107
+ return false;
108
+ const error = value.error;
109
+ if (typeof error !== "object" || error === null || !("metadata" in error))
110
+ return false;
111
+ const metadata = error.metadata;
112
+ return typeof metadata === "object" && metadata !== null && "limit_source" in metadata && metadata.limit_source === "openrouter_credits" && (!("reason" in metadata) || metadata.reason !== "weight_exceeds_budget");
113
+ } catch {
114
+ return false;
115
+ }
116
+ }
97
117
  // ../../node_modules/.bun/@cortexkit+common-auth@0.29.1+e881539e648aba62/node_modules/@cortexkit/common-auth/dist/redaction/index.js
98
118
  import { types } from "node:util";
99
119
 
@@ -1110,7 +1130,7 @@ function retryExpiry(response, now) {
1110
1130
  if (Number.isFinite(date) && date > now)
1111
1131
  return date;
1112
1132
  }
1113
- return now + 60000;
1133
+ return now + (response.status === 402 ? balanceProbeMs : 60000);
1114
1134
  }
1115
1135
  function limited(marks, now) {
1116
1136
  const expiries = [...marks.values()].filter((expiry) => expiry > now);
@@ -1143,6 +1163,7 @@ function createFetch(options) {
1143
1163
  const tried = new Set;
1144
1164
  const secrets = [];
1145
1165
  let saw429 = false;
1166
+ let saw402 = false;
1146
1167
  try {
1147
1168
  for (;; ) {
1148
1169
  signal.throwIfAborted();
@@ -1153,6 +1174,7 @@ function createFetch(options) {
1153
1174
  throw new ClaustrumAuthError("no-vault-account");
1154
1175
  }
1155
1176
  tried.add(route);
1177
+ const previousMark = rateLimitMarks.get(route);
1156
1178
  let target = url;
1157
1179
  let method = template.method;
1158
1180
  let bytes = body;
@@ -1202,11 +1224,26 @@ function createFetch(options) {
1202
1224
  }
1203
1225
  target = next;
1204
1226
  }
1205
- if (response.status !== 429 && response.status !== 401)
1227
+ let balance402 = false;
1228
+ if (response.status === 402) {
1229
+ let text;
1230
+ if (options.entry.service === "openrouter") {
1231
+ try {
1232
+ text = await response.clone().text();
1233
+ } catch {}
1234
+ }
1235
+ balance402 = isBalanceFailure(options.entry.service, text);
1236
+ }
1237
+ if ((response.ok || response.status === 402 && !balance402) && previousMark !== undefined && previousMark <= now() && rateLimitMarks.get(route) === previousMark)
1238
+ rateLimitMarks.delete(route);
1239
+ if (response.status !== 401 && response.status !== 429 && !balance402)
1206
1240
  return await redactResponse(response, secrets);
1207
1241
  signal.throwIfAborted();
1208
- if (response.status === 429) {
1209
- saw429 = true;
1242
+ if (response.status === 429 || balance402) {
1243
+ if (response.status === 429)
1244
+ saw429 = true;
1245
+ else
1246
+ saw402 = true;
1210
1247
  rateLimitMarks.set(route, retryExpiry(response, now()));
1211
1248
  }
1212
1249
  const next = orderedRoutes(routing, tried)[0];
@@ -1214,7 +1251,7 @@ function createFetch(options) {
1214
1251
  await response.body?.cancel().catch(() => {});
1215
1252
  continue;
1216
1253
  }
1217
- if (response.status === 401 && saw429) {
1254
+ if (saw429 && (response.status === 401 || saw402)) {
1218
1255
  await response.body?.cancel().catch(() => {});
1219
1256
  return limited(rateLimitMarks, now());
1220
1257
  }
@@ -7219,6 +7256,13 @@ var supportedProviders = [
7219
7256
  class: "A",
7220
7257
  origins: ["https://api.kimi.com", "https://api.kimi.ai"]
7221
7258
  },
7259
+ {
7260
+ service: "minimax-coding-plan",
7261
+ ids: ["minimax-coding-plan"],
7262
+ hosts: { opencode2: "minimax-coding-plan" },
7263
+ class: "A",
7264
+ origins: ["https://api.minimax.io"]
7265
+ },
7222
7266
  {
7223
7267
  service: "openrouter",
7224
7268
  ids: ["openrouter"],
@@ -7230,6 +7274,13 @@ var supportedProviders = [
7230
7274
  class: "A",
7231
7275
  origins: ["https://openrouter.ai"]
7232
7276
  },
7277
+ {
7278
+ service: "synthetic",
7279
+ ids: ["synthetic"],
7280
+ hosts: { opencode1: "synthetic", opencode2: "synthetic" },
7281
+ class: "A",
7282
+ origins: ["https://api.synthetic.new"]
7283
+ },
7233
7284
  {
7234
7285
  service: "typesafe",
7235
7286
  ids: ["typesafe"],
@@ -9354,34 +9405,32 @@ function frameCode(event) {
9354
9405
  const code = event.code ?? nested?.code ?? nested?.type;
9355
9406
  return typeof code === "string" ? code : undefined;
9356
9407
  }
9357
- function inspectResponsesFrame(data, attempt) {
9408
+ function inspectResponsesFrame(data, attempt, service) {
9358
9409
  let event;
9359
9410
  try {
9360
9411
  event = JSON.parse(data);
9361
9412
  } catch {
9362
- return;
9413
+ return { outputStarted: true };
9363
9414
  }
9364
9415
  if (!isRecord6(event))
9365
- return;
9416
+ return { outputStarted: true };
9366
9417
  const type = typeof event.type === "string" ? event.type : event.error != null ? "error" : undefined;
9367
- if (type === undefined)
9418
+ if (type === "response.created" || type === "response.in_progress" || type?.startsWith("codex."))
9368
9419
  return;
9369
9420
  if (type === "response.completed" || type === "response.incomplete")
9370
- return { done: true };
9421
+ return { done: true, outputStarted: true };
9371
9422
  if (type === "error" || type === "response.failed") {
9372
9423
  const status = frameStatus(event);
9373
9424
  if (attempt && status !== undefined)
9374
9425
  attempt.frameStatus = status;
9375
9426
  const code = frameCode(event);
9376
- const limited = status === 429 || code !== undefined && /rate.?limit/iu.test(code);
9427
+ const limited = status !== 402 && (status === 429 || code !== undefined && /rate.?limit/iu.test(code));
9377
9428
  return {
9378
9429
  error: "the provider answered with an error frame",
9379
- ...limited ? { limit: { reason: "rate-limit", status: status ?? 429 } } : {}
9430
+ ...status === 402 && isBalanceFailure(service, data) ? { limit: { reason: "payment-required", status } } : limited ? { limit: { reason: "rate-limit", status: status ?? 429 } } : {}
9380
9431
  };
9381
9432
  }
9382
- if (type.startsWith("response.") && type.endsWith(".delta"))
9383
- return { outputStarted: true };
9384
- return;
9433
+ return { outputStarted: true };
9385
9434
  }
9386
9435
  var defaultMarkMs = 60000;
9387
9436
  function retryAfterMs(headers, now) {
@@ -9395,7 +9444,7 @@ function retryAfterMs(headers, now) {
9395
9444
  return Number.isFinite(date) && date > now ? date - now : undefined;
9396
9445
  }
9397
9446
  function markUntil(limit, now) {
9398
- return now + (limit.retryAfterMs ?? defaultMarkMs);
9447
+ return now + (limit.retryAfterMs ?? (limit.status === 402 ? balanceProbeMs : defaultMarkMs));
9399
9448
  }
9400
9449
  async function rebuild(request, url, headers) {
9401
9450
  const body = request.body === null ? undefined : await request.clone().arrayBuffer();
@@ -9422,7 +9471,7 @@ function createVaultAdapter(options) {
9422
9471
  now,
9423
9472
  rateLimitMarks: marks
9424
9473
  }, tried);
9425
- const inspectEvent = options.entry.handshakeOrigins?.length ? ({ transport, data, attempt }) => transport === "ws" ? inspectResponsesFrame(data, attempt.data) : undefined : undefined;
9474
+ const inspectEvent = options.entry.handshakeOrigins?.length ? ({ transport, data, attempt }) => transport === "ws" ? inspectResponsesFrame(data, attempt.data, options.entry.service) : undefined : undefined;
9426
9475
  const noAccount = async () => {
9427
9476
  let mode;
9428
9477
  try {
@@ -9538,12 +9587,22 @@ function createVaultAdapter(options) {
9538
9587
  return;
9539
9588
  return redactResponse(response, [secret]);
9540
9589
  },
9541
- limitFromResponse({ status, headers }) {
9542
- if (status !== 429)
9590
+ async limitFromResponse({ status, headers, body }) {
9591
+ if (status !== 429 && status !== 402)
9543
9592
  return;
9593
+ if (status === 402) {
9594
+ let text;
9595
+ if (options.entry.service === "openrouter") {
9596
+ try {
9597
+ text = await body();
9598
+ } catch {}
9599
+ }
9600
+ if (!isBalanceFailure(options.entry.service, text))
9601
+ return;
9602
+ }
9544
9603
  const wait = retryAfterMs(headers, now());
9545
9604
  return {
9546
- reason: "rate-limit",
9605
+ reason: status === 402 ? "payment-required" : "rate-limit",
9547
9606
  status,
9548
9607
  ...wait === undefined ? {} : { retryAfterMs: wait }
9549
9608
  };
package/dist/setup-bin.js CHANGED
@@ -7,6 +7,8 @@ import { pathToFileURL } from "node:url";
7
7
  // src/setup.ts
8
8
  import { homedir as homedir2 } from "node:os";
9
9
  import path2 from "node:path";
10
+ // ../core/src/balance.ts
11
+ var balanceProbeMs = 5 * 60 * 1000;
10
12
  // ../../node_modules/.bun/@cortexkit+common-auth@0.29.1+e881539e648aba62/node_modules/@cortexkit/common-auth/dist/logger/redact.js
11
13
  var SECRET_KEY_EXACT = /^(authorization|x-api-key|cookie|set-cookie|refresh|access|token)$/i;
12
14
  var TOKEN_VALUE = /\b(Bearer\s+[\w.-]+|sk-[\w-]+|eyJ[\w.-]+)\b|ckh_[A-Za-z0-9_-]{20,}/g;
@@ -5787,6 +5789,13 @@ var supportedProviders = [
5787
5789
  class: "A",
5788
5790
  origins: ["https://api.kimi.com", "https://api.kimi.ai"]
5789
5791
  },
5792
+ {
5793
+ service: "minimax-coding-plan",
5794
+ ids: ["minimax-coding-plan"],
5795
+ hosts: { opencode2: "minimax-coding-plan" },
5796
+ class: "A",
5797
+ origins: ["https://api.minimax.io"]
5798
+ },
5790
5799
  {
5791
5800
  service: "openrouter",
5792
5801
  ids: ["openrouter"],
@@ -5798,6 +5807,13 @@ var supportedProviders = [
5798
5807
  class: "A",
5799
5808
  origins: ["https://openrouter.ai"]
5800
5809
  },
5810
+ {
5811
+ service: "synthetic",
5812
+ ids: ["synthetic"],
5813
+ hosts: { opencode1: "synthetic", opencode2: "synthetic" },
5814
+ class: "A",
5815
+ origins: ["https://api.synthetic.new"]
5816
+ },
5801
5817
  {
5802
5818
  service: "typesafe",
5803
5819
  ids: ["typesafe"],
@@ -6014,7 +6030,7 @@ import {
6014
6030
  // ../pi/package.json
6015
6031
  var package_default = {
6016
6032
  name: "@cortexkit/pi-claustrum-auth",
6017
- version: "0.1.1",
6033
+ version: "0.1.2",
6018
6034
  description: "Claustrum vault credentials for Pi",
6019
6035
  type: "module",
6020
6036
  license: "MIT",
@@ -6063,7 +6079,7 @@ var package_default = {
6063
6079
  // package.json
6064
6080
  var package_default2 = {
6065
6081
  name: "@cortexkit/opencode-claustrum-auth",
6066
- version: "0.1.1",
6082
+ version: "0.1.2",
6067
6083
  description: "Claustrum vault credentials for OpenCode 1 and OpenCode 2",
6068
6084
  type: "module",
6069
6085
  license: "MIT",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cortexkit/opencode-claustrum-auth",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Claustrum vault credentials for OpenCode 1 and OpenCode 2",
5
5
  "type": "module",
6
6
  "license": "MIT",