nolo-cli 0.97.6 → 0.97.8

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 (97) hide show
  1. package/{_executeModel-E64QIKWF.js → _executeModel-V7RANMQR.js} +25 -25
  2. package/{addContentAction-DX6T34JR.js → addContentAction-RBOUD7SJ.js} +5 -5
  3. package/{addDialogAgentAction-6SGG37BF.js → addDialogAgentAction-IODCR6TB.js} +4 -4
  4. package/{agentDeleteCommand-76VXVM3N.js → agentDeleteCommand-CF65LJO2.js} +15 -15
  5. package/{agentEmailCommands-URGNKPPJ.js → agentEmailCommands-HBNZIE5Q.js} +29 -29
  6. package/{agentListCommands-62NGDFOS.js → agentListCommands-5EFAYZ5B.js} +16 -16
  7. package/{agentMachineCommands-SDIABR4D.js → agentMachineCommands-HIGEYGHU.js} +14 -14
  8. package/{agentPullCommand-5DOL6RGF.js → agentPullCommand-B4T2DJ5H.js} +1 -1
  9. package/{agentRecordCommands-ZICUGEEH.js → agentRecordCommands-DIGUK2EV.js} +29 -29
  10. package/{agentRunCommand-66NCRPQ7.js → agentRunCommand-7IYB6QL5.js} +29 -29
  11. package/{agentRuntimeLocal-EZPUCRMS.js → agentRuntimeLocal-IOFBNVIL.js} +12 -12
  12. package/{agentSlice-V2EDVUXC.js → agentSlice-6ON6SBOW.js} +5 -5
  13. package/{appDeleteCommands-7WLUFWPE.js → appDeleteCommands-UZ6MYQJN.js} +12 -12
  14. package/{appDeployCommands-NK22AMAW.js → appDeployCommands-PQD6OJ6V.js} +12 -12
  15. package/{appDeployStatusCommands-PIWSMQET.js → appDeployStatusCommands-4JJSAK6R.js} +12 -12
  16. package/{appGetCommands-J3H6IHUT.js → appGetCommands-4M7DVU5T.js} +12 -12
  17. package/{appListCommands-CF4NYHRY.js → appListCommands-PERJZZRY.js} +12 -12
  18. package/{authCommand-T6UO5KPG.js → authCommand-NHDLY3IB.js} +2 -2
  19. package/{authCommands-KTIUCVVG.js → authCommands-UDBJVSZU.js} +2 -2
  20. package/{chunk-XBIYSBSG.js → chunk-46Y5D2BZ.js} +1 -1
  21. package/{chunk-NVRC52JS.js → chunk-4FFUDT6D.js} +4 -4
  22. package/{chunk-YWLAWZYQ.js → chunk-6RSG6HJR.js} +6 -6
  23. package/{chunk-KFJ7ZWBF.js → chunk-7JIOW5N3.js} +7 -7
  24. package/{chunk-WS2VEVHS.js → chunk-7MMSLEPA.js} +2 -2
  25. package/{chunk-V4UYSDTH.js → chunk-ADBZWMFB.js} +1 -1
  26. package/{chunk-SBFHKTI7.js → chunk-CD7Y7F5H.js} +13 -3
  27. package/{chunk-GBRG75BQ.js → chunk-D2MDMY2M.js} +1 -0
  28. package/{chunk-Z7A2EDGT.js → chunk-DFX557SE.js} +3 -3
  29. package/{chunk-EPCAQM3U.js → chunk-E73ON47R.js} +1 -1
  30. package/{chunk-ROFPWC4X.js → chunk-FJ5BGMNM.js} +2 -2
  31. package/{chunk-74D5HEDI.js → chunk-FOXQ7BAB.js} +1 -1
  32. package/{chunk-OCZQEXMX.js → chunk-FWBJR7BZ.js} +18 -12
  33. package/{chunk-7MTCBOOS.js → chunk-GARACBQB.js} +1 -1
  34. package/{chunk-ANRWQGOV.js → chunk-GDFA73QZ.js} +45 -11
  35. package/{chunk-SH7KLR4U.js → chunk-I72JY7FP.js} +3 -3
  36. package/{chunk-CERE5KFG.js → chunk-KN25LO6X.js} +1 -1
  37. package/{chunk-JNXHAQPJ.js → chunk-LDCAFLXD.js} +17 -1
  38. package/{chunk-EMQZSES6.js → chunk-LOCNXNOU.js} +1 -1
  39. package/{chunk-4XYBLM4D.js → chunk-LQ4PDQCI.js} +1 -1
  40. package/{chunk-PUOC4YRO.js → chunk-M7VLQGQP.js} +11 -0
  41. package/{chunk-BFU6C242.js → chunk-NMFV26UG.js} +1 -1
  42. package/{chunk-2TYM4V33.js → chunk-NNCYNBYV.js} +2 -2
  43. package/{chunk-KQHGZWSV.js → chunk-OXME3PEE.js} +1 -1
  44. package/{chunk-ELIMCKNX.js → chunk-PCF3QU5Q.js} +1 -1
  45. package/{chunk-RX4HD4H7.js → chunk-PTDYOADJ.js} +1 -1
  46. package/{chunk-RJYTVNWD.js → chunk-RS4ENQ4O.js} +2 -2
  47. package/{chunk-BFWQ65IZ.js → chunk-SNMQMOD2.js} +1 -1
  48. package/{chunk-2LM7XUCX.js → chunk-SPCBJGFO.js} +4 -4
  49. package/{chunk-ZGNDLCYH.js → chunk-TQE6BVFT.js} +22 -22
  50. package/{chunk-SESH42J6.js → chunk-UACUR6N5.js} +1 -1
  51. package/{chunk-PQ6BKMXB.js → chunk-UM4PH574.js} +1 -1
  52. package/{chunk-BS7YHAQP.js → chunk-UWVGKNAL.js} +244 -57
  53. package/{chunk-CV366NXM.js → chunk-V5OWQOJZ.js} +8 -2
  54. package/{chunk-3PELUSVV.js → chunk-WZLHDC7H.js} +2 -2
  55. package/{chunk-LYKHXIQC.js → chunk-X5YVT5HS.js} +2 -2
  56. package/{chunk-QNTL2KFU.js → chunk-XEALKKFF.js} +105 -32
  57. package/{chunk-WGPKQLZO.js → chunk-ZOWXSMIG.js} +7 -7
  58. package/{chunk-OXEHLZNH.js → chunk-ZTZCZV42.js} +3 -3
  59. package/{commandRegistry-N47CRDOH.js → commandRegistry-WSHNW7RD.js} +52 -52
  60. package/{contentThunks-RRD2XMWB.js → contentThunks-2IQTDXY2.js} +12 -12
  61. package/{createAgentAutomationAction-OW4WEVHP.js → createAgentAutomationAction-W42UXDBD.js} +12 -12
  62. package/{createDialogAction-L3WMTD5Z.js → createDialogAction-YWNYTXXK.js} +13 -13
  63. package/{createPageAction-PWG3K3K7.js → createPageAction-UFGCRJ3W.js} +12 -12
  64. package/{dbSlice-BUB77DHH.js → dbSlice-Q25STFGJ.js} +4 -4
  65. package/{deleteFile-HG4BF3CS.js → deleteFile-AJ2EZMHT.js} +2 -2
  66. package/{dialogCommands-CNXJGME5.js → dialogCommands-YQFKAGMA.js} +15 -15
  67. package/{dialogSlice-M7ZWTW5D.js → dialogSlice-34DUPW5Z.js} +11 -11
  68. package/{docCreateCommands-U2TEDZHS.js → docCreateCommands-FCANZT2K.js} +12 -12
  69. package/{docDeleteCommands-K4ME6F6S.js → docDeleteCommands-AJHN65NA.js} +14 -14
  70. package/{docReadCommands-ZUAVR3HH.js → docReadCommands-25KDEVTF.js} +12 -12
  71. package/{docStore-IX7ASJUP.js → docStore-FAQ6XUUA.js} +7 -5
  72. package/{docUpdateCommands-UKEOVRTF.js → docUpdateCommands-KFR7UB3E.js} +12 -12
  73. package/{fetchMessages-N2BW2L62.js → fetchMessages-I5ICDDHM.js} +2 -2
  74. package/{handleSendMessageAction-KMPC6UD4.js → handleSendMessageAction-5XCHOMQH.js} +28 -12
  75. package/index.js +3 -3
  76. package/{localDialogRead-3FHUPYAR.js → localDialogRead-ZHZ3KXDM.js} +1 -1
  77. package/{localRuntimeAuthority-AENMRPGX.js → localRuntimeAuthority-TU6OBC76.js} +5 -2
  78. package/{localRuntimeDb-AXJREE2T.js → localRuntimeDb-VKWVOPPI.js} +1 -1
  79. package/{machineCommands-U4RRZGU6.js → machineCommands-MSUNJQFK.js} +28 -28
  80. package/{machineWsRunDispatch-V3IOP2P2.js → machineWsRunDispatch-VO7TVIB4.js} +28 -28
  81. package/{memberThunks-LEUNURN2.js → memberThunks-R75S3RWP.js} +5 -5
  82. package/package.json +1 -1
  83. package/{read-TBK4DFHP.js → read-SRQMNO26.js} +2 -2
  84. package/{readDocTool-TJFCZ3ND.js → readDocTool-RC3JUNJ2.js} +1 -1
  85. package/{readlineWorkspace-QTCU2BC4.js → readlineWorkspace-QIPJ23JY.js} +33 -33
  86. package/{removeDialogAgentAction-CT5HGRZH.js → removeDialogAgentAction-46XQV5Q7.js} +5 -5
  87. package/{runAgentClientLoop-4VOARXQF.js → runAgentClientLoop-GSJ4FH6L.js} +23 -23
  88. package/{runtimeDoctorCommands-EQJA4MGD.js → runtimeDoctorCommands-PIVSBZRZ.js} +3 -3
  89. package/{setDialogExtraReferencesAction-JOENKFTX.js → setDialogExtraReferencesAction-J4V5ADQF.js} +5 -5
  90. package/{setPrimaryDialogAgentAction-MHWOGXP3.js → setPrimaryDialogAgentAction-UHHV2QZW.js} +5 -5
  91. package/{settingThunks-KLPZNA6L.js → settingThunks-2OFFBLF4.js} +4 -4
  92. package/{spaceCommands-ZESRWSTC.js → spaceCommands-R3SC2VWH.js} +14 -14
  93. package/{streamAgentChatTurn-VDAVK7N3.js → streamAgentChatTurn-IUQH52XL.js} +25 -25
  94. package/{switchDialogAgentAction-JHA4JEYA.js → switchDialogAgentAction-A2TMVGAE.js} +4 -4
  95. package/{tools-VJ3L5V6D.js → tools-BQKPNGWC.js} +19 -19
  96. package/{tuiSummaryLlmCaller-QUCBFGZK.js → tuiSummaryLlmCaller-Q65IBDGO.js} +8 -8
  97. package/{updateDialogTitleAction-GBUSLAQR.js → updateDialogTitleAction-Z7OREKH3.js} +12 -12
