nolo-cli 0.54.0-alpha.2 → 0.61.0-alpha.2

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 (172) hide show
  1. package/README.md +3 -3
  2. package/{_executeModel-ANY4SIAS.js → _executeModel-CKT6RGTL.js} +58 -49
  3. package/{action-Q4W5JPI5.js → action-76JX3JX3.js} +9 -8
  4. package/{addContentAction-O25HFR37.js → addContentAction-V3NAZRTJ.js} +9 -7
  5. package/{addDialogAgentAction-GH7AUPPB.js → addDialogAgentAction-RZOAF46K.js} +11 -9
  6. package/{agentDeleteCommand-JWIKNWWI.js → agentDeleteCommand-VN7NPXQ4.js} +37 -32
  7. package/{agentEmailCommands-PL22BEU5.js → agentEmailCommands-F2TNAV4A.js} +73 -65
  8. package/{agentGrantCommands-2LEZDADN.js → agentGrantCommands-R3VQEZJR.js} +1 -1
  9. package/{agentListCommands-6NR7AQEK.js → agentListCommands-OSM2ANI3.js} +78 -39
  10. package/{agentMachineCommands-TASPU6OA.js → agentMachineCommands-MTPWYVRV.js} +38 -33
  11. package/{agentPullCommand-M552CYSI.js → agentPullCommand-N7L2CT7L.js} +2 -2
  12. package/agentRecordCommands-VWAWTVVC.js +122 -0
  13. package/agentRunCommand-PLZOBNVK.js +149 -0
  14. package/{agentRunControl-4GHHSXFZ.js → agentRunControl-WECMOO6O.js} +13 -6
  15. package/{agentRuntimeLocal-PCJJ56J2.js → agentRuntimeLocal-XCJLRWQE.js} +35 -28
  16. package/{agentSlice-KYLDUSNN.js → agentSlice-F6DOP4IW.js} +10 -9
  17. package/{appDeleteCommands-WLHMJAVT.js → appDeleteCommands-3BCFTRFJ.js} +37 -32
  18. package/{appDeployCommands-CKON7N2E.js → appDeployCommands-B4GMHCYA.js} +37 -32
  19. package/{appDeployStatusCommands-PXRLDASH.js → appDeployStatusCommands-4MN36WIG.js} +37 -32
  20. package/{appGetCommands-RAB5RM4M.js → appGetCommands-4GJIEUAX.js} +37 -32
  21. package/{appListCommands-GU57FB62.js → appListCommands-CHU53GSX.js} +37 -32
  22. package/{authCommand-QOPOEYEK.js → authCommand-WOTWLJNF.js} +38 -32
  23. package/{authCommands-SBQVTD6V.js → authCommands-ILTBI6JV.js} +8 -6
  24. package/{chatQueueReduxAdapter-5O2WLITN.js → chatQueueReduxAdapter-HNSQXNIR.js} +29 -24
  25. package/{chunk-WL3UOGYO.js → chunk-22BTGNSP.js} +151 -155
  26. package/{chunk-7CH6U3FL.js → chunk-2GRGFCF6.js} +2 -4
  27. package/{chunk-V4KZGLOI.js → chunk-2HPRMEEZ.js} +3059 -1079
  28. package/{chunk-UNZDCI3O.js → chunk-2KDR4CWE.js} +35 -4
  29. package/{chunk-VRZIH5JO.js → chunk-2PGGC63K.js} +1 -1
  30. package/{chunk-T27IEBNQ.js → chunk-2QDDKFG5.js} +74 -1
  31. package/{chunk-7K5VMB4Q.js → chunk-37QVS7BU.js} +21 -8
  32. package/{chunk-UITMHBVK.js → chunk-37XDGCY7.js} +1 -1
  33. package/chunk-3BLB7QKO.js +433 -0
  34. package/{chunk-NQ4N4IGO.js → chunk-3JQ2NRYU.js} +33 -10
  35. package/{chunk-UW4INMD2.js → chunk-3JWKQDA4.js} +2 -2
  36. package/{chunk-IKTHA3JH.js → chunk-3QGUVVX5.js} +2 -2
  37. package/{chunk-WHVQA7PJ.js → chunk-45YO6H7P.js} +97 -35
  38. package/chunk-4C4ST2YE.js +20015 -0
  39. package/{chunk-32I5RVMY.js → chunk-4NJEIGBQ.js} +5 -5
  40. package/{chunk-KUUTWU4I.js → chunk-5ZYA4JJ3.js} +90 -22
  41. package/chunk-6YTOJY35.js +352 -0
  42. package/{chunk-INXBNYCG.js → chunk-7A3RRUCQ.js} +155 -12
  43. package/{chunk-GV35EHNA.js → chunk-7O7KH4X5.js} +1262 -971
  44. package/{chunk-Y7LNKP32.js → chunk-7UF7CQ6B.js} +4 -6
  45. package/{chunk-2BWU4ORW.js → chunk-AQMVUA7N.js} +2 -1
  46. package/{chunk-LA4IDAK7.js → chunk-AVE2YR4F.js} +1056 -3591
  47. package/{chunk-TI5BCZCH.js → chunk-B7DXRX7F.js} +59 -121
  48. package/chunk-BFU6C242.js +66 -0
  49. package/{chunk-FA4SY4F5.js → chunk-BYEJ7K2Z.js} +1 -1
  50. package/chunk-BYXBJQAS.js +0 -0
  51. package/{chunk-IA3A5373.js → chunk-C3FZR5EC.js} +1 -1
  52. package/{chunk-IWUMSAQF.js → chunk-CJCJF5XB.js} +26 -3
  53. package/{chunk-PAHILFNT.js → chunk-CP7VIDZ7.js} +4 -4
  54. package/{chunk-OYNDYVSE.js → chunk-CTCW7U7N.js} +1 -1
  55. package/{chunk-BJLYCOZK.js → chunk-D5XKNNUV.js} +135 -795
  56. package/{chunk-AV6KQCM5.js → chunk-DNNSCSA2.js} +19 -14
  57. package/{chunk-3AOLVADY.js → chunk-DVINR3PL.js} +1 -1
  58. package/{chunk-NI2BS6UD.js → chunk-DWUCB2A3.js} +1 -1
  59. package/{chunk-AA564GBL.js → chunk-DZZL7UBV.js} +1 -1
  60. package/{chunk-6FGXGFAH.js → chunk-E6RGHPDR.js} +6 -4
  61. package/chunk-EDKF7RX4.js +30 -0
  62. package/{chunk-6SZ52ORL.js → chunk-ES6CVKVD.js} +24 -30
  63. package/{chunk-DQLYEGP7.js → chunk-FHAGENAS.js} +3 -4
  64. package/{chunk-56W233KG.js → chunk-FKFMIBTT.js} +5 -1
  65. package/{chunk-INZZJSQF.js → chunk-FZGV4FGK.js} +24 -12
  66. package/{chunk-D3JQPONH.js → chunk-GAL47RNP.js} +1 -1
  67. package/{chunk-6FQ2552G.js → chunk-HBPV76EK.js} +1085 -1150
  68. package/{chunk-LN3OQJGG.js → chunk-HLU5Q2GV.js} +4 -4
  69. package/{chunk-U2A47SVI.js → chunk-HQP7HJDL.js} +7 -7
  70. package/{chunk-H2G6JXTR.js → chunk-HQUORJTM.js} +1 -1
  71. package/{chunk-3Z3DXZBD.js → chunk-IYCUMIYS.js} +24 -20
  72. package/{chunk-7APQB6R6.js → chunk-JX5PJCWS.js} +8 -6
  73. package/{chunk-LYGNQHUW.js → chunk-JYYZCK2Z.js} +2 -4
  74. package/{chunk-PYKV6FSC.js → chunk-KWSQR2KK.js} +16 -31
  75. package/{chunk-VULELK4T.js → chunk-L7B47JXR.js} +37 -64
  76. package/{chunk-4NN3EK7H.js → chunk-LAFC3B2I.js} +1 -1
  77. package/{chunk-VRJUIUIY.js → chunk-LJKICKVC.js} +2 -2
  78. package/chunk-M3JEW6N6.js +193 -0
  79. package/chunk-MBOEV4L2.js +301 -0
  80. package/{chunk-QDHZCAH3.js → chunk-MMZ6ZTVO.js} +229 -74
  81. package/{chunk-JDSUTNYY.js → chunk-MP64VFGD.js} +2 -2
  82. package/{chunk-U5Z7LFZF.js → chunk-MXUDQZXQ.js} +47 -8
  83. package/chunk-N4G4PKQ6.js +23 -0
  84. package/{chunk-SVEUG45B.js → chunk-NHRQCXIQ.js} +0 -24
  85. package/{chunk-KXKQO4Q6.js → chunk-NTW5GWDM.js} +58 -1
  86. package/chunk-ONXOABJR.js +215 -0
  87. package/{chunk-BANYWEYY.js → chunk-OZX2IPKM.js} +8 -3
  88. package/{chunk-Q24S4NDF.js → chunk-P7OOB7QP.js} +1 -1
  89. package/{chunk-GLGD2JGY.js → chunk-PEZJEQAO.js} +7 -7
  90. package/{chunk-GBADO3SM.js → chunk-PQDIDWGX.js} +1 -1
  91. package/chunk-PSCNXBYA.js +11 -0
  92. package/chunk-QEFJJS2I.js +508 -0
  93. package/{chunk-757BGY6Y.js → chunk-QEW2MFDQ.js} +1 -1
  94. package/{chunk-SP3DPVBH.js → chunk-RDBARW6T.js} +8 -3
  95. package/{chunk-TNPCQNGQ.js → chunk-RJ2SAFB5.js} +83 -41
  96. package/{chunk-FGEYVPPR.js → chunk-RVWRKFUB.js} +8 -65
  97. package/{chunk-43CXXVJD.js → chunk-RXX4GDIH.js} +1 -1
  98. package/chunk-SEJ5OS6F.js +49 -0
  99. package/{chunk-MFI4FGHX.js → chunk-SOJM57FX.js} +5 -2
  100. package/{chunk-EKLRRZIN.js → chunk-SPAQ4PVV.js} +0 -5
  101. package/{chunk-L7NG2M6H.js → chunk-TRV2MIDW.js} +89 -74
  102. package/chunk-UAD2WT54.js +64 -0
  103. package/{chunk-RTLJUGQH.js → chunk-UZPQSVM6.js} +2 -2
  104. package/{chunk-3QJTD6DO.js → chunk-VMWYBIXG.js} +9 -7
  105. package/{chunk-ZHXJ6M7T.js → chunk-W7XHHYWM.js} +4 -0
  106. package/{chunk-5WADL4O7.js → chunk-XAVSS3KE.js} +21 -3
  107. package/{chunk-CVT7L2WZ.js → chunk-XOKOSO35.js} +13 -22
  108. package/{chunk-6BYAXNH5.js → chunk-XTJTN3RW.js} +57 -4
  109. package/{chunk-T5HJEUQN.js → chunk-YCDWJX45.js} +1 -1
  110. package/{chunk-MRWGHF56.js → chunk-YDH3FDFQ.js} +12 -356
  111. package/{chunk-H4RYESI6.js → chunk-Z4QSJILV.js} +85 -13
  112. package/chunk-ZJ7UHBJS.js +89 -0
  113. package/{chunk-O5FLGN2L.js → chunk-ZRSJ3JEH.js} +6 -2
  114. package/{cliExecutor-BBUVQU4L.js → cliExecutor-HG3S345O.js} +1 -1
  115. package/{codingSkills-BCQXRZOI.js → codingSkills-VDXQYWX4.js} +2 -2
  116. package/contentThunks-7YG2ZYQC.js +73 -0
  117. package/{cooldownCommands-GI5NNWGL.js → cooldownCommands-BSCH2W7P.js} +2 -2
  118. package/{createAgentAutomationAction-UJLNFFFC.js → createAgentAutomationAction-PJQSCAIO.js} +32 -26
  119. package/createDialogAction-SFEJX6SP.js +64 -0
  120. package/{createPageAction-N3IYABHV.js → createPageAction-B7WRHOQO.js} +35 -28
  121. package/{dbSlice-D5CNGWPD.js → dbSlice-IBVOBVMS.js} +7 -6
  122. package/{deleteFile-44TUM34Y.js → deleteFile-FWP2PSBG.js} +4 -3
  123. package/{dialogCommands-35M6RBAC.js → dialogCommands-VL2X22QC.js} +38 -33
  124. package/{dialogSlice-KO7ADD7H.js → dialogSlice-ANMACABO.js} +29 -24
  125. package/{docCreateCommands-VXHZWQ3P.js → docCreateCommands-ITLGZ5YI.js} +40 -35
  126. package/{docDeleteCommands-4WFAJR6A.js → docDeleteCommands-LH3YNL4C.js} +37 -32
  127. package/{docReadCommands-OYREEFAR.js → docReadCommands-YAJ77F36.js} +36 -31
  128. package/{docStore-5BU76DFK.js → docStore-D4HGHPWI.js} +9 -33
  129. package/{docUpdateCommands-A7QERSME.js → docUpdateCommands-DQBOMH2G.js} +40 -35
  130. package/{fetchMessages-KZQVBXKY.js → fetchMessages-DRABNDPZ.js} +3 -3
  131. package/{getPricing-HAU62AFM.js → getPricing-NM3NUTAS.js} +5 -5
  132. package/handleSendMessageAction-DF2OABGW.js +675 -0
  133. package/index.js +79 -88
  134. package/{lib-2ZTNRXR4.js → lib-FRRS27KN.js} +63 -28
  135. package/{localDialogRead-NQ33HBSI.js → localDialogRead-PUQKFI73.js} +1 -1
  136. package/{localRuntimeAuthority-KQDAE64E.js → localRuntimeAuthority-R5UBODT3.js} +6 -4
  137. package/{localRuntimeDb-PF7CFKDL.js → localRuntimeDb-P37ZTX55.js} +1 -1
  138. package/{machineCommands-J43U3TX5.js → machineCommands-JXDYQ5LB.js} +309 -87
  139. package/{machineWsRunDispatch-Z2Z6STXZ.js → machineWsRunDispatch-3QHI7JX5.js} +67 -59
  140. package/memberThunks-VZI6G7YZ.js +640 -0
  141. package/{models-4QF4BJVY.js → models-FAMINFZ7.js} +2 -2
  142. package/package.json +3 -2
  143. package/{read-RGNPI5H2.js → read-2BYWW7AA.js} +4 -3
  144. package/{readDocTool-6ESWKTXD.js → readDocTool-LC3A7QTB.js} +1 -1
  145. package/{readlineWorkspace-YRPV6JPN.js → readlineWorkspace-KVZTEAHB.js} +4609 -2698
  146. package/{removeDialogAgentAction-JYT73FU2.js → removeDialogAgentAction-SFYZXHNK.js} +14 -12
  147. package/{runAgentClientLoop-5YM5WMAY.js → runAgentClientLoop-KGTEL7ZP.js} +60 -50
  148. package/{runtimeDoctorCommands-JKTTN723.js → runtimeDoctorCommands-CROTMULY.js} +7 -5
  149. package/{setDialogExtraReferencesAction-D564LMYQ.js → setDialogExtraReferencesAction-Q32RGFTA.js} +10 -8
  150. package/{setPrimaryDialogAgentAction-ACY3BLYA.js → setPrimaryDialogAgentAction-BFYJHUJS.js} +14 -12
  151. package/{settingSlice-MKI3MNZJ.js → settingSlice-IRUU4VFB.js} +8 -7
  152. package/{skillDiscovery-GPUDHDTZ.js → skillDiscovery-NTRLM6KP.js} +3 -3
  153. package/{spaceCommands-MY26V52L.js → spaceCommands-KNAYWMCZ.js} +40 -220
  154. package/{streamAgentChatTurn-XV5X5TNQ.js → streamAgentChatTurn-FLYPTXKZ.js} +140 -95
  155. package/{switchDialogAgentAction-CJ5H6SAR.js → switchDialogAgentAction-L2KOKCGG.js} +11 -9
  156. package/{tableCommands-R6WFRDYF.js → tableCommands-SUNTHAYX.js} +1 -1
  157. package/{toolApiClient-B2MFXMEG.js → toolApiClient-VGYUB4P5.js} +4 -2
  158. package/{tools-MIMELA2Y.js → tools-CVLUXK6P.js} +46 -38
  159. package/{tuiSummaryLlmCaller-XJ5BKNNS.js → tuiSummaryLlmCaller-F3DPFFZM.js} +20 -16
  160. package/{updateCommands-IYKLF3JX.js → updateCommands-AJYSD73Y.js} +2 -2
  161. package/{updateDialogTitleAction-EIZUSWHR.js → updateDialogTitleAction-HWJIZEIV.js} +33 -27
  162. package/agentRecordCommands-Z64TA63M.js +0 -114
  163. package/agentRunCommand-4QJQLPRW.js +0 -134
  164. package/agentSuperviseCommands-VB6BUS5H.js +0 -640
  165. package/chunk-6BGAQ3KR.js +0 -7081
  166. package/chunk-FD36SCCD.js +0 -105
  167. package/chunk-J3UALFHL.js +0 -370
  168. package/chunk-RU5D3B22.js +0 -230
  169. package/chunk-YBV6QJKM.js +0 -441
  170. package/createDialogAction-TJCX6GUE.js +0 -58
  171. package/handleSendMessageAction-OSGQJQ45.js +0 -406
  172. package/spaceSlice-JUIXC365.js +0 -127
@@ -4,10 +4,27 @@ import {
4
4
  refreshAntigravityOAuthToken,
5
5
  refreshOpenAiCodexToken,
6
6
  xaiRefresh
7
- } from "./chunk-U5Z7LFZF.js";
7
+ } from "./chunk-MXUDQZXQ.js";
8
8
  import {
9
9
  defaultLoopbackRequest
10
10
  } from "./chunk-EADNWBAZ.js";
11
+ import {
12
+ ackRunRecord,
13
+ appendRunQueue,
14
+ checkStaleRun,
15
+ claimRunRecord,
16
+ commitRunRecordClaim,
17
+ findRunRecord,
18
+ gcRunRecords,
19
+ popAllQueueEntries,
20
+ queryRunRecords,
21
+ releaseRunRecordAck,
22
+ serializeQueueEntries,
23
+ spawnLocalBackgroundRun,
24
+ terminateRunProcess,
25
+ transitionRunToTerminal,
26
+ withQueueLock
27
+ } from "./chunk-45YO6H7P.js";
11
28
  import {
12
29
  clearCredentialAvailability,
13
30
  markCredentialUnavailable,
@@ -15,59 +32,39 @@ import {
15
32
  readCredentialEntry,
16
33
  recordCredentialProbe,
17
34
  resolveCredentialKeyWithFallback
18
- } from "./chunk-NI2BS6UD.js";
35
+ } from "./chunk-DWUCB2A3.js";
19
36
  import {
20
37
  buildLocalAgentLookupKeys
21
- } from "./chunk-OYNDYVSE.js";
38
+ } from "./chunk-CTCW7U7N.js";
22
39
  import {
23
40
  LOCAL_CODEX_AGENT_ID,
24
41
  LOCAL_CODEX_AGENT_KEY,
25
42
  NOLO_DEFAULT_AGENT_ID,
26
43
  NOLO_DEFAULT_AGENT_KEY
27
- } from "./chunk-EKLRRZIN.js";
44
+ } from "./chunk-SPAQ4PVV.js";
28
45
  import {
29
46
  CliProviderQuotaError,
30
47
  executeCli
31
- } from "./chunk-JDSUTNYY.js";
32
- import {
33
- ackRunRecord,
34
- appendRunQueue,
35
- checkStaleRun,
36
- claimRunRecord,
37
- commitRunRecordClaim,
38
- finalizeRunRecord,
39
- findRunRecord,
40
- gcRunRecords,
41
- popAllQueueEntries,
42
- queryRunRecords,
43
- releaseRunRecordAck,
44
- resolveRunReportPath,
45
- serializeQueueEntries,
46
- spawnLocalBackgroundRun,
47
- terminateRunProcess,
48
- withQueueLock
49
- } from "./chunk-WHVQA7PJ.js";
48
+ } from "./chunk-MP64VFGD.js";
50
49
  import {
51
50
  inferCaptureIntent
52
- } from "./chunk-4NN3EK7H.js";
51
+ } from "./chunk-LAFC3B2I.js";
53
52
  import {
54
53
  buildCliPrompt
55
54
  } from "./chunk-ATNTHIZI.js";
56
55
  import {
57
56
  inlineImageUrlsForCustomProvider,
58
57
  prepareTools
59
- } from "./chunk-UW4INMD2.js";
58
+ } from "./chunk-3JWKQDA4.js";
60
59
  import {
61
60
  getServerProviderSecret
62
61
  } from "./chunk-HS7MLR74.js";
63
62
  import {
64
- getAntigravityUserAgent,
65
- isAntigravityOAuthAgent,
66
- readAntigravityProjectId,
67
- resolveAntigravityCloudCodeBaseUrl
68
- } from "./chunk-757BGY6Y.js";
69
- import {
63
+ CONTROL_AGENT_RUN_ACTIONS,
64
+ buildControlAgentRunFunctionSchema,
65
+ buildStartAgentRunFunctionSchema,
70
66
  deleteMemoryFunctionSchema,
67
+ queryMemoryFunctionSchema,
71
68
  readXPostFunc,
72
69
  readXPostFunctionSchema,
73
70
  readXhsProfileFunc,
@@ -75,7 +72,7 @@ import {
75
72
  rememberMemoryFunctionSchema,
76
73
  resolveAgentRequiredPackIds,
77
74
  setTodoListFunc
78
- } from "./chunk-V4KZGLOI.js";
75
+ } from "./chunk-2HPRMEEZ.js";
79
76
  import {
80
77
  fetchWithTransientRetry,
81
78
  isTransientFetchError
@@ -91,26 +88,26 @@ import {
91
88
  isAgentRunTerminalStatus,
92
89
  resolveRunLabel,
93
90
  shortRunId
94
- } from "./chunk-KXKQO4Q6.js";
91
+ } from "./chunk-NTW5GWDM.js";
95
92
  import {
96
93
  applyBuiltinAgentRuntimeOverride,
97
94
  applyTokenUsageToDayStats,
98
95
  prepareTokenUsageData,
99
96
  resolveBuiltinPlatformAgentConfig,
100
97
  runKeyed
101
- } from "./chunk-BJLYCOZK.js";
98
+ } from "./chunk-D5XKNNUV.js";
102
99
  import {
103
100
  BUILTIN_TITLE_LLM_CONFIG
104
101
  } from "./chunk-EVBFYPDC.js";
105
102
  import {
106
103
  fetchServerSyncedCredential
107
- } from "./chunk-U2A47SVI.js";
104
+ } from "./chunk-HQP7HJDL.js";
108
105
  import {
109
106
  require_date_fns
110
107
  } from "./chunk-M76ECQRD.js";
