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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +3 -3
  2. package/{_executeModel-ANY4SIAS.js → _executeModel-CKT6RGTL.js} +58 -49
  3. package/{action-Q4W5JPI5.js → action-76JX3JX3.js} +9 -8
  4. package/{addContentAction-O25HFR37.js → addContentAction-V3NAZRTJ.js} +9 -7
  5. package/{addDialogAgentAction-GH7AUPPB.js → addDialogAgentAction-RZOAF46K.js} +11 -9
  6. package/{agentDeleteCommand-JWIKNWWI.js → agentDeleteCommand-VN7NPXQ4.js} +37 -32
  7. package/{agentEmailCommands-PL22BEU5.js → agentEmailCommands-F2TNAV4A.js} +73 -65
  8. package/{agentGrantCommands-2LEZDADN.js → agentGrantCommands-R3VQEZJR.js} +1 -1
  9. package/{agentListCommands-6NR7AQEK.js → agentListCommands-OSM2ANI3.js} +78 -39
  10. package/{agentMachineCommands-TASPU6OA.js → agentMachineCommands-MTPWYVRV.js} +38 -33
  11. package/{agentPullCommand-M552CYSI.js → agentPullCommand-N7L2CT7L.js} +2 -2
  12. package/agentRecordCommands-VWAWTVVC.js +122 -0
  13. package/agentRunCommand-PLZOBNVK.js +149 -0
  14. package/{agentRunControl-4GHHSXFZ.js → agentRunControl-WECMOO6O.js} +13 -6
  15. package/{agentRuntimeLocal-PCJJ56J2.js → agentRuntimeLocal-XCJLRWQE.js} +35 -28
  16. package/{agentSlice-KYLDUSNN.js → agentSlice-F6DOP4IW.js} +10 -9
  17. package/{appDeleteCommands-WLHMJAVT.js → appDeleteCommands-3BCFTRFJ.js} +37 -32
  18. package/{appDeployCommands-CKON7N2E.js → appDeployCommands-B4GMHCYA.js} +37 -32
  19. package/{appDeployStatusCommands-PXRLDASH.js → appDeployStatusCommands-4MN36WIG.js} +37 -32
  20. package/{appGetCommands-RAB5RM4M.js → appGetCommands-4GJIEUAX.js} +37 -32
  21. package/{appListCommands-GU57FB62.js → appListCommands-CHU53GSX.js} +37 -32
  22. package/{authCommand-QOPOEYEK.js → authCommand-WOTWLJNF.js} +38 -32
  23. package/{authCommands-SBQVTD6V.js → authCommands-ILTBI6JV.js} +8 -6
  24. package/{chatQueueReduxAdapter-5O2WLITN.js → chatQueueReduxAdapter-HNSQXNIR.js} +29 -24
  25. package/{chunk-WL3UOGYO.js → chunk-22BTGNSP.js} +151 -155
  26. package/{chunk-7CH6U3FL.js → chunk-2GRGFCF6.js} +2 -4
  27. package/{chunk-V4KZGLOI.js → chunk-2HPRMEEZ.js} +3059 -1079
  28. package/{chunk-UNZDCI3O.js → chunk-2KDR4CWE.js} +35 -4
  29. package/{chunk-VRZIH5JO.js → chunk-2PGGC63K.js} +1 -1
  30. package/{chunk-T27IEBNQ.js → chunk-2QDDKFG5.js} +74 -1
  31. package/{chunk-7K5VMB4Q.js → chunk-37QVS7BU.js} +21 -8
  32. package/{chunk-UITMHBVK.js → chunk-37XDGCY7.js} +1 -1
  33. package/chunk-3BLB7QKO.js +433 -0
  34. package/{chunk-NQ4N4IGO.js → chunk-3JQ2NRYU.js} +33 -10
  35. package/{chunk-UW4INMD2.js → chunk-3JWKQDA4.js} +2 -2
  36. package/{chunk-IKTHA3JH.js → chunk-3QGUVVX5.js} +2 -2
  37. package/{chunk-WHVQA7PJ.js → chunk-45YO6H7P.js} +97 -35
  38. package/chunk-4C4ST2YE.js +20015 -0
  39. package/{chunk-32I5RVMY.js → chunk-4NJEIGBQ.js} +5 -5
  40. package/{chunk-KUUTWU4I.js → chunk-5ZYA4JJ3.js} +90 -22
  41. package/chunk-6YTOJY35.js +352 -0
  42. package/{chunk-INXBNYCG.js → chunk-7A3RRUCQ.js} +155 -12
  43. package/{chunk-GV35EHNA.js → chunk-7O7KH4X5.js} +1262 -971
  44. package/{chunk-Y7LNKP32.js → chunk-7UF7CQ6B.js} +4 -6
  45. package/{chunk-2BWU4ORW.js → chunk-AQMVUA7N.js} +2 -1
  46. package/{chunk-LA4IDAK7.js → chunk-AVE2YR4F.js} +1056 -3591
  47. package/{chunk-TI5BCZCH.js → chunk-B7DXRX7F.js} +59 -121
  48. package/chunk-BFU6C242.js +66 -0
  49. package/{chunk-FA4SY4F5.js → chunk-BYEJ7K2Z.js} +1 -1
  50. package/chunk-BYXBJQAS.js +0 -0
  51. package/{chunk-IA3A5373.js → chunk-C3FZR5EC.js} +1 -1
  52. package/{chunk-IWUMSAQF.js → chunk-CJCJF5XB.js} +26 -3
  53. package/{chunk-PAHILFNT.js → chunk-CP7VIDZ7.js} +4 -4
  54. package/{chunk-OYNDYVSE.js → chunk-CTCW7U7N.js} +1 -1
  55. package/{chunk-BJLYCOZK.js → chunk-D5XKNNUV.js} +135 -795
  56. package/{chunk-AV6KQCM5.js → chunk-DNNSCSA2.js} +19 -14
  57. package/{chunk-3AOLVADY.js → chunk-DVINR3PL.js} +1 -1
  58. package/{chunk-NI2BS6UD.js → chunk-DWUCB2A3.js} +1 -1
  59. package/{chunk-AA564GBL.js → chunk-DZZL7UBV.js} +1 -1
  60. package/{chunk-6FGXGFAH.js → chunk-E6RGHPDR.js} +6 -4
  61. package/chunk-EDKF7RX4.js +30 -0
  62. package/{chunk-6SZ52ORL.js → chunk-ES6CVKVD.js} +24 -30
  63. package/{chunk-DQLYEGP7.js → chunk-FHAGENAS.js} +3 -4
  64. package/{chunk-56W233KG.js → chunk-FKFMIBTT.js} +5 -1
  65. package/{chunk-INZZJSQF.js → chunk-FZGV4FGK.js} +24 -12
  66. package/{chunk-D3JQPONH.js → chunk-GAL47RNP.js} +1 -1
  67. package/{chunk-6FQ2552G.js → chunk-HBPV76EK.js} +1085 -1150
  68. package/{chunk-LN3OQJGG.js → chunk-HLU5Q2GV.js} +4 -4
  69. package/{chunk-U2A47SVI.js → chunk-HQP7HJDL.js} +7 -7
  70. package/{chunk-H2G6JXTR.js → chunk-HQUORJTM.js} +1 -1
  71. package/{chunk-3Z3DXZBD.js → chunk-IYCUMIYS.js} +24 -20
  72. package/{chunk-7APQB6R6.js → chunk-JX5PJCWS.js} +8 -6
  73. package/{chunk-LYGNQHUW.js → chunk-JYYZCK2Z.js} +2 -4
  74. package/{chunk-PYKV6FSC.js → chunk-KWSQR2KK.js} +16 -31
  75. package/{chunk-VULELK4T.js → chunk-L7B47JXR.js} +37 -64
  76. package/{chunk-4NN3EK7H.js → chunk-LAFC3B2I.js} +1 -1
  77. package/{chunk-VRJUIUIY.js → chunk-LJKICKVC.js} +2 -2
  78. package/chunk-M3JEW6N6.js +193 -0
  79. package/chunk-MBOEV4L2.js +301 -0
  80. package/{chunk-QDHZCAH3.js → chunk-MMZ6ZTVO.js} +229 -74
  81. package/{chunk-JDSUTNYY.js → chunk-MP64VFGD.js} +2 -2
  82. package/{chunk-U5Z7LFZF.js → chunk-MXUDQZXQ.js} +47 -8
  83. package/chunk-N4G4PKQ6.js +23 -0
  84. package/{chunk-SVEUG45B.js → chunk-NHRQCXIQ.js} +0 -24
  85. package/{chunk-KXKQO4Q6.js → chunk-NTW5GWDM.js} +58 -1
  86. package/chunk-ONXOABJR.js +215 -0
  87. package/{chunk-BANYWEYY.js → chunk-OZX2IPKM.js} +8 -3
  88. package/{chunk-Q24S4NDF.js → chunk-P7OOB7QP.js} +1 -1
  89. package/{chunk-GLGD2JGY.js → chunk-PEZJEQAO.js} +7 -7
  90. package/{chunk-GBADO3SM.js → chunk-PQDIDWGX.js} +1 -1
  91. package/chunk-PSCNXBYA.js +11 -0
  92. package/chunk-QEFJJS2I.js +508 -0
  93. package/{chunk-757BGY6Y.js → chunk-QEW2MFDQ.js} +1 -1
  94. package/{chunk-SP3DPVBH.js → chunk-RDBARW6T.js} +8 -3
  95. package/{chunk-TNPCQNGQ.js → chunk-RJ2SAFB5.js} +83 -41
  96. package/{chunk-FGEYVPPR.js → chunk-RVWRKFUB.js} +8 -65
  97. package/{chunk-43CXXVJD.js → chunk-RXX4GDIH.js} +1 -1
  98. package/chunk-SEJ5OS6F.js +49 -0
  99. package/{chunk-MFI4FGHX.js → chunk-SOJM57FX.js} +5 -2
  100. package/{chunk-EKLRRZIN.js → chunk-SPAQ4PVV.js} +0 -5
  101. package/{chunk-L7NG2M6H.js → chunk-TRV2MIDW.js} +89 -74
  102. package/chunk-UAD2WT54.js +64 -0
  103. package/{chunk-RTLJUGQH.js → chunk-UZPQSVM6.js} +2 -2
  104. package/{chunk-3QJTD6DO.js → chunk-VMWYBIXG.js} +9 -7
  105. package/{chunk-ZHXJ6M7T.js → chunk-W7XHHYWM.js} +4 -0
  106. package/{chunk-5WADL4O7.js → chunk-XAVSS3KE.js} +21 -3
  107. package/{chunk-CVT7L2WZ.js → chunk-XOKOSO35.js} +13 -22
  108. package/{chunk-6BYAXNH5.js → chunk-XTJTN3RW.js} +57 -4
  109. package/{chunk-T5HJEUQN.js → chunk-YCDWJX45.js} +1 -1
  110. package/{chunk-MRWGHF56.js → chunk-YDH3FDFQ.js} +12 -356
  111. package/{chunk-H4RYESI6.js → chunk-Z4QSJILV.js} +85 -13
  112. package/chunk-ZJ7UHBJS.js +89 -0
  113. package/{chunk-O5FLGN2L.js → chunk-ZRSJ3JEH.js} +6 -2
  114. package/{cliExecutor-BBUVQU4L.js → cliExecutor-HG3S345O.js} +1 -1
  115. package/{codingSkills-BCQXRZOI.js → codingSkills-VDXQYWX4.js} +2 -2
  116. package/contentThunks-7YG2ZYQC.js +73 -0
  117. package/{cooldownCommands-GI5NNWGL.js → cooldownCommands-BSCH2W7P.js} +2 -2
  118. package/{createAgentAutomationAction-UJLNFFFC.js → createAgentAutomationAction-PJQSCAIO.js} +32 -26
  119. package/createDialogAction-SFEJX6SP.js +64 -0
  120. package/{createPageAction-N3IYABHV.js → createPageAction-B7WRHOQO.js} +35 -28
  121. package/{dbSlice-D5CNGWPD.js → dbSlice-IBVOBVMS.js} +7 -6
  122. package/{deleteFile-44TUM34Y.js → deleteFile-FWP2PSBG.js} +4 -3
  123. package/{dialogCommands-35M6RBAC.js → dialogCommands-VL2X22QC.js} +38 -33
  124. package/{dialogSlice-KO7ADD7H.js → dialogSlice-ANMACABO.js} +29 -24
  125. package/{docCreateCommands-VXHZWQ3P.js → docCreateCommands-ITLGZ5YI.js} +40 -35
  126. package/{docDeleteCommands-4WFAJR6A.js → docDeleteCommands-LH3YNL4C.js} +37 -32
  127. package/{docReadCommands-OYREEFAR.js → docReadCommands-YAJ77F36.js} +36 -31
  128. package/{docStore-5BU76DFK.js → docStore-D4HGHPWI.js} +9 -33
  129. package/{docUpdateCommands-A7QERSME.js → docUpdateCommands-DQBOMH2G.js} +40 -35
  130. package/{fetchMessages-KZQVBXKY.js → fetchMessages-DRABNDPZ.js} +3 -3
  131. package/{getPricing-HAU62AFM.js → getPricing-NM3NUTAS.js} +5 -5
  132. package/handleSendMessageAction-DF2OABGW.js +675 -0
  133. package/index.js +79 -88
  134. package/{lib-2ZTNRXR4.js → lib-FRRS27KN.js} +63 -28
  135. package/{localDialogRead-NQ33HBSI.js → localDialogRead-PUQKFI73.js} +1 -1
  136. package/{localRuntimeAuthority-KQDAE64E.js → localRuntimeAuthority-R5UBODT3.js} +6 -4
  137. package/{localRuntimeDb-PF7CFKDL.js → localRuntimeDb-P37ZTX55.js} +1 -1
  138. package/{machineCommands-J43U3TX5.js → machineCommands-JXDYQ5LB.js} +309 -87
  139. package/{machineWsRunDispatch-Z2Z6STXZ.js → machineWsRunDispatch-3QHI7JX5.js} +67 -59
  140. package/memberThunks-VZI6G7YZ.js +640 -0
  141. package/{models-4QF4BJVY.js → models-FAMINFZ7.js} +2 -2
  142. package/package.json +3 -2
  143. package/{read-RGNPI5H2.js → read-2BYWW7AA.js} +4 -3
  144. package/{readDocTool-6ESWKTXD.js → readDocTool-LC3A7QTB.js} +1 -1
  145. package/{readlineWorkspace-YRPV6JPN.js → readlineWorkspace-KVZTEAHB.js} +4609 -2698
  146. package/{removeDialogAgentAction-JYT73FU2.js → removeDialogAgentAction-SFYZXHNK.js} +14 -12
  147. package/{runAgentClientLoop-5YM5WMAY.js → runAgentClientLoop-KGTEL7ZP.js} +60 -50
  148. package/{runtimeDoctorCommands-JKTTN723.js → runtimeDoctorCommands-CROTMULY.js} +7 -5
  149. package/{setDialogExtraReferencesAction-D564LMYQ.js → setDialogExtraReferencesAction-Q32RGFTA.js} +10 -8
  150. package/{setPrimaryDialogAgentAction-ACY3BLYA.js → setPrimaryDialogAgentAction-BFYJHUJS.js} +14 -12
  151. package/{settingSlice-MKI3MNZJ.js → settingSlice-IRUU4VFB.js} +8 -7
  152. package/{skillDiscovery-GPUDHDTZ.js → skillDiscovery-NTRLM6KP.js} +3 -3
  153. package/{spaceCommands-MY26V52L.js → spaceCommands-KNAYWMCZ.js} +40 -220
  154. package/{streamAgentChatTurn-XV5X5TNQ.js → streamAgentChatTurn-FLYPTXKZ.js} +140 -95
  155. package/{switchDialogAgentAction-CJ5H6SAR.js → switchDialogAgentAction-L2KOKCGG.js} +11 -9
  156. package/{tableCommands-R6WFRDYF.js → tableCommands-SUNTHAYX.js} +1 -1
  157. package/{toolApiClient-B2MFXMEG.js → toolApiClient-VGYUB4P5.js} +4 -2
  158. package/{tools-MIMELA2Y.js → tools-CVLUXK6P.js} +46 -38
  159. package/{tuiSummaryLlmCaller-XJ5BKNNS.js → tuiSummaryLlmCaller-F3DPFFZM.js} +20 -16
  160. package/{updateCommands-IYKLF3JX.js → updateCommands-AJYSD73Y.js} +2 -2
  161. package/{updateDialogTitleAction-EIZUSWHR.js → updateDialogTitleAction-HWJIZEIV.js} +33 -27
  162. package/agentRecordCommands-Z64TA63M.js +0 -114
  163. package/agentRunCommand-4QJQLPRW.js +0 -134
  164. package/agentSuperviseCommands-VB6BUS5H.js +0 -640
  165. package/chunk-6BGAQ3KR.js +0 -7081
  166. package/chunk-FD36SCCD.js +0 -105
  167. package/chunk-J3UALFHL.js +0 -370
  168. package/chunk-RU5D3B22.js +0 -230
  169. package/chunk-YBV6QJKM.js +0 -441
  170. package/createDialogAction-TJCX6GUE.js +0 -58
  171. package/handleSendMessageAction-OSGQJQ45.js +0 -406
  172. package/spaceSlice-JUIXC365.js +0 -127
@@ -1,6 +1,6 @@
1
1
  import {
2
- generateRunReport
3
- } from "./chunk-J3UALFHL.js";
2
+ findPotentialSecrets
3
+ } from "./chunk-S7Z2HMCN.js";
4
4
  import {
5
5
  buildLocalRunEnv,
6
6
  isFullstackCodingAgentRef,
@@ -9,40 +9,51 @@ import {
9
9
  resolveRawAgentInput,
10
10
  resolveServerUrl,
11
11
  writeUsage
12
- } from "./chunk-LYGNQHUW.js";
12
+ } from "./chunk-JYYZCK2Z.js";
13
13
  import {
14
14
  agentRunCardLabels,
15
15
  createCliLocalRuntimeAdapter,
16
+ detectCurrentMachineId,
16
17
  getCliLocale,
17
18
  isBuiltinNoloAgentRef,
19
+ isCliProviderAgentConfig,
20
+ isLiveAgentRunObservation,
21
+ isMachineBoundLocalhostCustomProvider,
18
22
  isSubtaskRun,
19
23
  parseAgentRunEvent,
24
+ resolveAuthToken as resolveAuthToken2,
25
+ resolveBoundMachineId,
26
+ resolveFileWriteGateEnabled,
27
+ resolveLocalUserId,
20
28
  t,
21
29
  toolLabel
22
- } from "./chunk-GV35EHNA.js";
30
+ } from "./chunk-7O7KH4X5.js";
31
+ import {
32
+ createRunActivityTracker,
33
+ popSingleQueueMessage,
34
+ readRunRecord,
35
+ resolveRunQueuePath,
36
+ settleRunTerminalAuthoritatively,
37
+ spawnLocalBackgroundRun
38
+ } from "./chunk-45YO6H7P.js";
39
+ import {
40
+ readCredentialEntry,
41
+ recordCredentialProbe,
42
+ resolveCredentialKeyWithFallback
43
+ } from "./chunk-DWUCB2A3.js";
23
44
  import {
24
45
  getReadableCliDb
25
- } from "./chunk-43CXXVJD.js";
46
+ } from "./chunk-RXX4GDIH.js";
26
47
  import {
27
- normalizeAgentHandle,
28
48
  readDbRecord,
29
49
  resolveAgentRecordFromHybridStore
30
- } from "./chunk-DQLYEGP7.js";
50
+ } from "./chunk-FHAGENAS.js";
31
51
  import {
32
- NOLO_PROJECT_MANAGER_AGENT_KEY,
33
52
  isLocalCliAgentKey
34
- } from "./chunk-EKLRRZIN.js";
53
+ } from "./chunk-SPAQ4PVV.js";
35
54
  import {
36
55
  CliProviderQuotaError
37
- } from "./chunk-JDSUTNYY.js";
38
- import {
39
- createRunActivityTracker,
40
- finalizeRunRecord,
41
- popSingleQueueMessage,
42
- readRunRecord,
43
- resolveRunQueuePath,
44
- spawnLocalBackgroundRun
45
- } from "./chunk-WHVQA7PJ.js";
56
+ } from "./chunk-MP64VFGD.js";
46
57
  import {
47
58
  resolveMachineId
48
59
  } from "./chunk-ESHYE7WU.js";
@@ -52,7 +63,7 @@ import {
52
63
  } from "./chunk-LTRXGFMS.js";
53
64
  import {
54
65
  formatAgentListCard
55
- } from "./chunk-V4KZGLOI.js";
66
+ } from "./chunk-2HPRMEEZ.js";
56
67
  import {
57
68
  isTransientFetchError
58
69
  } from "./chunk-5XTOKQLW.js";
@@ -66,26 +77,33 @@ import {
66
77
  formatStartRunCard,
67
78
  formatStatusRunCard,
68
79
  formatStopRunCard,
69
- isAgentRunTerminalStatus,
70
- runShowsLogTail
71
- } from "./chunk-KXKQO4Q6.js";
80
+ isAgentRunTerminalStatus
81
+ } from "./chunk-NTW5GWDM.js";
72
82
  import {
73
83
  buildMemorySubjectsForAgent,
74
84
  chooseMemoryOwners,
75
85
  loadMemoryCandidatesFromDb,
76
86
  resolveAgentMemoryPolicy
77
- } from "./chunk-6SZ52ORL.js";
87
+ } from "./chunk-ES6CVKVD.js";
78
88
  import {
79
89
  API_REPORTED_COST_MULTIPLIER,
80
90
  normalizeUsage,
81
91
  parseUiAskChoiceContent
82
- } from "./chunk-BJLYCOZK.js";
92
+ } from "./chunk-D5XKNNUV.js";
93
+ import {
94
+ isOAuthApiKeyRef
95
+ } from "./chunk-YYLHWIW6.js";
96
+ import {
97
+ isCliAuthorityBrokerProtocolError,
98
+ isCliAuthorityBrokerTimeoutError,
99
+ isCliAuthorityBrokerUnavailableError
100
+ } from "./chunk-TRV2MIDW.js";
83
101
  import {
84
102
  getDefaultCliLocalRuntimeDb
85
- } from "./chunk-IA3A5373.js";
103
+ } from "./chunk-C3FZR5EC.js";
86
104
  import {
87
105
  buildSkillDiscoveryContextLayer
88
- } from "./chunk-2BWU4ORW.js";
106
+ } from "./chunk-AQMVUA7N.js";
89
107
  import {
90
108
  parseExternalSkillMarkdown,
91
109
  parseSkillDocProtocol
@@ -93,34 +111,38 @@ import {
93
111
  import {
94
112
  LOCAL_AGENT_CONFIG_MISSING_CODE,
95
113
  LOCAL_TURN_ABORTED_CODE,
96
- readActionGate,
97
- readCommandActionGatePayload
98
- } from "./chunk-6BGAQ3KR.js";
114
+ readActionGate
115
+ } from "./chunk-4C4ST2YE.js";
99
116
  import {
100
117
  resolveAgentRuntimeConfigFromRecord
101
- } from "./chunk-CVT7L2WZ.js";
118
+ } from "./chunk-XOKOSO35.js";
102
119
  import {
103
120
  createThinkParserState,
104
121
  flushThinkParser,
105
122
  processThinkChunk
106
123
  } from "./chunk-N7J63Q6C.js";
107
124
  import {
108
- resolveClientVersion,
109
- resolvePlatformAuthToken
110
- } from "./chunk-SP3DPVBH.js";
125
+ isAntigravityOAuthAgent
126
+ } from "./chunk-QEW2MFDQ.js";
127
+ import {
128
+ resolveClientVersion
129
+ } from "./chunk-RDBARW6T.js";
111
130
  import {
112
- isQuotaExhaustedError
113
- } from "./chunk-IWUMSAQF.js";
131
+ isQuotaExhaustedError,
132
+ isQuotaLimited403Body,
133
+ mergeAvailabilityDeadline,
134
+ resolveCooldownGate
135
+ } from "./chunk-CJCJF5XB.js";
114
136
  import {
115
137
  DEFAULT_CONTEXT_WINDOW,
116
138
  getModelContextWindow
117
- } from "./chunk-KUUTWU4I.js";
139
+ } from "./chunk-5ZYA4JJ3.js";
118
140
  import {
119
141
  clipCompactText
120
- } from "./chunk-H4RYESI6.js";
142
+ } from "./chunk-Z4QSJILV.js";
121
143
  import {
122
144
  findModelConfig
123
- } from "./chunk-QDHZCAH3.js";
145
+ } from "./chunk-MMZ6ZTVO.js";
124
146
  import {
125
147
  compactWhitespace
126
148
  } from "./chunk-DWLEOOGR.js";
