@bman654/clodex 2.11.6 → 2.11.7

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/README.md CHANGED
@@ -106,6 +106,9 @@ flowchart LR
106
106
  > [!TIP]
107
107
  > Using Claude Code's agents view or background agents? Ask your Claude Code agent to read [docs/background-agents.md](docs/background-agents.md) and set it up for you — one global `clodex server --proxy` plus the `clodex-claude` wrapper bin bridges every claude process automatically.
108
108
 
109
+ > [!TIP]
110
+ > On Windows with the Claude Code VS Code extension? See [docs/windows-setup.md](docs/windows-setup.md) — proxy-mode env vars route the extension through clodex, and an optional process wrapper makes clodex models appear in its model picker.
111
+
109
112
  ## CLI reference
110
113
 
111
114
  ### `clodex claude [options] [claude-flags]`
package/dist/cli.js CHANGED
@@ -382,7 +382,7 @@ import { join } from "path";
382
382
  // package.json
383
383
  var package_default = {
384
384
  name: "@bman654/clodex",
385
- version: "2.11.6",
385
+ version: "2.11.7",
386
386
  publishConfig: {
387
387
  access: "public"
388
388
  },
@@ -8717,8 +8717,8 @@ var FAILURE_EVENT_TYPES = /* @__PURE__ */ new Set(["error", "response.failed", "
8717
8717
  var RESPONSES_WS_HARD_TTL_MS = 55 * 6e4;
8718
8718
  var RESPONSES_WS_IDLE_TTL_MS = 30 * 6e4;
8719
8719
  var RESPONSES_WS_NURSERY_IDLE_TTL_MS = 5 * 6e4;
8720
- var RESPONSES_WS_MAX_CONNECTIONS = 32;
8721
- var RESPONSES_WS_MAX_NURSERY_CONNECTIONS = 8;
8720
+ var RESPONSES_WS_MAX_CONNECTIONS = 64;
8721
+ var RESPONSES_WS_MAX_NURSERY_CONNECTIONS = 48;
8722
8722
  var diagnosticContext = new AsyncLocalStorage();
8723
8723
  function withResponsesWebSocketDiagnosticContext(context, fn) {
8724
8724
  return diagnosticContext.run(context, fn);
@@ -9100,13 +9100,16 @@ function mismatchDumpLine(items, index) {
9100
9100
  function canonicalItemStrings(items) {
9101
9101
  return items.map((item) => canonicalJson(normalizeToolCallJson([item])));
9102
9102
  }
9103
- function isStrictPrefix(head, client) {
9104
- if (client.length <= head.length) return false;
9103
+ function isPrefixOrEqual(head, client) {
9104
+ if (client.length < head.length) return false;
9105
9105
  for (let index = 0; index < head.length; index += 1) {
9106
9106
  if (head[index] !== client[index]) return false;
9107
9107
  }
9108
9108
  return true;
9109
9109
  }
9110
+ function isStrictPrefix(head, client) {
9111
+ return client.length > head.length && isPrefixOrEqual(head, client);
9112
+ }
9110
9113
  function continuationMatch(entry, payload, clientItems) {
9111
9114
  if (!entry.responseId || !entry.requestInput || !entry.expectedAssistant) return void 0;
9112
9115
  const full = inputArray(payload);
@@ -9599,11 +9602,16 @@ function evictOldestIdleGeneration(generation, maxConnections, reason) {
9599
9602
  while (connectionCountByGeneration(generation) >= maxConnections && idle.length) {
9600
9603
  const oldest = idle.shift();
9601
9604
  if (oldest) {
9605
+ const idleMs = Math.max(0, oldest.options.now() - oldest.lastUsedAt);
9606
+ oldest.debug(
9607
+ `evicting the oldest idle ${generation} connection to stay within its cap: connection=${oldest.debugId} idle_ms=${idleMs} cap=${maxConnections} reason=${reason}`
9608
+ );
9602
9609
  evictions.push({
9603
9610
  connectionId: oldest.debugId,
9604
9611
  partitionKey: oldest.key,
9605
9612
  generation: oldest.generation,
9606
- reason
9613
+ reason,
9614
+ idleMs
9607
9615
  });
9608
9616
  deleteEntry(oldest);
9609
9617
  }
@@ -10023,16 +10031,28 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10023
10031
  const diagnosticCorrelation = diagnosticContext.getStore();
10024
10032
  let now = resolvedOptions.now();
10025
10033
  const evictions = cleanupExpiredConnections(now);
10034
+ let canonicalClientItems;
10035
+ const clientItems = () => canonicalClientItems ??= canonicalItemStrings(inputArray(payload));
10026
10036
  const scanForHeads = () => {
10027
10037
  const scanned = partitionKey ? connectionEntries(partitionKey) : [];
10028
10038
  const idle = scanned.filter((entry) => !entry.inFlight);
10029
- const clientItems = idle.length ? canonicalItemStrings(inputArray(payload)) : [];
10039
+ const canonical = idle.length ? clientItems() : [];
10030
10040
  return {
10031
10041
  candidates: scanned,
10032
10042
  idleCandidates: idle,
10033
- matches: idle.map((entry) => ({ entry, match: continuationMatch(entry, payload, clientItems) })).filter((candidate) => candidate.match !== void 0).sort((left, right) => left.match.delta.length - right.match.delta.length || (left.match.mode === right.match.mode ? 0 : left.match.mode === "exact" ? -1 : 1))
10043
+ matches: idle.map((entry) => ({ entry, match: continuationMatch(entry, payload, canonical) })).filter((candidate) => candidate.match !== void 0).sort((left, right) => left.match.delta.length - right.match.delta.length || (left.match.mode === right.match.mode ? 0 : left.match.mode === "exact" ? -1 : 1))
10034
10044
  };
10035
10045
  };
10046
+ const couldPrecedeThisRequest = (entry) => {
10047
+ if (entry.responseId && entry.requestInput && entry.expectedAssistant) {
10048
+ return continuationMatch(entry, payload, clientItems()) !== void 0;
10049
+ }
10050
+ const streaming = entry.current;
10051
+ if (!streaming) return true;
10052
+ streaming.canonicalInput ??= canonicalItemStrings(inputArray(streaming.originalPayload));
10053
+ return isPrefixOrEqual(streaming.canonicalInput, clientItems());
10054
+ };
10055
+ const blockingHead = (entries) => entries.find((entry) => entry.inFlight && couldPrecedeThisRequest(entry));
10036
10056
  let { candidates, idleCandidates, matches } = scanForHeads();
10037
10057
  let selected = matches[0]?.entry;
10038
10058
  let selectedMatch = matches[0]?.match;
@@ -10075,9 +10095,10 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10075
10095
  );
10076
10096
  return "continuation";
10077
10097
  };
10098
+ let arrivalBlockingHead = selected ? void 0 : blockingHead(candidates);
10078
10099
  if (selected && selectedDelta) {
10079
10100
  decision = continueOnHead(selected, selectedMatch);
10080
- } else if (candidates.some((entry) => entry.inFlight)) {
10101
+ } else if (arrivalBlockingHead) {
10081
10102
  selected = void 0;
10082
10103
  persistent = false;
10083
10104
  decision = "parallel_isolated";
@@ -10176,11 +10197,15 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10176
10197
  pacingRescanOutcome = "no_change";
10177
10198
  }
10178
10199
  }
10179
- if (!selected && persistent && partitionKey && connectionEntries(partitionKey).some((entry) => entry.inFlight)) {
10180
- persistent = false;
10181
- decision = "parallel_isolated";
10182
- debug("parallel request using an isolated socket after pacing");
10183
- if (pacingRescanOutcome === "no_change") pacingRescanOutcome = "parallel_isolated";
10200
+ if (!selected && persistent && partitionKey) {
10201
+ const blocked = blockingHead(connectionEntries(partitionKey));
10202
+ if (blocked) {
10203
+ arrivalBlockingHead = blocked;
10204
+ persistent = false;
10205
+ decision = "parallel_isolated";
10206
+ debug("parallel request using an isolated socket after pacing");
10207
+ if (pacingRescanOutcome === "no_change") pacingRescanOutcome = "parallel_isolated";
10208
+ }
10184
10209
  }
10185
10210
  }
10186
10211
  let suppressedMismatchWarnings;
@@ -10236,6 +10261,10 @@ function createResponsesWebSocketFetch(wsUrl, log12, options = {}) {
10236
10261
  createdConnectionId: selected ? void 0 : nextConnectionDebugId,
10237
10262
  ...pacingWaitedMs !== void 0 ? { pacingWaitedMs } : {},
10238
10263
  ...pacingRescanOutcome !== void 0 ? { pacingRescanOutcome } : {},
10264
+ // Which busy head this request could not be told apart from. Without it an
10265
+ // isolated turn reads as unexplained, and isolation is the single largest
10266
+ // source of uncached prompt tokens on this transport.
10267
+ ...decision === "parallel_isolated" && arrivalBlockingHead ? { isolatedByConnectionId: arrivalBlockingHead.debugId } : {},
10239
10268
  ...suppressedMismatchWarnings !== void 0 ? { suppressedMismatchWarnings } : {},
10240
10269
  createdGeneration: selected ? void 0 : persistent ? "nursery" : "isolated",
10241
10270
  incrementalInputItems: selectedDelta?.length,