nolo-cli 0.211.0 → 0.213.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/{_executeModel-VVQEOY3D.js → _executeModel-CUJLCFWR.js} +57 -54
  2. package/{action-U235TV4P.js → action-DF5UYSJF.js} +4 -4
  3. package/{addContentAction-7C76J7ST.js → addContentAction-WERAONNY.js} +9 -9
  4. package/{addDialogAgentAction-KTYANUEC.js → addDialogAgentAction-7VI7YRML.js} +16 -13
  5. package/{agentDeleteCommand-WHRU6VDJ.js → agentDeleteCommand-XJORXPGU.js} +80 -76
  6. package/{agentEmailCommands-ALLHXPW3.js → agentEmailCommands-XTYYFR6Z.js} +85 -80
  7. package/{agentListCommands-POKMEKMS.js → agentListCommands-OBLRBLHS.js} +237 -115
  8. package/{agentMachineCommands-WJLZLBPI.js → agentMachineCommands-5FMT3OT5.js} +33 -31
  9. package/{agentProviderCommands-MN3ABDME.js → agentProviderCommands-Q5O33MED.js} +33 -4
  10. package/{agentRecordCommands-OULZW3KM.js → agentRecordCommands-ZQ7SVYGG.js} +75 -70
  11. package/{agentRunCommand-ZNG4LGNQ.js → agentRunCommand-WS7IGO2W.js} +77 -73
  12. package/{agentRunControl-AF7BMR22.js → agentRunControl-TAMHJQSR.js} +8 -7
  13. package/{agentRuntimeLocal-YMUHFV5M.js → agentRuntimeLocal-SOO2OPJG.js} +30 -27
  14. package/{agentSlice-WNGUIMQZ.js → agentSlice-CHR6KOZN.js} +13 -13
  15. package/{appDeleteCommands-6MXPLAVF.js → appDeleteCommands-GUP6P5YE.js} +34 -32
  16. package/{appDeployCommands-ERRSVASW.js → appDeployCommands-MH2FX4O5.js} +34 -32
  17. package/{appDeployStatusCommands-ULICISLI.js → appDeployStatusCommands-SUHN3HPJ.js} +34 -32
  18. package/{appGetCommands-WYYYWROF.js → appGetCommands-YWDEX6Z4.js} +34 -32
  19. package/{appListCommands-DFCUCRCV.js → appListCommands-ZQVMLPAY.js} +34 -32
  20. package/{authCommand-ZJMWXFMA.js → authCommand-PWX2ZNUP.js} +15 -15
  21. package/{authCommands-WK6E42L2.js → authCommands-HV3EAU3V.js} +2 -2
  22. package/{builtinSkillRegistry-HH75G5J3.js → builtinSkillRegistry-2QETTQPM.js} +5 -4
  23. package/{chromeOpsCommands-HEN5AX2J.js → chromeOpsCommands-DIVM2K3T.js} +1 -1
  24. package/{chunk-TRZP7JZ7.js → chunk-2QHFH3DR.js} +1 -0
  25. package/{chunk-XE4Q46FF.js → chunk-3CGG2PAL.js} +1 -1
  26. package/{chunk-YUXQAVRD.js → chunk-3UKL3HPD.js} +251 -14
  27. package/{chunk-BSISWVB4.js → chunk-4I7ERB7F.js} +1 -1
  28. package/{chunk-5ORJGHTL.js → chunk-4T2WNOY7.js} +6 -6
  29. package/{chunk-W5VC7F7V.js → chunk-5MQRBSMW.js} +84 -91
  30. package/{chunk-YLTLB5A7.js → chunk-6DWMYIUY.js} +7 -6
  31. package/chunk-6VLJ6YA7.js +11751 -0
  32. package/{chunk-KSTEXKL6.js → chunk-75XIDFBW.js} +4 -3
  33. package/{chunk-BTYQAODF.js → chunk-7BT37FK3.js} +196 -308
  34. package/{chunk-27E2CBBY.js → chunk-7OCO4TDT.js} +1 -1
  35. package/{chunk-V3M6IXQI.js → chunk-7QTZCMKL.js} +335 -131
  36. package/chunk-7RFNTILS.js +2213 -0
  37. package/{chunk-NHQKWPLP.js → chunk-7Y4YTDQF.js} +25 -23
  38. package/{chunk-CKAHAVMK.js → chunk-A7TFUNZO.js} +35 -25
  39. package/{chunk-PJNFNEJE.js → chunk-ALQ3657A.js} +28 -2
  40. package/{chunk-NV572QM3.js → chunk-BBJ22CLB.js} +15 -15
  41. package/chunk-CJEIOP3E.js +0 -0
  42. package/{chunk-4WCEC56C.js → chunk-COFEN36Z.js} +2 -2
  43. package/{chunk-25OB36GU.js → chunk-CRHOO2ZR.js} +4 -4
  44. package/{chunk-NTSRCTUX.js → chunk-CTPXME7U.js} +2 -2
  45. package/{chunk-TPCDYNJK.js → chunk-EHGEOAHI.js} +3 -3
  46. package/{chunk-Y2WUYX4I.js → chunk-EHSZD5OI.js} +1 -1
  47. package/{chunk-SU3QL7YG.js → chunk-FUGMREBO.js} +2 -2
  48. package/{chunk-UMEGDH6A.js → chunk-FW6YHHLI.js} +8 -8
  49. package/chunk-FY7F4Q6X.js +127 -0
  50. package/{chunk-25M2K6OA.js → chunk-G2BQWAVT.js} +3 -3
  51. package/chunk-G7MLNNEX.js +84 -0
  52. package/{chunk-DQLB4NQ3.js → chunk-GPVRUGGY.js} +2 -2
  53. package/{chunk-RQ22OZD7.js → chunk-H2TJUNCH.js} +1 -1
  54. package/{chunk-XPHZK3PJ.js → chunk-H4UOTUOX.js} +165 -51
  55. package/{chunk-CVCRAO6Q.js → chunk-H5HF7TJA.js} +9 -7
  56. package/{chunk-OP7PTBAJ.js → chunk-H7PPIYWP.js} +9 -9
  57. package/{chunk-QQM464AL.js → chunk-HPFCI4SK.js} +3 -3
  58. package/chunk-HRMJUN5J.js +26 -0
  59. package/{chunk-WI6OGHXJ.js → chunk-HSVBJRF4.js} +5 -5
  60. package/{chunk-RYWO5AKN.js → chunk-HUBHAQK2.js} +10 -10
  61. package/{chunk-LKDF3ATR.js → chunk-INUFILG6.js} +1 -1
  62. package/{chunk-NXCGNS4N.js → chunk-IXNGOHV5.js} +2 -2
  63. package/{chunk-ET2CWLIJ.js → chunk-J2NHJ7WX.js} +4 -4
  64. package/{chunk-ECX3NKRD.js → chunk-JY5NGFFH.js} +11 -0
  65. package/chunk-KC4XDTT3.js +227 -0
  66. package/{chunk-ADBWFYJD.js → chunk-KFLT5KAD.js} +9 -9
  67. package/{chunk-PLYWH7XM.js → chunk-KIM6CLW5.js} +7 -7
  68. package/{chunk-7IYBN7IA.js → chunk-LLRPJECG.js} +22 -13
  69. package/{chunk-3J3U3KXB.js → chunk-MDB67IWP.js} +5 -5
  70. package/chunk-MMA3LZ3W.js +105 -0
  71. package/{chunk-XDMGY5IU.js → chunk-MOIJOHA5.js} +227 -11
  72. package/{chunk-NLT32XBZ.js → chunk-NJLL224W.js} +2 -2
  73. package/{chunk-JBOUVTZX.js → chunk-NOKUNJON.js} +15 -4
  74. package/{chunk-C2XZM3K4.js → chunk-NSAPDIN2.js} +12 -27
  75. package/{chunk-PAFTGNWA.js → chunk-O2TZF4AI.js} +2 -2
  76. package/{chunk-UIOEHFF6.js → chunk-OQHIVPG4.js} +1 -0
  77. package/{chunk-TCTSYFDM.js → chunk-OQPKUBPB.js} +19 -6
  78. package/{chunk-X4F26D5K.js → chunk-P5L7CXOC.js} +58 -33
  79. package/{chunk-OXME3PEE.js → chunk-PCLE46CE.js} +1 -1
  80. package/{chunk-UCPAVEQB.js → chunk-PYRUW7XN.js} +1 -1
  81. package/{chunk-YXOBCDNW.js → chunk-QG4AOSON.js} +12 -49
  82. package/{chunk-RXCCWVA2.js → chunk-QHPRUL4O.js} +3 -3
  83. package/{chunk-I5PBXF7O.js → chunk-R5O4QAWG.js} +1 -1
  84. package/{chunk-HD3WR3TD.js → chunk-RLBNLZVC.js} +1 -1
  85. package/{chunk-SN5XE6GQ.js → chunk-RPQXPZZF.js} +4 -4
  86. package/{chunk-ZOO3WJIE.js → chunk-RSHTSUEG.js} +948 -108
  87. package/{chunk-6HVBI6TI.js → chunk-RZOV7OMV.js} +12 -229
  88. package/{chunk-D2MDMY2M.js → chunk-SVYO6AO7.js} +7 -1
  89. package/{chunk-IIHY4ZAI.js → chunk-TAKB25RM.js} +8 -4
  90. package/{chunk-ZN5AH4BY.js → chunk-TX5EYMGT.js} +6 -6
  91. package/{chunk-CKOO42G5.js → chunk-UHJGXRJ4.js} +4 -4
  92. package/{chunk-M4NTDZG3.js → chunk-UYD5HQ6T.js} +857 -295
  93. package/{chunk-WTKYP6QO.js → chunk-V5Y3R6BT.js} +114 -6
  94. package/{chunk-3RQVYR4B.js → chunk-VNYYOX3V.js} +59 -20
  95. package/{chunk-4LEGTOSR.js → chunk-VO4WSAVP.js} +3 -3
  96. package/{chunk-LNYHAKBP.js → chunk-W4S457LU.js} +1 -1
  97. package/{chunk-RIALQUSF.js → chunk-WMTBPBMP.js} +6 -6
  98. package/chunk-WPORQFYN.js +74 -0
  99. package/{chunk-Y6M7KJOA.js → chunk-WRYQ35LQ.js} +5 -5
  100. package/{chunk-YKFP6UGT.js → chunk-WYDI6TGM.js} +17 -17
  101. package/{chunk-SCYQJPGA.js → chunk-X7SDOJUM.js} +147 -20
  102. package/chunk-XFYFMTOM.js +92 -0
  103. package/{chunk-LT3EAHJY.js → chunk-XHQC4PXX.js} +65 -49
  104. package/{chunk-2WZXXAQD.js → chunk-YB3YZK56.js} +67 -1
  105. package/{chunk-JKW6LERJ.js → chunk-YJAFKXMU.js} +14 -14
  106. package/{chunk-GSQNH63I.js → chunk-YTF4WH7J.js} +3 -19
  107. package/{chunk-DA7CTWT4.js → chunk-YWSEPJ7C.js} +5 -5
  108. package/{chunk-3V2QMRNN.js → chunk-ZL5RAEEB.js} +3 -3
  109. package/{chunk-NEZGPBL7.js → chunk-ZNWI6OVT.js} +2 -2
  110. package/{chunk-MBS6CTZB.js → chunk-ZXOUUDCG.js} +266 -2014
  111. package/cliAgentConfigHelpers-WJBZQTLW.js +41 -0
  112. package/{commandRegistry-FI2IOQ3U.js → commandRegistry-W63CYRZJ.js} +91 -87
  113. package/{contentThunks-5LKNNDGY.js → contentThunks-U7PL5MQD.js} +27 -26
  114. package/{cooldownCommands-YXLWOXWR.js → cooldownCommands-TIGUHXTD.js} +3 -3
  115. package/{createAgentAutomationAction-TI4QG4CY.js → createAgentAutomationAction-OLBQDD6R.js} +27 -26
  116. package/{createDialogAction-TJ3JKLO4.js → createDialogAction-SVH6B3SB.js} +29 -28
  117. package/{createPageAction-GKXT6WEH.js → createPageAction-F4DIWZ2Z.js} +29 -28
  118. package/{dbSlice-LPMZ2DGJ.js → dbSlice-BVH2YZPQ.js} +8 -8
  119. package/{deleteFile-EPUQHKPA.js → deleteFile-5YOEKV4U.js} +4 -4
  120. package/{dialogCommands-IWPXIZ5P.js → dialogCommands-KHIEPY3M.js} +38 -36
  121. package/{dialogSlice-ZWNNS7GZ.js → dialogSlice-ZCTDV2PZ.js} +25 -24
  122. package/{dialogUsageCommand-ZCPPHPJ5.js → dialogUsageCommand-7KCPYGHG.js} +1 -1
  123. package/{docCreateCommands-HFSPKJSI.js → docCreateCommands-DPMZI7G5.js} +32 -30
  124. package/{docDeleteCommands-CRL62POH.js → docDeleteCommands-IRQQLUBT.js} +34 -33
  125. package/{docReadCommands-QOTOX3XW.js → docReadCommands-LK37XH6L.js} +32 -30
  126. package/{docStore-WYLRB7ED.js → docStore-V2KECILA.js} +11 -11
  127. package/{docUpdateCommands-7BMH4MCA.js → docUpdateCommands-O6T3HJHH.js} +32 -30
  128. package/{fetchMessages-YY4SATNR.js → fetchMessages-NR4KNQLO.js} +3 -3
  129. package/{getPricing-OQXBJ6VZ.js → getPricing-2MNMXEVG.js} +3 -3
  130. package/{handleSendMessageAction-P27YP2DQ.js → handleSendMessageAction-2PE25WM3.js} +49 -47
  131. package/hostCredentialCreate-S233UMAP.js +357 -0
  132. package/index.js +7 -7
  133. package/{keys-P4ZDOVJW.js → keys-BEGDOTRL.js} +3 -1
  134. package/{localDialogRead-5VCMQQZF.js → localDialogRead-7NNDVVF7.js} +1 -1
  135. package/{localRuntimeAdapter-GP6ZSSO3.js → localRuntimeAdapter-KY6WXNBR.js} +82 -75
  136. package/{machineCommands-6Z6H4BFX.js → machineCommands-Q6HA3IXF.js} +74 -69
  137. package/{machineWsRunDispatch-F2ZIXMYM.js → machineWsRunDispatch-WWJQ6WR3.js} +74 -69
  138. package/{memberThunks-YSEFJF47.js → memberThunks-7EDJADWU.js} +9 -9
  139. package/package.json +1 -1
  140. package/{projectArchive-PIGEOX3D.js → projectArchive-DRTDIMEV.js} +29 -28
  141. package/{providerPresetApply-ZYMLQA46.js → providerPresetApply-YXGV6NXB.js} +4 -4
  142. package/{providerRegistry-E34XWDLJ.js → providerRegistry-S6UL6UNA.js} +4 -4
  143. package/{read-DIIQBOOO.js → read-4V2RMG7N.js} +4 -4
  144. package/{readDocTool-HXYGOEA7.js → readDocTool-BH6ATGQO.js} +1 -1
  145. package/{readlineWorkspace-UG25G7KC.js → readlineWorkspace-2W4WRCOU.js} +437 -217
  146. package/{removeDialogAgentAction-ALJDUJ2E.js → removeDialogAgentAction-LYAZGNKW.js} +18 -15
  147. package/{runAgentClientLoop-IO5F7TCZ.js → runAgentClientLoop-J2VQBS2Z.js} +55 -52
  148. package/{runtimeDoctorCommands-PGAA47G5.js → runtimeDoctorCommands-QAI3MBKQ.js} +6 -6
  149. package/{secretCommands-ZCZ4KVET.js → secretCommands-LXDWOLZ6.js} +4 -4
  150. package/{setDialogExtraReferencesAction-O3SVMD5A.js → setDialogExtraReferencesAction-OCRPGPYH.js} +11 -11
  151. package/{setPrimaryDialogAgentAction-HE7RVFFF.js → setPrimaryDialogAgentAction-HFJDQIBU.js} +19 -16
  152. package/{settingThunks-BWWJQG4L.js → settingThunks-RAMHMTGM.js} +13 -12
  153. package/{spaceCommands-UAELIFEI.js → spaceCommands-KVJZVKVO.js} +32 -31
  154. package/{streamAgentChatTurn-VUKZQYJR.js → streamAgentChatTurn-GHBMJJ6S.js} +63 -60
  155. package/{switchDialogAgentAction-3VZS7SOS.js → switchDialogAgentAction-EBRMW3RA.js} +16 -13
  156. package/{tools-VRXJAVYI.js → tools-EWKCPKMS.js} +49 -46
  157. package/{tuiSummaryLlmCaller-TGCHZLSW.js → tuiSummaryLlmCaller-ALQYUUWB.js} +48 -19
  158. package/{updateCommands-Q6CYAEYJ.js → updateCommands-ZQYU6SCI.js} +5 -3
  159. package/{updateDialogTitleAction-MULWCJCW.js → updateDialogTitleAction-5GGMBTDF.js} +40 -72
  160. package/usageCommand-F4IPVMIZ.js +32 -0
  161. package/usageRebuildCommand-HAW2AD5N.js +626 -0
  162. package/{windowsSelfUpdate-XSQVF2GK.js → windowsSelfUpdate-257DV2T6.js} +2 -2
  163. package/{workloadLifecycle-4BEQHMSD.js → workloadLifecycle-4C42SVBD.js} +1 -0
  164. package/chunk-4LCOCOR5.js +0 -50
  165. package/chunk-7AUQ3WCW.js +0 -51
  166. package/chunk-ZRAU6T47.js +0 -56
  167. package/{agentFavoriteCommands-GAFEXKKP.js → agentFavoriteCommands-EDK743YA.js} +1 -1
  168. package/{agentGrantCommands-V5FOQKFD.js → agentGrantCommands-RQWK2TEV.js} +1 -1
  169. package/{agentPullCommand-2JMJP5BS.js → agentPullCommand-6EM3URVK.js} +1 -1
  170. package/{chunk-A2ZMIRLN.js → chunk-INN4LTAJ.js} +5 -5
  171. package/{chunk-PV6JJAUB.js → chunk-TCZHTTUU.js} +8 -8
  172. package/{chunk-AKE53VMW.js → chunk-ZCWRMUWT.js} +0 -0
  173. package/{tableCommands-D7WR4QSM.js → tableCommands-MP6VFSVT.js} +3 -3
