@rynfar/meridian 1.60.0 → 1.61.0

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.
@@ -1752,6 +1752,133 @@ var init_sqlite = __esm(() => {
1752
1752
  ];
1753
1753
  });
1754
1754
 
1755
+ // src/proxy/fileChanges.ts
1756
+ function extractFileChange(toolName, toolInput, mcpPrefix) {
1757
+ if (!toolName.startsWith(mcpPrefix))
1758
+ return;
1759
+ const shortName = toolName.slice(mcpPrefix.length);
1760
+ const input = toolInput;
1761
+ if (shortName === "write" && input?.path) {
1762
+ return { operation: "wrote", path: String(input.path) };
1763
+ }
1764
+ if (shortName === "edit" && input?.path) {
1765
+ return { operation: "edited", path: String(input.path) };
1766
+ }
1767
+ return;
1768
+ }
1769
+ function createFileChangeHook(changes, mcpPrefix) {
1770
+ return {
1771
+ matcher: "",
1772
+ hooks: [async (input) => {
1773
+ const change = extractFileChange(input.tool_name, input.tool_input, mcpPrefix);
1774
+ if (change) {
1775
+ changes.push(change);
1776
+ return {};
1777
+ }
1778
+ if (input.tool_name === `${mcpPrefix}bash`) {
1779
+ const toolInput = input.tool_input;
1780
+ if (toolInput?.command) {
1781
+ const bashChanges = extractFileChangesFromBash(String(toolInput.command));
1782
+ changes.push(...bashChanges);
1783
+ }
1784
+ }
1785
+ return {};
1786
+ }]
1787
+ };
1788
+ }
1789
+ function isLikelyFilePath(s) {
1790
+ if (s.length > 4096)
1791
+ return false;
1792
+ if (/[<>$`\\()[\]{}=]/.test(s))
1793
+ return false;
1794
+ if (/^-?\d+$/.test(s))
1795
+ return false;
1796
+ if (s.includes("/"))
1797
+ return true;
1798
+ if (/\.[A-Za-z0-9]{1,16}$/.test(s))
1799
+ return true;
1800
+ return false;
1801
+ }
1802
+ function extractFileChangesFromBash(command) {
1803
+ const changes = [];
1804
+ const seen = new Set;
1805
+ const addChange = (operation, path) => {
1806
+ if (path === "/dev/null" || path === "/dev/stderr" || path === "/dev/stdout")
1807
+ return;
1808
+ if (!path.trim())
1809
+ return;
1810
+ const key = `${operation}:${path}`;
1811
+ if (!seen.has(key)) {
1812
+ seen.add(key);
1813
+ changes.push({ operation, path });
1814
+ }
1815
+ };
1816
+ const redirectRegex = /(?<![0-9=])>{1,2}\s*['"]?([^\s'";&|)]+)['"]?/g;
1817
+ let match2;
1818
+ while ((match2 = redirectRegex.exec(command)) !== null) {
1819
+ if (isLikelyFilePath(match2[1])) {
1820
+ addChange("wrote", match2[1]);
1821
+ }
1822
+ }
1823
+ const teeRegex = /\btee\s+(?:-[a-zA-Z]\s+)*['"]?([^\s'";&|)]+)['"]?/g;
1824
+ while ((match2 = teeRegex.exec(command)) !== null) {
1825
+ addChange("wrote", match2[1]);
1826
+ }
1827
+ const sedRegex = /\bsed\s+(?:-[a-zA-Z]*i[a-zA-Z]*|-i)\b.*?['"]?([^\s'";&|)]+)['"]?\s*$/gm;
1828
+ while ((match2 = sedRegex.exec(command)) !== null) {
1829
+ addChange("edited", match2[1]);
1830
+ }
1831
+ return changes;
1832
+ }
1833
+ function extractFileChangesFromMessages(messages, extractFn) {
1834
+ const changes = [];
1835
+ const executedToolIds = new Set;
1836
+ for (const msg of messages) {
1837
+ if (msg.role !== "user")
1838
+ continue;
1839
+ const content = Array.isArray(msg.content) ? msg.content : [];
1840
+ for (const block of content) {
1841
+ if (block?.type === "tool_result" && block.tool_use_id) {
1842
+ executedToolIds.add(block.tool_use_id);
1843
+ }
1844
+ }
1845
+ }
1846
+ for (const msg of messages) {
1847
+ if (msg.role !== "assistant")
1848
+ continue;
1849
+ const content = Array.isArray(msg.content) ? msg.content : [];
1850
+ for (const block of content) {
1851
+ if (block?.type !== "tool_use")
1852
+ continue;
1853
+ if (!executedToolIds.has(block.id))
1854
+ continue;
1855
+ const blockChanges = extractFn(block.name, block.input);
1856
+ changes.push(...blockChanges);
1857
+ }
1858
+ }
1859
+ return changes;
1860
+ }
1861
+ function formatFileChangeSummary(changes) {
1862
+ if (changes.length === 0)
1863
+ return;
1864
+ const seen = new Set;
1865
+ const unique = [];
1866
+ for (const c of changes) {
1867
+ const key = `${c.operation}:${c.path}`;
1868
+ if (!seen.has(key)) {
1869
+ seen.add(key);
1870
+ unique.push(c);
1871
+ }
1872
+ }
1873
+ const lines = unique.map((c) => `- ${c.operation} ${c.path}`);
1874
+ return `
1875
+
1876
+ Files changed:
1877
+ ${lines.join(`
1878
+ `)}`;
1879
+ }
1880
+ var init_fileChanges = () => {};
1881
+
1755
1882
  // src/proxy/messages.ts
1756
1883
  function stripCacheControlForHashing(obj) {
1757
1884
  if (!obj || typeof obj !== "object")
@@ -1831,6 +1958,13 @@ ${history}
1831
1958
 
1832
1959
  ` + last.text;
1833
1960
  }
1961
+ function framePassthroughContinuation(delta) {
1962
+ if (!delta)
1963
+ return delta;
1964
+ return `${PASSTHROUGH_CONTINUATION_LEAD_IN}
1965
+
1966
+ ${delta}`;
1967
+ }
1834
1968
  function stripNonStandardStreamFields(event) {
1835
1969
  if (event && typeof event === "object") {
1836
1970
  const e = event;
@@ -1957,7 +2091,7 @@ function extractSystemText(system) {
1957
2091
  return system.filter((b) => b?.type === "text" && typeof b.text === "string" && b.text).map((b) => b.text).filter((text) => !TRANSPORT_HEADER_BLOCK.test(text)).join(`
1958
2092
  `);
1959
2093
  }
1960
- var HASH_IGNORED_BLOCK_TYPES, HASH_HANDLED_BLOCK_TYPES, HASH_SERIALIZED_BLOCK_TYPES, MULTIMODAL_TYPES, TOOL_TARGET_KEYS, CONTENT_SUMMARY_MAX = 120, TRANSPORT_HEADER_BLOCK;
2094
+ var HASH_IGNORED_BLOCK_TYPES, HASH_HANDLED_BLOCK_TYPES, HASH_SERIALIZED_BLOCK_TYPES, PASSTHROUGH_CONTINUATION_LEAD_IN, MULTIMODAL_TYPES, TOOL_TARGET_KEYS, CONTENT_SUMMARY_MAX = 120, TRANSPORT_HEADER_BLOCK;
1961
2095
  var init_messages = __esm(() => {
1962
2096
  HASH_IGNORED_BLOCK_TYPES = new Set(["thinking", "redacted_thinking"]);
1963
2097
  HASH_HANDLED_BLOCK_TYPES = new Set(["text", "tool_use", "tool_result"]);
@@ -1974,138 +2108,12 @@ var init_messages = __esm(() => {
1974
2108
  "tool_search_tool_result",
1975
2109
  "container_upload"
1976
2110
  ]);
2111
+ PASSTHROUGH_CONTINUATION_LEAD_IN = "The tool calls from your previous turn were forwarded to the client, which has now executed them — " + "their results follow. The instruction to end that turn without further text applied to it alone and " + "is now discharged: continue the work and respond.";
1977
2112
  MULTIMODAL_TYPES = new Set(["image", "document", "file"]);
1978
2113
  TOOL_TARGET_KEYS = ["filePath", "file_path", "path", "command", "pattern", "query", "url"];
1979
2114
  TRANSPORT_HEADER_BLOCK = /^\s*x-anthropic-[a-z0-9-]*header\s*:/i;
1980
2115
  });
1981
2116
 
1982
- // src/proxy/fileChanges.ts
1983
- function extractFileChange(toolName, toolInput, mcpPrefix) {
1984
- if (!toolName.startsWith(mcpPrefix))
1985
- return;
1986
- const shortName = toolName.slice(mcpPrefix.length);
1987
- const input = toolInput;
1988
- if (shortName === "write" && input?.path) {
1989
- return { operation: "wrote", path: String(input.path) };
1990
- }
1991
- if (shortName === "edit" && input?.path) {
1992
- return { operation: "edited", path: String(input.path) };
1993
- }
1994
- return;
1995
- }
1996
- function createFileChangeHook(changes, mcpPrefix) {
1997
- return {
1998
- matcher: "",
1999
- hooks: [async (input) => {
2000
- const change = extractFileChange(input.tool_name, input.tool_input, mcpPrefix);
2001
- if (change) {
2002
- changes.push(change);
2003
- return {};
2004
- }
2005
- if (input.tool_name === `${mcpPrefix}bash`) {
2006
- const toolInput = input.tool_input;
2007
- if (toolInput?.command) {
2008
- const bashChanges = extractFileChangesFromBash(String(toolInput.command));
2009
- changes.push(...bashChanges);
2010
- }
2011
- }
2012
- return {};
2013
- }]
2014
- };
2015
- }
2016
- function isLikelyFilePath(s) {
2017
- if (s.length > 4096)
2018
- return false;
2019
- if (/[<>$`\\()[\]{}=]/.test(s))
2020
- return false;
2021
- if (/^-?\d+$/.test(s))
2022
- return false;
2023
- if (s.includes("/"))
2024
- return true;
2025
- if (/\.[A-Za-z0-9]{1,16}$/.test(s))
2026
- return true;
2027
- return false;
2028
- }
2029
- function extractFileChangesFromBash(command) {
2030
- const changes = [];
2031
- const seen = new Set;
2032
- const addChange = (operation, path) => {
2033
- if (path === "/dev/null" || path === "/dev/stderr" || path === "/dev/stdout")
2034
- return;
2035
- if (!path.trim())
2036
- return;
2037
- const key = `${operation}:${path}`;
2038
- if (!seen.has(key)) {
2039
- seen.add(key);
2040
- changes.push({ operation, path });
2041
- }
2042
- };
2043
- const redirectRegex = /(?<![0-9=])>{1,2}\s*['"]?([^\s'";&|)]+)['"]?/g;
2044
- let match2;
2045
- while ((match2 = redirectRegex.exec(command)) !== null) {
2046
- if (isLikelyFilePath(match2[1])) {
2047
- addChange("wrote", match2[1]);
2048
- }
2049
- }
2050
- const teeRegex = /\btee\s+(?:-[a-zA-Z]\s+)*['"]?([^\s'";&|)]+)['"]?/g;
2051
- while ((match2 = teeRegex.exec(command)) !== null) {
2052
- addChange("wrote", match2[1]);
2053
- }
2054
- const sedRegex = /\bsed\s+(?:-[a-zA-Z]*i[a-zA-Z]*|-i)\b.*?['"]?([^\s'";&|)]+)['"]?\s*$/gm;
2055
- while ((match2 = sedRegex.exec(command)) !== null) {
2056
- addChange("edited", match2[1]);
2057
- }
2058
- return changes;
2059
- }
2060
- function extractFileChangesFromMessages(messages, extractFn) {
2061
- const changes = [];
2062
- const executedToolIds = new Set;
2063
- for (const msg of messages) {
2064
- if (msg.role !== "user")
2065
- continue;
2066
- const content = Array.isArray(msg.content) ? msg.content : [];
2067
- for (const block of content) {
2068
- if (block?.type === "tool_result" && block.tool_use_id) {
2069
- executedToolIds.add(block.tool_use_id);
2070
- }
2071
- }
2072
- }
2073
- for (const msg of messages) {
2074
- if (msg.role !== "assistant")
2075
- continue;
2076
- const content = Array.isArray(msg.content) ? msg.content : [];
2077
- for (const block of content) {
2078
- if (block?.type !== "tool_use")
2079
- continue;
2080
- if (!executedToolIds.has(block.id))
2081
- continue;
2082
- const blockChanges = extractFn(block.name, block.input);
2083
- changes.push(...blockChanges);
2084
- }
2085
- }
2086
- return changes;
2087
- }
2088
- function formatFileChangeSummary(changes) {
2089
- if (changes.length === 0)
2090
- return;
2091
- const seen = new Set;
2092
- const unique = [];
2093
- for (const c of changes) {
2094
- const key = `${c.operation}:${c.path}`;
2095
- if (!seen.has(key)) {
2096
- seen.add(key);
2097
- unique.push(c);
2098
- }
2099
- }
2100
- const lines = unique.map((c) => `- ${c.operation} ${c.path}`);
2101
- return `
2102
-
2103
- Files changed:
2104
- ${lines.join(`
2105
- `)}`;
2106
- }
2107
- var init_fileChanges = () => {};
2108
-
2109
2117
  // src/proxy/session/fingerprint.ts
2110
2118
  import { createHash } from "crypto";
2111
2119
  function extractClientCwd(body) {
@@ -2151,7 +2159,7 @@ var init_opencode = __esm(() => {
2151
2159
  openCodeTransforms = [
2152
2160
  {
2153
2161
  name: "opencode-core",
2154
- adapters: ["opencode", "openai", "codex"],
2162
+ adapters: ["opencode", "openai", "jcode", "codex"],
2155
2163
  onRequest(ctx) {
2156
2164
  const body = ctx.body;
2157
2165
  const blockedTools = BLOCKED_BUILTIN_TOOLS;
@@ -2325,6 +2333,51 @@ IMPORTANT: When using the task/Task tool, the subagent_type parameter must be on
2325
2333
  };
2326
2334
  });
2327
2335
 
2336
+ // src/proxy/adapters/openai.ts
2337
+ var openAiAdapter;
2338
+ var init_openai = __esm(() => {
2339
+ init_opencode2();
2340
+ openAiAdapter = {
2341
+ ...openCodeAdapter,
2342
+ name: "openai"
2343
+ };
2344
+ });
2345
+
2346
+ // src/proxy/adapters/jcode.ts
2347
+ function normalizeJcodeSessionId(value) {
2348
+ const trimmed = value?.trim();
2349
+ return trimmed && JCODE_SESSION_ID.test(trimmed) ? trimmed : undefined;
2350
+ }
2351
+ function isTextSystemBlock(value) {
2352
+ if (value === null || typeof value !== "object")
2353
+ return false;
2354
+ const part = value;
2355
+ return part.type === "text" && typeof part.text === "string";
2356
+ }
2357
+ function extractJcodeWorkingDirectory(body) {
2358
+ if (body === null || typeof body !== "object")
2359
+ return;
2360
+ const system = body.system;
2361
+ const text = typeof system === "string" ? system : Array.isArray(system) ? system.filter(isTextSystemBlock).map((part) => part.text).join(`
2362
+ `) : "";
2363
+ return text.match(/(?:^|\n)Working directory:[^\S\n]*([^\n]+)/)?.[1]?.trim() || undefined;
2364
+ }
2365
+ var JCODE_SESSION_ID, jcodeAdapter;
2366
+ var init_jcode = __esm(() => {
2367
+ init_openai();
2368
+ JCODE_SESSION_ID = /^[A-Za-z0-9._:-]{1,256}$/;
2369
+ jcodeAdapter = {
2370
+ ...openAiAdapter,
2371
+ name: "jcode",
2372
+ getSessionId(c) {
2373
+ return normalizeJcodeSessionId(c.req.header("x-jcode-session"));
2374
+ },
2375
+ extractWorkingDirectory(body) {
2376
+ return extractJcodeWorkingDirectory(body);
2377
+ }
2378
+ };
2379
+ });
2380
+
2328
2381
  // src/proxy/transforms/droid.ts
2329
2382
  function resolveDroidPassthrough() {
2330
2383
  return resolvePassthrough(false);
@@ -3008,16 +3061,6 @@ var init_forgecode2 = __esm(() => {
3008
3061
  };
3009
3062
  });
3010
3063
 
3011
- // src/proxy/adapters/openai.ts
3012
- var openAiAdapter;
3013
- var init_openai = __esm(() => {
3014
- init_opencode2();
3015
- openAiAdapter = {
3016
- ...openCodeAdapter,
3017
- name: "openai"
3018
- };
3019
- });
3020
-
3021
3064
  // src/proxy/adapters/codex.ts
3022
3065
  var codexAdapter;
3023
3066
  var init_codex = __esm(() => {
@@ -3202,6 +3245,9 @@ function detectAdapter(c) {
3202
3245
  return openCodeAdapter;
3203
3246
  }
3204
3247
  const userAgent = c.req.header("user-agent") || "";
3248
+ if (userAgent.startsWith("jcode/") && normalizeJcodeSessionId(c.req.header("x-jcode-session"))) {
3249
+ return jcodeAdapter;
3250
+ }
3205
3251
  if (userAgent.startsWith("opencode/")) {
3206
3252
  return openCodeAdapter;
3207
3253
  }
@@ -3236,6 +3282,7 @@ var init_detect = __esm(() => {
3236
3282
  init_forgecode2();
3237
3283
  init_claudecode();
3238
3284
  init_openai();
3285
+ init_jcode();
3239
3286
  init_codex();
3240
3287
  init_cherry();
3241
3288
  init_adapterInstances();
@@ -3251,6 +3298,7 @@ var init_detect = __esm(() => {
3251
3298
  cherry: cherryAdapter,
3252
3299
  cherrystudio: cherryAdapter,
3253
3300
  openai: openAiAdapter,
3301
+ jcode: jcodeAdapter,
3254
3302
  codex: codexAdapter
3255
3303
  };
3256
3304
  envDefault = process.env.MERIDIAN_DEFAULT_AGENT || "";
@@ -3401,6 +3449,9 @@ var init_sdkFeatures = __esm(() => {
3401
3449
  openai: {
3402
3450
  codeSystemPrompt: false
3403
3451
  },
3452
+ jcode: {
3453
+ codeSystemPrompt: false
3454
+ },
3404
3455
  cherry: {
3405
3456
  codeSystemPrompt: false
3406
3457
  },
@@ -6294,8 +6345,10 @@ var OAUTH_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
6294
6345
  var OAUTH_BETA_HEADER = "oauth-2025-04-20";
6295
6346
  var CACHE_TTL_MS_DEFAULT = 30000;
6296
6347
  var STALE_MAX_MS_DEFAULT = 15 * 60000;
6348
+ var RATE_LIMIT_BACKOFF_MS_DEFAULT = 60000;
6297
6349
  var cacheByProfile = new Map;
6298
6350
  var inflightByProfile = new Map;
6351
+ var rateLimitedUntilByProfile = new Map;
6299
6352
  var DEFAULT_KEY = "__default__";
6300
6353
  var WINDOW_TYPES = [
6301
6354
  "five_hour",
@@ -6317,6 +6370,15 @@ function normalizeUtilization(raw2) {
6317
6370
  return null;
6318
6371
  return Math.max(0, raw2 / 100);
6319
6372
  }
6373
+ function parseRetryAfterMs(raw2) {
6374
+ if (!raw2)
6375
+ return null;
6376
+ const seconds = Number(raw2);
6377
+ if (Number.isFinite(seconds))
6378
+ return Math.max(0, seconds * 1000);
6379
+ const retryAt = Date.parse(raw2);
6380
+ return Number.isFinite(retryAt) ? Math.max(0, retryAt - Date.now()) : null;
6381
+ }
6320
6382
  function modelScopedWindowType(limit) {
6321
6383
  if (limit.kind !== "weekly_scoped")
6322
6384
  return null;
@@ -6374,14 +6436,27 @@ async function callAnthropic(token, fetchImpl, signal) {
6374
6436
  },
6375
6437
  signal: signal ?? AbortSignal.timeout(1e4)
6376
6438
  });
6377
- if (!res.ok)
6378
- return { __status: res.status };
6439
+ if (!res.ok) {
6440
+ return {
6441
+ __status: res.status,
6442
+ retryAfterMs: parseRetryAfterMs(res.headers.get("retry-after"))
6443
+ };
6444
+ }
6379
6445
  return await res.json();
6380
6446
  }
6381
6447
  var _testOverride = null;
6382
6448
  async function fetchOAuthUsage(opts) {
6449
+ return (await fetchOAuthUsageResult(opts)).snapshot;
6450
+ }
6451
+ function missingReason(cacheKey2) {
6452
+ const until = rateLimitedUntilByProfile.get(cacheKey2);
6453
+ return until !== undefined && Date.now() < until ? "rate_limited" : "no_token";
6454
+ }
6455
+ async function fetchOAuthUsageResult(opts) {
6383
6456
  if (_testOverride && !opts?.fetchImpl && !opts?.store) {
6384
- return _testOverride(opts);
6457
+ const snapshot = await _testOverride(opts);
6458
+ const error = snapshot ? null : missingReason(opts?.profileId ?? DEFAULT_KEY);
6459
+ return { snapshot, error };
6385
6460
  }
6386
6461
  return fetchOAuthUsageImpl(opts);
6387
6462
  }
@@ -6389,30 +6464,37 @@ async function fetchOAuthUsageImpl(opts) {
6389
6464
  const ttl = opts?.ttlMs ?? CACHE_TTL_MS_DEFAULT;
6390
6465
  const cacheKey2 = opts?.profileId ?? DEFAULT_KEY;
6391
6466
  const fetchImpl = opts?.fetchImpl ?? globalThis.fetch;
6467
+ const staleMaxMs = opts?.staleMaxMs ?? STALE_MAX_MS_DEFAULT;
6468
+ const staleOr = (reason, error) => {
6469
+ const last = cacheByProfile.get(cacheKey2);
6470
+ if (last && Date.now() - last.fetchedAt < staleMaxMs) {
6471
+ claudeLog("oauth_usage.serving_stale", { profile: cacheKey2, reason, ageMs: Date.now() - last.fetchedAt });
6472
+ return { snapshot: { ...last, stale: true }, error: null };
6473
+ }
6474
+ return { snapshot: null, error };
6475
+ };
6392
6476
  if (!opts?.force) {
6393
6477
  const cached = cacheByProfile.get(cacheKey2);
6394
6478
  if (cached && Date.now() - cached.fetchedAt < ttl)
6395
- return cached;
6479
+ return { snapshot: cached, error: null };
6396
6480
  }
6397
6481
  const existing = inflightByProfile.get(cacheKey2);
6398
6482
  if (existing)
6399
6483
  return existing;
6484
+ const rateLimitedUntil = rateLimitedUntilByProfile.get(cacheKey2);
6485
+ if (rateLimitedUntil !== undefined) {
6486
+ if (Date.now() < rateLimitedUntil)
6487
+ return staleOr("rate_limited", "rate_limited");
6488
+ rateLimitedUntilByProfile.delete(cacheKey2);
6489
+ }
6400
6490
  const store = opts?.store ?? createPlatformCredentialStore({ claudeConfigDir: opts?.claudeConfigDir });
6401
- const staleMaxMs = opts?.staleMaxMs ?? STALE_MAX_MS_DEFAULT;
6402
- const staleOr = (reason) => {
6403
- const last = cacheByProfile.get(cacheKey2);
6404
- if (last && Date.now() - last.fetchedAt < staleMaxMs) {
6405
- claudeLog("oauth_usage.serving_stale", { profile: cacheKey2, reason, ageMs: Date.now() - last.fetchedAt });
6406
- return { ...last, stale: true };
6407
- }
6408
- return null;
6409
- };
6491
+ const rateLimitBackoffMs = opts?.rateLimitBackoffMs ?? RATE_LIMIT_BACKOFF_MS_DEFAULT;
6410
6492
  const promise = (async () => {
6411
6493
  try {
6412
6494
  const token = await readAccessToken(store);
6413
6495
  if (!token) {
6414
6496
  claudeLog("oauth_usage.no_token", { profile: cacheKey2 });
6415
- return staleOr("no_token");
6497
+ return staleOr("no_token", "no_token");
6416
6498
  }
6417
6499
  let result = await callAnthropic(token, fetchImpl);
6418
6500
  if ("__status" in result && result.__status === 401) {
@@ -6420,23 +6502,28 @@ async function fetchOAuthUsageImpl(opts) {
6420
6502
  const refreshed = await refreshOAuthToken(store);
6421
6503
  if (!refreshed) {
6422
6504
  claudeLog("oauth_usage.refresh_failed", { profile: cacheKey2 });
6423
- return staleOr("refresh_failed");
6505
+ return staleOr("refresh_failed", "upstream_error");
6424
6506
  }
6425
6507
  const newToken = await readAccessToken(store);
6426
6508
  if (!newToken)
6427
- return staleOr("no_token_after_refresh");
6509
+ return staleOr("no_token_after_refresh", "no_token");
6428
6510
  result = await callAnthropic(newToken, fetchImpl);
6429
6511
  }
6430
6512
  if ("__status" in result) {
6513
+ if (result.__status === 429) {
6514
+ const retryAfterMs = Math.min(Math.max(rateLimitBackoffMs, result.retryAfterMs ?? 0), Math.max(staleMaxMs, rateLimitBackoffMs));
6515
+ rateLimitedUntilByProfile.set(cacheKey2, Date.now() + retryAfterMs);
6516
+ }
6431
6517
  claudeLog("oauth_usage.upstream_error", { profile: cacheKey2, status: result.__status });
6432
- return staleOr(`upstream_${result.__status}`);
6518
+ return staleOr(`upstream_${result.__status}`, result.__status === 429 ? "rate_limited" : "upstream_error");
6433
6519
  }
6520
+ rateLimitedUntilByProfile.delete(cacheKey2);
6434
6521
  const snapshot = buildSnapshot(result);
6435
6522
  cacheByProfile.set(cacheKey2, snapshot);
6436
- return snapshot;
6523
+ return { snapshot, error: null };
6437
6524
  } catch (err) {
6438
6525
  claudeLog("oauth_usage.fetch_failed", { profile: cacheKey2, error: err instanceof Error ? err.message : String(err) });
6439
- return staleOr("exception");
6526
+ return staleOr("exception", "upstream_error");
6440
6527
  } finally {
6441
6528
  inflightByProfile.delete(cacheKey2);
6442
6529
  }
@@ -10715,6 +10802,31 @@ function shouldEarlyStop(tracker) {
10715
10802
  tracker.fired = true;
10716
10803
  return true;
10717
10804
  }
10805
+ function clientAbortDisposition(input) {
10806
+ if (input.isIndependentSession || !input.profileSessionId)
10807
+ return { action: "none" };
10808
+ if (!input.passthrough)
10809
+ return { action: "evict" };
10810
+ if (input.currentSessionId && !input.sawDuplicateToolUse && input.resumeBoundaryUuid) {
10811
+ return { action: "store", resumeUuid: input.resumeBoundaryUuid };
10812
+ }
10813
+ return { action: "evict" };
10814
+ }
10815
+ function resumeBoundaryUuid(message) {
10816
+ const m = message;
10817
+ if (m?.type !== "user")
10818
+ return;
10819
+ if (typeof m.uuid !== "string" || m.uuid.length === 0)
10820
+ return;
10821
+ const content = m.message?.content;
10822
+ if (!Array.isArray(content))
10823
+ return;
10824
+ const hasResult = content.some((block) => {
10825
+ const b = block;
10826
+ return b?.type === "tool_result";
10827
+ });
10828
+ return hasResult ? m.uuid : undefined;
10829
+ }
10718
10830
 
10719
10831
  // src/proxy/envelopeIntegrity.ts
10720
10832
  function checkEmptyToolInputs(contentBlocks, tools) {
@@ -10755,6 +10867,68 @@ function checkUndeliveredToolUses(captured, deliveredIds) {
10755
10867
  return violations;
10756
10868
  }
10757
10869
 
10870
+ // src/proxy/turnOutcome.ts
10871
+ function classifyTurnOutcome(input) {
10872
+ if (input.toolUses > 0)
10873
+ return { kind: "productive" };
10874
+ if (input.textEvents > 0)
10875
+ return { kind: "productive" };
10876
+ return {
10877
+ kind: "silent",
10878
+ reason: input.blocksForwarded > 0 ? "no_actionable_content" : "no_blocks"
10879
+ };
10880
+ }
10881
+ var SILENT_TURN_NUDGE = "Your previous turn produced no visible output — no text and no tool call — so the client received " + "nothing to act on. Any earlier instruction to end your turn without further text applied only to " + "that turn and is now discharged. Answer now, in text, addressing the most recent request and any " + "tool results above it. If a tool call is still required, make it.";
10882
+ function shouldInjectSilentTurn(input) {
10883
+ if (!input.raw)
10884
+ return false;
10885
+ if (input.raw === "1")
10886
+ return true;
10887
+ return Boolean(input.sessionId && input.raw === input.sessionId);
10888
+ }
10889
+ function createRecoveryLifter(allocateBlockIndex) {
10890
+ let blockIndex;
10891
+ return {
10892
+ lift(innerEvent) {
10893
+ const inner = innerEvent;
10894
+ if (!inner)
10895
+ return;
10896
+ if (inner.type === "content_block_start" && inner.content_block?.type === "text") {
10897
+ blockIndex = allocateBlockIndex();
10898
+ return {
10899
+ kind: "block_start",
10900
+ frame: { type: "content_block_start", index: blockIndex, content_block: { type: "text", text: "" } }
10901
+ };
10902
+ }
10903
+ if (inner.type === "content_block_delta" && inner.delta?.type === "text_delta" && blockIndex !== undefined) {
10904
+ const text = inner.delta.text;
10905
+ return {
10906
+ kind: "text_delta",
10907
+ frame: { type: "content_block_delta", index: blockIndex, delta: { type: "text_delta", text } },
10908
+ textChars: typeof text === "string" ? text.length : 0
10909
+ };
10910
+ }
10911
+ if (inner.type === "content_block_stop" && blockIndex !== undefined) {
10912
+ const index = blockIndex;
10913
+ blockIndex = undefined;
10914
+ return { kind: "block_stop", frame: { type: "content_block_stop", index } };
10915
+ }
10916
+ return;
10917
+ }
10918
+ };
10919
+ }
10920
+ function shouldAttemptRecovery(input) {
10921
+ if (!input.enabled)
10922
+ return false;
10923
+ if (input.outcome.kind === "productive")
10924
+ return false;
10925
+ if (input.alreadyAttempted)
10926
+ return false;
10927
+ if (input.clientGone)
10928
+ return false;
10929
+ return Boolean(input.sessionId);
10930
+ }
10931
+
10758
10932
  // src/proxy/server.ts
10759
10933
  init_agentMatch();
10760
10934
 
@@ -11780,6 +11954,7 @@ function extendedContextHint(model) {
11780
11954
  return advise("MERIDIAN_SONNET_MODEL=sonnet");
11781
11955
  return advise("MERIDIAN_1M_CONTEXT_SUPPORT=0");
11782
11956
  }
11957
+ var HIT_YOUR_LIMIT = /hit your (?:[\w-]+ )?limit/;
11783
11958
  function classifyError(errMsg, model) {
11784
11959
  const lower = errMsg.toLowerCase();
11785
11960
  if (lower.includes("oauth token has expired") || lower.includes("not logged in")) {
@@ -11796,7 +11971,7 @@ function classifyError(errMsg, model) {
11796
11971
  message: "Claude authentication expired or invalid. Run 'claude login' in your terminal to re-authenticate, then restart the proxy."
11797
11972
  };
11798
11973
  }
11799
- if (lower.includes("429") || lower.includes("rate limit") || lower.includes("too many requests") || lower.includes("hit your session limit") || lower.includes("usage limit reached")) {
11974
+ if (lower.includes("429") || lower.includes("rate limit") || lower.includes("too many requests") || HIT_YOUR_LIMIT.test(lower) || lower.includes("usage limit reached")) {
11800
11975
  const hint = lower.includes("1m") || lower.includes("context") ? extendedContextHint(model) : "";
11801
11976
  return {
11802
11977
  status: 429,
@@ -12279,7 +12454,7 @@ ${c.text}
12279
12454
  return "";
12280
12455
  }).filter(Boolean).join("");
12281
12456
  }
12282
- function translateOpenAiToAnthropic(body) {
12457
+ function translateOpenAiToAnthropic(body, options = {}) {
12283
12458
  const messages = body.messages ?? [];
12284
12459
  if (messages.length === 0)
12285
12460
  return null;
@@ -12371,7 +12546,7 @@ function translateOpenAiToAnthropic(body) {
12371
12546
  let systemPrompt = systemParts.join(`
12372
12547
  `);
12373
12548
  let messagesToSend = turns;
12374
- if (turns.length > 1) {
12549
+ if (turns.length > 1 && !options.preserveConversationHistory) {
12375
12550
  const history = turns.slice(0, -1).map((m) => `${m.role}: ${summarizeAnthropicContent(m.content)}`).join(`
12376
12551
  `);
12377
12552
  const historyBlock = `<conversation_history>
@@ -12666,6 +12841,9 @@ function buildModelList(isMaxSubscription, now = Math.floor(Date.now() / 1000))
12666
12841
  ];
12667
12842
  }
12668
12843
 
12844
+ // src/proxy/server.ts
12845
+ init_jcode();
12846
+
12669
12847
  // src/proxy/openaiResponses.ts
12670
12848
  function itemDiscriminator(item) {
12671
12849
  if (typeof item !== "object" || item === null)
@@ -18858,7 +19036,7 @@ function buildQueryOptions(ctx, abortController) {
18858
19036
  hasDeferredTools,
18859
19037
  resumeSessionId,
18860
19038
  isUndo,
18861
- undoRollbackUuid,
19039
+ resumeSessionAtUuid,
18862
19040
  forkSession,
18863
19041
  sdkHooks,
18864
19042
  blockedTools,
@@ -18929,7 +19107,7 @@ function buildQueryOptions(ctx, abortController) {
18929
19107
  ...Object.keys(sdkAgents).length > 0 ? { agents: sdkAgents } : {},
18930
19108
  ...resumeSessionId ? { resume: resumeSessionId } : {},
18931
19109
  ...isUndo || forkSession ? { forkSession: true } : {},
18932
- ...isUndo && undoRollbackUuid ? { resumeSessionAt: undoRollbackUuid } : {},
19110
+ ...resumeSessionAtUuid ? { resumeSessionAt: resumeSessionAtUuid } : {},
18933
19111
  ...sdkHooks ? { hooks: sdkHooks } : {},
18934
19112
  ...effort ? { effort } : {},
18935
19113
  ...thinking ? { thinking } : {},
@@ -19076,6 +19254,7 @@ var ADAPTER_TRANSFORMS = {
19076
19254
  cherry: cherryTransforms,
19077
19255
  "claude-code": claudeCodeTransforms,
19078
19256
  openai: openCodeTransforms,
19257
+ jcode: openCodeTransforms,
19079
19258
  codex: [...openCodeTransforms, ...codexTransforms]
19080
19259
  };
19081
19260
  function getAdapterTransforms(adapterName) {
@@ -19088,7 +19267,7 @@ import { join as join5, isAbsolute as isAbsolute2, extname } from "path";
19088
19267
  import { pathToFileURL } from "url";
19089
19268
 
19090
19269
  // src/proxy/plugins/validation.ts
19091
- var KNOWN_ADAPTERS = ["opencode", "openai", "crush", "droid", "pi", "forgecode", "passthrough"];
19270
+ var KNOWN_ADAPTERS = ["opencode", "openai", "jcode", "crush", "droid", "pi", "forgecode", "passthrough"];
19092
19271
  var KNOWN_HOOKS = ["onRequest", "onResponse", "onTelemetry", "onSession", "onToolUse", "onToolResult", "onError"];
19093
19272
  function validateTransform(exported) {
19094
19273
  if (exported == null || typeof exported !== "object") {
@@ -19448,6 +19627,19 @@ function computeMessageHashes(messages) {
19448
19627
  return [];
19449
19628
  return messages.map(hashMessage);
19450
19629
  }
19630
+ function hashNormalizedContent(content) {
19631
+ return createHash2("sha256").update(normalizeContent(content)).digest("hex").slice(0, 32);
19632
+ }
19633
+ function hashableContentBlocks(content) {
19634
+ if (!Array.isArray(content))
19635
+ return [content];
19636
+ return content.filter((block) => !HASH_IGNORED_BLOCK_TYPES.has(block?.type));
19637
+ }
19638
+ function computeMessageBlockHashes(messages) {
19639
+ if (!messages || messages.length === 0)
19640
+ return [];
19641
+ return messages.map((message) => hashableContentBlocks(message.content).map((block) => hashNormalizedContent(Array.isArray(message.content) ? [block] : block)));
19642
+ }
19451
19643
  function measurePrefixOverlap(storedHashes, incomingHashes) {
19452
19644
  let overlap = 0;
19453
19645
  const minLen = Math.min(storedHashes.length, incomingHashes.length);
@@ -19530,6 +19722,34 @@ function verifyLineage(cached, messages) {
19530
19722
  suffixOverlap
19531
19723
  };
19532
19724
  }
19725
+ const boundary = cached.messageCount - 1;
19726
+ if (boundary >= 0 && prefixOverlap === boundary && messages.length >= cached.messageCount && cached.messageBlockHashes?.length === cached.messageCount) {
19727
+ const incomingBoundary = messages[boundary];
19728
+ const storedBlocks = cached.messageBlockHashes[boundary];
19729
+ if (incomingBoundary?.role === "user" && storedBlocks && Array.isArray(incomingBoundary.content)) {
19730
+ const incomingBlocks = hashableContentBlocks(incomingBoundary.content);
19731
+ const incomingBlockHashes = incomingBlocks.map((block) => hashNormalizedContent([block]));
19732
+ const preservesStoredBlocks = incomingBlocks.length === incomingBoundary.content.length && incomingBlockHashes.length > storedBlocks.length && storedBlocks.every((hash, index) => incomingBlockHashes[index] === hash);
19733
+ const appendedBlocks = incomingBlocks.slice(storedBlocks.length);
19734
+ const seenToolResultIds = new Set(incomingBlocks.slice(0, storedBlocks.length).filter((block) => block?.type === "tool_result" && typeof block.tool_use_id === "string").map((block) => block.tool_use_id));
19735
+ const hasOnlyNewToolResults = appendedBlocks.every((block) => {
19736
+ if (block?.type !== "tool_result" || typeof block.tool_use_id !== "string")
19737
+ return false;
19738
+ if (seenToolResultIds.has(block.tool_use_id))
19739
+ return false;
19740
+ seenToolResultIds.add(block.tool_use_id);
19741
+ return true;
19742
+ });
19743
+ if (preservesStoredBlocks && hasOnlyNewToolResults) {
19744
+ return {
19745
+ type: "continuation",
19746
+ session: cached,
19747
+ resumeFrom: boundary,
19748
+ resumeContentFrom: storedBlocks.length
19749
+ };
19750
+ }
19751
+ }
19752
+ }
19533
19753
  if (prefixOverlap > 0 && suffixOverlap === 0 && messages.length <= cached.messageCount) {
19534
19754
  let rollbackUuid;
19535
19755
  if (cached.sdkMessageUuids) {
@@ -19676,7 +19896,7 @@ function lookupSharedSessionByClaudeId(claudeSessionId) {
19676
19896
  }
19677
19897
  return newest;
19678
19898
  }
19679
- function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage) {
19899
+ function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes, passthroughResumeUuid) {
19680
19900
  const path3 = getStorePath();
19681
19901
  const lockPath = `${path3}.lock`;
19682
19902
  const hasLock = skipLocking ? false : acquireLock(lockPath);
@@ -19694,7 +19914,9 @@ function storeSharedSession(key, claudeSessionId, messageCount, lineageHash, mes
19694
19914
  messageCount: messageCount ?? existing?.messageCount ?? 0,
19695
19915
  lineageHash: lineageHash ?? existing?.lineageHash,
19696
19916
  messageHashes: messageHashes ?? existing?.messageHashes,
19917
+ messageBlockHashes: messageBlockHashes ?? existing?.messageBlockHashes,
19697
19918
  sdkMessageUuids: sdkMessageUuids ?? existing?.sdkMessageUuids,
19919
+ passthroughResumeUuid: passthroughResumeUuid === undefined ? existing?.passthroughResumeUuid : passthroughResumeUuid ?? undefined,
19698
19920
  contextUsage: contextUsage ?? existing?.contextUsage,
19699
19921
  ...previousClaudeSessionId ? { previousClaudeSessionId } : {}
19700
19922
  };
@@ -19852,7 +20074,11 @@ function touchSession(state) {
19852
20074
  }
19853
20075
  function classifyLineage(state, messages, cacheKey2) {
19854
20076
  const result = verifyLineage(state, messages);
19855
- if (result.type === "compaction") {
20077
+ if (result.type === "continuation" && result.resumeContentFrom !== undefined) {
20078
+ const msg = `Parallel tool-result continuation (key=${cacheKey2.slice(0, 8)}…): resume from message ${result.resumeFrom}, content block ${result.resumeContentFrom}.`;
20079
+ console.error(`[PROXY] ${msg}`);
20080
+ diagnosticLog2.lineage(msg);
20081
+ } else if (result.type === "compaction") {
19856
20082
  const msg = `Compaction detected (key=${cacheKey2.slice(0, 8)}…): suffix overlap ${result.suffixOverlap}/${state.messageCount}, resume from incoming message ${result.resumeFrom}.`;
19857
20083
  console.error(`[PROXY] ${msg}`);
19858
20084
  diagnosticLog2.lineage(msg);
@@ -19884,7 +20110,9 @@ function lookupSession(sessionId, messages, workingDirectory) {
19884
20110
  messageCount: shared.messageCount || 0,
19885
20111
  lineageHash: shared.lineageHash || "",
19886
20112
  messageHashes: shared.messageHashes,
20113
+ messageBlockHashes: shared.messageBlockHashes,
19887
20114
  sdkMessageUuids: shared.sdkMessageUuids,
20115
+ passthroughResumeUuid: shared.passthroughResumeUuid,
19888
20116
  contextUsage: shared.contextUsage
19889
20117
  };
19890
20118
  const result = classifyLineage(state, messages, sessionId);
@@ -19912,7 +20140,9 @@ function lookupSession(sessionId, messages, workingDirectory) {
19912
20140
  messageCount: shared.messageCount || 0,
19913
20141
  lineageHash: shared.lineageHash || "",
19914
20142
  messageHashes: shared.messageHashes,
20143
+ messageBlockHashes: shared.messageBlockHashes,
19915
20144
  sdkMessageUuids: shared.sdkMessageUuids,
20145
+ passthroughResumeUuid: shared.passthroughResumeUuid,
19916
20146
  contextUsage: shared.contextUsage
19917
20147
  };
19918
20148
  const result = classifyLineage(state, messages, fp);
@@ -19945,24 +20175,29 @@ function getSessionByClaudeId(claudeSessionId) {
19945
20175
  messageCount: shared.messageCount || 0,
19946
20176
  lineageHash: shared.lineageHash || "",
19947
20177
  messageHashes: shared.messageHashes,
20178
+ messageBlockHashes: shared.messageBlockHashes,
19948
20179
  sdkMessageUuids: shared.sdkMessageUuids,
20180
+ passthroughResumeUuid: shared.passthroughResumeUuid,
19949
20181
  contextUsage: shared.contextUsage
19950
20182
  });
19951
20183
  }
19952
20184
  return newest;
19953
20185
  }
19954
- function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sdkMessageUuids, contextUsage) {
20186
+ function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sdkMessageUuids, contextUsage, passthroughResumeUuid) {
19955
20187
  if (!claudeSessionId)
19956
20188
  return;
19957
20189
  const lineageHash = computeLineageHash(messages);
19958
20190
  const messageHashes = computeMessageHashes(messages);
20191
+ const messageBlockHashes = computeMessageBlockHashes(messages);
19959
20192
  const state = {
19960
20193
  claudeSessionId,
19961
20194
  lastAccess: Date.now(),
19962
20195
  messageCount: messages?.length || 0,
19963
20196
  lineageHash,
19964
20197
  messageHashes,
20198
+ messageBlockHashes,
19965
20199
  sdkMessageUuids,
20200
+ ...passthroughResumeUuid ? { passthroughResumeUuid } : {},
19966
20201
  ...contextUsage ? { contextUsage } : {}
19967
20202
  };
19968
20203
  if (sessionId)
@@ -19972,14 +20207,14 @@ function storeSession(sessionId, messages, claudeSessionId, workingDirectory, sd
19972
20207
  fingerprintCache.set(fp, state);
19973
20208
  const key = sessionId || fp;
19974
20209
  if (key) {
19975
- storeSharedSession(key, claudeSessionId, state.messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage);
20210
+ storeSharedSession(key, claudeSessionId, state.messageCount, lineageHash, messageHashes, sdkMessageUuids, contextUsage, messageBlockHashes, passthroughResumeUuid ?? null);
19976
20211
  }
19977
20212
  }
19978
20213
 
19979
20214
  // src/proxy/server.ts
19980
20215
  var exec2 = promisify3(execCallback);
19981
20216
  var claudeExecutable = "";
19982
- var UPSTREAM_IDLE_MS = 90000;
20217
+ var UPSTREAM_IDLE_MS = envInt("UPSTREAM_IDLE_MS", 90000);
19983
20218
  function credentialStoreForProfile(profile) {
19984
20219
  if (profile.type !== "claude-max")
19985
20220
  return;
@@ -20566,8 +20801,11 @@ data: ${JSON.stringify(lastError)}
20566
20801
  const isUndo = lineageResult.type === "undo";
20567
20802
  const cachedSession = lineageResult.type !== "diverged" ? lineageResult.session : undefined;
20568
20803
  const resumeSessionId = cachedSession?.claudeSessionId;
20804
+ const passthrough = adapter.instancePassthrough !== undefined ? adapter.instancePassthrough : pipelineCtx.passthrough !== undefined ? pipelineCtx.passthrough : envBool("PASSTHROUGH");
20569
20805
  const resumeFrom = lineageResult.type === "continuation" || lineageResult.type === "compaction" ? lineageResult.resumeFrom : undefined;
20806
+ const resumeContentFrom = lineageResult.type === "continuation" ? lineageResult.resumeContentFrom : undefined;
20570
20807
  const undoRollbackUuid = isUndo && lineageResult.type === "undo" ? lineageResult.rollbackUuid : undefined;
20808
+ const passthroughResumeUuid = passthrough && isResume ? cachedSession?.passthroughResumeUuid : undefined;
20571
20809
  const msgSummary = body.messages?.map((m) => {
20572
20810
  const contentTypes = Array.isArray(m.content) ? m.content.map((b) => b.type).join(",") : "string";
20573
20811
  return `${m.role}[${contentTypes}]`;
@@ -20610,7 +20848,16 @@ data: ${JSON.stringify(lastError)}
20610
20848
  if (isUndo && undoRollbackUuid) {
20611
20849
  messagesToConvert = getLastUserMessage(allMessages);
20612
20850
  } else if (isResume) {
20613
- if (resumeFrom !== undefined && resumeFrom < allMessages.length) {
20851
+ if (resumeFrom !== undefined && resumeContentFrom !== undefined && resumeFrom < allMessages.length && Array.isArray(allMessages[resumeFrom]?.content)) {
20852
+ const boundaryMessage = allMessages[resumeFrom];
20853
+ messagesToConvert = [
20854
+ {
20855
+ ...boundaryMessage,
20856
+ content: boundaryMessage.content.slice(resumeContentFrom)
20857
+ },
20858
+ ...allMessages.slice(resumeFrom + 1)
20859
+ ];
20860
+ } else if (resumeFrom !== undefined && resumeFrom < allMessages.length) {
20614
20861
  messagesToConvert = allMessages.slice(resumeFrom);
20615
20862
  } else {
20616
20863
  messagesToConvert = getLastUserMessage(allMessages);
@@ -20659,6 +20906,13 @@ data: ${JSON.stringify(lastError)}
20659
20906
  if (structuredMessages.length > 1) {
20660
20907
  structuredMessages = consolidateMultimodalOntoLastUser(structuredMessages);
20661
20908
  }
20909
+ if (passthroughResumeUuid && structuredMessages.length > 0) {
20910
+ structuredMessages.unshift({
20911
+ type: "user",
20912
+ message: { role: "user", content: PASSTHROUGH_CONTINUATION_LEAD_IN },
20913
+ parent_tool_use_id: null
20914
+ });
20915
+ }
20662
20916
  } else {
20663
20917
  const toolIndex = buildToolUseIndex(allMessages ?? messagesToConvert ?? []);
20664
20918
  const promptTurns = (messagesToConvert ?? []).map((m) => {
@@ -20670,11 +20924,11 @@ data: ${JSON.stringify(lastError)}
20670
20924
  }
20671
20925
  return { role: "user", text: flattenUserContent(m.content, sanitizeOpts, toolIndex) };
20672
20926
  });
20673
- textPrompt = isResume ? promptTurns.map((t) => t.text).filter(Boolean).join(`
20927
+ const resumeDelta = promptTurns.map((t) => t.text).filter(Boolean).join(`
20674
20928
 
20675
- `) || "" : frameReplayTurns(promptTurns);
20929
+ `) || "";
20930
+ textPrompt = isResume ? passthroughResumeUuid ? framePassthroughContinuation(resumeDelta) : resumeDelta : frameReplayTurns(promptTurns);
20676
20931
  }
20677
- const passthrough = adapter.instancePassthrough !== undefined ? adapter.instancePassthrough : pipelineCtx.passthrough !== undefined ? pipelineCtx.passthrough : envBool("PASSTHROUGH");
20678
20932
  const settingSources = envBool("LOAD_CONTEXT") || sdkFeatures.claudeMd === "full" ? ["user", "project"] : sdkFeatures.claudeMd === "project" ? ["project"] : pipelineCtx.settingSources ?? [];
20679
20933
  const capturedToolUses = [];
20680
20934
  const capturedSignatures = new Set;
@@ -20842,6 +21096,7 @@ data: ${JSON.stringify(lastError)}
20842
21096
  claudeLog("upstream.start", { mode: "non_stream", model });
20843
21097
  let lastUsage;
20844
21098
  let lastStopReason;
21099
+ let nextPassthroughResumeUuid;
20845
21100
  try {
20846
21101
  if (!claudeExecutable) {
20847
21102
  claudeExecutable = await resolveClaudeExecutableAsync();
@@ -20878,8 +21133,8 @@ data: ${JSON.stringify(lastError)}
20878
21133
  hasDeferredTools,
20879
21134
  resumeSessionId,
20880
21135
  isUndo,
20881
- undoRollbackUuid,
20882
- forkSession: busySessionFork || undefined,
21136
+ resumeSessionAtUuid: undoRollbackUuid ?? passthroughResumeUuid,
21137
+ forkSession: busySessionFork || Boolean(passthroughResumeUuid) || undefined,
20883
21138
  sdkHooks,
20884
21139
  blockedTools: pipelineCtx.blockedTools,
20885
21140
  incompatibleTools: pipelineCtx.incompatibleTools,
@@ -20962,7 +21217,7 @@ data: ${JSON.stringify(lastError)}
20962
21217
  hasDeferredTools,
20963
21218
  resumeSessionId: undefined,
20964
21219
  isUndo: false,
20965
- undoRollbackUuid: undefined,
21220
+ resumeSessionAtUuid: undefined,
20966
21221
  sdkHooks,
20967
21222
  blockedTools: pipelineCtx.blockedTools,
20968
21223
  incompatibleTools: pipelineCtx.incompatibleTools,
@@ -21031,7 +21286,7 @@ data: ${JSON.stringify(lastError)}
21031
21286
  hasDeferredTools,
21032
21287
  resumeSessionId: undefined,
21033
21288
  isUndo: false,
21034
- undoRollbackUuid: undefined,
21289
+ resumeSessionAtUuid: undefined,
21035
21290
  sdkHooks,
21036
21291
  blockedTools: pipelineCtx.blockedTools,
21037
21292
  incompatibleTools: pipelineCtx.incompatibleTools,
@@ -21112,6 +21367,7 @@ data: ${JSON.stringify(lastError)}
21112
21367
  if (message.type === "assistant") {
21113
21368
  noteAssistantContent(earlyStop, message.message?.content);
21114
21369
  } else if (message.type === "user") {
21370
+ nextPassthroughResumeUuid = resumeBoundaryUuid(message) ?? nextPassthroughResumeUuid;
21115
21371
  noteUserContent(earlyStop, message.message?.content);
21116
21372
  if (shouldEarlyStop(earlyStop)) {
21117
21373
  earlyStopFired = true;
@@ -21351,7 +21607,7 @@ Subprocess stderr: ${stderrOutput}`;
21351
21607
  ]);
21352
21608
  }
21353
21609
  if (currentSessionId && !isIndependentSession && !sawDuplicateToolUse) {
21354
- storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage);
21610
+ storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, earlyStopFired ? nextPassthroughResumeUuid : null);
21355
21611
  }
21356
21612
  const responseSessionId = currentSessionId || resumeSessionId || `session_${Date.now()}`;
21357
21613
  return new Response(JSON.stringify({
@@ -21383,6 +21639,7 @@ Subprocess stderr: ${stderrOutput}`;
21383
21639
  let streamEventsSeen = 0;
21384
21640
  let eventsForwarded = 0;
21385
21641
  let textEventsForwarded = 0;
21642
+ let textCharsForwarded = 0;
21386
21643
  let bytesSent = 0;
21387
21644
  let streamClosed = false;
21388
21645
  let awaitingEarlyStopDrain = false;
@@ -21414,7 +21671,30 @@ Subprocess stderr: ${stderrOutput}`;
21414
21671
  let lastUsage;
21415
21672
  let hasStructuredOutput = false;
21416
21673
  let structuredOutput;
21674
+ let nextPassthroughResumeUuid;
21675
+ const silentTurnRecoveryEnabled = env("SILENT_TURN_RECOVERY") !== "0";
21676
+ let silentTurnRecoveryAttempted = false;
21677
+ let silentTurnRecovered = false;
21417
21678
  const streamedToolUseIds = new Set;
21679
+ let pendingTerminalDelta = null;
21680
+ let terminalDeltaSent = false;
21681
+ const sendTerminalDelta = (stopReasonOverride) => {
21682
+ if (terminalDeltaSent)
21683
+ return;
21684
+ const payload = stopReasonOverride ? encoder.encode(`event: message_delta
21685
+ data: ${JSON.stringify({
21686
+ type: "message_delta",
21687
+ delta: { stop_reason: stopReasonOverride, stop_sequence: null },
21688
+ usage: { output_tokens: lastUsage?.output_tokens ?? 0 }
21689
+ })}
21690
+
21691
+ `) : pendingTerminalDelta;
21692
+ if (!payload)
21693
+ return;
21694
+ terminalDeltaSent = true;
21695
+ if (safeEnqueue(payload, "terminal_message_delta"))
21696
+ eventsForwarded += 1;
21697
+ };
21418
21698
  const openClientBlocks = new Set;
21419
21699
  const resolvePendingStore = passthrough && earlyStopEnabled && !isIndependentSession && profileSessionId ? registerPendingStore(profileSessionId) : () => {};
21420
21700
  let pendingEarlyStop = false;
@@ -21430,10 +21710,7 @@ Subprocess stderr: ${stderrOutput}`;
21430
21710
  });
21431
21711
  pendingEarlyStop = false;
21432
21712
  flushOpenClientBlocks("early_stop");
21433
- safeEnqueue(encoder.encode(`event: message_delta
21434
- data: ${JSON.stringify({ type: "message_delta", delta: { stop_reason: "tool_use", stop_sequence: null }, usage: { output_tokens: lastUsage?.output_tokens ?? 0 } })}
21435
-
21436
- `), "early_stop");
21713
+ sendTerminalDelta("tool_use");
21437
21714
  safeEnqueue(encoder.encode(`event: message_stop
21438
21715
  data: ${JSON.stringify({ type: "message_stop" })}
21439
21716
 
@@ -21463,8 +21740,8 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
21463
21740
  }
21464
21741
  openClientBlocks.clear();
21465
21742
  };
21743
+ let currentSessionId;
21466
21744
  try {
21467
- let currentSessionId;
21468
21745
  const MAX_RATE_LIMIT_RETRIES = 2;
21469
21746
  const RATE_LIMIT_BASE_DELAY_MS = 1000;
21470
21747
  const response = async function* () {
@@ -21496,8 +21773,8 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
21496
21773
  hasDeferredTools,
21497
21774
  resumeSessionId,
21498
21775
  isUndo,
21499
- undoRollbackUuid,
21500
- forkSession: busySessionFork || undefined,
21776
+ resumeSessionAtUuid: undoRollbackUuid ?? passthroughResumeUuid,
21777
+ forkSession: busySessionFork || Boolean(passthroughResumeUuid) || undefined,
21501
21778
  sdkHooks,
21502
21779
  blockedTools: pipelineCtx.blockedTools,
21503
21780
  incompatibleTools: pipelineCtx.incompatibleTools,
@@ -21579,7 +21856,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
21579
21856
  hasDeferredTools,
21580
21857
  resumeSessionId: undefined,
21581
21858
  isUndo: false,
21582
- undoRollbackUuid: undefined,
21859
+ resumeSessionAtUuid: undefined,
21583
21860
  sdkHooks,
21584
21861
  blockedTools: pipelineCtx.blockedTools,
21585
21862
  incompatibleTools: pipelineCtx.incompatibleTools,
@@ -21648,7 +21925,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
21648
21925
  hasDeferredTools,
21649
21926
  resumeSessionId: undefined,
21650
21927
  isUndo: false,
21651
- undoRollbackUuid: undefined,
21928
+ resumeSessionAtUuid: undefined,
21652
21929
  sdkHooks,
21653
21930
  blockedTools: pipelineCtx.blockedTools,
21654
21931
  incompatibleTools: pipelineCtx.incompatibleTools,
@@ -21761,6 +22038,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
21761
22038
  if (message.type === "assistant" && message.uuid) {
21762
22039
  sdkUuidMap.push(message.uuid);
21763
22040
  }
22041
+ nextPassthroughResumeUuid = resumeBoundaryUuid(message) ?? nextPassthroughResumeUuid;
21764
22042
  if (earlyStopEnabled) {
21765
22043
  if (message.type === "assistant") {
21766
22044
  noteAssistantContent(earlyStop, message.message?.content);
@@ -21832,10 +22110,7 @@ data: ${JSON.stringify({ type: "content_block_stop", index: idx })}
21832
22110
  if (messageStartEmitted) {
21833
22111
  if (passthrough && streamedToolUseIds.size > 0) {
21834
22112
  flushOpenClientBlocks("turn2_suppression");
21835
- safeEnqueue(encoder.encode(`event: message_delta
21836
- data: ${JSON.stringify({ type: "message_delta", delta: { stop_reason: "tool_use", stop_sequence: null }, usage: { output_tokens: lastUsage?.output_tokens ?? 0 } })}
21837
-
21838
- `), "passthrough_turn2_stop");
22113
+ sendTerminalDelta("tool_use");
21839
22114
  safeEnqueue(encoder.encode(`event: message_stop
21840
22115
  data: ${JSON.stringify({ type: "message_stop" })}
21841
22116
 
@@ -21939,15 +22214,26 @@ data: ${JSON.stringify({
21939
22214
  }
21940
22215
  }
21941
22216
  }
22217
+ if (eventType === "content_block_delta" && event.delta?.type === "text_delta" && shouldInjectSilentTurn({
22218
+ raw: env("DEBUG_FORCE_SILENT_TURN"),
22219
+ sessionId: agentSessionId
22220
+ })) {
22221
+ claudeLog("debug.silent_turn_injected", { sessionId: agentSessionId });
22222
+ continue;
22223
+ }
21942
22224
  stripNonStandardStreamFields(event);
21943
22225
  const payload = encoder.encode(`event: ${eventType}
21944
22226
  data: ${JSON.stringify(event)}
21945
22227
 
21946
22228
  `);
21947
- if (!safeEnqueue(payload, `stream_event:${eventType}`)) {
21948
- break;
22229
+ if (eventType === "message_delta") {
22230
+ pendingTerminalDelta = payload;
22231
+ } else {
22232
+ if (!safeEnqueue(payload, `stream_event:${eventType}`)) {
22233
+ break;
22234
+ }
22235
+ eventsForwarded += 1;
21949
22236
  }
21950
- eventsForwarded += 1;
21951
22237
  if (eventType === "content_block_start") {
21952
22238
  const idx = event.index;
21953
22239
  if (typeof idx === "number")
@@ -21963,6 +22249,7 @@ data: ${JSON.stringify(event)}
21963
22249
  }
21964
22250
  if (passthrough && eventType === "message_delta" && event.delta?.stop_reason === "tool_use" && streamedToolUseIds.size > 0) {
21965
22251
  flushOpenClientBlocks("drain_close");
22252
+ sendTerminalDelta();
21966
22253
  safeEnqueue(encoder.encode(`event: message_stop
21967
22254
  data: ${JSON.stringify({ type: "message_stop" })}
21968
22255
 
@@ -21979,6 +22266,8 @@ data: ${JSON.stringify({ type: "message_stop" })}
21979
22266
  const delta = event.delta;
21980
22267
  if (delta?.type === "text_delta") {
21981
22268
  textEventsForwarded += 1;
22269
+ if (typeof delta.text === "string")
22270
+ textCharsForwarded += delta.text.length;
21982
22271
  }
21983
22272
  }
21984
22273
  }
@@ -22040,6 +22329,7 @@ data: ${JSON.stringify({
22040
22329
  messageStartEmitted = true;
22041
22330
  eventsForwarded += 5;
22042
22331
  textEventsForwarded += 1;
22332
+ textCharsForwarded += text.length;
22043
22333
  }
22044
22334
  if (passthrough) {
22045
22335
  recordEnvelopeViolations(checkUndeliveredToolUses(capturedToolUses, streamedToolUseIds));
@@ -22065,9 +22355,125 @@ data: ${JSON.stringify({
22065
22355
  plog(`[PROXY] ${requestMeta.requestId} discovered=${discoveredTools.size} (${newNames}) session_total=${allNames.length}`);
22066
22356
  }
22067
22357
  if (currentSessionId && !isIndependentSession && !sawDuplicateToolUse) {
22068
- storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage);
22358
+ storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, earlyStopFired ? nextPassthroughResumeUuid : null);
22069
22359
  }
22070
22360
  resolvePendingStore();
22361
+ const classifyNow = () => classifyTurnOutcome({
22362
+ textEvents: textEventsForwarded,
22363
+ toolUses: streamedToolUseIds.size,
22364
+ blocksForwarded: eventsForwarded
22365
+ });
22366
+ const preRecoveryOutcome = classifyNow();
22367
+ if (!streamClosed && messageStartEmitted && shouldAttemptRecovery({
22368
+ outcome: preRecoveryOutcome,
22369
+ alreadyAttempted: silentTurnRecoveryAttempted,
22370
+ clientGone: streamClosed,
22371
+ sessionId: currentSessionId || resumeSessionId,
22372
+ enabled: silentTurnRecoveryEnabled
22373
+ })) {
22374
+ silentTurnRecoveryAttempted = true;
22375
+ const capturedBeforeRecovery = capturedToolUses.length;
22376
+ claudeLog("response.silent_turn_recovery", {
22377
+ mode: "stream",
22378
+ kind: preRecoveryOutcome.kind,
22379
+ reason: preRecoveryOutcome.kind === "silent" ? preRecoveryOutcome.reason : undefined,
22380
+ sdkSessionId: currentSessionId || resumeSessionId
22381
+ });
22382
+ const recoveryLifter = createRecoveryLifter(() => nextClientBlockIndex++);
22383
+ let recoverySessionId;
22384
+ let recoveryBoundaryUuid;
22385
+ try {
22386
+ for await (const event of guardUpstreamIdle(query(buildQueryOptions({
22387
+ prompt: SILENT_TURN_NUDGE,
22388
+ model,
22389
+ workingDirectory,
22390
+ clientWorkingDirectory,
22391
+ systemContext,
22392
+ claudeExecutable,
22393
+ passthrough,
22394
+ stream: true,
22395
+ sdkAgents,
22396
+ passthroughMcp,
22397
+ cleanEnv: profileEnv,
22398
+ envOverrides,
22399
+ hasDeferredTools,
22400
+ resumeSessionId: currentSessionId || resumeSessionId,
22401
+ isUndo: false,
22402
+ resumeSessionAtUuid: nextPassthroughResumeUuid,
22403
+ forkSession: true,
22404
+ sdkHooks,
22405
+ blockedTools: pipelineCtx.blockedTools,
22406
+ incompatibleTools: pipelineCtx.incompatibleTools,
22407
+ mcpServerName: adapter.getMcpServerName(),
22408
+ allowedMcpTools: pipelineCtx.allowedMcpTools,
22409
+ onStderr,
22410
+ effort,
22411
+ thinking,
22412
+ taskBudget,
22413
+ outputFormat,
22414
+ betas,
22415
+ settingSources,
22416
+ codeSystemPrompt: sdkFeatures.codeSystemPrompt,
22417
+ clientSystemPrompt: sdkFeatures.clientSystemPrompt === false ? false : undefined,
22418
+ memory: sdkFeatures.memory,
22419
+ dreaming: sdkFeatures.dreaming,
22420
+ sharedMemory: sdkFeatures.sharedMemory,
22421
+ webFetchPreflight: sdkFeatures.webFetchPreflight,
22422
+ claudeAiConnectors: sdkFeatures.claudeAiConnectors,
22423
+ maxBudgetUsd: sdkFeatures.maxBudgetUsd,
22424
+ fallbackModel: sdkFeatures.fallbackModel,
22425
+ sdkDebug: sdkFeatures.sdkDebug,
22426
+ additionalDirectories: sdkFeatures.additionalDirectories ? sdkFeatures.additionalDirectories.split(",").map((d) => d.trim()).filter(Boolean) : undefined,
22427
+ advisorModel
22428
+ }, requestAbort.controller)), UPSTREAM_IDLE_MS, (sinceLastMs) => claudeLog("upstream.stalled", { mode: "silent_recovery", model, sinceLastMs }))) {
22429
+ const recoveryMessage = event;
22430
+ if (recoveryMessage.session_id)
22431
+ recoverySessionId = recoveryMessage.session_id;
22432
+ recoveryBoundaryUuid = resumeBoundaryUuid(recoveryMessage) ?? recoveryBoundaryUuid;
22433
+ if (recoveryMessage.type !== "stream_event")
22434
+ continue;
22435
+ const lifted = recoveryLifter.lift(event.event);
22436
+ if (!lifted)
22437
+ continue;
22438
+ safeEnqueue(encoder.encode(`event: ${lifted.frame.type}
22439
+ data: ${JSON.stringify(lifted.frame)}
22440
+
22441
+ `), `silent_recovery_${lifted.kind}`);
22442
+ if (lifted.kind === "block_start") {
22443
+ eventsForwarded += 1;
22444
+ } else if (lifted.kind === "text_delta") {
22445
+ textEventsForwarded += 1;
22446
+ textCharsForwarded += lifted.textChars;
22447
+ silentTurnRecovered = true;
22448
+ }
22449
+ }
22450
+ } catch (recoveryError) {
22451
+ claudeLog("response.silent_turn_recovery_failed", {
22452
+ mode: "stream",
22453
+ error: recoveryError instanceof Error ? recoveryError.message : String(recoveryError)
22454
+ });
22455
+ }
22456
+ if (capturedToolUses.length > capturedBeforeRecovery) {
22457
+ silentTurnRecovered = true;
22458
+ }
22459
+ if (silentTurnRecovered && recoverySessionId && !isIndependentSession && !sawDuplicateToolUse) {
22460
+ currentSessionId = recoverySessionId;
22461
+ nextPassthroughResumeUuid = recoveryBoundaryUuid;
22462
+ sdkUuidMap.length = 0;
22463
+ for (let i = 0;i < allMessages.length; i++)
22464
+ sdkUuidMap.push(null);
22465
+ storeSession(profileSessionId, body.messages || [], recoverySessionId, profileScopedCwd, sdkUuidMap, lastUsage, recoveryBoundaryUuid ?? null);
22466
+ }
22467
+ claudeLog("response.silent_turn_recovery_result", {
22468
+ mode: "stream",
22469
+ recovered: silentTurnRecovered,
22470
+ textEvents: textEventsForwarded,
22471
+ forkedSession: recoverySessionId ?? null
22472
+ });
22473
+ if (silentTurnRecovered && preRecoveryOutcome.kind === "silent") {
22474
+ diagnosticLog2.session(`${requestMeta.requestId} silent_turn reason=${preRecoveryOutcome.reason} ` + `blocks=${eventsForwarded} out=${lastUsage?.output_tokens ?? 0} ` + `recovery=succeeded`, requestMeta.requestId);
22475
+ }
22476
+ }
22071
22477
  if (!streamClosed) {
22072
22478
  const unseenToolUses = capturedToolUses.filter((tu) => !streamedToolUseIds.has(tu.id));
22073
22479
  if (passthrough && unseenToolUses.length > 0 && messageStartEmitted) {
@@ -22099,14 +22505,7 @@ data: ${JSON.stringify({
22099
22505
 
22100
22506
  `), "passthrough_tool_block_stop");
22101
22507
  }
22102
- safeEnqueue(encoder.encode(`event: message_delta
22103
- data: ${JSON.stringify({
22104
- type: "message_delta",
22105
- delta: { stop_reason: "tool_use", stop_sequence: null },
22106
- usage: { output_tokens: 0 }
22107
- })}
22108
-
22109
- `), "passthrough_message_delta");
22508
+ sendTerminalDelta("tool_use");
22110
22509
  }
22111
22510
  if (trackFileChanges && passthrough && pipelineCtx.extractFileChangesFromToolUse) {
22112
22511
  const passthroughChanges = extractFileChangesFromMessages(body.messages || [], pipelineCtx.extractFileChangesFromToolUse);
@@ -22143,6 +22542,7 @@ data: ${JSON.stringify({
22143
22542
  }
22144
22543
  }
22145
22544
  if (messageStartEmitted) {
22545
+ sendTerminalDelta();
22146
22546
  safeEnqueue(encoder.encode(`event: message_stop
22147
22547
  data: {"type":"message_stop"}
22148
22548
 
@@ -22208,13 +22608,18 @@ data: {"type":"message_stop"}
22208
22608
  cacheHitRate: computeCacheHitRate(lastUsage),
22209
22609
  ...envelopeViolations.length > 0 ? { envelopeViolations: [...envelopeViolations] } : {}
22210
22610
  });
22211
- if (textEventsForwarded === 0) {
22212
- claudeLog("response.empty_stream", {
22611
+ const turnOutcome = classifyNow();
22612
+ if (turnOutcome.kind === "silent") {
22613
+ claudeLog("response.silent_turn", {
22213
22614
  model,
22615
+ reason: turnOutcome.reason,
22214
22616
  streamEventsSeen,
22215
22617
  eventsForwarded,
22216
- reason: "no_text_deltas_forwarded"
22618
+ outputTokens: lastUsage?.output_tokens,
22619
+ recovered: silentTurnRecovered,
22620
+ recoveryAttempted: silentTurnRecoveryAttempted
22217
22621
  });
22622
+ diagnosticLog2.session(`${requestMeta.requestId} silent_turn reason=${turnOutcome.reason} ` + `blocks=${eventsForwarded} out=${lastUsage?.output_tokens ?? 0} ` + `recovery=${silentTurnRecoveryAttempted ? silentTurnRecovered ? "succeeded" : "failed" : "off"}`, requestMeta.requestId);
22218
22623
  }
22219
22624
  }
22220
22625
  } catch (error) {
@@ -22227,6 +22632,21 @@ data: {"type":"message_stop"}
22227
22632
  textEventsForwarded,
22228
22633
  durationMs: Date.now() - requestStartAt
22229
22634
  });
22635
+ const disposition = clientAbortDisposition({
22636
+ isIndependentSession,
22637
+ profileSessionId,
22638
+ currentSessionId,
22639
+ sawDuplicateToolUse,
22640
+ resumeBoundaryUuid: nextPassthroughResumeUuid,
22641
+ passthrough
22642
+ });
22643
+ if (disposition.action === "store" && currentSessionId) {
22644
+ storeSession(profileSessionId, body.messages || [], currentSessionId, profileScopedCwd, sdkUuidMap, lastUsage, disposition.resumeUuid);
22645
+ } else if (disposition.action === "evict") {
22646
+ evictSession(profileSessionId, profileScopedCwd, body.messages || []);
22647
+ }
22648
+ claudeLog("passthrough.client_abort_settled", { action: disposition.action });
22649
+ resolvePendingStore();
22230
22650
  return;
22231
22651
  }
22232
22652
  resolvePendingStore();
@@ -22380,26 +22800,41 @@ data: {"type":"message_stop"}
22380
22800
  error: streamErr.type
22381
22801
  });
22382
22802
  if (messageStartEmitted) {
22803
+ const errorStopReason = textEventsForwarded > 0 ? "end_turn" : "max_tokens";
22804
+ claudeLog("response.error_envelope", {
22805
+ mode: "stream",
22806
+ stopReason: errorStopReason,
22807
+ textEvents: textEventsForwarded,
22808
+ classified: streamErr.type
22809
+ });
22383
22810
  safeEnqueue(encoder.encode(`event: message_delta
22384
22811
  data: ${JSON.stringify({
22385
22812
  type: "message_delta",
22386
- delta: { stop_reason: "end_turn", stop_sequence: null },
22813
+ delta: { stop_reason: errorStopReason, stop_sequence: null },
22387
22814
  usage: { output_tokens: 0 }
22388
22815
  })}
22389
22816
 
22390
22817
  `), "error_message_delta");
22818
+ safeEnqueue(encoder.encode(`event: error
22819
+ data: ${JSON.stringify({
22820
+ type: "error",
22821
+ error: { type: streamErr.type, message: streamErr.message }
22822
+ })}
22823
+
22824
+ `), "error_event_before_stop");
22391
22825
  safeEnqueue(encoder.encode(`event: message_stop
22392
22826
  data: {"type":"message_stop"}
22393
22827
 
22394
22828
  `), "error_message_stop");
22395
- }
22396
- safeEnqueue(encoder.encode(`event: error
22829
+ } else {
22830
+ safeEnqueue(encoder.encode(`event: error
22397
22831
  data: ${JSON.stringify({
22398
- type: "error",
22399
- error: { type: streamErr.type, message: streamErr.message }
22400
- })}
22832
+ type: "error",
22833
+ error: { type: streamErr.type, message: streamErr.message }
22834
+ })}
22401
22835
 
22402
22836
  `), "error_event");
22837
+ }
22403
22838
  if (!streamClosed) {
22404
22839
  try {
22405
22840
  controller.close();
@@ -22657,7 +23092,7 @@ data: ${JSON.stringify({
22657
23092
  });
22658
23093
  });
22659
23094
  app.get("/profiles", async (c) => {
22660
- const { profilePageHtml } = await import("./profilePage-naychnb8.js");
23095
+ const { profilePageHtml } = await import("./profilePage-gtazq15d.js");
22661
23096
  return c.html(profilePageHtml);
22662
23097
  });
22663
23098
  app.post("/profiles/active", async (c) => {
@@ -22740,14 +23175,25 @@ data: ${JSON.stringify({
22740
23175
  });
22741
23176
  app.post("/v1/chat/completions", async (c) => {
22742
23177
  const rawBody = await c.req.json();
22743
- const anthropicBody = translateOpenAiToAnthropic(rawBody);
23178
+ const userAgent = c.req.header("user-agent") ?? "";
23179
+ const jcodeSessionId = userAgent.startsWith("jcode/") ? normalizeJcodeSessionId(c.req.header("x-jcode-session")) : undefined;
23180
+ const isJcode = jcodeSessionId !== undefined;
23181
+ const adapterName = isJcode ? "jcode" : "openai";
23182
+ const anthropicBody = translateOpenAiToAnthropic(rawBody, {
23183
+ preserveConversationHistory: isJcode
23184
+ });
22744
23185
  if (!anthropicBody) {
22745
23186
  return c.json({ type: "error", error: { type: "invalid_request_error", message: "messages: Field required" } }, 400);
22746
23187
  }
22747
23188
  const internalHeaders = {
22748
23189
  "Content-Type": "application/json",
22749
- "x-meridian-agent": "openai"
23190
+ "x-meridian-agent": adapterName
22750
23191
  };
23192
+ if (jcodeSessionId)
23193
+ internalHeaders["x-jcode-session"] = jcodeSessionId;
23194
+ const requestedProfile = c.req.header("x-meridian-profile");
23195
+ if (requestedProfile)
23196
+ internalHeaders["x-meridian-profile"] = requestedProfile;
22751
23197
  const xApiKey = c.req.header("x-api-key");
22752
23198
  if (xApiKey)
22753
23199
  internalHeaders["x-api-key"] = xApiKey;
@@ -22768,7 +23214,7 @@ data: ${JSON.stringify({
22768
23214
  const created = Math.floor(Date.now() / 1000);
22769
23215
  const model = typeof rawBody.model === "string" && rawBody.model ? rawBody.model : CANONICAL_SONNET_MODEL;
22770
23216
  const { getFeaturesForAdapter: getFeaturesForAdapter2 } = (init_sdkFeatures(), __toCommonJS(exports_sdkFeatures));
22771
- const sdkFeatures = getFeaturesForAdapter2("openai");
23217
+ const sdkFeatures = getFeaturesForAdapter2(adapterName);
22772
23218
  if (!anthropicBody.stream) {
22773
23219
  const anthropicRes = await internalRes.json();
22774
23220
  return c.json(translateAnthropicToOpenAi(anthropicRes, completionId, model, created, {
@@ -23014,7 +23460,7 @@ data: ${JSON.stringify({ response: { id: responseId, status: "failed", error: {
23014
23460
  const profilesList = getEffectiveProfiles(finalConfig.profiles);
23015
23461
  const activeId = getActiveProfileId() || finalConfig.defaultProfile || profilesList[0]?.id || null;
23016
23462
  if (profilesList.length === 0) {
23017
- const oauth = await fetchOAuthUsage({});
23463
+ const { snapshot: oauth, error } = await fetchOAuthUsageResult({});
23018
23464
  return c.json({
23019
23465
  profiles: [{
23020
23466
  id: "default",
@@ -23022,7 +23468,7 @@ data: ${JSON.stringify({ response: { id: responseId, status: "failed", error: {
23022
23468
  windows: oauth?.windows ?? [],
23023
23469
  extraUsage: oauth?.extraUsage ?? null,
23024
23470
  fetchedAt: oauth?.fetchedAt ?? null,
23025
- error: oauth ? null : "no_token"
23471
+ error
23026
23472
  }],
23027
23473
  activeProfile: "default",
23028
23474
  asOf: Date.now()
@@ -23041,7 +23487,7 @@ data: ${JSON.stringify({ response: { id: responseId, status: "failed", error: {
23041
23487
  error: "not_oauth"
23042
23488
  };
23043
23489
  }
23044
- const oauth = await fetchOAuthUsage({
23490
+ const { snapshot: oauth, error } = await fetchOAuthUsageResult({
23045
23491
  profileId: p.id,
23046
23492
  claudeConfigDir: p.claudeConfigDir
23047
23493
  });
@@ -23052,7 +23498,7 @@ data: ${JSON.stringify({ response: { id: responseId, status: "failed", error: {
23052
23498
  windows: oauth?.windows ?? [],
23053
23499
  extraUsage: oauth?.extraUsage ?? null,
23054
23500
  fetchedAt: oauth?.fetchedAt ?? null,
23055
- error: oauth ? null : "no_token"
23501
+ error
23056
23502
  };
23057
23503
  }));
23058
23504
  return c.json({