@@ -133,7 +155,7 @@ import {
133
155
  buildMemoryUseGuidanceLayer,
134
156
  partitionScopedBlocks,
135
157
  renderTurnContextBlocksWithScope
136
- } from "./chunk-3AOLVADY.js";
158
+ } from "./chunk-DVINR3PL.js";
137
159
  import {
138
160
  readPipeText,
139
161
  spawnProcess
@@ -145,13 +167,13 @@ import {
145
167
  CLIENT_VERSION_TOO_OLD_CODE,
146
168
  NOLO_CLIENT_VERSION_HEADER,
147
169
  buildClientVersionUpgradeMessage
148
- } from "./chunk-WL3UOGYO.js";
170
+ } from "./chunk-22BTGNSP.js";
149
171
  import {
150
172
  parsePositiveFiniteNumberOrFallback
151
173
  } from "./chunk-Y5GCAMGP.js";
152
174
  import {
153
175
  createMemoryKey
154
- } from "./chunk-SVEUG45B.js";
176
+ } from "./chunk-NHRQCXIQ.js";
155
177
  import {
156
178
  asTrimmedLowercaseString
157
179
  } from "./chunk-QSJ3HFEF.js";
@@ -159,21 +181,19 @@ import {
159
181
  BUILTIN_NOLO_AGENT_KEY,
160
182
  BUILTIN_NOLO_AGENT_NAME,
161
183
  builtinAgentCatalogEntryById
162
- } from "./chunk-VULELK4T.js";
184
+ } from "./chunk-L7B47JXR.js";
163
185
  import {
164
186
  parsePublicAgentId
165
187
  } from "./chunk-BJIRLHJR.js";
166
188
  import {
167
189
  asTrimmedString
168
190
  } from "./chunk-3EUW3WEO.js";
169
- import {
170
- isLoopbackUrl
171
- } from "./chunk-4SN6J65J.js";
172
191
  import {
173
192
  asOptionalTrimmedString
174
193
  } from "./chunk-G3SUCT4W.js";
175
194
 
176
195
  // packages/cli/client/tokenUsage.ts
