nolo-cli 0.16.0 → 0.17.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.
Files changed (132) hide show
  1. package/{_executeModel-AVCA2NAV.js → _executeModel-WPNX5DH4.js} +49 -43
  2. package/{action-F5JACQBG.js → action-LT7BRFLK.js} +10 -9
  3. package/{addContentAction-AQXEYRBE.js → addContentAction-PL3KKBDH.js} +9 -8
  4. package/{addDialogAgentAction-EJHHJZWW.js → addDialogAgentAction-FCMSKYAF.js} +8 -7
  5. package/{agentDeleteCommand-QW5PUMDQ.js → agentDeleteCommand-L3357EFL.js} +31 -28
  6. package/{agentEmailCommands-4ORVLGVQ.js → agentEmailCommands-N65AVLEI.js} +61 -55
  7. package/{agentListCommands-YWBYRTYC.js → agentListCommands-CH27FTI2.js} +30 -27
  8. package/{agentMachineCommands-JSQW4FOA.js → agentMachineCommands-PPK5HJZB.js} +29 -26
  9. package/{agentPullCommand-6HWUT3SW.js → agentPullCommand-ZZGU5KOY.js} +4 -4
  10. package/{agentRecordCommands-AASIWOBT.js → agentRecordCommands-HTVXD4TT.js} +56 -50
  11. package/{agentRunCommand-TB5BHXUH.js → agentRunCommand-MGLVJUA5.js} +62 -53
  12. package/{agentRunControl-6ADXVYMR.js → agentRunControl-P75VPTGS.js} +24 -1
  13. package/{agentRuntimeLocal-QNPNJRVH.js → agentRuntimeLocal-QUTBSY3I.js} +24 -21
  14. package/{agentSlice-RUNXC62Y.js → agentSlice-DOGRCMWK.js} +9 -8
  15. package/appDeleteCommands-FEEVXUBG.js +127 -0
  16. package/appDeployCommands-C4HCGC4B.js +166 -0
  17. package/appDeployStatusCommands-IR5ZUZBQ.js +147 -0
  18. package/appGetCommands-6RJGZ66Z.js +122 -0
  19. package/appListCommands-VMTF5YZF.js +125 -0
  20. package/{authCommand-YFTR3347.js → authCommand-WJZPOLSS.js} +16 -9
  21. package/{authCommands-YXGOXNBZ.js → authCommands-XTBV7OFZ.js} +6 -5
  22. package/{chunk-XPC5C7BK.js → chunk-3ND52WIL.js} +2 -2
  23. package/{chunk-SOTZ6RDN.js → chunk-3Q7WHGCB.js} +1 -1
  24. package/{chunk-M43KDE25.js → chunk-45BY7RLP.js} +2 -8
  25. package/{chunk-KKY4B2Q2.js → chunk-4PWB7JRR.js} +4 -1
  26. package/{chunk-6N4KODMN.js → chunk-4T5F7YZQ.js} +1 -1
  27. package/chunk-7BUYEZ6U.js +671 -0
  28. package/{chunk-AS3ZQ3O2.js → chunk-7OBMZCRD.js} +1 -1
  29. package/{chunk-AVVZUXXC.js → chunk-AAODAAUQ.js} +34 -13
  30. package/{chunk-QLUFR47U.js → chunk-AL2V7U3E.js} +1 -1
  31. package/{chunk-MTU75CZ2.js → chunk-B5TOXZAK.js} +1 -1
  32. package/{chunk-AUURUT6L.js → chunk-BT6K76S7.js} +238 -424
  33. package/chunk-CEFXYF66.js +107 -0
  34. package/{chunk-RLCXU7A5.js → chunk-D3HVJJIA.js} +1 -1
  35. package/{chunk-JTMNCCWF.js → chunk-DKZFOK24.js} +16 -87
  36. package/chunk-DL6EPNIK.js +50 -0
  37. package/{chunk-4L2OJPCU.js → chunk-EGPCU42M.js} +58 -8
  38. package/{chunk-IWLUTMYX.js → chunk-ELT65PZW.js} +2 -2
  39. package/chunk-FKXFCYVO.js +221 -0
  40. package/{chunk-4FX6NVDW.js → chunk-FPKLD4KB.js} +3 -136
  41. package/{chunk-PCTUYVUM.js → chunk-FVIPEIVX.js} +10 -3
  42. package/chunk-GFUIQ4RY.js +136 -0
  43. package/{chunk-66X4VSRC.js → chunk-HQPG2PIV.js} +41 -1
  44. package/{chunk-IGXREZW2.js → chunk-HV2A3B4W.js} +1 -1
  45. package/{chunk-LPEUV5RE.js → chunk-IOOMJJ4Z.js} +2 -2
  46. package/{setDialogExtraReferencesAction-LR6MSIXO.js → chunk-JLA4FXYC.js} +2 -17
  47. package/{chunk-3OIRVWXA.js → chunk-JP7REMYP.js} +10 -1
  48. package/chunk-KFEVY3ST.js +255 -0
  49. package/{chunk-P3RIAYGG.js → chunk-L2MLZQXU.js} +3 -3
  50. package/{chunk-55NSNCFM.js → chunk-L6NVTGI7.js} +1 -1
  51. package/{chunk-3WGLLTK4.js → chunk-LSFAWXKC.js} +100 -3
  52. package/{chunk-S2LXHNHG.js → chunk-MD3V54DA.js} +6 -6
  53. package/{chunk-6EVITP2G.js → chunk-MUCU6ATG.js} +2 -251
  54. package/{chunk-KFHN5NGJ.js → chunk-MVQ4TBSD.js} +1 -1
  55. package/{chunk-ZQBL7LIC.js → chunk-NEKFSXOP.js} +310 -211
  56. package/{chunk-NSCHQQPU.js → chunk-NVB267BZ.js} +397 -324
  57. package/{chunk-Z5JQNBNY.js → chunk-NYUXSXLY.js} +33 -14
  58. package/{chunk-FRV6A633.js → chunk-PZCBZO4J.js} +2 -2
  59. package/{chunk-GSINCD4P.js → chunk-QCJITMYO.js} +21 -11
  60. package/{chunk-OOSFSFMA.js → chunk-R5V5G73M.js} +2 -0
  61. package/{chunk-4IJYA27C.js → chunk-RG2U2MTJ.js} +1 -1
  62. package/{chunk-BEBNFWDU.js → chunk-RRGVDPH3.js} +3 -3
  63. package/{chunk-EABWT43X.js → chunk-RVOUXDFU.js} +5 -5
  64. package/{chunk-JTINRTBT.js → chunk-SKDNBYZK.js} +2 -2
  65. package/{chunk-3663CXZN.js → chunk-SNZV4QCE.js} +65 -22
  66. package/{chunk-KMQPSTMJ.js → chunk-TRT4I4UD.js} +2 -2
  67. package/{chunk-MYMMNKYL.js → chunk-TSIYZBTH.js} +156 -6
  68. package/{chunk-EHLHSX7R.js → chunk-UB4RYYNQ.js} +9 -2
  69. package/{chunk-YJKXGHJ6.js → chunk-UGUW3FHG.js} +4 -4
  70. package/{chunk-DPAB4FQ7.js → chunk-UZY4BEBR.js} +1579 -212
  71. package/chunk-V5R4NZP2.js +78 -0
  72. package/{chunk-MR6ISAGB.js → chunk-VDNQF5VI.js} +6 -6
  73. package/{chunk-33BJUVK4.js → chunk-VGMJ6PDJ.js} +5 -5
  74. package/{chunk-W4NVOSFF.js → chunk-WFHXMLHZ.js} +1 -1
  75. package/{chunk-H33743XH.js → chunk-WJRJDX2W.js} +1 -1
  76. package/chunk-X4Q4UZEY.js +26 -0
  77. package/{chunk-RPDGJO4D.js → chunk-XHG22OEX.js} +4 -4
  78. package/{chunk-DVRHHFEA.js → chunk-XMLRJUU5.js} +1 -1
  79. package/{chunk-3S2VOMIF.js → chunk-XRZJGPFI.js} +7 -7
  80. package/{chunk-7UKFVQ5W.js → chunk-YLRTBX4Y.js} +105 -36
  81. package/{chunk-DGEYDWEZ.js → chunk-YXTRNO5W.js} +3 -3
  82. package/{chunk-FY233ZFU.js → chunk-ZJZCMKOR.js} +107 -177
  83. package/{chunk-NVEWUJVX.js → chunk-ZVOZH2HW.js} +1 -1
  84. package/chunk-ZZ2MH7LE.js +84 -0
  85. package/{cliExecutor-K3F7DMRO.js → cliExecutor-DNE7TCC4.js} +2 -2
  86. package/codingSkills-36KN5NQT.js +48 -0
  87. package/{createAgentAutomationAction-FNHPSKKO.js → createAgentAutomationAction-PMOLEPGJ.js} +19 -18
  88. package/{createDialogAction-TZCVQ3NU.js → createDialogAction-DPRTYNAK.js} +21 -20
  89. package/{createPageAction-EIGZ3BKT.js → createPageAction-JGZK3WAM.js} +25 -24
  90. package/{dbSlice-7KQH6GOU.js → dbSlice-CGSRFJN3.js} +8 -7
  91. package/{deleteFile-WPWVZE4B.js → deleteFile-WDZ3VM7B.js} +3 -3
  92. package/{dialogCommands-FO77J5DQ.js → dialogCommands-XED6DKLV.js} +29 -26
  93. package/{dialogSlice-MM5U4KE2.js → dialogSlice-KO4NRNKC.js} +19 -18
  94. package/{docCreateCommands-I3BS3AZI.js → docCreateCommands-P6DYWHH3.js} +32 -27
  95. package/{docDeleteCommands-Q2OPV52P.js → docDeleteCommands-KUWXAMSN.js} +31 -26
  96. package/{docReadCommands-YOOFACYZ.js → docReadCommands-ECW55TKB.js} +30 -25
  97. package/{docStore-NGYQ2JTR.js → docStore-6KMERNUY.js} +20 -19
  98. package/{docUpdateCommands-2B32ITHN.js → docUpdateCommands-5J4BTJQN.js} +31 -26
  99. package/{fetchMessages-KTNM7QAR.js → fetchMessages-BMGVZVSE.js} +4 -3
  100. package/{getPricing-P4XRJRZB.js → getPricing-RYY6OBA4.js} +2 -2
  101. package/{handleSendMessageAction-JRZWWBKP.js → handleSendMessageAction-R3ZHTVU4.js} +20 -19
  102. package/index.js +95 -64
  103. package/{localDialogRead-2VRI24F4.js → localDialogRead-HQZPVIE3.js} +1 -1
  104. package/{localRuntimeDb-LGDF6FQP.js → localRuntimeDb-THJZGAOJ.js} +1 -1
  105. package/{machineCommands-WRWF2ICZ.js → machineCommands-JF2YL34J.js} +62 -56
  106. package/{machineWsRunDispatch-ZX7Q3TWZ.js → machineWsRunDispatch-ON4AEOJL.js} +54 -48
  107. package/{models-WQ5N4OJM.js → models-5K5G2CZI.js} +1 -1
  108. package/package.json +1 -1
  109. package/queryRunOverlay-O4LOMMPO.js +161 -0
  110. package/{read-CN3TNXIP.js → read-3FMPZPER.js} +3 -3
  111. package/{readDocTool-WF3675ED.js → readDocTool-VSYHKK3V.js} +1 -1
  112. package/{readlineWorkspace-ZTGRGW46.js → readlineWorkspace-SUCINTL7.js} +354 -185
  113. package/{removeDialogAgentAction-YDHBFEGI.js → removeDialogAgentAction-OAGA2G3U.js} +10 -9
  114. package/{runAgentClientLoop-JZCOP7LG.js → runAgentClientLoop-OBD2AVEL.js} +43 -37
  115. package/runOverlayPresentation-ZO4VCWEU.js +11 -0
  116. package/{runtimeDoctorCommands-THIHX2SY.js → runtimeDoctorCommands-E2OUORHK.js} +6 -6
  117. package/setDialogExtraReferencesAction-JZEXA5SL.js +27 -0
  118. package/{setPrimaryDialogAgentAction-IIVDCY5C.js → setPrimaryDialogAgentAction-4ZUQQKDG.js} +26 -17
  119. package/{settingSlice-O23YDK2O.js → settingSlice-7MNKHZ6R.js} +9 -8
  120. package/{skillDiscovery-6M2BZUFN.js → skillDiscovery-KJWT7JBU.js} +3 -3
  121. package/{spaceCommands-VV4GTPQK.js → spaceCommands-32NTNLHS.js} +30 -27
  122. package/{spaceSlice-DRWWZJP7.js → spaceSlice-P7VOXLY6.js} +19 -18
  123. package/{streamAgentChatTurn-Y6WGATQR.js → streamAgentChatTurn-UHEMNI3X.js} +97 -56
  124. package/{tableCommands-3P7MJ3PF.js → tableCommands-BEQAGE4I.js} +1 -1
  125. package/{tools-PUNBY3AH.js → tools-BMXIXHMB.js} +32 -27
  126. package/{tuiSummaryLlmCaller-F64WLSAF.js → tuiSummaryLlmCaller-VUNVBRX3.js} +5 -4
  127. package/types-ZSTJ7MPR.js +7 -0
  128. package/{updateDialogTitleAction-YSR4TCMB.js → updateDialogTitleAction-LJBDYZLH.js} +22 -21
  129. package/{chunk-O4BU24WZ.js → chunk-6Y7A3OQQ.js} +3 -3
  130. package/{chunk-XBS2WYJ2.js → chunk-RK5NYQEL.js} +0 -0
  131. package/{chunk-CMKUBIGW.js → chunk-X7W4TNB4.js} +3 -3
  132. package/{localRuntimeAuthority-TEGCOWX4.js → localRuntimeAuthority-4IXJCHZ7.js} +3 -3
@@ -3,12 +3,11 @@ import {
3
3
  refreshAntigravityOAuthToken,
4
4
  refreshOpenAiCodexToken,
5
5
  refreshXaiOAuthToken
6
- } from "./chunk-EHLHSX7R.js";
6
+ } from "./chunk-UB4RYYNQ.js";
7
7
  import {
8
8
  buildLocalAgentLookupKeys,
9
- normalizeAgentHandle,
10
9
  shouldReadAgentKeyRemotely
11
- } from "./chunk-M43KDE25.js";
10
+ } from "./chunk-45BY7RLP.js";
12
11
  import {
13
12
  LOCAL_CODEX_AGENT_ID,
14
13
  LOCAL_CODEX_AGENT_KEY,
@@ -17,17 +16,17 @@ import {
17
16
  } from "./chunk-VHBWHNVT.js";
18
17
  import {
19
18
  inferCaptureIntent
20
- } from "./chunk-KFHN5NGJ.js";
19
+ } from "./chunk-MVQ4TBSD.js";
21
20
  import {
22
21
  inlineImageUrlsForCustomProvider,
23
22
  prepareTools
24
- } from "./chunk-FRV6A633.js";
23
+ } from "./chunk-PZCBZO4J.js";
25
24
  import {
26
25
  getAntigravityUserAgent,
27
26
  isAntigravityOAuthAgent,
28
27
  readAntigravityProjectId,
29
28
  resolveAntigravityCloudCodeBaseUrl
30
- } from "./chunk-55NSNCFM.js";
29
+ } from "./chunk-L6NVTGI7.js";
31
30
  import {
32
31
  FORCED_TOOLS,
33
32
  addDefaultLightWebToolsForConfiguredAgents,
@@ -36,19 +35,13 @@ import {
36
35
  applyDisabledTools,
37
36
  applySystemBuiltinSkillFilter,
38
37
  expandEnabledPacks,
39
- formatListRunsCard,
40
- formatNotFoundRunCard,
41
- formatStartRunCard,
42
- formatStatusRunCard,
43
- formatStopRunCard,
44
38
  readXPostFunc,
45
39
  readXPostFunctionSchema,
46
40
  readXhsProfileFunc,
47
41
  readXhsProfileFunctionSchema,
48
42
  rememberMemoryFunctionSchema,
49
- resolveEffectiveEnabledPacks,
50
- resolveRunLabel
51
- } from "./chunk-ZQBL7LIC.js";
43
+ resolveEffectiveEnabledPacks
44
+ } from "./chunk-NEKFSXOP.js";
52
45
  import {
53
46
  createDrainExhaustedResponse,
54
47
  isCoreDrainingBody,
@@ -58,15 +51,18 @@ import {
58
51
  import {
59
52
  normalizeDialogTitle
60
53
  } from "./chunk-OWOHNGCN.js";
54
+ import {
55
+ getDefaultCliLocalRuntimeDb
56
+ } from "./chunk-WJRJDX2W.js";
61
57
  import {
62
58
  prepareTokenUsageData
63
- } from "./chunk-NSCHQQPU.js";
59
+ } from "./chunk-NVB267BZ.js";
64
60
  import {
65
61
  BUILTIN_TITLE_LLM_CONFIG
66
62
  } from "./chunk-XOIF2TNF.js";
67
63
  import {
68
64
  fetchServerSyncedCredential
69
- } from "./chunk-S2LXHNHG.js";
65
+ } from "./chunk-MD3V54DA.js";
70
66
  import {
71
67
  buildAgentRuntimeDialogWritePlan,
72
68
  buildLocalWorkspaceOpenAiTools,
@@ -77,9 +73,10 @@ import {
77
73
  executeLocalToolWithPolicy,
78
74
  executeOpenAiCompatibleChatCompletion,
79
75
  parseSseDataLineJson,
76
+ parseSseDataLineObject,
80
77
  readOpenAiCompatibleSseCompletion,
81
78
  resolveOpenAiCompatibleProviderConfig
82
- } from "./chunk-7UKFVQ5W.js";
79
+ } from "./chunk-YLRTBX4Y.js";
83
80
  import {
84
81
  buildPlatformChatCompletionRequest,
85
82
  canUsePlatformChatProvider,
@@ -88,25 +85,27 @@ import {
88
85
  readSseDataValues,
89
86
  resolvePlatformChatProviderConfig,
90
87
  shouldUsePlatformChatProvider
91
- } from "./chunk-AVVZUXXC.js";
88
+ } from "./chunk-AAODAAUQ.js";
92
89
  import {
93
90
  resolveAgentRuntimeConfigFromRecord
94
91
  } from "./chunk-OIQPORYI.js";
