claudish 14.18.0 → 14.18.1

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.
Files changed (2) hide show
  1. package/dist/index.js +481 -299
  2. package/package.json +5 -5
package/dist/index.js CHANGED
@@ -5494,7 +5494,7 @@ var init_onepassword_config = __esm(() => {
5494
5494
  });
5495
5495
 
5496
5496
  // src/version.ts
5497
- var VERSION = "14.18.0";
5497
+ var VERSION = "14.18.1";
5498
5498
 
5499
5499
  // src/redact.ts
5500
5500
  function isPlaceholder(value) {
@@ -5584,6 +5584,19 @@ function redactExactValues(text, values) {
5584
5584
  }
5585
5585
  return out;
5586
5586
  }
5587
+ function containsExactValue(text, values) {
5588
+ if (!text)
5589
+ return false;
5590
+ for (const value of values) {
5591
+ if (typeof value !== "string" || value.length < SIGNING_VALUE_MIN_LENGTH)
5592
+ continue;
5593
+ for (const form of signingValueForms(value)) {
5594
+ if (text.includes(form))
5595
+ return true;
5596
+ }
5597
+ }
5598
+ return false;
5599
+ }
5587
5600
  function redactForClient(text) {
5588
5601
  return redactSigningValues(text);
5589
5602
  }
@@ -34251,6 +34264,236 @@ var init_harness = __esm(() => {
34251
34264
  SKILL_LINE = /^-\s+([a-z0-9][a-z0-9:_-]*):\s*(.+)$/i;
34252
34265
  });
34253
34266
 