196
+ var PLATFORM_CREDIT_UNIT = "credits";
177
197
  var isUsableModelId = (model) => {
178
198
  const raw = model?.trim();
179
199
  return Boolean(raw) && raw !== "-" && raw !== "auto";
@@ -245,7 +265,7 @@ function buildTurnTokenUsage(usage, model) {
245
265
  const contextWindow = resolveContextWindow(model);
246
266
  const remaining = contextWindow && parsed.input > 0 ? Math.max(0, contextWindow - parsed.input) : void 0;
247
267
  const rawCost = typeof usage?.cost === "number" ? usage.cost : void 0;
248
- const isPlatformBilled = usage?.billing_unit === "credits";
268
+ const isPlatformBilled = usage?.billing_unit === PLATFORM_CREDIT_UNIT;
249
269
  const credits = rawCost !== void 0 && rawCost > 0 ? isPlatformBilled ? rawCost : rawCost * API_REPORTED_COST_MULTIPLIER : void 0;
250
270
  return {
251
271
  ...parsed,
@@ -254,6 +274,31 @@ function buildTurnTokenUsage(usage, model) {
254
274
  ...credits !== void 0 ? { credits } : {}
255
275
  };
256
276
  }
277
+ function sumPlatformCredits(records) {
278
+ if (!records?.length) return void 0;
279
+ let total = 0;
280
+ let sawPlatformCall = false;
281
+ for (const record of records) {
282
+ const credits = platformCreditsFromUsage(record?.usage);
283
+ if (credits === void 0) continue;
284
+ sawPlatformCall = true;
285
+ total += credits;
286
+ }
287
+ return sawPlatformCall ? total : void 0;
288
+ }
289
+ function platformCreditsFromUsage(usage) {
290
+ if (!usage || usage.billing_unit !== PLATFORM_CREDIT_UNIT) return void 0;
291
+ const cost = typeof usage.cost === "number" ? usage.cost : 0;
292
+ return Number.isFinite(cost) && cost > 0 ? cost : 0;
293
+ }
294
+ function withTurnCredits(tokens, credits) {
295
+ if (!tokens) return tokens;
296
+ if (credits === void 0) return tokens;
297
+ return { ...tokens, credits };
298
+ }
299
+ function formatCreditsChip(credits, options) {
300
+ return options?.compact ? `\u26A1${credits.toFixed(2)}` : `\u26A1 ${credits.toFixed(2)} \u79EF\u5206`;
301
+ }
257
302
  function formatTokenCount(value) {
258
303
  if (!Number.isFinite(value) || value < 0) return "\u2014";
259
304
  if (value < 1e3) return String(Math.round(value));
@@ -1098,7 +1143,7 @@ var THEME_PALETTES = {
1098
1143
  // denser slate — 687584 read too blue in dense prose (inline code/tool labels); 5E6A78 pulls blue down while staying darker than the old value
1099
1144
  },
1100
1145
  dark: {
1101
- accent: { hex: "5BA3D9", ansiFallback: "\x1B[34m" },
1146
+ accent: { hex: "5BA3D9", ansiFallback: "\x1B[94m" },
1102
1147
  // trail dark primary (was wrongly copied from catppuccin 89B4FA)
1103
1148
  chrome: { hex: "6C7086", ansiFallback: "\x1B[90m" },
1104
1149
  success: { hex: "5CB87A", ansiFallback: "\x1B[32m" },
@@ -1124,7 +1169,7 @@ var THEME_PALETTES = {
1124
1169
  muted: { hex: "6E7781", ansiFallback: "\x1B[90m" }
1125
1170
  },
1126
1171
  dark: {
1127
- accent: { hex: "89B4FA", ansiFallback: "\x1B[34m" },
1172
+ accent: { hex: "89B4FA", ansiFallback: "\x1B[94m" },
1128
1173
  // Catppuccin Mocha Blue
1129
1174
  chrome: { hex: "6C7086", ansiFallback: "\x1B[90m" },
1130
1175
  success: { hex: "A6E3A1", ansiFallback: "\x1B[32m" },
@@ -1146,7 +1191,7 @@ var THEME_PALETTES = {
1146
1191
  muted: { hex: "716E61", ansiFallback: "\x1B[90m" }
1147
1192
  },
1148
1193
  dark: {
1149
- accent: { hex: "7E9CD8", ansiFallback: "\x1B[34m" },
1194
+ accent: { hex: "7E9CD8", ansiFallback: "\x1B[94m" },
1150
1195
  // crystalBlue
1151
1196
  chrome: { hex: "727169", ansiFallback: "\x1B[90m" },
1152
1197
  success: { hex: "98BB6C", ansiFallback: "\x1B[32m" },
@@ -1167,7 +1212,7 @@ var THEME_PALETTES = {
1167
1212
  muted: { hex: "6E6A8A", ansiFallback: "\x1B[90m" }
1168
1213
  },
1169
1214
  dark: {
1170
- accent: { hex: "8B9CF4", ansiFallback: "\x1B[34m" },
1215
+ accent: { hex: "8B9CF4", ansiFallback: "\x1B[94m" },
1171
1216
  chrome: { hex: "5A5772", ansiFallback: "\x1B[90m" },
1172
1217
  success: { hex: "26BD6C", ansiFallback: "\x1B[32m" },
1173
1218
  warning: { hex: "F5A623", ansiFallback: "\x1B[33m" },
@@ -1187,7 +1232,7 @@ var THEME_PALETTES = {
1187
1232
  muted: { hex: "797593", ansiFallback: "\x1B[90m" }
1188
1233
  },
1189
1234
  dark: {
1190
- accent: { hex: "EB6F92", ansiFallback: "\x1B[35m" },
1235
+ accent: { hex: "EB6F92", ansiFallback: "\x1B[95m" },
1191
1236
  chrome: { hex: "6E6A86", ansiFallback: "\x1B[90m" },
1192
1237
  success: { hex: "9CCFD8", ansiFallback: "\x1B[32m" },
1193
1238
  warning: { hex: "F6C177", ansiFallback: "\x1B[33m" },
@@ -1271,6 +1316,9 @@ function detectSystemBrightnessFromEnv(env = process.env) {
1271
1316
  return null;
1272
1317
  }
1273
1318
  function resolveTuiBrightness(env = process.env) {
1319
+ return resolveTuiBrightnessSignal(env) ?? "dark";
1320
+ }
1321
+ function resolveTuiBrightnessSignal(env = process.env) {
1274
1322
  const explicit = (env.NOLO_TUI_THEME ?? "").trim().toLowerCase();
1275
1323
  if (explicit === "light") return "light";
1276
1324
  if (explicit === "dark") return "dark";
@@ -1283,9 +1331,7 @@ function resolveTuiBrightness(env = process.env) {
1283
1331
  if (!Number.isNaN(bg) && bg >= 0 && bg <= 6) return "dark";
1284
1332
  if (!Number.isNaN(bg) && bg >= 7 && bg <= 15) return "light";
1285
1333
  }
1286
- const sys = detectSystemBrightnessFromEnv(env);
1287
- if (sys) return sys;
1288
- return "dark";
1334
+ return detectSystemBrightnessFromEnv(env);
1289
1335
  }
1290
1336
  function resolveTuiThemeMode(env = process.env, fallback = activeThemeMode) {
1291
1337
  const explicit = (env.NOLO_TUI_THEME ?? "").trim().toLowerCase();
@@ -2908,6 +2954,14 @@ function normalizeListLine(line) {
2908
2954
  }
2909
2955
  return line;
2910
2956
  }
2957
+ function isPolishListLikeLine(line) {
2958
+ return LIST_LIKE_RE_FOR_GUARD.test(normalizeListLine(line));
2959
+ }
2960
+ var LIST_LIKE_RE_FOR_GUARD = /^\s*(?:•|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s/;
2961
+ function polishBreathInsertsBlankBetween(cur, next) {
2962
+ if (cur === "" || next === "") return false;
2963
+ return isPolishListLikeLine(cur) !== isPolishListLikeLine(next);
2964
+ }
2911
2965
  function convertMarkdownTablesForTerminal(text) {
2912
2966
  const lines = text.split("\n");
2913
2967
  const out = [];
@@ -2975,7 +3029,7 @@ function polishAssistantStructure(text, options = {}) {
2975
3029
  return line;
2976
3030
  });
2977
3031
  const afterHeading = maskedLines.join("\n").replace(/([^\n])\n(#{1,3} )/g, "$1\n\n$2").replace(/^(#{1,3} .+)\n(?!\n)/gm, "$1\n\n").replace(/\n{4,}/g, "\n\n\n");
2978
- const LIST_LIKE = /^\s*(?:•|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]/;
3032
+ const LIST_LIKE = /^\s*(?:•|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s/;
2979
3033
  const headingLines = afterHeading.split("\n");
2980
3034
  const breathed = [];
2981
3035
  for (let i = 0; i < headingLines.length; i++) {
@@ -3333,130 +3387,16 @@ function formatAssistantTextForCli(text) {
3333
3387
  return text.replace(/\u003cthink\u003e[\s\S]*?\u003c\/think\u003e\s*/gi, "").replace(/\n{3,}/g, "\n\n").trim();
3334
3388
  }
3335
3389
 
3336
- // packages/cli/client/formatReadPathTree.ts
3337
- import { homedir as osHomedir } from "node:os";
3338
-
3339
- // packages/core/foldHomePath.ts
3340
- function foldHomePath(path, home) {
3341
- if (!path) return path;
3342
- if (home) {
3343
- const cleanHome = home.endsWith("/") ? home.slice(0, -1) : home;
3344
- if (path === cleanHome) return "~";
3345
- if (path.startsWith(cleanHome + "/")) return `~${path.slice(cleanHome.length)}`;
3346
- }
3347
- return path.replace(/^(\/Users\/[^/]+|\/home\/[^/]+)(\/|$)/, "~$2");
3348
- }
3349
-
3350
- // packages/cli/client/formatReadPathTree.ts
3351
- function clipPathAware(value, max = 72) {
3352
- const compact = compactWhitespace(value);
3353
- if (compact.length <= max) return compact;
3354
- if (compact.includes(" ") || !compact.includes("/") && !compact.includes("\\")) {
3355
- return clipCompactText(value, max, "\u2026");
3356
- }
3357
- const segments = compact.split(/[/\\]/);
3358
- const filename = segments[segments.length - 1];
3359
- if (filename.length >= max) {
3360
- return clipCompactText(value, max, "\u2026");
3361
- }
3362
- const ELISION = "/\u2026/";
3363
- let prefix = "";
3364
- for (let i = 0; i < segments.length - 1; i += 1) {
3365
- const candidate = segments.slice(0, i + 1).join("/");
3366
- if (candidate.length + ELISION.length + filename.length > max) break;
3367
- prefix = candidate;
3368
- }
3369
- if (prefix) return `${prefix}${ELISION}${filename}`;
3370
- const filenameOnly = `\u2026/${filename}`;
3371
- if (filenameOnly.length <= max) return filenameOnly;
3372
- return clipCompactText(value, max, "\u2026");
3373
- }
3374
- function formatHomePath(path, customHomedir) {
3375
- if (!path) return "";
3376
- const home = customHomedir || (typeof process !== "undefined" ? process.env?.HOME : void 0) || (typeof osHomedir === "function" ? osHomedir() : "");
3377
- return foldHomePath(path, home);
3378
- }
3379
- function formatReadItemPath(rawPath, metadata, customHomedir) {
3380
- const inputPath = rawPath || (typeof metadata?.path === "string" ? metadata.path : void 0) || (typeof metadata?.filePath === "string" ? metadata.filePath : void 0) || "file";
3381
- let formattedPath = formatHomePath(inputPath, customHomedir);
3382
- if (!formattedPath) return "file";
3383
- let rangePart = "";
3384
- const match = formattedPath.match(/(:[0-9]+(-[0-9]+)?(,[0-9]+(-[0-9]+)?)*)$/);
3385
- if (match) {
3386
- rangePart = match[1];
3387
- formattedPath = formattedPath.slice(0, -rangePart.length);
3388
- } else if (metadata && typeof metadata.startLine === "number" && typeof metadata.endLine === "number" && typeof metadata.totalLines === "number") {
3389
- const { startLine, endLine, totalLines, truncated } = metadata;
3390
- if (truncated || startLine !== 1 || endLine !== totalLines) {
3391
- rangePart = `:${startLine}-${endLine}`;
3392
- }
3393
- }
3394
- const clippedPath = clipPathAware(formattedPath, 72);
3395
- return `${clippedPath}${rangePart}`;
3396
- }
3397
- function formatReadTreeLines(items, customHomedir) {
3398
- const count = items.length;
3399
- const header = `Read (${count})`;
3400
- const lines = items.map((item, index) => {
3401
- const connector = index === items.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
3402
- const pathWithRange = formatReadItemPath(item.path, item.metadata, customHomedir);
3403
- return { connector, pathWithRange };
3404
- });
3405
- return { header, count, lines };
3406
- }
3407
- function formatSearchItemQuery(query, path, customHomedir) {
3408
- let text = (query || "").trim();
3409
- if (path) {
3410
- const formattedPath = formatHomePath(path, customHomedir);
3411
- if (formattedPath) {
3412
- text = text ? `${text} in ${formattedPath}` : formattedPath;
3413
- }
3414
- }
3415
- if (!text) return "search";
3416
- return text.length > 80 ? `${text.slice(0, 79)}\u2026` : text;
3417
- }
3418
- function formatSearchTreeLines(items, customHomedir) {
3419
- const count = items.length;
3420
- const header = `Search (${count})`;
3421
- const lines = items.map((item, index) => {
3422
- const connector = index === items.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
3423
- const queryText = formatSearchItemQuery(item.query, item.path, customHomedir);
3424
- return { connector, queryText };
3425
- });
3426
- return { header, count, lines };
3427
- }
3428
- function formatRunItemCommand(command, exitCode, timedOut) {
3429
- let text = compactWhitespace(command || "");
3430
- if (!text) text = "command";
3431
- text = text.length > 80 ? `${text.slice(0, 79)}\u2026` : text;
3432
- if (timedOut) return `${text} (timed out)`;
3433
- if (typeof exitCode === "number" && exitCode !== 0) return `${text} (exit ${exitCode})`;
3434
- return text;
3435
- }
3436
- function formatRunTreeLines(items) {
3437
- const count = items.length;
3438
- const header = `Run (${count})`;
3439
- const lines = items.map((item, index) => {
3440
- const connector = index === items.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
3441
- const commandText = formatRunItemCommand(item.command, item.exitCode, item.timedOut);
3442
- return { connector, commandText };
3443
- });
3444
- return { header, count, lines };
3445
- }
3446
- function formatFetchItemUrl(url) {
3447
- const text = (url || "").trim();
3448
- if (!text) return "webpage";
3449
- return text.length > 80 ? `${text.slice(0, 79)}\u2026` : text;
3450
- }
3451
- function formatFetchTreeLines(items) {
3452
- const count = items.length;
3453
- const header = `Fetch (${count})`;
3454
- const lines = items.map((item, index) => {
3455
- const connector = index === items.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
3456
- const urlText = formatFetchItemUrl(item.url);
3457
- return { connector, urlText };
3458
- });
3459
- return { header, count, lines };
3390
+ // packages/cli/tui/redactSecrets.ts
3391
+ var REDACTED = "\u27E8redacted\u27E9";
3392
+ function redactSecrets(text) {
3393
+ return text.replace(/\b(?:sk|pk)-[A-Za-z0-9_-]{10,}/g, REDACTED).replace(/\b(Bearer\s+)[A-Za-z0-9._~+/=-]{12,}/gi, `$1${REDACTED}`).replace(
3394
+ /\b((?:api[_-]?key|apikey|access[_-]?token|auth[_-]?token|token|secret|password|passwd|credential)s?\s*[=:]\s*["']?)[^\s"',;]{8,}/gi,
3395
+ `$1${REDACTED}`
3396
+ ).replace(
3397
+ /\b((?:--[a-z-]*(?:token|key|secret|password|credential)[a-z-]*)\s+)[^\s"']{8,}/gi,
3398
+ `$1${REDACTED}`
3399
+ );
3460
3400
  }
3461
3401
 
3462
3402
  // node_modules/diff/libesm/diff/base.js
@@ -3709,186 +3649,110 @@ function tokenize(value, options) {
3709
3649
  return retLines;
3710
3650
  }
3711
3651
 
3712
- // packages/cli/client/toolOutput.ts
3713
- function normalizeToolDisplayMode(raw, fallback = "normal") {
3714
- const normalized = asTrimmedLowercaseString(raw);
3715
- if (normalized === "hide" || normalized === "off" || normalized === "false" || normalized === "0") {
3716
- return "hide";
3652
+ // packages/cli/client/formatReadPathTree.ts
3653
+ import { homedir as osHomedir } from "node:os";
3654
+
3655
+ // packages/core/foldHomePath.ts
3656
+ function foldHomePath(path, home) {
3657
+ if (!path) return path;
3658
+ if (home) {
3659
+ const cleanHome = home.endsWith("/") ? home.slice(0, -1) : home;
3660
+ if (path === cleanHome) return "~";
3661
+ if (path.startsWith(cleanHome + "/")) return `~${path.slice(cleanHome.length)}`;
3717
3662
  }
3718
- if (normalized === "verbose" || normalized === "debug" || normalized === "trace" || normalized === "full") {
3719
- return "verbose";
3663
+ return path.replace(/^(\/Users\/[^/]+|\/home\/[^/]+)(\/|$)/, "~$2");
3664
+ }
3665
+
3666
+ // packages/cli/client/formatReadPathTree.ts
3667
+ function clipPathAware(value, max = 72) {
3668
+ const compact = compactWhitespace(value);
3669
+ if (compact.length <= max) return compact;
3670
+ if (compact.includes(" ") || !compact.includes("/") && !compact.includes("\\")) {
3671
+ return clipCompactText(value, max, "\u2026");
3720
3672
  }
3721
- if (normalized === "normal" || normalized === "summary" || normalized === "on") {
3722
- return "normal";
3673
+ const segments = compact.split(/[/\\]/);
3674
+ const filename = segments[segments.length - 1];
3675
+ if (filename.length >= max) {
3676
+ return clipCompactText(value, max, "\u2026");
3723
3677
  }
3724
- if (normalized === "pro" || normalized === "compact" || normalized === "minimal" || normalized === "short") {
3725
- return "pro";
3678
+ const ELISION = "/\u2026/";
3679
+ let prefix = "";
3680
+ for (let i = 0; i < segments.length - 1; i += 1) {
3681
+ const candidate = segments.slice(0, i + 1).join("/");
3682
+ if (candidate.length + ELISION.length + filename.length > max) break;
3683
+ prefix = candidate;
3726
3684
  }
3727
- return fallback;
3685
+ if (prefix) return `${prefix}${ELISION}${filename}`;
3686
+ const filenameOnly = `\u2026/${filename}`;
3687
+ if (filenameOnly.length <= max) return filenameOnly;
3688
+ return clipCompactText(value, max, "\u2026");
3689
+ }
3690
+ function formatHomePath(path, customHomedir) {
3691
+ if (!path) return "";
3692
+ const home = customHomedir || (typeof process !== "undefined" ? process.env?.HOME : void 0) || (typeof osHomedir === "function" ? osHomedir() : "");
3693
+ return foldHomePath(path, home);
3728
3694
  }
3729
- function resolveToolDisplayMode(env = process.env) {
3730
- const legacyTrace = asTrimmedLowercaseString(env.NOLO_TRACE_TOOLS);
3731
- if (legacyTrace === "0" || legacyTrace === "false" || legacyTrace === "off") {
3732
- return "hide";
3695
+ function formatReadItemPath(rawPath, metadata, customHomedir) {
3696
+ const inputPath = rawPath || (typeof metadata?.path === "string" ? metadata.path : void 0) || (typeof metadata?.filePath === "string" ? metadata.filePath : void 0) || "file";
3697
+ let formattedPath = formatHomePath(inputPath, customHomedir);
3698
+ if (!formattedPath) return "file";
3699
+ let rangePart = "";
3700
+ const match = formattedPath.match(/(:[0-9]+(-[0-9]+)?(,[0-9]+(-[0-9]+)?)*)$/);
3701
+ if (match) {
3702
+ rangePart = match[1];
3703
+ formattedPath = formattedPath.slice(0, -rangePart.length);
3704
+ } else if (metadata && typeof metadata.startLine === "number" && typeof metadata.endLine === "number" && typeof metadata.totalLines === "number") {
3705
+ const { startLine, endLine, totalLines, truncated } = metadata;
3706
+ if (truncated || startLine !== 1 || endLine !== totalLines) {
3707
+ rangePart = `:${startLine}-${endLine}`;
3708
+ }
3733
3709
  }
3734
- if (legacyTrace === "verbose" || legacyTrace === "full") {
3735
- return "verbose";
3710
+ const clippedPath = clipPathAware(formattedPath, 72);
3711
+ return `${clippedPath}${rangePart}`;
3712
+ }
3713
+ function formatSearchItemQuery(query, path, customHomedir) {
3714
+ let text = (query || "").trim();
3715
+ if (path) {
3716
+ const formattedPath = formatHomePath(path, customHomedir);
3717
+ if (formattedPath) {
3718
+ text = text ? `${text} in ${formattedPath}` : formattedPath;
3719
+ }
3736
3720
  }
3737
- return normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "normal");
3721
+ if (!text) return "search";
3722
+ return text.length > 80 ? `${text.slice(0, 79)}\u2026` : text;
3723
+ }
3724
+ function formatRunItemCommand(command, exitCode, timedOut) {
3725
+ let text = compactWhitespace(command || "");
3726
+ if (!text) text = "command";
3727
+ text = text.length > 80 ? `${text.slice(0, 79)}\u2026` : text;
3728
+ if (timedOut) return `${text} (timed out)`;
3729
+ if (typeof exitCode === "number" && exitCode !== 0) return `${text} (exit ${exitCode})`;
3730
+ return text;
3738
3731
  }
3739
- function shouldEmitToolEvents(mode) {
3740
- return mode !== "hide";
3732
+ function formatFetchItemUrl(url) {
3733
+ const text = (url || "").trim();
3734
+ if (!text) return "webpage";
3735
+ return text.length > 80 ? `${text.slice(0, 79)}\u2026` : text;
3741
3736
  }
3737
+
3738
+ // packages/cli/client/toolOutput.ts
3742
3739
  function clip(value, max = 72) {
3743
3740
  return clipCompactText(value, max, "\u2026");
3744
3741
  }
3745
- function formatActiveToolLabel(event) {
3746
- const toolName = event.toolName || "tool";
3747
- const args = clipPathAware(event.argumentsPreview ?? "");
3748
- const label = toolLabel(toolName);
3749
- return args ? `${label} ${args}` : label;
3750
- }
3751
3742
  function formatConservativeActiveToolLabel(event) {
3752
3743
  return toolLabel(event.toolName || "tool");
3753
3744
  }
3754
- function compactResultHint(event) {
3755
- const gate = readActionGate(event.metadata?.actionGate);
3756
- if (gate) {
3757
- const commandPayload = gate.kind === "handoff" ? readCommandActionGatePayload(gate.payload) : null;
3758
- const command = commandPayload?.displayCommand ?? commandPayload?.command.join(" ") ?? "";
3759
- const detail = command.trim() ? command : gate.title;
3760
- return { inline: `${t("toolNeedsAction")}: ${clip(detail, 120)}` };
3761
- }
3762
- if (event.metadata?.timedOut) return { inline: t("toolTimedOut") };
3763
- if (event.toolName === "readFile" && event.metadata) {
3764
- const range = readReadFileRange(event.metadata);
3765
- if (range) return { inline: range };
3766
- }
3767
- if (event.toolName === "editFile" && event.metadata) {
3768
- const res = formatEditFileSnippet(event.metadata);
3769
- if (res) {
3770
- const stats = [];
3771
- if (res.addedCount > 0) stats.push(`+${res.addedCount}`);
3772
- if (res.removedCount > 0) stats.push(`-${res.removedCount}`);
3773
- const inline = stats.length > 0 ? `(${stats.join(", ")})` : "";
3774
- return { inline, detail: res.lines };
3775
- }
3776
- }
3777
- if (event.toolName === "writeFile" && event.metadata) {
3778
- const totalLines = event.metadata.totalLines ?? event.metadata.lines;
3779
- if (typeof totalLines === "number" && totalLines > 0) {
3780
- return { inline: `(+${totalLines})` };
3781
- }
3782
- }
3783
- const summary = event.summary;
3784
- if (!summary) return { inline: "" };
3785
- const exitMatch = summary.match(/exit=(\d+)/);
3786
- if (exitMatch && exitMatch[1] !== "0") return { inline: `${t("toolExitCode")} ${exitMatch[1]}` };
3787
- return { inline: "" };
3788
- }
3789
- function readReadFileRange(metadata) {
3790
- const startLine = metadata.startLine;
3791
- const endLine = metadata.endLine;
3792
- const totalLines = metadata.totalLines;
3793
- const truncated = metadata.truncated;
3794
- if (typeof startLine !== "number" || typeof endLine !== "number" || typeof totalLines !== "number") {
3795
- return void 0;
3796
- }
3797
- if (!truncated && startLine === 1 && endLine === totalLines) return void 0;
3798
- return `${startLine}-${endLine}/${totalLines}`;
3799
- }
3800
- var EDIT_SNIPPET_MAX_LINES = 24;
3801
- var DEFAULT_EDIT_SNIPPET_MAX_WIDTH = 96;
3802
- function resolveEditSnippetMaxWidth(env = process.env, columns) {
3803
- if (env.NOLO_TEST_DIFF_WIDTH) {
3804
- const parsed = parseInt(env.NOLO_TEST_DIFF_WIDTH, 10);
3805
- if (!Number.isNaN(parsed) && parsed > 0) return parsed;
3806
- }
3807
- const cols = typeof columns === "number" ? columns : typeof process !== "undefined" && typeof process.stdout?.columns === "number" ? process.stdout.columns : 0;
3808
- if (cols > 0) {
3809
- return Math.max(80, Math.min(160, cols - 8));
3810
- }
3811
- return DEFAULT_EDIT_SNIPPET_MAX_WIDTH;
3745
+ function isRunToolName(name) {
3746
+ return name === "execShell" || name === "runCommand" || name === "launchProcess";
3812
3747
  }
3813
- function formatEditFileSnippet(metadata) {
3814
- const oldSnippet = typeof metadata.oldSnippet === "string" ? metadata.oldSnippet : void 0;
3815
- const newSnippet = typeof metadata.newSnippet === "string" ? metadata.newSnippet : void 0;
3816
- if (!oldSnippet && !newSnippet) return void 0;
3817
- const maxWidth = resolveEditSnippetMaxWidth();
3818
- if (oldSnippet && !newSnippet) {
3819
- const lines = snippetLinesWithKind(oldSnippet, "removed", maxWidth);
3820
- return { lines, addedCount: 0, removedCount: lines.length };
3821
- }
3822
- if (newSnippet && !oldSnippet) {
3823
- const lines = snippetLinesWithKind(newSnippet, "added", maxWidth);
3824
- return { lines, addedCount: lines.length, removedCount: 0 };
3825
- }
3826
- const parts = diffLines(oldSnippet, newSnippet);
3827
- const all = [];
3828
- let addedCount = 0;
3829
- let removedCount = 0;
3830
- for (const part of parts) {
3831
- const kind = part.added ? "added" : part.removed ? "removed" : "context";
3832
- const raw = part.value.split("\n");
3833
- if (raw.length > 0 && raw[raw.length - 1] === "") raw.pop();
3834
- for (const line of raw) {
3835
- if (kind === "added") addedCount++;
3836
- if (kind === "removed") removedCount++;
3837
- all.push(buildEditLine(kind, line, maxWidth));
3838
- }
3839
- }
3840
- const changeCount = all.filter((l) => l.kind !== "context").length;
3841
- if (changeCount === 0) return void 0;
3842
- return {
3843
- lines: windowAndTruncate(all, EDIT_SNIPPET_MAX_LINES),
3844
- addedCount,
3845
- removedCount
3846
- };
3748
+ function isReadToolName(name) {
3749
+ return name === "readFile";
3847
3750
  }
3848
- function prefixFor(kind) {
3849
- return kind === "added" ? "+ " : kind === "removed" ? "- " : " ";
3850
- }
3851
- function buildEditLine(kind, body, maxWidth = resolveEditSnippetMaxWidth()) {
3852
- return { kind, text: prefixFor(kind) + truncateByDisplayWidth(body, maxWidth) };
3853
- }
3854
- function snippetLinesWithKind(snippet, kind, maxWidth = resolveEditSnippetMaxWidth()) {
3855
- const lines = snippet.split(/\r?\n/).filter((line) => line.length > 0);
3856
- return lines.slice(0, EDIT_SNIPPET_MAX_LINES).map((line) => buildEditLine(kind, line, maxWidth));
3857
- }
3858
- function truncateByDisplayWidth(line, maxWidth) {
3859
- if (displayWidth(line) <= maxWidth) return line;
3860
- let width = 0;
3861
- let kept = "";
3862
- for (const char of line) {
3863
- const w = displayWidth(char);
3864
- if (width + w + 1 > maxWidth) break;
3865
- kept += char;
3866
- width += w;
3867
- }
3868
- return `${kept}\u2026`;
3869
- }
3870
- function windowAndTruncate(lines, maxLines) {
3871
- if (lines.length <= maxLines) return lines;
3872
- const firstChange = lines.findIndex((l) => l.kind !== "context");
3873
- if (firstChange === -1) return lines.slice(0, maxLines);
3874
- const half = Math.floor(maxLines / 2);
3875
- let start = Math.max(0, firstChange - half);
3876
- if (start + maxLines > lines.length) start = Math.max(0, lines.length - maxLines);
3877
- const kept = lines.slice(start, start + maxLines);
3878
- const omitted = lines.length - kept.length;
3879
- if (omitted > 0) {
3880
- kept.push({ kind: "context", text: ` \u2026 +${omitted} more lines` });
3881
- }
3882
- return kept;
3883
- }
3884
- function isFailedToolResult(event) {
3885
- const exitCode = event.metadata?.exitCode;
3886
- if (event.metadata?.actionGate) return false;
3887
- if (typeof exitCode === "number" && exitCode !== 0) return true;
3888
- return Boolean(event.metadata?.timedOut);
3889
- }
3890
- function isNeedsActionToolResult(event) {
3891
- return Boolean(event.metadata?.actionGate);
3751
+ function isFailedToolResult(event) {
3752
+ const exitCode = event.metadata?.exitCode;
3753
+ if (event.metadata?.actionGate) return false;
3754
+ if (typeof exitCode === "number" && exitCode !== 0) return true;
3755
+ return Boolean(event.metadata?.timedOut);
3892
3756
  }
3893
3757
  function parseUiAskChoiceForCli(event) {
3894
3758
  if (event.toolName !== "ask_user" && !event.metadata?.uiAskChoice) {
@@ -4006,7 +3870,10 @@ function renderRunCard(snapshot, opts) {
4006
3870
  lastToolNames: snapshot.lastToolNames?.map(cleanUserText)
4007
3871
  } : snapshot;
4008
3872
  const hadError = safe && Boolean(source.errorMessage?.trim());
4009
- const errorFields = safe ? { errorMessage: void 0, logLines: void 0 } : { errorMessage: source.errorMessage, logLines: source.logLines };
3873
+ const errorFields = safe ? {
3874
+ errorMessage: hadError ? clip(redactSecrets(cleanUserText(source.errorMessage)), 160) : void 0,
3875
+ logLines: void 0
3876
+ } : { errorMessage: source.errorMessage, logLines: source.logLines };
4010
3877
  const body = isAgentRunTerminalStatus(snapshot.status) ? formatFinishedRunCard(name, snapshot.status, {
4011
3878
  runId: snapshot.runId,
4012
3879
  toolCallCount: source.toolCallCount,
@@ -4026,8 +3893,7 @@ function renderRunCard(snapshot, opts) {
4026
3893
  ...opts?.includeLogTail !== void 0 ? { includeLogTail: opts.includeLogTail } : {},
4027
3894
  labels
4028
3895
  });
4029
- return hadError ? `${body}
4030
- error ${t("runDiagnosticsHidden")}` : body;
3896
+ return body;
4031
3897
  }
4032
3898
  function recoverOrchestrationCard(event, toolName, opts) {
4033
3899
  const safe = opts?.safe === true;
@@ -4073,10 +3939,6 @@ function recoverOrchestrationCard(event, toolName, opts) {
4073
3939
  if (kind === "stop") return formatStopRunCard(snapshot.status, labels);
4074
3940
  return renderRunCard(snapshot, opts);
4075
3941
  }
4076
- function parseControlAgentRunStatusEvent(event) {
4077
- const parsed = parseAgentRunEvent(event);
4078
- return parsed?.kind === "status" ? parsed.snapshot : null;
4079
- }
4080
3942
  function formatOrchestrationCardBlock(event, toolName, colorEnabled, opts) {
4081
3943
  const safe = opts?.safe === true;
4082
3944
  const rawLabel = toolLabel(toolName);
@@ -4084,8 +3946,8 @@ function formatOrchestrationCardBlock(event, toolName, colorEnabled, opts) {
4084
3946
  const rawDataStr = recoverOrchestrationCard(event, toolName, { safe }) || bakedCard || (typeof event.content === "string" ? event.content : "");
4085
3947
  const failed = event.type === "tool-error" || isFailedToolResult(event) || Boolean(event.metadata?.failed) || /^Error:/i.test(rawDataStr.trim());
4086
3948
  if (failed) {
4087
- const firstLine = safe ? t("toolFailed") : rawDataStr.trim().split("\n")[0] || event.summary || event.message || t("toolFailed");
4088
- const message = clip(firstLine, 96);
3949
+ const firstLine = stripAnsi2(rawDataStr.trim().split("\n")[0] || event.summary || event.message || t("toolFailed"));
3950
+ const message = clip(redactSecrets(firstLine), 96);
4089
3951
  if (!colorEnabled) {
4090
3952
  return `\u2717 ${rawLabel} ${message}
4091
3953
  `;
@@ -4127,7 +3989,7 @@ function sanitizeRunCardForNormal(lines) {
4127
3989
  break;
4128
3990
  }
4129
3991
  if (/^\s*error\b/i.test(line)) {
4130
- out.push(` error ${t("runDiagnosticsHidden")}`);
3992
+ out.push(clip(redactSecrets(stripAnsi2(line)), 160));
4131
3993
  errorIndent = line.length - line.trimStart().length;
4132
3994
  continue;
4133
3995
  }
@@ -4146,59 +4008,207 @@ function sanitizeRunCardForNormal(lines) {
4146
4008
  }
4147
4009
  return out;
4148
4010
  }
4149
- function mergeRunSnapshot(previous, next) {
4150
- return {
4151
- ...previous,
4152
- ...next,
4153
- errorMessage: next.errorMessage ?? previous.errorMessage,
4154
- logLines: next.logLines ?? previous.logLines,
4155
- logKey: next.logKey || previous.logKey,
4156
- toolCallCount: next.toolCallCount ?? previous.toolCallCount,
4157
- lastToolNames: next.lastToolNames ?? previous.lastToolNames,
4158
- lastAssistantText: next.lastAssistantText ?? previous.lastAssistantText,
4159
- startedAt: next.startedAt ?? previous.startedAt,
4160
- finishedAt: next.finishedAt ?? previous.finishedAt
4161
- };
4011
+ var NORMAL_TOOL_GIST_MAX = 28;
4012
+ function gistClip(value, max = NORMAL_TOOL_GIST_MAX) {
4013
+ const oneLine = value.replace(/\s+/g, " ").trim();
4014
+ if (!oneLine) return "";
4015
+ return oneLine.length <= max ? oneLine : `${oneLine.slice(0, max - 1)}\u2026`;
4162
4016
  }
4163
- function formatFoldedControlStatusCard(snapshot, colorEnabled) {
4164
- const body = renderRunCard(snapshot, { includeLogTail: snapshot.includeLogTail });
4165
- return formatOrchestrationCardBlock(
4166
- {
4167
- type: "tool-result",
4168
- round: 0,
4169
- toolCallId: `fold-${snapshot.runId}`,
4170
- toolName: "controlAgentRun",
4171
- content: "",
4172
- metadata: { displayData: body }
4173
- },
4174
- "controlAgentRun",
4175
- colorEnabled
4176
- );
4017
+ var DEFAULT_RUN_GIST_MAX = 96;
4018
+ function normalRunGistMaxWidth(env = process.env, columns) {
4019
+ const pinned = parseInt(env.NOLO_TEST_RUN_GIST_WIDTH ?? "", 10);
4020
+ if (!Number.isNaN(pinned) && pinned > 0) return pinned;
4021
+ const cols = typeof columns === "number" ? columns : typeof process !== "undefined" && typeof process.stdout?.columns === "number" ? process.stdout.columns : 0;
4022
+ if (cols > 0) {
4023
+ return Math.max(48, Math.min(160, cols - 32));
4024
+ }
4025
+ return DEFAULT_RUN_GIST_MAX;
4026
+ }
4027
+ function commandFullGist(command, max) {
4028
+ const oneLine = command.replace(/\s+/g, " ").trim();
4029
+ if (!oneLine) return "";
4030
+ return truncateByDisplayWidth(redactSecrets(oneLine), max);
4177
4031
  }
4178
- function formatVerboseToolEvent(event, colorEnabled) {
4179
- const round = event.round + 1;
4180
- const detail = event.argumentsPreview ? ` ${event.argumentsPreview}` : "";
4181
- if (event.type === "tool-call") {
4182
- return formatToolTraceLine(`[nolo:tool] #${round} -> ${event.toolName}${detail}`, colorEnabled);
4032
+ function pathBasenameGist(path) {
4033
+ const segments = path.split(/[\\/]/).filter((segment) => segment.length > 0);
4034
+ const base = segments.pop();
4035
+ return base ? gistClip(base) : "";
4036
+ }
4037
+ var EDIT_SNIPPET_MAX_LINES = 24;
4038
+ var DEFAULT_EDIT_SNIPPET_MAX_WIDTH = 96;
4039
+ function resolveEditSnippetMaxWidth(env = process.env, columns) {
4040
+ if (env.NOLO_TEST_DIFF_WIDTH) {
4041
+ const parsed = parseInt(env.NOLO_TEST_DIFF_WIDTH, 10);
4042
+ if (!Number.isNaN(parsed) && parsed > 0) return parsed;
4183
4043
  }
4184
- if (event.type === "tool-error") {
4185
- const elapsed2 = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
4186
- return formatToolTraceLine(
4187
- `[nolo:tool] #${round} !! ${event.toolName}${elapsed2}: ${event.message ?? "failed"}`,
4188
- colorEnabled,
4189
- "error"
4190
- );
4044
+ const cols = typeof columns === "number" ? columns : typeof process !== "undefined" && typeof process.stdout?.columns === "number" ? process.stdout.columns : 0;
4045
+ if (cols > 0) {
4046
+ return Math.max(80, Math.min(160, cols - 8));
4191
4047
  }
4192
- const elapsed = typeof event.elapsedMs === "number" ? ` ${event.elapsedMs}ms` : "";
4193
- if (event.type === "tool-result" && (event.toolName === "ask_user" || event.metadata?.uiAskChoice)) {
4194
- const block = formatUiAskChoiceBlock(event, colorEnabled);
4195
- if (block) return `${formatToolTraceLine(`[nolo:tool] #${round} <- ${event.toolName}${elapsed}`, colorEnabled)}${block}`;
4048
+ return DEFAULT_EDIT_SNIPPET_MAX_WIDTH;
4049
+ }
4050
+ function prefixFor(kind) {
4051
+ return kind === "added" ? "+ " : kind === "removed" ? "- " : " ";
4052
+ }
4053
+ function buildEditLine(kind, body, maxWidth = resolveEditSnippetMaxWidth()) {
4054
+ return { kind, text: prefixFor(kind) + truncateByDisplayWidth(body, maxWidth) };
4055
+ }
4056
+ function snippetLinesWithKind(snippet, kind, maxWidth = resolveEditSnippetMaxWidth()) {
4057
+ const lines = snippet.split(/\r?\n/);
4058
+ if (lines.at(-1) === "") lines.pop();
4059
+ return lines.slice(0, EDIT_SNIPPET_MAX_LINES).map((line) => buildEditLine(kind, line, maxWidth));
4060
+ }
4061
+ function truncateByDisplayWidth(line, maxWidth) {
4062
+ if (displayWidth(line) <= maxWidth) return line;
4063
+ let width = 0;
4064
+ let kept = "";
4065
+ for (const char of line) {
4066
+ const w = displayWidth(char);
4067
+ if (width + w + 1 > maxWidth) break;
4068
+ kept += char;
4069
+ width += w;
4196
4070
  }
4197
- const summary = event.summary ? ` ${event.summary}` : "";
4198
- return formatToolTraceLine(
4199
- `[nolo:tool] #${round} <- ${event.toolName}${elapsed}${summary}`,
4200
- colorEnabled
4201
- );
4071
+ return `${kept}\u2026`;
4072
+ }
4073
+ function windowAndTruncate(lines, maxLines) {
4074
+ if (lines.length <= maxLines) return lines;
4075
+ const firstChange = lines.findIndex((l) => l.kind !== "context");
4076
+ if (firstChange === -1) return lines.slice(0, maxLines);
4077
+ const half = Math.floor(maxLines / 2);
4078
+ let start = Math.max(0, firstChange - half);
4079
+ if (start + maxLines > lines.length) start = Math.max(0, lines.length - maxLines);
4080
+ const kept = lines.slice(start, start + maxLines);
4081
+ const omitted = lines.length - kept.length;
4082
+ if (omitted > 0) {
4083
+ kept.push({ kind: "context", text: ` \u2026 +${omitted} more lines` });
4084
+ }
4085
+ return kept;
4086
+ }
4087
+ function formatEditFileSnippet(metadata) {
4088
+ const oldSnippet = typeof metadata.oldSnippet === "string" ? metadata.oldSnippet : void 0;
4089
+ const newSnippet = typeof metadata.newSnippet === "string" ? metadata.newSnippet : void 0;
4090
+ if (!oldSnippet && !newSnippet) return void 0;
4091
+ const maxWidth = resolveEditSnippetMaxWidth();
4092
+ if (oldSnippet && !newSnippet) {
4093
+ const lines = snippetLinesWithKind(oldSnippet, "removed", maxWidth);
4094
+ return { lines, addedCount: 0, removedCount: lines.length };
4095
+ }
4096
+ if (newSnippet && !oldSnippet) {
4097
+ const lines = snippetLinesWithKind(newSnippet, "added", maxWidth);
4098
+ return { lines, addedCount: lines.length, removedCount: 0 };
4099
+ }
4100
+ const parts = diffLines(oldSnippet, newSnippet);
4101
+ const all = [];
4102
+ let addedCount = 0;
4103
+ let removedCount = 0;
4104
+ for (const part of parts) {
4105
+ const kind = part.added ? "added" : part.removed ? "removed" : "context";
4106
+ const bodyLines = part.value.replace(/\n$/, "").split("\n");
4107
+ for (const line of bodyLines) {
4108
+ if (kind === "added") addedCount++;
4109
+ if (kind === "removed") removedCount++;
4110
+ all.push(buildEditLine(kind, line, maxWidth));
4111
+ }
4112
+ }
4113
+ return {
4114
+ lines: windowAndTruncate(all, EDIT_SNIPPET_MAX_LINES),
4115
+ addedCount,
4116
+ removedCount
4117
+ };
4118
+ }
4119
+ function editFileResultHint(event) {
4120
+ if (event.toolName !== "editFile" || !event.metadata) return null;
4121
+ const res = formatEditFileSnippet(event.metadata);
4122
+ if (!res) return null;
4123
+ const stats = [];
4124
+ if (res.addedCount > 0) stats.push(`+${res.addedCount}`);
4125
+ if (res.removedCount > 0) stats.push(`-${res.removedCount}`);
4126
+ const inline = stats.length > 0 ? `(${stats.join(", ")})` : "";
4127
+ return { inline, detail: res.lines };
4128
+ }
4129
+ function formatEditDetailBlock(lines, colorEnabled, filePath, env = process.env) {
4130
+ if (!colorEnabled) {
4131
+ return lines.map((line) => ` ${line.text}
4132
+ `).join("");
4133
+ }
4134
+ const isTruecolor = supportsTruecolor(env);
4135
+ const lang = isTruecolor ? detectCodeLangFromPath(filePath) : "unknown";
4136
+ const brightness = resolveTuiBrightness(env);
4137
+ const padTo = Math.max(...lines.map((line) => displayWidth(line.text))) + 1;
4138
+ return lines.map((line) => ` ${renderDiffLine({
4139
+ kind: line.kind,
4140
+ text: line.text,
4141
+ highlightedText: shouldHighlightEditLine(line, lang, isTruecolor) ? buildHighlightedEditLine(line, lang, brightness, env) : void 0,
4142
+ padTo,
4143
+ colorEnabled: true,
4144
+ env
4145
+ })}
4146
+ `).join("");
4147
+ }
4148
+ function shouldHighlightEditLine(line, lang, isTruecolor) {
4149
+ if (!isTruecolor || lang === "unknown") return false;
4150
+ if (line.text.startsWith(" \u2026") || line.text.startsWith("\u2026")) return false;
4151
+ return line.text.length >= 2;
4152
+ }
4153
+ function buildHighlightedEditLine(line, lang, brightness, env) {
4154
+ const prefix = line.text.slice(0, 2);
4155
+ const body = line.text.slice(2);
4156
+ const prefixToken = line.kind === "added" ? "success" : line.kind === "removed" ? "danger" : "chrome";
4157
+ const coloredPrefix = themeText(prefix, prefixToken, true, env);
4158
+ const highlightedBody = highlightCodeLine(body, lang, brightness);
4159
+ return `${coloredPrefix}${highlightedBody}`;
4160
+ }
4161
+ function normalToolGistRaw(event) {
4162
+ const metadata = event.metadata ?? {};
4163
+ const toolName = event.toolName || "";
4164
+ if (toolName === "readFile") {
4165
+ const path2 = typeof metadata.path === "string" ? metadata.path : typeof metadata.filePath === "string" ? metadata.filePath : "";
4166
+ if (path2) return gistClip(formatReadItemPath(path2, metadata), 52);
4167
+ }
4168
+ if (toolName === "fetchWebpage") {
4169
+ const url = typeof metadata.url === "string" ? metadata.url : "";
4170
+ if (url) return formatFetchItemUrl(url);
4171
+ }
4172
+ if (toolName === "exa_search") {
4173
+ const query2 = typeof metadata.query === "string" ? metadata.query : typeof metadata.pattern === "string" ? metadata.pattern : "";
4174
+ const path2 = typeof metadata.path === "string" ? metadata.path : void 0;
4175
+ if (query2 || path2) return formatSearchItemQuery(query2, path2);
4176
+ }
4177
+ if (isRunToolName(toolName)) {
4178
+ const command2 = typeof metadata.command === "string" ? metadata.command : "";
4179
+ if (command2) {
4180
+ return commandFullGist(command2, normalRunGistMaxWidth());
4181
+ }
4182
+ }
4183
+ const path = typeof metadata.path === "string" ? metadata.path : "";
4184
+ if (path) return pathBasenameGist(path);
4185
+ const command = typeof metadata.command === "string" ? metadata.command : "";
4186
+ if (command) return commandFullGist(command, normalRunGistMaxWidth());
4187
+ const query = typeof metadata.query === "string" ? metadata.query : "";
4188
+ if (query) return clipCompactText(query, 64, "\u2026");
4189
+ const remembered = event.toolName === "rememberMemory" && typeof metadata.content === "string" ? metadata.content : "";
4190
+ if (remembered) return clipCompactText(redactSecrets(remembered), 64, "\u2026");
4191
+ return "";
4192
+ }
4193
+ var NORMAL_GIST_SECRET_PATTERNS = [
4194
+ /\bbearer\s+[A-Za-z0-9._~+/=-]{8,}/i,
4195
+ /\bsk-(?:ant-)?(?:api)?[0-9a-zA-Z-]{10,}/,
4196
+ /\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{10,}/,
4197
+ /\bxox[baprs]-[A-Za-z0-9-]{10,}/
4198
+ ];
4199
+ function withholdIfSecretLike(gist) {
4200
+ if (!gist) return "";
4201
+ if (findPotentialSecrets(gist).length > 0) return "";
4202
+ if (NORMAL_GIST_SECRET_PATTERNS.some((pattern) => pattern.test(gist))) return "";
4203
+ return gist;
4204
+ }
4205
+ function normalToolGist(event) {
4206
+ return withholdIfSecretLike(normalToolGistRaw(event));
4207
+ }
4208
+ function formatNormalToolDuration(elapsedMs) {
4209
+ if (typeof elapsedMs !== "number" || !Number.isFinite(elapsedMs) || elapsedMs <= 500) return "";
4210
+ if (elapsedMs < 1e3) return `${Math.round(elapsedMs)}ms`;
4211
+ return `${(elapsedMs / 1e3).toFixed(1)}s`;
4202
4212
  }
4203
4213
  function formatNormalToolLine(event, pending, colorEnabled) {
4204
4214
  if (event.type === "tool-call") return "";
@@ -4220,158 +4230,42 @@ function formatNormalToolLine(event, pending, colorEnabled) {
4220
4230
  return formatToolTraceLine(`\u25B8 ${label} ! ${t("toolNeedsAction")}`, colorEnabled, "error");
4221
4231
  }
4222
4232
  if (event.type === "tool-error") {
4223
- return formatToolTraceLine(`\u25B8 ${label} \u2717 ${t("toolFailed")}`, colorEnabled, "error");
4233
+ return formatToolTraceLine(`\u25B8 ${label} \u2717 ${toolFailureReason(event) || t("toolFailed")}`, colorEnabled, "error");
4224
4234
  }
4225
4235
  if (event.metadata?.timedOut) {
4226
4236
  return formatToolTraceLine(`\u25B8 ${label} \u2717 ${t("toolTimedOut")}`, colorEnabled, "error");
4227
4237
  }
4228
4238
  if (isFailedToolResult(event)) {
4229
- return formatToolTraceLine(`\u25B8 ${label} \u2717 ${t("toolFailed")}`, colorEnabled, "error");
4230
- }
4231
- return formatToolTraceLine(`\u25B8 ${label} \u2713`, colorEnabled);
4232
- }
4233
- function isReadToolName(name) {
4234
- if (!name) return false;
4235
- return name === "read" || name === "readFile" || name === "read_file" || name === "readWorkspaceFile";
4236
- }
4237
- function isSearchToolName(name) {
4238
- if (!name) return false;
4239
- return name === "grep" || name === "codeSearch" || name === "code_search" || name === "globFiles" || name === "glob_files" || name === "glob" || name === "searchWorkspace" || name === "search_workspace" || name === "search_all_spaces" || name === "search";
4240
- }
4241
- function isRunToolName(name) {
4242
- if (!name) return false;
4243
- return name === "execShell" || name === "runCommand" || name === "run_command" || name === "launchProcess";
4244
- }
4245
- function isFetchToolName(name) {
4246
- if (!name) return false;
4247
- return name === "fetchWebpage" || name === "fetch_webpage";
4248
- }
4249
- function isWebSearchToolName(name) {
4250
- if (!name) return false;
4251
- return name === "exa_search" || name === "exaSearch";
4252
- }
4253
- function isRunResultFoldable(event) {
4254
- return Boolean(event.metadata?.actionGate) === false;
4255
- }
4256
- function formatSearchTreeBlockForCli(items, colorEnabled) {
4257
- if (items.length === 0) return "";
4258
- const { count, lines } = formatSearchTreeLines(items);
4259
- const titleText = toolLabel("codeSearch");
4260
- if (!colorEnabled) {
4261
- const headerLine2 = `\u2022 ${titleText} (${count})
4262
- `;
4263
- const treeLines2 = lines.map((l) => ` ${l.connector}${l.queryText}`).join("\n");
4264
- return `${headerLine2}${treeLines2}
4265
- `;
4266
- }
4267
- const bullet = themeText("\u2022", "chrome", true);
4268
- const title = styleCliText(titleText, "bold", true);
4269
- const countText = themeText(`(${count})`, "muted", true);
4270
- const headerLine = `${bullet} ${title} ${countText}
4271
- `;
4272
- const treeLines = lines.map((l) => {
4273
- const connector = themeText(` ${l.connector}`, "chrome", true);
4274
- const queryText = themeText(l.queryText, "muted", true);
4275
- return `${connector}${queryText}`;
4276
- }).join("\n");
4277
- return `${headerLine}${treeLines}
4278
- `;
4279
- }
4280
- function formatReadTreeBlockForCli(items, colorEnabled) {
4281
- if (items.length === 0) return "";
4282
- const { count, lines } = formatReadTreeLines(items);
4283
- const titleText = toolLabel("readFile");
4284
- if (!colorEnabled) {
4285
- const headerLine2 = `\u2022 ${titleText} (${count})
4286
- `;
4287
- const treeLines2 = lines.map((l) => ` ${l.connector}${l.pathWithRange}`).join("\n");
4288
- return `${headerLine2}${treeLines2}
4289
- `;
4290
- }
4291
- const bullet = themeText("\u2022", "chrome", true);
4292
- const title = styleCliText(titleText, "bold", true);
4293
- const countText = themeText(`(${count})`, "muted", true);
4294
- const headerLine = `${bullet} ${title} ${countText}
4295
- `;
4296
- const treeLines = lines.map((l) => {
4297
- const connector = themeText(` ${l.connector}`, "chrome", true);
4298
- const pathText = themeText(l.pathWithRange, "muted", true);
4299
- return `${connector}${pathText}`;
4300
- }).join("\n");
4301
- return `${headerLine}${treeLines}
4302
- `;
4303
- }
4304
- function formatRunTreeBlockForCli(items, colorEnabled) {
4305
- if (items.length === 0) return "";
4306
- const { count, lines } = formatRunTreeLines(items);
4307
- const titleText = toolLabel("execShell");
4308
- if (!colorEnabled) {
4309
- const headerLine2 = `\u2022 ${titleText} (${count})
4310
- `;
4311
- const treeLines2 = lines.map((l) => ` ${l.connector}${l.commandText}`).join("\n");
4312
- return `${headerLine2}${treeLines2}
4313
- `;
4314
- }
4315
- const bullet = themeText("\u2022", "chrome", true);
4316
- const title = styleCliText(titleText, "bold", true);
4317
- const countText = themeText(`(${count})`, "muted", true);
4318
- const headerLine = `${bullet} ${title} ${countText}
4319
- `;
4320
- const treeLines = lines.map((l) => {
4321
- const connector = themeText(` ${l.connector}`, "chrome", true);
4322
- const commandText = themeText(l.commandText, "muted", true);
4323
- return `${connector}${commandText}`;
4324
- }).join("\n");
4325
- return `${headerLine}${treeLines}
4326
- `;
4327
- }
4328
- function formatWebSearchTreeBlockForCli(items, colorEnabled) {
4329
- if (items.length === 0) return "";
4330
- const { count, lines } = formatSearchTreeLines(items);
4331
- const titleText = toolLabel("exa_search");
4332
- if (!colorEnabled) {
4333
- const headerLine2 = `\u2022 ${titleText} (${count})
4334
- `;
4335
- const treeLines2 = lines.map((l) => ` ${l.connector}${l.queryText}`).join("\n");
4336
- return `${headerLine2}${treeLines2}
4337
- `;
4338
- }
4339
- const bullet = themeText("\u2022", "chrome", true);
4340
- const title = styleCliText(titleText, "bold", true);
4341
- const countText = themeText(`(${count})`, "muted", true);
4342
- const headerLine = `${bullet} ${title} ${countText}
4343
- `;
4344
- const treeLines = lines.map((l) => {
4345
- const connector = themeText(` ${l.connector}`, "chrome", true);
4346
- const queryText = themeText(l.queryText, "muted", true);
4347
- return `${connector}${queryText}`;
4348
- }).join("\n");
4349
- return `${headerLine}${treeLines}
4350
- `;
4351
- }
4352
- function formatFetchTreeBlockForCli(items, colorEnabled) {
4353
- if (items.length === 0) return "";
4354
- const { count, lines } = formatFetchTreeLines(items);
4355
- const titleText = toolLabel("fetchWebpage");
4356
- if (!colorEnabled) {
4357
- const headerLine2 = `\u2022 ${titleText} (${count})
4358
- `;
4359
- const treeLines2 = lines.map((l) => ` ${l.connector}${l.urlText}`).join("\n");
4360
- return `${headerLine2}${treeLines2}
4361
- `;
4362
- }
4363
- const bullet = themeText("\u2022", "chrome", true);
4364
- const title = styleCliText(titleText, "bold", true);
4365
- const countText = themeText(`(${count})`, "muted", true);
4366
- const headerLine = `${bullet} ${title} ${countText}
4367
- `;
4368
- const treeLines = lines.map((l) => {
4369
- const connector = themeText(` ${l.connector}`, "chrome", true);
4370
- const urlText = themeText(l.urlText, "muted", true);
4371
- return `${connector}${urlText}`;
4372
- }).join("\n");
4373
- return `${headerLine}${treeLines}
4374
- `;
4239
+ return formatToolTraceLine(`\u25B8 ${label} \u2717 ${toolFailureReason(event) || t("toolFailed")}`, colorEnabled, "error");
4240
+ }
4241
+ const gist = normalToolGist(event);
4242
+ const hint = editFileResultHint(event);
4243
+ const statsInline = hint?.inline ? ` ${hint.inline}` : "";
4244
+ const durationInline = formatNormalToolDuration(event.elapsedMs);
4245
+ const tail = durationInline ? ` \u2713 ${durationInline}` : " \u2713";
4246
+ const mainLine = formatToolTraceLine(
4247
+ gist ? `\u25B8 ${label} \xB7 ${gist}${statsInline}${tail}` : `\u25B8 ${label}${statsInline}${tail}`,
4248
+ colorEnabled
4249
+ );
4250
+ if (hint?.detail?.length) {
4251
+ const filePath = typeof event.metadata?.path === "string" ? event.metadata.path : void 0;
4252
+ return `${mainLine}${formatEditDetailBlock(hint.detail, colorEnabled, filePath)}`;
4253
+ }
4254
+ return mainLine;
4255
+ }
4256
+ function toolFailureReason(event) {
4257
+ const metadata = event.metadata ?? {};
4258
+ const rawError = metadata.error ?? metadata.errorMessage;
4259
+ const raw = typeof rawError === "string" && rawError.trim() || event.message?.trim() || typeof event.content === "string" && event.content.trim() || event.summary?.trim() || "";
4260
+ const lines = raw.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
4261
+ const sectionLines = (section) => {
4262
+ const start = lines.findIndex((line) => new RegExp(`^${section}\\s*:$`, "i").test(line));
4263
+ if (start < 0) return [];
4264
+ const end = lines.findIndex((line, index) => index > start && /^(stdout|stderr|exitCode)\s*:/i.test(line));
4265
+ return lines.slice(start + 1, end < 0 ? lines.length : end);
4266
+ };
4267
+ const reasonLine = sectionLines("stderr")[0] ?? sectionLines("stdout")[0] ?? lines.find((line) => !/^(stdout|stderr|exitCode)\s*:/i.test(line)) ?? lines[0] ?? "";
4268
+ return reasonLine ? clip(redactSecrets(stripAnsi2(reasonLine)), 96) : "";
4375
4269
  }
4376
4270
  function resolveLoadSkillName(event) {
4377
4271
  const metaName = typeof event.metadata?.name === "string" ? event.metadata.name : void 0;
@@ -4436,326 +4330,74 @@ function formatLoadSkillBlock(event, colorEnabled, opts) {
4436
4330
  return `${star} ${labelPart}: ${namePart}
4437
4331
  `;
4438
4332
  }
4439
- function formatCompactToolLine(event, pending, colorEnabled) {
4440
- const toolName = event.toolName || pending?.toolName || "tool";
4441
- const todoBlock = formatTodoListForCli(event, colorEnabled);
4442
- if (todoBlock) return todoBlock;
4443
- if (isReadToolName(toolName) && event.type === "tool-result") {
4444
- const rawPath = (typeof event.metadata?.path === "string" ? event.metadata.path : void 0) || (typeof event.metadata?.filePath === "string" ? event.metadata.filePath : void 0) || event.argumentsPreview || pending?.argumentsPreview || "";
4445
- return formatReadTreeBlockForCli([{ path: rawPath, metadata: event.metadata }], colorEnabled);
4446
- }
4447
- if (isSearchToolName(toolName) && event.type === "tool-result") {
4448
- const rawQuery = (typeof event.metadata?.query === "string" ? event.metadata.query : void 0) || (typeof event.metadata?.pattern === "string" ? event.metadata.pattern : void 0) || event.argumentsPreview || pending?.argumentsPreview || "";
4449
- const rawPath = typeof event.metadata?.path === "string" ? event.metadata.path : void 0;
4450
- return formatSearchTreeBlockForCli([{ query: rawQuery, path: rawPath }], colorEnabled);
4451
- }
4452
- if (isFetchToolName(toolName) && event.type === "tool-result") {
4453
- const rawUrl = (typeof event.metadata?.url === "string" ? event.metadata.url : void 0) || event.argumentsPreview || pending?.argumentsPreview || "";
4454
- return formatFetchTreeBlockForCli([{ url: rawUrl }], colorEnabled);
4455
- }
4456
- if (isRunToolName(toolName) && event.type === "tool-result" && isRunResultFoldable(event)) {
4457
- const rawCommand = (typeof event.metadata?.command === "string" ? event.metadata.command : void 0) || event.argumentsPreview || pending?.argumentsPreview || "";
4458
- const exitCode = typeof event.metadata?.exitCode === "number" ? event.metadata.exitCode : void 0;
4459
- const timedOut = Boolean(event.metadata?.timedOut);
4460
- return formatRunTreeBlockForCli([{ command: rawCommand, exitCode, timedOut }], colorEnabled);
4461
- }
4462
- const rawArgs = clipPathAware(event.argumentsPreview || pending?.argumentsPreview || "", 72);
4463
- const rawLabel = toolLabel(toolName);
4464
- const label = rawArgs ? `${rawLabel} ${rawArgs}` : rawLabel;
4465
- if (event.type === "tool-error") {
4466
- const message = clip(event.message ?? t("toolFailed"), 96);
4467
- return formatToolTraceLine(`\u25B8 ${label} \u2717 ${message}`, colorEnabled, "error");
4468
- }
4469
- const loadSkillBlock = formatLoadSkillBlock(event, colorEnabled);
4470
- if (loadSkillBlock) return loadSkillBlock;
4471
- if (event.type === "tool-result" && (toolName === "listAgents" || toolName === "startAgentRun" || toolName === "controlAgentRun")) {
4472
- return formatOrchestrationCardBlock(event, toolName, colorEnabled);
4473
- }
4474
- if (event.type === "tool-result" && (event.toolName === "ask_user" || event.metadata?.uiAskChoice)) {
4475
- const block = formatUiAskChoiceBlock(event, colorEnabled);
4476
- if (block) return block;
4477
- }
4478
- const hint = compactResultHint(event);
4479
- const suffix = hint.inline ? ` ${hint.inline}` : "";
4480
- const failed = isFailedToolResult(event);
4481
- const marker = failed ? "\u2717" : isNeedsActionToolResult(event) ? "!" : "\u2713";
4482
- let mainLine;
4483
- if (!colorEnabled) {
4484
- mainLine = `\u25B8 ${label} ${marker}${suffix}
4485
- `;
4486
- } else {
4487
- const chromePointer = themeText("\u25B8", "chrome", true);
4488
- const mutedLabel = themeText(rawLabel, "muted", true);
4489
- const argsPart = rawArgs ? ` ${dimCliText(rawArgs, true)}` : "";
4490
- const statusToken = failed ? themeText("\u2717", "danger", true) : isNeedsActionToolResult(event) ? themeText("!", "warning", true) : themeText("\u2713", "success", true);
4491
- const suffixPart = hint.inline ? ` ${dimCliText(hint.inline, true)}` : "";
4492
- mainLine = `${chromePointer} ${mutedLabel}${argsPart} ${statusToken}${suffixPart}
4493
- `;
4494
- }
4495
- if (!hint.detail?.length) return mainLine;
4496
- const filePath = typeof event.metadata?.path === "string" ? event.metadata.path : event.argumentsPreview;
4497
- return `${mainLine}${formatEditDetailBlock(hint.detail, colorEnabled, filePath)}`;
4498
- }
4499
- function formatEditDetailBlock(lines, colorEnabled, filePath, env = process.env) {
4500
- if (!colorEnabled) {
4501
- return lines.map((line) => ` ${line.text}
4502
- `).join("");
4503
- }
4504
- const isTruecolor = supportsTruecolor(env);
4505
- const lang = isTruecolor ? detectCodeLangFromPath(filePath) : "unknown";
4506
- const brightness = resolveTuiBrightness(env);
4507
- const padTo = Math.max(...lines.map((line) => displayWidth(line.text))) + 1;
4508
- return lines.map((line) => ` ${renderDiffLine({
4509
- kind: line.kind,
4510
- text: line.text,
4511
- highlightedText: shouldHighlightEditLine(line, lang, isTruecolor) ? buildHighlightedEditLine(line, lang, brightness, env) : void 0,
4512
- padTo,
4513
- colorEnabled: true,
4514
- env
4515
- })}
4516
- `).join("");
4517
- }
4518
- function shouldHighlightEditLine(line, lang, isTruecolor) {
4519
- if (!isTruecolor || lang === "unknown") return false;
4520
- if (line.text.startsWith(" \u2026") || line.text.startsWith("\u2026")) return false;
4521
- return line.text.length >= 2;
4522
- }
4523
- function buildHighlightedEditLine(line, lang, brightness, env) {
4524
- const prefix = line.text.slice(0, 2);
4525
- const body = line.text.slice(2);
4526
- const prefixToken = line.kind === "added" ? "success" : line.kind === "removed" ? "danger" : "chrome";
4527
- const coloredPrefix = themeText(prefix, prefixToken, true, env);
4528
- const highlightedBody = highlightCodeLine(body, lang, brightness);
4529
- return `${coloredPrefix}${highlightedBody}`;
4530
- }
4531
- function createToolEventFormatter(mode, colorEnabled = resolveCliColorEnabled(), opts = {}) {
4532
- const suppressRunProgressCards = opts.suppressRunProgressCards === true;
4333
+ var TUI_TREE_MARKER = "TUI_TREE\n";
4334
+ var TUI_TREE_END = "";
4335
+ function createToolEventFormatter(colorEnabled = resolveCliColorEnabled(), opts = {}) {
4533
4336
  const pending = /* @__PURE__ */ new Map();
4534
- let readBuffer = [];
4535
- let searchBuffer = [];
4536
- let runBuffer = [];
4537
- let fetchBuffer = [];
4538
- let webSearchBuffer = [];
4539
- let statusFold = null;
4540
- const lastEmittedLogByRunId = /* @__PURE__ */ new Map();
4541
- const lastPrintedCardByRunId = /* @__PURE__ */ new Map();
4542
- const cardSubstance = (snapshot) => JSON.stringify([
4543
- snapshot.status,
4544
- snapshot.toolCallCount ?? -1,
4545
- snapshot.lastToolNames ?? [],
4546
- snapshot.lastAssistantText ?? "",
4547
- snapshot.errorMessage ?? "",
4548
- snapshot.logKey
4549
- ]);
4550
- const flushStatusFold = () => {
4551
- if (!statusFold) return "";
4552
- const fold = statusFold;
4553
- statusFold = null;
4554
- const substance = cardSubstance(fold);
4555
- if (lastPrintedCardByRunId.get(fold.runId) === substance) return "";
4556
- const prevLog = lastEmittedLogByRunId.get(fold.runId);
4557
- const changed = Boolean(fold.logKey) && fold.logKey !== prevLog;
4558
- if (suppressRunProgressCards) {
4559
- const terminal = isAgentRunTerminalStatus(fold.status);
4560
- if (!terminal && !fold.errorMessage && !changed) {
4561
- lastPrintedCardByRunId.set(fold.runId, substance);
4562
- return "";
4563
- }
4337
+ let tree = null;
4338
+ const treeKind = (name) => isRunToolName(name) ? "Run" : isReadToolName(name) ? "Read" : name === "exa_search" ? "Search" : name === "fetchWebpage" ? "Fetch" : null;
4339
+ const treeLine = (kind, items) => {
4340
+ const label = kind === "Run" ? toolLabel("execShell") : kind === "Read" ? toolLabel("readFile") : kind === "Fetch" ? toolLabel("fetchWebpage") : toolLabel("exa_search");
4341
+ return `${TUI_TREE_MARKER}${label} (${items.length})
4342
+ ${items.map((item, i) => `${i === items.length - 1 ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 "}${item} \u2713`).join("\n")}${TUI_TREE_END}
4343
+ `;
4344
+ };
4345
+ const formatTreeEvent = (event, call) => {
4346
+ if (!opts.tuiTrees || event.type !== "tool-result") return null;
4347
+ if (isFailedToolResult(event) || event.metadata?.failed || event.metadata?.timedOut || readActionGate(event.metadata?.actionGate)) {
4348
+ tree = null;
4349
+ return null;
4564
4350
  }
4565
- lastPrintedCardByRunId.set(fold.runId, substance);
4566
- if (changed && runShowsLogTail(fold.status)) {
4567
- lastEmittedLogByRunId.set(fold.runId, fold.logKey);
4351
+ const name = event.toolName || call?.toolName || "tool";
4352
+ const kind = treeKind(name);
4353
+ if (!kind) {
4354
+ tree = null;
4355
+ return null;
4568
4356
  }
4569
- return formatFoldedControlStatusCard({ ...fold, includeLogTail: changed }, colorEnabled);
4357
+ let item = "";
4358
+ const m = event.metadata ?? {};
4359
+ if (kind === "Run") {
4360
+ const command = typeof m.command === "string" ? m.command : "";
4361
+ item = command ? formatRunItemCommand(command, typeof m.exitCode === "number" ? m.exitCode : void 0, Boolean(m.timedOut)) : "command";
4362
+ }
4363
+ if (kind === "Read") item = formatReadItemPath(typeof m.path === "string" ? m.path : typeof m.filePath === "string" ? m.filePath : "file", m);
4364
+ if (kind === "Search") item = formatSearchItemQuery(typeof m.query === "string" ? m.query : typeof m.pattern === "string" ? m.pattern : "search", typeof m.path === "string" ? m.path : void 0);
4365
+ if (kind === "Fetch") item = formatFetchItemUrl(typeof m.url === "string" ? m.url : "webpage");
4366
+ item = withholdIfSecretLike(item) || toolLabel(name);
4367
+ if (tree?.kind !== kind) tree = { kind, items: [] };
4368
+ tree.items.push(item);
4369
+ if (tree.items.length < 2) return formatNormalToolLine(event, call, colorEnabled);
4370
+ return treeLine(kind, tree.items);
4570
4371
  };
4571
- const flushToolBuffers = () => {
4572
- let out = "";
4573
- if (readBuffer.length > 0) {
4574
- const items = readBuffer.map((evt) => {
4575
- const call = pending.get(evt.toolCallId);
4576
- const rawPath = (typeof evt.metadata?.path === "string" ? evt.metadata.path : void 0) || (typeof evt.metadata?.filePath === "string" ? evt.metadata.filePath : void 0) || evt.argumentsPreview || call?.argumentsPreview || "";
4577
- return { path: rawPath, metadata: evt.metadata };
4578
- });
4579
- for (const evt of readBuffer) pending.delete(evt.toolCallId);
4580
- readBuffer = [];
4581
- out += formatReadTreeBlockForCli(items, colorEnabled);
4582
- }
4583
- if (searchBuffer.length > 0) {
4584
- const items = searchBuffer.map((evt) => {
4585
- const call = pending.get(evt.toolCallId);
4586
- const rawQuery = (typeof evt.metadata?.query === "string" ? evt.metadata.query : void 0) || (typeof evt.metadata?.pattern === "string" ? evt.metadata.pattern : void 0) || evt.argumentsPreview || call?.argumentsPreview || "";
4587
- const rawPath = typeof evt.metadata?.path === "string" ? evt.metadata.path : void 0;
4588
- return { query: rawQuery, path: rawPath };
4589
- });
4590
- for (const evt of searchBuffer) pending.delete(evt.toolCallId);
4591
- searchBuffer = [];
4592
- out += formatSearchTreeBlockForCli(items, colorEnabled);
4593
- }
4594
- if (runBuffer.length > 0) {
4595
- const items = runBuffer.map((evt) => {
4596
- const call = pending.get(evt.toolCallId);
4597
- const rawCommand = (typeof evt.metadata?.command === "string" ? evt.metadata.command : void 0) || evt.argumentsPreview || call?.argumentsPreview || "";
4598
- const exitCode = typeof evt.metadata?.exitCode === "number" ? evt.metadata.exitCode : void 0;
4599
- const timedOut = Boolean(evt.metadata?.timedOut);
4600
- return { command: rawCommand, exitCode, timedOut };
4601
- });
4602
- for (const evt of runBuffer) pending.delete(evt.toolCallId);
4603
- runBuffer = [];
4604
- out += formatRunTreeBlockForCli(items, colorEnabled);
4605
- }
4606
- if (fetchBuffer.length > 0) {
4607
- const items = fetchBuffer.map((evt) => {
4608
- const call = pending.get(evt.toolCallId);
4609
- const rawUrl = (typeof evt.metadata?.url === "string" ? evt.metadata.url : void 0) || evt.argumentsPreview || call?.argumentsPreview || "";
4610
- return { url: rawUrl };
4611
- });
4612
- for (const evt of fetchBuffer) pending.delete(evt.toolCallId);
4613
- fetchBuffer = [];
4614
- out += formatFetchTreeBlockForCli(items, colorEnabled);
4615
- }
4616
- if (webSearchBuffer.length > 0) {
4617
- const items = webSearchBuffer.map((evt) => {
4618
- const call = pending.get(evt.toolCallId);
4619
- const rawQuery = (typeof evt.metadata?.query === "string" ? evt.metadata.query : void 0) || (typeof evt.metadata?.pattern === "string" ? evt.metadata.pattern : void 0) || evt.argumentsPreview || call?.argumentsPreview || "";
4620
- return { query: rawQuery };
4372
+ const format = (event) => {
4373
+ if (event.type === "tool-call") {
4374
+ pending.set(event.toolCallId, {
4375
+ toolName: event.toolName,
4376
+ argumentsPreview: event.argumentsPreview
4621
4377
  });
4622
- for (const evt of webSearchBuffer) pending.delete(evt.toolCallId);
4623
- webSearchBuffer = [];
4624
- out += formatWebSearchTreeBlockForCli(items, colorEnabled);
4378
+ return "";
4625
4379
  }
4626
- return out;
4380
+ const call = pending.get(event.toolCallId);
4381
+ pending.delete(event.toolCallId);
4382
+ const treeOutput = formatTreeEvent(event, call);
4383
+ if (treeOutput !== null) return treeOutput;
4384
+ return formatNormalToolLine(event, call, colorEnabled);
4627
4385
  };
4628
- const flushBuffers = () => `${flushStatusFold()}${flushToolBuffers()}`;
4629
- const bufferToolResult = (buffer, event) => {
4630
- const flushed = flushStatusFold();
4631
- buffer.push(event);
4632
- return flushed;
4386
+ format.reset = () => {
4387
+ tree = null;
4633
4388
  };
4634
- const formatter = (event) => {
4635
- if (mode === "hide") return "";
4636
- if (mode === "verbose") return formatVerboseToolEvent(event, colorEnabled);
4637
- if (mode === "normal") {
4638
- if (event.type === "tool-call") {
4639
- pending.set(event.toolCallId, {
4640
- toolName: event.toolName,
4641
- argumentsPreview: event.argumentsPreview
4642
- });
4643
- return "";
4644
- }
4645
- const call2 = pending.get(event.toolCallId);
4646
- pending.delete(event.toolCallId);
4647
- return formatNormalToolLine(event, call2, colorEnabled);
4648
- }
4649
- if (event.toolName === "controlAgentRun") {
4650
- if (event.type === "tool-call") {
4651
- pending.set(event.toolCallId, {
4652
- toolName: event.toolName,
4653
- argumentsPreview: event.argumentsPreview
4654
- });
4655
- return "";
4656
- }
4657
- if (event.type === "tool-result") {
4658
- const snapshot = parseControlAgentRunStatusEvent(event);
4659
- if (snapshot) {
4660
- let out = flushToolBuffers();
4661
- const open = statusFold;
4662
- const sameRun = open?.runId === snapshot.runId;
4663
- if (open && (!sameRun || open.status !== snapshot.status)) {
4664
- out += flushStatusFold();
4665
- }
4666
- statusFold = open && sameRun ? mergeRunSnapshot(open, snapshot) : snapshot;
4667
- pending.delete(event.toolCallId);
4668
- if (isAgentRunTerminalStatus(snapshot.status)) {
4669
- out += flushBuffers();
4670
- }
4671
- return out;
4672
- }
4673
- const flushed2 = flushBuffers();
4674
- const call2 = pending.get(event.toolCallId);
4675
- pending.delete(event.toolCallId);
4676
- return `${flushed2}${formatCompactToolLine(event, call2, colorEnabled)}`;
4677
- }
4678
- }
4679
- if (isReadToolName(event.toolName)) {
4680
- if (event.type === "tool-call") {
4681
- pending.set(event.toolCallId, {
4682
- toolName: event.toolName,
4683
- argumentsPreview: event.argumentsPreview
4684
- });
4685
- return "";
4686
- }
4687
- if (event.type === "tool-result") {
4688
- return bufferToolResult(readBuffer, event);
4689
- }
4690
- }
4691
- if (isSearchToolName(event.toolName)) {
4692
- if (event.type === "tool-call") {
4693
- pending.set(event.toolCallId, {
4694
- toolName: event.toolName,
4695
- argumentsPreview: event.argumentsPreview
4696
- });
4697
- return "";
4698
- }
4699
- if (event.type === "tool-result") {
4700
- return bufferToolResult(searchBuffer, event);
4701
- }
4702
- }
4703
- if (isRunToolName(event.toolName)) {
4704
- if (event.type === "tool-result" && !isRunResultFoldable(event)) {
4705
- const flushed2 = flushBuffers();
4706
- const call2 = pending.get(event.toolCallId);
4707
- pending.delete(event.toolCallId);
4708
- return `${flushed2}${formatCompactToolLine(event, call2, colorEnabled)}`;
4709
- }
4710
- if (event.type === "tool-call") {
4711
- pending.set(event.toolCallId, {
4712
- toolName: event.toolName,
4713
- argumentsPreview: event.argumentsPreview
4714
- });
4715
- return "";
4716
- }
4717
- if (event.type === "tool-result") {
4718
- return bufferToolResult(runBuffer, event);
4719
- }
4720
- }
4721
- if (isFetchToolName(event.toolName)) {
4722
- if (event.type === "tool-call") {
4723
- pending.set(event.toolCallId, {
4724
- toolName: event.toolName,
4725
- argumentsPreview: event.argumentsPreview
4726
- });
4727
- return "";
4728
- }
4729
- if (event.type === "tool-result") {
4730
- return bufferToolResult(fetchBuffer, event);
4731
- }
4732
- }
4733
- if (isWebSearchToolName(event.toolName)) {
4734
- if (event.type === "tool-call") {
4735
- pending.set(event.toolCallId, {
4736
- toolName: event.toolName,
4737
- argumentsPreview: event.argumentsPreview
4738
- });
4739
- return "";
4740
- }
4741
- if (event.type === "tool-result") {
4742
- return bufferToolResult(webSearchBuffer, event);
4743
- }
4744
- }
4745
- const flushed = flushBuffers();
4389
+ format.consume = (event) => {
4746
4390
  if (event.type === "tool-call") {
4747
4391
  pending.set(event.toolCallId, {
4748
4392
  toolName: event.toolName,
4749
4393
  argumentsPreview: event.argumentsPreview
4750
4394
  });
4751
- return flushed;
4395
+ return;
4752
4396
  }
4753
- const call = pending.get(event.toolCallId);
4754
4397
  pending.delete(event.toolCallId);
4755
- return `${flushed}${formatCompactToolLine(event, call, colorEnabled)}`;
4398
+ tree = null;
4756
4399
  };
4757
- formatter.flush = flushBuffers;
4758
- return formatter;
4400
+ return format;
4759
4401
  }
4760
4402
  function createSseToolEventAdapter(onEvent) {
4761
4403
  let round = 0;
@@ -4923,6 +4565,13 @@ ${this.text}
4923
4565
 
4924
4566
  // packages/cli/client/agentRunOutput.ts
4925
4567
  var IDENTITY_LABEL_SEPARATOR = " > ";
4568
+ var THINKING_PREVIEW_BUFFER_LIMIT = 512;
4569
+ function appendThinkingPreview(current, chunk, limit = THINKING_PREVIEW_BUFFER_LIMIT) {
4570
+ if (limit <= 0) return "";
4571
+ const combined = current + chunk;
4572
+ if (combined.length <= limit) return combined;
4573
+ return combined.slice(combined.length - limit);
4574
+ }
4926
4575
  function formatCompactionSummaryLine(event) {
4927
4576
  if (!event) return "";
4928
4577
  const action = event.reason === "tool_stub" ? "stub \u5DE5\u5177\u8F93\u51FA" : "\u751F\u6210\u5386\u53F2\u6458\u8981";
@@ -4973,10 +4622,8 @@ function createCliTurnOutput(params) {
4973
4622
  const { options } = params;
4974
4623
  const workingLabel = params.workingLabel ?? `${options.agentName} -> working`;
4975
4624
  const spinner = params.spinner ?? new Spinner(options.output, workingLabel, Boolean(options.activityReporter));
4976
- const toolDisplayMode = resolveToolDisplayMode(options.env);
4977
- const traceLocalTools = shouldEmitToolEvents(toolDisplayMode);
4978
- const formatToolEvent = createToolEventFormatter(toolDisplayMode, void 0, {
4979
- suppressRunProgressCards: typeof options.onAgentRunStatus === "function"
4625
+ const formatToolEvent = createToolEventFormatter(void 0, {
4626
+ tuiTrees: options.output.tuiTrees === true
4980
4627
  });
4981
4628
  const eventMode = resolveAgentEventMode(options);
4982
4629
  const showThinking = options.showThinking !== false;
@@ -4985,25 +4632,42 @@ function createCliTurnOutput(params) {
4985
4632
  let printedAssistantLabel = false;
4986
4633
  let thinkState = createThinkParserState();
4987
4634
  let thinkingFirstAt = null;
4988
- let thinkingLastAt = 0;
4989
- const markThinkingActivity = () => {
4990
- const now = Date.now();
4991
- if (thinkingFirstAt === null) thinkingFirstAt = now;
4992
- thinkingLastAt = now;
4635
+ let thinkingPreview = "";
4636
+ const markThinkingDelta = (chunk) => {
4637
+ if (!showThinking) return;
4638
+ if (streamedAssistantText) return;
4639
+ if (thinkingFirstAt === null) {
4640
+ thinkingFirstAt = Date.now();
4641
+ thinkingPreview = "";
4642
+ }
4643
+ thinkingPreview = appendThinkingPreview(thinkingPreview, chunk);
4644
+ spinner.setThinkingHint(thinkingPreview);
4645
+ reportThinkingProgress();
4646
+ };
4647
+ const reportThinkingProgress = () => {
4648
+ if (!showThinking) return;
4649
+ const preview = truncateThinkingHint(thinkingPreview, 60);
4650
+ const label = preview ? t("thinkingActivePreview", preview) : t("thinkingActive");
4651
+ options.activityReporter?.(label);
4993
4652
  };
4994
- const writeThinkingTrace = () => {
4653
+ const endThinkingPhase = () => {
4995
4654
  if (thinkingFirstAt === null) return;
4996
- const seconds = Math.max(0, Math.round((thinkingLastAt - thinkingFirstAt) / 1e3));
4655
+ const seconds = Math.max(0, Math.round((Date.now() - thinkingFirstAt) / 1e3));
4997
4656
  thinkingFirstAt = null;
4998
- options.output.write(`${dimCliText(t("thinkingTraceLine", formatElapsed(seconds)))}
4657
+ thinkingPreview = "";
4658
+ spinner.stop();
4659
+ options.activityReporter?.(null);
4660
+ if (seconds >= 1) {
4661
+ options.output.write(`${dimCliText(t("thinkingTraceLine", formatElapsed(seconds)))}
4999
4662
  `);
4663
+ }
5000
4664
  };
5001
4665
  let compactionEvent = null;
5002
4666
  const assistantLabelManaged = options.output.assistantLabelManaged === true;
5003
4667
  const writeToolOutput = (chunk) => {
5004
4668
  if (!chunk) return;
5005
4669
  if (typeof options.output.writeToolBlock === "function") {
5006
- options.output.writeToolBlock(chunk);
4670
+ if (!options.output.writeToolBlock(chunk)) formatToolEvent.reset?.();
5007
4671
  } else {
5008
4672
  options.output.write(chunk);
5009
4673
  }
@@ -5013,17 +4677,15 @@ function createCliTurnOutput(params) {
5013
4677
  });
5014
4678
  const writeVisibleAssistantChunk = (chunk) => {
5015
4679
  if (!chunk) return;
4680
+ formatToolEvent.reset?.();
5016
4681
  const parsed = processThinkChunk(chunk, thinkState);
5017
4682
  thinkState = parsed.state;
5018
4683
  if (!parsed.content && !parsed.reasoning) return;
5019
- if (showThinking && parsed.reasoning) {
5020
- markThinkingActivity();
5021
- spinner.setThinkingHint(parsed.reasoning);
4684
+ if (parsed.reasoning) {
4685
+ markThinkingDelta(parsed.reasoning);
5022
4686
  }
5023
4687
  if (!parsed.content) return;
5024
- writeThinkingTrace();
5025
- spinner.stop();
5026
- options.activityReporter?.(null);
4688
+ endThinkingPhase();
5027
4689
  if (!printedAssistantLabel) {
5028
4690
  if (!assistantLabelManaged) {
5029
4691
  options.output.write(`
@@ -5036,55 +4698,53 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
5036
4698
  renderWriter.push(parsed.content);
5037
4699
  };
5038
4700
  const handleToolEvent = (event) => {
5039
- if (!traceLocalTools) return;
5040
- const chunk = eventMode === "jsonl" ? formatToolJsonEvent(event) : formatToolEvent(event);
5041
4701
  if (eventMode === "jsonl") {
5042
- options.output.write(chunk);
4702
+ const chunk2 = formatToolJsonEvent(event);
4703
+ options.output.write(chunk2);
4704
+ if (options.onAgentRunStatus) {
4705
+ const parsed = parseAgentRunEvent(event);
4706
+ if (parsed) {
4707
+ options.onAgentRunStatus(parsed.snapshot);
4708
+ }
4709
+ }
5043
4710
  return;
5044
4711
  }
5045
4712
  if (event.type === "tool-call") {
5046
4713
  renderWriter.flush();
4714
+ formatToolEvent(event);
4715
+ endThinkingPhase();
4716
+ if (streamedAssistantText) {
4717
+ options.output.write("\n");
4718
+ streamedAssistantText = false;
4719
+ }
4720
+ const activeLabel = formatConservativeActiveToolLabel(event);
4721
+ spinner.show(activeLabel);
4722
+ options.activityReporter?.(activeLabel);
4723
+ return;
4724
+ }
4725
+ const parsedRunEvent = parseAgentRunEvent(event);
4726
+ if (options.onAgentRunStatus && parsedRunEvent) {
4727
+ options.onAgentRunStatus(parsedRunEvent.snapshot);
5047
4728
  }
5048
4729
  spinner.stop();
5049
4730
  options.activityReporter?.(null);
5050
- if (event.type === "tool-call" && streamedAssistantText) {
5051
- options.output.write("\n");
5052
- streamedAssistantText = false;
4731
+ if (isLiveAgentRunObservation(event, parsedRunEvent)) {
4732
+ formatToolEvent.consume?.(event);
4733
+ return;
5053
4734
  }
4735
+ const chunk = formatToolEvent(event);
5054
4736
  if (chunk) {
5055
4737
  writeToolOutput(chunk);
5056
4738
  }
5057
- if ((toolDisplayMode === "compact" || toolDisplayMode === "pro" || toolDisplayMode === "normal") && event.type === "tool-call") {
5058
- const activeLabel = toolDisplayMode === "normal" ? formatConservativeActiveToolLabel(event) : formatActiveToolLabel(event);
5059
- spinner.show(activeLabel);
5060
- options.activityReporter?.(activeLabel);
5061
- }
5062
- if (options.onAgentRunStatus) {
5063
- const parsed = parseAgentRunEvent(event);
5064
- if (parsed) {
5065
- options.onAgentRunStatus(parsed.snapshot);
5066
- }
5067
- }
5068
4739
  };
5069
4740
  return {
5070
4741
  spinner,
5071
- toolDisplayMode,
5072
- traceLocalTools,
5073
4742
  eventMode,
5074
4743
  pushText(chunk) {
5075
- if (eventMode !== "jsonl" && formatToolEvent.flush) {
5076
- const pendingToolOutput = formatToolEvent.flush();
5077
- if (pendingToolOutput) {
5078
- writeToolOutput(pendingToolOutput);
5079
- }
5080
- }
5081
4744
  writeVisibleAssistantChunk(chunk);
5082
4745
  },
5083
4746
  pushThinking(chunk) {
5084
- if (showThinking) {
5085
- markThinkingActivity();
5086
- spinner.setThinkingHint(chunk);
5087
- }
4747
+ markThinkingDelta(chunk);
5088
4748
  },
5089
4749
  handleToolEvent,
5090
4750
  /** 记录一条 compaction 观测事件(TUI 在 turn 结束时渲染一行 dim 摘要)。 */
@@ -5097,18 +4757,14 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
5097
4757
  options.activityReporter?.(activeLabel);
5098
4758
  },
5099
4759
  finish(fallbackContent) {
5100
- spinner.stop();
5101
- options.activityReporter?.(null);
5102
- writeThinkingTrace();
5103
4760
  const flushedThink = flushThinkParser(thinkState);
5104
4761
  thinkState = flushedThink.state;
5105
4762
  if (flushedThink.content) {
5106
4763
  writeVisibleAssistantChunk(flushedThink.content);
5107
4764
  }
5108
- const pendingToolOutput = formatToolEvent.flush ? formatToolEvent.flush() : "";
5109
- if (pendingToolOutput) {
5110
- writeToolOutput(pendingToolOutput);
5111
- }
4765
+ endThinkingPhase();
4766
+ spinner.stop();
4767
+ options.activityReporter?.(null);
5112
4768
  if (streamedAssistantText) {
5113
4769
  renderWriter.flush();
5114
4770
  options.output.write("\n");
@@ -5309,58 +4965,15 @@ ${describeClientVersionTooOldFailure(message, error)}`);
5309
4965
  if (usageText && shouldShowUsage(options.env))
5310
4966
  options.output.write(`${usageText}
5311
4967
  `);
4968
+ const turnCredits = platformCreditsFromUsage(usage);
5312
4969
  return {
5313
4970
  exitCode: 0,
5314
4971
  ...dialogId ? { dialogId } : {},
5315
- turnTokens: buildTurnTokenUsage(usage, options.agentKey)
4972
+ turnTokens: buildTurnTokenUsage(usage, options.agentKey),
4973
+ ...turnCredits !== void 0 ? { turnCredits } : {}
5316
4974
  };
5317
4975
  }
5318
4976
 
5319
- // packages/cli/client/agentRunTypes.ts
5320
- function resolveAuthToken2(env) {
5321
- return resolvePlatformAuthToken(env);
5322
- }
5323
- function resolveFileWriteGateEnabled(env) {
5324
- const raw = (env.NOLO_CLI_WRITE_GATE ?? "").trim().toLowerCase();
5325
- return raw !== "off" && raw !== "0" && raw !== "false";
5326
- }
5327
- function isMachineBoundLocalhostCustomProvider(agentConfig) {
5328
- const machineId = agentConfig?.runtimeBinding && typeof agentConfig.runtimeBinding === "object" ? String(agentConfig.runtimeBinding.machineId ?? "").trim() : "";
5329
- const providerUrl = asTrimmedString(agentConfig?.customProviderUrl);
5330
- if (!machineId || !providerUrl) return false;
5331
- return isLoopbackUrl(providerUrl);
5332
- }
5333
- function resolveBoundMachineId(agentConfig) {
5334
- return agentConfig?.runtimeBinding && typeof agentConfig.runtimeBinding === "object" ? String(agentConfig.runtimeBinding.machineId ?? "").trim() : "";
5335
- }
5336
- var CLI_PROVIDER_NAMES = /* @__PURE__ */ new Set([
5337
- "agy",
5338
- "claude",
5339
- "codex",
5340
- "copilot",
5341
- "gemini",
5342
- "grok",
5343
- "kimi",
5344
- "opencode",
5345
- "qoder"
5346
- ]);
5347
- function isCliProviderAgentConfig(agentConfig) {
5348
- const cliProvider = asTrimmedLowercaseString(agentConfig?.cliProvider);
5349
- const provider = asTrimmedLowercaseString(agentConfig?.provider);
5350
- return Boolean(cliProvider) || CLI_PROVIDER_NAMES.has(provider);
5351
- }
5352
- async function detectCurrentMachineId(env) {
5353
- const fromEnv = (env.NOLO_CURRENT_MACHINE_ID || env.NOLO_MACHINE_ID || "").trim();
5354
- if (fromEnv) return fromEnv;
5355
- try {
5356
- const { detectMachineInfo } = await import("./machineInfo-66ZFUMLE.js");
5357
- const machine = await detectMachineInfo({ probeLaunchable: true });
5358
- return asOptionalTrimmedString(machine?.machineId);
5359
- } catch {
5360
- return void 0;
5361
- }
5362
- }
5363
-
5364
4977
  // packages/cli/client/agentRunPlatformTools.ts
5365
4978
  var SERVER_PLATFORM_TOOL_NAMES = /* @__PURE__ */ new Set([
5366
4979
  "addTableRow",
@@ -5370,28 +4983,6 @@ var SERVER_PLATFORM_TOOL_NAMES = /* @__PURE__ */ new Set([
5370
4983
  "updateTableRow",
5371
4984
  "updateTableRows"
5372
4985
  ]);
5373
- var KNOWN_SERVER_PLATFORM_AGENT_KEYS = /* @__PURE__ */ new Set([NOLO_PROJECT_MANAGER_AGENT_KEY]);
5374
- var KNOWN_SERVER_PLATFORM_AGENT_ALIASES = /* @__PURE__ */ new Set([
5375
- "code-review",
5376
- "frontend",
5377
- "frontend-agent",
5378
- "frontend-implementer",
5379
- "full-stack",
5380
- "fullstack",
5381
- "nolo code review",
5382
- "nolo fullstack",
5383
- "nolo project manager",
5384
- "nolo reviewer",
5385
- "nolo-code-review",
5386
- "nolo-fullstack",
5387
- "nolo-pm",
5388
- "nolo-project-manager",
5389
- "nolo-reviewer",
5390
- "pm",
5391
- "project-manager",
5392
- "review",
5393
- "reviewer"
5394
- ]);
5395
4986
  function findServerPlatformTools(toolNames) {
5396
4987
  if (!Array.isArray(toolNames)) return [];
5397
4988
  return toolNames.filter(
@@ -5404,13 +4995,6 @@ function resolveServerPlatformToolNames(agentConfig) {
5404
4995
  ...Array.isArray(agentConfig?.runtimeToolPolicy?.agentTools) ? agentConfig.runtimeToolPolicy.agentTools : []
5405
4996
  ]);
5406
4997
  }
5407
- function isKnownServerPlatformAgent(options) {
5408
- if (KNOWN_SERVER_PLATFORM_AGENT_KEYS.has(options.agentKey)) return true;
5409
- const normalizedKey = normalizeAgentHandle(options.agentKey);
5410
- return Boolean(
5411
- normalizedKey && KNOWN_SERVER_PLATFORM_AGENT_ALIASES.has(normalizedKey)
5412
- );
5413
- }
5414
4998
 
5415
4999
  // packages/core/collapsedPaste.ts
5416
5000
  var COLLAPSE_PASTE_MIN_LINES = 8;
@@ -5592,10 +5176,14 @@ function findCollapsedPasteSpanAt(buffer, pos, opts = {}) {
5592
5176
  // packages/cli/client/agentRun.ts
5593
5177
  import { ulid } from "ulid";
5594
5178
  async function loadRunLocalAgentTurn() {
5595
- const { runLocalAgentTurn } = await import("./agentRuntimeLocal-PCJJ56J2.js");
5179
+ const { runLocalAgentTurn } = await import("./agentRuntimeLocal-XCJLRWQE.js");
5596
5180
  return runLocalAgentTurn;
5597
5181
  }
5598
5182
  var stripDebugNoise = (s) => s.replace(/\s*raw="[\s\S]*"/g, "").replace(/\s*raw=\S+/g, "").replace(/\s*headers=\[[^\]]*\]/g, "").replace(/\s*headers=\S+/g, "").trim();
5183
+ var pickEmptyAssistantFlags = (result) => ({
5184
+ ...result.emptyAssistantFallbackReason ? { emptyAssistantFallbackReason: result.emptyAssistantFallbackReason } : {},
5185
+ ...result.emptyAssistantOutputUsable ? { emptyAssistantOutputUsable: true } : {}
5186
+ });
5599
5187
  function extractEmbeddedErrorMessage(message) {
5600
5188
  const match = /"message"\s*:\s*"((?:[^"\\]|\\.)*)"/.exec(message);
5601
5189
  if (!match) return void 0;
@@ -5710,25 +5298,44 @@ function wrapLoadAgentConfigWithModelOverride(adapter, targetAgentKey, override)
5710
5298
  }
5711
5299
  };
5712
5300
  }
5301
+ var oauthChannelSkipReportedOutputs = /* @__PURE__ */ new WeakSet();
5302
+ function resolveOAuthChannelOwnerSkip(agentConfig, options) {
5303
+ if (!agentConfig) return null;
5304
+ const apiKeyRef = typeof agentConfig.apiKeyRef === "string" ? agentConfig.apiKeyRef : void 0;
5305
+ if (!isOAuthApiKeyRef(apiKeyRef) && !isAntigravityOAuthAgent(agentConfig)) {
5306
+ return null;
5307
+ }
5308
+ const rawRecord = agentConfig.rawRecord ?? {};
5309
+ const ownerUserId = asOptionalTrimmedString(rawRecord.userId) ?? asOptionalTrimmedString(rawRecord.ownerUserId);
5310
+ if (!ownerUserId) return null;
5311
+ const localUserId = resolveLocalUserId(options.env);
5312
+ if (ownerUserId === localUserId) return null;
5313
+ return `[nolo] auto runtime: skipping local runtime because ${options.agentKey} runs on its owner's OAuth subscription channel (owner ${ownerUserId}, this machine runs as ${localUserId}). Use --local explicitly to force this machine's own subscription.
5314
+ `;
5315
+ }
5713
5316
  async function shouldSkipAutoLocalForServerPlatformTools(options) {
5714
5317
  if (isBuiltinNoloAgentRef(options.agentKey)) return false;
5715
- if (options.localRuntimeCwd) {
5318
+ const adapter = resolveLocalRuntimeAdapter(options);
5319
+ if (!adapter) {
5716
5320
  return false;
5717
5321
  }
5718
- const knownServerPlatformAgent = isKnownServerPlatformAgent(options);
5719
- const adapter = resolveLocalRuntimeAdapter(options);
5720
- if (!adapter) return knownServerPlatformAgent;
5721
5322
  let agentConfig;
5722
5323
  try {
5723
5324
  agentConfig = await adapter.loadAgentConfig(options.agentKey);
5724
5325
  } catch {
5725
- if (knownServerPlatformAgent) {
5726
- options.output.write(
5727
- `[nolo] auto runtime: skipping local runtime because ${options.agentKey} is a known platform agent. Use --local explicitly to force local workspace tools.
5728
- `
5729
- );
5730
- return true;
5326
+ return false;
5327
+ }
5328
+ const oauthChannelOwnerSkip = resolveOAuthChannelOwnerSkip(agentConfig, options);
5329
+ if (oauthChannelOwnerSkip) {
5330
+ if (!options.output || typeof options.output !== "object" || !oauthChannelSkipReportedOutputs.has(options.output)) {
5331
+ if (options.output && typeof options.output === "object") {
5332
+ oauthChannelSkipReportedOutputs.add(options.output);
5333
+ }
5334
+ options.output.write(oauthChannelOwnerSkip);
5731
5335
  }
5336
+ return true;
5337
+ }
5338
+ if (options.localRuntimeCwd) {
5732
5339
  return false;
5733
5340
  }
5734
5341
  if (isCliProviderAgentConfig(agentConfig)) {
@@ -5741,10 +5348,12 @@ async function shouldSkipAutoLocalForServerPlatformTools(options) {
5741
5348
  );
5742
5349
  return true;
5743
5350
  }
5744
- if (knownServerPlatformAgent) {
5351
+ if (resolveBoundMachineId(agentConfig)) {
5352
+ const currentMachineId = (await resolveCurrentMachineId(options))?.trim() || "";
5353
+ const boundMachineId = resolveBoundMachineId(agentConfig);
5354
+ if (currentMachineId && currentMachineId === boundMachineId) return false;
5745
5355
  options.output.write(
5746
- `[nolo] auto runtime: skipping local runtime because ${options.agentKey} is a known platform agent. Use --local explicitly to force local workspace tools.
5747
- `
5356
+ `[nolo] auto runtime: skipping local runtime because ${options.agentKey} is a platform agent bound to machine ${boundMachineId}` + (currentMachineId ? ` (this machine is ${currentMachineId}).` : ".") + " The server will dispatch it to the bound machine connector.\n"
5748
5357
  );
5749
5358
  return true;
5750
5359
  }
@@ -5822,9 +5431,12 @@ function classifyLocalRunError(message) {
5822
5431
  if (!m) return { kind: "generic" };
5823
5432
  const status = Number(m[2]);
5824
5433
  const transport = PLATFORM_TRANSPORT_RE.test(message) ? "platform" : "local";
5825
- if (status === 401 || status === 403) {
5434
+ if (status === 401) {
5826
5435
  return { kind: "auth", transport, status };
5827
5436
  }
5437
+ if (status === 403) {
5438
+ return isQuotaLimited403Body(message) ? { kind: "rate-limit", transport, status } : { kind: "auth", transport, status };
5439
+ }
5828
5440
  if (status === 400 || status === 422) {
5829
5441
  return { kind: "rejected-payload", transport, status };
5830
5442
  }
@@ -5841,10 +5453,14 @@ var RUN_UNAVAILABLE_PREFIX = "[nolo] auto runtime: local run unavailable";
5841
5453
  var NO_FALLBACK = "Not falling back to server.";
5842
5454
  var SERVER_FALLBACK_HINT = "or use --server to run on the server explicitly.";
5843
5455
  function buildAuthFailure(ctx) {
5844
- const fix = ctx.where === "server chat proxy" ? `Check the agent's provider/api-key settings on nolo.chat` : `Fix the local credential/config and retry`;
5456
+ const platformNoToken = ctx.where === "server chat proxy" && isAuthNoTokenBody(ctx.message);
5457
+ const fix = platformNoToken ? `This install is not logged in \u2014 run \`nolo login\`, or set AUTH_TOKEN / NOLO_SERVER` : ctx.where === "server chat proxy" ? `Check the agent's provider/api-key settings on nolo.chat` : `Fix the local credential/config and retry`;
5845
5458
  return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}, auth rejected). Detail: ${ctx.message} ${NO_FALLBACK} ${fix}, ${SERVER_FALLBACK_HINT}.
5846
5459
  `;
5847
5460
  }
5461
+ function isAuthNoTokenBody(message) {
5462
+ return /"authCode"\s*:\s*"AUTH_NO_TOKEN"/i.test(message) || /no authentication token provided/i.test(message);
5463
+ }
5848
5464
  function buildRejectedPayloadFailure(ctx) {
5849
5465
  const looksLikeHistoryReplay = HISTORY_REPLAY_REJECTION_RE.test(ctx.message);
5850
5466
  const cause = looksLikeHistoryReplay ? ` This usually happens when the dialog history contains tool_calls or reasoning produced by a different model/provider (e.g. after /switch); the new provider rejects that history. Start a fresh dialog, or clean the offending history.` : "";
@@ -5873,6 +5489,9 @@ var FAILURE_BUILDERS = {
5873
5489
  upstream: buildUpstreamFailure
5874
5490
  };
5875
5491
  function describeLocalRunFailure(message, rawError) {
5492
+ if (rawError && typeof rawError === "object" && "code" in rawError && rawError.code === "PLATFORM_STREAM_INTERRUPTED") {
5493
+ return "[nolo] The platform LLM stream was interrupted before the turn completed. Your conversation was preserved. Send another message to continue.\n";
5494
+ }
5876
5495
  if (isClientVersionTooOldFailure(message, rawError)) {
5877
5496
  return describeClientVersionTooOldFailure(message, rawError);
5878
5497
  }
@@ -5903,6 +5522,26 @@ function describeLocalRunFailure(message, rawError) {
5903
5522
  balanceDetails.current
5904
5523
  ) : extractEmbeddedErrorMessage(cleanedMessage) ?? fallback;
5905
5524
  return `[nolo] ${shownMessage}
5525
+ `;
5526
+ }
5527
+ if (isCliAuthorityBrokerTimeoutError(rawError) || /CLI authority broker .* timed out/i.test(message)) {
5528
+ const cleaned = stripDebugNoise(message);
5529
+ return `${RUN_UNAVAILABLE_PREFIX} (${cleaned}). ${NO_FALLBACK} The local authority broker timed out and did not respond in time (an existing broker process may be unresponsive). Check the local broker process or retry, ${SERVER_FALLBACK_HINT}.
5530
+ `;
5531
+ }
5532
+ if (/CLI authority broker could not attach or take ownership/i.test(message)) {
5533
+ const cleaned = stripDebugNoise(message);
5534
+ return `${RUN_UNAVAILABLE_PREFIX} (${cleaned}). ${NO_FALLBACK} The local runtime could not attach to an existing broker or take database ownership. Check running broker processes holding the local authority store or retry, ${SERVER_FALLBACK_HINT}.
5535
+ `;
5536
+ }
5537
+ if (isCliAuthorityBrokerUnavailableError(rawError) || /CLI authority broker unavailable at/i.test(message)) {
5538
+ const cleaned = stripDebugNoise(message);
5539
+ return `${RUN_UNAVAILABLE_PREFIX} (${cleaned}). ${NO_FALLBACK} The local authority broker is unavailable. Start or restart the local authority broker and retry, ${SERVER_FALLBACK_HINT}.
5540
+ `;
5541
+ }
5542
+ if (isCliAuthorityBrokerProtocolError(rawError) || /CLI authority broker protocol|CLI authority broker .* returned malformed response/i.test(message)) {
5543
+ const cleaned = stripDebugNoise(message);
5544
+ return `${RUN_UNAVAILABLE_PREFIX} (${cleaned}). ${NO_FALLBACK} The local authority broker returned a protocol or malformed response error. Check the running broker process and retry, ${SERVER_FALLBACK_HINT}.
5906
5545
  `;
5907
5546
  }
5908
5547
  const cls = classifyLocalRunError(message);
@@ -5947,7 +5586,7 @@ function shouldAttemptAutoLocal(options) {
5947
5586
  if (options.env.NOLO_DISABLE_CLI_WORKSPACE_TOOLS !== "1" && isBuiltinNoloAgentRef(options.agentKey) && resolveAuthToken2(options.env)) {
5948
5587
  return true;
5949
5588
  }
5950
- if (options.env.NOLO_DISABLE_CLI_WORKSPACE_TOOLS !== "1" && resolveAuthToken2(options.env) && !isKnownServerPlatformAgent(options)) {
5589
+ if (options.env.NOLO_DISABLE_CLI_WORKSPACE_TOOLS !== "1" && resolveAuthToken2(options.env)) {
5951
5590
  return true;
5952
5591
  }
5953
5592
  return Boolean(
@@ -5989,9 +5628,6 @@ async function runHttpAgentTurn(options, authToken) {
5989
5628
  const fetchImpl = options.fetchImpl ?? fetch;
5990
5629
  const clientVersionHeader = resolveClientVersion(options.env ?? {});
5991
5630
  const subjectRefs = buildSubjectRefs(options);
5992
- const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter(
5993
- (key) => key.trim()
5994
- );
5995
5631
  const allowedToolNames = options.allowedToolNames?.filter(
5996
5632
  (name) => name.trim()
5997
5633
  );
@@ -6015,9 +5651,8 @@ async function runHttpAgentTurn(options, authToken) {
6015
5651
  capabilities: ["text-io", "streaming", "slash-commands"],
6016
5652
  ...options.dialogAgentMode ? { dialogAgentMode: options.dialogAgentMode } : {},
6017
5653
  ...subjectRefs ? { subjectRefs } : {},
6018
- ...allowedChildAgentKeys?.length ? { allowedChildAgentKeys } : {},
6019
- ...blockedToolNames?.length ? { blockedToolNames } : {},
6020
- ...allowedToolNames?.length ? { allowedToolNames } : {}
5654
+ ...blockedToolNames !== void 0 ? { blockedToolNames } : {},
5655
+ ...allowedToolNames !== void 0 ? { allowedToolNames } : {}
6021
5656
  },
6022
5657
  ...options.continueDialogId ? { continueDialogId: options.continueDialogId } : {},
6023
5658
  ...options.spaceId ? { spaceId: options.spaceId } : {},
@@ -6133,13 +5768,17 @@ ${options.agentName} > (no text response)
6133
5768
  const usage = formatUsage(data?.usage, data?.dialogId);
6134
5769
  if (usage && shouldShowUsage(options.env)) options.output.write(`${usage}
6135
5770
  `);
5771
+ const turnCredits = platformCreditsFromUsage(
5772
+ data?.usage
5773
+ );
6136
5774
  return {
6137
5775
  exitCode: 0,
6138
5776
  ...typeof data?.dialogId === "string" && data.dialogId ? { dialogId: data.dialogId } : {},
6139
5777
  turnTokens: buildTurnTokenUsage(
6140
5778
  data?.usage,
6141
5779
  typeof data?.model === "string" ? data.model : options.agentKey
6142
- )
5780
+ ),
5781
+ ...turnCredits !== void 0 ? { turnCredits } : {}
6143
5782
  };
6144
5783
  }
6145
5784
  async function runInjectedLocalAgentTurn(options) {
@@ -6169,21 +5808,17 @@ async function runLocalAgentTurnForCli(options, settings) {
6169
5808
  return { exitCode: 1 };
6170
5809
  }
6171
5810
  const subjectRefs = buildSubjectRefs(options);
6172
- const allowedChildAgentKeys = options.allowedChildAgentKeys?.filter(
6173
- (key) => key.trim()
6174
- );
6175
5811
  const allowedToolNames = options.allowedToolNames?.filter(
6176
5812
  (name) => name.trim()
6177
5813
  );
6178
5814
  const blockedToolNames = options.blockedToolNames?.filter(
6179
5815
  (name) => name.trim()
6180
5816
  );
6181
- const runtimeContext = subjectRefs || allowedChildAgentKeys?.length || allowedToolNames?.length || blockedToolNames?.length || options.parentWakeOnTerminal || options.dialogAgentMode ? {
5817
+ const runtimeContext = subjectRefs || allowedToolNames !== void 0 || blockedToolNames !== void 0 || options.parentWakeOnTerminal || options.dialogAgentMode ? {
6182
5818
  ...subjectRefs ? { subjectRefs } : {},
6183
5819
  ...options.dialogAgentMode ? { dialogAgentMode: options.dialogAgentMode } : {},
6184
- ...allowedChildAgentKeys?.length ? { allowedChildAgentKeys } : {},
6185
- ...allowedToolNames?.length ? { allowedToolNames } : {},
6186
- ...blockedToolNames?.length ? { blockedToolNames } : {},
5820
+ ...allowedToolNames !== void 0 ? { allowedToolNames } : {},
5821
+ ...blockedToolNames !== void 0 ? { blockedToolNames } : {},
6187
5822
  ...options.parentWakeOnTerminal ? { parentWakeOnTerminal: true } : {},
6188
5823
  ...options.parentDialogId ? { parentThreadId: options.parentDialogId } : {}
6189
5824
  } : void 0;
@@ -6223,6 +5858,8 @@ async function runLocalAgentTurnForCli(options, settings) {
6223
5858
  category: options.category,
6224
5859
  inheritedFromDialogKey: options.inheritedFromDialogKey,
6225
5860
  parentDialogId: options.parentDialogId,
5861
+ runtimeContext,
5862
+ runKind: options.env.NOLO_AGENT_RUN_CHILD === "1" ? "subtask" : "interactive",
6226
5863
  background: options.background,
6227
5864
  noStream: options.noStream,
6228
5865
  ...runtimeContext ? { runtimeContext } : {},
@@ -6235,7 +5872,7 @@ async function runLocalAgentTurnForCli(options, settings) {
6235
5872
  }
6236
5873
  if (event.kind === "image-downgraded") {
6237
5874
  options.output.write(
6238
- "[nolo] \u5F53\u524D agent \u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF0C\u5DF2\u7528\u5360\u4F4D\u6587\u672C\u66FF\u4EE3\u3002\u8981\u5B8C\u6574\u56FE\u7247\u7406\u89E3\u53EF /switch \u5230 Kimi K2.6\u3002\n"
5875
+ "[nolo] \u5F53\u524D agent \u88AB\u914D\u7F6E\u4E3A\u4E0D\u652F\u6301\u56FE\u7247\u8F93\u5165\uFF0C\u56FE\u7247\u5DF2\u7528\u5360\u4F4D\u6587\u672C\u66FF\u4EE3\u3002\u8BF7\u68C0\u67E5\u6A21\u578B\u7684\u56FE\u7247\u80FD\u529B\u914D\u7F6E\uFF0C\u6216\u7528 /switch \u9009\u62E9\u652F\u6301\u56FE\u7247\u7684 agent \u540E\u91CD\u65B0\u53D1\u9001\u56FE\u7247\u3002\n"
6239
5876
  );
6240
5877
  }
6241
5878
  if (event.kind === "compaction") {
@@ -6244,11 +5881,13 @@ async function runLocalAgentTurnForCli(options, settings) {
6244
5881
  options.onLoopEvent?.(event);
6245
5882
  },
6246
5883
  ...options.abortSignal ? { abortSignal: options.abortSignal } : {},
6247
- ...turnOutput.traceLocalTools ? {
6248
- onToolEvent: (event) => {
6249
- turnOutput.handleToolEvent(event);
6250
- }
6251
- } : {},
5884
+ // 回合内注入(TUI 后台 run 唤醒直投):透传给 local loop。
5885
+ ...options.drainInjections ? { drainInjections: options.drainInjections } : {},
5886
+ // tool-gist-fold 后 onToolEvent 无条件挂载(不再受 traceLocalTools 开关
5887
+ // 控制,显示模式合并为单一 gist/折叠通道)——保留 alpha 的新形态。
5888
+ onToolEvent: (event) => {
5889
+ turnOutput.handleToolEvent(event);
5890
+ },
6252
5891
  ...!options.noStream ? {
6253
5892
  onTextDelta: (chunk) => {
6254
5893
  turnOutput.pushText(chunk);
@@ -6259,24 +5898,35 @@ async function runLocalAgentTurnForCli(options, settings) {
6259
5898
  } : {}
6260
5899
  });
6261
5900
  turnOutput.finish(result.content);
5901
+ const turnCredits = sumPlatformCredits(result.usageRecords);
6262
5902
  return {
6263
5903
  exitCode: 0,
6264
5904
  dialogId: result.dialogId,
6265
5905
  title: result.title,
6266
5906
  ...result.titlePatchPromise ? { titlePatchPromise: result.titlePatchPromise } : {},
6267
- ...result.emptyAssistantFallbackReason ? { emptyAssistantFallbackReason: result.emptyAssistantFallbackReason } : {},
6268
- turnTokens: buildTurnTokenUsage(result.usage, result.model)
5907
+ ...pickEmptyAssistantFlags(result),
5908
+ // 积分口径按「全轮」而非「最后一次调用」:result.usage 只是收尾那次
5909
+ // provider 调用的 usage,本轮前面 N-1 次工具循环调用(以及自动压缩摘要)
5910
+ // 的 cost 都只存在于 usageRecords 里。token 字段仍取 result.usage——
5911
+ // 上下文占用本来就该看最后一次调用的累计输入,不是各次相加。
5912
+ turnTokens: withTurnCredits(buildTurnTokenUsage(result.usage, result.model), turnCredits),
5913
+ ...turnCredits !== void 0 ? { turnCredits } : {},
5914
+ ...result.usageRecords?.length ? { usageRecords: result.usageRecords } : {}
6269
5915
  };
6270
5916
  } catch (error) {
6271
5917
  turnOutput.spinner.stop();
6272
5918
  const savedDialogId = error?.dialogId;
5919
+ const abortedUsageRecords = error?.usageRecords;
5920
+ const abortedTurnCredits = sumPlatformCredits(abortedUsageRecords);
6273
5921
  if (error?.code === LOCAL_TURN_ABORTED_CODE || options.abortSignal?.aborted) {
6274
5922
  const pendingToolName = error?.pendingToolName;
6275
5923
  return {
6276
5924
  exitCode: 0,
6277
5925
  streamInterrupted: true,
6278
5926
  ...savedDialogId ? { dialogId: savedDialogId } : {},
6279
- ...pendingToolName ? { pendingToolName } : {}
5927
+ ...pendingToolName ? { pendingToolName } : {},
5928
+ ...abortedTurnCredits !== void 0 ? { turnCredits: abortedTurnCredits } : {},
5929
+ ...abortedUsageRecords?.length ? { usageRecords: abortedUsageRecords } : {}
6280
5930
  };
6281
5931
  }
6282
5932
  const cooldownUntil = await markStartupRateLimitCooldown(
@@ -6302,10 +5952,76 @@ async function runLocalAgentTurnForCli(options, settings) {
6302
5952
  return {
6303
5953
  exitCode: 1,
6304
5954
  localError: error,
6305
- ...savedDialogId ? { dialogId: savedDialogId } : {}
5955
+ ...savedDialogId ? { dialogId: savedDialogId } : {},
5956
+ ...abortedTurnCredits !== void 0 ? { turnCredits: abortedTurnCredits } : {},
5957
+ ...abortedUsageRecords?.length ? { usageRecords: abortedUsageRecords } : {}
6306
5958
  };
6307
5959
  }
6308
5960
  }
5961
+ async function checkLocalAvailabilityBeforeHttpDispatch(options) {
5962
+ const adapter = resolveLocalRuntimeAdapter(options);
5963
+ if (!adapter || typeof adapter.loadAgentConfig !== "function") return null;
5964
+ let config;
5965
+ try {
5966
+ config = await adapter.loadAgentConfig(options.agentKey);
5967
+ } catch {
5968
+ return null;
5969
+ }
5970
+ if (!config || typeof config !== "object") return null;
5971
+ const baseRecord = config.rawRecord ?? config;
5972
+ let credentialKey = resolveCredentialKeyWithFallback(baseRecord);
5973
+ if (credentialKey && resolveOAuthChannelOwnerSkip(
5974
+ config,
5975
+ options
5976
+ )) {
5977
+ credentialKey = void 0;
5978
+ }
5979
+ const agentLevelAt = baseRecord.nextAvailableAt;
5980
+ const agentLevelNextAvailableAt = typeof agentLevelAt === "number" && Number.isFinite(agentLevelAt) ? agentLevelAt : void 0;
5981
+ if (!credentialKey && agentLevelNextAvailableAt === void 0) return null;
5982
+ const env = options.env;
5983
+ const now = Date.now();
5984
+ const entry = credentialKey ? await readCredentialEntry(credentialKey, env, now).catch(() => void 0) : void 0;
5985
+ const entryAt = entry?.nextAvailableAt;
5986
+ const effectiveNextAvailableAt = typeof entryAt === "number" ? mergeAvailabilityDeadline(agentLevelNextAvailableAt, entryAt) : agentLevelNextAvailableAt;
5987
+ if (typeof effectiveNextAvailableAt !== "number") return null;
5988
+ const gateDecision = resolveCooldownGate(
5989
+ { nextAvailableAt: effectiveNextAvailableAt, lastProbeAt: entry?.lastProbeAt },
5990
+ now
5991
+ );
5992
+ if (gateDecision === "probe" && credentialKey) {
5993
+ await recordCredentialProbe(credentialKey, env, now).catch(() => void 0);
5994
+ return null;
5995
+ }
5996
+ if (gateDecision !== "blocked") return null;
5997
+ options.output.write(
5998
+ `[nolo] Agent ${options.agentName || options.agentKey} is temporarily unavailable (429 cooldown) until ${new Date(Number(effectiveNextAvailableAt)).toISOString()}.
5999
+ Dispatch aborted before reaching the server. Pick another agent via listAgents, or retry after the cooldown.
6000
+ `
6001
+ );
6002
+ return { exitCode: 1 };
6003
+ }
6004
+ function foldLocalResultForTui(localResult) {
6005
+ return {
6006
+ exitCode: localResult.exitCode,
6007
+ ...localResult.dialogId ? { dialogId: localResult.dialogId } : {},
6008
+ title: localResult.title,
6009
+ ...localResult.titlePatchPromise ? { titlePatchPromise: localResult.titlePatchPromise } : {},
6010
+ // 空 assistant 兜底成因必须随行:后台 run 的结算(resolveRunOutcome 的
6011
+ // isStalledOrTruncated)靠它把截断轮判成 stalled 而不是 clean 失败。
6012
+ ...pickEmptyAssistantFlags(localResult),
6013
+ ...localResult.turnTokens ? { turnTokens: localResult.turnTokens } : {},
6014
+ // 平台积分必须随行:runLocalAgentTurnForCli 里 sumPlatformCredits 已按
6015
+ // 「全轮逐次求和」算好(只认 billing_unit === "credits" 的平台计费帧)。
6016
+ ...localResult.turnCredits !== void 0 ? { turnCredits: localResult.turnCredits } : {},
6017
+ // 逐帧用量明细必须随行:cli-local 计费走 fail-open 客户端记账,服务端没有
6018
+ // 逐帧记录,TUI 计费审计(appendTurnBillingAudit)要靠它对账。白名单历史上
6019
+ // 漏过 turnCredits(fix/tui-session-credits),usageRecords 是同坑位新字段。
6020
+ ...localResult.usageRecords?.length ? { usageRecords: localResult.usageRecords } : {},
6021
+ ...localResult.streamInterrupted ? { streamInterrupted: localResult.streamInterrupted } : {},
6022
+ ...localResult.pendingToolName ? { pendingToolName: localResult.pendingToolName } : {}
6023
+ };
6024
+ }
6309
6025
  async function runAgentTurn(options) {
6310
6026
  const authToken = resolveAuthToken2(options.env);
6311
6027
  const runtimeMode = resolveRequestedRuntimeMode(options);
@@ -6319,15 +6035,7 @@ async function runAgentTurn(options) {
6319
6035
  reportFailure: false
6320
6036
  });
6321
6037
  if (localResult.exitCode === 0) {
6322
- return {
6323
- exitCode: localResult.exitCode,
6324
- ...localResult.dialogId ? { dialogId: localResult.dialogId } : {},
6325
- title: localResult.title,
6326
- ...localResult.titlePatchPromise ? { titlePatchPromise: localResult.titlePatchPromise } : {},
6327
- ...localResult.turnTokens ? { turnTokens: localResult.turnTokens } : {},
6328
- ...localResult.streamInterrupted ? { streamInterrupted: localResult.streamInterrupted } : {},
6329
- ...localResult.pendingToolName ? { pendingToolName: localResult.pendingToolName } : {}
6330
- };
6038
+ return foldLocalResultForTui(localResult);
6331
6039
  }
6332
6040
  if (isMissingLocalAgentConfigError(localResult.localError, options.agentKey)) {
6333
6041
  options.output.write(
@@ -6341,13 +6049,7 @@ async function runAgentTurn(options) {
6341
6049
  reportFailure: false
6342
6050
  });
6343
6051
  if (retriedLocalResult.exitCode === 0) {
6344
- return {
6345
- exitCode: retriedLocalResult.exitCode,
6346
- ...retriedLocalResult.dialogId ? { dialogId: retriedLocalResult.dialogId } : {},
6347
- title: retriedLocalResult.title,
6348
- ...retriedLocalResult.titlePatchPromise ? { titlePatchPromise: retriedLocalResult.titlePatchPromise } : {},
6349
- ...retriedLocalResult.turnTokens ? { turnTokens: retriedLocalResult.turnTokens } : {}
6350
- };
6052
+ return foldLocalResultForTui(retriedLocalResult);
6351
6053
  }
6352
6054
  }
6353
6055
  } catch {
@@ -6360,7 +6062,11 @@ async function runAgentTurn(options) {
6360
6062
  ...localResult.dialogId ? { dialogId: localResult.dialogId } : {},
6361
6063
  // Keep localError so TUI can show balance/quota/dialog-preserved hints
6362
6064
  // instead of only the raw auto-runtime line.
6363
- ...localResult.localError ? { localError: localResult.localError } : {}
6065
+ ...localResult.localError ? { localError: localResult.localError } : {},
6066
+ // 失败轮同样可能已发生平台计费(abort/失败照样扣费):turnCredits 与
6067
+ // 逐帧明细一起随行,否则审计日志在 auto 失败路径上缺账。
6068
+ ...localResult.turnCredits !== void 0 ? { turnCredits: localResult.turnCredits } : {},
6069
+ ...localResult.usageRecords?.length ? { usageRecords: localResult.usageRecords } : {}
6364
6070
  };
6365
6071
  }
6366
6072
  }
@@ -6370,26 +6076,107 @@ async function runAgentTurn(options) {
6370
6076
  );
6371
6077
  return { exitCode: 1 };
6372
6078
  }
6079
+ const localBlock = await checkLocalAvailabilityBeforeHttpDispatch(options);
6080
+ if (localBlock) {
6081
+ return { exitCode: localBlock.exitCode };
6082
+ }
6373
6083
  return runHttpAgentTurn(options, authToken);
6374
6084
  }
6375
6085
 
6376
6086
  // packages/cli/agentRunCommand.ts
6377
6087
  import * as nodeFs from "node:fs";
6378
- import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
6379
- import { join as join2 } from "node:path";
6380
6088
 
6381
6089
  // packages/cli/client/autoModelRouter.ts
6382
6090
  var CLI_AUTO_ROUTE_AGENT_KEY = BUILTIN_NOLO_AGENT_KEY;
6383
6091
 
6092
+ // packages/agent-runtime/agentsMd.ts
6093
+ import { existsSync, readFileSync } from "node:fs";
6094
+ import { join } from "node:path";
6095
+ var AGENTS_MD_MAX_BYTES = 8192;
6096
+ var AGENTS_MD_CANDIDATES = ["AGENTS.md", "CLAUDE.md"];
6097
+ function readAgentsMdLayerFromDisk(cwd) {
6098
+ for (const name of AGENTS_MD_CANDIDATES) {
6099
+ const filePath = join(cwd, name);
6100
+ if (!existsSync(filePath)) continue;
6101
+ try {
6102
+ let content = readFileSync(filePath, "utf8").trim();
6103
+ if (!content) continue;
6104
+ if (Buffer.byteLength(content, "utf8") > AGENTS_MD_MAX_BYTES) {
6105
+ content = Buffer.from(content, "utf8").subarray(0, AGENTS_MD_MAX_BYTES).toString("utf8") + "\n\n<!-- AGENTS.md truncated -->";
6106
+ }
6107
+ return buildAgentsMdLayer(content, name);
6108
+ } catch {
6109
+ }
6110
+ }
6111
+ return null;
6112
+ }
6113
+
6114
+ // packages/cli/agentRunDoD.ts
6115
+ import { spawnSync as nodeSpawnSync } from "node:child_process";
6116
+ var DOD_COMMAND_TIMEOUT_MS = 12e4;
6117
+ function extractTailLines(text, count) {
6118
+ if (!text) return [];
6119
+ const lines = String(text).split("\n");
6120
+ while (lines.length > 0 && lines[lines.length - 1].trim() === "") lines.pop();
6121
+ return lines.slice(-count);
6122
+ }
6123
+ function executeDoDCommand(cmd, cwd, deps = {}) {
6124
+ const spawnSync = deps.spawnSync ?? nodeSpawnSync;
6125
+ try {
6126
+ const res = spawnSync(cmd, {
6127
+ shell: true,
6128
+ cwd: cwd || process.cwd(),
6129
+ timeout: DOD_COMMAND_TIMEOUT_MS,
6130
+ maxBuffer: 10 * 1024 * 1024,
6131
+ encoding: "utf8"
6132
+ });
6133
+ if (res.error) {
6134
+ const errCode = res.error.code;
6135
+ const timedOut = errCode === "ETIMEDOUT" || res.signal === "SIGTERM" || res.signal === "SIGKILL";
6136
+ return {
6137
+ command: cmd,
6138
+ exitCode: timedOut ? "timeout" : "error",
6139
+ stdoutTail: extractTailLines(res.stdout, 20),
6140
+ stderrTail: extractTailLines(res.stderr || res.error.message, 10)
6141
+ };
6142
+ }
6143
+ if (res.status === null && (res.signal === "SIGTERM" || res.signal === "SIGKILL")) {
6144
+ return {
6145
+ command: cmd,
6146
+ exitCode: "timeout",
6147
+ stdoutTail: extractTailLines(res.stdout, 20),
6148
+ stderrTail: extractTailLines(res.stderr, 10)
6149
+ };
6150
+ }
6151
+ return {
6152
+ command: cmd,
6153
+ exitCode: typeof res.status === "number" ? res.status : "error",
6154
+ stdoutTail: extractTailLines(res.stdout, 20),
6155
+ stderrTail: extractTailLines(res.stderr, 10)
6156
+ };
6157
+ } catch (err) {
6158
+ return {
6159
+ command: cmd,
6160
+ exitCode: "error",
6161
+ stdoutTail: [],
6162
+ stderrTail: extractTailLines(err instanceof Error ? err.message : String(err), 10)
6163
+ };
6164
+ }
6165
+ }
6166
+ function runDoDCommands(commands, cwd, deps = {}) {
6167
+ if (!commands || commands.length === 0) return void 0;
6168
+ return commands.map((cmd) => executeDoDCommand(cmd, cwd, deps));
6169
+ }
6170
+
6384
6171
  // packages/cli/agentRunPrompts.ts
6385
- import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
6386
- import { dirname, extname, isAbsolute, join, relative as relativePath, resolve, sep } from "node:path";
6172
+ import { existsSync as existsSync2, readFileSync as readFileSync2, readdirSync, statSync } from "node:fs";
6173
+ import { dirname, extname, isAbsolute, join as join2, relative as relativePath, resolve, sep } from "node:path";
6387
6174
  function workflowRefToCandidatePath(cwd, ref) {
6388
6175
  const normalized = ref.trim();
6389
6176
  if (!normalized) return "";
6390
6177
  if (normalized.endsWith(".md") || normalized.includes("/") || normalized.includes("\\")) {
6391
6178
  const directPath = resolve(cwd, normalized);
6392
- if (existsSync(directPath)) return directPath;
6179
+ if (existsSync2(directPath)) return directPath;
6393
6180
  }
6394
6181
  const fileName = normalized.replace(/[^a-zA-Z0-9一-鿿]+/g, "-").replace(/^-+|-+$/g, "");
6395
6182
  return resolve(cwd, "docs", "workflows", `${fileName}.md`);
@@ -6402,21 +6189,21 @@ function skillRefToCandidatePath(cwd, ref) {
6402
6189
  if (!normalized) return "";
6403
6190
  if (normalized.endsWith(".md") || normalized.includes("/") || normalized.includes("\\")) {
6404
6191
  const directPath = resolve(cwd, normalized);
6405
- if (existsSync(directPath)) return directPath;
6192
+ if (existsSync2(directPath)) return directPath;
6406
6193
  }
6407
6194
  const fileName = normalized.replace(/[^a-zA-Z0-9一-鿿]+/g, "-").replace(/^-+|-+$/g, "");
6408
6195
  for (const dir of SKILL_SEARCH_DIRS) {
6409
6196
  const skillMdPath = resolve(cwd, dir, fileName, "SKILL.md");
6410
- if (existsSync(skillMdPath)) return skillMdPath;
6197
+ if (existsSync2(skillMdPath)) return skillMdPath;
6411
6198
  }
6412
6199
  return resolve(cwd, ".agents", "skills", fileName, "SKILL.md");
6413
6200
  }
6414
6201
  async function resolveWorkflowReference(ref, cwd = process.cwd()) {
6415
6202
  const path = workflowRefToCandidatePath(cwd, ref);
6416
- if (!path || !existsSync(path)) {
6203
+ if (!path || !existsSync2(path)) {
6417
6204
  throw new Error(`Workflow reference not found: ${ref}`);
6418
6205
  }
6419
- const markdown = readFileSync(path, "utf8");
6206
+ const markdown = readFileSync2(path, "utf8");
6420
6207
  const parsed = parseSkillDocProtocol(markdown);
6421
6208
  return {
6422
6209
  ref,
@@ -6433,8 +6220,8 @@ function inlineRelativeRefs(body, skillDir) {
6433
6220
  const absPath = resolve(skillDir, cleaned);
6434
6221
  const relative = relativePath(normalizedSkillDir, absPath);
6435
6222
  if (relative.startsWith("..") || isAbsolute(relative)) return match;
6436
- if (!existsSync(absPath) || !absPath.endsWith(".md")) return match;
6437
- const refContent = readFileSync(absPath, "utf8");
6223
+ if (!existsSync2(absPath) || !absPath.endsWith(".md")) return match;
6224
+ const refContent = readFileSync2(absPath, "utf8");
6438
6225
  return `
6439
6226
 
6440
6227
  ### ${label}
@@ -6445,8 +6232,8 @@ ${refContent}
6445
6232
  });
6446
6233
  }
6447
6234
  function listSkillScripts(skillDir) {
6448
- const scriptsDir = join(skillDir, "scripts");
6449
- if (!existsSync(scriptsDir) || !statSync(scriptsDir).isDirectory()) return null;
6235
+ const scriptsDir = join2(skillDir, "scripts");
6236
+ if (!existsSync2(scriptsDir) || !statSync(scriptsDir).isDirectory()) return null;
6450
6237
  const entries = readdirSync(scriptsDir).filter((e) => !e.startsWith("."));
6451
6238
  if (entries.length === 0) return null;
6452
6239
  return [
@@ -6473,10 +6260,10 @@ async function resolveSkillReference(ref, options = {}) {
6473
6260
  } else {
6474
6261
  const cwd = options.cwd ?? process.cwd();
6475
6262
  const path = skillRefToCandidatePath(cwd, ref);
6476
- if (!path || !existsSync(path)) {
6263
+ if (!path || !existsSync2(path)) {
6477
6264
  throw new Error(`Skill reference not found: ${ref}`);
6478
6265
  }
6479
- markdown = readFileSync(path, "utf8");
6266
+ markdown = readFileSync2(path, "utf8");
6480
6267
  filePath = path;
6481
6268
  skillDir = dirname(path);
6482
6269
  }
@@ -6581,8 +6368,8 @@ function prependSubjectDialogMarker(message, subjectDialogKey) {
6581
6368
  function normalizeCliImageInput(input) {
6582
6369
  if (/^(https?:|data:|file:)/i.test(input)) return input;
6583
6370
  const absolutePath = resolve(input);
6584
- if (!existsSync(absolutePath)) return input;
6585
- const base64 = readFileSync(absolutePath).toString("base64");
6371
+ if (!existsSync2(absolutePath)) return input;
6372
+ const base64 = readFileSync2(absolutePath).toString("base64");
6586
6373
  return `data:${imageMimeTypeForPath(absolutePath)};base64,${base64}`;
6587
6374
  }
6588
6375
  function imageMimeTypeForPath(path) {
@@ -6649,14 +6436,16 @@ ${args.inspection.status.trim()}`] : [],
6649
6436
  }
6650
6437
 
6651
6438
  // packages/ai/memory/storeShared.ts
6439
+ var retrievalCountOf = (item) => item.activationCount ?? 0;
6652
6440
  var touchMemoryItemsInDb = async (db, items, now = (/* @__PURE__ */ new Date()).toISOString()) => {
6653
6441
  if (items.length === 0) return;
6654
6442
  const batch = db.batch();
6655
6443
  for (const item of items) {
6656
6444
  batch.put(createMemoryKey(item.ownerType, item.ownerId, item.id), {
6657
6445
  ...item,
6446
+ // retrieval bookkeeping on legacy storage names — see doc comment above
6658
6447
  lastActivatedAt: now,
6659
- activationCount: (item.activationCount ?? 0) + 1
6448
+ activationCount: retrievalCountOf(item) + 1
6660
6449
  });
6661
6450
  }
6662
6451
  await batch.write();
@@ -6665,6 +6454,19 @@ var touchMemoryItemsInDb = async (db, items, now = (/* @__PURE__ */ new Date()).
6665
6454
  // packages/ai/memory/constants.ts
6666
6455
  var EXPLICIT_REMEMBER_PREFIX_REGEX = /^(你要记住|请记住|以后记住|记住)[,,。.\s::]*/u;
6667
6456
 
6457
+ // packages/ai/memory/source.ts
6458
+ var getMemorySourceKind = (item) => {
6459
+ if (item.sourceKind) return item.sourceKind;
6460
+ if (item.patternKey === "explicit-remember") return "explicit-user-directive";
6461
+ if (item.patternKey === "agent-remember" || item.patternKey === "procedural-runbook")
6462
+ return "agent-tool";
6463
+ if (item.patternKey?.startsWith("dialog-learning:"))
6464
+ return "dialog-learning";
6465
+ if (item.tags?.includes("understanding-memory"))
6466
+ return "inferred-understanding";
6467
+ return "agent-tool";
6468
+ };
6469
+
6668
6470
  // packages/ai/memory/overlay.ts
6669
6471
  var KIND_TITLES = {
6670
6472
  episodic: "Episodic",
@@ -6698,6 +6500,8 @@ var FACET_DISPLAY = {
6698
6500
  style: { label: "\u66F4\u504F\u597D", strip: "\u66F4\u559C\u6B22" },
6699
6501
  goal: { label: "\u60F3\u63A8\u8FDB", strip: "\u60F3\u63A8\u8FDB" }
6700
6502
  };
6503
+ var INFERRED_SOURCE_KINDS = /* @__PURE__ */ new Set(["inferred-understanding", "dialog-learning"]);
6504
+ var isInferredMemory = (item) => INFERRED_SOURCE_KINDS.has(getMemorySourceKind(item));
6701
6505
  var formatFacetContent = (facet, normalized, prefix) => {
6702
6506
  const { label, strip } = FACET_DISPLAY[facet];
6703
6507
  const stripped = normalized.startsWith(strip) ? normalized.slice(strip.length).trim() : normalized;
@@ -6719,9 +6523,79 @@ var normalizeDisplayContent = (item) => {
6719
6523
  }
6720
6524
  return normalized;
6721
6525
  };
6526
+ var pickWithinKind = (list, perKindLimit) => {
6527
+ if (perKindLimit <= 0) return [];
6528
+ const head = list.slice(0, perKindLimit);
6529
+ if (head.length < perKindLimit) return head;
6530
+ if (head.some((item) => item.subjectType === "user")) return head;
6531
+ const firstUserSubject = list.find((item) => item.subjectType === "user");
6532
+ if (!firstUserSubject) return head;
6533
+ return [...head.slice(0, perKindLimit - 1), firstUserSubject];
6534
+ };
6535
+ var DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET = 3200;
6536
+ var MIN_TRUNCATED_TOKENS = 20;
6537
+ var TRUNCATED_SUFFIX = "\u2026\uFF08\u672C\u6761\u5DF2\u622A\u65AD\uFF09";
6538
+ var truncateLineToTokens = (lineText, budgetTokens) => {
6539
+ if (budgetTokens < MIN_TRUNCATED_TOKENS) return null;
6540
+ const suffixTokens = estimateTokens(TRUNCATED_SUFFIX);
6541
+ const bodyBudget = budgetTokens - suffixTokens;
6542
+ if (bodyBudget < MIN_TRUNCATED_TOKENS / 2) return null;
6543
+ let used = 0;
6544
+ let cut = 0;
6545
+ for (const ch of lineText) {
6546
+ const chTokens = estimateTokens(ch);
6547
+ if (used + chTokens > bodyBudget) break;
6548
+ used += chTokens;
6549
+ cut += ch.length;
6550
+ }
6551
+ if (cut <= 2) return null;
6552
+ return `${lineText.slice(0, cut).trimEnd()}${TRUNCATED_SUFFIX}`;
6553
+ };
6554
+ var fitLinesToBudget = (allLines, remainingBudget) => {
6555
+ let usedTokens = 0;
6556
+ const keptByKind = {};
6557
+ let truncatedCount = 0;
6558
+ let droppedCount = 0;
6559
+ const pushLine = (kind, lineText) => {
6560
+ if (!keptByKind[kind]) keptByKind[kind] = [];
6561
+ keptByKind[kind].push(lineText);
6562
+ };
6563
+ for (const candidate of allLines) {
6564
+ const remaining = remainingBudget - usedTokens;
6565
+ if (remaining <= 0) {
6566
+ droppedCount += 1;
6567
+ continue;
6568
+ }
6569
+ if (candidate.lineTokens <= remaining) {
6570
+ usedTokens += candidate.lineTokens;
6571
+ pushLine(candidate.kind, candidate.lineText);
6572
+ continue;
6573
+ }
6574
+ const truncated = truncateLineToTokens(candidate.lineText, remaining);
6575
+ if (!truncated) {
6576
+ droppedCount += 1;
6577
+ continue;
6578
+ }
6579
+ usedTokens += estimateTokens(truncated);
6580
+ pushLine(candidate.kind, truncated);
6581
+ truncatedCount += 1;
6582
+ }
6583
+ return { keptByKind, truncatedCount, droppedCount };
6584
+ };
6585
+ var buildBudgetFooter = (fit) => {
6586
+ const notices = [];
6587
+ if (fit.truncatedCount > 0) {
6588
+ notices.push(`${fit.truncatedCount} \u6761\u56E0\u9884\u7B97\u88AB\u622A\u65AD`);
6589
+ }
6590
+ if (fit.droppedCount > 0) {
6591
+ notices.push(`${fit.droppedCount} \u6761\u672A\u663E\u793A`);
6592
+ }
6593
+ if (notices.length === 0) return [];
6594
+ return [`\uFF08${notices.join("\u3001")}\uFF1B\u9700\u8981\u5B8C\u6574\u5185\u5BB9\u6216\u66F4\u591A\u76F8\u5173\u8BB0\u5FC6\u65F6\u7528 queryMemory \u68C0\u7D22\uFF09`];
6595
+ };
6722
6596
  var buildMemoryOverlay = (items, options) => {
6723
6597
  if (items.length === 0) return null;
6724
- const maxTokens = options?.maxTokens ?? 2e3;
6598
+ const maxTokens = options?.maxTokens ?? DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET;
6725
6599
  const perKindLimit = options?.perKindLimit ?? 3;
6726
6600
  const byKind = {
6727
6601
  episodic: [],
@@ -6736,19 +6610,15 @@ var buildMemoryOverlay = (items, options) => {
6736
6610
  return OVERLAY_HEADER_LINES.join("\n");
6737
6611
  }
6738
6612
  const allLines = Object.entries(byKind).filter(([, list]) => list.length > 0).flatMap(
6739
- ([kind, list]) => list.slice(0, perKindLimit).map((item) => {
6740
- const lineText = `- ${normalizeDisplayContent(item)}`;
6613
+ ([kind, list]) => pickWithinKind(list, perKindLimit).map((item) => {
6614
+ const lineText = `- ${isInferredMemory(item) ? "\uFF08\u63A8\u65AD\uFF09" : ""}${normalizeDisplayContent(item)}`;
6741
6615
  return { kind, lineText, lineTokens: estimateTokens(lineText) };
6742
6616
  })
6743
6617
  ).sort((a, b) => (KIND_PRIORITY[a.kind] ?? 99) - (KIND_PRIORITY[b.kind] ?? 99));
6744
- let usedTokens = 0;
6745
- const keptByKind = {};
6746
- for (const candidate of allLines) {
6747
- if (usedTokens + candidate.lineTokens > remainingBudget) continue;
6748
- usedTokens += candidate.lineTokens;
6749
- if (!keptByKind[candidate.kind]) keptByKind[candidate.kind] = [];
6750
- keptByKind[candidate.kind].push(candidate.lineText);
6751
- }
6618
+ const { keptByKind, truncatedCount, droppedCount } = fitLinesToBudget(
6619
+ allLines,
6620
+ remainingBudget
6621
+ );
6752
6622
  const kindOrder = ["semantic", "procedural", "episodic"];
6753
6623
  const sections = kindOrder.filter((kind) => keptByKind[kind] && keptByKind[kind].length > 0).map((kind) => {
6754
6624
  return [`[${KIND_TITLES[kind]}]`, ...keptByKind[kind]].join("\n");
@@ -6756,7 +6626,7 @@ var buildMemoryOverlay = (items, options) => {
6756
6626
  if (sections.length === 0) {
6757
6627
  return OVERLAY_HEADER_LINES.join("\n");
6758
6628
  }
6759
- return [...OVERLAY_HEADER_LINES, ...sections].join("\n");
6629
+ return [...OVERLAY_HEADER_LINES, ...sections, ...buildBudgetFooter({ keptByKind, truncatedCount, droppedCount })].join("\n");
6760
6630
  };
6761
6631
 
6762
6632
  // packages/ai/memory/rank.ts
@@ -6803,13 +6673,28 @@ var identifierScore = (query, item) => {
6803
6673
  ).length;
6804
6674
  return matches / identifiers.length;
6805
6675
  };
6806
- var activationScore = (item, nowMs) => {
6807
- const lastActivatedMs = Date.parse(item.lastActivatedAt || item.createdAt);
6808
- const ageDays = Math.max(0, (nowMs - lastActivatedMs) / 864e5);
6676
+ var DAY_MS = 864e5;
6677
+ var UNRETRIEVED_MEMORY_GRACE_DAYS = 3;
6678
+ var MIN_UNRETRIEVED_SCORE_FACTOR = 0.3;
6679
+ var UNRETRIEVED_DECAY_HALF_LIFE_DAYS = 7;
6680
+ var retrievalFrequencyScore = (item, nowMs) => {
6681
+ const lastRetrievedMs = Date.parse(item.lastActivatedAt || item.createdAt);
6682
+ const ageDays = Math.max(0, (nowMs - lastRetrievedMs) / DAY_MS);
6809
6683
  const recency = 1 / (1 + ageDays / 7);
6810
- const reinforcement = Math.min(1, Math.log1p(item.activationCount ?? 0) / 3);
6811
- return 0.7 * recency + 0.3 * reinforcement;
6684
+ const frequency = Math.min(1, Math.log1p(item.activationCount ?? 0) / 3);
6685
+ return 0.7 * recency + 0.3 * frequency;
6686
+ };
6687
+ var unretrievedDecayFactor = (item, nowMs) => {
6688
+ if ((item.activationCount ?? 0) !== 0) return 1;
6689
+ const createdAgeDays = Math.max(0, (nowMs - Date.parse(item.createdAt)) / DAY_MS);
6690
+ if (createdAgeDays <= UNRETRIEVED_MEMORY_GRACE_DAYS) return 1;
6691
+ const overdue = createdAgeDays - UNRETRIEVED_MEMORY_GRACE_DAYS;
6692
+ return Math.max(
6693
+ MIN_UNRETRIEVED_SCORE_FACTOR,
6694
+ 1 / (1 + overdue / UNRETRIEVED_DECAY_HALF_LIFE_DAYS)
6695
+ );
6812
6696
  };
6697
+ var retrievalScore = (item, nowMs) => retrievalFrequencyScore(item, nowMs) * unretrievedDecayFactor(item, nowMs);
6813
6698
  var creationRecencyScore = (item, nowMs) => {
6814
6699
  const createdMs = Date.parse(item.createdAt);
6815
6700
  const ageDays = Math.max(0, (nowMs - createdMs) / 864e5);
@@ -6841,14 +6726,15 @@ var pathScore = (item, context) => {
6841
6726
  var scoreMemoryItem = (item, query, nowMs = Date.now(), context) => {
6842
6727
  const queryMatch = keywordScore(query, item);
6843
6728
  const identifierMatch = identifierScore(query, item);
6844
- const activation = activationScore(item, nowMs);
6729
+ const retrieval = retrievalScore(item, nowMs);
6845
6730
  const createdRecency = creationRecencyScore(item, nowMs);
6846
6731
  const importance = item.importance ?? 0;
6847
6732
  const confidence = item.confidence ?? 0;
6848
6733
  const typeFit = typeFitScore(item);
6849
6734
  const understanding = understandingScore(item);
6850
6735
  const path = pathScore(item, context);
6851
- return 0.25 * queryMatch + 0.2 * identifierMatch + 0.2 * path + 0.09 * activation + 0.16 * createdRecency + 0.06 * importance + 0.03 * confidence + 0.02 * typeFit + 0.01 * understanding;
6736
+ return 0.25 * queryMatch + 0.2 * identifierMatch + 0.2 * path + 0.09 * retrieval + // weak retrieval signal, NOT successful-use reinforcement
6737
+ 0.16 * createdRecency + 0.06 * importance + 0.03 * confidence + 0.02 * typeFit + 0.01 * understanding;
6852
6738
  };
6853
6739
  var rankMemoryCandidates = (items, query, context) => {
6854
6740
  const nowMs = Date.now();
@@ -6865,7 +6751,9 @@ var rankMemoryCandidates = (items, query, context) => {
6865
6751
 
6866
6752
  // packages/ai/memory/runtime.ts
6867
6753
  var COLD_STORAGE_CONFIDENCE = 0.3;
6868
- var MEMORY_OVERLAY_TOKEN_BUDGET = 2e3;
6754
+ var MEMORY_OVERLAY_TOKEN_BUDGET = DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET;
6755
+ var DEFAULT_MEMORY_RUNTIME_OWNER_LIMIT = 20;
6756
+ var CORROBORATED_PROCEDURAL_RESERVE = 5;
6869
6757
  var normalizeSelectedContent = (text) => text.trim().replace(EXPLICIT_REMEMBER_PREFIX_REGEX, "").replace(/[。!?!?]+$/u, "").trim();
6870
6758
  var STACK_TERMS = [
6871
6759
  "typescript",
@@ -6967,6 +6855,7 @@ var selectRuntimeMemoryItems = (items, context, userInput = "") => {
6967
6855
  );
6968
6856
  add(unique.find((item) => item.ownerType === "user"));
6969
6857
  add(unique.find((item) => item.ownerType === "space"));
6858
+ add(unique.find((item) => item.subjectType === "user"));
6970
6859
  add(unique.find((item) => item.kind === "procedural"));
6971
6860
  for (const item of unique) {
6972
6861
  add(item);
@@ -6992,8 +6881,9 @@ var resolveMemoryRuntime = async (input) => {
6992
6881
  policy
6993
6882
  }),
6994
6883
  kinds: ["episodic", "semantic", "procedural"],
6995
- ownerLimit: 20,
6996
- ownerFallback: policy.ownerFallback
6884
+ ownerLimit: input.ownerLimit ?? DEFAULT_MEMORY_RUNTIME_OWNER_LIMIT,
6885
+ ownerFallback: policy.ownerFallback,
6886
+ corroboratedProceduralReserve: input.corroboratedProceduralReserve ?? CORROBORATED_PROCEDURAL_RESERVE
6997
6887
  });
6998
6888
  const rankContext = {
6999
6889
  currentOwner: input.spaceId ? { ownerType: "space", ownerId: input.spaceId } : input.userId ? { ownerType: "user", ownerId: input.userId } : null,
@@ -7086,6 +6976,36 @@ var resolveCliMemory = async (input) => {
7086
6976
  function resolvePositiveMs(value, fallback) {
7087
6977
  return parsePositiveFiniteNumberOrFallback(value, fallback);
7088
6978
  }
6979
+ function resolveRunOutcome(input) {
6980
+ switch (input.kind) {
6981
+ case "stall":
6982
+ return { status: "failed", exitCode: 1 };
6983
+ case "timeout":
6984
+ return { status: "timeout", exitCode: 124 };
6985
+ case "result": {
6986
+ const failed = input.isStalledOrTruncated || input.exitCode !== 0;
6987
+ if (!failed) {
6988
+ return { status: "done", exitCode: 0 };
6989
+ }
6990
+ return { status: "failed", exitCode: input.exitCode !== 0 ? input.exitCode : 1 };
6991
+ }
6992
+ }
6993
+ }
6994
+ var FAILED_EMPTY_ASSISTANT_REASONS = /* @__PURE__ */ new Set([
6995
+ "length_truncated",
6996
+ "stream_truncated",
6997
+ "repetition_loop",
6998
+ "stagnant_tool_calls"
6999
+ ]);
7000
+ var isRunResultStalledOrTruncated = (result) => !result.emptyAssistantOutputUsable && FAILED_EMPTY_ASSISTANT_REASONS.has(result.emptyAssistantFallbackReason ?? "");
7001
+ var resolveRunSettlementNote = (result) => {
7002
+ const reason = result.emptyAssistantFallbackReason;
7003
+ if (!reason || !FAILED_EMPTY_ASSISTANT_REASONS.has(reason)) return {};
7004
+ if (result.emptyAssistantOutputUsable) {
7005
+ return { note: `output complete but stream lacked finish frame: ${reason}` };
7006
+ }
7007
+ return { note: `empty assistant output: ${reason}` };
7008
+ };
7089
7009
  async function resolveAgentRunAgentKey(args) {
7090
7010
  if (!args.agentInput.trim() || args.agentInput.startsWith("agent-")) {
7091
7011
  return void 0;
@@ -7121,11 +7041,14 @@ async function runAgentRunCommand(args, deps) {
7121
7041
  deps.stallTimeoutMs ?? env.NOLO_LOCAL_RUN_STALL_TIMEOUT_MS,
7122
7042
  5 * 6e4
7123
7043
  );
7044
+ const stallEnvExplicitlySet = typeof env.NOLO_LOCAL_RUN_STALL_TIMEOUT_MS === "string" && env.NOLO_LOCAL_RUN_STALL_TIMEOUT_MS.trim().length > 0;
7045
+ const armStallWatchdog = hasRegistry || stallEnvExplicitlySet;
7046
+ const armTimeoutWatchdog = typeof parsed.timeoutMs === "number" && parsed.timeoutMs > 0;
7124
7047
  let timedOut = false;
7125
7048
  let stalled = false;
7126
7049
  let timeoutTimer;
7127
7050
  let stallTimer;
7128
- const activityTracker = hasRegistry ? createRunActivityTracker(childRunId, {
7051
+ const activityTracker = armStallWatchdog ? createRunActivityTracker(childRunId ?? "__foreground__", {
7129
7052
  env,
7130
7053
  homedir: deps.homedir,
7131
7054
  fs: deps.fs,
@@ -7138,7 +7061,7 @@ async function runAgentRunCommand(args, deps) {
7138
7061
  activityTracker?.dispose();
7139
7062
  };
7140
7063
  let rejectOnWatchdogFailure;
7141
- const watchdogFailure = hasRegistry ? new Promise((_, reject) => {
7064
+ const watchdogFailure = armStallWatchdog || armTimeoutWatchdog ? new Promise((_, reject) => {
7142
7065
  rejectOnWatchdogFailure = reject;
7143
7066
  }) : void 0;
7144
7067
  const raceWithWatchdog = (work) => watchdogFailure ? Promise.race([work, watchdogFailure]) : work;
@@ -7148,8 +7071,18 @@ async function runAgentRunCommand(args, deps) {
7148
7071
  } catch {
7149
7072
  }
7150
7073
  };
7151
- if (hasRegistry) {
7152
- stallTimer = setInterval(() => {
7074
+ const finalizeWatchdogOutcome = async (outcome, note) => {
7075
+ if (!hasRegistry) return;
7076
+ await settleRunTerminalAuthoritatively(
7077
+ childRunId,
7078
+ { status: outcome.status, exitCode: outcome.exitCode, note },
7079
+ { env, homedir: deps.homedir, fs: deps.fs, now: deps.now, sleep: deps.sleep },
7080
+ // Test seam: stubbed transitions keep their single-attempt semantics.
7081
+ deps.transitionRunToTerminal
7082
+ );
7083
+ };
7084
+ if (armStallWatchdog) {
7085
+ stallTimer = setInterval(async () => {
7153
7086
  if (timedOut || stalled) return;
7154
7087
  const activity = activityTracker?.getActivity();
7155
7088
  const lastEventAtMs = activity ? new Date(activity.lastEventAt).getTime() : nowMs();
@@ -7166,31 +7099,25 @@ async function runAgentRunCommand(args, deps) {
7166
7099
  const note = `stalled: no progress for ${stallTimeoutMs}ms`;
7167
7100
  output.write(`[nolo] local run ${note}
7168
7101
  `);
7169
- (deps.finalizeRunRecord ?? finalizeRunRecord)(
7170
- childRunId,
7171
- { status: "failed", note },
7172
- { env, homedir: deps.homedir, fs: deps.fs, now: deps.now }
7173
- );
7102
+ const outcome = resolveRunOutcome({ kind: "stall" });
7103
+ await finalizeWatchdogOutcome(outcome, note);
7174
7104
  rejectOnWatchdogFailure?.(new Error(`[nolo] local run ${note}`));
7175
- exitFromWatchdog(1);
7105
+ exitFromWatchdog(outcome.exitCode);
7176
7106
  }
7177
7107
  }, Math.min(stallTimeoutMs, 1e4));
7178
- if (typeof parsed.timeoutMs === "number" && parsed.timeoutMs > 0) {
7179
- timeoutTimer = setTimeout(() => {
7180
- timedOut = true;
7181
- clearWatchdogs();
7182
- const note = `timed out after ${parsed.timeoutMs}ms`;
7183
- output.write(`[nolo] local run ${note}
7108
+ }
7109
+ if (armTimeoutWatchdog) {
7110
+ timeoutTimer = setTimeout(async () => {
7111
+ timedOut = true;
7112
+ clearWatchdogs();
7113
+ const note = `timed out after ${parsed.timeoutMs}ms`;
7114
+ output.write(`[nolo] local run ${note}
7184
7115
  `);
7185
- (deps.finalizeRunRecord ?? finalizeRunRecord)(
7186
- childRunId,
7187
- { status: "timeout", note },
7188
- { env, homedir: deps.homedir, fs: deps.fs, now: deps.now }
7189
- );
7190
- rejectOnWatchdogFailure?.(new Error(`[nolo] local run ${note}`));
7191
- exitFromWatchdog(124);
7192
- }, parsed.timeoutMs);
7193
- }
7116
+ const outcome = resolveRunOutcome({ kind: "timeout" });
7117
+ await finalizeWatchdogOutcome(outcome, note);
7118
+ rejectOnWatchdogFailure?.(new Error(`[nolo] local run ${note}`));
7119
+ exitFromWatchdog(outcome.exitCode);
7120
+ }, parsed.timeoutMs);
7194
7121
  }
7195
7122
  const wantsFallbackSuggestions = parsed.fallbackAgentKeys && parsed.fallbackAgentKeys.length > 0;
7196
7123
  const rawAgentInput = resolveRawAgentInput(args, deps.commandPath) ?? parsed.agentKey;
@@ -7286,7 +7213,7 @@ async function runAgentRunCommand(args, deps) {
7286
7213
  (acc, tools) => acc.filter((t2) => tools.includes(t2))
7287
7214
  );
7288
7215
  if (skillAllowed.length === 0) {
7289
- output.write(`[nolo] warning: attached skills declare incompatible allowed-tools; no tool restriction enforced
7216
+ output.write(`[nolo] warning: attached skills declare incompatible allowed-tools; this run has no tools
7290
7217
  `);
7291
7218
  }
7292
7219
  skillAllowedToolOverride = parsed.allowedToolNames?.length ? parsed.allowedToolNames.filter((t2) => skillAllowed.includes(t2)) : skillAllowed;
@@ -7345,22 +7272,8 @@ async function runAgentRunCommand(args, deps) {
7345
7272
  let memoryOverlayLayer = null;
7346
7273
  let memoryUseGuidanceLayer = null;
7347
7274
  if (!isSubtask) {
7348
- const AGENTS_MD_MAX = 8192;
7349
- for (const name of ["AGENTS.md", "CLAUDE.md"]) {
7350
- const agentsMdPath = join2(cliCwd, name);
7351
- if (existsSync2(agentsMdPath)) {
7352
- try {
7353
- let mdContent = readFileSync2(agentsMdPath, "utf8").trim();
7354
- if (!mdContent) continue;
7355
- if (Buffer.byteLength(mdContent, "utf8") > AGENTS_MD_MAX) {
7356
- mdContent = Buffer.from(mdContent, "utf8").subarray(0, AGENTS_MD_MAX).toString("utf8") + "\n\n<!-- AGENTS.md truncated -->";
7357
- }
7358
- scopedLayers.push(buildAgentsMdLayer(mdContent, name));
7359
- break;
7360
- } catch {
7361
- }
7362
- }
7363
- }
7275
+ const agentsMdLayer = readAgentsMdLayerFromDisk(cliCwd);
7276
+ if (agentsMdLayer) scopedLayers.push(agentsMdLayer);
7364
7277
  skillContentBlocks.push(...buildSkillContextBlocks(skillReferences));
7365
7278
  scopedLayers.push(buildSkillDiscoveryContextLayer(cliCwd));
7366
7279
  if (!deps.memoryRecallDisabled) {
@@ -7421,7 +7334,6 @@ async function runAgentRunCommand(args, deps) {
7421
7334
  ...parsed.parentWakeOnTerminal ? { parentWakeOnTerminal: true } : {},
7422
7335
  ...parsed.subjectDialogKey ? { subjectDialogKey: parsed.subjectDialogKey } : {},
7423
7336
  ...parsed.subjectRefs?.length ? { subjectRefs: parsed.subjectRefs } : {},
7424
- ...parsed.allowedChildAgentKeys?.length ? { allowedChildAgentKeys: parsed.allowedChildAgentKeys } : {},
7425
7337
  ...skillAllowedToolOverride !== void 0 ? { allowedToolNames: skillAllowedToolOverride } : parsed.allowedToolNames?.length ? { allowedToolNames: parsed.allowedToolNames } : {},
7426
7338
  ...parsed.blockedToolNames?.length ? { blockedToolNames: parsed.blockedToolNames } : {},
7427
7339
  ...activityTracker ? { onLoopEvent: activityTracker.onLoopEvent } : {},
@@ -7441,6 +7353,7 @@ async function runAgentRunCommand(args, deps) {
7441
7353
  })
7442
7354
  );
7443
7355
  clearWatchdogs();
7356
+ let runCreditsTotal = result.turnCredits;
7444
7357
  if (result.exitCode !== 0 && isQuotaExhaustedError(result.localError) && isLocalRun && parsed.fallbackAgentKeys && parsed.fallbackAgentKeys.length > 0) {
7445
7358
  const fallbackAgentKey = parsed.fallbackAgentKeys[0];
7446
7359
  output.write(
@@ -7456,7 +7369,11 @@ async function runAgentRunCommand(args, deps) {
7456
7369
  clearWatchdogs();
7457
7370
  if (fallbackResult.exitCode === 0) {
7458
7371
  result = fallbackResult;
7459
- } else {
7372
+ }
7373
+ if (fallbackResult.turnCredits !== void 0) {
7374
+ runCreditsTotal = (runCreditsTotal ?? 0) + fallbackResult.turnCredits;
7375
+ }
7376
+ if (fallbackResult.exitCode !== 0) {
7460
7377
  result = {
7461
7378
  ...fallbackResult,
7462
7379
  ...fallbackResult.dialogId || result.dialogId ? { dialogId: fallbackResult.dialogId ?? result.dialogId } : {}
@@ -7499,6 +7416,9 @@ async function runAgentRunCommand(args, deps) {
7499
7416
  );
7500
7417
  clearWatchdogs();
7501
7418
  result = turnResult;
7419
+ if (turnResult.turnCredits !== void 0) {
7420
+ runCreditsTotal = (runCreditsTotal ?? 0) + turnResult.turnCredits;
7421
+ }
7502
7422
  if (result.exitCode !== 0) {
7503
7423
  break;
7504
7424
  }
@@ -7549,41 +7469,48 @@ async function runAgentRunCommand(args, deps) {
7549
7469
  }
7550
7470
  }
7551
7471
  if (typeof childRunId === "string" && childRunId.length > 0) {
7552
- const isStalledOrTruncated = result.emptyAssistantFallbackReason === "length_truncated" || result.emptyAssistantFallbackReason === "stream_truncated" || result.emptyAssistantFallbackReason === "repetition_loop" || result.emptyAssistantFallbackReason === "stagnant_tool_calls";
7553
- const truncationNote = isStalledOrTruncated ? { note: `empty assistant output: ${result.emptyAssistantFallbackReason}` } : {};
7554
- const finalStatus = isStalledOrTruncated || result.exitCode !== 0 ? "failed" : "done";
7555
- await (deps.finalizeRunRecord ?? finalizeRunRecord)(
7472
+ const childRecordForDoD = (deps.readRunRecord ?? readRunRecord)(childRunId, {
7473
+ env,
7474
+ homedir: deps.homedir,
7475
+ fs: deps.fs
7476
+ });
7477
+ const isStalledOrTruncated = isRunResultStalledOrTruncated(result);
7478
+ const truncationNote = resolveRunSettlementNote(result);
7479
+ const outcome = resolveRunOutcome({
7480
+ kind: "result",
7481
+ exitCode: result.exitCode,
7482
+ isStalledOrTruncated
7483
+ });
7484
+ let dodResults;
7485
+ try {
7486
+ dodResults = (deps.runDoDCommands ?? runDoDCommands)(
7487
+ childRecordForDoD?.dodCommands,
7488
+ childRecordForDoD?.cwd
7489
+ );
7490
+ } catch (dodError) {
7491
+ console.warn(`[nolo] DoD verification failed to run for ${childRunId}:`, dodError);
7492
+ }
7493
+ await settleRunTerminalAuthoritatively(
7556
7494
  childRunId,
7557
7495
  {
7558
- status: finalStatus,
7559
- exitCode: result.exitCode,
7496
+ status: outcome.status,
7497
+ exitCode: outcome.exitCode,
7560
7498
  dialogId: result.dialogId,
7499
+ ...dodResults ? { dodResults } : {},
7500
+ // run 级累计的平台积分(主轮 + fallback + drain 轮):dock 行据此显示
7501
+ // 「⚡ x.xx」,让派发任务的消耗可见。undefined = 全程无平台计费。
7502
+ ...runCreditsTotal !== void 0 ? { credits: runCreditsTotal } : {},
7561
7503
  ...truncationNote
7562
7504
  },
7563
7505
  {
7564
7506
  env,
7565
7507
  homedir: deps.homedir,
7566
7508
  fs: deps.fs,
7567
- now: deps.now
7568
- }
7509
+ now: deps.now,
7510
+ sleep: deps.sleep
7511
+ },
7512
+ deps.transitionRunToTerminal
7569
7513
  );
7570
- try {
7571
- const record = (deps.readRunRecord ?? readRunRecord)(childRunId, {
7572
- env,
7573
- homedir: deps.homedir,
7574
- fs: deps.fs
7575
- });
7576
- if (record) {
7577
- await (deps.generateRunReport ?? generateRunReport)(record, {
7578
- env,
7579
- homedir: deps.homedir,
7580
- fs: deps.fs,
7581
- now: deps.now
7582
- });
7583
- }
7584
- } catch (reportError) {
7585
- console.warn(`[nolo] failed to generate run report for ${childRunId}:`, reportError);
7586
- }
7587
7514
  }
7588
7515
  return result.exitCode;
7589
7516
  }
@@ -7602,6 +7529,8 @@ function isBalanceExhaustedError(error) {
7602
7529
  export {
7603
7530
  resolveAgentModelIdentity,
7604
7531
  resolveAgentContextWindow,
7532
+ platformCreditsFromUsage,
7533
+ formatCreditsChip,
7605
7534
  formatTokenCount,
7606
7535
  renderTokenStatus,
7607
7536
  resolveCliColorEnabled,
@@ -7629,7 +7558,7 @@ export {
7629
7558
  setActiveThemeMode,
7630
7559
  setActiveBrightness,
7631
7560
  detectSystemBrightnessFromEnv,
7632
- resolveTuiBrightness,
7561
+ resolveTuiBrightnessSignal,
7633
7562
  resolveTuiThemeMode,
7634
7563
  resetWorkspaceThemeState,
7635
7564
  applyDetectedBackground,
@@ -7640,8 +7569,10 @@ export {
7640
7569
  themeText,
7641
7570
  tuiRenderThemeFingerprint,
7642
7571
  setMathRenderingEnabled,
7572
+ polishBreathInsertsBlankBetween,
7643
7573
  formatAssistantDisplay,
7644
- normalizeToolDisplayMode,
7574
+ redactSecrets,
7575
+ TUI_TREE_MARKER,
7645
7576
  COLLAPSED_PASTE_PLACEHOLDER_RE,
7646
7577
  shouldCollapsePaste,
7647
7578
  createCollapsedPasteStore,
@@ -7653,6 +7584,7 @@ export {
7653
7584
  expandRangeToCollapsedPasteChips,
7654
7585
  findCollapsedPasteSpanAt,
7655
7586
  runAgentTurn,
7587
+ readAgentsMdLayerFromDisk,
7656
7588
  resolveWorkflowReference,
7657
7589
  resolveSkillReference,
7658
7590
  buildSkillContextBlocks,
@@ -7660,6 +7592,9 @@ export {
7660
7592
  normalizeCliImageInput,
7661
7593
  inspectLocalRunWorkspace,
7662
7594
  resolveCliMemory,
7595
+ resolveRunOutcome,
7596
+ isRunResultStalledOrTruncated,
7597
+ resolveRunSettlementNote,
7663
7598
  runAgentRunCommand,
7664
7599
  isBalanceExhaustedError
7665
7600
  };