95
92
  import {
96
- parseToolArgumentsJson,
97
93
  summarizeToolArguments
98
- } from "./chunk-GSINCD4P.js";
94
+ } from "./chunk-QCJITMYO.js";
95
+ import {
96
+ convertMessagesToResponsesInput,
97
+ toResponsesTools
98
+ } from "./chunk-KFEVY3ST.js";
99
99
  import {
100
100
  resolvePlatformAuthToken
101
- } from "./chunk-6EVITP2G.js";
101
+ } from "./chunk-MUCU6ATG.js";
102
102
  import {
103
103
  buildLoadSkillExecutor,
104
104
  buildNoloWorkspaceCliToolExecutors,
105
105
  buildNoloWorkspaceOpenAiTools,
106
- canonicalizeToolNames,
107
106
  parseNoloWorkspaceToolArguments,
108
107
  resolveRuntimeToolSurfaceForAgent
109
- } from "./chunk-JTMNCCWF.js";
108
+ } from "./chunk-DKZFOK24.js";
110
109
  import {
111
110
  clipCompactText
112
111
  } from "./chunk-5MMAK75Q.js";
@@ -122,6 +121,15 @@ import {
122
121
  readOAuthCredential,
123
122
  resolveFreshAccessToken
124
123
  } from "./chunk-JZPBVBIY.js";
124
+ import {
125
+ isAdaptiveThinkingModelId
126
+ } from "./chunk-HQPG2PIV.js";
127
+ import {
128
+ toErrorMessage
129
+ } from "./chunk-HNMXYYJR.js";
130
+ import {
131
+ canonicalizeToolNames
132
+ } from "./chunk-ZZ2MH7LE.js";
125
133
  import {
126
134
  compactWhitespace
127
135
  } from "./chunk-DWLEOOGR.js";
@@ -129,22 +137,29 @@ import {
129
137
  checkStaleRun,
130
138
  finalizeRunRecord,
131
139
  findRunRecord,
132
- listRunRecords,
140
+ gcRunRecords,
141
+ queryRunRecords,
133
142
  spawnLocalBackgroundRun
134
- } from "./chunk-MYMMNKYL.js";
143
+ } from "./chunk-TSIYZBTH.js";
144
+ import {
145
+ TASK_PREVIEW_MAX,
146
+ formatListRunsCard,
147
+ formatNotFoundRunCard,
148
+ formatStartRunCard,
149
+ formatStatusRunCard,
150
+ formatStopRunCard,
151
+ isAgentNameFallback,
152
+ isAgentRunTerminalStatus,
153
+ resolveRunLabel,
154
+ shortRunId
155
+ } from "./chunk-FKXFCYVO.js";
135
156
  import {
136
157
  CliProviderQuotaError,
137
158
  executeCli
138
- } from "./chunk-CMKUBIGW.js";
159
+ } from "./chunk-X7W4TNB4.js";
139
160
  import {
140
161
  buildCliPrompt
141
162
  } from "./chunk-ATNTHIZI.js";
142
- import {
143
- toErrorMessage
144
- } from "./chunk-HNMXYYJR.js";
145
- import {
146
- getDefaultCliLocalRuntimeDb
147
- } from "./chunk-H33743XH.js";
148
163
  import {
149
164
  isCompiledBinary,
150
165
  parseUserIdFromAuthToken
@@ -152,27 +167,27 @@ import {
152
167
  import {
153
168
  DEFAULT_NOLO_SERVER_URL
154
169
  } from "./chunk-OLZBQWZU.js";
155
- import {
156
- asRecordOrEmpty
157
- } from "./chunk-KX6YBIHG.js";
158
170
  import {
159
171
  createTokenKey,
160
172
  createUserKey,
161
173
  dialogMessageRange
162
- } from "./chunk-O4BU24WZ.js";
174
+ } from "./chunk-6Y7A3OQQ.js";
175
+ import {
176
+ asOptionalFiniteNumber
177
+ } from "./chunk-WWC7I6TA.js";
163
178
  import {
164
179
  asTrimmedNonEmptyStringArray
165
180
  } from "./chunk-I42VC5KR.js";
166
181
  import {
167
- asOptionalFiniteNumber
168
- } from "./chunk-WWC7I6TA.js";
182
+ asTrimmedLowercaseString
183
+ } from "./chunk-QSJ3HFEF.js";
169
184
  import {
170
185
  BUILTIN_NOLO_AGENT_KEY,
171
186
  PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY,
172
187
  PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
173
188
  PUBLIC_GLM_52_AGENT_KEY,
174
189
  PUBLIC_KIMI_K26_IMAGE_AGENT_KEY
175
- } from "./chunk-XPC5C7BK.js";
190
+ } from "./chunk-3ND52WIL.js";
176
191
  import {
177
192
  asTrimmedString
178
193
  } from "./chunk-3EUW3WEO.js";
@@ -294,6 +309,10 @@ var STRINGS = {
294
309
  en: "Agent switch cancelled.",
295
310
  zh: "\u5DF2\u53D6\u6D88\u5207\u6362 agent\u3002"
296
311
  },