34267
+ // src/handlers/shared/call-context.ts
34268
+ function createSigningSecrets() {
34269
+ return { values: new Set, lease: acquireSigningLease() };
34270
+ }
34271
+ function signingSecretsOf(c) {
34272
+ const installed = readCallVar(c, SIGNING_SECRETS_KEY);
34273
+ if (installed)
34274
+ return installed;
34275
+ const lazy = createSigningSecrets();
34276
+ writeCallVar(c, SIGNING_SECRETS_KEY, lazy);
34277
+ return lazy;
34278
+ }
34279
+ function readCallVar(c, key) {
34280
+ if (!c || typeof c !== "object")
34281
+ return;
34282
+ const store = c;
34283
+ if (typeof store.get === "function")
34284
+ return store.get(key);
34285
+ return detachedCallVars.get(c)?.get(key);
34286
+ }
34287
+ function writeCallVar(c, key, value) {
34288
+ if (!c || typeof c !== "object")
34289
+ return;
34290
+ const store = c;
34291
+ if (typeof store.set === "function") {
34292
+ store.set(key, value);
34293
+ return;
34294
+ }
34295
+ let vars = detachedCallVars.get(c);
34296
+ if (!vars) {
34297
+ vars = new Map;
34298
+ detachedCallVars.set(c, vars);
34299
+ }
34300
+ vars.set(key, value);
34301
+ }
34302
+ function addSigningSecrets(c, values) {
34303
+ const secrets = signingSecretsOf(c);
34304
+ const list = [...values].filter((v) => typeof v === "string" && v.length > 0);
34305
+ for (const value of list)
34306
+ secrets.values.add(value);
34307
+ secrets.lease.add(list);
34308
+ }
34309
+ function isCredentialHeader(name) {
34310
+ const lower = name.toLowerCase();
34311
+ if (CREDENTIAL_HEADER_NAMES.has(lower))
34312
+ return true;
34313
+ return CREDENTIAL_HEADER_FRAGMENTS.some((fragment) => lower.includes(fragment));
34314
+ }
34315
+ function credentialPartsOf(name, value) {
34316
+ const parts = [value];
34317
+ const bare = value.replace(AUTH_SCHEME_PREFIX, "");
34318
+ if (bare !== value)
34319
+ parts.push(bare);
34320
+ if (name.toLowerCase() === "cookie") {
34321
+ for (const pair of value.split(";")) {
34322
+ const eq = pair.indexOf("=");
34323
+ if (eq > 0)
34324
+ parts.push(pair.slice(eq + 1).trim());
34325
+ }
34326
+ }
34327
+ return parts;
34328
+ }
34329
+ function credentialValuesFromRequest(headers, endpoint) {
34330
+ const out = [];
34331
+ for (const [name, value] of Object.entries(headers ?? {})) {
34332
+ if (typeof value !== "string" || !value || !isCredentialHeader(name))
34333
+ continue;
34334
+ out.push(...credentialPartsOf(name, value));
34335
+ }
34336
+ if (endpoint) {
34337
+ try {
34338
+ for (const [name, value] of new URL(endpoint).searchParams) {
34339
+ if (value && CREDENTIAL_QUERY_NAMES.has(name.toLowerCase()))
34340
+ out.push(value);
34341
+ }
34342
+ } catch {}
34343
+ }
34344
+ return out;
34345
+ }
34346
+ function releaseWhenBodyEnds(response, release) {
34347
+ const source = response.body;
34348
+ if (!source) {
34349
+ release();
34350
+ return response;
34351
+ }
34352
+ const reader = source.getReader();
34353
+ let cancelling = false;
34354
+ const stream = new ReadableStream({
34355
+ async pull(controller) {
34356
+ let result;
34357
+ try {
34358
+ result = await reader.read();
34359
+ } catch (err) {
34360
+ if (cancelling)
34361
+ return;
34362
+ release();
34363
+ controller.error(err);
34364
+ return;
34365
+ }
34366
+ if (cancelling)
34367
+ return;
34368
+ if (result.done) {
34369
+ release();
34370
+ controller.close();
34371
+ return;
34372
+ }
34373
+ controller.enqueue(result.value);
34374
+ },
34375
+ async cancel(reason) {
34376
+ cancelling = true;
34377
+ try {
34378
+ await reader.cancel(reason);
34379
+ } catch {} finally {
34380
+ release();
34381
+ }
34382
+ }
34383
+ }, { highWaterMark: 0 });
34384
+ return new Response(stream, {
34385
+ status: response.status,
34386
+ statusText: response.statusText,
34387
+ headers: response.headers
34388
+ });
34389
+ }
34390
+ function callAbortSignal(c) {
34391
+ return readCallVar(c, CALL_ABORT_SIGNAL_KEY);
34392
+ }
34393
+ function callAborted(c) {
34394
+ return callAbortSignal(c)?.aborted === true;
34395
+ }
34396
+ function callAbortError() {
34397
+ return new DOMException("the call's deadline passed; claudish stopped its work", "AbortError");
34398
+ }
34399
+ function raceCallAbort(p, signal) {
34400
+ if (!signal)
34401
+ return p;
34402
+ p.catch(() => {});
34403
+ if (signal.aborted)
34404
+ return Promise.reject(callAbortError());
34405
+ return new Promise((resolve, reject) => {
34406
+ const onAbort = () => reject(callAbortError());
34407
+ signal.addEventListener("abort", onAbort, { once: true });
34408
+ p.then((value) => {
34409
+ signal.removeEventListener("abort", onAbort);
34410
+ resolve(value);
34411
+ }, (err) => {
34412
+ signal.removeEventListener("abort", onAbort);
34413
+ reject(err);
34414
+ });
34415
+ });
34416
+ }
34417
+ function sleepUnlessAborted(ms, signal) {
34418
+ if (signal?.aborted)
34419
+ return Promise.resolve(true);
34420
+ return new Promise((resolve) => {
34421
+ const onAbort = () => {
34422
+ clearTimeout(timer);
34423
+ resolve(true);
34424
+ };
34425
+ const timer = setTimeout(() => {
34426
+ signal?.removeEventListener("abort", onAbort);
34427
+ resolve(false);
34428
+ }, ms);
34429
+ signal?.addEventListener("abort", onAbort, { once: true });
34430
+ });
34431
+ }
34432
+ function withCallSignal(sig, callSignal) {
34433
+ if (!callSignal)
34434
+ return sig;
34435
+ if (!sig)
34436
+ return callSignal;
34437
+ return AbortSignal.any([sig, callSignal]);
34438
+ }
34439
+ function abortedResponse() {
34440
+ return new Response(JSON.stringify({
34441
+ type: "error",
34442
+ error: {
34443
+ type: "timeout_error",
34444
+ message: "claudish stopped this call: its deadline passed"
34445
+ }
34446
+ }), {
34447
+ status: 408,
34448
+ headers: { "content-type": "application/json", [CALL_ABORTED_HEADER]: "1" }
34449
+ });
34450
+ }
34451
+ function hopLogOf(c) {
34452
+ return readCallVar(c, HOP_LOG_KEY);
34453
+ }
34454
+ function recordHopEntry(c, provider, wireModel) {
34455
+ const hops = hopLogOf(c);
34456
+ if (!hops)
34457
+ return;
34458
+ const plannedUid = readCallVar(c, PLANNED_HOP_KEY);
34459
+ const entry = {
34460
+ provider,
34461
+ wireModel,
34462
+ arm: null,
34463
+ billing: null,
34464
+ ...plannedUid ? { plannedUid } : {}
34465
+ };
34466
+ hops.push(entry);
34467
+ return entry;
34468
+ }
34469
+ async function withPlannedHop(c, plannedUid, work) {
34470
+ if (!hopLogOf(c))
34471
+ return work();
34472
+ const previous = readCallVar(c, PLANNED_HOP_KEY);
34473
+ writeCallVar(c, PLANNED_HOP_KEY, plannedUid);
34474
+ try {
34475
+ return await work();
34476
+ } finally {
34477
+ writeCallVar(c, PLANNED_HOP_KEY, previous);
34478
+ }
34479
+ }
34480
+ var SIGNING_SECRETS_KEY = "claudishSigningSecrets", detachedCallVars, CREDENTIAL_HEADER_NAMES, CREDENTIAL_HEADER_FRAGMENTS, CREDENTIAL_QUERY_NAMES, AUTH_SCHEME_PREFIX, CALL_ABORT_SIGNAL_KEY = "claudishCallAbortSignal", CALL_ABORTED_HEADER = "x-claudish-call-aborted", HOP_LOG_KEY = "claudishHopLog", PLANNED_HOP_KEY = "claudishPlannedHop";
34481
+ var init_call_context = __esm(() => {
34482
+ init_redact();
34483
+ detachedCallVars = new WeakMap;
34484
+ CREDENTIAL_HEADER_NAMES = new Set([
34485
+ "authorization",
34486
+ "proxy-authorization",
34487
+ "x-api-key",
34488
+ "api-key",
34489
+ "x-goog-api-key",
34490
+ "cookie"
34491
+ ]);
34492
+ CREDENTIAL_HEADER_FRAGMENTS = ["token", "secret", "key"];
34493
+ CREDENTIAL_QUERY_NAMES = new Set(["key", "api_key", "token", "access_token"]);
34494
+ AUTH_SCHEME_PREFIX = /^(?:Bearer|Basic|Token)\s+/i;
34495
+ });
34496
+
34254
34497
  // src/providers/codex-models-discovery.ts
34255
34498
  import { existsSync as existsSync14, readFileSync as readFileSync18 } from "fs";
34256
34499
  import { homedir as homedir16 } from "os";
@@ -34322,6 +34565,21 @@ function toModelTable(body) {
34322
34565
  }
34323
34566
  return table;
34324
34567
  }