@@ -1,3 +1,17 @@
1
+ import {
2
+ defaultLoopbackRequest
3
+ } from "./chunk-VP3BINY7.js";
4
+ import {
5
+ clearCredentialAvailability,
6
+ markCredentialUnavailable,
7
+ readCredentialEntry
8
+ } from "./chunk-YTF4WH7J.js";
9
+ import {
10
+ CREDENTIAL_STORE_SESSION_FALLBACK_WARNING,
11
+ OAUTH_PROVIDER_REFS,
12
+ buildLocalAgentLookupKeys,
13
+ getSharedSessionCredentialBroker
14
+ } from "./chunk-MOIJOHA5.js";
1
15
  import {
2
16
  customNativeAuthHeaders,
3
17
  detectDeclaredCustomNativeWire,
@@ -15,26 +29,16 @@ import {
15
29
  resolveClaudeCodeVersion,
16
30
  resolveServerSyncConfig,
17
31
  xaiRefresh
18
- } from "./chunk-SN5XE6GQ.js";
19
- import {
20
- defaultLoopbackRequest
21
- } from "./chunk-VP3BINY7.js";
32
+ } from "./chunk-RPQXPZZF.js";
22
33
  import {
23
- clearCredentialAvailability,
24
- markCredentialUnavailable,
25
- readCredentialEntry,
26
- readEffectiveCredentialEntry,
27
- recordCredentialProbe
28
- } from "./chunk-GSQNH63I.js";
29
- import {
30
- OAUTH_PROVIDER_REFS,
31
- buildLocalAgentLookupKeys
32
- } from "./chunk-7AUQ3WCW.js";
34
+ extractLastUserText,
35
+ localTurnHasSubjectRefs,
36
+ resolveLocalUserId,
37
+ withResolvedRuntimeToolSurface
38
+ } from "./chunk-G7MLNNEX.js";
33
39
  import {
34
40
  LOCAL_CODEX_AGENT_ID,
35
- LOCAL_CODEX_AGENT_KEY,
36
- NOLO_DEFAULT_AGENT_ID,
37
- NOLO_DEFAULT_AGENT_KEY
41
+ LOCAL_CODEX_AGENT_KEY
38
42
  } from "./chunk-NBTY7YJF.js";
39
43
  import {
40
44
  CliProviderQuotaError,
@@ -60,14 +64,14 @@ import {
60
64
  } from "./chunk-F7CI2ZC5.js";
61
65
  import {
62
66
  applyPublicAgentCatalogOverride
63
- } from "./chunk-RQ22OZD7.js";
67
+ } from "./chunk-H2TJUNCH.js";
64
68
  import {
65
69
  buildCliPrompt
66
70
  } from "./chunk-ATNTHIZI.js";
67
71
  import {
68
72
  inlineImageUrlsForCustomProvider,
69
73
  prepareTools
70
- } from "./chunk-25M2K6OA.js";
74
+ } from "./chunk-G2BQWAVT.js";
71
75
  import {
72
76
  getServerProviderSecret
73
77
  } from "./chunk-HS7MLR74.js";
@@ -89,7 +93,7 @@ import {
89
93
  resolveCliLocalRuntimeKeyCapability,
90
94
  resolveCliLocalSpawnDispatch,
91
95
  resolveStartAgentRunCwd
92
- } from "./chunk-LT3EAHJY.js";
96
+ } from "./chunk-XHQC4PXX.js";
93
97
  import {
94
98
  fetchWithTransientRetry,
95
99
  isTransientFetchError
@@ -97,37 +101,39 @@ import {
97
101
  import {
98
102
  deriveCredentialGroup,
99
103
  deriveCustomProviderCredentialGroup
100
- } from "./chunk-YXOBCDNW.js";
104
+ } from "./chunk-QG4AOSON.js";
101
105
  import {
102
106
  inferCaptureIntent,
103
107
  resolveUserSkillRuntime
104
- } from "./chunk-NEZGPBL7.js";
108
+ } from "./chunk-ZNWI6OVT.js";
105
109
  import {
106
110
  resolveAgentRequiredPackIds,
107
111
  resolveUserEnabledSkills
108
- } from "./chunk-I5PBXF7O.js";
112
+ } from "./chunk-R5O4QAWG.js";
109
113
  import {
110
114
  applyBuiltinAgentRuntimeOverride,
111
- applyTokenUsageToDayStats,
112
- format,
113
115
  prepareTokenUsageData,
114
116
  resolveBuiltinPlatformAgentConfig,
115
117
  runKeyed,
116
118
  validateAskChoiceInput
117
- } from "./chunk-MBS6CTZB.js";
119
+ } from "./chunk-ZXOUUDCG.js";
120
+ import {
121
+ applyTokenUsageToDayStats,
122
+ require_format
123
+ } from "./chunk-7RFNTILS.js";
118
124
  import {
119
125
  BUILTIN_DIALOG_LLM_CHAT_FALLBACK_MODEL,
120
126
  BUILTIN_TITLE_LLM_CONFIG
121
127
  } from "./chunk-523DITKR.js";
122
128
  import {
123
129
  fetchServerSyncedCredential
124
- } from "./chunk-ADBWFYJD.js";
130
+ } from "./chunk-KFLT5KAD.js";
125
131
  import {
126
132
  getDefaultCliLocalRuntimeDb
127
133
  } from "./chunk-AZMYUSVF.js";
128
134
  import {
129
135
  isTombstoneRecord
130
- } from "./chunk-D2MDMY2M.js";
136
+ } from "./chunk-SVYO6AO7.js";
131
137
  import {
132
138
  FORCED_TOOLS,
133
139
  addDefaultLightWebToolsForConfiguredAgents,
@@ -137,7 +143,7 @@ import {
137
143
  applySystemBuiltinSkillFilter,
138
144
  expandEnabledPacks,
139
145
  resolveEffectiveEnabledPacks
140
- } from "./chunk-TPCDYNJK.js";
146
+ } from "./chunk-EHGEOAHI.js";
141
147
  import {
142
148
  DEFAULT_HYBRID_READ_TIMEOUT_MS,
143
149
  Duration_exports,
@@ -153,9 +159,11 @@ import {
153
159
  buildNoloWorkspaceCliToolExecutors,
154
160
  codexStreamFailureStatus,
155
161
  createDevinProvider,
162
+ createHostCredentialBrokerChain,
156
163
  createHybridRecordStore,
157
164
  createLocalWorkspaceToolExecutors,
158
165
  createResponsesStreamCollector,
166
+ createStrictHostCredentialBroker,
159
167
  deriveStableUuid,
160
168
  dialogMessageRecordToAgentRuntimeMessage,
161
169
  executeLocalToolWithPolicy,
@@ -181,7 +189,18 @@ import {
181
189
  runExecShellGates,
182
190
  validateConfiguredRootExecutionLease,
183
191
  verifyOwnerRouteAck
184
- } from "./chunk-ZOO3WJIE.js";
192
+ } from "./chunk-RSHTSUEG.js";
193
+ import {
194
+ PlatformStreamInterruptedError,
195
+ buildPlatformChatCompletionRequest,
196
+ canUsePlatformChatProvider,
197
+ hasDirectOpenAiCompatibleProvider,
198
+ parsePlatformChatCompletionData,
199
+ parsePlatformChatCompletionResponse,
200
+ readPlatformChatSseCompletion,
201
+ resolvePlatformChatProviderConfig,
202
+ shouldUsePlatformChatProvider
203
+ } from "./chunk-OQPKUBPB.js";
185
204
  import {
186
205
  accumulateGeminiChunks,
187
206
  buildGeminiGenerateContentRequest,
@@ -193,32 +212,21 @@ import {
193
212
  resolveAntigravityFinishReason,
194
213
  resolveGeminiModelQuirks,
195
214
  shouldUseGeminiNativeToolRoute
196
- } from "./chunk-NTSRCTUX.js";
197
- import {
198
- PlatformStreamInterruptedError,
199
- buildPlatformChatCompletionRequest,
200
- canUsePlatformChatProvider,
201
- hasDirectOpenAiCompatibleProvider,
202
- parsePlatformChatCompletionData,
203
- parsePlatformChatCompletionResponse,
204
- readPlatformChatSseCompletion,
205
- resolvePlatformChatProviderConfig,
206
- shouldUsePlatformChatProvider
207
- } from "./chunk-TCTSYFDM.js";
215
+ } from "./chunk-CTPXME7U.js";
208
216
  import {
209
217
  readSseDataValues,
210
218
  readSseFrames
211
219
  } from "./chunk-HNUWUO75.js";
212
220
  import {
213
221
  resolveAgentRuntimeConfigFromRecord
214
- } from "./chunk-LNYHAKBP.js";
222
+ } from "./chunk-W4S457LU.js";
215
223
  import {
216
224
  collectStablePromptPrefix,
217
225
  convertMessagesToResponsesInput,
218
226
  findAgentStatePairingIssues,
219
227
  stablePromptCacheKey,
220
228
  toResponsesTools
221
- } from "./chunk-CVCRAO6Q.js";
229
+ } from "./chunk-H5HF7TJA.js";
222
230
  import {
223
231
  EMPTY_TOOL_RESULT_TEXT,
224
232
  createToolImageBudget,
@@ -232,32 +240,39 @@ import {
232
240
  buildNoloWorkspaceOpenAiTools,
233
241
  filterClientNoloWorkspaceToolNames,
234
242
  parseNoloWorkspaceToolArguments,
235
- resolveRequestToolSurface,
236
- resolveRuntimeToolSurfaceForAgent
237
- } from "./chunk-6HVBI6TI.js";
243
+ resolveDispatchedSubtaskBudget
244
+ } from "./chunk-RZOV7OMV.js";
238
245
  import {
246
+ extractQuotaSnapshot,
239
247
  isCapacitySaturatedRateLimit,
240
248
  mergeAvailabilityDeadline,
241
249
  resolveAvailabilityAction,
242
- resolveCooldownGate,
243
250
  resolveCredentialKeyWithFallback
244
- } from "./chunk-YUXQAVRD.js";
251
+ } from "./chunk-3UKL3HPD.js";
252
+ import {
253
+ resolveRequestToolSurface
254
+ } from "./chunk-KC4XDTT3.js";
245
255
  import {
246
256
  resolveHistoricalToolContentCap
247
- } from "./chunk-2WZXXAQD.js";
257
+ } from "./chunk-YB3YZK56.js";
248
258
  import {
249
259
  resolveToolImagePolicy
250
- } from "./chunk-DA7CTWT4.js";
260
+ } from "./chunk-YWSEPJ7C.js";
251
261
  import {
252
262
  buildDialogFallbackTitleFromUserInput,
253
263
  normalizeDialogTitle
254
264
  } from "./chunk-2MBTWINN.js";
255
265
  import {
256
- normalizeUsage
257
- } from "./chunk-WTKYP6QO.js";
258
- import {
259
- isDevinOAuthAgent
260
- } from "./chunk-5ZUL4CUO.js";
266
+ CODEX_OAUTH_CATALOG_RETRY_FLOOR_MS,
267
+ CODEX_OAUTH_CATALOG_TTL_MS,
268
+ codexOAuthCatalogAccountKey,
269
+ codexOAuthCatalogSnapshot,
270
+ commitCodexOAuthCatalogWindows,
271
+ isCodexOAuthAgent,
272
+ markCodexOAuthCatalogFailure,
273
+ normalizeUsage,
274
+ resolveCodexOAuthEffectiveModel
275
+ } from "./chunk-V5Y3R6BT.js";
261
276
  import {
262
277
  createProviderCallTimingTracker,
263
278
  finalizeProviderCallTiming,
@@ -265,6 +280,9 @@ import {
265
280
  observeMeaningfulProviderResponseAt,
266
281
  withProviderCallTimingFields
267
282
  } from "./chunk-H57T64RA.js";
283
+ import {
284
+ isDevinOAuthAgent
285
+ } from "./chunk-5ZUL4CUO.js";
268
286
  import {
269
287
  isOAuthApiKeyRef
270
288
  } from "./chunk-UKZX3NHN.js";
@@ -275,35 +293,26 @@ import {
275
293
  resolveCurrentRunRuntimeToolPolicy,
276
294
  resolveLocalWorkspaceExecutorOptionsFromPolicy,
277
295
  resolveRequestedRuntimeToolNames
278
- } from "./chunk-TRZP7JZ7.js";
296
+ } from "./chunk-2QHFH3DR.js";
279
297
  import {
280
298
  createFileCredentialBroker
281
- } from "./chunk-UIOEHFF6.js";
299
+ } from "./chunk-OQHIVPG4.js";
282
300
  import {
283
301
  asRecordOrEmpty
284
302
  } from "./chunk-KX6YBIHG.js";
285
303
  import {
286
304
  compactWhitespace
287
305
  } from "./chunk-DWLEOOGR.js";
288
- import {
289
- createOAuthTokenStore,
290
- isTokenExpired,
291
- readOAuthCredential,
292
- resolveFreshAccessToken
293
- } from "./chunk-G7Y4GXTY.js";
294
306
  import {
295
307
  canonicalizeToolNames
296
- } from "./chunk-AKE53VMW.js";
308
+ } from "./chunk-ZCWRMUWT.js";
297
309
  import {
298
310
  CHROME_CONNECTOR_ACCEPTED_TOOL_NAMES,
299
311
  canonicalizeChromeConnectorToolNames
300
312
  } from "./chunk-ZC3CMUKU.js";