312
+ agentPickerLoading: {
313
+ en: "Loading agents\u2026",
314
+ zh: "\u6B63\u5728\u52A0\u8F7D agent \u5217\u8868\u2026"
315
+ },
297
316
  historyPickerTitle: {
298
317
  en: "Resume dialog (\u2191\u2193 Enter Esc)",
299
318
  zh: "\u6062\u590D\u5BF9\u8BDD\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Enter \u9009\u62E9 \xB7 Esc \u53D6\u6D88\uFF09"
@@ -458,6 +477,10 @@ var STRINGS = {
458
477
  en: "Run stopped",
459
478
  zh: "\u8FD0\u884C\u5DF2\u505C\u6B62"
460
479
  },
480
+ runFinishedLabel: {
481
+ en: "Run finished",
482
+ zh: "\u8FD0\u884C\u5DF2\u7ED3\u675F"
483
+ },
461
484
  runLogTailLabel: {
462
485
  en: "Log tail:",
463
486
  zh: "\u65E5\u5FD7\u5C3E\u90E8\uFF1A"
@@ -492,6 +515,10 @@ var STRINGS = {
492
515
  en: "selected",
493
516
  zh: "\u5DF2\u9009"
494
517
  },
518
+ dialogMultiSelectRequired: {
519
+ en: "Pick at least one option to submit",
520
+ zh: "\u81F3\u5C11\u9009\u62E9\u4E00\u9879\u624D\u80FD\u63D0\u4EA4"
521
+ },
495
522
  dialogConfirmHint: {
496
523
  en: "(\u2191\u2193 move \xB7 Enter choose \xB7 Esc cancel)",
497
524
  zh: "\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Enter \u9009\u62E9 \xB7 Esc \u53D6\u6D88\uFF09"
@@ -532,7 +559,7 @@ var STRINGS = {
532
559
  en: "abort the operation",
533
560
  zh: "\u4E2D\u6B62\u64CD\u4F5C"
534
561
  },
535
- // --- Ask choice (ui_ask_choice) ------------------------------------------
562
+ // --- Ask choice (ask_user) ------------------------------------------
536
563
  askChoiceTitle: {
537
564
  en: "question",
538
565
  zh: "\u95EE\u9898"
@@ -613,10 +640,6 @@ var STRINGS = {
613
640
  en: "tools",
614
641
  zh: "\u5DE5\u5177"
615
642
  },
616
- contextFieldThinking: {
617
- en: "thinking",
618
- zh: "\u601D\u8003"
619
- },
620
643
  contextFieldServer: {
621
644
  en: "server",
622
645
  zh: "\u670D\u52A1\u7AEF"
@@ -654,7 +677,6 @@ var STRINGS = {
654
677
  " /context Show workspace context and next actions",
655
678
  " /runtime <mode> Use auto, local, or server runtime",
656
679
  " /tools <mode> Control tool trace: hide, compact, verbose",
657
- " /thinking <mode> Control thinking output: hide, marker, show",
658
680
  " /switch Pick an agent interactively (\u2191\u2193, Enter)",
659
681
  " /switch list List agents as text",
660
682
  " /switch <name> Switch directly by name, alias, or key (alias: /agent)",
@@ -691,7 +713,6 @@ var STRINGS = {
691
713
  " /context \u67E5\u770B\u5DE5\u4F5C\u533A\u4E0A\u4E0B\u6587\u4E0E\u540E\u7EED\u64CD\u4F5C",
692
714
  " /runtime <mode> \u5207\u6362 runtime\uFF1Aauto\u3001local\u3001server",
693
715
  " /tools <mode> \u5DE5\u5177\u8F68\u8FF9\u663E\u793A\uFF1Ahide\u3001compact\u3001verbose",
694
- " /thinking <mode> \u601D\u8003\u8FC7\u7A0B\u663E\u793A\uFF1Ahide\u3001marker\u3001show",
695
716
  " /switch \u4EA4\u4E92\u5F0F\u9009\u62E9 agent\uFF08\u2191\u2193 \u79FB\u52A8\uFF0CEnter \u786E\u8BA4\uFF09",
696
717
  " /switch list \u4EE5\u6587\u672C\u5217\u51FA\u5168\u90E8 agent",
697
718
  " /switch <name> \u6309\u540D\u79F0\u3001\u522B\u540D\u6216 key \u76F4\u63A5\u5207\u6362\uFF08\u522B\u540D\uFF1A/agent\uFF09",
@@ -736,12 +757,6 @@ var STRINGS = {
736
757
  },
737
758
  toolsUsage: { en: "Usage: /tools <hide|compact|verbose>", zh: "\u7528\u6CD5\uFF1A/tools <hide|compact|verbose>" },
738
759
  toolsSet: { en: "Tool display: {0}", zh: "\u5DE5\u5177\u663E\u793A\uFF1A{0}" },
739
- thinkingCurrent: {
740
- en: "Thinking display: {0} (hide | marker | show)",
741
- zh: "\u601D\u8003\u663E\u793A\uFF1A{0}\uFF08hide | marker | show\uFF09"
742
- },
743
- thinkingUsage: { en: "Usage: /thinking <hide|marker|show>", zh: "\u7528\u6CD5\uFF1A/thinking <hide|marker|show>" },
744
- thinkingSet: { en: "Thinking display: {0}", zh: "\u601D\u8003\u663E\u793A\uFF1A{0}" },
745
760
  tasksRunning: { en: "Running processes ({0}):", zh: "\u8FD0\u884C\u4E2D\u7684\u8FDB\u7A0B\uFF08{0}\uFF09\uFF1A" },
746
761
  tasksStopped: { en: "Stopped/exited ({0}):", zh: "\u5DF2\u505C\u6B62/\u5DF2\u9000\u51FA\uFF08{0}\uFF09\uFF1A" },
747
762
  tasksNone: { en: "No processes.", zh: "\u6CA1\u6709\u8FD0\u884C\u4E2D\u7684\u8FDB\u7A0B\u3002" },
@@ -935,11 +950,191 @@ function agentRunCardLabels() {
935
950
  runStatus: t("runStatusLabel"),
936
951
  runStarted: t("runStartedLabel"),
937
952
  runStopped: t("runStoppedLabel"),
953
+ runFinished: t("runFinishedLabel"),
938
954
  logTail: t("runLogTailLabel"),
939
955
  runs: (count) => t("runsListLabel", String(count))
940
956
  };
941
957
  }
942
958
 
959
+ // packages/ai/tools/agent/quotaCircuitBreaker.ts
960
+ var QUOTA_ERROR_PATTERNS = [
961
+ /429/,
962
+ /quota/i,
963
+ /rate\s*limit/i,
964
+ /too\s*many\s*requests/i,
965
+ /额度/,
966
+ /上限/,
967
+ /用尽/,
968
+ /CliProviderQuotaError/i
969
+ ];
970
+ var AGENT_NOT_FOUND_PATTERNS = [
971
+ /agent[^\n]{0,80}not\s+found/i,
972
+ /agent[^\n]{0,80}not\s+exist/i,
973
+ /agent[^\n]{0,80}不存在/i,
974
+ /agent[^\n]{0,80}未找到/i,
975
+ /AGENT_NOT_FOUND/
976
+ ];
977
+ var AUTH_ERROR_PATTERNS = [
978
+ /401/,
979
+ /403/,
980
+ /unauthori[sz]ed/i,
981
+ /authentication\s+failed/i,
982
+ /invalid\s+(api[-\s]?key|token|credential)/i,
983
+ /api[-\s]?key\s+(invalid|missing|not\s+found)/i,
984
+ /token\s*(invalid|expired|失效|过期)/i,
985
+ /未授权/,
986
+ /认证失败/,
987
+ /凭证/
988
+ ];
989
+ var NETWORK_ERROR_PATTERNS = [
990
+ /ECONNREFUSED|ECONNRESET|ETIMEDOUT|ENOTFOUND|EHOSTUNREACH|EPIPE/i,
991
+ /getaddrinfo|DNS\s+(error|fail)/i,
992
+ /fetch\s+failed/i,
993
+ /network\s+(error|unreachable|down|disconnected)/i,
994
+ /socket\s+(hang|closed|error)/i,
995
+ /连接失败/,
996
+ /网络错误|网络异常|无法连接/
997
+ ];
998
+ function findActiveBreaker(now, table, target) {
999
+ if (!Number.isFinite(now)) return void 0;
1000
+ for (const entry of table) {
1001
+ if (entry.target !== target) continue;
1002
+ if (typeof entry.until === "number" && entry.until > now) return entry;
1003
+ }
1004
+ return void 0;
1005
+ }
1006
+ function isCliProviderQuotaErrorShape(error) {
1007
+ if (!error || typeof error !== "object") return false;
1008
+ const e = error;
1009
+ return e.name === "CliProviderQuotaError" || typeof e.message === "string" && e.message.startsWith("[QUOTA_LIMITED:");
1010
+ }
1011
+ function isQuotaExhaustedError(error) {
1012
+ if (!error) return false;
1013
+ if (isCliProviderQuotaErrorShape(error)) return true;
1014
+ if (error instanceof Error) {
1015
+ return QUOTA_ERROR_PATTERNS.some((pattern) => pattern.test(error.message));
1016
+ }
1017
+ if (typeof error === "string") {
1018
+ return QUOTA_ERROR_PATTERNS.some((pattern) => pattern.test(error));
1019
+ }
1020
+ const maybeStatus = error.status;
1021
+ if (typeof maybeStatus === "number" && maybeStatus === 429) return true;
1022
+ const maybeStatusCode = error.statusCode;
1023
+ if (typeof maybeStatusCode === "number" && maybeStatusCode === 429) return true;
1024
+ return false;
1025
+ }
1026
+ function isAgentNotFoundError(error) {
1027
+ if (!error) return false;
1028
+ const e = error;
1029
+ if (e.code === "AGENT_NOT_FOUND") return true;
1030
+ const message = typeof e.message === "string" ? e.message : typeof error === "string" ? error : "";
1031
+ if (AGENT_NOT_FOUND_PATTERNS.some((pattern) => pattern.test(message))) return true;
1032
+ if ((e.status === 404 || e.statusCode === 404) && /agent|不存在|未找到/i.test(message)) {
1033
+ return true;
1034
+ }
1035
+ return false;
1036
+ }
1037
+ function extractMessage(error) {
1038
+ if (typeof error === "string") return error;
1039
+ if (error instanceof Error) return error.message;
1040
+ if (error && typeof error === "object") {
1041
+ const m = error.message;
1042
+ return typeof m === "string" ? m : "";
1043
+ }
1044
+ return "";
1045
+ }
1046
+ function extractStatus(error) {
1047
+ if (!error || typeof error !== "object") return void 0;
1048
+ const e = error;
1049
+ const s = typeof e.status === "number" ? e.status : void 0;
1050
+ const sc = typeof e.statusCode === "number" ? e.statusCode : void 0;
1051
+ return s ?? sc;
1052
+ }
1053
+ function parseResetsInMs(text) {
1054
+ if (!text) return void 0;
1055
+ const unitMs = (n, unit) => {
1056
+ if (/^d/.test(unit)) return n * 24 * 3600 * 1e3;
1057
+ if (/^h/.test(unit)) return n * 3600 * 1e3;
1058
+ if (/^m/.test(unit)) return n * 60 * 1e3;
1059
+ if (/^s/.test(unit)) return n * 1e3;
1060
+ return NaN;
1061
+ };
1062
+ const re = /(\d+)\s*(d(?:ay|ays)?|h(?:r|rs|our|ours)?|m(?:in|ins|inute|inutes)?|s(?:ec|ecs|econd|econds)?)/gi;
1063
+ let totalMs = 0;
1064
+ let matched = false;
1065
+ let m;
1066
+ while ((m = re.exec(text)) !== null) {
1067
+ const ms = unitMs(Number(m[1]), m[2]);
1068
+ if (!Number.isFinite(ms)) continue;
1069
+ totalMs += ms;
1070
+ matched = true;
1071
+ }
1072
+ return matched ? totalMs : void 0;
1073
+ }
1074
+ function extractProvider(error) {
1075
+ if (!error || typeof error !== "object") return void 0;
1076
+ const p = error.provider;
1077
+ if (typeof p === "string" && p.length > 0) return p;
1078
+ const message = extractMessage(error);
1079
+ const tag = /\[QUOTA_LIMITED:([^\]]+)\]/i.exec(message);
1080
+ if (tag?.[1]) return tag[1];
1081
+ return void 0;
1082
+ }
1083
+ function extractRetryAfterHeader(error) {
1084
+ if (!error || typeof error !== "object") return void 0;
1085
+ const headers = error.headers;
1086
+ if (!headers || typeof headers !== "object") return void 0;
1087
+ const raw = headers["retry-after"];
1088
+ if (typeof raw !== "string" && typeof raw !== "number") return void 0;
1089
+ const secs = Number(raw);
1090
+ return Number.isFinite(secs) && secs > 0 ? secs * 1e3 : void 0;
1091
+ }
1092
+ function classifyRunFailure(error) {
1093
+ const message = extractMessage(error);
1094
+ const status = extractStatus(error);
1095
+ const retryAfterMs = extractRetryAfterHeader(error) ?? parseResetsInMs(message);
1096
+ if (isQuotaExhaustedError(error)) {
1097
+ return {
1098
+ reason: "quota",
1099
+ provider: extractProvider(error),
1100
+ // 纯函数不取时钟:resetsAt 由调用方用 now + retryAfterMs 计算后补齐
1101
+ retryAfterMs,
1102
+ message
1103
+ };
1104
+ }
1105
+ if (isAgentNotFoundError(error)) {
1106
+ return { reason: "agent-not-found", message };
1107
+ }
1108
+ if (isAuthError(error)) {
1109
+ return { reason: "auth", message };
1110
+ }
1111
+ if (isNetworkError(error)) {
1112
+ return { reason: "network", message };
1113
+ }
1114
+ return { reason: "other", message };
1115
+ }
1116
+ function isAuthError(error) {
1117
+ const message = extractMessage(error);
1118
+ const status = extractStatus(error);
1119
+ if (status === 401 || status === 403) return true;
1120
+ return AUTH_ERROR_PATTERNS.some((pattern) => pattern.test(message));
1121
+ }
1122
+ function isNetworkError(error) {
1123
+ const message = extractMessage(error);
1124
+ return NETWORK_ERROR_PATTERNS.some((pattern) => pattern.test(message));
1125
+ }
1126
+ var DEFAULT_QUOTA_BREAKER_MS = 6 * 3600 * 1e3;
1127
+ var DEFAULT_AGENT_NOT_FOUND_BREAKER_MS = 15 * 60 * 1e3;
1128
+ function buildBreakerEntry(now, target, kind, retryAfterMs) {
1129
+ const ttl = kind === "quota" ? typeof retryAfterMs === "number" && retryAfterMs > 0 ? retryAfterMs : DEFAULT_QUOTA_BREAKER_MS : DEFAULT_AGENT_NOT_FOUND_BREAKER_MS;
1130
+ return {
1131
+ target,
1132
+ kind,
1133
+ until: now + ttl,
1134
+ ...kind === "quota" && typeof retryAfterMs === "number" ? { resetsAt: now + retryAfterMs } : {}
1135
+ };
1136
+ }
1137
+
943
1138
  // packages/cli/client/localRuntimeDiagnostics.ts
944
1139
  import { ulid } from "ulid";
945
1140
  var preparedAgentRuntimeCache = /* @__PURE__ */ new Map();
@@ -979,7 +1174,7 @@ function summarizeOpenAiToolNames(tools) {
979
1174
  }
980
1175
 
981
1176
  // packages/cli/client/localRuntimeAdapter.ts
982
- import { dirname, extname, join } from "node:path";
1177
+ import { dirname as dirname2, extname, join as join2 } from "node:path";
983
1178
  import { fileURLToPath } from "node:url";
984
1179
 
985
1180
  // packages/core/summarizeEndpoint.ts
@@ -1130,6 +1325,11 @@ async function fetchWithTransientRetry(fetchImpl, input, init, options = {}) {
1130
1325
  const attemptBudget = coreDraining ? coreDrainingMaxAttempts : maxAttempts;
1131
1326
  if (attempt < attemptBudget) {
1132
1327
  const delayMs = await resolveRetryAfterMs(response, attempt);
1328
+ options.onRetry?.({
1329
+ attempt: attempt + 1,
1330
+ maxAttempts: attemptBudget,
1331
+ delayMs
1332
+ });
1133
1333
  await (options.sleep ?? defaultSleep)(delayMs);
1134
1334
  continue;
1135
1335
  }
@@ -1143,7 +1343,13 @@ async function fetchWithTransientRetry(fetchImpl, input, init, options = {}) {
1143
1343
  if (!isTransientFetchError(error)) throw error;
1144
1344
  lastError = error;
1145
1345
  if (attempt < maxAttempts) {
1146
- await (options.sleep ?? defaultSleep)(transientFetchRetryDelayMs(attempt));
1346
+ const delayMs = transientFetchRetryDelayMs(attempt);
1347
+ options.onRetry?.({
1348
+ attempt: attempt + 1,
1349
+ maxAttempts,
1350
+ delayMs
1351
+ });
1352
+ await (options.sleep ?? defaultSleep)(delayMs);
1147
1353
  }
1148
1354
  }
1149
1355
  }
@@ -1590,23 +1796,6 @@ async function readAgentFromStore(args) {
1590
1796
  if (!record || typeof record !== "object") continue;
1591
1797
  return resolveAgentRuntimeConfigFromRecord(key, record);
1592
1798
  }
1593
- const normalizedRef = normalizeAgentHandle(args.agentRef);
1594
- if (!normalizedRef) {
1595
- return resolveBuiltinPlatformAgentConfig(args.agentRef);
1596
- }
1597
- try {
1598
- const iterator = args.store.iterator({
1599
- gte: "agent-",
1600
- lte: "agent-\uFFFF"
1601
- });
1602
- for await (const [key, record] of iterator) {
1603
- if (!record || typeof record !== "object") continue;
1604
- const handle = normalizeAgentHandle(record.handle);
1605
- if (handle !== normalizedRef) continue;
1606
- return resolveAgentRuntimeConfigFromRecord(key, record);
1607
- }
1608
- } catch {
1609
- }
1610
1799
  return resolveBuiltinPlatformAgentConfig(args.agentRef);
1611
1800
  }
1612
1801
  async function readDialogMessages(args) {
@@ -1765,7 +1954,10 @@ var LOCAL_SERVER_WEB_TOOL_NAMES = ["fetchWebpage", "exa_search"];
1765
1954
  var LOCAL_SERVER_WEB_TOOL_NAME_SET = new Set(
1766
1955
  LOCAL_SERVER_WEB_TOOL_NAMES
1767
1956
  );
1768
- var LOCAL_SERVER_MEMORY_TOOL_NAMES = ["rememberMemory"];
1957
+ var LOCAL_SERVER_MEMORY_TOOL_NAMES = [
1958
+ "queryMemory",
1959
+ "rememberMemory"
1960
+ ];
1769
1961
  var LOCAL_SERVER_MEMORY_TOOL_NAME_SET = new Set(
1770
1962
  LOCAL_SERVER_MEMORY_TOOL_NAMES
1771
1963
  );
@@ -1997,6 +2189,25 @@ function buildServerPlatformToolExecutors(args) {
1997
2189
  }
1998
2190
  ])
1999
2191
  );
2192
+ const queryMemory = async (call) => {
2193
+ const parsed = parseNoloWorkspaceToolArguments(call.arguments);
2194
+ const query = typeof parsed.query === "string" ? parsed.query.trim() : "";
2195
+ if (!query) {
2196
+ return {
2197
+ content: JSON.stringify({ error: "queryMemory \u9700\u8981\u975E\u7A7A query\u3002" }),
2198
+ metadata: { serverPlatformTool: true, memoryRead: false }
2199
+ };
2200
+ }
2201
+ const body = { userInput: query };
2202
+ if (args.agentKey) body.agentKey = args.agentKey;
2203
+ const raw = await postServer("/api/memory/query", body, {
2204
+ retryTransient: true
2205
+ });
2206
+ return {
2207
+ content: raw,
2208
+ metadata: { serverPlatformTool: true, memoryRead: true }
2209
+ };
2210
+ };
2000
2211
  const rememberMemory = async (call) => {
2001
2212
  const parsed = parseNoloWorkspaceToolArguments(call.arguments);
2002
2213
  const content = typeof parsed.content === "string" ? parsed.content.trim() : "";
@@ -2023,11 +2234,368 @@ function buildServerPlatformToolExecutors(args) {
2023
2234
  metadata: { serverPlatformTool: true, memoryWrite: true }
2024
2235
  };
2025
2236
  };
2026
- return { ...tableExecutors, ...webExecutors, rememberMemory };
2237
+ return { ...tableExecutors, ...webExecutors, queryMemory, rememberMemory };
2238
+ }
2239
+
2240
+ // packages/cli/client/cliAgentRunToolExecutors.ts
2241
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
2242
+
2243
+ // packages/cli/client/agentRunSnapshot.ts
2244
+ function readString(value) {
2245
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
2246
+ }
2247
+ function readLogLines(parsed) {
2248
+ if (Array.isArray(parsed.logLines)) return parsed.logLines;
2249
+ const tail = readString(parsed.logTail);
2250
+ return tail ? tail.split("\n") : void 0;
2251
+ }
2252
+ function readTimestamp(value) {
2253
+ if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
2254
+ if (typeof value === "string" && value.trim()) {
2255
+ const parsed = Date.parse(value);
2256
+ if (Number.isFinite(parsed) && parsed > 0) return parsed;
2257
+ }
2258
+ return void 0;
2259
+ }
2260
+ function readToolNames(value) {
2261
+ if (!Array.isArray(value)) return void 0;
2262
+ const names = value.filter((n) => typeof n === "string" && Boolean(n.trim()));
2263
+ return names.length > 0 ? names : void 0;
2264
+ }
2265
+ function buildSnapshot(parsed, event) {
2266
+ const runId = readString(parsed.runId) ?? readString(event.metadata?.runId) ?? "";
2267
+ const label = resolveRunLabel({
2268
+ agentName: parsed.agentName,
2269
+ name: parsed.name,
2270
+ agentKey: parsed.agentKey
2271
+ });
2272
+ const logLines = readLogLines(parsed);
2273
+ const taskPreview = readString(parsed.taskPreview);
2274
+ const lastToolNames = readToolNames(parsed.lastToolNames);
2275
+ const lastAssistantText = readString(parsed.lastAssistantText);
2276
+ const errorMessage = readString(parsed.errorMessage);
2277
+ const startedAt = readTimestamp(parsed.startedAt);
2278
+ const finishedAt = readTimestamp(parsed.finishedAt) ?? readTimestamp(parsed.endedAt);
2279
+ return {
2280
+ runId,
2281
+ status: readString(parsed.status) ?? "running",
2282
+ // The literal `agent` fallback is dropped here rather than at each render
2283
+ // site: an unnamed run should render no name row, not the word "agent".
2284
+ ...isAgentNameFallback(label) ? {} : { agentName: label },
2285
+ ...taskPreview ? { taskPreview } : {},
2286
+ ...typeof parsed.toolCallCount === "number" && Number.isFinite(parsed.toolCallCount) ? { toolCallCount: parsed.toolCallCount } : {},
2287
+ ...lastToolNames ? { lastToolNames } : {},
2288
+ ...lastAssistantText ? { lastAssistantText } : {},
2289
+ ...errorMessage ? { errorMessage } : {},
2290
+ ...startedAt !== void 0 ? { startedAt } : {},
2291
+ ...finishedAt !== void 0 ? { finishedAt } : {},
2292
+ ...logLines ? { logLines } : {},
2293
+ logKey: logLines && logLines.length > 0 ? logLines.join("\n") : ""
2294
+ };
2295
+ }
2296
+ var STOP_STATUSES = /* @__PURE__ */ new Set(["killed", "cancelled", "cancelling"]);
2297
+ function parseAgentRunEvent(event) {
2298
+ if (event.type !== "tool-result") return null;
2299
+ if (event.toolName !== "startAgentRun" && event.toolName !== "controlAgentRun") {
2300
+ return null;
2301
+ }
2302
+ const raw = typeof event.content === "string" ? event.content.trim() : "";
2303
+ if (!raw.startsWith("{")) return null;
2304
+ let parsed;
2305
+ try {
2306
+ parsed = JSON.parse(raw);
2307
+ } catch {
2308
+ return null;
2309
+ }
2310
+ if (Array.isArray(parsed.runs)) return null;
2311
+ const snapshot = buildSnapshot(parsed, event);
2312
+ const status = readString(parsed.status);
2313
+ if (event.toolName === "startAgentRun") {
2314
+ if (!snapshot.runId) return null;
2315
+ return { kind: "start", snapshot };
2316
+ }
2317
+ if (parsed.found === false || status === "not_found") {
2318
+ return { kind: "gone", snapshot: { ...snapshot, status: "not_found" } };
2319
+ }
2320
+ if (status && STOP_STATUSES.has(status)) {
2321
+ return { kind: "stop", snapshot };
2322
+ }
2323
+ if (!status) return null;
2324
+ if (!snapshot.runId) return null;
2325
+ return { kind: "status", snapshot };
2326
+ }
2327
+
2328
+ // packages/ai/tools/agent/batchAggregation.ts
2329
+ var DEFAULT_BATCH_TIMEOUT_MS = 30 * 60 * 1e3;
2330
+ var MAX_ERROR_SUMMARY_CHARS = 120;
2331
+ var MAX_FAILURE_LINES = 10;
2332
+ function isFailureStatus(status) {
2333
+ return isAgentRunTerminalStatus(status) && status !== "done";
2334
+ }
2335
+ function isOrphanedStatus(status) {
2336
+ return status === "orphaned";
2337
+ }
2338
+ function toEpochMs(iso) {
2339
+ if (!iso) return void 0;
2340
+ const ms = Date.parse(iso);
2341
+ return Number.isFinite(ms) ? ms : void 0;
2342
+ }
2343
+ function isOverTimeout(run, nowMs, timeoutMs) {
2344
+ const startedMs = toEpochMs(run.startedAt);
2345
+ if (startedMs === void 0) return false;
2346
+ return nowMs - startedMs >= timeoutMs;
2347
+ }
2348
+ function truncateErrorSummary(text, max = MAX_ERROR_SUMMARY_CHARS) {
2349
+ if (!text) return "";
2350
+ const collapsed = text.replace(/\s+/g, " ").trim();
2351
+ if (collapsed.length <= max) return collapsed;
2352
+ return `${collapsed.slice(0, max - 1)}\u2026`;
2353
+ }
2354
+ function formatFailureLine(run) {
2355
+ const label = shortRunId(run.runId);
2356
+ const agent = run.agentName ? ` (${run.agentName})` : "";
2357
+ const error = truncateErrorSummary(run.errorSummary);
2358
+ return error ? `\u5931\u8D25: ${label}${agent} \u2014 ${error}` : `\u5931\u8D25: ${label}${agent}`;
2359
+ }
2360
+ function formatBatchSummary(batchId, counts, runs, reason) {
2361
+ const failures = runs.filter((r) => isFailureStatus(r.status));
2362
+ const unfinished = runs.filter((r) => !isAgentRunTerminalStatus(r.status));
2363
+ if (reason === "timeout") {
2364
+ const lines2 = [
2365
+ `\u6279\u6B21 ${batchId}: \u8D85\u65F6\u672A\u6536\u655B \u2014 ${counts.running} \u4E2A\u672A\u5B8C\u6210`
2366
+ ];
2367
+ for (const run of unfinished.slice(0, MAX_FAILURE_LINES)) {
2368
+ const agent = run.agentName ? ` (${run.agentName})` : "";
2369
+ lines2.push(`\u672A\u5B8C\u6210: ${shortRunId(run.runId)}${agent}`);
2370
+ }
2371
+ const rest2 = unfinished.length - MAX_FAILURE_LINES;
2372
+ if (rest2 > 0) lines2.push(`\u2026 \u53CA\u53E6\u5916 ${rest2} \u4E2A\u672A\u5B8C\u6210`);
2373
+ return lines2.join("\n");
2374
+ }
2375
+ const tail = counts.running > 0 ? `, ${counts.running} \u4ECD\u5728\u8DD1` : "";
2376
+ const lines = [
2377
+ `\u6279\u6B21 ${batchId}: ${counts.success + counts.failed}/${counts.total} \u5B8C\u6210 \u2014 ${counts.success} \u6210\u529F, ${counts.failed} \u5931\u8D25${tail}`
2378
+ ];
2379
+ for (const run of failures.slice(0, MAX_FAILURE_LINES)) {
2380
+ lines.push(formatFailureLine(run));
2381
+ }
2382
+ const rest = failures.length - MAX_FAILURE_LINES;
2383
+ if (rest > 0) lines.push(`\u2026 \u53CA\u53E6\u5916 ${rest} \u4E2A\u5931\u8D25`);
2384
+ return lines.join("\n");
2385
+ }
2386
+ function aggregateBatch(input) {
2387
+ const { batchId, runs, now } = input;
2388
+ const timeoutMs = input.timeoutMs ?? DEFAULT_BATCH_TIMEOUT_MS;
2389
+ const notified = new Set(input.notifiedReasons ?? []);
2390
+ const nowMs = toEpochMs(now) ?? 0;
2391
+ let success = 0;
2392
+ let failed = 0;
2393
+ let orphaned = 0;
2394
+ let running = 0;
2395
+ const unfinished = [];
2396
+ let timedOut = false;
2397
+ for (const run of runs) {
2398
+ if (isAgentRunTerminalStatus(run.status)) {
2399
+ if (run.status === "done") success += 1;
2400
+ else {
2401
+ failed += 1;
2402
+ if (isOrphanedStatus(run.status)) orphaned += 1;
2403
+ }
2404
+ } else {
2405
+ running += 1;
2406
+ unfinished.push(run.runId);
2407
+ if (isOverTimeout(run, nowMs, timeoutMs)) timedOut = true;
2408
+ }
2409
+ }
2410
+ const converged = running === 0;
2411
+ let newWakeReasons = [];
2412
+ if (failed > 0 && !notified.has("failure")) {
2413
+ newWakeReasons = ["failure"];
2414
+ } else if (converged && !notified.has("converged")) {
2415
+ newWakeReasons = ["converged"];
2416
+ } else if (timedOut && !notified.has("timeout")) {
2417
+ newWakeReasons = ["timeout"];
2418
+ }
2419
+ const counts = {
2420
+ total: runs.length,
2421
+ success,
2422
+ failed,
2423
+ orphaned,
2424
+ running
2425
+ };
2426
+ const summary = newWakeReasons.length > 0 ? formatBatchSummary(batchId, counts, runs, newWakeReasons[0]) : "";
2427
+ return {
2428
+ batchId,
2429
+ converged,
2430
+ timedOut,
2431
+ counts,
2432
+ newWakeReasons,
2433
+ unfinished,
2434
+ summary
2435
+ };
2436
+ }
2437
+
2438
+ // packages/ai/tools/agent/runtimeTodo.ts
2439
+ var TODO_REVIEW_BLOCK = "BLOCK";
2440
+ function deriveTodoStatus(input) {
2441
+ const { todo, runs } = input;
2442
+ if (todo.status === "abandoned") {
2443
+ return { status: "abandoned" };
2444
+ }
2445
+ if (runs.length === 0) {
2446
+ return { status: todo.status };
2447
+ }
2448
+ if (runs.some((r) => !isAgentRunTerminalStatus(r.status))) {
2449
+ return { status: "running", latestRun: latestRun(runs) };
2450
+ }
2451
+ const latest = latestRun(runs);
2452
+ if (latest?.reviewVerdict === TODO_REVIEW_BLOCK) {
2453
+ return {
2454
+ status: "blocked",
2455
+ latestRun: latest,
2456
+ blockedReason: clipSummary(latest.reviewReason, MAX_ERROR_SUMMARY_CHARS)
2457
+ };
2458
+ }
2459
+ if (latest?.status === "done") {
2460
+ return { status: "done", latestRun: latest };
2461
+ }
2462
+ return { status: "pending", latestRun: latest };
2463
+ }
2464
+ function toEpochMs2(iso) {
2465
+ if (!iso) return void 0;
2466
+ const ms = Date.parse(iso);
2467
+ return Number.isFinite(ms) ? ms : void 0;
2468
+ }
2469
+ function latestRun(runs) {
2470
+ let latest;
2471
+ let latestScore = -1;
2472
+ for (const run of runs) {
2473
+ const score = toEpochMs2(run.finishedAt) ?? toEpochMs2(run.startedAt) ?? -1;
2474
+ if (latest === void 0 || score >= latestScore) {
2475
+ latest = run;
2476
+ latestScore = score;
2477
+ }
2478
+ }
2479
+ return latest;
2480
+ }
2481
+ function clipSummary(text, max) {
2482
+ if (!text) return void 0;
2483
+ const folded = text.replace(/\s+/g, " ").trim();
2484
+ if (folded.length === 0) return void 0;
2485
+ return folded.length > max ? `${folded.slice(0, max - 1)}\u2026` : folded;
2486
+ }
2487
+
2488
+ // packages/cli/client/fileSystemStores.ts
2489
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2490
+ import { homedir as nodeHomedir } from "node:os";
2491
+ import { dirname, join } from "node:path";
2492
+ var nodeFs = {
2493
+ mkdirSync,
2494
+ writeFileSync,
2495
+ readFileSync,
2496
+ existsSync
2497
+ };
2498
+ function resolveNoloHome(env, homedir) {
2499
+ const custom = env?.NOLO_HOME;
2500
+ if (custom && custom.trim()) return custom.trim();
2501
+ return join(homedir(), ".nolo");
2502
+ }
2503
+ function ensureDir(dir, fs) {
2504
+ fs.mkdirSync(dir, { recursive: true });
2505
+ }
2506
+ function readJson(path, fs) {
2507
+ if (!fs.existsSync(path)) return void 0;
2508
+ try {
2509
+ const raw = fs.readFileSync(path, "utf8");
2510
+ return JSON.parse(String(raw));
2511
+ } catch {
2512
+ return void 0;
2513
+ }
2514
+ }
2515
+ function writeJson(path, data, fs) {
2516
+ fs.writeFileSync(path, JSON.stringify(data, null, 2));
2517
+ }
2518
+ function createFileSystemCircuitBreakerStore(opts = {}) {
2519
+ const env = opts.env ?? process.env;
2520
+ const homedir = opts.homedir ?? nodeHomedir;
2521
+ const fs = opts.fs ?? nodeFs;
2522
+ const filePath = opts.filePath ?? join(resolveNoloHome(env, homedir), "breakers.json");
2523
+ const loadMap = () => {
2524
+ const data = readJson(filePath, fs);
2525
+ const map = /* @__PURE__ */ new Map();
2526
+ if (data?.entries) {
2527
+ for (const entry of data.entries) {
2528
+ if (entry && typeof entry.target === "string") map.set(entry.target, entry);
2529
+ }
2530
+ }
2531
+ return map;
2532
+ };
2533
+ const persist = (map) => {
2534
+ ensureDir(dirname(filePath), fs);
2535
+ writeJson(filePath, { entries: [...map.values()] }, fs);
2536
+ };
2537
+ return {
2538
+ get(target) {
2539
+ return loadMap().get(target);
2540
+ },
2541
+ set(entry) {
2542
+ const map = loadMap();
2543
+ map.set(entry.target, entry);
2544
+ persist(map);
2545
+ },
2546
+ clear(target) {
2547
+ const map = loadMap();
2548
+ map.delete(target);
2549
+ persist(map);
2550
+ },
2551
+ clearAll() {
2552
+ persist(/* @__PURE__ */ new Map());
2553
+ }
2554
+ };
2555
+ }
2556
+ function createFileSystemTodoStore(opts = {}) {
2557
+ const env = opts.env ?? process.env;
2558
+ const homedir = opts.homedir ?? nodeHomedir;
2559
+ const fs = opts.fs ?? nodeFs;
2560
+ const filePath = opts.filePath ?? join(resolveNoloHome(env, homedir), "todos.json");
2561
+ const loadMap = () => {
2562
+ const data = readJson(filePath, fs);
2563
+ const map = /* @__PURE__ */ new Map();
2564
+ if (data?.todos) {
2565
+ for (const todo of data.todos) {
2566
+ if (todo && typeof todo.id === "string") map.set(todo.id, todo);
2567
+ }
2568
+ }
2569
+ return map;
2570
+ };
2571
+ const persist = (map) => {
2572
+ ensureDir(dirname(filePath), fs);
2573
+ writeJson(filePath, { todos: [...map.values()] }, fs);
2574
+ };
2575
+ return {
2576
+ async getTodo(id) {
2577
+ return loadMap().get(id);
2578
+ },
2579
+ async listTodos(filter) {
2580
+ const all = [...loadMap().values()];
2581
+ if (!filter?.statuses || filter.statuses.length === 0) return all;
2582
+ const wanted = new Set(filter.statuses);
2583
+ return all.filter((t2) => wanted.has(t2.status));
2584
+ },
2585
+ async putTodo(todo) {
2586
+ const map = loadMap();
2587
+ map.set(todo.id, todo);
2588
+ persist(map);
2589
+ },
2590
+ async deleteTodo(id) {
2591
+ const map = loadMap();
2592
+ map.delete(id);
2593
+ persist(map);
2594
+ }
2595
+ };
2027
2596
  }
2028
2597
 
2029
2598
  // packages/cli/client/cliAgentRunToolExecutors.ts
2030
- import { existsSync, readFileSync } from "node:fs";
2031
2599
  var noopOutput = { write: () => {
2032
2600
  } };
2033
2601
  var parseCallArgs = (call) => {
@@ -2037,7 +2605,7 @@ var parseCallArgs = (call) => {
2037
2605
  return {};
2038
2606
  }
2039
2607
  };
2040
- var resolveFs = (deps) => deps.fs ?? { existsSync, readFileSync };
2608
+ var resolveFs = (deps) => deps.fs ?? { existsSync: existsSync2, readFileSync: readFileSync2 };
2041
2609
  var tailFile = (logPath, tailLines, fs) => {
2042
2610
  if (!fs.existsSync(logPath)) return void 0;
2043
2611
  try {
@@ -2049,6 +2617,10 @@ var tailFile = (logPath, tailLines, fs) => {
2049
2617
  return void 0;
2050
2618
  }
2051
2619
  };
2620
+ var resolveBreakerStore = (deps) => deps.breakerStore ?? createFileSystemCircuitBreakerStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
2621
+ var resolveTodoStore = (deps) => deps.todoStore ?? createFileSystemTodoStore({ env: deps.env, homedir: deps.homedir, fs: deps.fs });
2622
+ var resolveNowMs = (deps) => typeof deps.nowMs === "function" ? deps.nowMs() : Date.now();
2623
+ var resolveTarget = (deps, agentKey) => typeof deps.resolveProviderTarget === "function" ? deps.resolveProviderTarget(agentKey) : agentKey;
2052
2624
  function createCliStartAgentRunExecutor(deps = {}) {
2053
2625
  return async (call) => {
2054
2626
  const args = parseCallArgs(call);
@@ -2056,6 +2628,29 @@ function createCliStartAgentRunExecutor(deps = {}) {
2056
2628
  const task = typeof args.task === "string" ? args.task.trim() : "";
2057
2629
  if (!agentKey) throw new Error("startAgentRun: \u7F3A\u5C11 agentKey \u53C2\u6570\u3002");
2058
2630
  if (!task) throw new Error("startAgentRun: \u7F3A\u5C11\u6709\u6548\u7684 task \u6587\u672C\u63CF\u8FF0\u3002");
2631
+ const breakerStore = resolveBreakerStore(deps);
2632
+ const target = resolveTarget(deps, agentKey);
2633
+ const nowMs = resolveNowMs(deps);
2634
+ const activeBreaker = findActiveBreaker(
2635
+ nowMs,
2636
+ [breakerStore.get(target)].filter(Boolean),
2637
+ target
2638
+ );
2639
+ if (activeBreaker) {
2640
+ const resetsAt = activeBreaker.resetsAt;
2641
+ return {
2642
+ content: JSON.stringify({
2643
+ rejected: true,
2644
+ reason: "quota",
2645
+ provider: target,
2646
+ ...resetsAt !== void 0 ? { resetsAt } : {},
2647
+ message: `provider ${target} \u5904\u4E8E\u7194\u65AD\u671F\uFF08\u914D\u989D\u8017\u5C3D\uFF09\uFF0C\u5EFA\u8BAE\u6539\u6D3E\u5176\u5B83 provider\u3002`
2648
+ }),
2649
+ metadata: {
2650
+ displayData: `Run rejected \xB7 quota breaker active on ${target}`
2651
+ }
2652
+ };
2653
+ }
2059
2654
  const message = typeof args.input === "undefined" ? task : `${task}
2060
2655
 
2061
2656
  --- \u9644\u52A0\u8F93\u5165 ---
@@ -2071,13 +2666,16 @@ ${JSON.stringify(args.input)}`;
2071
2666
  ...args.ephemeral === true ? ["--ephemeral"] : []
2072
2667
  ];
2073
2668
  const agentName = typeof args.agentName === "string" && args.agentName.trim() ? args.agentName.trim() : typeof args.name === "string" && args.name.trim() ? args.name.trim() : void 0;
2074
- const { runId } = await spawnLocalBackgroundRun(
2669
+ const batchId = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
2670
+ const { runId, batchId: resolvedBatchId } = await spawnLocalBackgroundRun(
2075
2671
  {
2076
2672
  rawArgs,
2077
2673
  commandPath: ["agent", "run"],
2078
2674
  cliEntrypointPath: deps.cliEntrypoint,
2079
2675
  agentKey,
2080
2676
  ...agentName ? { agentName } : {},
2677
+ ...batchId ? { batchId } : {},
2678
+ ...typeof args.parentDialogId === "string" && args.parentDialogId.trim() ? { parentDialogId: args.parentDialogId.trim() } : {},
2081
2679
  cwd: deps.cwd ?? process.cwd(),
2082
2680
  message,
2083
2681
  output: noopOutput
@@ -2086,14 +2684,49 @@ ${JSON.stringify(args.input)}`;
2086
2684
  );
2087
2685
  const displayName = resolveRunLabel({ agentName, agentKey, runId });
2088
2686
  const labels = agentRunCardLabels();
2687
+ const taskPreview = typeof args.task === "string" ? args.task.replace(/\s+/g, " ").trim().slice(0, TASK_PREVIEW_MAX) : "";
2688
+ const trackTodo = typeof args.trackTodo === "boolean" ? args.trackTodo : Boolean(resolvedBatchId);
2689
+ if (trackTodo) {
2690
+ try {
2691
+ const todoStore = resolveTodoStore(deps);
2692
+ const todoId = `todo-${resolvedBatchId}`;
2693
+ const existing = await todoStore.getTodo(todoId);
2694
+ const nowIso = new Date(nowMs).toISOString();
2695
+ const runIds = existing?.runIds ?? [];
2696
+ if (!runIds.includes(runId)) runIds.push(runId);
2697
+ const todo = {
2698
+ id: todoId,
2699
+ title: taskPreview || task.slice(0, 100),
2700
+ status: existing?.status ?? "pending",
2701
+ ...existing?.specPath ? { specPath: existing.specPath } : {},
2702
+ ...existing?.worktree ? { worktree: existing.worktree } : {},
2703
+ ...existing?.branch ? { branch: existing.branch } : {},
2704
+ ...deps.cwd ? { worktree: deps.cwd } : {},
2705
+ runIds,
2706
+ deps: existing?.deps ?? [],
2707
+ createdAt: existing?.createdAt ?? nowIso,
2708
+ updatedAt: nowIso
2709
+ };
2710
+ await todoStore.putTodo(todo);
2711
+ } catch {
2712
+ }
2713
+ }
2089
2714
  return {
2090
2715
  content: JSON.stringify({
2091
2716
  runId,
2092
2717
  status: "running",
2093
- ...agentName ? { agentName } : {}
2718
+ // batchId is always returned so the caller can later filter by it —
2719
+ // even when the caller didn't supply one, a fresh id was generated.
2720
+ batchId: resolvedBatchId,
2721
+ ...agentName ? { agentName } : {},
2722
+ ...taskPreview ? { taskPreview } : {}
2094
2723
  }),
2095
2724
  metadata: {
2096
- displayData: formatStartRunCard(displayName, "running", labels)
2725
+ displayData: formatStartRunCard(displayName, "running", {
2726
+ task: taskPreview,
2727
+ runId,
2728
+ labels
2729
+ })
2097
2730
  }
2098
2731
  };
2099
2732
  };
@@ -2104,26 +2737,103 @@ function createCliControlAgentRunExecutor(deps = {}) {
2104
2737
  const action = typeof args.action === "string" ? args.action : "";
2105
2738
  const tailLines = typeof args.tailLines === "number" ? args.tailLines : 0;
2106
2739
  if (action === "list") {
2107
- const records = listRunRecords(deps);
2740
+ gcRunRecords(deps);
2741
+ const { runs: records, total, hasMore } = queryRunRecords(
2742
+ {
2743
+ ...typeof args.batchId === "string" && args.batchId.trim() ? { batchId: args.batchId.trim() } : {},
2744
+ ...typeof args.status === "string" && args.status.trim() ? { status: args.status.trim() } : typeof args.statusFilter === "string" && args.statusFilter.trim() ? { status: args.statusFilter.trim() } : {},
2745
+ ...typeof args.limit === "number" ? { limit: args.limit } : {},
2746
+ ...typeof args.offset === "number" ? { offset: args.offset } : {}
2747
+ },
2748
+ deps
2749
+ );
2108
2750
  const runs = records.map((record2) => {
2109
- const reconciled = checkStaleRun(record2.runId, deps) ?? record2;
2110
2751
  return {
2111
- runId: reconciled.runId,
2112
- status: reconciled.status,
2113
- agentKey: reconciled.agentKey,
2114
- ...reconciled.agentName ? { agentName: reconciled.agentName } : {},
2115
- pid: reconciled.pid ?? null,
2116
- startedAt: reconciled.startedAt
2752
+ runId: record2.runId,
2753
+ status: record2.status,
2754
+ agentKey: record2.agentKey,
2755
+ ...record2.agentName ? { agentName: record2.agentName } : {},
2756
+ ...record2.batchId ? { batchId: record2.batchId } : {},
2757
+ pid: record2.pid ?? null,
2758
+ startedAt: record2.startedAt
2117
2759
  };
2118
2760
  });
2119
2761
  const labels2 = agentRunCardLabels();
2762
+ const batchIdArg = typeof args.batchId === "string" && args.batchId.trim() ? args.batchId.trim() : void 0;
2763
+ let batchSummary;
2764
+ if (batchIdArg && records.length > 0) {
2765
+ const batchRuns = records.map((r) => ({
2766
+ runId: r.runId,
2767
+ status: r.status,
2768
+ startedAt: r.startedAt,
2769
+ ...r.agentName ? { agentName: r.agentName } : {}
2770
+ }));
2771
+ batchSummary = aggregateBatch({
2772
+ batchId: batchIdArg,
2773
+ runs: batchRuns,
2774
+ now: new Date(resolveNowMs(deps)).toISOString()
2775
+ });
2776
+ }
2120
2777
  return {
2121
- content: JSON.stringify({ runs, count: runs.length }),
2778
+ content: JSON.stringify({
2779
+ runs,
2780
+ count: runs.length,
2781
+ total,
2782
+ hasMore,
2783
+ ...batchSummary?.summary ? { batchSummary: batchSummary.summary } : {}
2784
+ }),
2122
2785
  metadata: {
2123
2786
  displayData: formatListRunsCard(runs, labels2)
2124
2787
  }
2125
2788
  };
2126
2789
  }
2790
+ if (action === "todo") {
2791
+ const todoStore = resolveTodoStore(deps);
2792
+ const statusesRaw = typeof args.status === "string" ? args.status.trim() : void 0;
2793
+ const filter = statusesRaw && statusesRaw !== "all" ? { statuses: statusesRaw.split(",").map((s) => s.trim()).filter(Boolean) } : void 0;
2794
+ const todos = await todoStore.listTodos(filter);
2795
+ const enriched = await Promise.all(
2796
+ todos.map(async (todo) => {
2797
+ const runSummaries = [];
2798
+ for (const rid of todo.runIds) {
2799
+ const rec = findRunRecord(rid, deps);
2800
+ if (!rec) continue;
2801
+ runSummaries.push({
2802
+ runId: rec.runId,
2803
+ status: rec.status,
2804
+ startedAt: rec.startedAt,
2805
+ ...rec.agentName ? { agentName: rec.agentName } : {}
2806
+ });
2807
+ }
2808
+ const derived = deriveTodoStatus({
2809
+ todo: { id: todo.id, status: todo.status },
2810
+ runs: runSummaries,
2811
+ now: new Date(resolveNowMs(deps)).toISOString()
2812
+ });
2813
+ return {
2814
+ id: todo.id,
2815
+ title: todo.title,
2816
+ status: derived.status,
2817
+ runIds: todo.runIds,
2818
+ ...derived.blockedReason ? { blockedReason: derived.blockedReason } : {},
2819
+ ...derived.latestRun ? { latestRunId: derived.latestRun.runId, latestRunStatus: derived.latestRun.status } : {},
2820
+ updatedAt: todo.updatedAt
2821
+ };
2822
+ })
2823
+ );
2824
+ return {
2825
+ content: JSON.stringify({ todos: enriched, count: enriched.length }),
2826
+ metadata: {
2827
+ displayData: formatListRunsCard(
2828
+ enriched.map((t2) => ({
2829
+ agentName: t2.title,
2830
+ status: t2.status
2831
+ })),
2832
+ agentRunCardLabels()
2833
+ )
2834
+ }
2835
+ };
2836
+ }
2127
2837
  if (action !== "status" && action !== "stop") {
2128
2838
  throw new Error(`controlAgentRun: \u672A\u77E5 action "${action}"\u3002`);
2129
2839
  }
@@ -2142,6 +2852,25 @@ function createCliControlAgentRunExecutor(deps = {}) {
2142
2852
  const name = resolveRunLabel(reconciled);
2143
2853
  const logLines = logTail ? logTail.split("\n") : void 0;
2144
2854
  const labels2 = agentRunCardLabels();
2855
+ if (reconciled.status === "failed" || reconciled.status === "orphaned") {
2856
+ try {
2857
+ const failureSource = logTail ?? reconciled.note ?? "";
2858
+ const failureInfo = classifyRunFailure(
2859
+ failureSource || reconciled.status
2860
+ );
2861
+ if (failureInfo.reason === "quota") {
2862
+ const t2 = resolveTarget(deps, reconciled.agentKey);
2863
+ const entry = buildBreakerEntry(
2864
+ resolveNowMs(deps),
2865
+ t2,
2866
+ "quota",
2867
+ failureInfo.retryAfterMs
2868
+ );
2869
+ resolveBreakerStore(deps).set(entry);
2870
+ }
2871
+ } catch {
2872
+ }
2873
+ }
2145
2874
  return {
2146
2875
  content: JSON.stringify({
2147
2876
  runId: reconciled.runId,
@@ -2166,7 +2895,15 @@ function createCliControlAgentRunExecutor(deps = {}) {
2166
2895
  ...logLines ? { logLines } : {}
2167
2896
  }),
2168
2897
  metadata: {
2169
- displayData: formatStatusRunCard(name, reconciled.status, { logLines, labels: labels2 })
2898
+ displayData: formatStatusRunCard(name, reconciled.status, {
2899
+ runId: reconciled.runId,
2900
+ timing: {
2901
+ startedAt: readTimestamp(reconciled.startedAt),
2902
+ finishedAt: readTimestamp(reconciled.endedAt)
2903
+ },
2904
+ logLines,
2905
+ labels: labels2
2906
+ })
2170
2907
  }
2171
2908
  };
2172
2909
  }
@@ -2304,7 +3041,7 @@ function buildLocalToolExecutors(args) {
2304
3041
  }
2305
3042
  };
2306
3043
  },
2307
- ui_ask_choice: async (call) => {
3044
+ ask_user: async (call) => {
2308
3045
  const parsedArgs = (() => {
2309
3046
  try {
2310
3047
  return JSON.parse(call.arguments || "{}");
@@ -2320,8 +3057,8 @@ function buildLocalToolExecutors(args) {
2320
3057
  if (!hasQuestions && (!question || choices.length === 0)) {
2321
3058
  return {
2322
3059
  content: JSON.stringify({
2323
- error: "ui_ask_choice",
2324
- detail: "ui_ask_choice \u9700\u8981 question+choices \u6216 questions\u3002"
3060
+ error: "ask_user",
3061
+ detail: "ask_user \u9700\u8981 question+choices \u6216 questions\u3002"
2325
3062
  }),
2326
3063
  metadata: { uiAskChoice: true, error: true }
2327
3064
  };
@@ -2337,7 +3074,7 @@ function buildLocalToolExecutors(args) {
2337
3074
  if (result.kind === "multi-submitted") {
2338
3075
  return {
2339
3076
  content: JSON.stringify({
2340
- type: "ui_ask_choice",
3077
+ type: "ask_user",
2341
3078
  question,
2342
3079
  choices,
2343
3080
  blocking,
@@ -2354,7 +3091,7 @@ function buildLocalToolExecutors(args) {
2354
3091
  if (result.kind === "selected") {
2355
3092
  return {
2356
3093
  content: JSON.stringify({
2357
- type: "ui_ask_choice",
3094
+ type: "ask_user",
2358
3095
  question,
2359
3096
  choices,
2360
3097
  blocking,
@@ -2369,7 +3106,7 @@ function buildLocalToolExecutors(args) {
2369
3106
  }
2370
3107
  return {
2371
3108
  content: JSON.stringify({
2372
- type: "ui_ask_choice",
3109
+ type: "ask_user",
2373
3110
  question,
2374
3111
  choices,
2375
3112
  blocking,
@@ -2384,7 +3121,7 @@ function buildLocalToolExecutors(args) {
2384
3121
  }
2385
3122
  return {
2386
3123
  content: JSON.stringify({
2387
- type: "ui_ask_choice",
3124
+ type: "ask_user",
2388
3125
  question,
2389
3126
  choices,
2390
3127
  blocking,
@@ -2448,19 +3185,22 @@ function resolveAntigravityWireModel(logicalModelId) {
2448
3185
  return { wireModelId: id };
2449
3186
  }
2450
3187
 
2451
- // packages/agent-runtime/antigravityCloudCodeProvider.ts
2452
- var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
3188
+ // packages/agent-runtime/geminiNativeShared.ts
2453
3189
  var SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
2454
- function isGemini3WireModel(modelId) {
3190
+ function isGemini3Model(modelId) {
2455
3191
  return modelId.includes("gemini-3");
2456
3192
  }
2457
3193
  function messageText(content) {
2458
3194
  if (typeof content === "string") return content;
2459
3195
  if (!Array.isArray(content)) return "";
2460
- return content.filter((part) => part?.type === "text").map((part) => part.text).join("\n").trim();
3196
+ return content.filter(
3197
+ (part) => part?.type === "text"
3198
+ ).map((part) => part.text).join("\n").trim();
2461
3199
  }
2462
3200
  function parseDataUrlToInlineData(url) {
2463
- const match = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(url);
3201
+ const match = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(
3202
+ url
3203
+ );
2464
3204
  if (!match) return null;
2465
3205
  return { mimeType: match[1], data: match[2] };
2466
3206
  }
@@ -2477,7 +3217,7 @@ function extractInlineDataParts(content) {
2477
3217
  }
2478
3218
  return parts;
2479
3219
  }
2480
- function convertOpenAiMessagesToCca(messages, options) {
3220
+ function convertOpenAiMessagesToGemini(messages, options) {
2481
3221
  const contents = [];
2482
3222
  const systemTexts = [];
2483
3223
  const toolNamesById = /* @__PURE__ */ new Map();
@@ -2493,9 +3233,11 @@ function convertOpenAiMessagesToCca(messages, options) {
2493
3233
  };
2494
3234
  const flushPendingFunctionCalls = () => {
2495
3235
  if (pendingFunctionCalls.length === 0) return;
2496
- const dummyResponses = pendingFunctionCalls.map(({ name }) => ({
2497
- functionResponse: { name, response: { output: "{}" } }
2498
- }));
3236
+ const dummyResponses = pendingFunctionCalls.map(
3237
+ ({ name }) => ({
3238
+ functionResponse: { name, response: { output: "{}" } }
3239
+ })
3240
+ );
2499
3241
  pendingFunctionCalls = [];
2500
3242
  pushOrMergeContent("user", dummyResponses);
2501
3243
  };
@@ -2504,13 +3246,17 @@ function convertOpenAiMessagesToCca(messages, options) {
2504
3246
  const role = String(raw.role);
2505
3247
  const content = "content" in raw ? raw.content : null;
2506
3248
  if (role === "system") {
2507
- const text = messageText(content);
3249
+ const text = messageText(
3250
+ content
3251
+ );
2508
3252
  if (text) systemTexts.push(text);
2509
3253
  continue;
2510
3254
  }
2511
3255
  if (role === "user") {
2512
3256
  flushPendingFunctionCalls();
2513
- const text = messageText(content);
3257
+ const text = messageText(
3258
+ content
3259
+ );
2514
3260
  const imageParts = extractInlineDataParts(
2515
3261
  content
2516
3262
  );
@@ -2524,7 +3270,9 @@ function convertOpenAiMessagesToCca(messages, options) {
2524
3270
  if (role === "assistant") {
2525
3271
  flushPendingFunctionCalls();
2526
3272
  const parts = [];
2527
- const text = messageText(content);
3273
+ const text = messageText(
3274
+ content
3275
+ );
2528
3276
  if (text) parts.push({ text });
2529
3277
  const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
2530
3278
  for (const call of toolCalls) {
@@ -2534,17 +3282,20 @@ function convertOpenAiMessagesToCca(messages, options) {
2534
3282
  toolNamesById.set(id, name);
2535
3283
  pendingFunctionCalls.push({ name, id });
2536
3284
  const realSignature = typeof call.thought_signature === "string" && call.thought_signature ? call.thought_signature : void 0;
2537
- const isFirstFunctionCallPart = !parts.some((p) => "functionCall" in p);
2538
- parts.push({
3285
+ const isFirstFunctionCallPart = !parts.some(
3286
+ (p) => "functionCall" in p
3287
+ );
3288
+ const signature = realSignature ?? (options.attachSkipThoughtSignature && isFirstFunctionCallPart ? SKIP_THOUGHT_SIGNATURE : void 0);
3289
+ const part = {
2539
3290
  functionCall: {
2540
3291
  name,
2541
- args: parseToolArgumentsJson(call.function?.arguments),
2542
- id
3292
+ args: parseToolArgs(call.function?.arguments),
3293
+ ...id ? { id } : {}
2543
3294
  },
2544
- ...realSignature ? { thoughtSignature: realSignature } : options.attachSkipThoughtSignature && isFirstFunctionCallPart ? { thoughtSignature: SKIP_THOUGHT_SIGNATURE } : {}
2545
- });
3295
+ ...signature ? { thoughtSignature: signature } : {}
3296
+ };
3297
+ parts.push(part);
2546
3298
  }
2547
- if (parts.length === 0) continue;
2548
3299
  pushOrMergeContent("model", parts);
2549
3300
  continue;
2550
3301
  }
@@ -2562,14 +3313,39 @@ function convertOpenAiMessagesToCca(messages, options) {
2562
3313
  }
2563
3314
  const output = messageText(content) || "{}";
2564
3315
  pushOrMergeContent("user", [
2565
- { functionResponse: { name, response: { output } } }
3316
+ {
3317
+ functionResponse: {
3318
+ name,
3319
+ response: { output },
3320
+ // 保留 OpenAI tool_call_id:antigravity Cloud Code Assist 网关把
3321
+ // Gemini contents 转成 Claude messages 时需要 functionResponse →
3322
+ // tool_result 的 tool_use_id;缺 id 时网关报
3323
+ // "tool_result.tool_use_id: Field required"(HTTP 400)。
3324
+ ...toolCallId ? { id: toolCallId } : {}
3325
+ }
3326
+ }
2566
3327
  ]);
2567
3328
  }
2568
3329
  }
2569
3330
  flushPendingFunctionCalls();
2570
3331
  return { contents, systemTexts };
2571
3332
  }
2572
- function convertOpenAiTools(tools) {
3333
+ function parseToolArgs(raw) {
3334
+ if (typeof raw === "string") {
3335
+ try {
3336
+ const parsed = JSON.parse(raw);
3337
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
3338
+ return parsed;
3339
+ }
3340
+ } catch {
3341
+ }
3342
+ }
3343
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
3344
+ return raw;
3345
+ }
3346
+ return {};
3347
+ }
3348
+ function convertOpenAiToolsToGemini(tools) {
2573
3349
  if (!Array.isArray(tools) || tools.length === 0) return void 0;
2574
3350
  const declarations = [];
2575
3351
  for (const tool of tools) {
@@ -2586,79 +3362,7 @@ function convertOpenAiTools(tools) {
2586
3362
  if (declarations.length === 0) return void 0;
2587
3363
  return [{ functionDeclarations: declarations }];
2588
3364
  }
2589
- function buildCloudCodeAssistPayload(args) {
2590
- const projectId = readAntigravityProjectId(args.metadata);
2591
- if (!projectId) {
2592
- throw new Error(
2593
- "Antigravity OAuth credential is missing metadata.projectId. Re-run `nolo auth antigravity`."
2594
- );
2595
- }
2596
- const logicalModel = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gemini-3.1-pro";
2597
- const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
2598
- const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
2599
- const { contents, systemTexts } = convertOpenAiMessagesToCca(rawMessages, {
2600
- attachSkipThoughtSignature: isGemini3WireModel(model)
2601
- });
2602
- if (contents.length === 0) {
2603
- throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
2604
- }
2605
- const prompt = args.agentConfig.prompt?.trim();
2606
- if (prompt) systemTexts.unshift(prompt);
2607
- const request = { contents };
2608
- if (systemTexts.length > 0) {
2609
- request.systemInstruction = {
2610
- role: "user",
2611
- parts: systemTexts.map((text) => ({ text }))
2612
- };
2613
- }
2614
- const tools = convertOpenAiTools(
2615
- Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
2616
- );
2617
- if (tools) {
2618
- request.tools = tools;
2619
- request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
2620
- }
2621
- const generationConfig = {};
2622
- if (profile?.maxOutputTokens) {
2623
- generationConfig.maxOutputTokens = profile.maxOutputTokens;
2624
- } else if (typeof args.agentConfig.max_tokens === "number" && args.agentConfig.max_tokens > 0) {
2625
- generationConfig.maxOutputTokens = args.agentConfig.max_tokens;
2626
- }
2627
- if (typeof args.agentConfig.temperature === "number") {
2628
- generationConfig.temperature = args.agentConfig.temperature;
2629
- }
2630
- if (Object.keys(generationConfig).length > 0) {
2631
- request.generationConfig = generationConfig;
2632
- }
2633
- const agentId = randomUUID();
2634
- const trajectoryId = randomUUID();
2635
- const step = 2;
2636
- const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
2637
- const isClaude = model.toLowerCase().includes("claude");
2638
- const labels = {
2639
- trajectory_id: trajectoryId,
2640
- last_step_index: String(step - 1),
2641
- used_claude: String(isClaude),
2642
- used_claude_conservative: String(isClaude)
2643
- };
2644
- if (profile?.modelEnum) {
2645
- labels.model_enum = profile.modelEnum;
2646
- }
2647
- request.labels = labels;
2648
- request.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
2649
- return {
2650
- url: `${resolveAntigravityCloudCodeBaseUrl(args.agentConfig.customProviderUrl)}${STREAM_PATH}`,
2651
- envelope: {
2652
- project: projectId,
2653
- model,
2654
- request,
2655
- requestId,
2656
- requestType: "agent",
2657
- userAgent: "antigravity"
2658
- }
2659
- };
2660
- }
2661
- function accumulateCcaChunks(chunks) {
3365
+ function accumulateGeminiChunks(chunks) {
2662
3366
  let text = "";
2663
3367
  const toolCalls = [];
2664
3368
  let usage;
@@ -2679,11 +3383,10 @@ function accumulateCcaChunks(chunks) {
2679
3383
  }
2680
3384
  const candidates = Array.isArray(response.candidates) ? response.candidates : [];
2681
3385
  for (const candidate of candidates) {
2682
- if (!candidate || typeof candidate !== "object" || !("content" in candidate)) continue;
2683
- const content = candidate.content;
2684
- if (!content || typeof content !== "object" || !("parts" in content)) continue;
2685
- const parts = content.parts;
2686
- if (!Array.isArray(parts)) continue;
3386
+ if (!candidate || typeof candidate !== "object") continue;
3387
+ const parts = Array.isArray(
3388
+ candidate.content?.parts
3389
+ ) ? candidate.content.parts : [];
2687
3390
  for (const part of parts) {
2688
3391
  if (!part || typeof part !== "object") continue;
2689
3392
  const partSignature = part.thoughtSignature;
@@ -2700,7 +3403,7 @@ function accumulateCcaChunks(chunks) {
2700
3403
  const call = part.functionCall;
2701
3404
  const name = typeof call.name === "string" ? call.name : "tool";
2702
3405
  const id = typeof call.id === "string" ? call.id : `${name}_${toolCalls.length}`;
2703
- const argsObj = asRecordOrEmpty(call.args);
3406
+ const argsObj = call.args && typeof call.args === "object" ? call.args : {};
2704
3407
  const resolvedSignature = typeof partSignature === "string" && partSignature ? partSignature : pendingThoughtSignature;
2705
3408
  pendingThoughtSignature = void 0;
2706
3409
  toolCalls.push({
@@ -2713,7 +3416,114 @@ function accumulateCcaChunks(chunks) {
2713
3416
  }
2714
3417
  }
2715
3418
  }
2716
- return { text, toolCalls, usage };
3419
+ return { text, toolCalls, usage };
3420
+ }
3421
+ function shouldUseGeminiNativeToolRoute(provider, model, tools, isImageModel) {
3422
+ return provider === "google" && !isImageModel(model) && isGemini3Model(model) && Array.isArray(tools) && tools.length > 0;
3423
+ }
3424
+ function buildGeminiGenerateContentRequest(args) {
3425
+ const { contents, systemTexts } = convertOpenAiMessagesToGemini(
3426
+ args.messages,
3427
+ { attachSkipThoughtSignature: args.attachSkipThoughtSignature }
3428
+ );
3429
+ const request = { contents };
3430
+ if (systemTexts.length > 0) {
3431
+ request.systemInstruction = {
3432
+ role: "user",
3433
+ parts: systemTexts.map((text) => ({ text }))
3434
+ };
3435
+ }
3436
+ const toolsResult = convertOpenAiToolsToGemini(args.tools);
3437
+ if (toolsResult) {
3438
+ request.tools = toolsResult;
3439
+ request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
3440
+ }
3441
+ const generationConfig = {};
3442
+ if (typeof args.maxTokens === "number" && args.maxTokens > 0) {
3443
+ generationConfig.maxOutputTokens = args.maxTokens;
3444
+ }
3445
+ if (typeof args.temperature === "number") {
3446
+ generationConfig.temperature = args.temperature;
3447
+ }
3448
+ if (Object.keys(generationConfig).length > 0) {
3449
+ request.generationConfig = generationConfig;
3450
+ }
3451
+ return request;
3452
+ }
3453
+
3454
+ // packages/agent-runtime/antigravityCloudCodeProvider.ts
3455
+ var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
3456
+ function buildCloudCodeAssistPayload(args) {
3457
+ const projectId = readAntigravityProjectId(args.metadata);
3458
+ if (!projectId) {
3459
+ throw new Error(
3460
+ "Antigravity OAuth credential is missing metadata.projectId. Re-run `nolo auth antigravity`."
3461
+ );
3462
+ }
3463
+ const logicalModel = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gemini-3.1-pro";
3464
+ const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
3465
+ const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
3466
+ const isClaude = model.toLowerCase().includes("claude");
3467
+ const { contents, systemTexts } = convertOpenAiMessagesToGemini(rawMessages, {
3468
+ attachSkipThoughtSignature: isGemini3Model(model)
3469
+ });
3470
+ if (contents.length === 0) {
3471
+ throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
3472
+ }
3473
+ const prompt = args.agentConfig.prompt?.trim();
3474
+ if (prompt) systemTexts.unshift(prompt);
3475
+ const request = { contents };
3476
+ if (systemTexts.length > 0) {
3477
+ request.systemInstruction = {
3478
+ role: "user",
3479
+ parts: systemTexts.map((text) => ({ text }))
3480
+ };
3481
+ }
3482
+ const tools = convertOpenAiToolsToGemini(
3483
+ Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
3484
+ );
3485
+ if (tools) {
3486
+ request.tools = tools;
3487
+ request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
3488
+ }
3489
+ const generationConfig = {};
3490
+ if (profile?.maxOutputTokens) {
3491
+ generationConfig.maxOutputTokens = profile.maxOutputTokens;
3492
+ } else if (typeof args.agentConfig.max_tokens === "number" && args.agentConfig.max_tokens > 0) {
3493
+ generationConfig.maxOutputTokens = args.agentConfig.max_tokens;
3494
+ }
3495
+ if (typeof args.agentConfig.temperature === "number") {
3496
+ generationConfig.temperature = args.agentConfig.temperature;
3497
+ }
3498
+ if (Object.keys(generationConfig).length > 0) {
3499
+ request.generationConfig = generationConfig;
3500
+ }
3501
+ const agentId = randomUUID();
3502
+ const trajectoryId = randomUUID();
3503
+ const step = 2;
3504
+ const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
3505
+ const labels = {
3506
+ trajectory_id: trajectoryId,
3507
+ last_step_index: String(step - 1),
3508
+ used_claude: String(isClaude),
3509
+ used_claude_conservative: String(isClaude)
3510
+ };
3511
+ if (profile?.modelEnum) {
3512
+ labels.model_enum = profile.modelEnum;
3513
+ }
3514
+ request.labels = labels;
3515
+ request.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
3516
+ return {
3517
+ url: `${resolveAntigravityCloudCodeBaseUrl(args.agentConfig.customProviderUrl)}${STREAM_PATH}`,
3518
+ envelope: {
3519
+ project: projectId,
3520
+ model,
3521
+ request,
3522
+ requestId,
3523
+ requestType: "agent",
3524
+ userAgent: "antigravity"
3525
+ }
3526
+ };
2717
3527
  }
2718
3528
  async function readSseJsonChunks(response) {
2719
3529
  return readSseDataValues(response, parseSseDataLineJson);
@@ -2739,7 +3549,7 @@ async function fetchAntigravityCloudCodeCompletion(args) {
2739
3549
  };
2740
3550
  }
2741
3551
  const chunks = await readSseJsonChunks(response);
2742
- const { text, toolCalls, usage } = accumulateCcaChunks(chunks);
3552
+ const { text, toolCalls, usage } = accumulateGeminiChunks(chunks);
2743
3553
  const message = {
2744
3554
  role: "assistant",
2745
3555
  content: text || null
@@ -2775,9 +3585,67 @@ var CLAUDE_CODE_IDENTITY_PATTERNS = [
2775
3585
  CLAUDE_CODE_SYSTEM_INSTRUCTION,
2776
3586
  "You are Claude Code"
2777
3587
  ];
3588
+ var REASONING_EFFORT_TO_BUDGET = {
3589
+ minimal: 2048,
3590
+ low: 4096,
3591
+ medium: 8192,
3592
+ high: 16384,
3593
+ xhigh: 32e3,
3594
+ max: 32e3
3595
+ };
3596
+ function resolveThinkingBudget(effort) {
3597
+ if (!effort) return void 0;
3598
+ const normalized = effort.toLowerCase();
3599
+ if (normalized === "none" || normalized === "off") return void 0;
3600
+ return REASONING_EFFORT_TO_BUDGET[normalized];
3601
+ }
3602
+ var DEFAULT_THINKING_EFFORT = "medium";
3603
+ var DEFAULT_ENABLED_BUDGET = 8192;
3604
+ var DEFAULT_ENABLE_THINKING_BUDGET = 8e3;
3605
+ var ANTHROPIC_EFFORT_ALIASES = { minimal: "low" };
3606
+ function resolveThinkingSpec(input) {
3607
+ const { model, maxTokens } = input;
3608
+ const normalizedEffort = input.reasoningEffort?.toLowerCase();
3609
+ const effortDisabled = normalizedEffort === "none" || normalizedEffort === "off";
3610
+ const effectiveEffort = normalizedEffort !== void 0 && !effortDisabled ? ANTHROPIC_EFFORT_ALIASES[normalizedEffort] ?? normalizedEffort : DEFAULT_THINKING_EFFORT;
3611
+ let thinkingBlock;
3612
+ let outputConfig;
3613
+ let finalMaxTokens = maxTokens;
3614
+ let finalTemperature = input.temperature;
3615
+ if (isAdaptiveThinkingModelId(model)) {
3616
+ if (effortDisabled) {
3617
+ thinkingBlock = { type: "disabled" };
3618
+ } else {
3619
+ thinkingBlock = { type: "adaptive", display: "summarized" };
3620
+ outputConfig = { effort: effectiveEffort };
3621
+ }
3622
+ } else {
3623
+ const injected = input.injectedThinking;
3624
+ const injectedBudget = injected?.type === "enabled" && typeof injected.budget_tokens === "number" ? injected.budget_tokens : void 0;
3625
+ const effortBudget = resolveThinkingBudget(input.reasoningEffort);
3626
+ const fallbackBudget = input.reasoningEffort === void 0 ? injectedBudget ?? (input.enableThinking === true ? typeof input.thinkingBudget === "number" ? input.thinkingBudget : DEFAULT_ENABLE_THINKING_BUDGET : DEFAULT_ENABLED_BUDGET) : void 0;
3627
+ const thinkingBudget = effortBudget ?? fallbackBudget;
3628
+ if (thinkingBudget !== void 0) {
3629
+ thinkingBlock = { type: "enabled", budget_tokens: thinkingBudget };
3630
+ finalMaxTokens = Math.max(maxTokens, thinkingBudget + 1);
3631
+ finalTemperature = 1;
3632
+ }
3633
+ }
3634
+ return {
3635
+ thinkingBlock,
3636
+ outputConfig,
3637
+ maxTokens: finalMaxTokens,
3638
+ temperature: finalTemperature
3639
+ };
3640
+ }
2778
3641
  function stringValue(value) {
2779
3642
  return typeof value === "string" && value.length > 0 ? value : void 0;
2780
3643
  }
3644
+ function isCacheControl(value) {
3645
+ return Boolean(
3646
+ value && typeof value === "object" && !Array.isArray(value) && typeof value.type === "string"
3647
+ );
3648
+ }
2781
3649
  function toAnthropicContent(content) {
2782
3650
  if (typeof content === "string") {
2783
3651
  return content.length > 0 ? [{ type: "text", text: content }] : [];
@@ -2788,17 +3656,23 @@ function toAnthropicContent(content) {
2788
3656
  if (!raw || typeof raw !== "object") continue;
2789
3657
  const part = raw;
2790
3658
  if ((part.type === "text" || part.type === "input_text") && typeof part.text === "string") {
2791
- if (part.text.length > 0) blocks.push({ type: "text", text: part.text });
3659
+ if (part.text.length > 0) {
3660
+ const block2 = { type: "text", text: part.text };
3661
+ if (isCacheControl(part.cache_control)) block2.cache_control = part.cache_control;
3662
+ blocks.push(block2);
3663
+ }
2792
3664
  continue;
2793
3665
  }
2794
3666
  if (part.type !== "image_url") continue;
2795
3667
  const imageUrl = typeof part.image_url === "string" ? part.image_url : stringValue(part.image_url?.url);
2796
3668
  if (!imageUrl) continue;
2797
3669
  const dataMatch = imageUrl.match(/^data:([^;,]+);base64,(.+)$/s);
2798
- blocks.push({
3670
+ const block = {
2799
3671
  type: "image",
2800
3672
  source: dataMatch ? { type: "base64", media_type: dataMatch[1], data: dataMatch[2] } : { type: "url", url: imageUrl }
2801
- });
3673
+ };
3674
+ if (isCacheControl(part.cache_control)) block.cache_control = part.cache_control;
3675
+ blocks.push(block);
2802
3676
  }
2803
3677
  return blocks;
2804
3678
  }
@@ -2832,7 +3706,15 @@ function buildAnthropicMessagesBody(args) {
2832
3706
  const message = raw;
2833
3707
  const role = String(message.role ?? "");
2834
3708
  if (role === "system" || role === "developer") {
2835
- system.push(...toAnthropicContent(message.content));
3709
+ const stablePrefixChars = Number(message.stable_prefix_chars);
3710
+ if (typeof message.content === "string" && Number.isFinite(stablePrefixChars) && stablePrefixChars > 0 && stablePrefixChars <= message.content.length) {
3711
+ const stable = message.content.slice(0, stablePrefixChars);
3712
+ const dynamic = message.content.slice(stablePrefixChars);
3713
+ system.push({ type: "text", text: stable, cache_control: { type: "ephemeral" } });
3714
+ if (dynamic) system.push({ type: "text", text: dynamic });
3715
+ } else {
3716
+ system.push(...toAnthropicContent(message.content));
3717
+ }
2836
3718
  continue;
2837
3719
  }
2838
3720
  if (role === "tool") {
@@ -2874,6 +3756,9 @@ function buildAnthropicMessagesBody(args) {
2874
3756
  if (!hasClaudeCodeIdentity(system)) {
2875
3757
  system.unshift({ type: "text", text: CLAUDE_CODE_SYSTEM_INSTRUCTION });
2876
3758
  }
3759
+ if (system.length > 0 && !system.some((block) => isCacheControl(block.cache_control))) {
3760
+ system[system.length - 1].cache_control = { type: "ephemeral" };
3761
+ }
2877
3762
  const tools = Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools.flatMap((raw) => {
2878
3763
  if (!raw || typeof raw !== "object") return [];
2879
3764
  const fn = raw.function;
@@ -2888,14 +3773,39 @@ function buildAnthropicMessagesBody(args) {
2888
3773
  const model = stringValue(args.openAiBody.model) ?? args.agentConfig.model ?? "claude-sonnet-5";
2889
3774
  const maxTokensRaw = args.openAiBody.max_completion_tokens ?? args.openAiBody.max_tokens ?? args.agentConfig.max_tokens;
2890
3775
  const maxTokens = typeof maxTokensRaw === "number" && Number.isFinite(maxTokensRaw) ? Math.max(1, Math.floor(maxTokensRaw)) : 8192;
3776
+ const reasoningEffort = stringValue(args.openAiBody.reasoning_effort) ?? stringValue(args.agentConfig.reasoning_effort);
3777
+ const spec = resolveThinkingSpec({
3778
+ model,
3779
+ reasoningEffort,
3780
+ maxTokens,
3781
+ temperature: typeof args.openAiBody.temperature === "number" ? args.openAiBody.temperature : args.agentConfig.temperature,
3782
+ injectedThinking: args.openAiBody.thinking,
3783
+ enableThinking: args.agentConfig.enableThinking,
3784
+ thinkingBudget: args.agentConfig.thinkingBudget
3785
+ });
3786
+ const { thinkingBlock, outputConfig } = spec;
3787
+ const finalMaxTokens = spec.maxTokens;
3788
+ const finalTemperature = spec.temperature;
3789
+ if (messages.length > 0) {
3790
+ const lastMessage = messages[messages.length - 1];
3791
+ const content = Array.isArray(lastMessage.content) ? lastMessage.content : [];
3792
+ if (content.length > 0) {
3793
+ const lastBlock = content[content.length - 1];
3794
+ if (!isCacheControl(lastBlock.cache_control)) {
3795
+ lastBlock.cache_control = { type: "ephemeral" };
3796
+ }
3797
+ }
3798
+ }
2891
3799
  return {
2892
3800
  model,
2893
3801
  messages,
2894
- max_tokens: maxTokens,
3802
+ max_tokens: finalMaxTokens,
2895
3803
  stream: false,
3804
+ ...thinkingBlock ? { thinking: thinkingBlock } : {},
3805
+ ...outputConfig ? { output_config: outputConfig } : {},
2896
3806
  ...system.length > 0 ? { system } : {},
2897
3807
  ...tools.length > 0 ? { tools } : {},
2898
- ...typeof args.openAiBody.temperature === "number" ? { temperature: args.openAiBody.temperature } : typeof args.agentConfig.temperature === "number" ? { temperature: args.agentConfig.temperature } : {},
3808
+ ...typeof finalTemperature === "number" ? { temperature: finalTemperature } : {},
2899
3809
  ...typeof args.openAiBody.top_p === "number" ? { top_p: args.openAiBody.top_p } : {}
2900
3810
  };
2901
3811
  }
@@ -2919,6 +3829,8 @@ function mapAnthropicMessageToOpenAi(payload) {
2919
3829
  }
2920
3830
  const usage = payload.usage ?? {};
2921
3831
  const inputTokens = (typeof usage.input_tokens === "number" ? usage.input_tokens : 0) + (typeof usage.cache_creation_input_tokens === "number" ? usage.cache_creation_input_tokens : 0) + (typeof usage.cache_read_input_tokens === "number" ? usage.cache_read_input_tokens : 0);
3832
+ const cacheCreationInputTokens = typeof usage.cache_creation_input_tokens === "number" ? usage.cache_creation_input_tokens : 0;
3833
+ const cacheReadInputTokens = typeof usage.cache_read_input_tokens === "number" ? usage.cache_read_input_tokens : 0;
2922
3834
  const outputTokens = typeof usage.output_tokens === "number" ? usage.output_tokens : 0;
2923
3835
  const stopReason = String(payload.stop_reason ?? "");
2924
3836
  const message = { role: "assistant", content: text || null };
@@ -2934,9 +3846,16 @@ function mapAnthropicMessageToOpenAi(payload) {
2934
3846
  finish_reason: toolCalls.length > 0 || stopReason === "tool_use" ? "tool_calls" : stopReason === "max_tokens" ? "length" : "stop"
2935
3847
  }],
2936
3848
  usage: {
3849
+ // prompt_tokens/input_tokens are total input, including cache read/write.
3850
+ // Preserve Anthropic's components so normalization and billing can apply
3851
+ // the correct cache prices without double-counting them.
2937
3852
  prompt_tokens: inputTokens,
3853
+ input_tokens: inputTokens,
2938
3854
  completion_tokens: outputTokens,
2939
- total_tokens: inputTokens + outputTokens
3855
+ output_tokens: outputTokens,
3856
+ total_tokens: inputTokens + outputTokens,
3857
+ cache_creation_input_tokens: cacheCreationInputTokens,
3858
+ cache_read_input_tokens: cacheReadInputTokens
2940
3859
  }
2941
3860
  };
2942
3861
  }
@@ -9011,6 +9930,262 @@ function isCursorOAuthAgent(agent) {
9011
9930
  return agent.apiKeyRef?.trim().toLowerCase() === "cursor";
9012
9931
  }
9013
9932
 
9933
+ // packages/agent-runtime/codexResponsesProvider.ts
9934
+ import { randomUUID as randomUUID4 } from "node:crypto";
9935
+ var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
9936
+ var CODEX_CLIENT_VERSION = "0.144.1";
9937
+ var CODEX_ORIGINATOR = "codex_cli_rs";
9938
+ var CODEX_OPENAI_BETA = "responses=experimental";
9939
+ var OPENAI_AUTH_CLAIM = "https://api.openai.com/auth";
9940
+ var CODEX_INSTALLATION_ID = randomUUID4();
9941
+ function decodeCodexAccountId(accessToken) {
9942
+ const parts = accessToken.split(".");
9943
+ if (parts.length < 2) return void 0;
9944
+ try {
9945
+ const payload = JSON.parse(
9946
+ Buffer.from(parts[1], "base64").toString("utf8")
9947
+ );
9948
+ const claim = payload[OPENAI_AUTH_CLAIM];
9949
+ const value = claim && typeof claim === "object" ? claim.chatgpt_account_id : void 0;
9950
+ return typeof value === "string" && value ? value : void 0;
9951
+ } catch {
9952
+ return void 0;
9953
+ }
9954
+ }
9955
+ function createCodexRequestIdentity(installationId = CODEX_INSTALLATION_ID) {
9956
+ const sessionId = randomUUID4();
9957
+ const threadId = randomUUID4();
9958
+ const windowId = randomUUID4();
9959
+ const turnId = randomUUID4();
9960
+ const turnMetadata = {
9961
+ installation_id: installationId,
9962
+ session_id: sessionId,
9963
+ thread_id: threadId,
9964
+ turn_id: turnId,
9965
+ window_id: windowId,
9966
+ request_kind: "turn",
9967
+ turn_started_at_unix_ms: Date.now()
9968
+ };
9969
+ const turnMetadataJson = JSON.stringify(turnMetadata);
9970
+ return {
9971
+ sessionId,
9972
+ threadId,
9973
+ windowId,
9974
+ turnId,
9975
+ turnMetadataJson,
9976
+ clientMetadata: {
9977
+ "x-codex-installation-id": installationId,
9978
+ session_id: sessionId,
9979
+ thread_id: threadId,
9980
+ "x-codex-window-id": windowId,
9981
+ turn_id: turnId,
9982
+ "x-codex-turn-metadata": turnMetadataJson
9983
+ }
9984
+ };
9985
+ }
9986
+ function buildCodexCompatibilityHeaders(identity, accountId) {
9987
+ return {
9988
+ Authorization: "",
9989
+ // filled by caller with bearer token
9990
+ "Content-Type": "application/json",
9991
+ Accept: "text/event-stream",
9992
+ "chatgpt-account-id": accountId,
9993
+ "OpenAI-Beta": CODEX_OPENAI_BETA,
9994
+ originator: CODEX_ORIGINATOR,
9995
+ version: CODEX_CLIENT_VERSION,
9996
+ session_id: identity.sessionId,
9997
+ conversation_id: identity.sessionId,
9998
+ "x-client-request-id": identity.sessionId,
9999
+ "session-id": identity.sessionId,
10000
+ "thread-id": identity.threadId,
10001
+ "x-codex-window-id": identity.windowId,
10002
+ "x-codex-turn-metadata": identity.turnMetadataJson
10003
+ };
10004
+ }
10005
+ function collectInstructions(messages, agentPrompt) {
10006
+ const systemTexts = [];
10007
+ const prompt = agentPrompt?.trim();
10008
+ if (prompt) systemTexts.push(prompt);
10009
+ for (const raw of messages) {
10010
+ if (!raw || typeof raw !== "object") continue;
10011
+ const role = String(raw.role ?? "");
10012
+ if (role !== "system" && role !== "developer") continue;
10013
+ const content = raw.content;
10014
+ const stringContent = asOptionalTrimmedString(content);
10015
+ if (stringContent) {
10016
+ systemTexts.push(stringContent);
10017
+ } else if (Array.isArray(content)) {
10018
+ const text = content.filter(
10019
+ (p) => !!p && p.type === "text"
10020
+ ).map((p) => p.text).join("\n").trim();
10021
+ if (text) systemTexts.push(text);
10022
+ }
10023
+ }
10024
+ return systemTexts.join("\n\n");
10025
+ }
10026
+ function collectStableInstructions(messages, fallbackPrompt) {
10027
+ const systemTexts = [];
10028
+ if (fallbackPrompt?.trim()) systemTexts.push(fallbackPrompt.trim());
10029
+ for (const raw of messages) {
10030
+ if (!raw || typeof raw !== "object") continue;
10031
+ const message = raw;
10032
+ const role = String(message.role ?? "");
10033
+ if (role !== "system" && role !== "developer") continue;
10034
+ if (typeof message.content === "string") {
10035
+ const boundary = Number(message.stable_prefix_chars);
10036
+ const text = Number.isFinite(boundary) && boundary > 0 ? message.content.slice(0, boundary) : message.content;
10037
+ if (text.trim()) systemTexts.push(text.trim());
10038
+ }
10039
+ }
10040
+ return systemTexts.join("\n\n");
10041
+ }
10042
+ function stablePromptCacheKey(parts) {
10043
+ const value = JSON.stringify(parts);
10044
+ let hash = 2166136261;
10045
+ for (let index = 0; index < value.length; index += 1) {
10046
+ hash ^= value.charCodeAt(index);
10047
+ hash = Math.imul(hash, 16777619) >>> 0;
10048
+ }
10049
+ return `nolo-codex-${hash.toString(16).padStart(8, "0")}`;
10050
+ }
10051
+ function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
10052
+ const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
10053
+ const nonSystem = rawMessages.filter((m) => {
10054
+ const role = m && typeof m === "object" ? String(m.role) : "";
10055
+ return role !== "system" && role !== "developer";
10056
+ });
10057
+ const input = convertMessagesToResponsesInput(nonSystem);
10058
+ const instructions = collectInstructions(rawMessages, args.agentConfig.prompt);
10059
+ const stableInstructions = collectStableInstructions(rawMessages, args.agentConfig.prompt);
10060
+ const model = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gpt-5.5";
10061
+ const tools = toResponsesTools(
10062
+ Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
10063
+ );
10064
+ const body = {
10065
+ model,
10066
+ input,
10067
+ stream: true,
10068
+ store: false,
10069
+ // Keep routing stable across turns and request UUIDs. Growing input/history
10070
+ // is intentionally excluded; only stable request-prefix material belongs.
10071
+ prompt_cache_key: stablePromptCacheKey([model, stableInstructions, tools ?? []]),
10072
+ client_metadata: identity.clientMetadata
10073
+ };
10074
+ if (instructions) body.instructions = instructions;
10075
+ if (tools && tools.length > 0) {
10076
+ body.tools = tools;
10077
+ body.tool_choice = "auto";
10078
+ body.parallel_tool_calls = true;
10079
+ }
10080
+ return body;
10081
+ }
10082
+ function aggregateResponsesStream(events) {
10083
+ let text = "";
10084
+ const toolCalls = [];
10085
+ let usage;
10086
+ for (const ev of events) {
10087
+ const type = String(ev.type ?? "");
10088
+ if (type === "response.output_text.delta" && typeof ev.delta === "string") {
10089
+ text += ev.delta;
10090
+ continue;
10091
+ }
10092
+ if (type === "response.output_item.done") {
10093
+ const item = ev.item;
10094
+ if (item && item.type === "function_call") {
10095
+ const name = typeof item.name === "string" ? item.name : "";
10096
+ if (name) {
10097
+ toolCalls.push({
10098
+ id: typeof item.call_id === "string" && item.call_id ? item.call_id : `${name}_${toolCalls.length}`,
10099
+ type: "function",
10100
+ function: {
10101
+ name,
10102
+ arguments: typeof item.arguments === "string" ? item.arguments : "{}"
10103
+ }
10104
+ });
10105
+ }
10106
+ }
10107
+ continue;
10108
+ }
10109
+ if (type === "response.completed") {
10110
+ const response = ev.response;
10111
+ const u = response?.usage;
10112
+ if (u) {
10113
+ const prompt = typeof u.input_tokens === "number" ? u.input_tokens : 0;
10114
+ const completion = typeof u.output_tokens === "number" ? u.output_tokens : 0;
10115
+ const total = typeof u.total_tokens === "number" ? u.total_tokens : prompt + completion;
10116
+ usage = {
10117
+ prompt_tokens: prompt,
10118
+ completion_tokens: completion,
10119
+ total_tokens: total
10120
+ };
10121
+ }
10122
+ }
10123
+ }
10124
+ return { text, toolCalls, usage };
10125
+ }
10126
+ async function readSseEvents(response) {
10127
+ return readSseDataValues(response, (line) => {
10128
+ const ev = parseSseDataLineObject(line);
10129
+ return ev && !Array.isArray(ev) ? ev : null;
10130
+ });
10131
+ }
10132
+ async function fetchCodexResponsesCompletion(args) {
10133
+ const fetchImpl = args.fetchImpl ?? fetch;
10134
+ const accountId = args.accountId?.trim() || decodeCodexAccountId(args.accessToken);
10135
+ if (!accountId) {
10136
+ return {
10137
+ status: 401,
10138
+ body: {
10139
+ error: {
10140
+ message: "ChatGPT Codex credential is missing chatgpt_account_id. Re-run `nolo auth chatgpt`."
10141
+ }
10142
+ }
10143
+ };
10144
+ }
10145
+ const identity = createCodexRequestIdentity();
10146
+ const body = buildCodexRequestBody(args, identity);
10147
+ const headers = buildCodexCompatibilityHeaders(identity, accountId);
10148
+ headers.Authorization = `Bearer ${args.accessToken}`;
10149
+ const response = await fetchImpl(CODEX_RESPONSES_URL, {
10150
+ method: "POST",
10151
+ headers,
10152
+ body: JSON.stringify(body),
10153
+ signal: args.signal
10154
+ });
10155
+ if (!response.ok) {
10156
+ const errorText = await response.text();
10157
+ return {
10158
+ status: response.status,
10159
+ body: { error: { message: errorText || response.statusText } }
10160
+ };
10161
+ }
10162
+ const events = await readSseEvents(response);
10163
+ const { text, toolCalls, usage } = aggregateResponsesStream(events);
10164
+ const message = {
10165
+ role: "assistant",
10166
+ content: text || null
10167
+ };
10168
+ if (toolCalls.length > 0) message.tool_calls = toolCalls;
10169
+ return {
10170
+ status: 200,
10171
+ body: {
10172
+ choices: [
10173
+ {
10174
+ index: 0,
10175
+ message,
10176
+ finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop"
10177
+ }
10178
+ ],
10179
+ ...usage ? { usage } : {}
10180
+ }
10181
+ };
10182
+ }
10183
+ function isCodexOAuthAgent(agentConfig) {
10184
+ if (!agentConfig) return false;
10185
+ const apiKeyRef = asTrimmedLowercaseString(agentConfig.apiKeyRef);
10186
+ return apiKeyRef === "chatgpt";
10187
+ }
10188
+
9014
10189
  // packages/agent-runtime/oauthProviders.ts
9015
10190
  var XAI_ACCESS_TOKEN_CLIENT_SKEW_MS = 5 * 60 * 1e3;
9016
10191
  var decodeBase64 = (s) => Buffer.from(s, "base64").toString("utf8");
@@ -9504,7 +10679,7 @@ function buildOpenAiTools(args) {
9504
10679
  const toolset = buildLocalWorkspaceToolsetForEnv(args);
9505
10680
  const toolNameSet = new Set(args.toolNames ?? []);
9506
10681
  const callAgentTools = toolNameSet.has("callAgent") ? prepareTools(["callAgent"]) : [];
9507
- const uiAskChoiceTools = toolNameSet.has("ui_ask_choice") ? prepareTools(["ui_ask_choice"]) : [];
10682
+ const uiAskChoiceTools = toolNameSet.has("ask_user") ? prepareTools(["ask_user"]) : [];
9508
10683
  const readPastedTextTools = toolNameSet.has("readPastedText") ? [
9509
10684
  {
9510
10685
  type: "function",
@@ -9564,10 +10739,10 @@ function buildOpenAiTools(args) {
9564
10739
  var CLI_DEFAULT_TOOLS = ["exa_search", "fetchWebpage"];
9565
10740
  function addDefaultCliCoreTools(toolNames, env, options) {
9566
10741
  const declaredOnly = env && shouldUseDeclaredOnlyLocalWorkspaceTools(env);
9567
- const forcedTools = options?.hasUserChoice === true ? FORCED_TOOLS : FORCED_TOOLS.filter((name) => name !== "ui_ask_choice");
10742
+ const forcedTools = options?.hasUserChoice === true ? FORCED_TOOLS : FORCED_TOOLS.filter((name) => name !== "ask_user");
9568
10743
  const injected = declaredOnly ? [...forcedTools] : [...forcedTools, ...CLI_DEFAULT_TOOLS];
9569
10744
  const combined = [...toolNames, ...injected];
9570
- const filtered = options?.hasUserChoice === true ? combined : combined.filter((name) => name !== "ui_ask_choice");
10745
+ const filtered = options?.hasUserChoice === true ? combined : combined.filter((name) => name !== "ask_user");
9571
10746
  return [...new Set(filtered)];
9572
10747
  }
9573
10748
  function resolveCliEffectiveEnabledPacks(args) {
@@ -9860,9 +11035,9 @@ function createCliCallAgentToolExecutor(deps, ctx) {
9860
11035
  // packages/cli/client/localRuntimeAdapter.ts
9861
11036
  var currentMetaFile = fileURLToPath(import.meta.url);
9862
11037
  var isJsBundle = extname(currentMetaFile) === ".js";
9863
- var SOURCE_CLI_DIR = isJsBundle ? dirname(currentMetaFile) : dirname(dirname(currentMetaFile));
9864
- var CLI_DIR = isCompiledBinary() ? dirname(process.execPath) : SOURCE_CLI_DIR;
9865
- var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join(SOURCE_CLI_DIR, "index.ts");
11038
+ var SOURCE_CLI_DIR = isJsBundle ? dirname2(currentMetaFile) : dirname2(dirname2(currentMetaFile));
11039
+ var CLI_DIR = isCompiledBinary() ? dirname2(process.execPath) : SOURCE_CLI_DIR;
11040
+ var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join2(SOURCE_CLI_DIR, "index.ts");
9866
11041
  function createCliLocalRuntimeAdapter(deps) {
9867
11042
  const now = deps.now ?? Date.now;
9868
11043
  const createId = deps.createId ?? createFallbackId;
@@ -10208,6 +11383,74 @@ function createCliLocalRuntimeAdapter(deps) {
10208
11383
  }
10209
11384
  };
10210
11385
  }
11386
+ if (isCodexOAuthAgent(agentConfig)) {
11387
+ const accessToken = await apiKeyRefResolver("chatgpt");
11388
+ if (!accessToken) {
11389
+ throw new Error(
11390
+ 'OAuth credential for "chatgpt" not found locally. Run `nolo auth chatgpt`.'
11391
+ );
11392
+ }
11393
+ const credential = readOAuthCredential("chatgpt");
11394
+ const accountId = credential?.accountId;
11395
+ const { requestedToolNames: requestedToolNames2, tools: tools2 } = resolveProviderOpenAiToolBundle(
11396
+ agentConfig,
11397
+ deps.env,
11398
+ buildProviderOpenAiTools,
11399
+ additionalToolNames,
11400
+ { hasUserChoice: Boolean(deps.requestUserChoice) }
11401
+ );
11402
+ logLocalRuntimeDiagnostic("provider.selected", {
11403
+ agentKey: agentConfig.key,
11404
+ transport: "codex-responses",
11405
+ provider: "openai",
11406
+ model: agentConfig.model ?? "gpt-5.6-sol",
11407
+ hasApiKey: true
11408
+ });
11409
+ return {
11410
+ model: agentConfig.model || "gpt-5.6-sol",
11411
+ complete: async (messages, options) => {
11412
+ const result = await fetchCodexResponsesCompletion({
11413
+ agentConfig,
11414
+ accessToken,
11415
+ ...accountId ? { accountId } : {},
11416
+ openAiBody: {
11417
+ model: agentConfig.model || "gpt-5.6-sol",
11418
+ messages,
11419
+ stream: false,
11420
+ ...tools2.length > 0 ? { tools: tools2 } : {}
11421
+ },
11422
+ fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
11423
+ sleep: deps.sleep,
11424
+ loopbackRequest
11425
+ })
11426
+ });
11427
+ if (result.status < 200 || result.status >= 300) {
11428
+ const errMsg = result.body?.error && typeof result.body.error === "object" && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
11429
+ throw new Error(
11430
+ `local Codex OAuth provider failed: HTTP ${result.status} ${errMsg}`
11431
+ );
11432
+ }
11433
+ const choice = Array.isArray(result.body.choices) ? result.body.choices[0] : void 0;
11434
+ const message = choice?.message ?? {};
11435
+ const content = typeof message.content === "string" ? message.content : "";
11436
+ const tool_calls = Array.isArray(message.tool_calls) ? message.tool_calls : void 0;
11437
+ if (content && options?.onTextDelta) options.onTextDelta(content);
11438
+ logLocalRuntimeDiagnostic("provider.request.result", {
11439
+ agentKey: agentConfig.key,
11440
+ transport: "codex-responses",
11441
+ ok: true,
11442
+ contentChars: content.length,
11443
+ toolCallCount: tool_calls?.length ?? 0,
11444
+ requestedToolNames: requestedToolNames2
11445
+ });
11446
+ return {
11447
+ content,
11448
+ ...tool_calls ? { tool_calls } : {},
11449
+ trace: messages
11450
+ };
11451
+ }
11452
+ };
11453
+ }
10211
11454
  if (isCursorOAuthAgent(agentConfig)) {
10212
11455
  const accessToken = await apiKeyRefResolver("cursor");
10213
11456
  if (!accessToken) {
@@ -10277,6 +11520,101 @@ function createCliLocalRuntimeAdapter(deps) {
10277
11520
  }
10278
11521
  };
10279
11522
  }
11523
+ if (shouldUsePlatformChatProvider(deps.env, agentConfig) && isGemini3Model(agentConfig.model ?? "") && agentConfig.provider === "google") {
11524
+ const providerConfig2 = await resolvePlatformChatProviderConfig({
11525
+ agentConfig,
11526
+ env: deps.env,
11527
+ apiKeyRefResolver,
11528
+ credentialBroker,
11529
+ syncFetcher
11530
+ });
11531
+ const { requestedToolNames: requestedToolNames2, tools: tools2 } = resolveProviderOpenAiToolBundle(
11532
+ agentConfig,
11533
+ deps.env,
11534
+ buildProviderOpenAiTools,
11535
+ additionalToolNames,
11536
+ { hasUserChoice: Boolean(deps.requestUserChoice) }
11537
+ );
11538
+ if (tools2.length > 0 && providerConfig2.apiKey && shouldUseGeminiNativeToolRoute(
11539
+ agentConfig.provider ?? "",
11540
+ agentConfig.model ?? "",
11541
+ tools2,
11542
+ () => false
11543
+ // CLI 端不区分 image 模型
11544
+ )) {
11545
+ logLocalRuntimeDiagnostic("provider.selected", {
11546
+ agentKey: agentConfig.key,
11547
+ transport: "gemini-native-tool",
11548
+ apiSource: agentConfig.apiSource ?? null,
11549
+ provider: providerConfig2.provider,
11550
+ model: providerConfig2.model,
11551
+ hasApiKey: Boolean(providerConfig2.apiKey)
11552
+ });
11553
+ return {
11554
+ model: providerConfig2.model,
11555
+ complete: async (messages, options) => {
11556
+ const requestBody = buildGeminiGenerateContentRequest({
11557
+ messages,
11558
+ tools: tools2,
11559
+ maxTokens: typeof agentConfig.max_tokens === "number" ? agentConfig.max_tokens : void 0,
11560
+ temperature: typeof agentConfig.temperature === "number" ? agentConfig.temperature : void 0,
11561
+ attachSkipThoughtSignature: true
11562
+ });
11563
+ const model = providerConfig2.model;
11564
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:streamGenerateContent?alt=sse`;
11565
+ logLocalRuntimeDiagnostic("provider.request.start", {
11566
+ agentKey: agentConfig.key,
11567
+ transport: "gemini-native-tool",
11568
+ model,
11569
+ messageCount: messages.length,
11570
+ toolCount: tools2.length,
11571
+ requestedToolNames: requestedToolNames2
11572
+ });
11573
+ const res = await fetchImpl(url, {
11574
+ method: "POST",
11575
+ headers: {
11576
+ "Content-Type": "application/json",
11577
+ "x-goog-api-key": providerConfig2.apiKey ?? ""
11578
+ },
11579
+ body: JSON.stringify(requestBody),
11580
+ signal: AbortSignal.timeout(12e4)
11581
+ });
11582
+ if (!res.ok) {
11583
+ const errText = await res.text();
11584
+ logLocalRuntimeDiagnostic("provider.request.failed", {
11585
+ agentKey: agentConfig.key,
11586
+ transport: "gemini-native-tool",
11587
+ status: res.status,
11588
+ error: errText.slice(0, 200)
11589
+ });
11590
+ throw new Error(
11591
+ `gemini native tool provider failed: HTTP ${res.status} ${errText.slice(0, 500)}`
11592
+ );
11593
+ }
11594
+ const chunks = await readSseDataValues(res, parseSseDataLineJson);
11595
+ const { text, toolCalls, usage } = accumulateGeminiChunks(chunks);
11596
+ if (text && options?.onTextDelta) {
11597
+ options.onTextDelta(text);
11598
+ }
11599
+ const result = {
11600
+ content: text,
11601
+ model,
11602
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
11603
+ ...usage ? { usage } : {},
11604
+ trace: messages
11605
+ };
11606
+ logLocalRuntimeDiagnostic("provider.request.result", {
11607
+ agentKey: agentConfig.key,
11608
+ transport: "gemini-native-tool",
11609
+ ok: true,
11610
+ contentChars: text.length,
11611
+ toolCallCount: toolCalls.length
11612
+ });
11613
+ return result;
11614
+ }
11615
+ };
11616
+ }
11617
+ }
10280
11618
  if (shouldUsePlatformChatProvider(deps.env, agentConfig)) {
10281
11619
  const providerConfig2 = await resolvePlatformChatProviderConfig({
10282
11620
  agentConfig,
@@ -10337,7 +11675,16 @@ function createCliLocalRuntimeAdapter(deps) {
10337
11675
  },
10338
11676
  {
10339
11677
  sleep: deps.sleep,
10340
- loopbackRequest
11678
+ loopbackRequest,
11679
+ // auto 档位转发 nolo.chat 时,网关层 502(server: Caddy、空 body)
11680
+ // 意味着请求根本没到 Bun 上游,provider 未受理,重试安全。
11681
+ // 与 429/503 同口径:不会重复计费/重复生成。
11682
+ retryableStatuses: /* @__PURE__ */ new Set([429, 502, 503]),
11683
+ onRetry: deps.activityReporter ? ({ attempt, maxAttempts, delayMs }) => {
11684
+ deps.activityReporter(
11685
+ `\u81EA\u52A8\u91CD\u8BD5 ${attempt}/${maxAttempts} \xB7 ${Math.ceil(delayMs / 1e3)}s`
11686
+ );
11687
+ } : void 0
10341
11688
  }
10342
11689
  );
10343
11690
  if (!res.ok) {
@@ -10493,6 +11840,23 @@ function createCliLocalRuntimeAdapter(deps) {
10493
11840
  };
10494
11841
  },
10495
11842
  executeTool: async (call, opts) => {
11843
+ const contextualCall = opts?.runtimeContext ? { ...call, runtimeContext: opts.runtimeContext } : call;
11844
+ let injectedCall = contextualCall;
11845
+ if (contextualCall.name === "startAgentRun" && deps.parentDialogId && typeof contextualCall.arguments === "string") {
11846
+ try {
11847
+ const args = JSON.parse(contextualCall.arguments);
11848
+ if (!args.parentDialogId) {
11849
+ injectedCall = {
11850
+ ...contextualCall,
11851
+ arguments: JSON.stringify({
11852
+ ...args,
11853
+ parentDialogId: deps.parentDialogId
11854
+ })
11855
+ };
11856
+ }
11857
+ } catch {
11858
+ }
11859
+ }
10496
11860
  assertWithinLocalToolBudget({
10497
11861
  toolName: call.name,
10498
11862
  budgets: localToolBudgets,
@@ -10501,7 +11865,7 @@ function createCliLocalRuntimeAdapter(deps) {
10501
11865
  const result = await executeLocalToolWithPolicy({
10502
11866
  env: deps.env,
10503
11867
  agentToolNames: activeAgentToolNames,
10504
- call,
11868
+ call: injectedCall,
10505
11869
  executors: localToolExecutors,
10506
11870
  abortSignal: opts?.abortSignal,
10507
11871
  detachMs: resolveExecShellDetachMs(deps.env),
@@ -10522,6 +11886,7 @@ function createCliLocalRuntimeAdapter(deps) {
10522
11886
  export {
10523
11887
  summarizeEndpoint,
10524
11888
  isBuiltinNoloAgentRef,
11889
+ parseAgentRunEvent,
10525
11890
  parseCliLocale,
10526
11891
  getCliLocale,
10527
11892
  setCliLocale,
@@ -10529,6 +11894,8 @@ export {
10529
11894
  t,
10530
11895
  toolLabel,
10531
11896
  agentRunCardLabels,
11897
+ QUOTA_ERROR_PATTERNS,
11898
+ isQuotaExhaustedError,
10532
11899
  clearCliLocalRuntimePreparedAgentCache,
10533
11900
  createCliCallAgentToolExecutor,
10534
11901
  createCliLocalRuntimeAdapter