34568
+ function dropCredentialTiers(table, credentialValues) {
34569
+ let dropped = 0;
34570
+ for (const info of table.values()) {
34571
+ if (info.serviceTiers) {
34572
+ const kept = info.serviceTiers.filter((tier) => !containsExactValue(tier.id, credentialValues) && !containsExactValue(tier.name, credentialValues));
34573
+ dropped += info.serviceTiers.length - kept.length;
34574
+ info.serviceTiers = kept;
34575
+ }
34576
+ if (info.defaultServiceTier !== undefined && containsExactValue(info.defaultServiceTier, credentialValues)) {
34577
+ delete info.defaultServiceTier;
34578
+ dropped++;
34579
+ }
34580
+ }
34581
+ return dropped;
34582
+ }
34325
34583
  function discoveryHeaders(binding) {
34326
34584
  const headers = {};
34327
34585
  for (const [name, value] of Object.entries(binding.auth?.headers ?? {})) {
@@ -34355,6 +34613,10 @@ async function fetchModelTable(binding, opts) {
34355
34613
  log("[CodexDiscovery] GET /models body has no models array");
34356
34614
  return;
34357
34615
  }
34616
+ const dropped = dropCredentialTiers(table, credentialValuesFromRequest(binding.auth?.headers, binding.auth?.endpoint));
34617
+ if (dropped > 0) {
34618
+ log(`[CodexDiscovery] dropped ${dropped} service tier(s) that contain a credential value`);
34619
+ }
34358
34620
  log(`[CodexDiscovery] GET /models: ${table.size} model(s)`);
34359
34621
  return table;
34360
34622
  } catch (err) {
@@ -34437,7 +34699,9 @@ async function getCodexModelInfo(slug, binding, accountKey, opts = {}) {
34437
34699
  }
34438
34700
  var CODEX_DISCOVERY_CLIENT_VERSION = "0.161.0", CODEX_DISCOVERY_TTL_MS, CODEX_DISCOVERY_FETCH_TIMEOUT_MS = 1e4, CODEX_DISCOVERY_DEFAULT_WAIT_MS = 2000, FAILURE_RETRY_AFTER_MS, memo;
34439
34701
  var init_codex_models_discovery = __esm(() => {
34702
+ init_call_context();
34440
34703
  init_logger();
34704
+ init_redact();
34441
34705
  CODEX_DISCOVERY_TTL_MS = 60 * 60 * 1000;
34442
34706
  FAILURE_RETRY_AFTER_MS = 60 * 1000;
34443
34707
  memo = new Map;
@@ -41218,236 +41482,6 @@ function decideCodexSpeed(speed, modelInfo) {
41218
41482
  }
41219
41483
  var CODEX_SERVICE_TIER_POINTER = "/service_tier";
41220
41484
 
41221
- // src/handlers/shared/call-context.ts
41222
- function createSigningSecrets() {
41223
- return { values: new Set, lease: acquireSigningLease() };
41224
- }
41225
- function signingSecretsOf(c) {
41226
- const installed = readCallVar(c, SIGNING_SECRETS_KEY);
41227
- if (installed)
41228
- return installed;
41229
- const lazy = createSigningSecrets();
41230
- writeCallVar(c, SIGNING_SECRETS_KEY, lazy);
41231
- return lazy;
41232
- }
41233
- function readCallVar(c, key) {
41234
- if (!c || typeof c !== "object")
41235
- return;
41236
- const store = c;
41237
- if (typeof store.get === "function")
41238
- return store.get(key);
41239
- return detachedCallVars.get(c)?.get(key);
41240
- }
41241
- function writeCallVar(c, key, value) {
41242
- if (!c || typeof c !== "object")
41243
- return;
41244
- const store = c;
41245
- if (typeof store.set === "function") {
41246
- store.set(key, value);
41247
- return;
41248
- }
41249
- let vars = detachedCallVars.get(c);
41250
- if (!vars) {
41251
- vars = new Map;
41252
- detachedCallVars.set(c, vars);
41253
- }
41254
- vars.set(key, value);
41255
- }
41256
- function addSigningSecrets(c, values) {
41257
- const secrets = signingSecretsOf(c);
41258
- const list = [...values].filter((v) => typeof v === "string" && v.length > 0);
41259
- for (const value of list)
41260
- secrets.values.add(value);
41261
- secrets.lease.add(list);
41262
- }
41263
- function isCredentialHeader(name) {
41264
- const lower = name.toLowerCase();
41265
- if (CREDENTIAL_HEADER_NAMES.has(lower))
41266
- return true;
41267
- return CREDENTIAL_HEADER_FRAGMENTS.some((fragment) => lower.includes(fragment));
41268
- }
41269
- function credentialPartsOf(name, value) {
41270
- const parts = [value];
41271
- const bare = value.replace(AUTH_SCHEME_PREFIX, "");
41272
- if (bare !== value)
41273
- parts.push(bare);
41274
- if (name.toLowerCase() === "cookie") {
41275
- for (const pair of value.split(";")) {
41276
- const eq = pair.indexOf("=");
41277
- if (eq > 0)
41278
- parts.push(pair.slice(eq + 1).trim());
41279
- }
41280
- }
41281
- return parts;
41282
- }
41283
- function credentialValuesFromRequest(headers, endpoint) {
41284
- const out = [];
41285
- for (const [name, value] of Object.entries(headers ?? {})) {
41286
- if (typeof value !== "string" || !value || !isCredentialHeader(name))
41287
- continue;
41288
- out.push(...credentialPartsOf(name, value));
41289
- }
41290
- if (endpoint) {
41291
- try {
41292
- for (const [name, value] of new URL(endpoint).searchParams) {
41293
- if (value && CREDENTIAL_QUERY_NAMES.has(name.toLowerCase()))
41294
- out.push(value);
41295
- }
41296
- } catch {}
41297
- }
41298
- return out;
41299
- }
41300
- function releaseWhenBodyEnds(response, release) {
41301
- const source = response.body;
41302
- if (!source) {
41303
- release();
41304
- return response;
41305
- }
41306
- const reader = source.getReader();
41307
- let cancelling = false;
41308
- const stream = new ReadableStream({
41309
- async pull(controller) {
41310
- let result;
41311
- try {
41312
- result = await reader.read();
41313
- } catch (err) {
41314
- if (cancelling)
41315
- return;
41316
- release();
41317
- controller.error(err);
41318
- return;
41319
- }
41320
- if (cancelling)
41321
- return;
41322
- if (result.done) {
41323
- release();
41324
- controller.close();
41325
- return;
41326
- }
41327
- controller.enqueue(result.value);
41328
- },
41329
- async cancel(reason) {
41330
- cancelling = true;
41331
- try {
41332
- await reader.cancel(reason);
41333
- } catch {} finally {
41334
- release();
41335
- }
41336
- }
41337
- }, { highWaterMark: 0 });
41338
- return new Response(stream, {
41339
- status: response.status,
41340
- statusText: response.statusText,
41341
- headers: response.headers
41342
- });
41343
- }
41344
- function callAbortSignal(c) {
41345
- return readCallVar(c, CALL_ABORT_SIGNAL_KEY);
41346
- }
41347
- function callAborted(c) {
41348
- return callAbortSignal(c)?.aborted === true;
41349
- }
41350
- function callAbortError() {
41351
- return new DOMException("the call's deadline passed; claudish stopped its work", "AbortError");
41352
- }
41353
- function raceCallAbort(p, signal) {
41354
- if (!signal)
41355
- return p;
41356
- p.catch(() => {});
41357
- if (signal.aborted)
41358
- return Promise.reject(callAbortError());
41359
- return new Promise((resolve, reject) => {
41360
- const onAbort = () => reject(callAbortError());
41361
- signal.addEventListener("abort", onAbort, { once: true });
41362
- p.then((value) => {
41363
- signal.removeEventListener("abort", onAbort);
41364
- resolve(value);
41365
- }, (err) => {
41366
- signal.removeEventListener("abort", onAbort);
41367
- reject(err);
41368
- });
41369
- });
41370
- }
41371
- function sleepUnlessAborted(ms, signal) {
41372
- if (signal?.aborted)
41373
- return Promise.resolve(true);
41374
- return new Promise((resolve) => {
41375
- const onAbort = () => {
41376
- clearTimeout(timer);
41377
- resolve(true);
41378
- };
41379
- const timer = setTimeout(() => {
41380
- signal?.removeEventListener("abort", onAbort);
41381
- resolve(false);
41382
- }, ms);
41383
- signal?.addEventListener("abort", onAbort, { once: true });
41384
- });
41385
- }
41386
- function withCallSignal(sig, callSignal) {
41387
- if (!callSignal)
41388
- return sig;
41389
- if (!sig)
41390
- return callSignal;
41391
- return AbortSignal.any([sig, callSignal]);
41392
- }
41393
- function abortedResponse() {
41394
- return new Response(JSON.stringify({
41395
- type: "error",
41396
- error: {
41397
- type: "timeout_error",
41398
- message: "claudish stopped this call: its deadline passed"
41399
- }
41400
- }), {
41401
- status: 408,
41402
- headers: { "content-type": "application/json", [CALL_ABORTED_HEADER]: "1" }
41403
- });
41404
- }
41405
- function hopLogOf(c) {
41406
- return readCallVar(c, HOP_LOG_KEY);
41407
- }
41408
- function recordHopEntry(c, provider, wireModel) {
41409
- const hops = hopLogOf(c);
41410
- if (!hops)
41411
- return;
41412
- const plannedUid = readCallVar(c, PLANNED_HOP_KEY);
41413
- const entry = {
41414
- provider,
41415
- wireModel,
41416
- arm: null,
41417
- billing: null,
41418
- ...plannedUid ? { plannedUid } : {}
41419
- };
41420
- hops.push(entry);
41421
- return entry;
41422
- }
41423
- async function withPlannedHop(c, plannedUid, work) {
41424
- if (!hopLogOf(c))
41425
- return work();
41426
- const previous = readCallVar(c, PLANNED_HOP_KEY);
41427
- writeCallVar(c, PLANNED_HOP_KEY, plannedUid);
41428
- try {
41429
- return await work();
41430
- } finally {
41431
- writeCallVar(c, PLANNED_HOP_KEY, previous);
41432
- }
41433
- }
41434
- var SIGNING_SECRETS_KEY = "claudishSigningSecrets", detachedCallVars, CREDENTIAL_HEADER_NAMES, CREDENTIAL_HEADER_FRAGMENTS, CREDENTIAL_QUERY_NAMES, AUTH_SCHEME_PREFIX, CALL_ABORT_SIGNAL_KEY = "claudishCallAbortSignal", CALL_ABORTED_HEADER = "x-claudish-call-aborted", HOP_LOG_KEY = "claudishHopLog", PLANNED_HOP_KEY = "claudishPlannedHop";
41435
- var init_call_context = __esm(() => {
41436
- init_redact();
41437
- detachedCallVars = new WeakMap;
41438
- CREDENTIAL_HEADER_NAMES = new Set([
41439
- "authorization",
41440
- "proxy-authorization",
41441
- "x-api-key",
41442
- "api-key",
41443
- "x-goog-api-key",
41444
- "cookie"
41445
- ]);
41446
- CREDENTIAL_HEADER_FRAGMENTS = ["token", "secret", "key"];
41447
- CREDENTIAL_QUERY_NAMES = new Set(["key", "api_key", "token", "access_token"]);
41448
- AUTH_SCHEME_PREFIX = /^(?:Bearer|Basic|Token)\s+/i;
41449
- });
41450
-
41451
41485
  // src/handlers/shared/gemini-queue.ts
41452
41486
  function rejectIfAborted(request) {
41453
41487
  if (request.onAbort)
@@ -92866,6 +92900,111 @@ var init_handler_set = __esm(() => {
92866
92900
  init_composed_handler();
92867
92901
  });
92868
92902
 
92903
+ // src/handlers/shared/anthropic-forward.ts
92904
+ function inboundAuthHeaders(incoming) {
92905
+ const out = {};
92906
+ const authorization = incoming.get("authorization");
92907
+ const apiKey = incoming.get("x-api-key");
92908
+ if (authorization)
92909
+ out.authorization = authorization;
92910
+ if (apiKey)
92911
+ out["x-api-key"] = apiKey;
92912
+ return out;
92913
+ }
92914
+ function connectionNamed(headers) {
92915
+ const named = new Set;
92916
+ for (const token of (headers.get("connection") ?? "").split(",")) {
92917
+ const name = token.trim().toLowerCase();
92918
+ if (name)
92919
+ named.add(name);
92920
+ }
92921
+ return named;
92922
+ }
92923
+ function requestHeadersToForward(incoming) {
92924
+ const named = connectionNamed(incoming);
92925
+ const out = {};
92926
+ incoming.forEach((value, name) => {
92927
+ const key = name.toLowerCase();
92928
+ if (!ALLOWED_NAMES.has(key))
92929
+ return;
92930
+ if (HOP_BY_HOP.has(key) || named.has(key) || key.startsWith(INTERNAL_PREFIX))
92931
+ return;
92932
+ out[key] = value;
92933
+ });
92934
+ return out;
92935
+ }
92936
+ function querySegmentName(segment) {
92937
+ const eq = segment.indexOf("=");
92938
+ const rawName = eq < 0 ? segment : segment.slice(0, eq);
92939
+ try {
92940
+ return decodeURIComponent(rawName.replace(/\+/g, " "));
92941
+ } catch {
92942
+ return null;
92943
+ }
92944
+ }
92945
+ function forwardedSearch(c) {
92946
+ const url = c.req.url;
92947
+ if (typeof url !== "string" || url.length === 0)
92948
+ return "";
92949
+ let search;
92950
+ try {
92951
+ search = new URL(url).search;
92952
+ } catch {
92953
+ return "";
92954
+ }
92955
+ const kept = search.slice(1).split("&").filter((segment) => {
92956
+ const name = querySegmentName(segment);
92957
+ return name !== null && ALLOWED_QUERY_NAMES.has(name);
92958
+ });
92959
+ return kept.length > 0 ? `?${kept.join("&")}` : "";
92960
+ }
92961
+ function recordInboundBody(c, raw, parsed) {
92962
+ c.set(INBOUND_BODY_KEY, { raw, canonical: JSON.stringify(parsed) });
92963
+ }
92964
+ function bodyToForward(c, payload) {
92965
+ const serialized = JSON.stringify(payload);
92966
+ const inbound = c.get(INBOUND_BODY_KEY);
92967
+ return inbound !== undefined && inbound.canonical === serialized ? inbound.raw : serialized;
92968
+ }
92969
+ var ALLOWED_NAMES, HOP_BY_HOP, INTERNAL_PREFIX = "x-claudish-", ALLOWED_QUERY_NAMES, INBOUND_BODY_KEY = "inboundBody";
92970
+ var init_anthropic_forward = __esm(() => {
92971
+ ALLOWED_NAMES = new Set([
92972
+ "authorization",
92973
+ "x-api-key",
92974
+ "content-type",
92975
+ "accept",
92976
+ "accept-encoding",
92977
+ "user-agent",
92978
+ "x-app",
92979
+ "anthropic-beta",
92980
+ "anthropic-version",
92981
+ "anthropic-dangerous-direct-browser-access",
92982
+ "x-claude-code-session-id",
92983
+ "x-stainless-arch",
92984
+ "x-stainless-lang",
92985
+ "x-stainless-os",
92986
+ "x-stainless-package-version",
92987
+ "x-stainless-retry-count",
92988
+ "x-stainless-runtime",
92989
+ "x-stainless-runtime-version",
92990
+ "x-stainless-timeout"
92991
+ ]);
92992
+ HOP_BY_HOP = new Set([
92993
+ "connection",
92994
+ "keep-alive",
92995
+ "proxy-connection",
92996
+ "proxy-authenticate",
92997
+ "proxy-authorization",
92998
+ "te",
92999
+ "trailer",
93000
+ "transfer-encoding",
93001
+ "upgrade",
93002
+ "host",
93003
+ "content-length"
93004
+ ]);
93005
+ ALLOWED_QUERY_NAMES = new Set(["beta"]);
93006
+ });
93007
+
92869
93008
  // src/handlers/shared/thinking-signature.ts
92870
93009
  function isUnsignedThinking(block) {
92871
93010
  if (!block || typeof block !== "object")
@@ -92956,7 +93095,10 @@ class NativeHandler {
92956
93095
  }
92957
93096
  async handle(c, incoming) {
92958
93097
  const payload = await this.applyRequestHooks(c, incoming);
92959
- const originalHeaders = c.req.header();
93098
+ const headers = {
93099
+ ...requestHeadersToForward(c.req.raw.headers),
93100
+ ...inboundAuthHeaders(c.req.raw.headers)
93101
+ };
92960
93102
  const target = payload.model;
92961
93103
  const strippedThinking = stripUnsignedThinkingBlocks(payload.messages);
92962
93104
  if (strippedThinking > 0) {
@@ -92965,22 +93107,15 @@ class NativeHandler {
92965
93107
  const advisorSwapped = c.get(ADVISOR_SWAPPED_CONTEXT_KEY) === true;
92966
93108
  log(`
92967
93109
  === [NATIVE] Claude Code \u2192 Anthropic API Request ===`);
92968
- log(`[Native] x-api-key: ${originalHeaders["x-api-key"] ? maskCredential(originalHeaders["x-api-key"]) : "(not set)"}`);
92969
- log(`[Native] authorization: ${originalHeaders.authorization ? maskCredential(originalHeaders.authorization) : "(not set)"}`);
93110
+ log(`[Native] x-api-key: ${headers["x-api-key"] ? maskCredential(headers["x-api-key"]) : "(not set)"}`);
93111
+ log(`[Native] authorization: ${headers.authorization ? maskCredential(headers.authorization) : "(not set)"}`);
92970
93112
  log(`Request body (Model: ${target}):`);
92971
93113
  log(`=== End Request ===
92972
93114
  `);
92973
- const headers = {
92974
- "Content-Type": "application/json",
92975
- "anthropic-version": originalHeaders["anthropic-version"] || "2023-06-01"
92976
- };
92977
- if (originalHeaders.authorization) {
92978
- headers.authorization = originalHeaders.authorization;
92979
- }
92980
- if (originalHeaders["x-api-key"]) {
92981
- headers["x-api-key"] = originalHeaders["x-api-key"];
92982
- }
92983
- if (!originalHeaders.authorization && !originalHeaders["x-api-key"]) {
93115
+ headers["content-type"] = "application/json";
93116
+ if (!headers["anthropic-version"])
93117
+ headers["anthropic-version"] = "2023-06-01";
93118
+ if (!headers.authorization && !headers["x-api-key"]) {
92984
93119
  let fallbackKey = this.apiKey;
92985
93120
  if (!fallbackKey) {
92986
93121
  const auth = await credentials.getRequestAuth("native-anthropic", { model: target });
@@ -92990,28 +93125,27 @@ class NativeHandler {
92990
93125
  headers["x-api-key"] = fallbackKey;
92991
93126
  }
92992
93127
  }
92993
- if (originalHeaders["anthropic-beta"]) {
92994
- const incomingBeta = originalHeaders["anthropic-beta"];
92995
- if (advisorSwapped) {
92996
- const { stripped, changed } = stripAdvisorBeta(incomingBeta);
92997
- if (changed) {
92998
- log(`[Native][advisor-swap] stripped advisor-tool beta; before=${incomingBeta} after=${stripped ?? "(empty)"}`);
92999
- logAdvisorEvent(loadAdvisorSwapConfig(this.advisorModels, this.advisorCollector), {
93000
- kind: "beta_stripped",
93001
- before: incomingBeta,
93002
- after: stripped ?? ""
93003
- });
93004
- }
93005
- if (stripped)
93006
- headers["anthropic-beta"] = stripped;
93007
- } else {
93008
- headers["anthropic-beta"] = incomingBeta;
93128
+ const incomingBeta = headers["anthropic-beta"];
93129
+ if (incomingBeta && advisorSwapped) {
93130
+ const { stripped, changed } = stripAdvisorBeta(incomingBeta);
93131
+ if (changed) {
93132
+ log(`[Native][advisor-swap] stripped advisor-tool beta; before=${incomingBeta} after=${stripped ?? "(empty)"}`);
93133
+ logAdvisorEvent(loadAdvisorSwapConfig(this.advisorModels, this.advisorCollector), {
93134
+ kind: "beta_stripped",
93135
+ before: incomingBeta,
93136
+ after: stripped ?? ""
93137
+ });
93009
93138
  }
93139
+ if (stripped)
93140
+ headers["anthropic-beta"] = stripped;
93141
+ else
93142
+ delete headers["anthropic-beta"];
93010
93143
  }
93011
- addSigningSecrets(c, credentialValuesFromRequest(headers));
93012
- const body = JSON.stringify(payload);
93144
+ const url = `${this.baseUrl}/v1/messages${forwardedSearch(c)}`;
93145
+ addSigningSecrets(c, credentialValuesFromRequest(headers, url));
93146
+ const body = bodyToForward(c, payload);
93013
93147
  try {
93014
- const anthropicResponse = await fetch(`${this.baseUrl}/v1/messages`, {
93148
+ const anthropicResponse = await fetch(url, {
93015
93149
  method: "POST",
93016
93150
  headers,
93017
93151
  body
@@ -93163,6 +93297,7 @@ var init_native_handler = __esm(() => {
93163
93297
  init_advisor_decorator();
93164
93298
  init_native_handler_advisor();
93165
93299
  init_anthropic_error();
93300
+ init_anthropic_forward();
93166
93301
  init_call_context();
93167
93302
  });
93168
93303
 
@@ -94281,7 +94416,9 @@ ${plan.hint}` : `[Route] ${plan.reason}`;
94281
94416
  app.post("/v1/messages", async (c) => {
94282
94417
  let handlerThrew = false;
94283
94418
  try {
94284
- const body = await c.req.json();
94419
+ const raw = await c.req.text();
94420
+ const body = JSON.parse(raw);
94421
+ recordInboundBody(c, raw, body);
94285
94422
  log(`[RequestMeta] model=${body.model} output_config=${JSON.stringify(body.output_config) ?? "(none)"} metadata=${JSON.stringify(body.metadata) ?? "(none)"} anthropic-beta=${c.req.header("anthropic-beta") ?? "(none)"}`);
94286
94423
  maybeCaptureClassifierRequest(c, body);
94287
94424
  if (!monitorMode && options.classifier?.enabled && isAutoModeClassifierRequest(body)) {
@@ -94359,6 +94496,7 @@ var init_proxy_server = __esm(() => {
94359
94496
  init_native_handler_advisor();
94360
94497
  init_native_handler();
94361
94498
  init_anthropic_error();
94499
+ init_anthropic_forward();
94362
94500
  init_call_context();
94363
94501
  init_hop_decision();
94364
94502
  init_hooks();
@@ -97189,6 +97327,30 @@ var init_pane_launch = __esm(() => {
97189
97327
  FATAL_MAGMUX_STDERR = /ignoring --id|magmux: (?:--sock-dir|MAGMUX_SOCK_DIR) |magmux: socket/;
97190
97328
  });
97191
97329
 
97330
+ // src/process-tree.ts
97331
+ function waitForExit(proc, ms) {
97332
+ if (proc.exitCode !== null || proc.signalCode !== null)
97333
+ return Promise.resolve(true);
97334
+ return new Promise((resolve) => {
97335
+ let settled = false;
97336
+ const done = (value) => {
97337
+ if (settled)
97338
+ return;
97339
+ settled = true;
97340
+ proc.off("exit", onExit);
97341
+ resolve(value);
97342
+ };
97343
+ const onExit = () => done(true);
97344
+ proc.once("exit", onExit);
97345
+ const t = setTimeout(() => done(false), ms);
97346
+ t.unref?.();
97347
+ });
97348
+ }
97349
+ var KILL_PROCESS_GROUP;
97350
+ var init_process_tree = __esm(() => {
97351
+ KILL_PROCESS_GROUP = process.platform !== "win32";
97352
+ });
97353
+
97192
97354
  // src/recovery/types.ts
97193
97355
  var UI_LEASE_MS = 1e4, FRAME_TICK_MS = 1000;
97194
97356
 
@@ -98655,7 +98817,7 @@ Or set CLAUDE_PATH to your custom installation:`);
98655
98817
  } catch {}
98656
98818
  });
98657
98819
  }
98658
- setupSignalHandlers(proc, tempSettingsPath, config.quiet, onCleanup);
98820
+ const signalShutdown = setupSignalHandlers(proc, tempSettingsPath, config.quiet, onCleanup);
98659
98821
  const { exitCode, exitSignal } = await new Promise((resolve) => {
98660
98822
  proc.on("exit", (code, signal) => {
98661
98823
  setClaudeCodeRunning(false);
@@ -98682,22 +98844,45 @@ Or set CLAUDE_PATH to your custom installation:`);
98682
98844
  try {
98683
98845
  unlinkSync11(tempSettingsPath);
98684
98846
  } catch {}
98847
+ signalShutdown.launcherCleanupDone();
98848
+ if (signalShutdown.started())
98849
+ return new Promise(() => {});
98685
98850
  return exitCode;
98686
98851
  }
98687
98852
  function sessionOutcomeOf(exitCode) {
98688
98853
  return exitCode === 0 ? { state: "COMPLETED", reason: null, exitCode } : { state: "FAILED", reason: "child_exited", exitCode };
98689
98854
  }
98855
+ function delay(ms) {
98856
+ return new Promise((resolve) => {
98857
+ const t = setTimeout(resolve, Math.max(0, ms));
98858
+ t.unref?.();
98859
+ });
98860
+ }
98690
98861
  function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
98691
98862
  const signals = isWindows2() ? ["SIGINT", "SIGTERM"] : ["SIGINT", "SIGTERM", "SIGHUP"];
98692
- claimSignalExit();
98693
- for (const signal of signals) {
98694
- process.on(signal, () => {
98695
- releaseTerminalIsolation();
98696
- if (!quiet) {
98697
- console.error(`
98698
- [claudish] Received ${signal}, shutting down...`);
98863
+ let shuttingDown = null;
98864
+ let markLauncherCleanupDone = () => {};
98865
+ const launcherCleanup = new Promise((resolve) => {
98866
+ markLauncherCleanupDone = resolve;
98867
+ });
98868
+ const shutdown = async (signal) => {
98869
+ const startedAt = Date.now();
98870
+ try {
98871
+ proc.kill("SIGTERM");
98872
+ if (!await waitForExit(proc, SIGNAL_CHILD_EXIT_GRACE_MS)) {
98873
+ log(`[claudish] Claude Code did not exit within ${SIGNAL_CHILD_EXIT_GRACE_MS} ms of SIGTERM; sending SIGKILL`);
98874
+ try {
98875
+ proc.kill("SIGKILL");
98876
+ } catch {}
98877
+ await waitForExit(proc, SIGNAL_CHILD_KILL_WAIT_MS);
98699
98878
  }
98700
- proc.kill();
98879
+ await Promise.race([
98880
+ launcherCleanup,
98881
+ delay(SIGNAL_SHUTDOWN_BUDGET_MS - (Date.now() - startedAt))
98882
+ ]);
98883
+ } catch (err) {
98884
+ log(`[claudish] Signal shutdown error: ${err}`);
98885
+ } finally {
98701
98886
  if (onCleanup) {
98702
98887
  try {
98703
98888
  onCleanup();
@@ -98707,8 +98892,28 @@ function setupSignalHandlers(proc, tempSettingsPath, quiet, onCleanup) {
98707
98892
  unlinkSync11(tempSettingsPath);
98708
98893
  } catch {}
98709
98894
  process.exit(signalExitCode(signal));
98895
+ }
98896
+ };
98897
+ claimSignalExit();
98898
+ for (const signal of signals) {
98899
+ process.on(signal, () => {
98900
+ if (shuttingDown) {
98901
+ log(`[claudish] Received ${signal} while shutting down from ${shuttingDown}; ignored`);
98902
+ return;
98903
+ }
98904
+ shuttingDown = signal;
98905
+ releaseTerminalIsolation();
98906
+ if (!quiet) {
98907
+ console.error(`
98908
+ [claudish] Received ${signal}, shutting down...`);
98909
+ }
98910
+ shutdown(signal);
98710
98911
  });
98711
98912
  }
98913
+ return {
98914
+ started: () => shuttingDown !== null,
98915
+ launcherCleanupDone: () => markLauncherCleanupDone()
98916
+ };
98712
98917
  }
98713
98918
  async function findClaudeBinary(env = process.env) {
98714
98919
  const isWindows = process.platform === "win32";
@@ -98809,7 +99014,7 @@ var restoreTerminal = null, macosKeychainAnthropicMemo, defaultKeychainAnthropic
98809
99014
  }
98810
99015
  macosKeychainAnthropicMemo.set(memoKey, found);
98811
99016
  return found;
98812
- }, CLAUDISH_PLACEHOLDER_API_KEY = "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx", CLAUDISH_PLACEHOLDER_AUTH_TOKEN = "placeholder-token-not-used-proxy-handles-auth", STALE_TOKEN_FILE_MS, MAX_TOKEN_FILES_SCANNED = 4000, CLAUDE_CODE_DEFAULT_MAX_CONTEXT = 200000, USER_STATUS_LINE_TIMEOUT_SECONDS = 3, MIN_AUTO_COMPACT_WINDOW = 200000, MAX_AUTO_COMPACT_WINDOW = 1e6, ADVISOR_TOOL_ENV_VAR = "CLAUDE_CODE_ENABLE_EXPERIMENTAL_ADVISOR_TOOL", CLAUDISH_CHILD_ADVISOR_MODEL = "sonnet", CHILD_STDERR_NOISE;
99017
+ }, CLAUDISH_PLACEHOLDER_API_KEY = "sk-ant-api03-placeholder-not-used-proxy-handles-auth-with-openrouter-key-xxxxxxxxxxxxxxxxxxxxx", CLAUDISH_PLACEHOLDER_AUTH_TOKEN = "placeholder-token-not-used-proxy-handles-auth", STALE_TOKEN_FILE_MS, MAX_TOKEN_FILES_SCANNED = 4000, CLAUDE_CODE_DEFAULT_MAX_CONTEXT = 200000, USER_STATUS_LINE_TIMEOUT_SECONDS = 3, MIN_AUTO_COMPACT_WINDOW = 200000, MAX_AUTO_COMPACT_WINDOW = 1e6, ADVISOR_TOOL_ENV_VAR = "CLAUDE_CODE_ENABLE_EXPERIMENTAL_ADVISOR_TOOL", CLAUDISH_CHILD_ADVISOR_MODEL = "sonnet", CHILD_STDERR_NOISE, SIGNAL_CHILD_EXIT_GRACE_MS = 3000, SIGNAL_CHILD_KILL_WAIT_MS = 500, SIGNAL_SHUTDOWN_BUDGET_MS = 4000;
98813
99018
  var init_claude_runner = __esm(() => {
98814
99019
  init_model_catalog();
98815
99020
  init_claude_code_facts();
@@ -98825,6 +99030,7 @@ var init_claude_runner = __esm(() => {
98825
99030
  init_logger();
98826
99031
  init_child_env();
98827
99032
  init_pane_launch();
99033
+ init_process_tree();
98828
99034
  init_profile_config();
98829
99035
  init_model_discovery();
98830
99036
  init_model_parser();
@@ -99858,30 +100064,6 @@ var init_gate_binding = __esm(() => {
99858
100064
  init_input_gate();
99859
100065
  });
99860
100066
 
99861
- // src/process-tree.ts
99862
- function waitForExit(proc, ms) {
99863
- if (proc.exitCode !== null || proc.signalCode !== null)
99864
- return Promise.resolve(true);
99865
- return new Promise((resolve) => {
99866
- let settled = false;
99867
- const done = (value) => {
99868
- if (settled)
99869
- return;
99870
- settled = true;
99871
- proc.off("exit", onExit);
99872
- resolve(value);
99873
- };
99874
- const onExit = () => done(true);
99875
- proc.once("exit", onExit);
99876
- const t = setTimeout(() => done(false), ms);
99877
- t.unref?.();
99878
- });
99879
- }
99880
- var KILL_PROCESS_GROUP;
99881
- var init_process_tree = __esm(() => {
99882
- KILL_PROCESS_GROUP = process.platform !== "win32";
99883
- });
99884
-
99885
100067
  // src/pane/pane-reap.ts
99886
100068
  function alive(p) {
99887
100069
  return !!p && p.exitCode === null && p.signalCode === null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claudish",
3
- "version": "14.18.0",
3
+ "version": "14.18.1",
4
4
  "description": "Run Claude Code with any model - OpenRouter, Ollama, LM Studio & local models",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -71,10 +71,10 @@
71
71
  "ai"
72
72
  ],
73
73
  "optionalDependencies": {
74
- "@claudish/magmux-darwin-arm64": "14.18.0",
75
- "@claudish/magmux-darwin-x64": "14.18.0",
76
- "@claudish/magmux-linux-arm64": "14.18.0",
77
- "@claudish/magmux-linux-x64": "14.18.0"
74
+ "@claudish/magmux-darwin-arm64": "14.18.1",
75
+ "@claudish/magmux-darwin-x64": "14.18.1",
76
+ "@claudish/magmux-linux-arm64": "14.18.1",
77
+ "@claudish/magmux-linux-x64": "14.18.1"
78
78
  },
79
79
  "author": "Jack Rudenko <i@madappgang.com>",
80
80
  "license": "MIT",