301
- import {
302
- isSystemBuiltinTrustedAgentKey
303
- } from "./chunk-LOEO7LRC.js";
304
313
  import {
305
314
  isAntigravityOAuthAgent
306
- } from "./chunk-PLYWH7XM.js";
315
+ } from "./chunk-KIM6CLW5.js";
307
316
  import {
308
317
  ackRunRecord,
309
318
  appendRunQueue,
@@ -318,18 +327,21 @@ import {
318
327
  queryRunRecords,
319
328
  readHostMemory,
320
329
  releaseRunRecordAck,
321
- remoteDialogSyncTimeout,
322
330
  resolveRunsDir,
323
- resolveRuntimeAuthToken,
324
- resolveRuntimeServerUrl,
325
331
  serializeQueueEntries,
326
332
  spawnLocalBackgroundRun,
327
333
  terminateRunProcess,
328
334
  transitionRunToTerminal,
329
335
  withQueueLock
330
- } from "./chunk-C2XZM3K4.js";
336
+ } from "./chunk-NSAPDIN2.js";
337
+ import {
338
+ remoteDialogSyncTimeout,
339
+ resolveRuntimeAuthToken,
340
+ resolveRuntimeServerUrl
341
+ } from "./chunk-HRMJUN5J.js";
331
342
  import {
332
343
  TASK_PREVIEW_MAX,
344
+ formatControlRunMessageCard,
333
345
  formatListRunsCard,
334
346
  formatNotFoundRunCard,
335
347
  formatStartRunCard,
@@ -340,14 +352,14 @@ import {
340
352
  normalizeRunTitle,
341
353
  resolveRunLabel,
342
354
  shortRunId
343
- } from "./chunk-PJNFNEJE.js";
355
+ } from "./chunk-ALQ3657A.js";
344
356
  import {
345
357
  estimateTokenCount
346
358
  } from "./chunk-PSCNXBYA.js";