@@ -45,7 +45,7 @@ import {
45
45
  import {
46
46
  inlineImageUrlsForCustomProvider,
47
47
  prepareTools
48
- } from "./chunk-LYKHXIQC.js";
48
+ } from "./chunk-X5YVT5HS.js";
49
49
  import {
50
50
  getServerProviderSecret
51
51
  } from "./chunk-HS7MLR74.js";
@@ -63,7 +63,7 @@ import {
63
63
  rememberMemoryFunctionSchema,
64
64
  resolveAgentRequiredPackIds,
65
65
  setTodoListFunc
66
- } from "./chunk-ZGNDLCYH.js";
66
+ } from "./chunk-TQE6BVFT.js";
67
67
  import {
68
68
  deriveCredentialGroup,
69
69
  deriveCustomProviderCredentialGroup
@@ -107,7 +107,7 @@ import {
107
107
  } from "./chunk-E3YWHWCR.js";
108
108
  import {
109
109
  getDefaultCliLocalRuntimeDb
110
- } from "./chunk-74D5HEDI.js";
110
+ } from "./chunk-FOXQ7BAB.js";
111
111
  import {
112
112
  applyBuiltinAgentRuntimeOverride,
113
113
  applyTokenUsageToDayStats,
@@ -115,14 +115,14 @@ import {
115
115
  prepareTokenUsageData,
116
116
  resolveBuiltinPlatformAgentConfig,
117
117
  runKeyed
118
- } from "./chunk-BS7YHAQP.js";
118
+ } from "./chunk-UWVGKNAL.js";
119
119
  import {
120
120
  BUILTIN_DIALOG_LLM_CHAT_FALLBACK_MODEL,
121
121
  BUILTIN_TITLE_LLM_CONFIG
122
122
  } from "./chunk-523DITKR.js";