111
108
  import {
112
109
  getDefaultCliLocalRuntimeDb
113
- } from "./chunk-IA3A5373.js";
110
+ } from "./chunk-C3FZR5EC.js";
114
111
  import {
115
112
  FORCED_TOOLS,
116
113
  addDefaultLightWebToolsForConfiguredAgents,
@@ -120,9 +117,16 @@ import {
120
117
  applySystemBuiltinSkillFilter,
121
118
  expandEnabledPacks,
122
119
  resolveEffectiveEnabledPacks
123
- } from "./chunk-O5FLGN2L.js";
120
+ } from "./chunk-ZRSJ3JEH.js";
124
121
  import {
122
+ DEFAULT_HYBRID_READ_TIMEOUT_MS,
123
+ Duration_exports,
124
+ Effect_exports,
125
+ Exit_exports,
126
+ Option_exports,
127
+ accumulateGeminiChunks,
125
128
  aggregateResponsesStream,
129
+ buildGeminiGenerateContentRequest,
126
130
  buildLoadSkillExecutor,
127
131
  buildLocalDialogWritePlan,
128
132
  buildLocalWorkspaceOpenAiTools,
@@ -134,18 +138,24 @@ import {
134
138
  evaluateFileWritePolicy,
135
139
  executeLocalToolWithPolicy,
136
140
  executeOpenAiCompatibleChatCompletion,
141
+ fetchAntigravityCloudCodeCompletion,
137
142
  filterRetainedLedgerRecords,
138
143
  internalListWorkspaceEntries,
139
144
  internalSearchWorkspace,
145
+ isGemini3Model,
140
146
  isLineRangeCovered,
141
147
  localDialogMessageRecordToRuntimeMessage,
142
148
  parseSseDataLineJson,
143
149
  parseSseDataLineObject,
144
150
  parseSyncServersEnv,
151
+ parseUpstreamErrorBody,
152
+ resolveAntigravityFinishReason,
145
153
  resolveOpenAiCompatibleProviderConfig,
154
+ shouldUseGeminiNativeToolRoute,
146
155
  summarizeToolArguments
147
- } from "./chunk-6BGAQ3KR.js";
156
+ } from "./chunk-4C4ST2YE.js";
148
157
  import {
158
+ PlatformStreamInterruptedError,
149
159
  buildPlatformChatCompletionRequest,
150
160
  canUsePlatformChatProvider,
151
161
  hasDirectOpenAiCompatibleProvider,
@@ -154,55 +164,66 @@ import {
154
164
  readPlatformChatSseCompletion,
155
165
  readSseDataValues,
156
166
  resolvePlatformChatProviderConfig,
157
- shouldUsePlatformChatProvider,
158
- streamSseDataValues
159
- } from "./chunk-INXBNYCG.js";
167
+ shouldUsePlatformChatProvider
168
+ } from "./chunk-7A3RRUCQ.js";
160
169
  import {
161
170
  resolveAgentRuntimeConfigFromRecord,
162
171
  resolveHistoricalToolContentCap
163
- } from "./chunk-CVT7L2WZ.js";
172
+ } from "./chunk-XOKOSO35.js";
164
173
  import {
174
+ collectStablePromptPrefix,
165
175
  convertMessagesToResponsesInput,
176
+ stablePromptCacheKey,
166
177
  toResponsesTools
167
- } from "./chunk-6BYAXNH5.js";
178
+ } from "./chunk-XTJTN3RW.js";
179
+ import {
180
+ isAntigravityOAuthAgent
181
+ } from "./chunk-QEW2MFDQ.js";
168
182
  import {
169
183
  resolvePlatformAuthToken
170
- } from "./chunk-SP3DPVBH.js";
184
+ } from "./chunk-RDBARW6T.js";
171
185
  import {
172
186
  buildNoloWorkspaceOpenAiTools,
173
187
  parseNoloWorkspaceToolArguments,
174
188
  resolveRuntimeToolSurfaceForAgent
175
- } from "./chunk-TNPCQNGQ.js";
189
+ } from "./chunk-RJ2SAFB5.js";
176
190
  import {
177
191
  mergeAvailabilityDeadline,
178
192
  resolveAvailabilityAction,
179
193
  resolveCooldownGate
180
- } from "./chunk-IWUMSAQF.js";
194
+ } from "./chunk-CJCJF5XB.js";
181
195
  import {
182
196
  buildDialogFallbackTitleFromUserInput,
183
197
  normalizeDialogTitle
184
198
  } from "./chunk-2MBTWINN.js";
185
199
  import {
186
- clipCompactText
187
- } from "./chunk-H4RYESI6.js";
200
+ clipCompactText,
201
+ createProviderCallTimingTracker,
202
+ finalizeProviderCallTiming,
203
+ observeMeaningfulProviderResponseAt,
204
+ withProviderCallTimingFields
205
+ } from "./chunk-Z4QSJILV.js";
206
+ import {
207
+ estimateTokenCount
208
+ } from "./chunk-PSCNXBYA.js";
209
+ import {
210
+ isAdaptiveThinkingModelId
211
+ } from "./chunk-MMZ6ZTVO.js";
212
+ import {
213
+ compactWhitespace
214
+ } from "./chunk-DWLEOOGR.js";
188
215
  import {
189
216
  createFileCredentialBroker,
190
217
  resolveCurrentRunRuntimeToolPolicy,
191
218
  resolveLocalWorkspaceExecutorOptionsFromPolicy,
192
219
  resolveRequestedRuntimeToolNames
193
- } from "./chunk-NQ4N4IGO.js";
220
+ } from "./chunk-3JQ2NRYU.js";
194
221
  import {
195
222
  createOAuthTokenStore,
196
223
  isTokenExpired,
197
224
  readOAuthCredential,
198
225
  resolveFreshAccessToken
199
- } from "./chunk-FD36SCCD.js";
200
- import {
201
- isAdaptiveThinkingModelId
202
- } from "./chunk-QDHZCAH3.js";
203
- import {
204
- compactWhitespace
205
- } from "./chunk-DWLEOOGR.js";
226
+ } from "./chunk-ONXOABJR.js";
206
227
  import {
207
228
  toErrorMessage
208
229
  } from "./chunk-HNMXYYJR.js";
@@ -221,22 +242,25 @@ import {
221
242
  createTokenStatsKey,
222
243
  createUserKey,
223
244
  dialogMessageRange
224
- } from "./chunk-SVEUG45B.js";
225
- import {
226
- asTrimmedNonEmptyStringArray
227
- } from "./chunk-I42VC5KR.js";
245
+ } from "./chunk-NHRQCXIQ.js";
228
246
  import {
229
247
  asTrimmedLowercaseString
230
248
  } from "./chunk-QSJ3HFEF.js";
231
249
  import {
232
250
  isSystemBuiltinTrustedAgentKey
233
- } from "./chunk-VULELK4T.js";
251
+ } from "./chunk-L7B47JXR.js";
252
+ import {
253
+ asTrimmedString
254
+ } from "./chunk-3EUW3WEO.js";
234
255
  import {
235
256
  isRecord
236
257
  } from "./chunk-KUG52IAP.js";
237
258
  import {
238
259
  NOLO_CLUSTER_SERVERS
239
260
  } from "./chunk-LCBAMY2M.js";
261
+ import {
262
+ isLoopbackUrl
263
+ } from "./chunk-4SN6J65J.js";
240
264
  import {
241
265
  normalizeServerOrigin
242
266
  } from "./chunk-CF7PE763.js";
@@ -305,6 +329,12 @@ function isSubtaskRun(env) {
305
329
  const value = env.NOLO_AGENT_RUN_CHILD;
306
330
  return typeof value === "string" && value.length > 0 && value !== "0";
307
331
  }