347
359
  import {
348
360
  buildProviderSessionHeaders,
349
361
  resolvePlatformAuthToken
350
- } from "./chunk-PV6JJAUB.js";
362
+ } from "./chunk-TCZHTTUU.js";
351
363
  import {
352
364
  anthropicOAuthModelMaxOutputTokens,
353
365
  findModelConfig,
@@ -363,6 +375,9 @@ import {
363
375
  import {
364
376
  isRecord
365
377
  } from "./chunk-KUG52IAP.js";
378
+ import {
379
+ asTrimmedLowercaseString
380
+ } from "./chunk-QSJ3HFEF.js";
366
381
  import {
367
382
  getLogger
368
383
  } from "./chunk-EYLGAEB4.js";
@@ -387,13 +402,19 @@ import {
387
402
  import {
388
403
  agentRunCardLabels,
389
404
  t
390
- } from "./chunk-3RQVYR4B.js";
405
+ } from "./chunk-VNYYOX3V.js";
406
+ import {
407
+ createOAuthTokenStore,
408
+ isTokenExpired,
409
+ readOAuthCredential,
410
+ resolveFreshAccessToken
411
+ } from "./chunk-G7Y4GXTY.js";
391
412
  import {
392
413
  createTokenDialogIndexKey,
393
414
  createTokenKey,
394
415
  createTokenStatsKey,
395
416
  createUserKey
396
- } from "./chunk-ECX3NKRD.js";
417
+ } from "./chunk-JY5NGFFH.js";
397
418
  import {
398
419
  dialogMessageKey,
399
420
  dialogMessagePrefix,
@@ -406,8 +427,8 @@ import {
406
427
  asOptionalTrimmedString
407
428
  } from "./chunk-G3SUCT4W.js";
408
429
  import {
409
- asTrimmedLowercaseString
410
- } from "./chunk-QSJ3HFEF.js";
430
+ __toESM
431
+ } from "./chunk-4VNS5WPM.js";
411
432
 
412
433
  // packages/agent-runtime/anthropicMessagesProvider.ts
413
434
  import { randomUUID } from "node:crypto";
@@ -1047,7 +1068,7 @@ async function fetchAnthropicMessagesCompletion(args) {
1047
1068
  const errorBody = await response.json().catch(async () => ({
1048
1069
  error: { message: await response.text().catch(() => response.statusText) }
1049
1070
  }));
1050
- if (adoptRequiredClaudeCodeVersion(errorBody)) {
1071
+ if (!args.noRetries && adoptRequiredClaudeCodeVersion(errorBody)) {
1051
1072
  response = await (args.fetchImpl ?? fetch)(ANTHROPIC_MESSAGES_URL, {
1052
1073
  method: "POST",
1053
1074
  headers: buildHeaders(),
@@ -1514,6 +1535,8 @@ var resolveAnthropicOAuthTransport = async (ctx) => {
1514
1535
  const result = await fetchAnthropicMessagesCompletion({
1515
1536
  agentConfig,
1516
1537
  accessToken,
1538
+ signal: options?.signal,
1539
+ ...options?.noRetries ? { noRetries: true } : {},
1517
1540
  openAiBody: {
1518
1541
  model: agentConfig.model || "claude-sonnet-5",
1519
1542
  messages,
@@ -1522,7 +1545,8 @@ var resolveAnthropicOAuthTransport = async (ctx) => {
1522
1545
  },
1523
1546
  fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
1524
1547
  sleep: deps.sleep,
1525
- loopbackRequest
1548
+ loopbackRequest,
1549
+ ...options?.noRetries ? { maxAttempts: 1, coreDrainingMaxAttempts: 1 } : {}
1526
1550
  })
1527
1551
  });
1528
1552
  await recordLocalAvailability(result.status, result.body);
@@ -1836,61 +1860,6 @@ function summarizeEndpoint(value) {
1836
1860
  }
1837
1861
  }
1838
1862
 
1839
- // packages/cli/client/cliAgentConfigHelpers.ts
1840
- var BUILTIN_NOLO_AGENT_KEY = NOLO_DEFAULT_AGENT_KEY;
1841
- var BUILTIN_NOLO_AGENT_ID = NOLO_DEFAULT_AGENT_ID;
1842
- function resolveLocalUserId(env) {
1843
- const explicitUserId = env.NOLO_LOCAL_USER_ID || env.NOLO_USER_ID;
1844
- if (explicitUserId) return explicitUserId;
1845
- const tokenUserId = parseUserIdFromAuthToken(resolveRuntimeAuthToken(env));
1846
- return tokenUserId || "local";
1847
- }
1848
- function isBuiltinNoloAgentRef(ref) {
1849
- if (typeof ref !== "string") return false;
1850
- const normalized = ref.trim();
1851
- return normalized === BUILTIN_NOLO_AGENT_KEY || normalized === BUILTIN_NOLO_AGENT_ID || normalized.endsWith(`-${BUILTIN_NOLO_AGENT_ID}`);
1852
- }
1853
- function isBuiltinNoloAgentConfig(agentConfig) {
1854
- const key = agentConfig?.key || agentConfig?.rawRecord?.dbKey || agentConfig?.rawRecord?.agentKey;
1855
- const id = agentConfig?.rawRecord?.id;
1856
- return isBuiltinNoloAgentRef(key) || isBuiltinNoloAgentRef(id);
1857
- }
1858
- function withResolvedRuntimeToolSurface(agentConfig, env) {
1859
- if (!agentConfig) return agentConfig;
1860
- const currentUserId = resolveLocalUserId(env);
1861
- const rawRecord = agentConfig.rawRecord ?? {};
1862
- const ownerId = asOptionalTrimmedString(rawRecord.userId) ?? null;
1863
- const agentKey = rawRecord.dbKey ?? agentConfig.key;
1864
- const toolSurface = resolveRuntimeToolSurfaceForAgent({
1865
- explicitToolNames: agentConfig.toolNames,
1866
- currentUserId,
1867
- agentOwnerId: ownerId,
1868
- agentKey,
1869
- isPublic: !isBuiltinNoloAgentConfig(agentConfig) && rawRecord.isPublic === true,
1870
- sharingLevel: typeof rawRecord.sharingLevel === "string" ? rawRecord.sharingLevel : null,
1871
- trustedPrivateInvocation: isBuiltinNoloAgentConfig(agentConfig) || isSystemBuiltinTrustedAgentKey(agentKey),
1872
- runtimeHost: "cli"
1873
- });
1874
- return {
1875
- ...agentConfig,
1876
- toolNames: toolSurface.finalToolNames,
1877
- toolSurface,
1878
- prompt: agentConfig.prompt
1879
- };
1880
- }
1881
- function extractLastUserText(messages) {
1882
- const lastUser = [...messages].reverse().find((m) => m.role === "user");
1883
- if (!lastUser) return "";
1884
- if (typeof lastUser.content === "string") return lastUser.content;
1885
- if (Array.isArray(lastUser.content)) {
1886
- return lastUser.content.filter((part) => part?.type === "text").map((part) => part.text ?? "").join(" ");
1887
- }
1888
- return "";
1889
- }
1890
- function localTurnHasSubjectRefs(input) {
1891
- return Array.isArray(input.runtimeContext?.subjectRefs) && input.runtimeContext.subjectRefs.length > 0;
1892
- }
1893
-
1894
1863
  // packages/cli/client/providerResolution/antigravityTransport.ts
1895
1864
  var resolveAntigravityTransport = async (ctx) => {
1896
1865
  const {
@@ -1968,7 +1937,7 @@ var resolveAntigravityTransport = async (ctx) => {
1968
1937
  agentConfig,
1969
1938
  resolveCredential: resolveLocalCredential,
1970
1939
  // 非 OAuth(api-key ref)不重试:metered key 没有 refresh 语义。
1971
- supportsAuthRetry: !isApiKeyRef,
1940
+ supportsAuthRetry: !isApiKeyRef && !options?.noRetries,
1972
1941
  openAiBody,
1973
1942
  ...options?.signal ? { signal: options.signal } : {},
1974
1943
  // whole-invocation timeout 透传:seam 最外层 timeoutOption 统一 interrupt
@@ -1978,7 +1947,8 @@ var resolveAntigravityTransport = async (ctx) => {
1978
1947
  onReasoningDelta: options?.onReasoningDelta,
1979
1948
  fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
1980
1949
  sleep: deps.sleep,
1981
- loopbackRequest
1950
+ loopbackRequest,
1951
+ ...options?.noRetries ? { maxAttempts: 1, coreDrainingMaxAttempts: 1 } : {}
1982
1952
  })
1983
1953
  });
1984
1954
  } catch (error) {
@@ -2299,6 +2269,7 @@ function collectCliProviderImageInputs(messages) {
2299
2269
  var resolveCliProviderTransport = async (ctx) => {
2300
2270
  const { agentConfig, deps, workspaceRoot } = ctx;
2301
2271
  if (isCliProviderAgent(agentConfig)) {
2272
+ if (ctx.textOnly) throw new Error("local CLI subprocess does not support isolated text-only mode");
2302
2273
  const provider = resolveCliProviderName(agentConfig);
2303
2274
  logLocalRuntimeDiagnostic("provider.selected", {
2304
2275
  agentKey: agentConfig.key,
@@ -2361,41 +2332,6 @@ var resolveCliProviderTransport = async (ctx) => {
2361
2332
  // packages/agent-runtime/codexResponsesProvider.ts
2362
2333
  import { createHash } from "node:crypto";
2363
2334
  import { randomUUID as randomUUID2 } from "node:crypto";
2364
-
2365
- // packages/agent-runtime/codexOAuthModelAliases.ts
2366
- var CODEX_OAUTH_MODEL_ALIASES = {
2367
- // sol 家族最新:gpt-6.1-sol
2368
- "gpt-6-sol": {
2369
- aliasOf: "gpt-6.1-sol",
2370
- since: "2026-11-01",
2371
- reason: "\u540C\u5BB6\u65CF\u6362\u4EE3\uFF0Cowner \u51B3\u5B9A\u900F\u660E\u91CD\u5B9A\u5411\uFF08sol \u5BB6\u65CF\u6700\u65B0\u4E3A gpt-6.1-sol\uFF09\u3002"
2372
- },
2373
- "gpt-5.6-sol": {
2374
- aliasOf: "gpt-6.1-sol",
2375
- since: "2026-11-01",
2376
- reason: "\u540C\u5BB6\u65CF\u6362\u4EE3\uFF0Cowner \u51B3\u5B9A\u900F\u660E\u91CD\u5B9A\u5411\uFF08sol \u5BB6\u65CF\u6700\u65B0\u4E3A gpt-6.1-sol\uFF09\u3002"
2377
- },
2378
- // terra 家族最新:gpt-6.1-terra
2379
- "gpt-5.6-terra": {
2380
- aliasOf: "gpt-6.1-terra",
2381
- since: "2026-11-01",
2382
- reason: "\u540C\u5BB6\u65CF\u6362\u4EE3\uFF0Cowner \u51B3\u5B9A\u900F\u660E\u91CD\u5B9A\u5411\uFF08terra \u5BB6\u65CF\u6700\u65B0\u4E3A gpt-6.1-terra\uFF09\u3002"
2383
- },
2384
- // luna 家族最新:gpt-6-luna(上游无 6.1-luna,luna 家族最新即为 gpt-6-luna)
2385
- "gpt-5.6-luna": {
2386
- aliasOf: "gpt-6-luna",
2387
- since: "2026-11-01",
2388
- reason: "\u540C\u5BB6\u65CF\u6362\u4EE3\uFF0Cowner \u51B3\u5B9A\u900F\u660E\u91CD\u5B9A\u5411\uFF08luna \u5BB6\u65CF\u6700\u65B0\u4E3A gpt-6-luna\uFF09\u3002"
2389
- }
2390
- };
2391
- function resolveCodexOAuthEffectiveModel(model) {
2392
- const raw = asOptionalTrimmedString(model);
2393
- if (!raw) return void 0;
2394
- const normalized = raw.toLowerCase();
2395
- return CODEX_OAUTH_MODEL_ALIASES[normalized]?.aliasOf ?? raw;
2396
- }
2397
-
2398
- // packages/agent-runtime/codexResponsesProvider.ts
2399
2335
  var CODEX_RESPONSES_URL = "https://chatgpt.com/backend-api/codex/responses";
2400
2336
  var CODEX_CLIENT_VERSION = "0.162.1";
2401
2337
  var CODEX_ORIGINATOR = "codex_cli_rs";
@@ -2546,6 +2482,8 @@ function buildCodexRequestBody(args, identity = createCodexRequestIdentity(), se
2546
2482
  prompt_cache_key: sessionKey && isStableSessionIdentityEnabled() ? identity.sessionId : stablePromptCacheKey([model, stableInstructions, tools ?? []], "nolo-codex"),
2547
2483
  client_metadata: identity.clientMetadata
2548
2484
  };
2485
+ const reasoningEffort = args.openAiBody.reasoning_effort;
2486
+ if (reasoningEffort === "low") body.reasoning = { effort: reasoningEffort };
2549
2487
  if (instructions) body.instructions = instructions;
2550
2488
  if (tools && tools.length > 0) {
2551
2489
  body.tools = tools;
@@ -2721,10 +2659,96 @@ async function fetchCodexResponsesCompletion(args) {
2721
2659
  }
2722
2660
  return result;
2723
2661
  }
2724
- function isCodexOAuthAgent(agentConfig) {
2725
- if (!agentConfig) return false;
2726
- const apiKeyRef = asTrimmedLowercaseString(agentConfig.apiKeyRef);
2727
- return apiKeyRef === "chatgpt";
2662
+
2663
+ // packages/agent-runtime/codexOAuthModelCatalog.ts
2664
+ var CODEX_OAUTH_MODELS_URL = "https://chatgpt.com/backend-api/codex/models";
2665
+ var CODEX_OAUTH_CATALOG_REQUEST_TIMEOUT_MS = 4e3;
2666
+ var inFlightCatalogFetches = /* @__PURE__ */ new Map();
2667
+ var catalogRequestUrl = () => `${CODEX_OAUTH_MODELS_URL}?client_version=${encodeURIComponent(CODEX_CLIENT_VERSION)}`;
2668
+ var parseCodexOAuthModelCatalog = (payload) => {
2669
+ const models = payload?.models;
2670
+ if (!Array.isArray(models)) return null;
2671
+ const windows = {};
2672
+ for (const entry of models) {
2673
+ if (!entry || typeof entry !== "object") continue;
2674
+ const record = entry;
2675
+ const slug = typeof record.slug === "string" ? record.slug.trim().toLowerCase() : "";
2676
+ if (!slug) continue;
2677
+ const contextWindow = record.context_window;
2678
+ if (typeof contextWindow !== "number" || !Number.isInteger(contextWindow) || contextWindow <= 0) {
2679
+ continue;
2680
+ }
2681
+ windows[slug] = contextWindow;
2682
+ }
2683
+ return windows;
2684
+ };
2685
+ var reportCodexOAuthCatalogFailure = (stage, accountId) => {
2686
+ try {
2687
+ const account = accountId ? accountId.slice(0, 6) : null;
2688
+ console.debug(
2689
+ `[codexOAuthModelCatalog] ${stage}${account ? ` account=${account}\u2026` : ""}`
2690
+ );
2691
+ } catch {
2692
+ }
2693
+ };
2694
+ async function ensureCodexOAuthModelCatalog(args) {
2695
+ const accessToken = args.accessToken?.trim();
2696
+ if (!accessToken) return;
2697
+ const accountId = args.accountId?.trim() || void 0;
2698
+ const nowMs = () => args.now ? args.now() : Date.now();
2699
+ const ttlMs = args.ttlMs ?? CODEX_OAUTH_CATALOG_TTL_MS;
2700
+ const accountKey = codexOAuthCatalogAccountKey(accountId);
2701
+ const snapshot = codexOAuthCatalogSnapshot(accountId);
2702
+ const now = nowMs();
2703
+ if (snapshot.fetchedAt !== null && now - snapshot.fetchedAt < ttlMs) return;
2704
+ if (snapshot.lastFailureAt !== null && now - snapshot.lastFailureAt < CODEX_OAUTH_CATALOG_RETRY_FLOOR_MS) {
2705
+ return;
2706
+ }
2707
+ const pending = inFlightCatalogFetches.get(accountKey);
2708
+ if (pending) {
2709
+ await pending;
2710
+ return;
2711
+ }
2712
+ const fetchImpl = args.fetchImpl ?? fetch;
2713
+ const timeoutMs = args.timeoutMs ?? CODEX_OAUTH_CATALOG_REQUEST_TIMEOUT_MS;
2714
+ const job = (async () => {
2715
+ try {
2716
+ const headers = {
2717
+ Authorization: `Bearer ${accessToken}`,
2718
+ originator: CODEX_ORIGINATOR,
2719
+ version: CODEX_CLIENT_VERSION,
2720
+ Accept: "application/json"
2721
+ };
2722
+ if (accountId) headers["chatgpt-account-id"] = accountId;
2723
+ const response = await fetchImpl(catalogRequestUrl(), {
2724
+ method: "GET",
2725
+ headers,
2726
+ signal: typeof AbortSignal !== "undefined" && typeof AbortSignal.timeout === "function" && timeoutMs > 0 ? AbortSignal.timeout(timeoutMs) : void 0
2727
+ });
2728
+ if (!response.ok) {
2729
+ markCodexOAuthCatalogFailure({ accountId, now: nowMs() });
2730
+ reportCodexOAuthCatalogFailure(`http ${response.status}`, accountId);
2731
+ return;
2732
+ }
2733
+ const payload = await response.json();
2734
+ const windows = parseCodexOAuthModelCatalog(payload);
2735
+ if (!windows) {
2736
+ markCodexOAuthCatalogFailure({ accountId, now: nowMs() });
2737
+ reportCodexOAuthCatalogFailure("malformed payload", accountId);
2738
+ return;
2739
+ }
2740
+ commitCodexOAuthCatalogWindows({ accountId, models: windows, now: nowMs() });
2741
+ } catch {
2742
+ markCodexOAuthCatalogFailure({ accountId, now: nowMs() });
2743
+ reportCodexOAuthCatalogFailure("request failed", accountId);
2744
+ }
2745
+ })();
2746
+ inFlightCatalogFetches.set(accountKey, job);
2747
+ try {
2748
+ await job;
2749
+ } finally {
2750
+ inFlightCatalogFetches.delete(accountKey);
2751
+ }
2728
2752
  }
2729
2753
 
2730
2754
  // packages/cli/client/providerResolution/codexOAuthTransport.ts
@@ -2829,7 +2853,12 @@ var resolveCodexOAuthTransport = async (ctx) => {
2829
2853
  trace.log("headers", { attempt, status: res.status });
2830
2854
  return res;
2831
2855
  };
2856
+ if (!options?.noRetries) void ensureCodexOAuthModelCatalog({
2857
+ accessToken,
2858
+ ...accountId ? { accountId } : {}
2859
+ });
2832
2860
  const result = await fetchCodexResponsesCompletion({
2861
+ ...options?.noRetries ? { maxAttempts: 1 } : {},
2833
2862
  agentConfig,
2834
2863
  accessToken,
2835
2864
  ...accountId ? { accountId } : {},
@@ -2837,7 +2866,8 @@ var resolveCodexOAuthTransport = async (ctx) => {
2837
2866
  model: agentConfig.model || "gpt-5.6-sol",
2838
2867
  messages,
2839
2868
  stream: false,
2840
- ...tools.length > 0 ? { tools } : {}
2869
+ ...tools.length > 0 ? { tools } : {},
2870
+ ...options?.reasoning_effort ? { reasoning_effort: options.reasoning_effort } : {}
2841
2871
  },
2842
2872
  sessionKey: resolveSessionKey({ dialogId: options?.dialogId }),
2843
2873
  signal: options?.signal,
@@ -2846,7 +2876,8 @@ var resolveCodexOAuthTransport = async (ctx) => {
2846
2876
  fetchImpl: (url, init) => fetchWithTransientRetry(observedFetch, url, init, {
2847
2877
  // 内层退避也要能被本次请求的 signal 打断(见 abortableSleep 注释)。
2848
2878
  sleep: (ms) => abortableSleep(deps.sleep, ms, init?.signal ?? options?.signal),
2849
- loopbackRequest
2879
+ loopbackRequest,
2880
+ ...options?.noRetries ? { maxAttempts: 1, coreDrainingMaxAttempts: 1 } : {}
2850
2881
  })
2851
2882
  });
2852
2883
  await recordLocalAvailability(result.status, result.body);
@@ -3233,7 +3264,11 @@ var resolveCursorTransport = async (ctx) => {
3233
3264
  }
3234
3265
  };
3235
3266
  };
3236
- const confirmExternalFileAccess = deps.confirmDestructiveAction;
3267
+ const hostConfirm = deps.confirmDestructiveAction;
3268
+ const confirmExternalFileAccess = hostConfirm ? async (request) => {
3269
+ const decision = await hostConfirm(request);
3270
+ return typeof decision === "boolean" ? decision : decision.approved === true;
3271
+ } : void 0;
3237
3272
  const cursorSearchWorkspace = (args) => internalSearchWorkspace({
3238
3273
  workspaceRoot,
3239
3274
  query: args.query,
@@ -3255,9 +3290,11 @@ var resolveCursorTransport = async (ctx) => {
3255
3290
  model: agentConfig.model || "cursor-default",
3256
3291
  systemPrompt: agentConfig.prompt?.trim() || void 0,
3257
3292
  tools,
3258
- executeTool: cursorExecuteTool,
3259
- searchWorkspace: cursorSearchWorkspace,
3260
- listWorkspaceEntries: cursorListWorkspaceEntries
3293
+ ...ctx.textOnly ? {} : {
3294
+ executeTool: cursorExecuteTool,
3295
+ searchWorkspace: cursorSearchWorkspace,
3296
+ listWorkspaceEntries: cursorListWorkspaceEntries
3297
+ }
3261
3298
  });
3262
3299
  return {
3263
3300
  model: agentConfig.model || "cursor-default",
@@ -3444,13 +3481,15 @@ var resolveDirectOpenAiCompatibleTransport = async (ctx) => {
3444
3481
  tools,
3445
3482
  fetchImpl: (url, init) => fetchWithTransientRetry(fetchImpl, url, init, {
3446
3483
  sleep: deps.sleep,
3447
- loopbackRequest
3484
+ loopbackRequest,
3485
+ ...options?.noRetries ? { maxAttempts: 1, coreDrainingMaxAttempts: 1 } : {}
3448
3486
  }),
3449
3487
  stream,
3450
3488
  sessionId: asOptionalTrimmedString(options?.dialogId) ?? asOptionalTrimmedString(agentConfig.key),
3451
3489
  onTextDelta: options?.onTextDelta,
3452
3490
  onReasoningDelta: options?.onReasoningDelta,
3453
3491
  signal: options?.signal,
3492
+ ...options?.noRetries ? { noRetries: true } : {},
3454
3493
  outboundDiagnostics: options?.requestId ? { callId: options.requestId } : void 0,
3455
3494
  onHttpResult: ({ status, body }) => recordLocalAvailability(status, body),
3456
3495
  ...resolveRequestApiKey ? { resolveApiKey: resolveRequestApiKey } : {}
@@ -3780,14 +3819,8 @@ var resolveOwnerOAuthProxyTransport = async (ctx) => {
3780
3819
  retryNetworkErrors: false,
3781
3820
  // 内层预算按「剩余总额度」裁剪:普通可重试状态码 ≤ 3 次、503
3782
3821
  // core_draining 排空窗口 ≤ 30 次,且都不超过剩余总额度。
3783
- maxAttempts: Math.min(
3784
- OWNER_PROXY_GENERIC_MAX_ATTEMPTS,
3785
- remaining
3786
- ),
3787
- coreDrainingMaxAttempts: Math.min(
3788
- OWNER_PROXY_CORE_DRAINING_MAX_ATTEMPTS,
3789
- remaining
3790
- ),
3822
+ maxAttempts: options?.noRetries ? 1 : Math.min(OWNER_PROXY_GENERIC_MAX_ATTEMPTS, remaining),
3823
+ coreDrainingMaxAttempts: options?.noRetries ? 1 : Math.min(OWNER_PROXY_CORE_DRAINING_MAX_ATTEMPTS, remaining),
3791
3824
  // 注意:计数必须**无条件**挂在 onRetry 上——若只在有 activityReporter
3792
3825
  // 时才挂,innerRetries / usedAttempts 会漏计,重试预算就形同虚设。
3793
3826
  onRetry: ({ attempt, maxAttempts, delayMs }) => {
@@ -3802,7 +3835,7 @@ var resolveOwnerOAuthProxyTransport = async (ctx) => {
3802
3835
  usedAttempts += 1;
3803
3836
  return { response, innerRetried: innerRetries > 0 };
3804
3837
  };
3805
- const res = await sendWithOwnerOriginMismatchRetry(
3838
+ const res = options?.noRetries ? (await send()).response : await sendWithOwnerOriginMismatchRetry(
3806
3839
  send,
3807
3840
  init.signal ?? void 0,
3808
3841
  deps.activityReporter ? ({ attempt, maxAttempts, delayMs }) => {
@@ -4005,6 +4038,7 @@ var resolvePlatformProxyTransport = async (ctx) => {
4005
4038
  {
4006
4039
  sleep: deps.sleep,
4007
4040
  loopbackRequest,
4041
+ ...options?.noRetries ? { maxAttempts: 1, coreDrainingMaxAttempts: 1 } : {},
4008
4042
  // A chat POST is not safe to replay after an ambiguous network or
4009
4043
  // gateway failure: the server/provider may already have accepted
4010
4044
  // it. The client only waits through the server's explicit pre-
@@ -4155,6 +4189,27 @@ async function resolveLocalProvider(ctx) {
4155
4189
  );
4156
4190
  }
4157
4191
 
4192
+ // packages/cli/client/providerResolveOverrides.ts
4193
+ function resolveProviderResolveOverrides(agentConfig, options) {
4194
+ if (!options) return agentConfig;
4195
+ const { toolNames, prompt } = options;
4196
+ if (toolNames === void 0 && prompt === void 0) return agentConfig;
4197
+ const current = agentConfig;
4198
+ return {
4199
+ ...agentConfig,
4200
+ ...toolNames !== void 0 ? {
4201
+ toolNames,
4202
+ exposedToolNames: toolNames,
4203
+ toolSurface: { ...current.toolSurface, finalToolNames: toolNames },
4204
+ runScopedToolSurface: {
4205
+ ...current.runScopedToolSurface,
4206
+ finalToolNames: toolNames
4207
+ }
4208
+ } : {},
4209
+ ...prompt !== void 0 ? { prompt } : {}
4210
+ };
4211
+ }
4212
+
4158
4213
  // packages/cli/client/localRuntimePaths.ts
4159
4214
  import { dirname, extname, join } from "node:path";
4160
4215
  import { fileURLToPath } from "node:url";
@@ -4443,7 +4498,7 @@ function clipLocalWakeEvidence(value, max = 1200) {
4443
4498
  function buildLocalWakeDisplayText(args) {
4444
4499
  const failed = args.terminalStatus !== "done";
4445
4500
  const duration = typeof args.durationMs === "number" && args.durationMs >= 0 ? ` \xB7 ${Math.floor(args.durationMs / 6e4)}m${Math.floor(args.durationMs / 1e3) % 60}s` : "";
4446
- return `1 \u6761\u540E\u53F0 run \u5DF2\u5B8C\u6210 \xB7 ${failed ? "\u2717" : "\u2713"} ${args.label || "\u540E\u53F0 run"}${failed ? ` ${args.terminalStatus}` : ""}${duration}`;
4501
+ return `1 \u6761\u540E\u53F0 run \u5DF2\u7ED3\u675F \xB7 ${failed ? "\u2717" : "\u2713"} ${args.label || "\u540E\u53F0 run"} [${args.terminalStatus}]${duration}`;
4447
4502
  }
4448
4503
  function buildLocalParentWakeMessage(args) {
4449
4504
  return [
@@ -5940,21 +5995,27 @@ var INSTABOX_DEFAULT_BASE_URL = "https://api.instabox.sh/v1";
5940
5995
  var INSTABOX_MAX_EXEC_SECONDS = 600;
5941
5996
  var INSTABOX_MAX_STDIN_BYTES = 1024 * 1024;
5942
5997
  var SAFE_MESSAGE = {
5998
+ instabox_upload_failed: "Instabox file upload failed",
5999
+ instabox_recovery_failed: "Instabox recovery persistence or authority validation failed",
6000
+ instabox_recovery_unknown: "Instabox machine identity is unknown; manual reconciliation required",
5943
6001
  "instabox_invalid_config": "Rejected: instabox backend needs an apiKey and a templateId",
5944
6002
  "instabox_invalid_ticket": "Rejected: execution ticket cannot be satisfied by the instabox backend",
5945
6003
  "instabox_unsupported_request": "Request is not supported by the instabox backend",
5946
6004
  "instabox_lease_not_found": "Unknown execution lease",
5947
6005
  "instabox_lease_mismatch": "Lease does not match this backend or ticket",
5948
6006
  "instabox_lease_released": "Lease was already released",
6007
+ "instabox_lease_stopping": "Lease stop was requested; execution is fenced",
5949
6008
  "instabox_create_failed": "Instabox machine create failed",
5950
6009
  "instabox_create_unconfirmed": "Instabox machine create could not be confirmed",
5951
6010
  "instabox_exec_failed": "Instabox exec could not be completed",
6011
+ "instabox_delete_forbidden": "Instabox machine deletion is forbidden; machine was not cleaned up",
5952
6012
  "instabox_cleanup_pending": "Instabox machine delete could not be confirmed; cleanup is pending"
5953
6013
  };
5954
6014
  var InstaboxBackendError = class extends Error {
5955
- constructor(code, detail, cleanupPending = false, machineId, upstreamErrorCode) {
6015
+ constructor(code, detail, cleanupPending = false, machineId, upstreamErrorCode, recovery) {
5956
6016
  super(detail ? `${SAFE_MESSAGE[code]} (${detail})` : SAFE_MESSAGE[code]);
5957
6017
  this.machineId = machineId;
6018
+ this.recovery = recovery;
5958
6019
  this.name = "InstaboxBackendError";
5959
6020
  this.code = code;
5960
6021
  this.cleanupPending = cleanupPending;
@@ -5965,6 +6026,7 @@ var InstaboxBackendError = class extends Error {
5965
6026
  cleanupPending;
5966
6027
  upstreamErrorCode;
5967
6028
  };
6029
+ var INSTABOX_MAX_UPLOAD_BYTES = 5 * 1024 ** 3;
5968
6030
  var DEFAULT_OPERATION_WAIT_SECONDS = 20;
5969
6031
  var DEFAULT_POLL_INTERVAL_MS = 1e3;
5970
6032
  var DEFAULT_MAX_POLL_ATTEMPTS = 30;
@@ -6041,6 +6103,7 @@ var InstaboxBackend = class {
6041
6103
  #machineTimeoutSeconds;
6042
6104
  #createTimeoutMs;
6043
6105
  #deleteTimeoutMs;
6106
+ #stopTimeoutMs;
6044
6107
  #operationWaitSeconds;
6045
6108
  #pollIntervalMs;
6046
6109
  #maxPollAttempts;
@@ -6049,9 +6112,23 @@ var InstaboxBackend = class {
6049
6112
  #creationPlan;
6050
6113
  #freeOrgObservation;
6051
6114
  #billingPolicy;
6115
+ #deletionPolicy;
6052
6116
  #deleteMachineImpl;
6117
+ #recovery;
6053
6118
  #leases = /* @__PURE__ */ new Map();
6119
+ #recoveryWrites = /* @__PURE__ */ new WeakMap();
6054
6120
  constructor(options) {
6121
+ if (options.deletionPolicy !== void 0 && options.deletionPolicy !== "legacy" && options.deletionPolicy !== "forbid") {
6122
+ throw new InstaboxBackendError("instabox_invalid_config", "invalid deletion policy");
6123
+ }
6124
+ this.#deletionPolicy = options.deletionPolicy ?? "legacy";
6125
+ if (options.recovery) {
6126
+ const a = options.recovery.authority;
6127
+ if (this.#deletionPolicy !== "forbid" || !options.creationPlan || !options.recovery.accountId?.trim() || !a?.ownerUserId?.trim() || !a.ticketId?.trim() || !a.grantId?.trim() || !Number.isSafeInteger(a.generation) || a.generation < 0) {
6128
+ throw new InstaboxBackendError("instabox_invalid_config", "invalid recovery binding");
6129
+ }
6130
+ this.#recovery = { ...options.recovery, authority: structuredClone(a) };
6131
+ }
6055
6132
  const apiKey = options.apiKey?.trim() ?? "";
6056
6133
  const templateId = options.templateId?.trim() ?? "";
6057
6134
  if (!apiKey || !templateId) {
@@ -6077,11 +6154,21 @@ var InstaboxBackend = class {
6077
6154
  ""
6078
6155
  );
6079
6156
  this.#now = options.now ?? Date.now;
6080
- this.#fetch = options.fetchImpl ?? ((url, init) => globalThis.fetch(url, init));
6157
+ this.#fetch = options.fetchImpl ?? ((url, init) => {
6158
+ const { rawBody, ...request } = init;
6159
+ return globalThis.fetch(url, {
6160
+ ...request,
6161
+ ...rawBody === void 0 ? {} : { body: rawBody }
6162
+ });
6163
+ });
6081
6164
  this.#sleep = options.sleepImpl ?? ((ms) => new Promise((resolve5) => setTimeout(resolve5, ms)));
6082
6165
  this.#machineTimeoutSeconds = options.machineTimeoutSeconds ?? 1800;
6083
6166
  this.#createTimeoutMs = options.createTimeoutMs ?? 18e4;
6084
6167
  this.#deleteTimeoutMs = options.deleteTimeoutMs ?? 12e4;
6168
+ this.#stopTimeoutMs = options.stopTimeoutMs ?? 12e4;
6169
+ if (!Number.isFinite(this.#stopTimeoutMs) || this.#stopTimeoutMs <= 0) {
6170
+ throw new InstaboxBackendError("instabox_invalid_config");
6171
+ }
6085
6172
  this.#operationWaitSeconds = options.operationWaitSeconds ?? DEFAULT_OPERATION_WAIT_SECONDS;
6086
6173
  this.#pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;
6087
6174
  this.#maxPollAttempts = options.maxPollAttempts ?? DEFAULT_MAX_POLL_ATTEMPTS;
@@ -6103,6 +6190,15 @@ var InstaboxBackend = class {
6103
6190
  * 成功时刻(不采信 202 响应时间,那是「已受理」不是「可用」)。
6104
6191
  */
6105
6192
  async prepare(ticket) {
6193
+ const context = {};
6194
+ try {
6195
+ return await this.#prepare(ticket, context);
6196
+ } catch (error) {
6197
+ if (context.record) throw this.#withRecovery(error, context.record);
6198
+ throw error;
6199
+ }
6200
+ }
6201
+ async #prepare(ticket, context) {
6106
6202
  if (ticket.version !== 1 || !ticket.ticketId || !ticket.grantId) {
6107
6203
  throw new InstaboxBackendError("instabox_invalid_ticket");
6108
6204
  }
@@ -6116,23 +6212,61 @@ var InstaboxBackend = class {
6116
6212
  }
6117
6213
  }
6118
6214
  const machineName = plan?.name ?? buildInstaboxMachineName(ticket.ticketId, ticket.agentKey);
6215
+ const createBody = plan ? {
6216
+ name: plan.name,
6217
+ templateId: plan.templateId,
6218
+ orgId: plan.orgId,
6219
+ vcpus: plan.vcpus,
6220
+ memMiB: plan.memMiB
6221
+ } : {
6222
+ name: machineName,
6223
+ templateId: this.#templateId,
6224
+ timeoutSeconds: this.#machineTimeoutSeconds
6225
+ };
6226
+ const createKey2 = buildInstaboxCreateIdempotencyKey(ticket.ticketId);
6227
+ if (this.#recovery && plan) {
6228
+ const authority = this.#recovery.authority;
6229
+ if (ticket.ticketId !== authority.ticketId || ticket.grantId !== authority.grantId || ticket.callerUserId !== authority.ownerUserId) {
6230
+ throw new InstaboxBackendError("instabox_recovery_failed");
6231
+ }
6232
+ const expectedSpec = this.#freeOrgObservation.allowedSpecs.find(
6233
+ (s) => s.vcpus === plan.vcpus && s.memMiB === plan.memMiB
6234
+ );
6235
+ context.record = {
6236
+ version: 1,
6237
+ recordId: crypto.randomUUID(),
6238
+ revision: 0,
6239
+ ...authority,
6240
+ accountId: this.#recovery.accountId,
6241
+ provider: "instabox",
6242
+ baseUrl: this.#baseUrl,
6243
+ plan: structuredClone(plan),
6244
+ billingPolicy: this.#billingPolicy,
6245
+ persistentDiskGiB: expectedSpec.persistentDiskGiB,
6246
+ create: {
6247
+ method: "POST",
6248
+ path: "/machines",
6249
+ body: JSON.stringify(createBody),
6250
+ idempotencyKey: createKey2,
6251
+ requestedAt,
6252
+ state: "submitted-unknown"
6253
+ },
6254
+ stop: { intent: false, accepted: false }
6255
+ };
6256
+ await this.#saveRecovery(context.record);
6257
+ }
6119
6258
  const created = await this.#call({
6120
6259
  method: "POST",
6121
6260
  path: "/machines",
6122
- idempotencyKey: buildInstaboxCreateIdempotencyKey(ticket.ticketId),
6123
- body: plan ? {
6124
- name: plan.name,
6125
- templateId: plan.templateId,
6126
- orgId: plan.orgId,
6127
- vcpus: plan.vcpus,
6128
- memMiB: plan.memMiB
6129
- // Ordinary API keys cannot change free maxRunMinutes. Do not send it.
6130
- } : {
6131
- name: machineName,
6132
- templateId: this.#templateId,
6133
- timeoutSeconds: this.#machineTimeoutSeconds
6134
- }
6261
+ idempotencyKey: createKey2,
6262
+ body: createBody
6135
6263
  });
6264
+ if (context.record) {
6265
+ context.record.machineId = readString2(asRecord(created.payload)?.machineId) ?? void 0;
6266
+ context.record.createOperationId = readString2(asRecord(created.payload)?.id) ?? void 0;
6267
+ if (isSuccess(created.status)) context.record.create.state = "responded";
6268
+ await this.#saveRecovery(context.record);
6269
+ }
6136
6270
  if (!isSuccess(created.status)) {
6137
6271
  const upstreamCode = extractInstaboxErrorCode(created.payload);
6138
6272
  let detail = `create HTTP ${created.status}`;
@@ -6205,6 +6339,7 @@ var InstaboxBackend = class {
6205
6339
  if (this.#billingPolicy === "free-only" && machine.maxRunMinutes !== 480) mismatches.push("maxRunMinutes mismatch");
6206
6340
  if (mismatches.length > 0) {
6207
6341
  const reason = mismatches.join("; ");
6342
+ this.#assertDeletionAllowed(machineId, reason);
6208
6343
  try {
6209
6344
  if (this.#deleteMachineImpl) {
6210
6345
  await this.#deleteMachineImpl(machineId);
@@ -6250,6 +6385,7 @@ var InstaboxBackend = class {
6250
6385
  const usageBaselineRunningMs = baseline === null ? null : Math.round(baseline.runningSeconds * 1e3);
6251
6386
  const leaseId = `${machineId}:${ticket.ticketId}`;
6252
6387
  this.#leases.set(leaseId, {
6388
+ recovery: context.record,
6253
6389
  machineId,
6254
6390
  ticketId: ticket.ticketId,
6255
6391
  grantId: ticket.grantId,
@@ -6258,7 +6394,9 @@ var InstaboxBackend = class {
6258
6394
  createOperationId: operationId,
6259
6395
  usageBaselineRunningMs,
6260
6396
  releasedAt: null,
6261
- releaseOutcome: null
6397
+ releaseOutcome: null,
6398
+ stopState: null,
6399
+ stopAccepted: false
6262
6400
  });
6263
6401
  return {
6264
6402
  leaseId,
@@ -6269,6 +6407,7 @@ var InstaboxBackend = class {
6269
6407
  readableRoots: [...ticket.filesystem.readableRoots],
6270
6408
  writableRoots: [...ticket.filesystem.writableRoots],
6271
6409
  metadata: {
6410
+ ...context.record ? { recoveryRecordId: context.record.recordId } : {},
6272
6411
  machineId,
6273
6412
  machineName,
6274
6413
  templateId: this.#templateId,
@@ -6279,11 +6418,92 @@ var InstaboxBackend = class {
6279
6418
  }
6280
6419
  };
6281
6420
  }
6421
+ /** Official OpenAPI: upload-url is on the API's own origin, then PUT raw
6422
+ * bytes with the signed token and NO API credential. No redirect is followed.
6423
+ * Caller retains ownership of bytes and must not mutate them until completion.
6424
+ * Provider follows target symlinks: lexical /workspace validation is not an OS
6425
+ * containment guarantee. Deliver source before executing untrusted code. */
6426
+ async uploadFile(lease, input) {
6427
+ const entry = this.#requireEntry(lease);
6428
+ const checkLease = () => {
6429
+ if (entry.releasedAt !== null) throw new InstaboxBackendError("instabox_lease_released");
6430
+ if (entry.stopState !== null) throw new InstaboxBackendError("instabox_lease_stopping");
6431
+ };
6432
+ const fail5 = () => new InstaboxBackendError("instabox_upload_failed");
6433
+ checkLease();
6434
+ if (!input || typeof input.path !== "string" || !input.path.startsWith("/workspace/") || input.path.endsWith("/") || input.path.split("/").some((p, i) => i > 0 && (!p || p === "." || p === "..")) || /[\\\x00-\x1f\x7f]/.test(input.path) || !(input.bytes instanceof Uint8Array) || input.bytes.byteLength > INSTABOX_MAX_UPLOAD_BYTES || !input.signal || !Number.isFinite(input.deadlineAt)) throw fail5();
6435
+ let base;
6436
+ try {
6437
+ base = new URL(this.#baseUrl);
6438
+ } catch {
6439
+ throw fail5();
6440
+ }
6441
+ if (base.protocol !== "https:" || base.username || base.password || base.search || base.hash) throw fail5();
6442
+ const controller = new AbortController();
6443
+ const remaining = input.deadlineAt - this.#now();
6444
+ if (input.signal.aborted || remaining <= 0) throw fail5();
6445
+ const started = performance.now();
6446
+ const timeLeft = () => Math.min(input.deadlineAt - this.#now(), remaining - (performance.now() - started));
6447
+ let timer;
6448
+ let onAbort;
6449
+ const interrupted = new Promise((_resolve, reject) => {
6450
+ onAbort = () => {
6451
+ controller.abort();
6452
+ reject(fail5());
6453
+ };
6454
+ input.signal.addEventListener("abort", onAbort, { once: true });
6455
+ const tick = () => {
6456
+ const left = timeLeft();
6457
+ if (left <= 0) onAbort();
6458
+ else timer = setTimeout(tick, Math.min(left, 2147483647));
6459
+ };
6460
+ tick();
6461
+ });
6462
+ const check = () => {
6463
+ checkLease();
6464
+ if (input.signal.aborted || controller.signal.aborted || timeLeft() <= 0) throw fail5();
6465
+ };
6466
+ try {
6467
+ check();
6468
+ const response = await Promise.race([this.#call({
6469
+ method: "POST",
6470
+ path: `/machines/${encodeURIComponent(entry.machineId)}/files/upload-url`,
6471
+ body: { path: input.path, parents: true },
6472
+ signal: controller.signal,
6473
+ redirect: "error"
6474
+ }), interrupted]);
6475
+ check();
6476
+ const payload = asRecord(response.payload);
6477
+ if (response.status !== 201 || !payload || payload.method !== "PUT" || payload.path !== input.path || typeof payload.url !== "string" || typeof payload.expiresAt !== "string" || !Number.isSafeInteger(payload.maxBytes) || payload.maxBytes < input.bytes.byteLength || payload.maxBytes > INSTABOX_MAX_UPLOAD_BYTES || !Number.isFinite(Date.parse(payload.expiresAt)) || Date.parse(payload.expiresAt) <= this.#now()) throw fail5();
6478
+ const url = new URL(payload.url);
6479
+ if (url.protocol !== "https:" || url.origin !== base.origin || url.username || url.password || url.hash || url.pathname !== `${base.pathname}/machines/${encodeURIComponent(entry.machineId)}/files` || !url.searchParams.get("token")) throw fail5();
6480
+ check();
6481
+ const uploaded = await Promise.race([this.#fetch(url.href, {
6482
+ method: "PUT",
6483
+ headers: { "Content-Type": "application/octet-stream" },
6484
+ rawBody: input.bytes,
6485
+ signal: controller.signal,
6486
+ redirect: "error"
6487
+ }), interrupted]);
6488
+ check();
6489
+ if (uploaded.redirected || !isSuccess(uploaded.status)) throw fail5();
6490
+ } catch (error) {
6491
+ checkLease();
6492
+ throw fail5();
6493
+ } finally {
6494
+ if (timer !== void 0) clearTimeout(timer);
6495
+ if (onAbort) input.signal.removeEventListener("abort", onAbort);
6496
+ controller.abort();
6497
+ }
6498
+ }
6282
6499
  async execute(lease, request, onEvent) {
6283
6500
  const entry = this.#requireEntry(lease);
6284
6501
  if (entry.releasedAt !== null) {
6285
6502
  throw new InstaboxBackendError("instabox_lease_released");
6286
6503
  }
6504
+ if (entry.stopState !== null) {
6505
+ throw entry.recovery ? this.#withRecovery(new InstaboxBackendError("instabox_lease_stopping"), entry.recovery) : new InstaboxBackendError("instabox_lease_stopping");
6506
+ }
6287
6507
  if (request.kind !== "command") {
6288
6508
  throw new InstaboxBackendError(
6289
6509
  "instabox_unsupported_request",
@@ -6302,11 +6522,17 @@ var InstaboxBackend = class {
6302
6522
  const executionId = `${entry.machineId}:${this.#now().toString(36)}`;
6303
6523
  const startedAt = this.#now();
6304
6524
  onEvent?.({ type: "started", executionId, at: startedAt });
6525
+ if (entry.stopState !== null) {
6526
+ throw entry.recovery ? this.#withRecovery(new InstaboxBackendError("instabox_lease_stopping"), entry.recovery) : new InstaboxBackendError("instabox_lease_stopping");
6527
+ }
6305
6528
  const response = await this.#call({
6306
6529
  method: "POST",
6307
6530
  path: `/machines/${encodeURIComponent(entry.machineId)}/exec`,
6308
6531
  body: { cmd, timeoutSeconds, ...stdin === void 0 ? {} : { stdin } }
6309
6532
  });
6533
+ if (entry.stopState !== null) {
6534
+ throw entry.recovery ? this.#withRecovery(new InstaboxBackendError("instabox_lease_stopping"), entry.recovery) : new InstaboxBackendError("instabox_lease_stopping");
6535
+ }
6310
6536
  if (!isSuccess(response.status)) {
6311
6537
  throw new InstaboxBackendError(
6312
6538
  "instabox_exec_failed",
@@ -6341,6 +6567,9 @@ var InstaboxBackend = class {
6341
6567
  usage: { wallMs: Math.max(0, this.#now() - startedAt) }
6342
6568
  });
6343
6569
  onEvent?.({ type: "exited", executionId, exitCode });
6570
+ if (entry.stopState !== null) {
6571
+ throw entry.recovery ? this.#withRecovery(new InstaboxBackendError("instabox_lease_stopping"), entry.recovery) : new InstaboxBackendError("instabox_lease_stopping");
6572
+ }
6344
6573
  return {
6345
6574
  executionId,
6346
6575
  ok: !timedOut && exitCode === 0,
@@ -6353,6 +6582,114 @@ var InstaboxBackend = class {
6353
6582
  }
6354
6583
  };
6355
6584
  }
6585
+ /**
6586
+ * Official contract verified from https://api.instabox.sh/v1/openapi.json:
6587
+ * POST /v1/machines/{id}/stop -> 202 Operation (not a Machine).
6588
+ * GET /v1/machines/{id} -> Machine; only state=stopped confirms shutdown.
6589
+ * No release/delete, and no inference from operation success, 404 or desiredState.
6590
+ * State is process-local. Restart recovery requires a durable lease/machine binding,
6591
+ * stop intent, idempotency key and reconciliation API owned by the caller.
6592
+ * A caller publishing an already-resolved execute result must also fence its
6593
+ * own run generation/cancellation state: this backend cannot revoke that result.
6594
+ * The request deadline bounds observation, not transport cancellation; an HTTP
6595
+ * request may settle late, so retries keep the same stop idempotency key.
6596
+ */
6597
+ async stop(lease) {
6598
+ const entry = this.#requireEntry(lease);
6599
+ if (entry.releasedAt !== null) {
6600
+ throw new InstaboxBackendError("instabox_lease_released");
6601
+ }
6602
+ if (entry.stopState === "stopped") {
6603
+ return { ok: true, state: "stopped", machineId: entry.machineId };
6604
+ }
6605
+ if (entry.stopTask) return entry.stopTask;
6606
+ entry.stopState = "unknown";
6607
+ const task = this.#stopEntry(entry);
6608
+ entry.stopTask = task;
6609
+ try {
6610
+ return await task;
6611
+ } catch (error) {
6612
+ if (entry.recovery) throw this.#withRecovery(error, entry.recovery);
6613
+ throw error;
6614
+ } finally {
6615
+ entry.stopTask = void 0;
6616
+ }
6617
+ }
6618
+ async #stopEntry(entry) {
6619
+ const startedAt = this.#now();
6620
+ const wallStartedAt = Date.now();
6621
+ const remaining = () => this.#stopTimeoutMs - Math.max(
6622
+ this.#now() - startedAt,
6623
+ Date.now() - wallStartedAt
6624
+ );
6625
+ if (entry.recovery) {
6626
+ entry.recovery.stop.intent = true;
6627
+ entry.recovery.stop.idempotencyKey ??= `nolo-stop-${entry.machineId}`;
6628
+ await this.#saveRecovery(entry.recovery);
6629
+ }
6630
+ const result = async (state2) => {
6631
+ if (entry.recovery) {
6632
+ entry.recovery.stop.lastObservedState = state2;
6633
+ await this.#saveRecovery(entry.recovery);
6634
+ }
6635
+ entry.stopState = state2;
6636
+ return { ok: state2 === "stopped", state: state2, machineId: entry.machineId };
6637
+ };
6638
+ const path = `/machines/${encodeURIComponent(entry.machineId)}`;
6639
+ let state = "unknown";
6640
+ for (let attempt = 0; attempt < this.#maxPollAttempts && remaining() > 0; attempt += 1) {
6641
+ const observed = await this.#call({ method: "GET", path, timeoutMs: remaining() });
6642
+ const machine = observed.status === 200 ? asRecord(observed.payload) : null;
6643
+ if (machine?.id !== entry.machineId || typeof machine.state !== "string") {
6644
+ return result("unknown");
6645
+ }
6646
+ if (machine.state === "stopped") return result("stopped");
6647
+ if (machine.state !== "running" && machine.state !== "stopping") {
6648
+ return result("unknown");
6649
+ }
6650
+ state = entry.stopAccepted || machine.state === "stopping" ? "pending" : "unknown";
6651
+ if (!entry.stopAccepted && machine.state === "running" && remaining() > 0) {
6652
+ const accepted = await this.#call({
6653
+ method: "POST",
6654
+ path: `${path}/stop`,
6655
+ idempotencyKey: entry.recovery?.stop.idempotencyKey ?? `nolo-stop-${entry.machineId}`,
6656
+ timeoutMs: remaining(),
6657
+ // Runs even when the HTTP response arrives after the observation deadline.
6658
+ onResult: entry.recovery ? async (response) => {
6659
+ if (response.status === 202) {
6660
+ entry.stopAccepted = true;
6661
+ entry.recovery.stop.accepted = true;
6662
+ const operation2 = asRecord(response.payload);
6663
+ if (this.#isStopOperation(operation2, entry)) {
6664
+ entry.recovery.stop.operationId = readString2(operation2?.id);
6665
+ }
6666
+ await this.#saveRecovery(entry.recovery);
6667
+ }
6668
+ } : void 0
6669
+ });
6670
+ if (accepted.status === 202) entry.stopAccepted = true;
6671
+ const operation = asRecord(accepted.payload);
6672
+ if (accepted.status !== 202 || !this.#isStopOperation(operation, entry)) {
6673
+ return result("unknown");
6674
+ }
6675
+ state = "pending";
6676
+ }
6677
+ if (attempt + 1 < this.#maxPollAttempts && remaining() > 0 && this.#pollIntervalMs > 0) {
6678
+ let timer;
6679
+ try {
6680
+ await Promise.race([
6681
+ this.#sleep(Math.min(this.#pollIntervalMs, remaining())),
6682
+ new Promise((resolve5) => {
6683
+ timer = setTimeout(resolve5, remaining());
6684
+ })
6685
+ ]);
6686
+ } finally {
6687
+ if (timer !== void 0) clearTimeout(timer);
6688
+ }
6689
+ }
6690
+ }
6691
+ return result(state);
6692
+ }
6356
6693
  /**
6357
6694
  * DELETE 只是「已受理」;必须轮询 delete operation 到 `succeeded` 才算清理完成。
6358
6695
  * 未确认一律抛 `instabox_cleanup_pending`(`cleanupPending: true`),lease 保持可重试。
@@ -6360,6 +6697,12 @@ var InstaboxBackend = class {
6360
6697
  */
6361
6698
  async release(lease, reason) {
6362
6699
  const entry = this.#requireEntry(lease);
6700
+ try {
6701
+ this.#assertDeletionAllowed(entry.machineId);
6702
+ } catch (error) {
6703
+ if (entry.recovery) throw this.#withRecovery(error, entry.recovery);
6704
+ throw error;
6705
+ }
6363
6706
  if (entry.releasedAt !== null) {
6364
6707
  return entry.releaseOutcome ?? { ok: true };
6365
6708
  }
@@ -6408,6 +6751,145 @@ var InstaboxBackend = class {
6408
6751
  });
6409
6752
  return this.#confirmRelease(entry, providerUsageMs);
6410
6753
  }
6754
+ #assertDeletionAllowed(machineId, detail) {
6755
+ if (this.#deletionPolicy === "forbid") {
6756
+ throw new InstaboxBackendError("instabox_delete_forbidden", detail, true, machineId);
6757
+ }
6758
+ }
6759
+ #isStopOperation(operation, entry) {
6760
+ const id = readString2(operation?.id);
6761
+ const knownId = entry.recovery?.stop.operationId;
6762
+ return id !== null && operation?.machineId === entry.machineId && (!entry.recovery || operation.type === "stop") && ["queued", "running", "succeeded", "failed"].includes(String(operation.state)) && (knownId === void 0 || knownId === id);
6763
+ }
6764
+ #withRecovery(error, record) {
6765
+ const known = error instanceof InstaboxBackendError ? error : void 0;
6766
+ return new InstaboxBackendError(
6767
+ known?.code ?? "instabox_recovery_failed",
6768
+ void 0,
6769
+ true,
6770
+ record.machineId,
6771
+ known?.upstreamErrorCode,
6772
+ {
6773
+ recordId: record.recordId,
6774
+ machineId: record.machineId,
6775
+ createOperationId: record.createOperationId,
6776
+ stopOperationId: record.stop.operationId,
6777
+ machineState: record.machineId ? "known" : "unknown"
6778
+ }
6779
+ );
6780
+ }
6781
+ async #saveRecovery(record) {
6782
+ const previous = this.#recoveryWrites.get(record) ?? Promise.resolve();
6783
+ const task = previous.then(async () => {
6784
+ const revision = record.revision;
6785
+ const next = structuredClone({ ...record, revision: revision + 1 });
6786
+ try {
6787
+ await this.#recovery.store.save(next, revision);
6788
+ record.revision = next.revision;
6789
+ } catch {
6790
+ throw this.#withRecovery(new InstaboxBackendError("instabox_recovery_failed"), record);
6791
+ }
6792
+ });
6793
+ this.#recoveryWrites.set(record, task);
6794
+ await task;
6795
+ }
6796
+ /** Authority must come from authenticated host context, never from a request body. */
6797
+ async restoreForStop(recordId, authority) {
6798
+ if (typeof recordId !== "string" || !/^[a-zA-Z0-9_-]{1,128}$/.test(recordId)) {
6799
+ throw new InstaboxBackendError("instabox_recovery_failed");
6800
+ }
6801
+ try {
6802
+ return await this.#restoreForStop(recordId, authority);
6803
+ } catch (error) {
6804
+ if (error instanceof InstaboxBackendError && error.recovery) throw error;
6805
+ throw new InstaboxBackendError(
6806
+ "instabox_recovery_failed",
6807
+ void 0,
6808
+ true,
6809
+ void 0,
6810
+ void 0,
6811
+ { recordId, machineState: "unknown" }
6812
+ );
6813
+ }
6814
+ }
6815
+ async #restoreForStop(recordId, authority) {
6816
+ const binding = this.#recovery;
6817
+ if (!binding || !/^[a-zA-Z0-9_-]{1,128}$/.test(recordId)) {
6818
+ throw new InstaboxBackendError("instabox_recovery_failed");
6819
+ }
6820
+ let record;
6821
+ try {
6822
+ record = await binding.store.load(recordId);
6823
+ } catch {
6824
+ throw new InstaboxBackendError("instabox_recovery_failed");
6825
+ }
6826
+ if (!record || record.version !== 1 || record.recordId !== recordId || !Number.isSafeInteger(record.revision) || record.revision < 1 || record.provider !== "instabox" || record.accountId !== binding.accountId || record.baseUrl !== this.#baseUrl || ![authority, binding.authority].every((a) => a.ticketId === record.ticketId && a.grantId === record.grantId && a.generation === record.generation && a.ownerUserId === record.ownerUserId) || !record.plan || !this.#creationPlan || ![
6827
+ "orgId",
6828
+ "name",
6829
+ "templateId",
6830
+ "vcpus",
6831
+ "memMiB",
6832
+ "maxRunMinutes",
6833
+ "snapshotId",
6834
+ "persistentDiskGiB",
6835
+ "rootDiskGiB"
6836
+ ].every(
6837
+ (key) => record.plan[key] === this.#creationPlan[key]
6838
+ ) || record.billingPolicy !== this.#billingPolicy || !Number.isSafeInteger(record.persistentDiskGiB) || record.persistentDiskGiB < 0 || record.create?.method !== "POST" || record.create.path !== "/machines" || record.create.idempotencyKey !== buildInstaboxCreateIdempotencyKey(record.ticketId) || !Number.isFinite(record.create.requestedAt) || !["submitted-unknown", "responded"].includes(record.create.state) || typeof record.stop?.intent !== "boolean" || typeof record.stop.accepted !== "boolean" || record.stop.accepted && !record.stop.intent || record.stop.intent && record.stop.idempotencyKey !== `nolo-stop-${record.machineId}`) {
6839
+ throw new InstaboxBackendError("instabox_recovery_failed");
6840
+ }
6841
+ const plan = this.#creationPlan;
6842
+ const expectedSpec = this.#freeOrgObservation?.allowedSpecs.filter(
6843
+ (spec2) => spec2.vcpus === plan.vcpus && spec2.memMiB === plan.memMiB
6844
+ );
6845
+ if (expectedSpec?.length !== 1 || expectedSpec[0].persistentDiskGiB !== record.persistentDiskGiB) {
6846
+ throw new InstaboxBackendError("instabox_recovery_failed");
6847
+ }
6848
+ const body = JSON.stringify({
6849
+ name: plan.name,
6850
+ templateId: plan.templateId,
6851
+ orgId: plan.orgId,
6852
+ vcpus: plan.vcpus,
6853
+ memMiB: plan.memMiB
6854
+ });
6855
+ if (record.create.body !== body) throw new InstaboxBackendError("instabox_recovery_failed");
6856
+ if (!readString2(record.machineId)) {
6857
+ throw this.#withRecovery(new InstaboxBackendError("instabox_recovery_unknown"), record);
6858
+ }
6859
+ const machineId = record.machineId;
6860
+ const response = await this.#call({ method: "GET", path: `/machines/${encodeURIComponent(machineId)}` });
6861
+ const machine = asRecord(response.payload);
6862
+ const spec = asRecord(machine?.spec);
6863
+ if (response.status !== 200 || machine?.id !== machineId || machine.orgId !== plan.orgId || machine.name !== plan.name || asRecord(machine.template)?.id !== plan.templateId || spec?.vcpus !== plan.vcpus || spec?.memMiB !== plan.memMiB || spec?.persistentDiskGiB !== record.persistentDiskGiB || typeof machine.free !== "boolean" || record.billingPolicy === "free-only" && (machine.free !== true || machine.maxRunMinutes !== plan.maxRunMinutes)) {
6864
+ throw this.#withRecovery(new InstaboxBackendError("instabox_recovery_failed"), record);
6865
+ }
6866
+ const leaseId = `${machineId}:${record.ticketId}`;
6867
+ if (this.#leases.has(leaseId)) throw this.#withRecovery(new InstaboxBackendError("instabox_lease_mismatch"), record);
6868
+ this.#leases.set(leaseId, {
6869
+ recovery: structuredClone(record),
6870
+ machineId,
6871
+ ticketId: record.ticketId,
6872
+ grantId: record.grantId,
6873
+ requestedAt: record.create.requestedAt,
6874
+ readyAt: this.#now(),
6875
+ createOperationId: record.createOperationId ?? "",
6876
+ usageBaselineRunningMs: null,
6877
+ releasedAt: null,
6878
+ releaseOutcome: null,
6879
+ stopState: "unknown",
6880
+ stopAccepted: record.stop.accepted
6881
+ });
6882
+ return {
6883
+ leaseId,
6884
+ backendId: INSTABOX_BACKEND_ID,
6885
+ ticketId: record.ticketId,
6886
+ grantId: record.grantId,
6887
+ createdAt: this.#now(),
6888
+ readableRoots: [],
6889
+ writableRoots: [],
6890
+ metadata: { machineId, recoveryRecordId: recordId, stopOnly: true }
6891
+ };
6892
+ }
6411
6893
  #confirmRelease(entry, providerUsageMs) {
6412
6894
  const outcome = providerUsageMs === void 0 ? { ok: true } : { ok: true, providerUsageMs };
6413
6895
  entry.releasedAt = this.#now();
@@ -6494,6 +6976,25 @@ var InstaboxBackend = class {
6494
6976
  return segments.join(" && ");
6495
6977
  }
6496
6978
  async #call(args) {
6979
+ if (args.timeoutMs !== void 0) {
6980
+ if (args.timeoutMs <= 0) return { status: 0, payload: null, transportError: "Timeout" };
6981
+ let timer;
6982
+ try {
6983
+ return await Promise.race([
6984
+ this.#call({ ...args, timeoutMs: void 0 }),
6985
+ new Promise((resolve5) => {
6986
+ timer = setTimeout(() => resolve5({ status: 0, payload: null, transportError: "Timeout" }), args.timeoutMs);
6987
+ })
6988
+ ]);
6989
+ } finally {
6990
+ if (timer !== void 0) clearTimeout(timer);
6991
+ }
6992
+ }
6993
+ if (args.onResult) {
6994
+ const response = await this.#call({ ...args, onResult: void 0 });
6995
+ await args.onResult(response);
6996
+ return response;
6997
+ }
6497
6998
  const headers = {
6498
6999
  "X-API-Key": this.#apiKey,
6499
7000
  Accept: "application/json"
@@ -6504,8 +7005,11 @@ var InstaboxBackend = class {
6504
7005
  const response = await this.#fetch(`${this.#baseUrl}${args.path}`, {
6505
7006
  method: args.method,
6506
7007
  headers,
7008
+ ...args.signal ? { signal: args.signal } : {},
7009
+ ...args.redirect ? { redirect: args.redirect } : {},
6507
7010
  ...args.body !== void 0 ? { body: JSON.stringify(args.body) } : {}
6508
7011
  });
7012
+ if (args.redirect === "error" && response.redirected) return { status: 0, payload: null };
6509
7013
  let payload = null;
6510
7014
  if (typeof response?.json === "function") {
6511
7015
  try {
@@ -7434,6 +7938,11 @@ function createCliStartAgentRunExecutor(deps = {}) {
7434
7938
  allowCredentialConcurrency: effectiveAllowCredentialConcurrency
7435
7939
  });
7436
7940
  const dodCommands = Array.isArray(args.dodCommands) ? args.dodCommands.filter((c) => typeof c === "string" && c.trim().length > 0).map((c) => c.trim()) : typeof args.dod === "string" && args.dod.trim().length > 0 ? [args.dod.trim()] : Array.isArray(args.dod) ? args.dod.filter((c) => typeof c === "string" && c.trim().length > 0).map((c) => c.trim()) : void 0;
7941
+ const dispatchedBudget = resolveDispatchedSubtaskBudget({
7942
+ ...typeof args.maxToolCalls === "number" ? { maxToolCalls: args.maxToolCalls } : {},
7943
+ ...typeof args.maxWallClockMs === "number" ? { maxWallClockMs: args.maxWallClockMs } : {},
7944
+ env: deps.env
7945
+ });
7437
7946
  const { runId, batchId: resolvedBatchId } = await spawnLocalBackgroundRun(
7438
7947
  {
7439
7948
  rawArgs,
@@ -7451,6 +7960,7 @@ function createCliStartAgentRunExecutor(deps = {}) {
7451
7960
  ...dodCommands && dodCommands.length > 0 ? { dodCommands } : {},
7452
7961
  cwd: requestedCwd ?? deps.cwd ?? process.cwd(),
7453
7962
  message,
7963
+ subtaskBudgetLimits: dispatchedBudget.limits,
7454
7964
  ...args.ephemeral === true ? { ephemeral: true } : {},
7455
7965
  output: noopOutput
7456
7966
  },
@@ -7511,7 +8021,11 @@ function createCliStartAgentRunExecutor(deps = {}) {
7511
8021
  };
7512
8022
  };
7513
8023
  }
7514
- async function spawnContinuationRun(reconciled, userInput, deps) {
8024
+ function controlMessageLabels(queuedCount) {
8025
+ const labels = agentRunCardLabels().controlMessage;
8026
+ return { ...labels, queued: queuedCount === void 0 ? labels.queued : labels.enqueued(queuedCount) };
8027
+ }
8028
+ async function spawnContinuationRun(reconciled, message, userInput, deps) {
7515
8029
  if (!reconciled.ephemeral && !reconciled.dialogId) {
7516
8030
  throw new Error(t("agentRunTool.noDialogToContinue"));
7517
8031
  }
@@ -7546,19 +8060,13 @@ async function spawnContinuationRun(reconciled, userInput, deps) {
7546
8060
  // 续跑继承原 run 的凭证组(同一 agent),供并发扇出守卫判定。
7547
8061
  ...reconciled.credentialGroup ? { credentialGroup: reconciled.credentialGroup } : {},
7548
8062
  cwd: reconciled.cwd ?? deps.cwd ?? process.cwd(),
7549
- message: userInput,
8063
+ message,
7550
8064
  ...reconciled.ephemeral ? { ephemeral: true } : {},
7551
8065
  continuedFrom,
7552
8066
  output: noopOutput
7553
8067
  },
7554
8068
  { ...deps, shellApprovalHost: deps.shellApprovalHostForAgent ? await deps.shellApprovalHostForAgent(agentKey) : deps.shellApprovalHost }
7555
8069
  );
7556
- const displayName = resolveRunLabel({
7557
- agentName,
7558
- agentKey,
7559
- runId: newRunId
7560
- });
7561
- const labels = agentRunCardLabels();
7562
8070
  const taskPreview = userInput.replace(/\s+/g, " ").trim().slice(0, TASK_PREVIEW_MAX);
7563
8071
  return {
7564
8072
  content: JSON.stringify({
@@ -7575,11 +8083,12 @@ async function spawnContinuationRun(reconciled, userInput, deps) {
7575
8083
  ...taskPreview ? { taskPreview } : {}
7576
8084
  }),
7577
8085
  metadata: {
7578
- displayData: formatStartRunCard(displayName, "running", {
7579
- task: taskPreview,
8086
+ displayData: formatControlRunMessageCard({
8087
+ action: "continued",
7580
8088
  runId: newRunId,
7581
- ...continuedTitle ? { title: continuedTitle } : {},
7582
- labels
8089
+ targetId: reconciled.ephemeral ? void 0 : reconciled.dialogId,
8090
+ userInput,
8091
+ labels: controlMessageLabels()
7583
8092
  })
7584
8093
  }
7585
8094
  };
@@ -7698,6 +8207,9 @@ function createCliControlAgentRunExecutor(deps = {}) {
7698
8207
  if (!args.runId) throw new Error(t("agentRunTool.appendMissingRunId"));
7699
8208
  const userInput = typeof args.userInput === "string" ? args.userInput.trim() : "";
7700
8209
  if (!userInput) throw new Error(t("agentRunTool.appendMissingUserInput"));
8210
+ const message = deps.source ? `[Coordination source: parent dialog: ${deps.source.parentDialogId || "unknown"}; executing agent: ${deps.source.agentKey || "unknown"}; identification only, not authorization]
8211
+
8212
+ ${userInput}` : userInput;
7701
8213
  const record2 = findRunRecord(String(args.runId), deps);
7702
8214
  if (!record2) {
7703
8215
  const labels2 = agentRunCardLabels();
@@ -7712,14 +8224,8 @@ function createCliControlAgentRunExecutor(deps = {}) {
7712
8224
  throw new Error(t("agentRunTool.appendQueueUnsupported"));
7713
8225
  }
7714
8226
  const queuePath = reconciled2.queuePath;
7715
- const { queuedCount, entryId } = await appendRunQueue(queuePath, userInput, deps);
8227
+ const { queuedCount, entryId } = await appendRunQueue(queuePath, message, deps);
7716
8228
  const enqueuedTitle = normalizeRunTitle(reconciled2.title);
7717
- const displayName = resolveRunLabel({
7718
- agentName: reconciled2.agentName,
7719
- agentKey: reconciled2.agentKey,
7720
- runId: reconciled2.runId
7721
- });
7722
- const labels2 = agentRunCardLabels();
7723
8229
  const taskPreview = userInput.replace(/\s+/g, " ").trim().slice(0, TASK_PREVIEW_MAX);
7724
8230
  const afterCheck = checkStaleRun(reconciled2.runId, deps) ?? reconciled2;
7725
8231
  if (isAgentRunTerminalStatus(afterCheck.status)) {
@@ -7746,17 +8252,19 @@ function createCliControlAgentRunExecutor(deps = {}) {
7746
8252
  ...taskPreview ? { taskPreview } : {}
7747
8253
  }),
7748
8254
  metadata: {
7749
- displayData: formatStartRunCard(displayName, afterCheck.status, {
7750
- task: `[consumed] ${taskPreview}`,
8255
+ displayData: formatControlRunMessageCard({
8256
+ action: "consumed",
7751
8257
  runId: reconciled2.runId,
7752
- ...enqueuedTitle ? { title: enqueuedTitle } : {},
7753
- labels: labels2
8258
+ targetId: reconciled2.ephemeral ? void 0 : afterCheck.dialogId ?? reconciled2.dialogId,
8259
+ userInput,
8260
+ labels: controlMessageLabels()
7754
8261
  })
7755
8262
  }
7756
8263
  };
7757
8264
  }
7758
- const mergedMessage = remainingEntries.map((e) => e.text).join("\n\n");
7759
- return await spawnContinuationRun(afterCheck, mergedMessage, deps);
8265
+ const mergedMessage = remainingEntries.length === 1 ? remainingEntries[0].text : remainingEntries.map((entry, index) => `--- queued message ${index + 1} of ${remainingEntries.length} (${entry.text.length} characters) ---
8266
+ ${entry.text}`).join("\n\n");
8267
+ return await spawnContinuationRun(afterCheck, mergedMessage, userInput, deps);
7760
8268
  }
7761
8269
  return {
7762
8270
  content: JSON.stringify({
@@ -7771,16 +8279,17 @@ function createCliControlAgentRunExecutor(deps = {}) {
7771
8279
  ...taskPreview ? { taskPreview } : {}
7772
8280
  }),
7773
8281
  metadata: {
7774
- displayData: formatStartRunCard(displayName, "running", {
7775
- task: `[enqueued ${queuedCount}] ${taskPreview}`,
8282
+ displayData: formatControlRunMessageCard({
8283
+ action: "queued",
7776
8284
  runId: reconciled2.runId,
7777
- ...enqueuedTitle ? { title: enqueuedTitle } : {},
7778
- labels: labels2
8285
+ targetId: reconciled2.ephemeral ? void 0 : reconciled2.dialogId,
8286
+ userInput,
8287
+ labels: controlMessageLabels(queuedCount)
7779
8288
  })
7780
8289
  }
7781
8290
  };
7782
8291
  }
7783
- return await spawnContinuationRun(reconciled2, userInput, deps);
8292
+ return await spawnContinuationRun(reconciled2, message, userInput, deps);
7784
8293
  }
7785
8294
  if (action !== "status" && action !== "stop" && action !== "wait") {
7786
8295
  throw new Error(t("agentRunTool.unknownAction", String(action)));
@@ -8294,7 +8803,14 @@ function buildLocalToolExecutors(args) {
8294
8803
  workspaceRoot: args.workspaceRoot,
8295
8804
  commandTimeoutMs: args.commandTimeoutMs,
8296
8805
  commandOutputLimit: args.commandOutputLimit,
8297
- ...args.confirmDestructiveAction ? { confirmExternalFileAccess: args.confirmDestructiveAction } : {}
8806
+ ...args.confirmDestructiveAction ? {
8807
+ // 边界换算:文件访问确认只关心「批没批」,宿主代执行(hostResult)
8808
+ // 由 execShell 的 capability 通道消费。类型仍取共享契约,不另写 union。
8809
+ confirmExternalFileAccess: async (request) => {
8810
+ const decision = await args.confirmDestructiveAction(request);
8811
+ return typeof decision === "boolean" ? decision : decision.approved === true;
8812
+ }
8813
+ } : {}
8298
8814
  }),
8299
8815
  ...buildServerPlatformToolExecutors({
8300
8816
  env: args.env,
@@ -8456,6 +8972,7 @@ function buildLocalToolExecutors(args) {
8456
8972
  currentAgentKey: args.agentKey
8457
8973
  }),
8458
8974
  controlAgentRun: createCliControlAgentRunExecutor({
8975
+ source: { parentDialogId: args.sourceParentDialogId, agentKey: args.agentKey },
8459
8976
  shellApprovalHostForAgent: args.shellApprovalHostForAgent,
8460
8977
  cwd: args.workspaceRoot,
8461
8978
  cliEntrypoint: args.cliEntrypoint,
@@ -10053,7 +10570,7 @@ async function createLocalDockerWorkload(args) {
10053
10570
  }
10054
10571
  const createLifecycle = args.createLifecycle ?? (async () => {
10055
10572
  const [{ DockerWorkloadLifecycle, createDockerBindingAuthorizer }, accounts] = await Promise.all([
10056
- import("./workloadLifecycle-4BEQHMSD.js"),
10573
+ import("./workloadLifecycle-4C42SVBD.js"),
10057
10574
  import("./accountResolver-4LKIHEKL.js")
10058
10575
  ]);
10059
10576
  const resolveAccount = args.resolveAccount ?? accounts.createDockerAccountResolver({
@@ -11866,6 +12383,7 @@ function buildTokenDialogIndexOps(args) {
11866
12383
  }
11867
12384
 
11868
12385
  // packages/cli/client/localRuntimeDialog.ts
12386
+ var import_format = __toESM(require_format(), 1);
11869
12387
  import { appendFileSync, mkdirSync as mkdirSync3 } from "fs";
11870
12388
  import { homedir } from "os";
11871
12389
  import { join as join7 } from "path";
@@ -12066,7 +12584,7 @@ async function writeLocalTokenRecord(args) {
12066
12584
  })
12067
12585
  ]);
12068
12586
  ops.push({ type: "put", key: recordKey, value: tokenRecord });
12069
- const dateKey = format(timestamp, "yyyy-MM-dd");
12587
+ const dateKey = (0, import_format.default)(timestamp, "yyyy-MM-dd");
12070
12588
  const statsKey = createTokenStatsKey(args.userId, dateKey);
12071
12589
  await runKeyed(statsKey, async () => {
12072
12590
  let existingStats = null;
@@ -12082,6 +12600,15 @@ async function writeLocalTokenRecord(args) {
12082
12600
  input_tokens: prepared.usage.input_tokens,
12083
12601
  output_tokens: prepared.usage.output_tokens,
12084
12602
  cost: prepared.tokenData.cost,
12603
+ // Cache counters are parsed by normalizeUsage already; dropping them
12604
+ // here made every CLI-local day bucket report cacheRead=0 even when the
12605
+ // provider did report hits (the detail records carried the real value).
12606
+ cache_read_input_tokens: prepared.usage.cache_read_input_tokens,
12607
+ cache_creation_input_tokens: prepared.usage.cache_creation_input_tokens,
12608
+ // DayStats.agents exists and every other writer feeds it; the CLI-local
12609
+ // path was the only one leaving every agent bucket empty.
12610
+ agentId: prepared.tokenData.agentId,
12611
+ entry_path: prepared.tokenData.entry_path,
12085
12612
  billingCategory: prepared.tokenData.billable ?? false ? "platform" : "subscription"
12086
12613
  });
12087
12614
  const statsRecord = { ...newStats, id: statsKey, type: "token" };
@@ -12328,6 +12855,8 @@ function parseTitleUpdatedAtMs(existingDialog) {
12328
12855
  }
12329
12856
 
12330
12857
  // packages/cli/client/localRuntimeAdapter.ts
12858
+ var legacyHitNotified = /* @__PURE__ */ new Set();
12859
+ var sessionFallbackNotified = false;
12331
12860
  var LOCAL_INSTABOX_TOOL_NAMES = [
12332
12861
  EXECUTION_SHELL_TOOL,
12333
12862
  ...INSTABOX_FILE_TOOL_NAMES
@@ -12490,7 +13019,6 @@ async function recordLocalAvailabilityForAgent(args) {
12490
13019
  return typeof entry?.nextAvailableAt === "number" ? entry.nextAvailableAt : action.nextAvailableAt;
12491
13020
  }
12492
13021
  const record = current;
12493
- if (action.kind === "clear" && !("nextAvailableAt" in record)) return void 0;
12494
13022
  const next = { ...record };
12495
13023
  let effectiveNextAvailableAt;
12496
13024
  if (action.kind === "mark") {
@@ -12501,7 +13029,30 @@ async function recordLocalAvailabilityForAgent(args) {
12501
13029
  next.nextAvailableAt = merged;
12502
13030
  effectiveNextAvailableAt = merged;
12503
13031
  } else {
13032
+ const hadCooldown = "nextAvailableAt" in record;
12504
13033
  delete next.nextAvailableAt;
13034
+ const observedAt = now();
13035
+ const snapshot = extractQuotaSnapshot(
13036
+ typeof agentConfig?.provider === "string" ? agentConfig.provider : void 0,
13037
+ status,
13038
+ void 0,
13039
+ args.body,
13040
+ observedAt
13041
+ );
13042
+ const previous = record.quota && typeof record.quota === "object" ? record.quota : void 0;
13043
+ const hasFreshSnapshot = Boolean(snapshot) && (!previous?.observedAt || previous.observedAt <= observedAt);
13044
+ if (!hadCooldown && !hasFreshSnapshot) return void 0;
13045
+ if (hasFreshSnapshot) {
13046
+ const windows = new Map(
13047
+ (Array.isArray(previous?.windows) ? previous.windows : []).map((window) => [window.scope, window])
13048
+ );
13049
+ for (const window of snapshot?.windows ?? []) windows.set(window.scope, window);
13050
+ next.quota = {
13051
+ ...previous,
13052
+ windows: [...windows.values()],
13053
+ observedAt
13054
+ };
13055
+ }
12505
13056
  }
12506
13057
  await store.write(key, next).catch(() => void 0);
12507
13058
  if (action.kind !== "mark") return void 0;
@@ -12695,7 +13246,7 @@ function createCliLocalRuntimeAdapter(deps) {
12695
13246
  emitRunIsolationNotice(fact, { runId });
12696
13247
  try {
12697
13248
  const { writeFileSync: writeFileSync4, mkdirSync: mkdirSync4 } = await import("node:fs");
12698
- const { resolveRunsDir: resolveRunsDir2 } = await import("./agentRunControl-AF7BMR22.js");
13249
+ const { resolveRunsDir: resolveRunsDir2 } = await import("./agentRunControl-TAMHJQSR.js");
12699
13250
  recordLocalRunExecutionIsolation({
12700
13251
  runId,
12701
13252
  runsDir: resolveRunsDir2(deps.env),
@@ -12720,7 +13271,7 @@ function createCliLocalRuntimeAdapter(deps) {
12720
13271
  dockerWorkloadReleased = true;
12721
13272
  dockerWorkloadLoad = null;
12722
13273
  if (loaded) {
12723
- const { resolveRunsDir: resolveRunsDir2 } = await import("./agentRunControl-AF7BMR22.js");
13274
+ const { resolveRunsDir: resolveRunsDir2 } = await import("./agentRunControl-TAMHJQSR.js");
12724
13275
  const exportRunDiff = deps.exportDockerRunDiffArtifact ?? exportDockerRunDiffArtifact;
12725
13276
  const warn = (message) => process.stderr.write(`[nolo] ${message}
12726
13277
  `);
@@ -12803,6 +13354,7 @@ function createCliLocalRuntimeAdapter(deps) {
12803
13354
  let runtimeToolExecutionLimits = {};
12804
13355
  const buildCurrentToolExecutors = (agentKey) => buildLocalToolExecutors({
12805
13356
  workspaceRoot,
13357
+ sourceParentDialogId: deps.parentDialogId,
12806
13358
  env: deps.env,
12807
13359
  fetchImpl,
12808
13360
  ...deps.chromeConnectorClient ? { chromeConnectorClient: deps.chromeConnectorClient } : {},
@@ -12841,9 +13393,34 @@ function createCliLocalRuntimeAdapter(deps) {
12841
13393
  ...runtimeToolExecutionLimits
12842
13394
  });
12843
13395
  let localToolExecutors = buildCurrentToolExecutors();
12844
- const credentialBroker = createFileCredentialBroker({
12845
- migration: { enableLegacyMigration: true }
13396
+ const credentialBroker = createHostCredentialBrokerChain({
13397
+ strict: createStrictHostCredentialBroker(),
13398
+ // 会话内存:无钥匙串时贴 key 仍可用(本进程有效,不落盘)。
13399
+ session: getSharedSessionCredentialBroker(),
13400
+ // 读旧只读回退:既有 agent 的凭据还在旧 file broker 里,只读命中即可用,不迁移。
13401
+ legacy: createFileCredentialBroker({
13402
+ migration: { enableLegacyMigration: true }
13403
+ }),
13404
+ notifySessionFallback: () => {
13405
+ if (sessionFallbackNotified) return;
13406
+ sessionFallbackNotified = true;
13407
+ process.stderr.write(
13408
+ `[nolo] Warning: ${CREDENTIAL_STORE_SESSION_FALLBACK_WARNING}
13409
+ `
13410
+ );
13411
+ },
13412
+ notifyLegacyHit: (ref) => {
13413
+ const key = `legacy-hit:${ref}`;
13414
+ if (legacyHitNotified.has(key)) return;
13415
+ legacyHitNotified.add(key);
13416
+ process.stderr.write(
13417
+ `[nolo] Warning: \u51ED\u636E "${ref}" \u6765\u81EA\u9057\u7559\u672C\u5730\u660E\u6587\u5B58\u50A8\uFF08\u53EA\u8BFB\u56DE\u9000\uFF09\u3002\u5EFA\u8BAE\u91CD\u65B0\u5F55\u5165\u8BE5 API key \u4EE5\u8FC1\u5165\u7CFB\u7EDF\u5B89\u5168\u533A\u3002
13418
+ `
13419
+ );
13420
+ }
12846
13421
  });
13422
+ let nextSettingsRemoteAttempt = 0;
13423
+ let settingsDiagnosticEmitted = false;
12847
13424
  const adapterBase = {
12848
13425
  host: "cli",
12849
13426
  capabilities: [
@@ -12859,10 +13436,23 @@ function createCliLocalRuntimeAdapter(deps) {
12859
13436
  const sharedStore = await getOrCreateSharedStore(deps);
12860
13437
  if (userId) {
12861
13438
  try {
12862
- const settingsRecord = await sharedStore.read(
12863
- createUserKey.settings(userId),
12864
- { remote: false }
12865
- );
13439
+ const settingsKey = createUserKey.settings(userId);
13440
+ let settingsRecord = await sharedStore.read(settingsKey, { remote: false });
13441
+ if (!settingsRecord && Date.now() >= nextSettingsRemoteAttempt) {
13442
+ nextSettingsRemoteAttempt = Date.now() + 3e4;
13443
+ let unavailable = false;
13444
+ settingsRecord = await sharedStore.read(settingsKey, {
13445
+ onRemoteUnavailable: () => {
13446
+ unavailable = true;
13447
+ }
13448
+ });
13449
+ if (!settingsRecord && !settingsDiagnosticEmitted) {
13450
+ process.stderr.write(`[nolo] Account skill settings ${unavailable ? "unavailable" : "not found"}; preferences unknown, retrying on a later load.
13451
+ `);
13452
+ settingsDiagnosticEmitted = true;
13453
+ }
13454
+ }
13455
+ if (settingsRecord) settingsDiagnosticEmitted = false;
12866
13456
  if (settingsRecord && typeof settingsRecord === "object") {
12867
13457
  skillPreferences = {
12868
13458
  ...Object.prototype.hasOwnProperty.call(settingsRecord, "enabledSkills") ? { enabledSkills: settingsRecord.enabledSkills } : {},
@@ -12871,6 +13461,10 @@ function createCliLocalRuntimeAdapter(deps) {
12871
13461
  }
12872
13462
  systemBuiltinSkills = settingsRecord && typeof settingsRecord === "object" ? settingsRecord.systemBuiltinSkills ?? null : null;
12873
13463
  } catch {
13464
+ if (!settingsDiagnosticEmitted) {
13465
+ process.stderr.write("[nolo] Account skill settings unavailable; preferences unknown, retrying on a later load.\n");
13466
+ settingsDiagnosticEmitted = true;
13467
+ }
12874
13468
  }
12875
13469
  }
12876
13470
  const enabledSkills = resolveUserEnabledSkills(skillPreferences).sort();
@@ -13037,8 +13631,7 @@ function createCliLocalRuntimeAdapter(deps) {
13037
13631
  loopbackRequest
13038
13632
  })
13039
13633
  }),
13040
- resolveProviderBase: async (agentConfig) => {
13041
- const nowMs = now();
13634
+ resolveProviderBase: async (agentConfig, options) => {
13042
13635
  const serverUrl = asOptionalTrimmedString(deps.env.NOLO_SERVER) ?? "https://us.nolo.chat";
13043
13636
  const authToken = asOptionalTrimmedString(deps.env.AUTH_TOKEN);
13044
13637
  let ownerOriginExecution;
@@ -13134,18 +13727,6 @@ function createCliLocalRuntimeAdapter(deps) {
13134
13727
  let recordLocalAvailability = async () => ownerRouteLeakGuard("availability write");
13135
13728
  let apiKeyRefResolver = () => ownerRouteLeakGuard("apiKeyRefResolver read");
13136
13729
  if (!ownerOriginExecution) {
13137
- const credentialKeyForGate = resolveCredentialKeyWithFallback(
13138
- agentConfig
13139
- );
13140
- const gateEntry = credentialKeyForGate ? await readEffectiveCredentialEntry(credentialKeyForGate, deps.env, nowMs).catch(
13141
- () => void 0
13142
- ) : void 0;
13143
- const credentialCooldownAt = gateEntry?.nextAvailableAt;
13144
- const agentLevelNextAvailableAt = agentConfig.nextAvailableAt;
13145
- const effectiveNextAvailableAt = typeof credentialCooldownAt === "number" ? mergeAvailabilityDeadline(
13146
- agentLevelNextAvailableAt,
13147
- credentialCooldownAt
13148
- ) : agentLevelNextAvailableAt;
13149
13730
  recordLocalAvailability = (status, body) => recordLocalAvailabilityForAgent({
13150
13731
  deps,
13151
13732
  agentConfig,
@@ -13153,24 +13734,6 @@ function createCliLocalRuntimeAdapter(deps) {
13153
13734
  body,
13154
13735
  now
13155
13736
  }).then(() => void 0);
13156
- const gateDecision = resolveCooldownGate(
13157
- {
13158
- nextAvailableAt: effectiveNextAvailableAt,
13159
- lastProbeAt: gateEntry?.lastProbeAt
13160
- },
13161
- nowMs
13162
- );
13163
- if (gateDecision === "blocked") {
13164
- throw new Error(
13165
- `agent temporarily unavailable until ${new Date(Number(effectiveNextAvailableAt)).toISOString()}`
13166
- );
13167
- }
13168
- const activeKeyForGate = gateEntry?.matchedKey || credentialKeyForGate;
13169
- if (gateDecision === "probe" && activeKeyForGate) {
13170
- await recordCredentialProbe(activeKeyForGate, deps.env, nowMs).catch(
13171
- () => void 0
13172
- );
13173
- }
13174
13737
  const legacyCredentialMigration = {
13175
13738
  enableLegacyMigration: true
13176
13739
  };
@@ -13200,14 +13763,18 @@ function createCliLocalRuntimeAdapter(deps) {
13200
13763
  return null;
13201
13764
  }
13202
13765
  } : void 0;
13766
+ const resolvedAgentConfig = resolveProviderResolveOverrides(agentConfig, options?.textOnly ? { ...options, toolNames: [] } : options);
13203
13767
  return resolveLocalProvider({
13204
- agentConfig,
13768
+ agentConfig: resolvedAgentConfig,
13205
13769
  deps,
13206
13770
  fetchImpl,
13207
13771
  loopbackRequest,
13208
13772
  now,
13209
13773
  workspaceRoot,
13210
- additionalToolNames,
13774
+ ...options?.textOnly ? { textOnly: true } : {},
13775
+ // 请求空工具面时连 host 追加项(readPastedText)也一并去掉,
13776
+ // 否则 `toolNames: []` 的契约会被 additionalToolNames 刺破。
13777
+ additionalToolNames: options?.textOnly || options?.toolNames !== void 0 ? [] : additionalToolNames,
13211
13778
  activeAgentToolNames,
13212
13779
  localToolExecutors,
13213
13780
  buildProviderOpenAiTools,
@@ -13434,10 +14001,12 @@ function createCliLocalRuntimeAdapter(deps) {
13434
14001
  get compactionSummaryFallback() {
13435
14002
  return cliAutoCompactionSummaryFallback;
13436
14003
  },
13437
- resolveProvider: async (agentConfig) => {
14004
+ resolveProvider: async (agentConfig, options) => {
13438
14005
  const provider = await adapterBase.resolveProviderBase(
13439
- agentConfig
14006
+ agentConfig,
14007
+ options
13440
14008
  );
14009
+ if (options?.textOnly) return { ...provider, textOnly: true };
13441
14010
  return shouldUsePlatformChatProvider(deps.env, agentConfig) ? withProviderStreamRetry(provider, {
13442
14011
  ...deps,
13443
14012
  retryOnly: isBusyProviderStreamError
@@ -13490,13 +14059,6 @@ export {
13490
14059
  buildLocalPolicyToolNames,
13491
14060
  buildServerPlatformOpenAiTools,
13492
14061
  summarizeEndpoint,
13493
- BUILTIN_NOLO_AGENT_KEY,
13494
- resolveLocalUserId,
13495
- isBuiltinNoloAgentRef,
13496
- isBuiltinNoloAgentConfig,
13497
- withResolvedRuntimeToolSurface,
13498
- extractLastUserText,
13499
- localTurnHasSubjectRefs,
13500
14062
  resolveAuthToken2 as resolveAuthToken,
13501
14063
  resolveFileWriteGateEnabled,
13502
14064
  isMachineBoundLocalhostCustomProvider,