123
123
  import {
124
124
  fetchServerSyncedCredential
125
- } from "./chunk-2LM7XUCX.js";
125
+ } from "./chunk-SPCBJGFO.js";
126
126
  import {
127
127
  FORCED_TOOLS,
128
128
  addDefaultLightWebToolsForConfiguredAgents,
@@ -149,6 +149,7 @@ import {
149
149
  createDevinProvider,
150
150
  createHybridRecordStore,
151
151
  createLocalWorkspaceToolExecutors,
152
+ deriveStableUuid,
152
153
  executeLocalToolWithPolicy,
153
154
  executeOpenAiCompatibleChatCompletion,
154
155
  filterRetainedLedgerRecords,
@@ -156,11 +157,13 @@ import {
156
157
  internalListWorkspaceEntries,
157
158
  internalSearchWorkspace,
158
159
  isLineRangeCovered,
160
+ isStableSessionIdentityEnabled,
159
161
  localDialogMessageRecordToRuntimeMessage,
160
162
  parseSyncServersEnv,
161
163
  readDevinUpstreamFailure,
162
- resolveOpenAiCompatibleProviderConfig
163
- } from "./chunk-ANRWQGOV.js";
164
+ resolveOpenAiCompatibleProviderConfig,
165
+ resolveSessionKey
166
+ } from "./chunk-GDFA73QZ.js";
164
167
  import {
165
168
  accumulateGeminiChunks,
166
169
  buildGeminiGenerateContentRequest,
@@ -182,14 +185,14 @@ import {
182
185
  readPlatformChatSseCompletion,
183
186
  resolvePlatformChatProviderConfig,
184
187
  shouldUsePlatformChatProvider
185
- } from "./chunk-CV366NXM.js";
188
+ } from "./chunk-V5OWQOJZ.js";
186
189
  import {
187
190
  readSseDataValues
188
191
  } from "./chunk-GMZLP5DV.js";
189
192
  import {
190
193
  resolveAgentRuntimeConfigFromRecord,
191
194
  resolveHistoricalToolContentCap
192
- } from "./chunk-4XYBLM4D.js";
195
+ } from "./chunk-LQ4PDQCI.js";
193
196
  import {
194
197
  isDevinOAuthAgent
195
198
  } from "./chunk-5ZUL4CUO.js";