332
+ var RUN_WAKE_CHANNEL_ENV = "NOLO_RUN_WAKE";
333
+ function hasRunWakeChannel(env) {
334
+ if (!env) return false;
335
+ const value = env[RUN_WAKE_CHANNEL_ENV];
336
+ return typeof value === "string" && value.length > 0 && value !== "0";
337
+ }
308
338
  function filterToolNamesForRunKind(toolNames, isSubtask) {
309
339
  if (!isSubtask) return [...toolNames];
310
340
  return toolNames.filter((name) => !SUBTASK_REMOVED_TOOL_NAMES.has(name));
@@ -347,11 +377,30 @@ function initCliLocale(env = process.env) {
347
377
  function newlineHint(platform = process.platform) {
348
378
  return platform === "win32" ? "Ctrl+J" : "Shift+Enter";
349
379
  }
380
+ var WELCOME_TIPS = {
381
+ en: [
382
+ `Tip: ${newlineHint()} for a newline; /help lists all commands.`,
383
+ "Tip: paste a screenshot or drag an image into the terminal \u2014 nolo can see it.",
384
+ "Tip: /doc attach <doc> brings a doc into this conversation's context.",
385
+ "Tip: /theme switches colors; terminal mode follows your terminal's day/night.",
386
+ "Tip: /history resumes a recent dialog; /agents lists your agents."
387
+ ],
388
+ zh: [
389
+ `\u63D0\u793A\uFF1A${newlineHint()} \u6362\u884C\uFF1B/help \u5217\u51FA\u5168\u90E8\u547D\u4EE4\u3002`,
390
+ "\u63D0\u793A\uFF1A\u76F4\u63A5\u7C98\u8D34\u622A\u56FE\u6216\u628A\u56FE\u7247\u62D6\u8FDB\u7EC8\u7AEF\uFF0Cnolo \u770B\u5F97\u61C2\u3002",
391
+ "\u63D0\u793A\uFF1A/doc attach <doc> \u628A\u6587\u6863\u6302\u8FDB\u5F53\u524D\u5BF9\u8BDD\u7684\u4E0A\u4E0B\u6587\u3002",
392
+ "\u63D0\u793A\uFF1A/theme \u5207\u6362\u914D\u8272\uFF1Bterminal \u6A21\u5F0F\u8DDF\u968F\u7EC8\u7AEF\u7684\u65E5\u591C\u4E3B\u9898\u3002",
393
+ "\u63D0\u793A\uFF1A/history \u56DE\u5230\u6700\u8FD1\u5BF9\u8BDD\uFF1B/agents \u67E5\u770B\u53EF\u7528 Agent\u3002"
394
+ ]
395
+ };
396
+ function dailyWelcomeTip(now = Date.now()) {
397
+ const tips = WELCOME_TIPS[currentLocale];
398
+ const day = Math.floor(now / 864e5);
399
+ return tips[day % tips.length];
400
+ }
350
401
  var STRINGS = {
351
- welcomeHint: {
352
- en: `Tell nolo what you want. Use /help for commands. ${newlineHint()} for newline.`,
353
- zh: `\u544A\u8BC9 nolo \u4F60\u60F3\u8981\u4EC0\u4E48\u3002\u8F93\u5165 /help \u67E5\u770B\u547D\u4EE4\u3002${newlineHint()} \u6362\u884C\u3002`
354
- },
402
+ // Welcome hint lives in WELCOME_TIPS + dailyWelcomeTip() (rotating daily
403
+ // tips); the composer placeholder already covers "type / for commands".
355
404
  promptLabel: {
356
405
  en: "\u276F ",
357
406
  zh: "\u276F "
@@ -604,6 +653,14 @@ var STRINGS = {
604
653
  // --- Tool trace copy ------------------------------------------------------
605
654
  // The compact trace shows only status, never timing or output size: a line
606
655
  // count told the user nothing actionable and the ms figure read as noise.
656
+ thinkingActive: {
657
+ en: "Thinking\u2026",
658
+ zh: "\u601D\u8003\u4E2D\u2026"
659
+ },
660
+ thinkingActivePreview: {
661
+ en: "Thinking: {0}",
662
+ zh: "\u601D\u8003\u4E2D\uFF1A{0}"
663
+ },
607
664
  thinkingTraceLine: {
608
665
  en: "\u273B Thought for {0}",
609
666
  zh: "\u273B \u601D\u8003 {0}"
@@ -651,10 +708,6 @@ var STRINGS = {
651
708
  },
652
709
  // Normal-mode safe projection: the raw errorMessage/logLines of a failed run
653
710
  // stay in pro/verbose; normal mode names the failure and points at pro.
654
- runDiagnosticsHidden: {
655
- en: "run failed \u2014 full diagnostics in pro mode",
656
- zh: "\u8FD0\u884C\u5931\u8D25\u2014\u2014\u5B8C\u6574\u8BCA\u65AD\u89C1 pro \u6A21\u5F0F"
657
- },
658
711
  runsListLabel: {
659
712
  en: "Runs ({0})",
660
713
  zh: "\u8FD0\u884C ({0})"
@@ -810,10 +863,6 @@ var STRINGS = {
810
863
  en: "runtime",
811
864
  zh: "\u8FD0\u884C\u65F6"
812
865
  },
813
- contextFieldTools: {
814
- en: "tools",
815
- zh: "\u5DE5\u5177"
816
- },
817
866
  contextFieldServer: {
818
867
  en: "server",
819
868
  zh: "\u670D\u52A1\u7AEF"
@@ -873,7 +922,7 @@ var STRINGS = {
873
922
  " /customize Describe how you want to tune nolo",
874
923
  " /tasks List background process tasks (aliases: /jobs, /procs)",
875
924
  " /stop <pid|all> Stop background process tasks",
876
- " /login Show login/profile hint",
925
+ " /login Show login/profile hint (/login --server <url> to log in here)",
877
926
  " /profile Show active profile",
878
927
  " /update Update the nolo CLI install",
879
928
  " /version Show version/update hint",
@@ -911,7 +960,7 @@ var STRINGS = {
911
960
  " /customize \u63CF\u8FF0\u4F60\u60F3\u600E\u4E48\u8C03\u6559 nolo",
912
961
  " /tasks \u5217\u51FA\u540E\u53F0\u5B50\u8FDB\u7A0B\u4EFB\u52A1\uFF08\u522B\u540D\uFF1A/jobs, /procs\uFF09",
913
962
  " /stop <pid|all> \u505C\u6B62\u6307\u5B9A\u7684\u540E\u53F0\u4EFB\u52A1",
914
- " /login \u67E5\u770B\u767B\u5F55 / \u914D\u7F6E\u63D0\u793A",
963
+ " /login \u67E5\u770B\u767B\u5F55 / \u914D\u7F6E\u63D0\u793A\uFF08/login --server <url> \u53EF\u5728\u672C\u4F1A\u8BDD\u5185\u767B\u5F55\uFF09",
915
964
  " /profile \u67E5\u770B\u5F53\u524D\u914D\u7F6E\u73AF\u5883",
916
965
  " /update \u66F4\u65B0 nolo CLI",
917
966
  " /version \u67E5\u770B\u7248\u672C\u4E0E\u66F4\u65B0\u63D0\u793A",
@@ -930,8 +979,8 @@ var STRINGS = {
930
979
  runtimeUsage: { en: "Usage: /runtime <auto|local|server>", zh: "\u7528\u6CD5\uFF1A/runtime <auto|local|server>" },
931
980
  runtimeSet: { en: "Runtime: {0}", zh: "\u8FD0\u884C\u6A21\u5F0F\uFF1A{0}" },
932
981
  displayFixedHint: {
933
- en: "The TUI now ships a single built-in display default, no switching needed. Power users can fall back to environment variables (applied on restart): NOLO_CLI_TOOLS=normal|pro|verbose|hide controls the tool trace, NOLO_CLI_THINKING=show|hide controls reasoning visibility.",
934
- zh: "TUI \u73B0\u5728\u53EA\u6709\u4E00\u5957\u5185\u7F6E\u9ED8\u8BA4\u663E\u793A\uFF0C\u65E0\u9700\u5207\u6362\u3002\u4E13\u4E1A\u7EC6\u8282\u53EF\u7528\u73AF\u5883\u53D8\u91CF\u515C\u5E95\uFF08\u91CD\u542F\u751F\u6548\uFF09\uFF1ANOLO_CLI_TOOLS=normal|pro|verbose|hide \u63A7\u5236\u5DE5\u5177\u8F68\u8FF9\uFF0CNOLO_CLI_THINKING=show|hide \u63A7\u5236\u601D\u8003\u8FC7\u7A0B\u3002"
982
+ en: "The TUI ships a single built-in tool display \u2014 no configuration needed. Thinking process visibility is still controlled independently via NOLO_CLI_THINKING=show|hide (applied on restart).",
983
+ zh: "TUI \u53EA\u6709\u4E00\u5957\u5185\u7F6E\u5DE5\u5177\u663E\u793A\uFF0C\u65E0\u9700\u914D\u7F6E\u3002\u601D\u8003\u8FC7\u7A0B\u4ECD\u53EF\u7528 NOLO_CLI_THINKING=show|hide \u72EC\u7ACB\u63A7\u5236\uFF08\u91CD\u542F\u751F\u6548\uFF09\u3002"
935
984
  },
936
985
  tasksRunning: { en: "Running processes ({0}):", zh: "\u8FD0\u884C\u4E2D\u7684\u8FDB\u7A0B\uFF08{0}\uFF09\uFF1A" },
937
986
  tasksStopped: { en: "Stopped/exited ({0}):", zh: "\u5DF2\u505C\u6B62/\u5DF2\u9000\u51FA\uFF08{0}\uFF09\uFF1A" },
@@ -1044,14 +1093,56 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`,
1044
1093
  en: "MVP login uses profile/env auth. Set AUTH_TOKEN, NOLO_SERVER, or NOLO_PROFILE before starting nolo.",
1045
1094
  zh: "MVP \u767B\u5F55\u8D70 profile/\u73AF\u5883\u53D8\u91CF\u8BA4\u8BC1\u3002\u542F\u52A8 nolo \u524D\u8BF7\u8BBE\u7F6E AUTH_TOKEN\u3001NOLO_SERVER \u6216 NOLO_PROFILE\u3002"
1046
1095
  },
1096
+ loginTuiStart: {
1097
+ en: "Or run `/login --server <url>` to log in right here (opens a browser authorization URL).",
1098
+ zh: "\u4E5F\u53EF\u4EE5\u6267\u884C /login --server <url> \u76F4\u63A5\u5728\u8FD9\u91CC\u767B\u5F55\uFF08\u4F1A\u7ED9\u51FA\u6D4F\u89C8\u5668\u6388\u6743\u94FE\u63A5\uFF09\u3002"
1099
+ },
1100
+ loginUsage: {
1101
+ en: "Usage: /login [--server <url>]. Unsupported flags: {0}",
1102
+ zh: "\u7528\u6CD5\uFF1A/login [--server <url>]\u3002\u4E0D\u652F\u6301\u7684\u53C2\u6570\uFF1A{0}"
1103
+ },
1104
+ loginStarted: {
1105
+ en: "Open this URL to authorize nolo-cli:\n{0}\nCode: {1}",
1106
+ zh: "\u6253\u5F00\u8FD9\u4E2A\u94FE\u63A5\u6388\u6743 nolo-cli\uFF1A\n{0}\n\u6388\u6743\u7801\uFF1A{1}"
1107
+ },
1108
+ loginBrowserFailed: {
1109
+ en: "Could not open a browser automatically. Paste the URL above into a browser.",
1110
+ zh: "\u65E0\u6CD5\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u628A\u4E0A\u9762\u7684\u94FE\u63A5\u7C98\u8D34\u5230\u6D4F\u89C8\u5668\u91CC\u3002"
1111
+ },
1112
+ loginWaiting: {
1113
+ en: "[nolo] Waiting for browser authorization ({0} remaining)... (Ctrl+C to cancel)",
1114
+ zh: "[nolo] \u7B49\u5F85\u6D4F\u89C8\u5668\u6388\u6743\uFF08\u5269\u4F59 {0}\uFF09\u2026\u2026\u6309 Ctrl+C \u53D6\u6D88"
1115
+ },
1116
+ loginStillWaiting: {
1117
+ en: "[nolo] Still waiting... ({0} remaining)",
1118
+ zh: "[nolo] \u4ECD\u5728\u7B49\u5F85\u2026\u2026\uFF08\u5269\u4F59 {0}\uFF09"
1119
+ },
1120
+ loginSuccess: {
1121
+ en: "Logged in. Token saved to profile; this session now uses it immediately.",
1122
+ zh: "\u767B\u5F55\u6210\u529F\u3002Token \u5DF2\u5199\u5165 profile\uFF0C\u5F53\u524D\u4F1A\u8BDD\u7ACB\u5373\u751F\u6548\u3002"
1123
+ },
1124
+ loginFailed: {
1125
+ en: "Login failed: {0}",
1126
+ zh: "\u767B\u5F55\u5931\u8D25\uFF1A{0}"
1127
+ },
1128
+ loginTimeout: {
1129
+ en: "Login timed out. Run /login again, or use `nolo login --token <jwt>` in a shell.",
1130
+ zh: "\u767B\u5F55\u8D85\u65F6\u3002\u8BF7\u91CD\u65B0\u6267\u884C /login\uFF0C\u6216\u5728 shell \u91CC\u7528 nolo login --token <jwt>\u3002"
1131
+ },
1132
+ loginCancelled: {
1133
+ en: "Login cancelled.",
1134
+ zh: "\u5DF2\u53D6\u6D88\u767B\u5F55\u3002"
1135
+ },
1047
1136
  versionInfo: {
1048
1137
  en: "nolo {0}\nUpdate this install with: nolo update\nIf repo-local output differs, publish/install the latest npm package first.",
1049
1138
  zh: "nolo {0}\n\u7528 nolo update \u66F4\u65B0\u5F53\u524D\u5B89\u88C5\u3002\n\u5982\u679C\u672C\u5730\u4ED3\u5E93\u8F93\u51FA\u7684\u7248\u672C\u4E0D\u540C\uFF0C\u8BF7\u5148\u53D1\u5E03/\u5B89\u88C5\u6700\u65B0\u7684 npm \u5305\u3002"
1050
1139
  },
1051
1140
  versionUnknown: { en: "unknown version", zh: "\u672A\u77E5\u7248\u672C" },
1052
1141
  updateAvailable: {
1053
- en: "New nolo {0} available (you have {1}) \u2014 run /update to upgrade",
1054
- zh: "\u65B0\u7248\u672C nolo {0} \u53EF\u7528\uFF08\u5F53\u524D {1}\uFF09\u2014 \u8FD0\u884C /update \u5347\u7EA7"
1142
+ // 保持短:这行在窄终端物理换行会破坏 banner 重绘的行数计算。当前版本
1143
+ // 号上一行 version line 已有,不重复。
1144
+ en: "\u2191 nolo {0} available \u2014 /update to upgrade",
1145
+ zh: "\u2191 nolo {0} \u53EF\u7528 \u2014 /update \u5347\u7EA7"
1055
1146
  },
1056
1147
  // --- Dialog list / timestamps -----------------------------------------
1057
1148
  recentDialogs: { en: "Recent dialogs:", zh: "\u6700\u8FD1\u5BF9\u8BDD\uFF1A" },
@@ -1461,6 +1552,7 @@ function mapAnthropicMessageToOpenAi(payload) {
1461
1552
  };
1462
1553
  }
1463
1554
  async function fetchAnthropicMessagesCompletion(args) {
1555
+ const timingTracker = createProviderCallTimingTracker();
1464
1556
  const response = await (args.fetchImpl ?? fetch)(ANTHROPIC_MESSAGES_URL, {
1465
1557
  method: "POST",
1466
1558
  headers: {
@@ -1479,7 +1571,16 @@ async function fetchAnthropicMessagesCompletion(args) {
1479
1571
  error: { message: await response.text().catch(() => response.statusText) }
1480
1572
  }));
1481
1573
  if (!response.ok) return { status: response.status, body: payload, headers: response.headers };
1482
- return { status: 200, body: mapAnthropicMessageToOpenAi(payload) };
1574
+ const mapped = mapAnthropicMessageToOpenAi(payload);
1575
+ const timing = finalizeProviderCallTiming(timingTracker);
1576
+ const usage = mapped.usage;
1577
+ if (usage && typeof usage === "object" && timing.callDurationMs !== void 0) {
1578
+ mapped.usage = {
1579
+ ...usage,
1580
+ callDurationMs: timing.callDurationMs
1581
+ };
1582
+ }
1583
+ return { status: 200, body: mapped };
1483
1584
  }
1484
1585
  function isAnthropicOAuthAgent(agent) {
1485
1586
  return agent.apiKeyRef?.trim().toLowerCase() === "claude";
@@ -1518,6 +1619,7 @@ var LOCAL_SERVER_MEMORY_TOOL_NAME_SET = new Set(
1518
1619
  // packages/cli/client/localRuntimeTools.ts
1519
1620
  function buildOpenAiTools(args) {
1520
1621
  const toolset = buildLocalWorkspaceToolsetForEnv(args);
1622
+ const workspaceToolNames = toolset.toolNames;
1521
1623
  const toolNameSet = new Set(args.toolNames ?? []);
1522
1624
  const uiAskChoiceTools = toolNameSet.has("ask_user") ? prepareTools(["ask_user"]) : [];
1523
1625
  const readPastedTextTools = toolNameSet.has("readPastedText") ? [
@@ -1559,19 +1661,47 @@ function buildOpenAiTools(args) {
1559
1661
  ...uiAskChoiceTools,
1560
1662
  ...readPastedTextTools,
1561
1663
  ...buildLocalWorkspaceOpenAiTools({
1562
- toolNames: toolset.toolNames,
1664
+ toolNames: args.effectiveToolNames ?? workspaceToolNames,
1563
1665
  exposeShellTools: toolset.exposeShellTools
1564
1666
  }),
1565
1667
  ...buildServerPlatformOpenAiTools({ toolNames: args.toolNames }),
1566
1668
  ...buildNoloWorkspaceOpenAiTools({ toolNames: args.toolNames }),
1567
- ...prepareTools(
1568
- ["startAgentRun", "controlAgentRun"].filter((name) => toolNameSet.has(name))
1569
- )
1669
+ ...buildOrchestrationOpenAiTools({
1670
+ toolNameSet,
1671
+ env: args.env
1672
+ })
1570
1673
  ];
1571
1674
  }
1675
+ function buildOrchestrationOpenAiTools(args) {
1676
+ const names = ["startAgentRun", "controlAgentRun"].filter(
1677
+ (name) => args.toolNameSet.has(name)
1678
+ );
1679
+ if (names.length === 0) return [];
1680
+ const waitCapableActions = CONTROL_AGENT_RUN_ACTIONS.filter(
1681
+ (action) => action !== "wait"
1682
+ );
1683
+ const wakeChannel = hasRunWakeChannel(args.env);
1684
+ const controlSchema = buildControlAgentRunFunctionSchema({
1685
+ ...wakeChannel ? { actions: waitCapableActions } : {},
1686
+ wakeEnabled: wakeChannel
1687
+ });
1688
+ const startSchema = buildStartAgentRunFunctionSchema({
1689
+ supportsWait: false,
1690
+ wakeEnabled: wakeChannel
1691
+ });
1692
+ return prepareTools(names).map((tool) => {
1693
+ if (tool?.function?.name === "controlAgentRun") {
1694
+ return { ...tool, function: controlSchema };
1695
+ }
1696
+ if (tool?.function?.name === "startAgentRun") {
1697
+ return { ...tool, function: startSchema };
1698
+ }
1699
+ return tool;
1700
+ });
1701
+ }
1572
1702
  var CLI_DEFAULT_TOOLS = ["exa_search", "fetchWebpage", "ask_user"];
1573
- function addDefaultCliCoreTools(toolNames, env) {
1574
- const declaredOnly = env && shouldUseDeclaredOnlyLocalWorkspaceTools(env);
1703
+ function addDefaultCliCoreTools(toolNames, env, args) {
1704
+ const declaredOnly = args?.skipHostDefaults === true || (env ? shouldUseDeclaredOnlyLocalWorkspaceTools(env) : false);
1575
1705
  const injected = declaredOnly ? [...FORCED_TOOLS] : [...FORCED_TOOLS, ...CLI_DEFAULT_TOOLS];
1576
1706
  return [.../* @__PURE__ */ new Set([...toolNames, ...injected])];
1577
1707
  }
@@ -1579,6 +1709,10 @@ function resolveCliEffectiveEnabledPacks(args) {
1579
1709
  return resolveEffectiveEnabledPacks({
1580
1710
  enabledPacks: resolveAgentRequiredPackIds(args),
1581
1711
  declaredOnly: args.declaredOnly,
1712
+ // 子任务不继承 ALWAYS_ON 交互默认(memory/skills)——agent 显式声明
1713
+ // (enabledPacks / required skill packs)的包照常展开;code 兜底是
1714
+ // host-required,子任务保留(否则零声明叶子上没有任何文件/shell 工具)。
1715
+ includeAlwaysOnPacks: args.isSubtask !== true,
1582
1716
  emptyFallbackPacks: ["code"]
1583
1717
  });
1584
1718
  }
@@ -1600,46 +1734,48 @@ function withRuntimeEnabledPacksAndPrompt(config) {
1600
1734
  }
1601
1735
  function resolveCliRequestedToolNames(agentConfig, env, systemBuiltinSkills) {
1602
1736
  const declaredOnly = shouldUseDeclaredOnlyLocalWorkspaceTools(env);
1603
- const expanded = addDefaultLightWebToolsForConfiguredAgents(
1604
- addDefaultCliCoreTools(
1605
- canonicalizeToolNames(
1606
- expandEnabledPacks(
1607
- resolveCliEffectiveEnabledPacks({
1608
- enabledPacks: agentConfig?.enabledPacks,
1609
- skills: agentConfig?.skills,
1610
- declaredOnly
1611
- }),
1612
- resolveRequestedRuntimeToolNames({ agentConfig })
1613
- )
1614
- ),
1615
- env
1737
+ const isSubtask = isSubtaskRun(env);
1738
+ const coreExpanded = addDefaultCliCoreTools(
1739
+ canonicalizeToolNames(
1740
+ expandEnabledPacks(
1741
+ resolveCliEffectiveEnabledPacks({
1742
+ enabledPacks: agentConfig?.enabledPacks,
1743
+ skills: agentConfig?.skills,
1744
+ declaredOnly,
1745
+ isSubtask
1746
+ }),
1747
+ resolveRequestedRuntimeToolNames({ agentConfig })
1748
+ )
1616
1749
  ),
1617
- agentConfig
1750
+ env,
1751
+ { skipHostDefaults: isSubtask }
1618
1752
  );
1753
+ const expanded = isSubtask ? coreExpanded : addDefaultLightWebToolsForConfiguredAgents(coreExpanded, agentConfig);
1619
1754
  const filtered = applySystemBuiltinSkillFilter(
1620
1755
  // Default-on system capabilities (agent-orchestration) are mounted for
1621
- // every non-declared-only agent before the global filter runs, so the
1622
- // user's global "off" still wins. declared-only (ablation) runs keep
1623
- // their strict surface.
1624
- declaredOnly ? expanded : addDefaultSystemCapabilityTools(expanded),
1756
+ // every non-declared-only interactive agent before the global filter runs,
1757
+ // so the user's global "off" still wins. declared-only (ablation) and
1758
+ // subtask runs keep their strict surface.
1759
+ declaredOnly || isSubtask ? expanded : addDefaultSystemCapabilityTools(expanded),
1625
1760
  systemBuiltinSkills
1626
1761
  );
1627
1762
  const afterDisabled = applyDisabledTools(
1628
1763
  filtered,
1629
1764
  agentConfig?.disabledTools
1630
1765
  );
1631
- return filterToolNamesForRunKind(afterDisabled, isSubtaskRun(env));
1766
+ return filterToolNamesForRunKind(afterDisabled, isSubtask);
1632
1767
  }
1633
1768
  function resolveProviderOpenAiToolBundle(agentConfig, env, buildTools = buildOpenAiTools, additionalToolNames = []) {
1634
1769
  const requestedToolNames = [
1635
1770
  .../* @__PURE__ */ new Set([
1636
- ...resolveCliRequestedToolNames(agentConfig, env, null),
1771
+ ...Array.isArray(agentConfig.runScopedToolSurface?.finalToolNames) ? agentConfig.runScopedToolSurface.finalToolNames : resolveCliRequestedToolNames(agentConfig, env, null),
1637
1772
  ...additionalToolNames
1638
1773
  ])
1639
1774
  ];
1640
1775
  const tools = buildTools({
1641
1776
  agentKey: agentConfig.key,
1642
1777
  toolNames: requestedToolNames,
1778
+ ...Array.isArray(agentConfig.runScopedToolSurface?.finalToolNames) ? { effectiveToolNames: requestedToolNames } : {},
1643
1779
  env
1644
1780
  });
1645
1781
  return { requestedToolNames, tools };
@@ -1648,9 +1784,9 @@ function buildLocalWorkspaceToolsetForEnv(args) {
1648
1784
  const toolset = buildLocalWorkspaceToolset({
1649
1785
  declaredToolNames: args.toolNames,
1650
1786
  exposeShellTools: true,
1651
- useDeclaredToolNamesOnly: shouldUseDeclaredOnlyLocalWorkspaceTools(
1652
- args.env
1653
- )
1787
+ // The requested list is already the effective run surface. Re-expanding
1788
+ // shell/workspace defaults here would bypass run-scoped constraints.
1789
+ useDeclaredToolNamesOnly: args.useDeclaredToolNamesOnly === true || args.useDeclaredToolNamesOnly === void 0 && shouldUseDeclaredOnlyLocalWorkspaceTools(args.env)
1654
1790
  });
1655
1791
  return toolset;
1656
1792
  }
@@ -1685,6 +1821,12 @@ function buildServerPlatformOpenAiTools(args) {
1685
1821
  function: rememberMemoryFunctionSchema
1686
1822
  }
1687
1823
  ] : [],
1824
+ ...toolNameSet.has("queryMemory") ? [
1825
+ {
1826
+ type: "function",
1827
+ function: queryMemoryFunctionSchema
1828
+ }
1829
+ ] : [],
1688
1830
  ...toolNameSet.has("deleteMemory") ? [
1689
1831
  {
1690
1832
  type: "function",
@@ -1750,7 +1892,8 @@ var resolveAnthropicOAuthTransport = async (ctx) => {
1750
1892
  });
1751
1893
  await recordLocalAvailability(result.status, result.body);
1752
1894
  if (result.status < 200 || result.status >= 300) {
1753
- const errMsg = result.body?.error && typeof result.body.error === "object" && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
1895
+ const errorObj = result.body?.error;
1896
+ const errMsg = typeof errorObj?.message === "string" ? errorObj.message : JSON.stringify(result.body);
1754
1897
  throw new Error(
1755
1898
  `local Claude OAuth provider failed: HTTP ${result.status} ${errMsg}`
1756
1899
  );
@@ -1774,9 +1917,11 @@ var resolveAnthropicOAuthTransport = async (ctx) => {
1774
1917
  provider: "anthropic",
1775
1918
  ...tool_calls ? { tool_calls } : {},
1776
1919
  // fetchAnthropicMessagesCompletion 已把 Anthropic Messages 响应归一化成
1777
- // OpenAI chat.completions 形状:choices[0] + usage(prompt_tokens/
1778
- // output_tokens/cache_*)。必须透传,否则 localLoop 的 lastUsage 无
1779
- // token 数,TUI context chip 拿不到更新(与 Codex OAuth 分支同因)。
1920
+ // OpenAI chat.completions 形状:choices[0].finish_reason("stop"/"tool_calls")
1921
+ // + usage(prompt_tokens/output_tokens/cache_*)。必须透传,否则 localLoop 在
1922
+ // 收尾轮无 finish_reason / stream_complete 时会误判成 stream_truncated(与 Antigravity 同理)。
1923
+ finish_reason: typeof choice?.finish_reason === "string" ? choice.finish_reason : void 0,
1924
+ stream_complete: true,
1780
1925
  usage: result.body?.usage,
1781
1926
  trace: messages
1782
1927
  };
@@ -1786,494 +1931,256 @@ var resolveAnthropicOAuthTransport = async (ctx) => {
1786
1931
  return null;
1787
1932
  };
1788
1933
 
1789
- // packages/core/chat/upstreamErrorBody.ts
1790
- function parseUpstreamErrorBody(errorText, statusText) {
1791
- if (errorText) {
1792
- try {
1793
- const parsed = JSON.parse(errorText);
1794
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1795
- const error = parsed.error;
1796
- if (error && typeof error === "object" && !Array.isArray(error)) {
1797
- return parsed;
1798
- }
1934
+ // packages/agent-runtime/antigravityInvocation.ts
1935
+ var AUTH_RETRYABLE_STATUSES = /* @__PURE__ */ new Set([401, 403]);
1936
+ function antigravityAttemptEffect(args) {
1937
+ return Effect_exports.suspend(() => {
1938
+ const attemptController = new AbortController();
1939
+ const externalSignal = args.externalSignal;
1940
+ let onExternalAbort;
1941
+ const forwardExternalAbort = () => {
1942
+ if (!attemptController.signal.aborted) attemptController.abort(externalSignal?.reason);
1943
+ };
1944
+ if (externalSignal) {
1945
+ if (externalSignal.aborted) forwardExternalAbort();
1946
+ else {
1947
+ onExternalAbort = forwardExternalAbort;
1948
+ externalSignal.addEventListener("abort", onExternalAbort, { once: true });
1799
1949
  }
1800
- } catch {
1801
1950
  }
1802
- }
1803
- return { error: { message: errorText || statusText } };
1951
+ const removeExternalListener = () => {
1952
+ if (onExternalAbort) {
1953
+ externalSignal?.removeEventListener("abort", onExternalAbort);
1954
+ onExternalAbort = void 0;
1955
+ }
1956
+ };
1957
+ const attempt = Effect_exports.callback((resume, fiberSignal) => {
1958
+ const onFiberAbort = () => forwardExternalAbort();
1959
+ if (fiberSignal?.aborted) forwardExternalAbort();
1960
+ else fiberSignal?.addEventListener("abort", onFiberAbort);
1961
+ const removeFiberListener = () => {
1962
+ if (onFiberAbort) fiberSignal?.removeEventListener("abort", onFiberAbort);
1963
+ };
1964
+ if (attemptController.signal.aborted) {
1965
+ removeFiberListener();
1966
+ removeExternalListener();
1967
+ resume(Effect_exports.fail(buildInvocationError(
1968
+ "ANTIGRAVITY_INVOCATION_ABORTED",
1969
+ "Antigravity invocation aborted before request."
1970
+ )));
1971
+ return Effect_exports.succeed(void 0);
1972
+ }
1973
+ const pending = fetchAntigravityCloudCodeCompletion({
1974
+ agentConfig: args.agentConfig,
1975
+ accessToken: args.credential.accessToken,
1976
+ metadata: args.credential.metadata,
1977
+ openAiBody: args.openAiBody,
1978
+ signal: attemptController.signal,
1979
+ fetchImpl: args.fetchImpl,
1980
+ ...args.onTextDelta ? { onTextDelta: args.onTextDelta } : {},
1981
+ ...args.onReasoningDelta ? { onReasoningDelta: args.onReasoningDelta } : {}
1982
+ });
1983
+ pending.then(
1984
+ (result) => resume(Effect_exports.succeed(result)),
1985
+ (error) => resume(Effect_exports.fail(error))
1986
+ );
1987
+ return Effect_exports.sync(() => {
1988
+ removeFiberListener();
1989
+ removeExternalListener();
1990
+ });
1991
+ }).pipe(
1992
+ // 兜底:winner 路径(正常 settle)也要摘 listener;timeout 赢时 attempt
1993
+ // 是输家 fiber,callback cleanup 已由 race/timeout 的 interrupt 触发,
1994
+ // 这里保证任何出口 listener 都被移除。
1995
+ Effect_exports.ensuring(Effect_exports.sync(() => {
1996
+ removeExternalListener();
1997
+ }))
1998
+ );
1999
+ return attempt;
2000
+ });
1804
2001
  }
1805
-
1806
- // packages/agent-runtime/antigravityCloudCodeProvider.ts
1807
- import { randomUUID as randomUUID2 } from "node:crypto";
1808
-
1809
- // packages/agent-runtime/antigravityWireModel.ts
1810
- var WIRE_PROFILES = {
1811
- // Antigravity discovery exposes 3.7 Flash as one tiered wire model.
1812
- // The UI labels its effort variants (Low/Medium/High), but the literal
1813
- // -medium/-high ids return 404 from streamGenerateContent.
1814
- "gemini-3.7-flash-tiered": { modelEnum: "MODEL_PLACEHOLDER_M301", maxOutputTokens: 65536 },
1815
- "gemini-3.6-flash-low": { maxOutputTokens: 65536 },
1816
- "gemini-3.6-flash-medium": { maxOutputTokens: 65536 },
1817
- "gemini-3.6-flash-high": { maxOutputTokens: 65536 },
1818
- // 旧模型 wire 映射保留:存量自定义 agent 仍可能引用(注册表已下线不影响此处)。
1819
- "gemini-3.5-flash-extra-low": { modelEnum: "MODEL_PLACEHOLDER_M187", maxOutputTokens: 65536 },
1820
- "gemini-3.5-flash-low": { modelEnum: "MODEL_PLACEHOLDER_M20", maxOutputTokens: 65536 },
1821
- "gemini-3-flash-agent": { modelEnum: "MODEL_PLACEHOLDER_M132", maxOutputTokens: 65536 },
1822
- "gemini-3.1-pro-low": { modelEnum: "MODEL_PLACEHOLDER_M36", maxOutputTokens: 65535 },
1823
- "gemini-pro-agent": { modelEnum: "MODEL_PLACEHOLDER_M16", maxOutputTokens: 65535 },
1824
- "claude-sonnet-5": { maxOutputTokens: 64e3 },
1825
- "claude-sonnet-4-6": { maxOutputTokens: 64e3 },
1826
- "claude-opus-4-6-thinking": { maxOutputTokens: 64e3 },
1827
- "gemini-2.5-flash": { maxOutputTokens: 65536 }
1828
- };
1829
- function resolveAntigravityWireModel(logicalModelId) {
1830
- const id = logicalModelId.trim();
1831
- const lower = id.toLowerCase();
1832
- if (lower === "gemini-3.5-flash") {
1833
- const wireModelId = "gemini-3.5-flash-low";
1834
- return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
1835
- }
1836
- if (lower === "gemini-3.7-flash" || ["gemini-3.7-flash-low", "gemini-3.7-flash-medium", "gemini-3.7-flash-high"].includes(lower)) {
1837
- const wireModelId = "gemini-3.7-flash-tiered";
1838
- return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
1839
- }
1840
- if (lower === "gemini-3.6-flash") {
1841
- const wireModelId = "gemini-3.6-flash-low";
1842
- return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
1843
- }
1844
- if (lower === "gemini-3.1-pro" || lower === "gemini-3.1-pro-preview") {
1845
- const wireModelId = "gemini-3.1-pro-low";
1846
- return { wireModelId, profile: WIRE_PROFILES[wireModelId] };
2002
+ function attemptWithAbort(args) {
2003
+ const externalSignal = args.externalSignal;
2004
+ if (!externalSignal) {
2005
+ return antigravityAttemptEffect(args);
1847
2006
  }
1848
- if (WIRE_PROFILES[id]) {
1849
- return { wireModelId: id, profile: WIRE_PROFILES[id] };
1850
- }
1851
- return { wireModelId: id };
1852
- }
1853
-
1854
- // packages/agent-runtime/geminiNativeShared.ts
1855
- var SKIP_THOUGHT_SIGNATURE = "skip_thought_signature_validator";
1856
- function isGemini3Model(modelId) {
1857
- return modelId.includes("gemini-3");
1858
- }
1859
- function messageText(content) {
1860
- if (typeof content === "string") return content;
1861
- if (!Array.isArray(content)) return "";
1862
- return content.filter(
1863
- (part) => part?.type === "text"
1864
- ).map((part) => part.text).join("\n").trim();
1865
- }
1866
- function parseDataUrlToInlineData(url) {
1867
- const match = /^data:([A-Za-z0-9.+-]+\/[A-Za-z0-9.+-]+);base64,([A-Za-z0-9+/=]*)$/.exec(
1868
- url
2007
+ let abortListener;
2008
+ const removeAbortListener = () => {
2009
+ if (abortListener) externalSignal.removeEventListener("abort", abortListener);
2010
+ abortListener = void 0;
2011
+ };
2012
+ const abortEffect = Effect_exports.callback((resume) => {
2013
+ const finish = () => resume(Effect_exports.succeed("aborted"));
2014
+ if (externalSignal.aborted) {
2015
+ finish();
2016
+ return;
2017
+ }
2018
+ abortListener = () => finish();
2019
+ externalSignal.addEventListener("abort", abortListener, { once: true });
2020
+ return Effect_exports.sync(removeAbortListener);
2021
+ }).pipe(Effect_exports.ensuring(Effect_exports.sync(removeAbortListener)));
2022
+ return Effect_exports.raceFirst(
2023
+ antigravityAttemptEffect(args),
2024
+ abortEffect
1869
2025
  );
1870
- if (!match) return null;
1871
- return { mimeType: match[1], data: match[2] };
1872
- }
1873
- function extractInlineDataParts(content) {
1874
- if (!Array.isArray(content)) return [];
1875
- const parts = [];
1876
- for (const part of content) {
1877
- if (!part || typeof part !== "object") continue;
1878
- if (part.type !== "image_url") continue;
1879
- const url = part.image_url?.url;
1880
- if (typeof url !== "string" || !url.trim()) continue;
1881
- const inline = parseDataUrlToInlineData(url);
1882
- if (inline) parts.push({ inlineData: inline });
1883
- }
1884
- return parts;
1885
2026
  }
1886
- function convertOpenAiMessagesToGemini(messages, options) {
1887
- const contents = [];
1888
- const systemTexts = [];
1889
- let toolCallIndex = 0;
1890
- let pendingFunctionCalls = [];
1891
- const pushOrMergeContent = (role, parts) => {
1892
- if (parts.length === 0) return;
1893
- const last = contents[contents.length - 1];
1894
- if (last && last.role === role) {
1895
- last.parts.push(...parts);
1896
- } else {
1897
- contents.push({ role, parts });
1898
- }
1899
- };
1900
- const flushPendingFunctionCalls = () => {
1901
- if (pendingFunctionCalls.length === 0) return;
1902
- const dummyResponses = pendingFunctionCalls.map(
1903
- ({ name, id }) => ({
1904
- functionResponse: {
1905
- name,
1906
- response: { output: "{}" },
1907
- ...id ? { id } : {}
1908
- }
1909
- })
2027
+ function invokeAntigravityEffect(args) {
2028
+ const authRetryable = args.authRetryableStatuses ?? AUTH_RETRYABLE_STATUSES;
2029
+ const timeoutMs = typeof args.timeoutMs === "number" && args.timeoutMs > 0 ? args.timeoutMs : void 0;
2030
+ const runOneAttempt = (credential) => Effect_exports.suspend(
2031
+ () => attemptWithAbort({
2032
+ agentConfig: args.agentConfig,
2033
+ credential,
2034
+ openAiBody: args.openAiBody,
2035
+ externalSignal: args.signal,
2036
+ fetchImpl: args.fetchImpl ?? fetch,
2037
+ ...args.onTextDelta ? { onTextDelta: args.onTextDelta } : {},
2038
+ ...args.onReasoningDelta ? { onReasoningDelta: args.onReasoningDelta } : {}
2039
+ })
2040
+ );
2041
+ const orchestration = Effect_exports.gen(function* () {
2042
+ const firstCredential = yield* Effect_exports.tryPromise({
2043
+ try: () => args.resolveCredential({ forceRefresh: false }),
2044
+ catch: (error) => error
2045
+ });
2046
+ const first = yield* Effect_exports.exit(
2047
+ runOneAttempt(firstCredential)
1910
2048
  );
1911
- pendingFunctionCalls = [];
1912
- pushOrMergeContent("user", dummyResponses);
1913
- };
1914
- for (const raw of messages) {
1915
- if (!raw || typeof raw !== "object" || !("role" in raw)) continue;
1916
- const role = String(raw.role);
1917
- const content = "content" in raw ? raw.content : null;
1918
- if (role === "system") {
1919
- const text = messageText(
1920
- content
1921
- );
1922
- if (text) systemTexts.push(text);
1923
- continue;
1924
- }
1925
- if (role === "user") {
1926
- flushPendingFunctionCalls();
1927
- const text = messageText(
1928
- content
1929
- );
1930
- const imageParts = extractInlineDataParts(
1931
- content
1932
- );
1933
- if (!text && imageParts.length === 0) continue;
1934
- const parts = [];
1935
- if (text) parts.push({ text });
1936
- for (const img of imageParts) parts.push(img);
1937
- pushOrMergeContent("user", parts);
1938
- continue;
1939
- }
1940
- if (role === "assistant") {
1941
- flushPendingFunctionCalls();
1942
- const text = messageText(
1943
- content
2049
+ if (Exit_exports.isFailure(first)) {
2050
+ const errorOption = Exit_exports.findErrorOption(first);
2051
+ const error = Option_exports.isSome(errorOption) ? errorOption.value : first.cause;
2052
+ if (isAntigravityAbortErrorValue(error)) {
2053
+ return { kind: "aborted" };
2054
+ }
2055
+ return { kind: "failed", error };
2056
+ }
2057
+ let current = first.value;
2058
+ if (typeof current !== "string" && supportsAuthRetry(args.supportsAuthRetry, current.status, authRetryable)) {
2059
+ const refreshed = yield* Effect_exports.exit(
2060
+ Effect_exports.tryPromise({
2061
+ try: () => args.resolveCredential({ forceRefresh: true }),
2062
+ catch: (error) => error
2063
+ })
1944
2064
  );
1945
- const toolCalls = "tool_calls" in raw && Array.isArray(raw.tool_calls) ? raw.tool_calls ?? [] : [];
1946
- const parts = [];
1947
- if (text) {
1948
- parts.push({ text });
1949
- }
1950
- for (const call of toolCalls) {
1951
- const name = call?.function?.name?.trim();
1952
- if (!name) continue;
1953
- const id = call.id?.trim() || `${name}_${toolCallIndex++}`;
1954
- pendingFunctionCalls.push({ name, id });
1955
- const realSignature = typeof call.thought_signature === "string" && call.thought_signature ? call.thought_signature : void 0;
1956
- const isFirstFunctionCallPart = !parts.some(
1957
- (p) => "functionCall" in p
2065
+ if (Exit_exports.isSuccess(refreshed) && credentialChanged(firstCredential, refreshed.value)) {
2066
+ const retried = yield* Effect_exports.exit(
2067
+ runOneAttempt(refreshed.value)
1958
2068
  );
1959
- const signature = realSignature ?? (options.attachSkipThoughtSignature && isFirstFunctionCallPart ? SKIP_THOUGHT_SIGNATURE : void 0);
1960
- const part = {
1961
- functionCall: {
1962
- name,
1963
- args: parseToolArgs(call.function?.arguments),
1964
- ...id ? { id } : {}
1965
- },
1966
- ...signature ? { thoughtSignature: signature } : {}
1967
- };
1968
- parts.push(part);
1969
- }
1970
- pushOrMergeContent("model", parts);
1971
- continue;
1972
- }
1973
- if (role === "tool") {
1974
- const toolCallId = "tool_call_id" in raw && typeof raw.tool_call_id === "string" ? raw.tool_call_id : "";
1975
- const rawName = "name" in raw && typeof raw.name === "string" ? raw.name.trim() : "";
1976
- const pendingIndex = pendingFunctionCalls.findIndex(
1977
- (p) => toolCallId ? p.id === toolCallId : rawName ? p.name === rawName : true
1978
- );
1979
- if (pendingIndex === -1) continue;
1980
- const [{ name, id }] = pendingFunctionCalls.splice(pendingIndex, 1);
1981
- const output = messageText(content) || "{}";
1982
- pushOrMergeContent("user", [
1983
- {
1984
- functionResponse: {
1985
- name,
1986
- response: { output },
1987
- // 保留 OpenAI tool_call_id:antigravity Cloud Code Assist 网关把
1988
- // Gemini contents 转成 Claude messages 时需要 functionResponse →
1989
- // tool_result 的 tool_use_id;缺 id 时网关报
1990
- // "tool_result.tool_use_id: Field required"(HTTP 400)。
1991
- ...id ? { id } : {}
1992
- }
2069
+ if (Exit_exports.isSuccess(retried)) {
2070
+ current = retried.value;
1993
2071
  }
1994
- ]);
1995
- }
1996
- }
1997
- flushPendingFunctionCalls();
1998
- if (contents.length > 0 && contents[0]?.role === "model") {
1999
- contents.unshift({
2000
- role: "user",
2001
- parts: [{ text: "Continue the conversation." }]
2002
- });
2003
- }
2004
- return { contents, systemTexts };
2005
- }
2006
- function parseToolArgs(raw) {
2007
- if (typeof raw === "string") {
2008
- try {
2009
- const parsed = JSON.parse(raw);
2010
- if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
2011
- return parsed;
2012
2072
  }
2013
- } catch {
2014
2073
  }
2015
- }
2016
- if (raw && typeof raw === "object" && !Array.isArray(raw)) {
2017
- return raw;
2018
- }
2019
- return {};
2074
+ if (current === "aborted") return { kind: "aborted" };
2075
+ return { kind: "done", result: current };
2076
+ }).pipe(Effect_exports.catch((error) => Effect_exports.succeed({
2077
+ kind: "failed",
2078
+ error
2079
+ })));
2080
+ if (typeof timeoutMs !== "number") return orchestration;
2081
+ return Effect_exports.gen(function* () {
2082
+ const outcome = yield* Effect_exports.timeoutOption(orchestration, Duration_exports.millis(timeoutMs));
2083
+ return Option_exports.isNone(outcome) ? { kind: "timeout" } : outcome.value;
2084
+ });
2020
2085
  }
2021
- function convertOpenAiToolsToGemini(tools) {
2022
- if (!Array.isArray(tools) || tools.length === 0) return void 0;
2023
- const declarations = [];
2024
- for (const tool of tools) {
2025
- if (!tool || typeof tool !== "object" || !("function" in tool)) continue;
2026
- const fn = tool.function;
2027
- const name = typeof fn.name === "string" ? fn.name : "";
2028
- if (!name) continue;
2029
- declarations.push({
2030
- name,
2031
- description: typeof fn.description === "string" ? fn.description : "",
2032
- parameters: fn.parameters ?? { type: "object", properties: {} }
2033
- });
2034
- }
2035
- if (declarations.length === 0) return void 0;
2036
- return [{ functionDeclarations: declarations }];
2086
+ function supportsAuthRetry(supports, status, authRetryable) {
2087
+ return supports && authRetryable.has(status);
2037
2088
  }
2038
- function createGeminiAccumulatorState() {
2039
- return {
2040
- text: "",
2041
- toolCalls: []
2042
- };
2089
+ function isAntigravityAbortErrorValue(error) {
2090
+ const code = error?.code;
2091
+ return code === "ANTIGRAVITY_INVOCATION_ABORTED" || error instanceof Error && error.name === "AbortError" || typeof DOMException !== "undefined" && error instanceof DOMException && error.name === "AbortError";
2043
2092
  }
2044
- function applyGeminiChunk(chunk, state, options) {
2045
- if (!chunk || typeof chunk !== "object") return;
2046
- const response = "response" in chunk && chunk.response && typeof chunk.response === "object" ? chunk.response : chunk;
2047
- if ("usageMetadata" in response && response.usageMetadata && typeof response.usageMetadata === "object") {
2048
- const meta = response.usageMetadata;
2049
- const prompt = typeof meta.promptTokenCount === "number" ? meta.promptTokenCount : 0;
2050
- const candidates2 = typeof meta.candidatesTokenCount === "number" ? meta.candidatesTokenCount : 0;
2051
- const total = typeof meta.totalTokenCount === "number" ? meta.totalTokenCount : prompt + candidates2;
2052
- state.usage = {
2053
- prompt_tokens: prompt,
2054
- completion_tokens: candidates2,
2055
- total_tokens: total
2056
- };
2093
+ function credentialChanged(before, after) {
2094
+ return before.accessToken !== after.accessToken || before.accountId !== after.accountId || before.projectId !== after.projectId || JSON.stringify(before.metadata) !== JSON.stringify(after.metadata);
2095
+ }
2096
+ async function invokeAntigravity(args) {
2097
+ const outcome = await (args.runtime ? args.runtime.runPromise(invokeAntigravityEffect(args)) : Effect_exports.runPromise(invokeAntigravityEffect(args)));
2098
+ if (outcome.kind === "done") return outcome.result;
2099
+ if (outcome.kind === "timeout") {
2100
+ throw buildInvocationError("ANTIGRAVITY_INVOCATION_TIMEOUT", "Antigravity invocation timed out.");
2057
2101
  }
2058
- const candidates = Array.isArray(response.candidates) ? response.candidates : [];
2059
- for (const candidate of candidates) {
2060
- if (!candidate || typeof candidate !== "object") continue;
2061
- const parts = Array.isArray(
2062
- candidate.content?.parts
2063
- ) ? candidate.content.parts : [];
2064
- for (const part of parts) {
2065
- if (!part || typeof part !== "object") continue;
2066
- const partSignature = part.thoughtSignature;
2067
- const isThought = Boolean(part.thought);
2068
- if ("text" in part && typeof part.text === "string") {
2069
- const piece = part.text;
2070
- if (!isThought) {
2071
- state.text += piece;
2072
- if (piece && options?.onTextDelta) {
2073
- options.onTextDelta(piece);
2074
- }
2075
- } else {
2076
- if (piece && options?.onReasoningDelta) {
2077
- options.onReasoningDelta(piece);
2078
- }
2079
- }
2080
- }
2081
- if (isThought && typeof partSignature === "string" && partSignature) {
2082
- state.pendingThoughtSignature = partSignature;
2083
- }
2084
- if ("functionCall" in part && part.functionCall) {
2085
- const call = part.functionCall;
2086
- const name = typeof call.name === "string" ? call.name : "tool";
2087
- const id = typeof call.id === "string" ? call.id : `${name}_${state.toolCalls.length}`;
2088
- const argsObj = call.args && typeof call.args === "object" ? call.args : {};
2089
- const resolvedSignature = typeof partSignature === "string" && partSignature ? partSignature : state.pendingThoughtSignature;
2090
- state.pendingThoughtSignature = void 0;
2091
- state.toolCalls.push({
2092
- id,
2093
- type: "function",
2094
- function: { name, arguments: JSON.stringify(argsObj) },
2095
- ...typeof resolvedSignature === "string" && resolvedSignature ? { thought_signature: resolvedSignature } : {}
2096
- });
2097
- }
2098
- }
2102
+ if (outcome.kind === "aborted") {
2103
+ throw buildInvocationError("ANTIGRAVITY_INVOCATION_ABORTED", "Antigravity invocation aborted.");
2099
2104
  }
2105
+ throw outcome.error ?? new Error("Antigravity invocation failed.");
2100
2106
  }
2101
- function accumulateGeminiChunks(chunks, options) {
2102
- const state = createGeminiAccumulatorState();
2103
- for (const chunk of chunks) {
2104
- applyGeminiChunk(chunk, state, options);
2105
- }
2106
- return {
2107
- text: state.text,
2108
- toolCalls: state.toolCalls,
2109
- usage: state.usage
2110
- };
2107
+ function buildInvocationError(code, message) {
2108
+ const error = new Error(message);
2109
+ error.code = code;
2110
+ return error;
2111
2111
  }
2112
- async function accumulateGeminiStream(stream, options) {
2113
- const state = createGeminiAccumulatorState();
2114
- for await (const chunk of stream) {
2115
- applyGeminiChunk(chunk, state, options);
2116
- }
2112
+ function isAntigravityInvocationAbortError(error) {
2113
+ const code = error?.code;
2114
+ return error instanceof Error && (code === "ANTIGRAVITY_INVOCATION_ABORTED" || code === "ANTIGRAVITY_INVOCATION_TIMEOUT");
2115
+ }
2116
+
2117
+ // packages/agent-runtime/antigravityCredential.ts
2118
+ function createAntigravityCredentialPlan(args) {
2119
+ const owner = asOptionalTrimmedString(args.credentialOwnerUserId);
2120
+ if (!owner) throw new Error("Antigravity credential owner is required.");
2117
2121
  return {
2118
- text: state.text,
2119
- toolCalls: state.toolCalls,
2120
- usage: state.usage
2122
+ provider: "antigravity",
2123
+ credentialOwnerUserId: owner,
2124
+ source: args.source,
2125
+ forceRefresh: args.forceRefresh === true
2121
2126
  };
2122
2127
  }
2123
- function shouldUseGeminiNativeToolRoute(provider, model, tools, isImageModel) {
2124
- return provider === "google" && !isImageModel(model) && isGemini3Model(model) && Array.isArray(tools) && tools.length > 0;
2125
- }
2126
- function buildGeminiGenerateContentRequest(args) {
2127
- const { contents, systemTexts } = convertOpenAiMessagesToGemini(
2128
- args.messages,
2129
- { attachSkipThoughtSignature: args.attachSkipThoughtSignature }
2130
- );
2131
- const request = { contents };
2132
- if (systemTexts.length > 0) {
2133
- request.systemInstruction = {
2134
- role: "user",
2135
- parts: systemTexts.map((text) => ({ text }))
2136
- };
2137
- }
2138
- const toolsResult = convertOpenAiToolsToGemini(args.tools);
2139
- if (toolsResult) {
2140
- request.tools = toolsResult;
2141
- request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
2128
+ function resolveAntigravityCredential(args) {
2129
+ if (args.plan.provider !== "antigravity") {
2130
+ throw new Error("Unsupported Antigravity credential plan provider.");
2142
2131
  }
2143
- const generationConfig = {};
2144
- if (typeof args.maxTokens === "number" && args.maxTokens > 0) {
2145
- generationConfig.maxOutputTokens = args.maxTokens;
2146
- }
2147
- if (typeof args.temperature === "number") {
2148
- generationConfig.temperature = args.temperature;
2149
- }
2150
- if (Object.keys(generationConfig).length > 0) {
2151
- request.generationConfig = generationConfig;
2152
- }
2153
- return request;
2132
+ return toResolvedAntigravityCredential(args);
2154
2133
  }
2155
-
2156
- // packages/agent-runtime/antigravityCloudCodeProvider.ts
2157
- var STREAM_PATH = "/v1internal:streamGenerateContent?alt=sse";
2158
- function buildCloudCodeAssistPayload(args) {
2159
- const projectId = readAntigravityProjectId(args.metadata);
2134
+ function toResolvedAntigravityCredential(args) {
2135
+ const accessToken = asOptionalTrimmedString(args.accessToken);
2136
+ const projectId = asOptionalTrimmedString(args.metadata?.projectId);
2137
+ if (!accessToken) throw new Error("Antigravity credential access token is missing.");
2160
2138
  if (!projectId) {
2161
2139
  throw new Error(
2162
2140
  "Antigravity OAuth credential is missing metadata.projectId. Re-run `nolo auth antigravity`."
2163
2141
  );
2164
2142
  }
2165
- const logicalModel = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gemini-3.1-pro";
2166
- const { wireModelId: model, profile } = resolveAntigravityWireModel(logicalModel);
2167
- const rawMessages = Array.isArray(args.openAiBody.messages) ? args.openAiBody.messages : [];
2168
- const isClaude = model.toLowerCase().includes("claude");
2169
- const { contents, systemTexts } = convertOpenAiMessagesToGemini(rawMessages, {
2170
- attachSkipThoughtSignature: isGemini3Model(model)
2171
- });
2172
- if (contents.length === 0) {
2173
- throw new Error("Antigravity Cloud Code Assist request has no user/model contents.");
2174
- }
2175
- const prompt = args.agentConfig.prompt?.trim();
2176
- if (prompt) systemTexts.unshift(prompt);
2177
- const request = { contents };
2178
- if (systemTexts.length > 0) {
2179
- request.systemInstruction = {
2180
- role: "user",
2181
- parts: systemTexts.map((text) => ({ text }))
2182
- };
2183
- }
2184
- const tools = convertOpenAiToolsToGemini(
2185
- Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
2186
- );
2187
- if (tools) {
2188
- request.tools = tools;
2189
- request.toolConfig = { functionCallingConfig: { mode: "VALIDATED" } };
2190
- }
2191
- const generationConfig = {};
2192
- if (profile?.maxOutputTokens) {
2193
- generationConfig.maxOutputTokens = profile.maxOutputTokens;
2194
- } else if (typeof args.agentConfig.max_tokens === "number" && args.agentConfig.max_tokens > 0) {
2195
- generationConfig.maxOutputTokens = args.agentConfig.max_tokens;
2196
- }
2197
- if (typeof args.agentConfig.temperature === "number") {
2198
- generationConfig.temperature = args.agentConfig.temperature;
2199
- }
2200
- if (Object.keys(generationConfig).length > 0) {
2201
- request.generationConfig = generationConfig;
2202
- }
2203
- const agentId = randomUUID2();
2204
- const trajectoryId = randomUUID2();
2205
- const step = 2;
2206
- const requestId = `agent/${agentId}/${Date.now()}/${trajectoryId}/${step}`;
2207
- const labels = {
2208
- trajectory_id: trajectoryId,
2209
- last_step_index: String(step - 1),
2210
- used_claude: String(isClaude),
2211
- used_claude_conservative: String(isClaude)
2212
- };
2213
- if (profile?.modelEnum) {
2214
- labels.model_enum = profile.modelEnum;
2215
- }
2216
- request.labels = labels;
2217
- request.sessionId = `-${Math.floor(Math.random() * 9e15)}`;
2218
2143
  return {
2219
- url: `${resolveAntigravityCloudCodeBaseUrl(args.agentConfig.customProviderUrl)}${STREAM_PATH}`,
2220
- envelope: {
2221
- project: projectId,
2222
- model,
2223
- request,
2224
- requestId,
2225
- requestType: "agent",
2226
- userAgent: "antigravity"
2227
- }
2144
+ provider: "antigravity",
2145
+ accessToken,
2146
+ projectId,
2147
+ metadata: { ...args.metadata ?? {}, projectId },
2148
+ accountId: asOptionalTrimmedString(args.accountId) ?? null
2228
2149
  };
2229
2150
  }
2230
- async function fetchAntigravityCloudCodeCompletion(args) {
2231
- const fetchImpl = args.fetchImpl ?? fetch;
2232
- const { url, envelope } = buildCloudCodeAssistPayload(args);
2233
- const response = await fetchImpl(url, {
2234
- method: "POST",
2235
- headers: {
2236
- Authorization: `Bearer ${args.accessToken}`,
2237
- "Content-Type": "application/json",
2238
- "User-Agent": getAntigravityUserAgent()
2239
- },
2240
- body: JSON.stringify(envelope),
2241
- signal: args.signal
2242
- });
2243
- if (!response.ok) {
2244
- const errorText = await response.text();
2245
- return {
2246
- status: response.status,
2247
- // 保留上游结构:Antigravity 的限流 body 同样携带结构化的重置信息,
2248
- // 压成字符串会让冷却退化成 5 分钟默认值。
2249
- body: parseUpstreamErrorBody(errorText, response.statusText)
2250
- };
2151
+ async function resolveLocalAntigravityCredential(args) {
2152
+ const rawRef = asTrimmedLowercaseString(args.apiKeyRef);
2153
+ const isApiKeyRef = rawRef.startsWith("api-key:");
2154
+ const providerRef = isApiKeyRef ? rawRef : rawRef || "antigravity";
2155
+ if (isApiKeyRef && args.forceRefresh) {
2156
+ throw new Error(`Cannot force-refresh non-OAuth API key ref "${rawRef}".`);
2251
2157
  }
2252
- const chunkStream = streamSseDataValues(response, parseSseDataLineJson);
2253
- const { text, toolCalls, usage } = await accumulateGeminiStream(chunkStream, {
2254
- onTextDelta: args.onTextDelta,
2255
- onReasoningDelta: args.onReasoningDelta
2256
- });
2257
- const message = {
2258
- role: "assistant",
2259
- content: text || null
2260
- };
2261
- if (toolCalls.length > 0) {
2262
- message.tool_calls = toolCalls;
2263
- }
2264
- return {
2265
- status: 200,
2266
- body: {
2267
- choices: [
2268
- {
2269
- index: 0,
2270
- message,
2271
- finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop"
2272
- }
2273
- ],
2274
- ...usage ? { usage } : {}
2158
+ const token = await args.apiKeyRefResolver(
2159
+ providerRef,
2160
+ args.forceRefresh ? { force: true } : void 0
2161
+ );
2162
+ const trimmedToken = asOptionalTrimmedString(token);
2163
+ if (!trimmedToken) {
2164
+ if (isApiKeyRef) {
2165
+ throw new Error(`API key for "${rawRef}" not found locally.`);
2275
2166
  }
2276
- };
2167
+ throw new Error(
2168
+ 'OAuth credential for "antigravity" not found locally. Run `nolo auth antigravity`.'
2169
+ );
2170
+ }
2171
+ const read = args.readCredential ?? readOAuthCredential;
2172
+ const raw = read("antigravity");
2173
+ const plan = createAntigravityCredentialPlan({
2174
+ credentialOwnerUserId: args.credentialOwnerUserId || "local",
2175
+ source: args.source || "local",
2176
+ forceRefresh: args.forceRefresh === true
2177
+ });
2178
+ return resolveAntigravityCredential({
2179
+ plan,
2180
+ accessToken: trimmedToken,
2181
+ metadata: raw?.metadata ?? args.metadata ?? null,
2182
+ accountId: raw?.accountId ?? args.accountId ?? null
2183
+ });
2277
2184
  }
2278
2185
 
2279
2186
  // packages/core/summarizeEndpoint.ts
@@ -2287,21 +2194,98 @@ function summarizeEndpoint(value) {
2287
2194
  }
2288
2195
  }
2289
2196
 
2197
+ // packages/cli/client/localRuntimeHelpers.ts
2198
+ var REMOTE_DIALOG_SYNC_TIMEOUT_MS = 1e4;
2199
+ var remoteDialogSyncTimeoutMsForTest;
2200
+ function remoteDialogSyncTimeout() {
2201
+ return remoteDialogSyncTimeoutMsForTest ?? REMOTE_DIALOG_SYNC_TIMEOUT_MS;
2202
+ }
2203
+ function resolveRuntimeServerUrl(env) {
2204
+ return (env?.NOLO_SERVER_URL || env?.NOLO_SERVER || env?.BASE_URL || "").replace(/\/+$/, "");
2205
+ }
2206
+ function resolveRuntimeAuthToken(env) {
2207
+ return resolvePlatformAuthToken(env ?? {});
2208
+ }
2209
+
2210
+ // packages/cli/client/cliAgentConfigHelpers.ts
2211
+ var BUILTIN_NOLO_AGENT_KEY = NOLO_DEFAULT_AGENT_KEY;
2212
+ var BUILTIN_NOLO_AGENT_ID = NOLO_DEFAULT_AGENT_ID;
2213
+ function resolveLocalUserId(env) {
2214
+ const explicitUserId = env.NOLO_LOCAL_USER_ID || env.NOLO_USER_ID;
2215
+ if (explicitUserId) return explicitUserId;
2216
+ const tokenUserId = parseUserIdFromAuthToken(resolveRuntimeAuthToken(env));
2217
+ return tokenUserId || "local";
2218
+ }
2219
+ function isBuiltinNoloAgentRef(ref) {
2220
+ if (typeof ref !== "string") return false;
2221
+ const normalized = ref.trim();
2222
+ return normalized === BUILTIN_NOLO_AGENT_KEY || normalized === BUILTIN_NOLO_AGENT_ID || normalized.endsWith(`-${BUILTIN_NOLO_AGENT_ID}`);
2223
+ }
2224
+ function isBuiltinNoloAgentConfig(agentConfig) {
2225
+ const key = agentConfig?.key || agentConfig?.rawRecord?.dbKey || agentConfig?.rawRecord?.agentKey;
2226
+ const id = agentConfig?.rawRecord?.id;
2227
+ return isBuiltinNoloAgentRef(key) || isBuiltinNoloAgentRef(id);
2228
+ }
2229
+ function withResolvedRuntimeToolSurface(agentConfig, env) {
2230
+ if (!agentConfig) return agentConfig;
2231
+ const currentUserId = resolveLocalUserId(env);
2232
+ const rawRecord = agentConfig.rawRecord ?? {};
2233
+ const ownerId = asOptionalTrimmedString(rawRecord.userId) ?? null;
2234
+ const agentKey = rawRecord.dbKey ?? agentConfig.key;
2235
+ const toolSurface = resolveRuntimeToolSurfaceForAgent({
2236
+ explicitToolNames: agentConfig.toolNames,
2237
+ currentUserId,
2238
+ agentOwnerId: ownerId,
2239
+ agentKey,
2240
+ isPublic: !isBuiltinNoloAgentConfig(agentConfig) && rawRecord.isPublic === true,
2241
+ sharingLevel: typeof rawRecord.sharingLevel === "string" ? rawRecord.sharingLevel : null,
2242
+ trustedPrivateInvocation: isBuiltinNoloAgentConfig(agentConfig) || isSystemBuiltinTrustedAgentKey(agentKey),
2243
+ runtimeHost: "cli"
2244
+ });
2245
+ return {
2246
+ ...agentConfig,
2247
+ toolNames: toolSurface.finalToolNames,
2248
+ toolSurface,
2249
+ prompt: agentConfig.prompt
2250
+ };
2251
+ }
2252
+ function extractLastUserText(messages) {
2253
+ const lastUser = [...messages].reverse().find((m) => m.role === "user");
2254
+ if (!lastUser) return "";
2255
+ if (typeof lastUser.content === "string") return lastUser.content;
2256
+ if (Array.isArray(lastUser.content)) {
2257
+ return lastUser.content.filter((part) => part?.type === "text").map((part) => part.text ?? "").join(" ");
2258
+ }
2259
+ return "";
2260
+ }
2261
+ function localTurnHasSubjectRefs(input) {
2262
+ return Array.isArray(input.runtimeContext?.subjectRefs) && input.runtimeContext.subjectRefs.length > 0;
2263
+ }
2264
+
2290
2265
  // packages/cli/client/providerResolution/antigravityTransport.ts
2291
2266
  var resolveAntigravityTransport = async (ctx) => {
2292
- const { agentConfig, deps, fetchImpl, loopbackRequest, additionalToolNames, buildProviderOpenAiTools, recordLocalAvailability, apiKeyRefResolver } = ctx;
2267
+ const {
2268
+ agentConfig,
2269
+ deps,
2270
+ fetchImpl,
2271
+ loopbackRequest,
2272
+ additionalToolNames,
2273
+ buildProviderOpenAiTools,
2274
+ recordLocalAvailability,
2275
+ apiKeyRefResolver
2276
+ } = ctx;
2277
+ const legacyCredentialMigration = { enableLegacyMigration: true };
2293
2278
  if (isAntigravityOAuthAgent(agentConfig)) {
2294
- const resolveAccessToken = async () => {
2295
- const accessToken = await apiKeyRefResolver("antigravity");
2296
- if (!accessToken) {
2297
- throw new Error(
2298
- 'OAuth credential for "antigravity" not found locally. Run `nolo auth antigravity`.'
2299
- );
2300
- }
2301
- return accessToken;
2302
- };
2303
- await resolveAccessToken();
2304
- const credential = readOAuthCredential("antigravity");
2279
+ const credentialOwnerUserId = resolveLocalUserId(deps.env) || "local";
2280
+ const apiKeyRef = asTrimmedLowercaseString(agentConfig.apiKeyRef);
2281
+ const isApiKeyRef = apiKeyRef.startsWith("api-key:");
2282
+ const initialCredential = await resolveLocalAntigravityCredential({
2283
+ credentialOwnerUserId,
2284
+ apiKeyRefResolver,
2285
+ apiKeyRef: agentConfig.apiKeyRef,
2286
+ readCredential: () => readOAuthCredential("antigravity", void 0, legacyCredentialMigration),
2287
+ migration: legacyCredentialMigration
2288
+ });
2305
2289
  const { requestedToolNames, tools } = resolveProviderOpenAiToolBundle(
2306
2290
  agentConfig,
2307
2291
  deps.env,
@@ -2316,7 +2300,7 @@ var resolveAntigravityTransport = async (ctx) => {
2316
2300
  model: agentConfig.model ?? null,
2317
2301
  customProviderEndpoint: summarizeEndpoint(agentConfig.customProviderUrl) ?? null,
2318
2302
  hasApiKey: true,
2319
- hasProjectId: Boolean(credential?.metadata?.projectId)
2303
+ hasProjectId: Boolean(initialCredential?.projectId)
2320
2304
  });
2321
2305
  return {
2322
2306
  model: agentConfig.model || "gemini-3.1-pro",
@@ -2336,52 +2320,79 @@ var resolveAntigravityTransport = async (ctx) => {
2336
2320
  requestedToolNames,
2337
2321
  openAiToolNames: summarizeOpenAiToolNames(tools)
2338
2322
  });
2339
- const accessToken = await resolveAccessToken();
2340
- const sendCcaRequest = (token) => fetchAntigravityCloudCodeCompletion({
2341
- agentConfig,
2342
- accessToken: token,
2343
- metadata: credential?.metadata ?? null,
2344
- openAiBody,
2345
- signal: options?.signal,
2346
- onTextDelta: options?.onTextDelta,
2347
- onReasoningDelta: options?.onReasoningDelta,
2348
- fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
2349
- sleep: deps.sleep,
2350
- loopbackRequest
2351
- })
2323
+ const resolveLocalCredential = async ({ forceRefresh }) => resolveLocalAntigravityCredential({
2324
+ credentialOwnerUserId,
2325
+ apiKeyRefResolver,
2326
+ apiKeyRef: agentConfig.apiKeyRef,
2327
+ readCredential: () => readOAuthCredential("antigravity", void 0, legacyCredentialMigration),
2328
+ migration: legacyCredentialMigration,
2329
+ forceRefresh
2352
2330
  });
2353
- let result = await sendCcaRequest(accessToken);
2354
- if (result.status === 401) {
2355
- try {
2356
- const refreshed = await apiKeyRefResolver("antigravity", {
2357
- force: true
2358
- });
2359
- if (refreshed && refreshed !== accessToken) {
2360
- logLocalRuntimeDiagnostic("provider.request.auth_retry", {
2361
- agentKey: agentConfig.key,
2362
- transport: "antigravity-cloud-code"
2363
- });
2364
- result = await sendCcaRequest(refreshed);
2365
- }
2366
- } catch (error) {
2367
- logLocalRuntimeDiagnostic("provider.request.auth_retry_failed", {
2368
- agentKey: agentConfig.key,
2369
- transport: "antigravity-cloud-code",
2370
- error: toErrorMessage(error)
2371
- });
2372
- }
2331
+ let result;
2332
+ try {
2333
+ result = await invokeAntigravity({
2334
+ agentConfig,
2335
+ resolveCredential: resolveLocalCredential,
2336
+ // 非 OAuth(api-key ref)不重试:metered key 没有 refresh 语义。
2337
+ supportsAuthRetry: !isApiKeyRef,
2338
+ openAiBody,
2339
+ ...options?.signal ? { signal: options.signal } : {},
2340
+ // whole-invocation timeout 透传:seam 最外层 timeoutOption 统一 interrupt
2341
+ // 整个 orchestration(resolve/attempt/refresh 共享预算)并真实 abort fetch/SSE。
2342
+ ...typeof options?.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {},
2343
+ onTextDelta: options?.onTextDelta,
2344
+ onReasoningDelta: options?.onReasoningDelta,
2345
+ fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
2346
+ sleep: deps.sleep,
2347
+ loopbackRequest
2348
+ })
2349
+ });
2350
+ } catch (error) {
2351
+ if (isAntigravityInvocationAbortError(error)) throw error;
2352
+ logLocalRuntimeDiagnostic("provider.request.result", {
2353
+ agentKey: agentConfig.key,
2354
+ transport: "antigravity-cloud-code",
2355
+ ok: false,
2356
+ error: toErrorMessage(error)
2357
+ });
2358
+ throw error;
2373
2359
  }
2374
2360
  await recordLocalAvailability(result.status, result.body);
2361
+ if (result.providerFailure) {
2362
+ logLocalRuntimeDiagnostic("provider.request.failure", {
2363
+ agentKey: agentConfig.key,
2364
+ transport: "antigravity-cloud-code",
2365
+ code: result.providerFailure.code,
2366
+ providerReason: result.providerFailure.providerReason,
2367
+ retryable: result.providerFailure.retryable
2368
+ });
2369
+ return {
2370
+ content: "",
2371
+ model: agentConfig.model || "gemini-3.1-pro",
2372
+ provider: agentConfig.provider || "google-antigravity",
2373
+ finish_reason: "error",
2374
+ stream_complete: true,
2375
+ error: true,
2376
+ errorMessage: result.providerFailure.message,
2377
+ providerEvents: result.providerEvents,
2378
+ providerFailure: result.providerFailure,
2379
+ runtimeProviderFailure: result.runtimeProviderFailure,
2380
+ trace: messages
2381
+ };
2382
+ }
2375
2383
  if (result.status < 200 || result.status >= 300) {
2376
2384
  const errMsg = result.body && typeof result.body === "object" && result.body.error && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
2377
2385
  throw new Error(
2378
2386
  `local antigravity provider failed: HTTP ${result.status} ${errMsg}`
2379
2387
  );
2380
2388
  }
2381
- const choice = Array.isArray(result.body.choices) ? result.body.choices[0] : void 0;
2389
+ const choice = Array.isArray(result.body?.choices) ? result.body.choices[0] : void 0;
2382
2390
  const message = choice?.message ?? {};
2383
- const content = typeof message.content === "string" ? message.content : message.content == null ? "" : String(message.content);
2384
- const tool_calls = Array.isArray(message.tool_calls) ? message.tool_calls : void 0;
2391
+ const tool_calls = Array.isArray(result.toolCalls) && result.toolCalls.length > 0 ? result.toolCalls : Array.isArray(message.tool_calls) ? message.tool_calls : void 0;
2392
+ const content = typeof result.text === "string" ? result.text : typeof message.content === "string" ? message.content : message.content == null ? "" : String(message.content);
2393
+ const reasoning_content = typeof result.reasoningContent === "string" ? result.reasoningContent : typeof message.reasoning_content === "string" ? message.reasoning_content : void 0;
2394
+ const finish_reason = tool_calls && tool_calls.length > 0 ? "tool_calls" : typeof result.finishReason === "string" ? resolveAntigravityFinishReason(result.finishReason) : typeof choice?.finish_reason === "string" ? choice.finish_reason : void 0;
2395
+ const usage = result.usage ?? result.body?.usage;
2385
2396
  logLocalRuntimeDiagnostic("provider.request.result", {
2386
2397
  agentKey: agentConfig.key,
2387
2398
  transport: "antigravity-cloud-code",
@@ -2394,12 +2405,14 @@ var resolveAntigravityTransport = async (ctx) => {
2394
2405
  model: agentConfig.model || "gemini-3.1-pro",
2395
2406
  provider: agentConfig.provider || "google-antigravity",
2396
2407
  ...tool_calls ? { tool_calls } : {},
2397
- // fetchAntigravityCloudCodeCompletion 已把 CCA 流聚合完毕并归一化成
2398
- // OpenAI chat.completions 形状:choices[0] + usage
2399
- // (prompt_tokens/completion_tokens/total_tokens)。必须透传,否则
2400
- // localLoop 的 lastUsage 无 token 数,TUI context chip 拿不到更新。
2401
- usage: result.body?.usage,
2402
- trace: messages
2408
+ ...reasoning_content ? { reasoning_content } : {},
2409
+ finish_reason,
2410
+ stream_complete: true,
2411
+ ...usage ? { usage } : {},
2412
+ trace: messages,
2413
+ providerEvents: result.providerEvents,
2414
+ ...result.providerFailure ? { providerFailure: result.providerFailure } : {},
2415
+ ...result.runtimeProviderFailure ? { runtimeProviderFailure: result.runtimeProviderFailure } : {}
2403
2416
  };
2404
2417
  }
2405
2418
  };
@@ -2407,14 +2420,136 @@ var resolveAntigravityTransport = async (ctx) => {
2407
2420
  return null;
2408
2421
  };
2409
2422
 
2423
+ // packages/cli/client/agentRunTypes.ts
2424
+ function resolveAuthToken(env) {
2425
+ return resolvePlatformAuthToken(env);
2426
+ }
2427
+ function resolveFileWriteGateEnabled(env) {
2428
+ const raw = (env.NOLO_CLI_WRITE_GATE ?? "").trim().toLowerCase();
2429
+ return raw !== "off" && raw !== "0" && raw !== "false";
2430
+ }
2431
+ function isMachineBoundLocalhostCustomProvider(agentConfig) {
2432
+ const machineId = agentConfig?.runtimeBinding && typeof agentConfig.runtimeBinding === "object" ? String(agentConfig.runtimeBinding.machineId ?? "").trim() : "";
2433
+ const providerUrl = asTrimmedString(agentConfig?.customProviderUrl);
2434
+ if (!machineId || !providerUrl) return false;
2435
+ return isLoopbackUrl(providerUrl);
2436
+ }
2437
+ function resolveBoundMachineId(agentConfig) {
2438
+ return agentConfig?.runtimeBinding && typeof agentConfig.runtimeBinding === "object" ? String(agentConfig.runtimeBinding.machineId ?? "").trim() : "";
2439
+ }
2440
+ var CLI_PROVIDER_NAMES = /* @__PURE__ */ new Set([
2441
+ "agy",
2442
+ "claude",
2443
+ "codex",
2444
+ "copilot",
2445
+ "gemini",
2446
+ "grok",
2447
+ "kimi",
2448
+ "opencode",
2449
+ "qoder"
2450
+ ]);
2451
+ function isCliProviderAgentConfig(agentConfig) {
2452
+ if (asTrimmedLowercaseString(agentConfig?.apiSource) === "cli") return true;
2453
+ const cliProvider = asTrimmedLowercaseString(agentConfig?.cliProvider);
2454
+ if (cliProvider && CLI_PROVIDER_NAMES.has(cliProvider)) return true;
2455
+ const provider = asTrimmedLowercaseString(agentConfig?.provider);
2456
+ if (provider === "cli") return true;
2457
+ return CLI_PROVIDER_NAMES.has(provider);
2458
+ }
2459
+ async function detectCurrentMachineId(env) {
2460
+ const fromEnv = (env.NOLO_CURRENT_MACHINE_ID || env.NOLO_MACHINE_ID || "").trim();
2461
+ if (fromEnv) return fromEnv;
2462
+ try {
2463
+ const { detectMachineInfo } = await import("./machineInfo-66ZFUMLE.js");
2464
+ const machine = await detectMachineInfo({ probeLaunchable: true });
2465
+ return asOptionalTrimmedString(machine?.machineId);
2466
+ } catch {
2467
+ return void 0;
2468
+ }
2469
+ }
2470
+
2410
2471
  // packages/cli/client/cliProviderHelpers.ts
2472
+ function buildDelegatedTaskContent(task, input) {
2473
+ if (input === void 0 || input === null) {
2474
+ return task;
2475
+ }
2476
+ if (typeof input === "string") {
2477
+ const trimmedInput = input.trim();
2478
+ if (!trimmedInput || trimmedInput === task.trim()) {
2479
+ return task;
2480
+ }
2481
+ return `${task}
2482
+
2483
+ --- INPUT (text) ---
2484
+ ${input}`;
2485
+ }
2486
+ let jsonStr;
2487
+ try {
2488
+ const serialized = JSON.stringify(input, null, 2);
2489
+ if (serialized === void 0) {
2490
+ return task;
2491
+ }
2492
+ jsonStr = serialized;
2493
+ } catch {
2494
+ jsonStr = "[Unserializable Input]";
2495
+ }
2496
+ return `${task}
2497
+
2498
+ --- INPUT (json) ---
2499
+ ${jsonStr}`;
2500
+ }
2501
+ function calculateDelegatedPayloadMetrics(task, input, delegatedContent) {
2502
+ const taskText = typeof task === "string" ? task : "";
2503
+ const taskChars = taskText.length;
2504
+ let inputChars = 0;
2505
+ let serializedInputForTokens = void 0;
2506
+ if (input !== void 0 && input !== null) {
2507
+ if (typeof input === "string") {
2508
+ inputChars = input.length;
2509
+ serializedInputForTokens = input;
2510
+ } else {
2511
+ try {
2512
+ const serialized = JSON.stringify(input, null, 2);
2513
+ if (serialized !== void 0) {
2514
+ inputChars = serialized.length;
2515
+ serializedInputForTokens = serialized;
2516
+ } else {
2517
+ inputChars = 0;
2518
+ }
2519
+ } catch {
2520
+ const fallback = "[Unserializable Input]";
2521
+ inputChars = fallback.length;
2522
+ serializedInputForTokens = fallback;
2523
+ }
2524
+ }
2525
+ }
2526
+ const finalContent = delegatedContent ?? buildDelegatedTaskContent(task, input);
2527
+ const totalChars = finalContent.length;
2528
+ const estimatedTaskTokens = estimateTokenCount(taskText);
2529
+ const estimatedTotalTokens = estimateTokenCount(finalContent);
2530
+ const estimatedInputTokens = serializedInputForTokens && inputChars > 0 ? estimateTokenCount(serializedInputForTokens) : 0;
2531
+ return {
2532
+ taskChars,
2533
+ inputChars,
2534
+ totalChars,
2535
+ estimatedTaskTokens,
2536
+ estimatedInputTokens,
2537
+ estimatedTotalTokens
2538
+ };
2539
+ }
2411
2540
  function isCliProviderAgent(agentConfig) {
2412
- return Boolean(
2413
- agentConfig.apiSource === "cli" || agentConfig.provider === "cli" || agentConfig.cliProvider
2414
- );
2541
+ const providerName = asTrimmedLowercaseString(agentConfig.cliProvider);
2542
+ if (providerName && CLI_PROVIDER_NAMES.has(providerName)) return true;
2543
+ if (agentConfig.apiSource === "cli") return true;
2544
+ if (asTrimmedLowercaseString(agentConfig.provider) === "cli") return true;
2545
+ return false;
2415
2546
  }
2416
2547
  function resolveCliProviderName(agentConfig) {
2417
- return (agentConfig.cliProvider || agentConfig.provider || "codex").trim() || "codex";
2548
+ const explicit = asTrimmedLowercaseString(agentConfig.cliProvider);
2549
+ if (explicit && CLI_PROVIDER_NAMES.has(explicit)) return explicit;
2550
+ const providerName = asTrimmedLowercaseString(agentConfig.provider);
2551
+ if (providerName && CLI_PROVIDER_NAMES.has(providerName)) return providerName;
2552
+ return "codex";
2418
2553
  }
2419
2554
  function stringifyRuntimeMessageContent(content) {
2420
2555
  if (typeof content === "string") return content;
@@ -2520,13 +2655,13 @@ var resolveCliProviderTransport = async (ctx) => {
2520
2655
  };
2521
2656
 
2522
2657
  // packages/agent-runtime/codexResponsesProvider.ts
2523
- import { randomUUID as randomUUID3 } from "node:crypto";
2658
+ import { randomUUID as randomUUID2 } from "node:crypto";
2524
2659
  var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
2525
- var CODEX_CLIENT_VERSION = "0.144.1";
2660
+ var CODEX_CLIENT_VERSION = "0.154.0";
2526
2661
  var CODEX_ORIGINATOR = "codex_cli_rs";
2527
2662
  var CODEX_OPENAI_BETA = "responses=experimental";
2528
2663
  var OPENAI_AUTH_CLAIM = "https://api.openai.com/auth";
2529
- var CODEX_INSTALLATION_ID = randomUUID3();
2664
+ var CODEX_INSTALLATION_ID = randomUUID2();
2530
2665
  function decodeCodexAccountId(accessToken) {
2531
2666
  const parts = accessToken.split(".");
2532
2667
  if (parts.length < 2) return void 0;
@@ -2542,10 +2677,10 @@ function decodeCodexAccountId(accessToken) {
2542
2677
  }
2543
2678
  }
2544
2679
  function createCodexRequestIdentity(installationId = CODEX_INSTALLATION_ID) {
2545
- const sessionId = randomUUID3();
2546
- const threadId = randomUUID3();
2547
- const windowId = randomUUID3();
2548
- const turnId = randomUUID3();
2680
+ const sessionId = randomUUID2();
2681
+ const threadId = randomUUID2();
2682
+ const windowId = randomUUID2();
2683
+ const turnId = randomUUID2();
2549
2684
  const turnMetadata = {
2550
2685
  installation_id: installationId,
2551
2686
  session_id: sessionId,
@@ -2612,31 +2747,6 @@ function collectInstructions(messages, agentPrompt) {
2612
2747
  }
2613
2748
  return systemTexts.join("\n\n");
2614
2749
  }
2615
- function collectStableInstructions(messages, fallbackPrompt) {
2616
- const systemTexts = [];
2617
- if (fallbackPrompt?.trim()) systemTexts.push(fallbackPrompt.trim());
2618
- for (const raw of messages) {
2619
- if (!raw || typeof raw !== "object") continue;
2620
- const message = raw;
2621
- const role = String(message.role ?? "");
2622
- if (role !== "system" && role !== "developer") continue;
2623
- if (typeof message.content === "string") {
2624
- const boundary = Number(message.stable_prefix_chars);
2625
- const text = Number.isFinite(boundary) && boundary > 0 ? message.content.slice(0, boundary) : message.content;
2626
- if (text.trim()) systemTexts.push(text.trim());
2627
- }
2628
- }
2629
- return systemTexts.join("\n\n");
2630
- }
2631
- function stablePromptCacheKey(parts) {
2632
- const value = JSON.stringify(parts);
2633
- let hash = 2166136261;
2634
- for (let index = 0; index < value.length; index += 1) {
2635
- hash ^= value.charCodeAt(index);
2636
- hash = Math.imul(hash, 16777619) >>> 0;
2637
- }
2638
- return `nolo-codex-${hash.toString(16).padStart(8, "0")}`;
2639
- }
2640
2750
  function convertMessagesToCodexInput(messages) {
2641
2751
  return convertMessagesToResponsesInput(messages).map((item) => {
2642
2752
  if (item.type !== "reasoning") return item;
@@ -2657,7 +2767,7 @@ function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
2657
2767
  });
2658
2768
  const input = convertMessagesToCodexInput(nonSystem);
2659
2769
  const instructions = collectInstructions(rawMessages, args.agentConfig.prompt);
2660
- const stableInstructions = collectStableInstructions(rawMessages, args.agentConfig.prompt);
2770
+ const stableInstructions = collectStablePromptPrefix(rawMessages, args.agentConfig.prompt);
2661
2771
  const model = asOptionalTrimmedString(args.openAiBody.model) ?? asOptionalTrimmedString(args.agentConfig.model) ?? "gpt-5.5";
2662
2772
  const tools = toResponsesTools(
2663
2773
  Array.isArray(args.openAiBody.tools) ? args.openAiBody.tools : void 0
@@ -2669,7 +2779,7 @@ function buildCodexRequestBody(args, identity = createCodexRequestIdentity()) {
2669
2779
  store: false,
2670
2780
  // Keep routing stable across turns and request UUIDs. Growing input/history
2671
2781
  // is intentionally excluded; only stable request-prefix material belongs.
2672
- prompt_cache_key: stablePromptCacheKey([model, stableInstructions, tools ?? []]),
2782
+ prompt_cache_key: stablePromptCacheKey([model, stableInstructions, tools ?? []], "nolo-codex"),
2673
2783
  client_metadata: identity.clientMetadata
2674
2784
  };
2675
2785
  if (instructions) body.instructions = instructions;
@@ -2690,7 +2800,7 @@ async function readSseEvents(response) {
2690
2800
  });
2691
2801
  }
2692
2802
  var defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
2693
- async function callCodexResponsesOnce(args, accountId) {
2803
+ async function callCodexResponsesOnce(args, accountId, timingTracker) {
2694
2804
  const fetchImpl = args.fetchImpl ?? fetch;
2695
2805
  const identity = createCodexRequestIdentity();
2696
2806
  const body = buildCodexRequestBody(args, identity);
@@ -2710,7 +2820,17 @@ async function callCodexResponsesOnce(args, accountId) {
2710
2820
  };
2711
2821
  }
2712
2822
  const events = await readSseEvents(response);
2713
- const { text, toolCalls, usage, failure } = aggregateResponsesStream(events);
2823
+ let firstAcceptedOutputAt;
2824
+ const { text, toolCalls, usage, failure } = aggregateResponsesStream(events, {
2825
+ onMeaningfulDelta: () => {
2826
+ firstAcceptedOutputAt ??= timingTracker.now();
2827
+ }
2828
+ });
2829
+ if (!failure && firstAcceptedOutputAt !== void 0) {
2830
+ observeMeaningfulProviderResponseAt(timingTracker, firstAcceptedOutputAt);
2831
+ }
2832
+ const timingFields = finalizeProviderCallTiming(timingTracker);
2833
+ const usageWithTiming = withProviderCallTimingFields(usage, timingFields);
2714
2834
  if (failure) {
2715
2835
  return {
2716
2836
  status: codexStreamFailureStatus(failure),
@@ -2738,7 +2858,7 @@ async function callCodexResponsesOnce(args, accountId) {
2738
2858
  finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop"
2739
2859
  }
2740
2860
  ],
2741
- ...usage ? { usage } : {}
2861
+ ...usageWithTiming ? { usage: usageWithTiming } : {}
2742
2862
  }
2743
2863
  };
2744
2864
  }
@@ -2757,12 +2877,13 @@ async function fetchCodexResponsesCompletion(args) {
2757
2877
  const sleep = args.sleep ?? defaultSleep;
2758
2878
  const requestedMaxAttempts = Number(args.maxAttempts);
2759
2879
  const maxAttempts = Number.isFinite(requestedMaxAttempts) ? Math.min(10, Math.max(1, Math.floor(requestedMaxAttempts))) : CODEX_STREAM_MAX_ATTEMPTS;
2760
- let result = await callCodexResponsesOnce(args, accountId);
2880
+ const timingTracker = createProviderCallTimingTracker(args.now);
2881
+ let result = await callCodexResponsesOnce(args, accountId, timingTracker);
2761
2882
  for (let attempt = 1; attempt < maxAttempts; attempt += 1) {
2762
2883
  if (!RETRYABLE_CODEX_STREAM_STATUSES.has(result.status)) break;
2763
2884
  if (args.signal?.aborted) break;
2764
2885
  await sleep(CODEX_STREAM_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
2765
- result = await callCodexResponsesOnce(args, accountId);
2886
+ result = await callCodexResponsesOnce(args, accountId, timingTracker);
2766
2887
  }
2767
2888
  return result;
2768
2889
  }
@@ -2817,7 +2938,8 @@ var resolveCodexOAuthTransport = async (ctx) => {
2817
2938
  });
2818
2939
  await recordLocalAvailability(result.status, result.body);
2819
2940
  if (result.status < 200 || result.status >= 300) {
2820
- const errMsg = result.body?.error && typeof result.body.error === "object" && typeof result.body.error.message === "string" ? result.body.error.message : JSON.stringify(result.body);
2941
+ const errorObj = result.body?.error;
2942
+ const errMsg = typeof errorObj?.message === "string" ? errorObj.message : JSON.stringify(result.body);
2821
2943
  throw new Error(
2822
2944
  `local Codex OAuth provider failed: HTTP ${result.status} ${errMsg}`
2823
2945
  );
@@ -2837,6 +2959,8 @@ var resolveCodexOAuthTransport = async (ctx) => {
2837
2959
  });
2838
2960
  return {
2839
2961
  content,
2962
+ model: agentConfig.model || "gpt-5.6-sol",
2963
+ provider: "openai",
2840
2964
  ...tool_calls ? { tool_calls } : {},
2841
2965
  // fetchCodexResponsesCompletion 已把 codex responses 流聚合完毕并归一化成
2842
2966
  // OpenAI chat.completions 形状:choices[0].finish_reason("stop"/"tool_calls")
@@ -2855,7 +2979,7 @@ var resolveCodexOAuthTransport = async (ctx) => {
2855
2979
  };
2856
2980
 
2857
2981
  // packages/agent-runtime/cursor/cursorProvider.ts
2858
- import { createHash, randomUUID as randomUUID4 } from "node:crypto";
2982
+ import { createHash, randomUUID as randomUUID3 } from "node:crypto";
2859
2983
  import http2 from "node:http2";
2860
2984
 
2861
2985
  // node_modules/@bufbuild/protobuf/dist/esm/is-message.js
@@ -7614,7 +7738,7 @@ function deterministicUuid(seed) {
7614
7738
  const hex = hash.slice(0, 32);
7615
7739
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-4${hex.slice(13, 16)}-8${hex.slice(17, 20)}-${hex.slice(20, 32)}`;
7616
7740
  }
7617
- function createCursorUserMessage(content, text, messageId = randomUUID4()) {
7741
+ function createCursorUserMessage(content, text, messageId = randomUUID3()) {
7618
7742
  const images = extractImages(content);
7619
7743
  return create(UserMessageSchema, {
7620
7744
  text,
@@ -7633,7 +7757,7 @@ function extractImages(content) {
7633
7757
  const match = url.match(/^data:([^;,]+);base64,(.+)$/s);
7634
7758
  if (!match) return null;
7635
7759
  return create(SelectedImageSchema, {
7636
- uuid: randomUUID4(),
7760
+ uuid: randomUUID3(),
7637
7761
  mimeType: match[1],
7638
7762
  dataOrBlobId: {
7639
7763
  case: "data",
@@ -7644,7 +7768,7 @@ function extractImages(content) {
7644
7768
  }
7645
7769
  function buildCursorRunRequestBytes(args) {
7646
7770
  const blobStore = args.blobStore ?? /* @__PURE__ */ new Map();
7647
- const conversationId = args.conversationId ?? randomUUID4();
7771
+ const conversationId = args.conversationId ?? randomUUID3();
7648
7772
  const systemPromptIds = buildCursorSystemPromptJsons(
7649
7773
  args.systemPrompt ? [args.systemPrompt] : void 0
7650
7774
  ).map(
@@ -7782,7 +7906,7 @@ function processCursorServerMessage(msg, state, onTextDelta, onReasoningDelta) {
7782
7906
  async function streamCursorChat(messages, options) {
7783
7907
  const baseUrl = options.baseUrl || CURSOR_API_URL;
7784
7908
  const clientVersion = options.clientVersion || CURSOR_CLIENT_VERSION;
7785
- const conversationId = options.conversationId ?? randomUUID4();
7909
+ const conversationId = options.conversationId ?? randomUUID3();
7786
7910
  const toolCalls = [];
7787
7911
  const state = createStreamState();
7788
7912
  const execCtx = {
@@ -7820,7 +7944,7 @@ async function streamCursorChat(messages, options) {
7820
7944
  "x-ghost-mode": "true",
7821
7945
  "x-cursor-client-version": clientVersion,
7822
7946
  "x-cursor-client-type": "cli",
7823
- "x-request-id": randomUUID4()
7947
+ "x-request-id": randomUUID3()
7824
7948
  };
7825
7949
  try {
7826
7950
  h2Client = http2.connect(baseUrl);
@@ -8375,7 +8499,7 @@ async function handleExecServerMessage(execMsg, h2Request, ctx) {
8375
8499
  switch (execCase) {
8376
8500
  case "readArgs": {
8377
8501
  const args = execMsg.message.value;
8378
- if (!args.toolCallId) args.toolCallId = randomUUID4();
8502
+ if (!args.toolCallId) args.toolCallId = randomUUID3();
8379
8503
  const path = args.path;
8380
8504
  const toolCallBlock = synthesizeCursorExecToolCall(ctx, args.toolCallId, "readFile", { path });
8381
8505
  let result;
@@ -8435,7 +8559,7 @@ async function handleExecServerMessage(execMsg, h2Request, ctx) {
8435
8559
  case "shellArgs":
8436
8560
  case "shellStreamArgs": {
8437
8561
  const args = execMsg.message.value;
8438
- if (!args.toolCallId) args.toolCallId = randomUUID4();
8562
+ if (!args.toolCallId) args.toolCallId = randomUUID3();
8439
8563
  const command = args.command;
8440
8564
  const workingDirectory = args.workingDirectory || process.cwd();
8441
8565
  const shellTimeout = args.timeout && args.timeout > 0 ? args.timeout : void 0;
@@ -8534,7 +8658,7 @@ async function handleExecServerMessage(execMsg, h2Request, ctx) {
8534
8658
  }
8535
8659
  case "grepArgs": {
8536
8660
  const args = execMsg.message.value;
8537
- if (!args.toolCallId) args.toolCallId = randomUUID4();
8661
+ if (!args.toolCallId) args.toolCallId = randomUUID3();
8538
8662
  const searchPath = args.glob ? `${args.path || "."}/${args.glob}` : args.path || ".";
8539
8663
  const pattern = args.pattern || "";
8540
8664
  const toolCallBlock = synthesizeCursorExecToolCall(ctx, args.toolCallId, "searchWorkspace", {
@@ -8602,7 +8726,7 @@ async function handleExecServerMessage(execMsg, h2Request, ctx) {
8602
8726
  }
8603
8727
  case "writeArgs": {
8604
8728
  const args = execMsg.message.value;
8605
- if (!args.toolCallId) args.toolCallId = randomUUID4();
8729
+ if (!args.toolCallId) args.toolCallId = randomUUID3();
8606
8730
  const path = args.path;
8607
8731
  const content = args.fileText ?? new TextDecoder().decode(args.fileBytes ?? new Uint8Array());
8608
8732
  const toolCallBlock = synthesizeCursorExecToolCall(ctx, args.toolCallId, "writeFile", { path, content });
@@ -8665,7 +8789,7 @@ async function handleExecServerMessage(execMsg, h2Request, ctx) {
8665
8789
  }
8666
8790
  case "deleteArgs": {
8667
8791
  const args = execMsg.message.value;
8668
- if (!args.toolCallId) args.toolCallId = randomUUID4();
8792
+ if (!args.toolCallId) args.toolCallId = randomUUID3();
8669
8793
  const path = args.path;
8670
8794
  const toolCallBlock = synthesizeCursorExecToolCall(ctx, args.toolCallId, "deleteFile", { path });
8671
8795
  let result;
@@ -8724,7 +8848,7 @@ async function handleExecServerMessage(execMsg, h2Request, ctx) {
8724
8848
  }
8725
8849
  case "lsArgs": {
8726
8850
  const args = execMsg.message.value;
8727
- if (!args.toolCallId) args.toolCallId = randomUUID4();
8851
+ if (!args.toolCallId) args.toolCallId = randomUUID3();
8728
8852
  const path = args.path;
8729
8853
  const toolCallBlock = synthesizeCursorExecToolCall(ctx, args.toolCallId, "listWorkspaceEntries", { path: path || "." });
8730
8854
  let result;
@@ -8785,7 +8909,7 @@ async function handleExecServerMessage(execMsg, h2Request, ctx) {
8785
8909
  for (const [key, value] of Object.entries(args.args ?? {})) {
8786
8910
  decodedArgs[key] = decodeMcpArgValue(value);
8787
8911
  }
8788
- if (!args.toolCallId) args.toolCallId = randomUUID4();
8912
+ if (!args.toolCallId) args.toolCallId = randomUUID3();
8789
8913
  const toolCallBlock = synthesizeCursorExecToolCall(ctx, args.toolCallId, toolName, decodedArgs);
8790
8914
  let result;
8791
8915
  if (ctx.executeTool) {
@@ -9225,6 +9349,8 @@ var resolveGeminiNativeToolTransport = async (ctx) => {
9225
9349
  content: text,
9226
9350
  model,
9227
9351
  tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
9352
+ finish_reason: toolCalls.length > 0 ? "tool_calls" : "stop",
9353
+ stream_complete: true,
9228
9354
  ...usage ? { usage } : {},
9229
9355
  trace: messages
9230
9356
  };
@@ -9286,6 +9412,7 @@ var resolvePlatformProxyTransport = async (ctx) => {
9286
9412
  return {
9287
9413
  model: providerConfig.model,
9288
9414
  complete: async (messages, options) => {
9415
+ const requestId = crypto.randomUUID();
9289
9416
  const usesResponsesApi = providerConfig.endpoint.includes("/responses");
9290
9417
  const stream = Boolean(options?.onTextDelta);
9291
9418
  const request = buildPlatformChatCompletionRequest({
@@ -9293,6 +9420,7 @@ var resolvePlatformProxyTransport = async (ctx) => {
9293
9420
  messages,
9294
9421
  tools,
9295
9422
  stream,
9423
+ requestId,
9296
9424
  ...options?.dialogId ? { dialogId: options.dialogId } : {}
9297
9425
  });
9298
9426
  logLocalRuntimeDiagnostic("provider.request.start", {
@@ -9305,93 +9433,122 @@ var resolvePlatformProxyTransport = async (ctx) => {
9305
9433
  toolCount: tools.length,
9306
9434
  requestedToolNames,
9307
9435
  openAiToolNames: summarizeOpenAiToolNames(tools),
9308
- stream
9436
+ stream,
9437
+ requestId
9309
9438
  });
9310
- let res = await fetchWithTransientRetry(
9311
- fetchImpl,
9312
- request.url,
9313
- {
9314
- ...request.init
9315
- },
9316
- {
9317
- sleep: deps.sleep,
9318
- loopbackRequest,
9319
- // A chat POST is not safe to replay after an ambiguous network or
9320
- // gateway failure: the server/provider may already have accepted
9321
- // it. The client only waits through the server's explicit pre-
9322
- // admission deployment drain signal.
9323
- retryableStatuses: /* @__PURE__ */ new Set([503]),
9324
- shouldRetryResponse: shouldRetryPlatformProxyResponse,
9325
- retryNetworkErrors: false,
9326
- onRetry: deps.activityReporter ? ({ attempt, maxAttempts, delayMs }) => {
9327
- deps.activityReporter(
9328
- `\u81EA\u52A8\u91CD\u8BD5 ${attempt}/${maxAttempts} \xB7 ${Math.ceil(delayMs / 1e3)}s`
9329
- );
9330
- } : void 0
9331
- }
9332
- );
9333
- if (!res.ok) {
9334
- const raw2 = await res.text().catch(() => "");
9335
- const data2 = parsePlatformChatCompletionData(raw2);
9336
- await recordLocalAvailability(res.status, data2);
9337
- const rawPreview = raw2.length > 200 ? `${raw2.slice(0, 200)}\u2026(${raw2.length}b)` : raw2;
9338
- const gatewayHeaders = [
9339
- "server",
9340
- "cf-ray",
9341
- "cf-cache-status",
9342
- "content-length"
9343
- ].map((h) => {
9344
- const v = res.headers.get(h);
9345
- return v ? `${h}=${v}` : null;
9346
- }).filter(Boolean).join(" ");
9347
- throw new Error(
9348
- `platform provider failed: HTTP ${res.status} ${JSON.stringify(data2)}` + (rawPreview ? ` raw="${rawPreview}"` : "") + (gatewayHeaders ? ` headers=[${gatewayHeaders}]` : "")
9439
+ try {
9440
+ let res = await fetchWithTransientRetry(
9441
+ fetchImpl,
9442
+ request.url,
9443
+ {
9444
+ ...request.init
9445
+ },
9446
+ {
9447
+ sleep: deps.sleep,
9448
+ loopbackRequest,
9449
+ // A chat POST is not safe to replay after an ambiguous network or
9450
+ // gateway failure: the server/provider may already have accepted
9451
+ // it. The client only waits through the server's explicit pre-
9452
+ // admission deployment drain signal.
9453
+ retryableStatuses: /* @__PURE__ */ new Set([503]),
9454
+ shouldRetryResponse: shouldRetryPlatformProxyResponse,
9455
+ retryNetworkErrors: false,
9456
+ onRetry: deps.activityReporter ? ({ attempt, maxAttempts, delayMs }) => {
9457
+ deps.activityReporter(
9458
+ `\u81EA\u52A8\u91CD\u8BD5 ${attempt}/${maxAttempts} \xB7 ${Math.ceil(delayMs / 1e3)}s`
9459
+ );
9460
+ } : void 0
9461
+ }
9349
9462
  );
9350
- }
9351
- await recordLocalAvailability(res.status);
9352
- const contentType = res.headers.get("content-type") ?? "";
9353
- const shouldStream = Boolean(stream && options?.onTextDelta) && contentType.includes("text/event-stream");
9354
- if (shouldStream && options?.onTextDelta) {
9355
- const streamed = await readPlatformChatSseCompletion({
9356
- response: res,
9357
- usesResponsesApi,
9358
- onTextDelta: options.onTextDelta,
9359
- onReasoningDelta: options.onReasoningDelta
9360
- });
9463
+ if (!res.ok) {
9464
+ const raw2 = await res.text().catch(() => "");
9465
+ const data2 = parsePlatformChatCompletionData(raw2);
9466
+ await recordLocalAvailability(res.status, data2);
9467
+ const rawPreview = raw2.length > 200 ? `${raw2.slice(0, 200)}\u2026(${raw2.length}b)` : raw2;
9468
+ const gatewayHeaders = [
9469
+ "server",
9470
+ "cf-ray",
9471
+ "cf-cache-status",
9472
+ "content-length"
9473
+ ].map((h) => {
9474
+ const v = res.headers.get(h);
9475
+ return v ? `${h}=${v}` : null;
9476
+ }).filter(Boolean).join(" ");
9477
+ throw new Error(
9478
+ `platform provider failed: HTTP ${res.status} ${JSON.stringify(data2)}` + (rawPreview ? ` raw="${rawPreview}"` : "") + (gatewayHeaders ? ` headers=[${gatewayHeaders}]` : "")
9479
+ );
9480
+ }
9481
+ await recordLocalAvailability(res.status);
9482
+ const contentType = res.headers.get("content-type") ?? "";
9483
+ const shouldStream = Boolean(stream && options?.onTextDelta) && contentType.includes("text/event-stream");
9484
+ if (shouldStream && options?.onTextDelta) {
9485
+ const streamed = await readPlatformChatSseCompletion({
9486
+ response: res,
9487
+ usesResponsesApi,
9488
+ onTextDelta: options.onTextDelta,
9489
+ onReasoningDelta: options.onReasoningDelta
9490
+ });
9491
+ if (streamed.streamTruncated) {
9492
+ logLocalRuntimeDiagnostic("provider.stream.truncated", {
9493
+ phase: "streaming",
9494
+ contentChars: streamed.content.length,
9495
+ toolCallCount: streamed.tool_calls?.length ?? 0,
9496
+ requestId,
9497
+ ...options?.dialogId ? { dialogId: options.dialogId } : {}
9498
+ });
9499
+ }
9500
+ logLocalRuntimeDiagnostic("provider.request.result", {
9501
+ agentKey: agentConfig.key,
9502
+ transport: "platform-proxy",
9503
+ ok: true,
9504
+ stream: true,
9505
+ contentChars: streamed.content.length,
9506
+ toolCallCount: streamed.tool_calls?.length ?? 0
9507
+ });
9508
+ return {
9509
+ content: streamed.content,
9510
+ model: providerConfig.model,
9511
+ provider: providerConfig.provider,
9512
+ ...streamed.tool_calls ? { tool_calls: streamed.tool_calls } : {},
9513
+ ...streamed.reasoning_content ? { reasoning_content: streamed.reasoning_content } : {},
9514
+ ...streamed.usage ? { usage: streamed.usage } : {},
9515
+ ...streamed.finish_reason ? { finish_reason: streamed.finish_reason } : {},
9516
+ ...streamed.stream_complete ? { stream_complete: streamed.stream_complete } : {},
9517
+ ...streamed.streamTruncated ? { stream_truncated: true } : {},
9518
+ trace: messages
9519
+ };
9520
+ }
9521
+ const raw = await res.text().catch(() => "");
9361
9522
  logLocalRuntimeDiagnostic("provider.request.result", {
9362
9523
  agentKey: agentConfig.key,
9363
9524
  transport: "platform-proxy",
9364
- ok: true,
9365
- stream: true,
9366
- contentChars: streamed.content.length,
9367
- toolCallCount: streamed.tool_calls?.length ?? 0
9525
+ status: res.status,
9526
+ ok: res.ok,
9527
+ responseBytes: raw.length
9368
9528
  });
9369
- return {
9370
- content: streamed.content,
9371
- model: providerConfig.model,
9372
- provider: providerConfig.provider,
9373
- ...streamed.tool_calls ? { tool_calls: streamed.tool_calls } : {},
9374
- ...streamed.reasoning_content ? { reasoning_content: streamed.reasoning_content } : {},
9375
- ...streamed.usage ? { usage: streamed.usage } : {},
9376
- ...streamed.finish_reason ? { finish_reason: streamed.finish_reason } : {},
9377
- ...streamed.stream_complete ? { stream_complete: streamed.stream_complete } : {},
9529
+ const data = parsePlatformChatCompletionData(raw);
9530
+ return parsePlatformChatCompletionResponse({
9531
+ providerConfig,
9532
+ data,
9378
9533
  trace: messages
9379
- };
9534
+ });
9535
+ } catch (error) {
9536
+ if (error instanceof PlatformStreamInterruptedError) {
9537
+ logLocalRuntimeDiagnostic("provider.stream.interrupted", {
9538
+ phase: error.phase,
9539
+ frameCount: error.frameCount,
9540
+ textChars: error.textChars,
9541
+ sawDone: error.sawDone,
9542
+ sawUsage: error.sawUsage,
9543
+ sawFinishReason: error.sawFinishReason,
9544
+ elapsedMs: error.elapsedMs,
9545
+ requestId,
9546
+ ...options?.dialogId ? { dialogId: options.dialogId } : {},
9547
+ cause: error.cause instanceof Error ? error.cause.message : typeof error.cause === "string" ? error.cause : error.message
9548
+ });
9549
+ }
9550
+ throw error;
9380
9551
  }
9381
- const raw = await res.text().catch(() => "");
9382
- logLocalRuntimeDiagnostic("provider.request.result", {
9383
- agentKey: agentConfig.key,
9384
- transport: "platform-proxy",
9385
- status: res.status,
9386
- ok: res.ok,
9387
- responseBytes: raw.length
9388
- });
9389
- const data = parsePlatformChatCompletionData(raw);
9390
- return parsePlatformChatCompletionResponse({
9391
- providerConfig,
9392
- data,
9393
- trace: messages
9394
- });
9395
9552
  }
9396
9553
  };
9397
9554
  }
@@ -9421,7 +9578,7 @@ async function resolveLocalProvider(ctx) {
9421
9578
  }
9422
9579
 
9423
9580
  // packages/cli/client/localRuntimeAdapter.ts
9424
- import { dirname as dirname2, extname, join as join2 } from "node:path";
9581
+ import { dirname as dirname2, extname, join as join3 } from "node:path";
9425
9582
  import { fileURLToPath } from "node:url";
9426
9583
 
9427
9584
  // packages/cli/client/providerStreamRetry.ts
@@ -9484,19 +9641,6 @@ function withProviderStreamRetry(provider, deps) {
9484
9641
  };
9485
9642
  }
9486
9643
 
9487
- // packages/cli/client/localRuntimeHelpers.ts
9488
- var REMOTE_DIALOG_SYNC_TIMEOUT_MS = 1e4;
9489
- var remoteDialogSyncTimeoutMsForTest;
9490
- function remoteDialogSyncTimeout() {
9491
- return remoteDialogSyncTimeoutMsForTest ?? REMOTE_DIALOG_SYNC_TIMEOUT_MS;
9492
- }
9493
- function resolveRuntimeServerUrl(env) {
9494
- return (env?.NOLO_SERVER_URL || env?.NOLO_SERVER || env?.BASE_URL || "").replace(/\/+$/, "");
9495
- }
9496
- function resolveRuntimeAuthToken(env) {
9497
- return resolvePlatformAuthToken(env ?? {});
9498
- }
9499
-
9500
9644
  // packages/cli/client/cliRemoteDialogSync.ts
9501
9645
  function prepareRemoteDialogEvidenceRecord(key, value) {
9502
9646
  const record = isRecord(value) ? { ...value } : {};
@@ -9505,9 +9649,6 @@ function prepareRemoteDialogEvidenceRecord(key, value) {
9505
9649
  }
9506
9650
  return record;
9507
9651
  }
9508
- function normalizeRemoteStringList(value) {
9509
- return [...new Set(asTrimmedNonEmptyStringArray(value))];
9510
- }
9511
9652
  function normalizeRemoteSubjectRef(value) {
9512
9653
  if (!isRecord(value)) return null;
9513
9654
  const kind = asOptionalTrimmedString(value.kind);
@@ -9550,6 +9691,11 @@ function clipLocalWakeEvidence(value, max = 1200) {
9550
9691
  const compact = clipCompactText(value, max);
9551
9692
  return compact || void 0;
9552
9693
  }
9694
+ function buildLocalWakeDisplayText(args) {
9695
+ const failed = args.terminalStatus !== "done";
9696
+ const duration = typeof args.durationMs === "number" && args.durationMs >= 0 ? ` \xB7 ${Math.floor(args.durationMs / 6e4)}m${Math.floor(args.durationMs / 1e3) % 60}s` : "";
9697
+ return `1 \u6761\u540E\u53F0 run \u5DF2\u5B8C\u6210 \xB7 ${failed ? "\u2717" : "\u2713"} ${args.label || "\u540E\u53F0 run"}${failed ? ` ${args.terminalStatus}` : ""}${duration}`;
9698
+ }
9553
9699
  function buildLocalParentWakeMessage(args) {
9554
9700
  return [
9555
9701
  "A child agent dialog you started has reached a terminal status.",
@@ -9599,7 +9745,14 @@ async function postRemoteRecord(args) {
9599
9745
  },
9600
9746
  // evidence 写是 customKey 幂等覆盖写(同 key 重写结果相同),
9601
9747
  // 因此 502 重试安全:即便前一次已被服务端处理,重写结果不变。
9602
- { retryableStatuses: /* @__PURE__ */ new Set([429, 502, 503]) }
9748
+ // 402(ledger append conflict)同样幂等可重试:token 记录同 key
9749
+ // 覆盖写 + 扣费幂等键(token:<key>)在 prepare 阶段短路 duplicate,
9750
+ // 重试不会双扣。服务端 chargeTokenUsageWithLedger 内部已带 conflict
9751
+ // 重试,走到 402 说明多重冲突,客户端再退避重试一轮兜底。
9752
+ // Effect v4 迁移锚点:白名单重试 ≈ Effect.retry({ while: res =>
9753
+ // retryableStatuses.has(res.status), schedule: Schedule.exponential }),
9754
+ // 退避/抖动由 Schedule 组合表达,测试用 TestClock 免真实 sleep。
9755
+ { retryableStatuses: /* @__PURE__ */ new Set([402, 429, 502, 503]) }
9603
9756
  );
9604
9757
  if (!response.ok) {
9605
9758
  const text = await response.text().catch(() => "");
@@ -9646,15 +9799,6 @@ async function maybeWakeParentDialogAfterLocalSync(args) {
9646
9799
  args.childDialogRecord.subjectRefs,
9647
9800
  [{ kind: "dialog", id: childDialogId, role: "completed-child-dialog" }]
9648
9801
  );
9649
- const allowedChildAgentKeys = normalizeRemoteStringList(
9650
- args.input.runtimeContext?.allowedChildAgentKeys
9651
- );
9652
- const allowedToolNames = normalizeRemoteStringList(
9653
- args.input.runtimeContext?.allowedToolNames
9654
- );
9655
- const blockedToolNames = normalizeRemoteStringList(
9656
- args.input.runtimeContext?.blockedToolNames
9657
- );
9658
9802
  const wakeResponse = await args.fetchImpl(`${args.serverUrl}/api/agent/run`, {
9659
9803
  method: "POST",
9660
9804
  headers: {
@@ -9676,10 +9820,13 @@ async function maybeWakeParentDialogAfterLocalSync(args) {
9676
9820
  host: "terminal",
9677
9821
  runtime: "bun",
9678
9822
  entrypoint: "agent-runtime:parent-child-terminal-wake",
9679
- subjectRefs,
9680
- ...allowedChildAgentKeys.length ? { allowedChildAgentKeys } : {},
9681
- ...allowedToolNames.length ? { allowedToolNames } : {},
9682
- ...blockedToolNames.length ? { blockedToolNames } : {}
9823
+ wakeChildDialogKey: args.childDialogKey,
9824
+ wakeTerminalStatus: "done",
9825
+ wakeDisplayText: buildLocalWakeDisplayText({
9826
+ label: args.childDialogRecord.taskLabel ?? args.childDialogRecord.title,
9827
+ terminalStatus: "done"
9828
+ }),
9829
+ subjectRefs
9683
9830
  }
9684
9831
  })
9685
9832
  });
@@ -9812,61 +9959,6 @@ async function readDialogMessages(args) {
9812
9959
  return messages;
9813
9960
  }
9814
9961
 
9815
- // packages/cli/client/cliAgentConfigHelpers.ts
9816
- var BUILTIN_NOLO_AGENT_KEY = NOLO_DEFAULT_AGENT_KEY;
9817
- var BUILTIN_NOLO_AGENT_ID = NOLO_DEFAULT_AGENT_ID;
9818
- function resolveLocalUserId(env) {
9819
- const explicitUserId = env.NOLO_LOCAL_USER_ID || env.NOLO_USER_ID;
9820
- if (explicitUserId) return explicitUserId;
9821
- const tokenUserId = parseUserIdFromAuthToken(resolveRuntimeAuthToken(env));
9822
- return tokenUserId || "local";
9823
- }
9824
- function isBuiltinNoloAgentRef(ref) {
9825
- if (typeof ref !== "string") return false;
9826
- const normalized = ref.trim();
9827
- return normalized === BUILTIN_NOLO_AGENT_KEY || normalized === BUILTIN_NOLO_AGENT_ID || normalized.endsWith(`-${BUILTIN_NOLO_AGENT_ID}`);
9828
- }
9829
- function isBuiltinNoloAgentConfig(agentConfig) {
9830
- const key = agentConfig?.key || agentConfig?.rawRecord?.dbKey || agentConfig?.rawRecord?.agentKey;
9831
- const id = agentConfig?.rawRecord?.id;
9832
- return isBuiltinNoloAgentRef(key) || isBuiltinNoloAgentRef(id);
9833
- }
9834
- function withResolvedRuntimeToolSurface(agentConfig, env) {
9835
- if (!agentConfig) return agentConfig;
9836
- const currentUserId = resolveLocalUserId(env);
9837
- const rawRecord = agentConfig.rawRecord ?? {};
9838
- const ownerId = asOptionalTrimmedString(rawRecord.userId) ?? null;
9839
- const agentKey = rawRecord.dbKey ?? agentConfig.key;
9840
- const toolSurface = resolveRuntimeToolSurfaceForAgent({
9841
- explicitToolNames: agentConfig.toolNames,
9842
- currentUserId,
9843
- agentOwnerId: ownerId,
9844
- agentKey,
9845
- isPublic: !isBuiltinNoloAgentConfig(agentConfig) && rawRecord.isPublic === true,
9846
- sharingLevel: typeof rawRecord.sharingLevel === "string" ? rawRecord.sharingLevel : null,
9847
- trustedPrivateInvocation: isBuiltinNoloAgentConfig(agentConfig) || isSystemBuiltinTrustedAgentKey(agentKey),
9848
- runtimeHost: "cli"
9849
- });
9850
- return {
9851
- ...agentConfig,
9852
- toolNames: toolSurface.finalToolNames,
9853
- toolSurface,
9854
- prompt: agentConfig.prompt
9855
- };
9856
- }
9857
- function extractLastUserText(messages) {
9858
- const lastUser = [...messages].reverse().find((m) => m.role === "user");
9859
- if (!lastUser) return "";
9860
- if (typeof lastUser.content === "string") return lastUser.content;
9861
- if (Array.isArray(lastUser.content)) {
9862
- return lastUser.content.filter((part) => part?.type === "text").map((part) => part.text ?? "").join(" ");
9863
- }
9864
- return "";
9865
- }
9866
- function localTurnHasSubjectRefs(input) {
9867
- return Array.isArray(input.runtimeContext?.subjectRefs) && input.runtimeContext.subjectRefs.length > 0;
9868
- }
9869
-
9870
9962
  // packages/core/fetchWebpageShaping.ts
9871
9963
  var FETCH_WEBPAGE_PREVIEW_LENGTH = 1200;
9872
9964
  var FETCH_WEBPAGE_MAX_CONTENT_LENGTH = 12 * 1024;
@@ -10088,7 +10180,8 @@ function buildServerPlatformToolExecutors(args) {
10088
10180
  content,
10089
10181
  metadata: {
10090
10182
  serverPlatformTool: true,
10091
- webTool: toolName
10183
+ webTool: toolName,
10184
+ query: parsed.query
10092
10185
  }
10093
10186
  };
10094
10187
  }
@@ -10110,7 +10203,7 @@ function buildServerPlatformToolExecutors(args) {
10110
10203
  });
10111
10204
  return {
10112
10205
  content: raw,
10113
- metadata: { serverPlatformTool: true, memoryRead: true }
10206
+ metadata: { serverPlatformTool: true, memoryRead: true, query }
10114
10207
  };
10115
10208
  };
10116
10209
  const rememberMemory = async (call) => {
@@ -10130,13 +10223,16 @@ function buildServerPlatformToolExecutors(args) {
10130
10223
  kind: parsed.kind ?? "episodic",
10131
10224
  source: "agent-inferred"
10132
10225
  };
10226
+ if (typeof parsed.recurrenceEvidence === "string" && parsed.recurrenceEvidence.trim()) {
10227
+ body.recurrenceEvidence = parsed.recurrenceEvidence.trim();
10228
+ }
10133
10229
  if (args.agentKey) body.agentKey = args.agentKey;
10134
10230
  const raw = await postServer("/api/memory/remember", body, {
10135
10231
  retryTransient: true
10136
10232
  });
10137
10233
  return {
10138
10234
  content: raw,
10139
- metadata: { serverPlatformTool: true, memoryWrite: true }
10235
+ metadata: { serverPlatformTool: true, memoryWrite: true, content }
10140
10236
  };
10141
10237
  };
10142
10238
  const deleteMemory = async (call) => {
@@ -10186,6 +10282,61 @@ function buildServerPlatformToolExecutors(args) {
10186
10282
  };
10187
10283
  }
10188
10284
 
10285
+ // packages/cli/client/cliAgentRunToolExecutors.ts
10286
+ import * as nodeFs2 from "node:fs";
10287
+
10288
+ // packages/agent-runtime/waitForRunTerminal.ts
10289
+ var readEffect = (read) => Effect_exports.tryPromise({ try: () => Promise.resolve(read()), catch: (error) => error });
10290
+ function waitForRunTerminal(args) {
10291
+ let lastState;
10292
+ let token = null;
10293
+ let committed = false;
10294
+ const abort = args.abortSignal;
10295
+ let removeAbortListener;
10296
+ const abortEffect = abort ? Effect_exports.callback((resume) => {
10297
+ const listener = () => resume(Effect_exports.succeed("aborted"));
10298
+ if (abort.aborted) {
10299
+ listener();
10300
+ return;
10301
+ }
10302
+ removeAbortListener = () => {
10303
+ abort.removeEventListener("abort", listener);
10304
+ removeAbortListener = void 0;
10305
+ };
10306
+ abort.addEventListener("abort", listener, { once: true });
10307
+ return Effect_exports.sync(() => removeAbortListener?.());
10308
+ }).pipe(Effect_exports.ensuring(Effect_exports.sync(() => removeAbortListener?.()))) : void 0;
10309
+ const sleep = (ms) => {
10310
+ const effect = args.sleep ? Effect_exports.tryPromise({ try: () => Promise.resolve(args.sleep(ms)), catch: (error) => error }) : Effect_exports.sleep(Duration_exports.millis(ms));
10311
+ return abortEffect ? Effect_exports.raceFirst(effect, abortEffect) : effect;
10312
+ };
10313
+ const loop = Effect_exports.gen(function* () {
10314
+ token = args.claim?.acquire() ?? null;
10315
+ while (true) {
10316
+ const state = yield* readEffect(args.read);
10317
+ lastState = state;
10318
+ if (args.isTerminal(state)) {
10319
+ if (args.claim) {
10320
+ args.claim.commit(token);
10321
+ committed = true;
10322
+ }
10323
+ return { kind: "terminal", state };
10324
+ }
10325
+ const slept = yield* sleep(args.pollIntervalMs);
10326
+ if (slept === "aborted") return { kind: "aborted" };
10327
+ }
10328
+ }).pipe(
10329
+ Effect_exports.timeoutOption(Duration_exports.millis(args.timeoutMs)),
10330
+ Effect_exports.map((result) => Option_exports.isNone(result) ? { kind: "timeout", waitedMs: args.timeoutMs, lastState } : result.value),
10331
+ Effect_exports.catch((error) => Effect_exports.succeed({ kind: "failed", error })),
10332
+ Effect_exports.ensuring(Effect_exports.sync(() => {
10333
+ if (args.claim && !committed) args.claim.release(token);
10334
+ }))
10335
+ );
10336
+ const run = args.runtime ? args.runtime.runPromise(loop) : Effect_exports.runPromise(loop);
10337
+ return run;
10338
+ }
10339
+
10189
10340
  // packages/cli/client/cliAgentRunToolExecutors.ts
10190
10341
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
10191
10342
 
@@ -10235,6 +10386,7 @@ function buildSnapshot(parsed, event) {
10235
10386
  ...typeof parsed.toolCallCount === "number" && Number.isFinite(parsed.toolCallCount) ? { toolCallCount: parsed.toolCallCount } : {},
10236
10387
  ...lastToolNames ? { lastToolNames } : {},
10237
10388
  ...lastAssistantText ? { lastAssistantText } : {},
10389
+ ...typeof parsed.credits === "number" && Number.isFinite(parsed.credits) ? { credits: parsed.credits } : {},
10238
10390
  ...errorMessage ? { errorMessage } : {},
10239
10391
  ...startedAt !== void 0 ? { startedAt } : {},
10240
10392
  ...finishedAt !== void 0 ? { finishedAt } : {},
@@ -10273,6 +10425,24 @@ function parseAgentRunEvent(event) {
10273
10425
  if (!snapshot.runId) return null;
10274
10426
  return { kind: "status", snapshot };
10275
10427
  }
10428
+ function isFailedToolEvent(event) {
10429
+ if (event.type === "tool-error") return true;
10430
+ if (event.metadata?.actionGate) return false;
10431
+ const exitCode = event.metadata?.exitCode;
10432
+ if (typeof exitCode === "number" && exitCode !== 0) return true;
10433
+ if (event.metadata?.failed || event.metadata?.timedOut) return true;
10434
+ return false;
10435
+ }
10436
+ var LIVE_RUN_STATUSES = /* @__PURE__ */ new Set(["running", "pending"]);
10437
+ function isLiveAgentRunObservation(event, parsed) {
10438
+ if (event.type !== "tool-result") return false;
10439
+ if (event.toolName !== "controlAgentRun") return false;
10440
+ if (isFailedToolEvent(event)) return false;
10441
+ const resolved = parsed !== void 0 ? parsed : parseAgentRunEvent(event);
10442
+ if (!resolved || resolved.kind !== "status") return false;
10443
+ if (!LIVE_RUN_STATUSES.has(resolved.snapshot.status)) return false;
10444
+ return true;
10445
+ }
10276
10446
 
10277
10447
  // packages/ai/tools/agent/batchAggregation.ts
10278
10448
  var DEFAULT_BATCH_TIMEOUT_MS = 30 * 60 * 1e3;
@@ -10413,18 +10583,18 @@ function deriveAgentRunTodoStatus(input) {
10413
10583
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
10414
10584
  import { homedir as nodeHomedir } from "node:os";
10415
10585
  import { dirname, join } from "node:path";
10416
- var nodeFs2 = {
10586
+ var nodeFs = {
10417
10587
  mkdirSync,
10418
10588
  writeFileSync,
10419
10589
  readFileSync,
10420
10590
  existsSync
10421
10591
  };
10422
- function resolveNoloHome(env, homedir) {
10592
+ function resolveNoloHome(env, homedir2) {
10423
10593
  const custom = env?.NOLO_HOME;
10424
10594
  if (custom && custom.trim()) return custom.trim();
10425
10595
  const ambient = process.env.NOLO_HOME?.trim();
10426
10596
  if (ambient) return ambient;
10427
- return join(homedir(), ".nolo");
10597
+ return join(homedir2(), ".nolo");
10428
10598
  }
10429
10599
  function ensureDir(dir, fs) {
10430
10600
  fs.mkdirSync(dir, { recursive: true });
@@ -10443,9 +10613,9 @@ function writeJson(path, data, fs) {
10443
10613
  }
10444
10614
  function createFileSystemTodoStore(opts = {}) {
10445
10615
  const env = opts.env ?? process.env;
10446
- const homedir = opts.homedir ?? nodeHomedir;
10447
- const fs = opts.fs ?? nodeFs2;
10448
- const noloHome = resolveNoloHome(env, homedir);
10616
+ const homedir2 = opts.homedir ?? nodeHomedir;
10617
+ const fs = opts.fs ?? nodeFs;
10618
+ const noloHome = resolveNoloHome(env, homedir2);
10449
10619
  const filePath = opts.filePath ?? join(noloHome, "agent_run_todos.json");
10450
10620
  const oldFilePath = join(noloHome, "todos.json");
10451
10621
  const loadMap = () => {
@@ -10564,9 +10734,6 @@ function buildRunStatusPayload(reconciled, deps, opts = {}) {
10564
10734
  const logLines = opts.logTail ? opts.logTail.split("\n") : void 0;
10565
10735
  const name = resolveRunLabel(reconciled);
10566
10736
  const labels = agentRunCardLabels();
10567
- const fs = resolveFs(deps);
10568
- const reportPath = resolveRunReportPath(reconciled.runId, deps.env, deps.homedir);
10569
- const reportExists = Boolean(fs.existsSync?.(reportPath));
10570
10737
  return {
10571
10738
  content: JSON.stringify({
10572
10739
  runId: reconciled.runId,
@@ -10586,7 +10753,6 @@ function buildRunStatusPayload(reconciled, deps, opts = {}) {
10586
10753
  ephemeral: true,
10587
10754
  dialogNote: "\u6B64 run \u672A\u6301\u4E45\u5316 dialog\uFF0C\u7ED3\u679C\u89C1 run \u8F93\u51FA"
10588
10755
  } : reconciled.dialogId ? { dialogId: reconciled.dialogId } : {},
10589
- ...reportExists ? { reportPath } : {},
10590
10756
  // Progress is what makes tailLines:0 an actual answer to "is it
10591
10757
  // stuck?". Without it a poll returns `running` and a pid, so the only
10592
10758
  // way to tell a working run from a wedged one was to pull 30 lines of
@@ -10598,7 +10764,6 @@ function buildRunStatusPayload(reconciled, deps, opts = {}) {
10598
10764
  ...logLines ? { logLines } : {}
10599
10765
  }),
10600
10766
  metadata: {
10601
- ...reportExists ? { reportPath } : {},
10602
10767
  displayData: formatStatusRunCard(name, reconciled.status, {
10603
10768
  runId: reconciled.runId,
10604
10769
  timing: {
@@ -10619,10 +10784,8 @@ function createCliStartAgentRunExecutor(deps = {}) {
10619
10784
  if (!agentKey) throw new Error("startAgentRun: \u7F3A\u5C11 agentKey \u53C2\u6570\u3002");
10620
10785
  if (!task) throw new Error("startAgentRun: \u7F3A\u5C11\u6709\u6548\u7684 task \u6587\u672C\u63CF\u8FF0\u3002");
10621
10786
  const nowMs = resolveNowMs(deps);
10622
- const message = typeof args.input === "undefined" ? task : `${task}
10623
-
10624
- --- \u9644\u52A0\u8F93\u5165 ---
10625
- ${JSON.stringify(args.input)}`;
10787
+ const message = buildDelegatedTaskContent(task, args.input);
10788
+ const payloadMetrics = calculateDelegatedPayloadMetrics(task, args.input, message);
10626
10789
  const rawArgs = [
10627
10790
  "--agent",
10628
10791
  agentKey,
@@ -10689,14 +10852,16 @@ ${JSON.stringify(args.input)}`;
10689
10852
  // even when the caller didn't supply one, a fresh id was generated.
10690
10853
  batchId: resolvedBatchId,
10691
10854
  ...agentName ? { agentName } : {},
10692
- ...taskPreview ? { taskPreview } : {}
10855
+ ...taskPreview ? { taskPreview } : {},
10856
+ payloadMetrics
10693
10857
  }),
10694
10858
  metadata: {
10695
10859
  displayData: formatStartRunCard(displayName, "running", {
10696
10860
  task: taskPreview,
10697
10861
  runId,
10698
10862
  labels
10699
- })
10863
+ }),
10864
+ payloadMetrics
10700
10865
  }
10701
10866
  };
10702
10867
  };
@@ -10877,47 +11042,47 @@ function createCliControlAgentRunExecutor(deps = {}) {
10877
11042
  metadata: { displayData: formatNotFoundRunCard(labels2) }
10878
11043
  };
10879
11044
  }
10880
- let reconciled = checkStaleRun(record2.runId, deps) ?? record2;
10881
- if (!isAgentRunTerminalStatus(reconciled.status)) {
10882
- if (!reconciled.queuePath) {
11045
+ let reconciled2 = checkStaleRun(record2.runId, deps) ?? record2;
11046
+ if (!isAgentRunTerminalStatus(reconciled2.status)) {
11047
+ if (!reconciled2.queuePath) {
10883
11048
  throw new Error("\u8BE5 run \u542F\u52A8\u65F6\u4E0D\u652F\u6301\u8FD0\u884C\u4E2D\u5165\u961F\uFF08\u65E0\u961F\u5217\u901A\u9053\uFF09\uFF0C\u8BF7\u7B49\u7EC8\u6001\u540E\u518D append");
10884
11049
  }
10885
- const queuePath = reconciled.queuePath;
11050
+ const queuePath = reconciled2.queuePath;
10886
11051
  const { queuedCount, entryId } = await appendRunQueue(queuePath, userInput, deps);
10887
11052
  const displayName = resolveRunLabel({
10888
- agentName: reconciled.agentName,
10889
- agentKey: reconciled.agentKey,
10890
- runId: reconciled.runId
11053
+ agentName: reconciled2.agentName,
11054
+ agentKey: reconciled2.agentKey,
11055
+ runId: reconciled2.runId
10891
11056
  });
10892
11057
  const labels2 = agentRunCardLabels();
10893
11058
  const taskPreview = userInput.replace(/\s+/g, " ").trim().slice(0, TASK_PREVIEW_MAX);
10894
- const afterCheck = checkStaleRun(reconciled.runId, deps) ?? reconciled;
11059
+ const afterCheck = checkStaleRun(reconciled2.runId, deps) ?? reconciled2;
10895
11060
  if (isAgentRunTerminalStatus(afterCheck.status)) {
10896
11061
  const remainingEntries = await popAllQueueEntries(queuePath, deps);
10897
11062
  const ourEntryFound = remainingEntries.some((e) => e.id === entryId);
10898
11063
  if (!ourEntryFound) {
10899
11064
  if (remainingEntries.length > 0) {
10900
11065
  await withQueueLock(queuePath, deps, () => {
10901
- const fs = deps.fs ?? nodeFs;
11066
+ const fs = deps.fs ?? nodeFs2;
10902
11067
  const existing = fs.existsSync(queuePath) ? fs.readFileSync(queuePath, "utf8") : "";
10903
11068
  fs.writeFileSync(queuePath, serializeQueueEntries(remainingEntries) + existing, "utf8");
10904
11069
  });
10905
11070
  }
10906
11071
  return {
10907
11072
  content: JSON.stringify({
10908
- runId: reconciled.runId,
11073
+ runId: reconciled2.runId,
10909
11074
  // ephemeral 不外泄合成 dialogId;非 ephemeral 保持原 dialogId 透出。
10910
- ...reconciled.ephemeral ? { ephemeral: true } : afterCheck.dialogId || reconciled.dialogId ? { dialogId: afterCheck.dialogId ?? reconciled.dialogId } : {},
11075
+ ...reconciled2.ephemeral ? { ephemeral: true } : afterCheck.dialogId || reconciled2.dialogId ? { dialogId: afterCheck.dialogId ?? reconciled2.dialogId } : {},
10911
11076
  mode: "enqueue",
10912
11077
  consumed: true,
10913
11078
  status: afterCheck.status,
10914
- ...reconciled.agentName ? { agentName: reconciled.agentName } : {},
11079
+ ...reconciled2.agentName ? { agentName: reconciled2.agentName } : {},
10915
11080
  ...taskPreview ? { taskPreview } : {}
10916
11081
  }),
10917
11082
  metadata: {
10918
11083
  displayData: formatStartRunCard(displayName, afterCheck.status, {
10919
11084
  task: `[consumed] ${taskPreview}`,
10920
- runId: reconciled.runId,
11085
+ runId: reconciled2.runId,
10921
11086
  labels: labels2
10922
11087
  })
10923
11088
  }
@@ -10928,25 +11093,25 @@ function createCliControlAgentRunExecutor(deps = {}) {
10928
11093
  }
10929
11094
  return {
10930
11095
  content: JSON.stringify({
10931
- runId: reconciled.runId,
11096
+ runId: reconciled2.runId,
10932
11097
  // ephemeral 不外泄合成 dialogId(enqueue 场景同样收敛)。
10933
- ...reconciled.ephemeral ? { ephemeral: true } : reconciled.dialogId ? { dialogId: reconciled.dialogId } : {},
11098
+ ...reconciled2.ephemeral ? { ephemeral: true } : reconciled2.dialogId ? { dialogId: reconciled2.dialogId } : {},
10934
11099
  mode: "enqueue",
10935
11100
  queued: queuedCount,
10936
11101
  status: "running",
10937
- ...reconciled.agentName ? { agentName: reconciled.agentName } : {},
11102
+ ...reconciled2.agentName ? { agentName: reconciled2.agentName } : {},
10938
11103
  ...taskPreview ? { taskPreview } : {}
10939
11104
  }),
10940
11105
  metadata: {
10941
11106
  displayData: formatStartRunCard(displayName, "running", {
10942
11107
  task: `[enqueued ${queuedCount}] ${taskPreview}`,
10943
- runId: reconciled.runId,
11108
+ runId: reconciled2.runId,
10944
11109
  labels: labels2
10945
11110
  })
10946
11111
  }
10947
11112
  };
10948
11113
  }
10949
- return await spawnContinuationRun(reconciled, userInput, deps);
11114
+ return await spawnContinuationRun(reconciled2, userInput, deps);
10950
11115
  }
10951
11116
  if (action !== "status" && action !== "stop" && action !== "wait") {
10952
11117
  throw new Error(`controlAgentRun: \u672A\u77E5 action "${action}"\u3002`);
@@ -10961,82 +11126,65 @@ function createCliControlAgentRunExecutor(deps = {}) {
10961
11126
  };
10962
11127
  }
10963
11128
  if (action === "status") {
10964
- const reconciled = checkStaleRun(record.runId, deps) ?? record;
11129
+ const reconciled2 = checkStaleRun(record.runId, deps) ?? record;
10965
11130
  const logTail = tailLines > 0 ? tailFile(record.logPath, tailLines, resolveFs(deps)) : void 0;
10966
- return buildRunStatusPayload(reconciled, deps, { logTail });
11131
+ return buildRunStatusPayload(reconciled2, deps, { logTail });
10967
11132
  }
10968
11133
  if (action === "wait") {
10969
11134
  const timeoutMs = typeof args.timeoutMs === "number" && args.timeoutMs > 0 ? args.timeoutMs : DEFAULT_WAIT_TIMEOUT_MS;
10970
- const claimToken = claimRunRecord(record.runId, {
10971
- ...deps,
10972
- ttlMs: timeoutMs + ACK_LEASE_GRACE_MS
10973
- });
10974
- let claimConsumed = false;
10975
- try {
10976
- const startMs = resolveNowMs(deps);
10977
- const deadline = startMs + timeoutMs;
10978
- const baseSleep = deps.sleep ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
10979
- const sleep = abortSignal ? (ms) => new Promise((resolve, reject) => {
10980
- const done = () => {
10981
- abortSignal.removeEventListener("abort", done);
10982
- resolve();
10983
- };
10984
- abortSignal.addEventListener("abort", done, { once: true });
10985
- Promise.resolve(baseSleep(ms)).then(done).catch((err) => {
10986
- abortSignal.removeEventListener("abort", done);
10987
- reject(err);
10988
- });
10989
- }) : baseSleep;
10990
- let reconciled = record;
10991
- for (; ; ) {
10992
- reconciled = checkStaleRun(record.runId, deps) ?? record;
10993
- if (isAgentRunTerminalStatus(reconciled.status)) break;
10994
- if (abortSignal?.aborted) {
10995
- throw new Error("controlAgentRun(wait) \u5DF2\u88AB\u4E2D\u6B62\u3002");
10996
- }
10997
- const nowMs = resolveNowMs(deps);
10998
- const waitedMs = nowMs - startMs;
10999
- if (nowMs >= deadline) {
11000
- return {
11001
- content: JSON.stringify({
11002
- runId: reconciled.runId,
11003
- found: true,
11004
- status: "timeout",
11005
- runStatus: reconciled.status,
11006
- pid: reconciled.pid ?? null,
11007
- agentKey: reconciled.agentKey,
11008
- ...reconciled.agentName ? { agentName: reconciled.agentName } : {},
11009
- startedAt: reconciled.startedAt,
11010
- waitedMs,
11011
- timeoutMs,
11012
- ...buildProgressField(reconciled, nowMs)
11013
- }),
11014
- metadata: {
11015
- displayData: `\u23F3 wait \u8D85\u65F6\uFF08${Math.round(waitedMs / 1e3)}s\uFF09\uFF0Crun \u4ECD\u5728\u8FD0\u884C\uFF1A\u53EF\u7A0D\u540E\u518D wait\uFF0C\u6216\u6539\u7528 status/stop`
11016
- }
11017
- };
11135
+ let claimToken = null;
11136
+ const result = await waitForRunTerminal({
11137
+ read: () => checkStaleRun(record.runId, deps) ?? record,
11138
+ isTerminal: (state) => isAgentRunTerminalStatus(state.status),
11139
+ pollIntervalMs: WAIT_POLL_INTERVAL_MS,
11140
+ timeoutMs,
11141
+ abortSignal,
11142
+ sleep: deps.sleep,
11143
+ claim: {
11144
+ acquire: () => {
11145
+ claimToken = claimRunRecord(record.runId, { ...deps, ttlMs: timeoutMs + ACK_LEASE_GRACE_MS });
11146
+ return claimToken;
11147
+ },
11148
+ commit: (token) => {
11149
+ if (token) commitRunRecordClaim(record.runId, token, deps);
11150
+ else ackRunRecord(record.runId, deps);
11151
+ },
11152
+ release: (token) => {
11153
+ if (token) releaseRunRecordAck(record.runId, token, deps);
11018
11154
  }
11019
- await sleep(WAIT_POLL_INTERVAL_MS);
11020
- }
11021
- const payload = buildRunStatusPayload(reconciled, deps);
11022
- if (claimToken) commitRunRecordClaim(record.runId, claimToken, deps);
11023
- else ackRunRecord(reconciled.runId, deps);
11024
- claimConsumed = true;
11025
- return payload;
11026
- } finally {
11027
- if (!claimConsumed && claimToken) {
11028
- releaseRunRecordAck(record.runId, claimToken, deps);
11029
11155
  }
11156
+ });
11157
+ if (result.kind === "aborted") throw new Error("controlAgentRun(wait) \u5DF2\u88AB\u4E2D\u6B62\u3002");
11158
+ if (result.kind === "failed") throw result.error;
11159
+ if (result.kind === "timeout") {
11160
+ const reconciled2 = result.lastState ?? record;
11161
+ const nowMs = resolveNowMs(deps);
11162
+ return { content: JSON.stringify({ runId: reconciled2.runId, found: true, status: "timeout", runStatus: reconciled2.status, pid: reconciled2.pid ?? null, agentKey: reconciled2.agentKey, ...reconciled2.agentName ? { agentName: reconciled2.agentName } : {}, startedAt: reconciled2.startedAt, waitedMs: result.waitedMs, timeoutMs, ...buildProgressField(reconciled2, nowMs) }), metadata: { displayData: `\u23F3 wait \u8D85\u65F6\uFF08${Math.round(result.waitedMs / 1e3)}s\uFF09\uFF0Crun \u4ECD\u5728\u8FD0\u884C\uFF1A\u53EF\u7A0D\u540E\u518D wait\uFF0C\u6216\u6539\u7528 status/stop` } };
11030
11163
  }
11164
+ return buildRunStatusPayload(result.state, deps);
11165
+ }
11166
+ const reconciled = checkStaleRun(record.runId, deps) ?? record;
11167
+ if (isAgentRunTerminalStatus(reconciled.status)) {
11168
+ const labels2 = agentRunCardLabels();
11169
+ return {
11170
+ content: JSON.stringify({
11171
+ runId: reconciled.runId,
11172
+ found: true,
11173
+ status: reconciled.status
11174
+ }),
11175
+ metadata: {
11176
+ displayData: formatStopRunCard(reconciled.status, labels2)
11177
+ }
11178
+ };
11031
11179
  }
11032
- if (typeof record.pid === "number") {
11033
- const confirmed = await terminateRunProcess(record, "SIGTERM", deps);
11180
+ if (typeof reconciled.pid === "number") {
11181
+ const confirmed = await (deps.terminateRunProcess ?? terminateRunProcess)(reconciled, "SIGTERM", deps);
11034
11182
  if (!confirmed) {
11035
11183
  return {
11036
11184
  content: JSON.stringify({
11037
11185
  runId: record.runId,
11038
11186
  found: true,
11039
- status: record.status,
11187
+ status: reconciled.status,
11040
11188
  stopConfirmed: false
11041
11189
  }),
11042
11190
  metadata: {
@@ -11045,11 +11193,21 @@ function createCliControlAgentRunExecutor(deps = {}) {
11045
11193
  };
11046
11194
  }
11047
11195
  }
11048
- finalizeRunRecord(record.runId, { status: "killed" }, deps);
11196
+ const transition = transitionRunToTerminal(reconciled.runId, { status: "killed" }, deps);
11197
+ const finalRecord = transition.kind === "not_found" ? reconciled : transition.record;
11049
11198
  const labels = agentRunCardLabels();
11050
11199
  return {
11051
- content: JSON.stringify({ runId: record.runId, found: true, status: "killed" }),
11052
- metadata: { displayData: formatStopRunCard("killed", labels) }
11200
+ content: JSON.stringify({
11201
+ runId: finalRecord.runId,
11202
+ found: true,
11203
+ status: finalRecord.status,
11204
+ // 进程已确认终止、但 terminal 记录被并发 writer 占住(待 reconcile):
11205
+ // 如实标记 terminal 未落盘,不偷偷重写 killed。
11206
+ ...transition.kind === "contended" ? { terminalPersisted: false } : {}
11207
+ }),
11208
+ metadata: {
11209
+ displayData: transition.kind === "contended" ? `${formatStopRunCard(finalRecord.status, labels)} (pending reconcile)` : formatStopRunCard(finalRecord.status, labels)
11210
+ }
11053
11211
  };
11054
11212
  };
11055
11213
  }
@@ -11057,6 +11215,7 @@ function createCliControlAgentRunExecutor(deps = {}) {
11057
11215
  // packages/cli/client/cliLocalToolExecutors.ts
11058
11216
  var MAX_PASTED_TEXT_LINES_PER_READ = 200;
11059
11217
  var PASTED_TEXT_EXPLICIT_OVERSHOOT_LINES = 20;
11218
+ var FULLY_DELIVERED_SEGMENT_LINES = MAX_PASTED_TEXT_LINES_PER_READ + PASTED_TEXT_EXPLICIT_OVERSHOOT_LINES;
11060
11219
  var PASTE_LEDGER_MAX_RECORDS = 64;
11061
11220
  function createReadPastedTextExecutor(store) {
11062
11221
  const ledger = /* @__PURE__ */ new Map();
@@ -11124,8 +11283,19 @@ function createReadPastedTextExecutor(store) {
11124
11283
  const clamped = explicitEnd !== void 0 && endLine < explicitEnd && endLine < lines.length;
11125
11284
  const paged = explicitEnd === void 0 && endLine < lines.length;
11126
11285
  const needsFooter = clamped || paged;
11286
+ const nextStartLine = endLine + 1;
11287
+ const remainingLines = lines.length - endLine;
11288
+ const footer = !needsFooter ? void 0 : remainingLines <= FULLY_DELIVERED_SEGMENT_LINES ? `[readPastedText: returned lines ${startLine}-${endLine} of ${lines.length}. Continue with startLine=${nextStartLine}.]` : (() => {
11289
+ const firstEnd = Math.min(
11290
+ nextStartLine + FULLY_DELIVERED_SEGMENT_LINES - 1,
11291
+ lines.length
11292
+ );
11293
+ const secondStart = firstEnd + 1;
11294
+ const secondEnd = Math.min(secondStart + FULLY_DELIVERED_SEGMENT_LINES - 1, lines.length);
11295
+ return `[readPastedText: returned lines ${startLine}-${endLine} of ${lines.length}. Continue with startLine=${nextStartLine}, or fetch the remaining ${remainingLines} lines in one turn with parallel calls (e.g. ${nextStartLine}-${firstEnd}, ${secondStart}-${secondEnd})]`;
11296
+ })();
11127
11297
  const content = needsFooter ? `${delivered}
11128
- [readPastedText: returned lines ${startLine}-${endLine} of ${lines.length}. Continue with startLine=${endLine + 1}.]` : delivered;
11298
+ ${footer}` : delivered;
11129
11299
  const metadata = {
11130
11300
  pasteId,
11131
11301
  startLine,
@@ -11136,7 +11306,7 @@ function createReadPastedTextExecutor(store) {
11136
11306
  // Continuation pointer whenever more content exists, even when an
11137
11307
  // explicit request was honored in full — the schema contract says a
11138
11308
  // truncated read advertises the exact next startLine.
11139
- ...endLine < lines.length ? { nextStartLine: endLine + 1 } : {},
11309
+ ...endLine < lines.length ? { nextStartLine: endLine + 1, remainingLines: lines.length - endLine } : {},
11140
11310
  source: "tui-paste-store"
11141
11311
  };
11142
11312
  const persistedChars = content.length + "\n\n[tool metadata]\n".length + JSON.stringify(metadata).length;
@@ -11336,7 +11506,7 @@ function buildLocalToolExecutors(args) {
11336
11506
  var REFRESH_BY_PROVIDER = {
11337
11507
  chatgpt: refreshOpenAiCodexToken,
11338
11508
  // Previously only chatgpt was wired; expired antigravity/xai tokens then
11339
- // surfaced as "OAuth credential not found" even when ~/.nolo/credentials
11509
+ // surfaced as "OAuth credential not found" even when `$NOLO_HOME/credentials` (or `~/.nolo/credentials` when `NOLO_HOME` is unset)
11340
11510
  // still held a valid refresh_token.
11341
11511
  antigravity: refreshAntigravityOAuthToken,
11342
11512
  xai: xaiRefresh,
@@ -11354,11 +11524,12 @@ function createOAuthApiKeyRefResolver(options = {}) {
11354
11524
  const token = await resolveFreshAccessToken({
11355
11525
  provider,
11356
11526
  ...options.homeDir ? { homeDir: options.homeDir } : {},
11527
+ ...options.migration ? { migration: options.migration } : {},
11357
11528
  ...refresh ? { refresh } : {},
11358
11529
  ...opts?.force ? { force: true } : {}
11359
11530
  });
11360
11531
  if (token) return token;
11361
- const store = createOAuthTokenStore(options.homeDir);
11532
+ const store = createOAuthTokenStore(options.homeDir, options.migration);
11362
11533
  const credential = store.read(provider);
11363
11534
  if (credential && isTokenExpired(credential)) {
11364
11535
  throw new Error(
@@ -11379,9 +11550,18 @@ function resolveFallbackServers(env) {
11379
11550
  ].filter((value) => typeof value === "string" && value.trim().length > 0);
11380
11551
  return [...new Set(values.map(normalizeServerOrigin))];
11381
11552
  }
11382
- function resolveAuthToken(env) {
11553
+ function resolveAuthToken2(env) {
11383
11554
  return resolvePlatformAuthToken(env);
11384
11555
  }
11556
+ function resolveHybridReadTimeoutMs(env = process.env) {
11557
+ const raw = env.NOLO_HYBRID_READ_TIMEOUT_MS?.trim();
11558
+ if (!raw) return DEFAULT_HYBRID_READ_TIMEOUT_MS;
11559
+ const parsed = Number(raw);
11560
+ if (!Number.isFinite(parsed) || parsed < 0) {
11561
+ return DEFAULT_HYBRID_READ_TIMEOUT_MS;
11562
+ }
11563
+ return parsed;
11564
+ }
11385
11565
  function createCliHybridRecordStore(deps) {
11386
11566
  return createHybridRecordStore({
11387
11567
  db: deps.db,
@@ -11389,8 +11569,9 @@ function createCliHybridRecordStore(deps) {
11389
11569
  deps.env.NOLO_SERVER || deps.env.BASE_URL || DEFAULT_NOLO_SERVER_URL
11390
11570
  ),
11391
11571
  fallbackServers: resolveFallbackServers(deps.env),
11392
- authToken: resolveAuthToken(deps.env),
11393
- fetchImpl: deps.fetchImpl
11572
+ authToken: resolveAuthToken2(deps.env),
11573
+ fetchImpl: deps.fetchImpl,
11574
+ requestTimeoutMs: resolveHybridReadTimeoutMs(deps.env)
11394
11575
  });
11395
11576
  }
11396
11577
 
@@ -11615,6 +11796,70 @@ function isRemoteAuthEndpoint(endpoint) {
11615
11796
 
11616
11797
  // packages/cli/client/localRuntimeDialog.ts
11617
11798
  var import_date_fns = __toESM(require_date_fns(), 1);
11799
+ import { appendFileSync, mkdirSync as mkdirSync2 } from "fs";
11800
+ import { homedir } from "os";
11801
+ import { join as join2 } from "path";
11802
+ var RAW_USAGE_SCALARS = [
11803
+ "prompt_tokens",
11804
+ "completion_tokens",
11805
+ "total_tokens",
11806
+ "input_tokens",
11807
+ "output_tokens",
11808
+ "cache_read_input_tokens",
11809
+ "cache_creation_input_tokens",
11810
+ "prompt_cache_hit_tokens",
11811
+ "prompt_cache_miss_tokens",
11812
+ "cost",
11813
+ "cost_in_usd_ticks",
11814
+ "provider_call_id"
11815
+ ];
11816
+ var RAW_USAGE_DETAIL_OBJECTS = [
11817
+ "prompt_tokens_details",
11818
+ "completion_tokens_details",
11819
+ "input_tokens_details",
11820
+ "output_tokens_details",
11821
+ "cost_details"
11822
+ ];
11823
+ function projectRawUsage(usage) {
11824
+ const out = {};
11825
+ for (const key of RAW_USAGE_SCALARS) {
11826
+ const value = usage[key];
11827
+ if (typeof value === "number" && Number.isFinite(value)) {
11828
+ out[key] = value;
11829
+ } else if (key === "provider_call_id" && typeof value === "string" && value.trim()) {
11830
+ out[key] = value;
11831
+ }
11832
+ }
11833
+ for (const key of RAW_USAGE_DETAIL_OBJECTS) {
11834
+ const value = usage[key];
11835
+ if (!value || typeof value !== "object" || Array.isArray(value)) continue;
11836
+ const numericLeaves = Object.fromEntries(
11837
+ Object.entries(value).filter(
11838
+ ([, leaf]) => typeof leaf === "number" && Number.isFinite(leaf)
11839
+ )
11840
+ );
11841
+ if (Object.keys(numericLeaves).length > 0) out[key] = numericLeaves;
11842
+ }
11843
+ return out;
11844
+ }
11845
+ function debugCaptureRawUsage(item) {
11846
+ if (!process.env.NOLO_DEBUG_RAW_USAGE) return;
11847
+ try {
11848
+ const noloHome = process.env.NOLO_HOME?.trim() || join2(homedir(), ".nolo");
11849
+ const dir = join2(noloHome, "logs");
11850
+ mkdirSync2(dir, { recursive: true });
11851
+ appendFileSync(
11852
+ join2(dir, "raw-usage.jsonl"),
11853
+ JSON.stringify({
11854
+ ts: Date.now(),
11855
+ model: item.model,
11856
+ provider: item.provider,
11857
+ usage: projectRawUsage(item.usage)
11858
+ }) + "\n"
11859
+ );
11860
+ } catch {
11861
+ }
11862
+ }
11618
11863
  async function resolveStore(deps) {
11619
11864
  if (deps.store) return deps.store;
11620
11865
  return createCliHybridRecordStore({
@@ -11703,6 +11948,7 @@ async function writeLocalTokenRecord(args) {
11703
11948
  const ops = [];
11704
11949
  for (const item of usageRecords) {
11705
11950
  if (!item.usage || Object.keys(item.usage).length === 0) continue;
11951
+ debugCaptureRawUsage(item);
11706
11952
  const timestamp = args.now();
11707
11953
  const callId = item.callId || typeof item.usage.provider_call_id === "string" && item.usage.provider_call_id.trim() || args.createId();
11708
11954
  const prepared = prepareTokenUsageData({
@@ -11722,7 +11968,11 @@ async function writeLocalTokenRecord(args) {
11722
11968
  agentId: args.input.agentKey,
11723
11969
  dialogId: args.dialogId,
11724
11970
  timestamp,
11725
- entry_path: "cli-local"
11971
+ entry_path: "cli-local",
11972
+ ...item.stablePrefixHash ? {
11973
+ stable_prefix_hash: item.stablePrefixHash,
11974
+ stable_prefix_estimated_tokens: item.stablePrefixEstimatedTokens
11975
+ } : {}
11726
11976
  });
11727
11977
  const recordKey = createTokenKey.recordForStableCall(args.userId, callId);
11728
11978
  const existingToken = await args.store.read(recordKey, { remote: false }).catch(() => null);
@@ -11967,7 +12217,7 @@ var currentMetaFile = fileURLToPath(import.meta.url);
11967
12217
  var isJsBundle = extname(currentMetaFile) === ".js";
11968
12218
  var SOURCE_CLI_DIR = isJsBundle ? dirname2(currentMetaFile) : dirname2(dirname2(currentMetaFile));
11969
12219
  var CLI_DIR = isCompiledBinary() ? dirname2(process.execPath) : SOURCE_CLI_DIR;
11970
- var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join2(SOURCE_CLI_DIR, "index.ts");
12220
+ var CLI_ENTRYPOINT = isCompiledBinary() ? process.execPath : isJsBundle ? currentMetaFile : join3(SOURCE_CLI_DIR, "index.ts");
11971
12221
  async function recordLocalAvailabilityForAgent(args) {
11972
12222
  const now = args.now ?? Date.now;
11973
12223
  const { deps, status } = args;
@@ -12107,10 +12357,15 @@ function createCliLocalRuntimeAdapter(deps) {
12107
12357
  deps.env,
12108
12358
  systemBuiltinSkills
12109
12359
  ) : [];
12360
+ const effectiveToolNames = [...requestedToolNames, ...additionalToolNames];
12110
12361
  activeAgentToolNames = buildLocalPolicyToolNames({
12111
12362
  agentKey: agentConfig?.key,
12112
- toolNames: [...requestedToolNames, ...additionalToolNames],
12113
- env: deps.env
12363
+ toolNames: effectiveToolNames,
12364
+ env: deps.env,
12365
+ buildProviderOpenAiTools: (toolArgs) => buildOpenAiTools({
12366
+ ...toolArgs,
12367
+ effectiveToolNames
12368
+ })
12114
12369
  });
12115
12370
  runtimeToolExecutionLimits = resolveLocalWorkspaceExecutorOptionsFromPolicy(
12116
12371
  resolveCurrentRunRuntimeToolPolicy(agentConfig)
@@ -12171,8 +12426,12 @@ function createCliLocalRuntimeAdapter(deps) {
12171
12426
  output: deps.output,
12172
12427
  cwd: workspaceRoot,
12173
12428
  titleGenerator: createLocalDialogTitleGenerator(deps, {
12174
- apiKeyRefResolver: createOAuthApiKeyRefResolver(),
12175
- credentialBroker: createFileCredentialBroker(),
12429
+ apiKeyRefResolver: createOAuthApiKeyRefResolver({
12430
+ migration: { enableLegacyMigration: true }
12431
+ }),
12432
+ credentialBroker: createFileCredentialBroker({
12433
+ migration: { enableLegacyMigration: true }
12434
+ }),
12176
12435
  loopbackRequest
12177
12436
  })
12178
12437
  }),
@@ -12215,8 +12474,15 @@ function createCliLocalRuntimeAdapter(deps) {
12215
12474
  () => void 0
12216
12475
  );
12217
12476
  }
12218
- const apiKeyRefResolver = createOAuthApiKeyRefResolver();
12219
- const credentialBroker = createFileCredentialBroker();
12477
+ const legacyCredentialMigration = {
12478
+ enableLegacyMigration: true
12479
+ };
12480
+ const apiKeyRefResolver = createOAuthApiKeyRefResolver({
12481
+ migration: legacyCredentialMigration
12482
+ });
12483
+ const credentialBroker = createFileCredentialBroker({
12484
+ migration: legacyCredentialMigration
12485
+ });
12220
12486
  const serverUrl = asOptionalTrimmedString(deps.env.NOLO_SERVER) ?? "https://us.nolo.chat";
12221
12487
  const authToken = asOptionalTrimmedString(deps.env.AUTH_TOKEN);
12222
12488
  const syncFetcher = authToken ? async (ref) => {
@@ -12263,17 +12529,22 @@ function createCliLocalRuntimeAdapter(deps) {
12263
12529
  executeTool: async (call, opts) => {
12264
12530
  const contextualCall = opts?.runtimeContext ? { ...call, runtimeContext: opts.runtimeContext } : call;
12265
12531
  let injectedCall = contextualCall;
12266
- if (contextualCall.name === "startAgentRun" && deps.parentDialogId && typeof contextualCall.arguments === "string") {
12532
+ let spawnedWithoutParent = false;
12533
+ if (contextualCall.name === "startAgentRun" && typeof contextualCall.arguments === "string") {
12267
12534
  try {
12268
12535
  const args = JSON.parse(contextualCall.arguments);
12269
12536
  if (!args.parentDialogId) {
12270
- injectedCall = {
12271
- ...contextualCall,
12272
- arguments: JSON.stringify({
12273
- ...args,
12274
- parentDialogId: deps.parentDialogId
12275
- })
12276
- };
12537
+ if (deps.parentDialogId) {
12538
+ injectedCall = {
12539
+ ...contextualCall,
12540
+ arguments: JSON.stringify({
12541
+ ...args,
12542
+ parentDialogId: deps.parentDialogId
12543
+ })
12544
+ };
12545
+ } else {
12546
+ spawnedWithoutParent = true;
12547
+ }
12277
12548
  }
12278
12549
  } catch {
12279
12550
  }
@@ -12286,12 +12557,22 @@ function createCliLocalRuntimeAdapter(deps) {
12286
12557
  const result = await executeLocalToolWithPolicy({
12287
12558
  env: deps.env,
12288
12559
  agentToolNames: activeAgentToolNames,
12560
+ runToolNames: activeAgentToolNames,
12289
12561
  call: injectedCall,
12290
12562
  executors: localToolExecutors,
12291
12563
  abortSignal: opts?.abortSignal,
12292
12564
  detachMs: resolveExecShellDetachMs(deps.env),
12293
12565
  ...deps.confirmDestructiveAction ? { confirmDestructiveAction: deps.confirmDestructiveAction } : {}
12294
12566
  });
12567
+ if (spawnedWithoutParent && deps.onBackgroundRunSpawned) {
12568
+ try {
12569
+ const payload = JSON.parse(result?.content ?? "");
12570
+ if (payload && typeof payload.runId === "string" && payload.runId) {
12571
+ deps.onBackgroundRunSpawned(payload.runId);
12572
+ }
12573
+ } catch {
12574
+ }
12575
+ }
12295
12576
  return {
12296
12577
  ...result,
12297
12578
  metadata: {
@@ -12330,14 +12611,24 @@ function createCliLocalRuntimeAdapter(deps) {
12330
12611
  export {
12331
12612
  clearCliLocalRuntimePreparedAgentCache,
12332
12613
  isSubtaskRun,
12614
+ RUN_WAKE_CHANNEL_ENV,
12333
12615
  summarizeEndpoint,
12616
+ resolveLocalUserId,
12334
12617
  isBuiltinNoloAgentRef,
12618
+ resolveAuthToken,
12619
+ resolveFileWriteGateEnabled,
12620
+ isMachineBoundLocalhostCustomProvider,
12621
+ resolveBoundMachineId,
12622
+ isCliProviderAgentConfig,
12623
+ detectCurrentMachineId,
12335
12624
  readTimestamp,
12336
12625
  parseAgentRunEvent,
12626
+ isLiveAgentRunObservation,
12337
12627
  parseCliLocale,
12338
12628
  getCliLocale,
12339
12629
  setCliLocale,
12340
12630
  initCliLocale,
12631
+ dailyWelcomeTip,
12341
12632
  t,
12342
12633
  toolLabel,
12343
12634
  agentRunCardLabels,