@@ -198,7 +201,7 @@ import {
198
201
  convertMessagesToResponsesInput,
199
202
  stablePromptCacheKey,
200
203
  toResponsesTools
201
- } from "./chunk-PUOC4YRO.js";
204
+ } from "./chunk-M7VLQGQP.js";
202
205
  import {
203
206
  buildNoloWorkspaceOpenAiTools,
204
207
  parseNoloWorkspaceToolArguments,
@@ -216,14 +219,14 @@ import {
216
219
  } from "./chunk-2MBTWINN.js";
217
220
  import {
218
221
  normalizeUsage
219
- } from "./chunk-JNXHAQPJ.js";
222
+ } from "./chunk-LDCAFLXD.js";
220
223
  import {
221
224
  createProviderCallTimingTracker,
222
225
  finalizeProviderCallTiming,
223
226
  observeMeaningfulProviderResponse,
224
227
  observeMeaningfulProviderResponseAt,
225
228
  withProviderCallTimingFields
226
- } from "./chunk-WS2VEVHS.js";
229
+ } from "./chunk-7MMSLEPA.js";
227
230
  import {
228
231
  clipCompactText
229
232
  } from "./chunk-5MMAK75Q.js";
@@ -1712,6 +1715,44 @@ function resolveThinkingSpec(input) {
1712
1715
  function stringValue(value) {
1713
1716
  return typeof value === "string" && value.length > 0 ? value : void 0;
1714
1717
  }
1718
+ function ephemeralCache(slot) {
1719
+ const mode = (process.env.NOLO_ANTHROPIC_CACHE_TTL ?? "turn").trim().toLowerCase();
1720
+ if (mode === "5m") return { type: "ephemeral" };
1721
+ if (mode === "1h") return { type: "ephemeral", ttl: "1h" };
1722
+ return slot === "tail" ? { type: "ephemeral" } : { type: "ephemeral", ttl: "1h" };
1723
+ }
1724
+ function findTurnStartIndex(messages) {
1725
+ for (let i = messages.length - 1; i >= 0; i--) {
1726
+ const m = messages[i];
1727
+ if (m.role !== "user") continue;
1728
+ const content = Array.isArray(m.content) ? m.content : [];
1729
+ if (content.length === 0) continue;
1730
+ if (content.some((c) => c && c.type === "tool_result")) continue;
1731
+ return i;
1732
+ }
1733
+ return -1;
1734
+ }
1735
+ function enforceCacheTtlOrder(...groups) {
1736
+ let seenShort = false;
1737
+ const visit = (cc, holder) => {
1738
+ if (!isCacheControl(cc)) return;
1739
+ const rec = cc;
1740
+ if (rec.ttl === "1h" && seenShort) {
1741
+ const { ttl: _ttl, ...rest } = rec;
1742
+ holder.cache_control = rest;
1743
+ } else if (rec.ttl !== "1h") seenShort = true;
1744
+ };
1745
+ for (const group of groups) {
1746
+ for (const item of group) {
1747
+ visit(item.cache_control, item);
1748
+ if (Array.isArray(item.content)) {
1749
+ for (const part of item.content) {
1750
+ if (part && typeof part === "object") visit(part.cache_control, part);
1751
+ }
1752
+ }
1753
+ }
1754
+ }
1755
+ }
1715
1756
  function isCacheControl(value) {
1716
1757
  return Boolean(
1717
1758
  value && typeof value === "object" && !Array.isArray(value) && typeof value.type === "string"
@@ -1798,7 +1839,7 @@ function buildAnthropicMessagesBody(args) {
1798
1839
  if (typeof message.content === "string" && Number.isFinite(stablePrefixChars) && stablePrefixChars > 0 && stablePrefixChars <= message.content.length) {
1799
1840
  const stable = message.content.slice(0, stablePrefixChars);
1800
1841
  const dynamic = message.content.slice(stablePrefixChars);
1801
- system.push({ type: "text", text: stable, cache_control: { type: "ephemeral" } });
1842
+ system.push({ type: "text", text: stable, cache_control: ephemeralCache("prefix") });
1802
1843
  if (dynamic) system.push({ type: "text", text: dynamic });
1803
1844
  } else {
1804
1845
  system.push(...toAnthropicContent(message.content));
@@ -1845,7 +1886,7 @@ function buildAnthropicMessagesBody(args) {
1845
1886
  system.unshift({ type: "text", text: CLAUDE_CODE_SYSTEM_INSTRUCTION });
1846
1887
  }
1847
1888
  if (system.length > 0 && !system.some((block) => isCacheControl(block.cache_control))) {
1848
- system[system.length - 1].cache_control = { type: "ephemeral" };
1889
+ system[system.length - 1].cache_control = ephemeralCache("prefix");
1849
1890
  }
1850
1891
  const tools = Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools.flatMap((raw) => {
1851
1892
  if (!raw || typeof raw !== "object") return [];
@@ -1859,7 +1900,7 @@ function buildAnthropicMessagesBody(args) {
1859
1900
  }];
1860
1901
  }) : [];
1861
1902
  if (tools.length > 0 && !tools.some((tool) => isCacheControl(tool.cache_control))) {
1862
- tools[tools.length - 1].cache_control = { type: "ephemeral" };
1903
+ tools[tools.length - 1].cache_control = ephemeralCache("prefix");
1863
1904
  }
1864
1905
  const model = stringValue(args.openAiBody.model) ?? args.agentConfig.model ?? "claude-sonnet-5";
1865
1906
  const maxTokensRaw = args.openAiBody.max_completion_tokens ?? args.openAiBody.max_tokens ?? args.agentConfig.max_tokens;
@@ -1881,15 +1922,22 @@ function buildAnthropicMessagesBody(args) {
1881
1922
  const finalMaxTokens = spec.maxTokens;
1882
1923
  const finalTemperature = spec.temperature;
1883
1924
  if (messages.length > 0) {
1884
- const lastMessage = messages[messages.length - 1];
1885
- const content = Array.isArray(lastMessage.content) ? lastMessage.content : [];
1886
- if (content.length > 0) {
1887
- const lastBlock = content[content.length - 1];
1888
- if (!isCacheControl(lastBlock.cache_control)) {
1889
- lastBlock.cache_control = { type: "ephemeral" };
1890
- }
1925
+ const mode = (process.env.NOLO_ANTHROPIC_CACHE_TTL ?? "turn").trim().toLowerCase();
1926
+ const lastIdx = messages.length - 1;
1927
+ const startIdx = mode === "5m" ? -1 : findTurnStartIndex(messages);
1928
+ const mark = (idx, slot) => {
1929
+ const content = Array.isArray(messages[idx].content) ? messages[idx].content : [];
1930
+ if (content.length === 0) return;
1931
+ const block = content[content.length - 1];
1932
+ if (!isCacheControl(block.cache_control)) block.cache_control = ephemeralCache(slot);
1933
+ };
1934
+ if (startIdx === lastIdx) mark(lastIdx, "turnStart");
1935
+ else {
1936
+ if (startIdx >= 0) mark(startIdx, "turnStart");
1937
+ mark(lastIdx, "tail");
1891
1938
  }
1892
1939
  }
1940
+ enforceCacheTtlOrder(tools, system, messages);
1893
1941
  return {
1894
1942
  model: normalizeAnthropicWireModel(model),
1895
1943
  messages,
@@ -3189,6 +3237,7 @@ var resolveCliProviderTransport = async (ctx) => {
3189
3237
  };
3190
3238
 
3191
3239
  // packages/agent-runtime/codexResponsesProvider.ts
3240
+ import { createHash } from "node:crypto";
3192
3241
  import { randomUUID as randomUUID2 } from "node:crypto";
3193
3242
  var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
3194
3243
  var CODEX_CLIENT_VERSION = "0.159.2";
@@ -3210,11 +3259,25 @@ function decodeCodexAccountId(accessToken) {
3210
3259
  return void 0;
3211
3260
  }
3212
3261
  }
3213
- function createCodexRequestIdentity(installationId = CODEX_INSTALLATION_ID) {
3214
- const sessionId = randomUUID2();
3215
- const threadId = randomUUID2();
3216
- const windowId = randomUUID2();
3217
- const turnId = randomUUID2();
3262
+ var turnStartedAtByTurn = /* @__PURE__ */ new Map();
3263
+ function createCodexRequestIdentity(installationId = CODEX_INSTALLATION_ID, stable) {
3264
+ const key = stable?.sessionKey && isStableSessionIdentityEnabled() ? stable.sessionKey : void 0;
3265
+ const sessionId = key ? deriveStableUuid(key, "session") : randomUUID2();
3266
+ const threadId = key ? sessionId : randomUUID2();
3267
+ const windowId = key ? deriveStableUuid(key, "window") : randomUUID2();
3268
+ const turnId = key ? deriveStableUuid(key, `turn:${stable?.turnToken ?? ""}`) : randomUUID2();
3269
+ let turnStartedAt = Date.now();
3270
+ if (key) {
3271
+ const tk = `${key}\0${stable?.turnToken ?? ""}`;
3272
+ const prev = turnStartedAtByTurn.get(tk);
3273
+ if (prev !== void 0) turnStartedAt = prev;
3274
+ else {
3275
+ if (turnStartedAtByTurn.size >= 500) {
3276
+ turnStartedAtByTurn.delete(turnStartedAtByTurn.keys().next().value);
3277
+ }
3278
+ turnStartedAtByTurn.set(tk, turnStartedAt);
3279
+ }
3280
+ }
3218
3281
  const turnMetadata = {
3219
3282
  installation_id: installationId,
3220
3283
  session_id: sessionId,
@@ -3222,7 +3285,7 @@ function createCodexRequestIdentity(installationId = CODEX_INSTALLATION_ID) {
3222
3285
  turn_id: turnId,
3223
3286
  window_id: windowId,
3224
3287
  request_kind: "turn",
3225
- turn_started_at_unix_ms: Date.now()
3288
+ turn_started_at_unix_ms: turnStartedAt
3226
3289
  };
3227
3290
  const turnMetadataJson = JSON.stringify(turnMetadata);
3228
3291
  return {
@@ -3293,7 +3356,7 @@ function convertMessagesToCodexInput(messages) {
3293
3356
  };
3294
3357
  });
3295
3358
  }
3296
- function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
3359
+ function buildCodexRequestBody(args, identity = createCodexRequestIdentity(), sessionKey) {
3297
3360
  const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
3298
3361
  const nonSystem = rawMessages.filter((m) => {
3299
3362
  const role = m && typeof m === "object" ? String(m.role) : "";
@@ -3313,7 +3376,10 @@ function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
3313
3376
  store: false,
3314
3377
  // Keep routing stable across turns and request UUIDs. Growing input/history
3315
3378
  // is intentionally excluded; only stable request-prefix material belongs.
3316
- prompt_cache_key: stablePromptCacheKey([model, stableInstructions, tools ?? []], "nolo-codex"),
3379
+ // 真实 Codex CLI 用 session_id 作 prompt_cache_key(codex-rs/core/src/client.rs
3380
+ // prompt_cache_key());OpenAI 文档:同 key 超过 ~15 req/min 会溢出到其他机器。
3381
+ // 有会话键时按会话分片,无则回退到前缀派生键。
3382
+ prompt_cache_key: sessionKey && isStableSessionIdentityEnabled() ? identity.sessionId : stablePromptCacheKey([model, stableInstructions, tools ?? []], "nolo-codex"),
3317
3383
  client_metadata: identity.clientMetadata
3318
3384
  };
3319
3385
  if (instructions) body.instructions = instructions;
@@ -3336,8 +3402,14 @@ async function readSseEvents(response) {
3336
3402
  var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3337
3403
  async function callCodexResponsesOnce(args, accountId, timingTracker) {
3338
3404
  const fetchImpl = args.fetchImpl ?? fetch;
3339
- const identity = createCodexRequestIdentity();
3340
- const body = buildCodexRequestBody(args, identity);
3405
+ const msgs = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
3406
+ const lastUser = [...msgs].reverse().find((m) => m && m.role === "user");
3407
+ const turnToken = createHash("sha256").update(JSON.stringify(lastUser?.content ?? "")).digest("hex").slice(0, 24);
3408
+ const identity = createCodexRequestIdentity(
3409
+ void 0,
3410
+ args.sessionKey ? { sessionKey: args.sessionKey, turnToken } : void 0
3411
+ );
3412
+ const body = buildCodexRequestBody(args, identity, args.sessionKey);
3341
3413
  const headers = buildCodexCompatibilityHeaders(identity, accountId);
3342
3414
  headers.Authorization = `Bearer ${args.accessToken}`;
3343
3415
  const response = await fetchImpl(CODEX_RESPONSES_URL, {
@@ -3465,6 +3537,7 @@ var resolveCodexOAuthTransport = async (ctx) => {
3465
3537
  stream: false,
3466
3538
  ...tools.length > 0 ? { tools } : {}
3467
3539
  },
3540
+ sessionKey: resolveSessionKey({ dialogId: options?.dialogId }),
3468
3541
  fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
3469
3542
  sleep: deps.sleep,
3470
3543
  loopbackRequest
@@ -5,14 +5,14 @@ import {
5
5
  inlineImageUrlsForCustomProvider,
6
6
  prepareTools,
7
7
  shouldInlineImageUrlsForAgent
8
- } from "./chunk-LYKHXIQC.js";
8
+ } from "./chunk-X5YVT5HS.js";
9
9
  import {
10
10
  INVALID_TOOL_ARGS_REPLACEMENT,
11
11
  buildInvalidToolCallSelfHealResult,
12
12
  parseToolCallArguments,
13
13
  performFetchRequest,
14
14
  sanitizeOutboundMessages
15
- } from "./chunk-KFJ7ZWBF.js";
15
+ } from "./chunk-7JIOW5N3.js";
16
16
  import {
17
17
  createSSEParser,
18
18
  createToolRunId,
@@ -23,7 +23,7 @@ import {
23
23
  toolRunSetPending,
24
24
  toolRunStarted,
25
25
  toolRunSucceeded
26
- } from "./chunk-ZGNDLCYH.js";
26
+ } from "./chunk-TQE6BVFT.js";
27
27
  import {
28
28
  getPublicImageAgentMode
29
29
  } from "./chunk-VIDPVFP3.js";
@@ -38,10 +38,10 @@ import {
38
38
  messageStreamEnd,
39
39
  messageStreaming,
40
40
  updateToolMessage
41
- } from "./chunk-BS7YHAQP.js";
41
+ } from "./chunk-UWVGKNAL.js";
42
42
  import {
43
43
  streamAgentChatTurn
44
- } from "./chunk-2LM7XUCX.js";
44
+ } from "./chunk-SPCBJGFO.js";
45
45
  import {
46
46
  addActiveController,
47
47
  removeActiveController,
@@ -59,10 +59,10 @@ import {
59
59
  import {
60
60
  EMPTY_ASSISTANT_REPAIR_PROMPT,
61
61
  getModelInfo
62
- } from "./chunk-JNXHAQPJ.js";
62
+ } from "./chunk-LDCAFLXD.js";
63
63
  import {
64
64
  write
65
- } from "./chunk-NVRC52JS.js";
65
+ } from "./chunk-4FFUDT6D.js";
66
66
  import {
67
67
  getApiEndpoint
68
68
  } from "./chunk-3BXNTXYI.js";
@@ -7,7 +7,7 @@ import {
7
7
  listUserRecordsFromServers,
8
8
  readDbRecordFromServers,
9
9
  readLiveDbRecordAfterTombstoneMerge
10
- } from "./chunk-RJYTVNWD.js";
10
+ } from "./chunk-RS4ENQ4O.js";
11
11
  import {
12
12
  fetchWithTransientRetry,
13
13
  parsePositiveFiniteNumberOrFallback
@@ -723,7 +723,7 @@ function isExplicitDialogIdMismatch(meta, dialogId) {
723
723
  return meta && typeof meta === "object" && "id" in meta && meta.id != null && String(meta.id) !== dialogId;
724
724
  }
725
725
  async function readDialogFromLocalDb(dialogKey, dialogId, limit, readLocalDialog) {
726
- const reader = readLocalDialog ?? (await import("./localDialogRead-3FHUPYAR.js")).readDialogFromLocalDb;
726
+ const reader = readLocalDialog ?? (await import("./localDialogRead-ZHZ3KXDM.js")).readDialogFromLocalDb;
727
727
  const result = await reader({ dialogKey, dialogId, limit });
728
728
  return {
729
729
  ...result,
@@ -740,7 +740,7 @@ async function readLocalDialogAtDbPathDefault(args) {
740
740
  const [{ Level }, { safeJsonEncoding }, { fetchMessages }] = await Promise.all([
741
741
  import("./levelLazyShim-GZBKODGI.js"),
742
742
  import("./serverStoreFactory-YMXDF4NI.js"),
743
- import("./fetchMessages-N2BW2L62.js")
743
+ import("./fetchMessages-I5ICDDHM.js")
744
744
  ]);
745
745
  const db = new Level(args.dbPath, {
746
746
  valueEncoding: safeJsonEncoding,