nolo-cli 0.95.0-alpha.5 → 0.95.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/README.md +1 -1
  2. package/{_executeModel-UXVEB3GO.js → _executeModel-4NTXSCYT.js} +67 -63
  3. package/{action-YVYQEAAV.js → action-GI44T4DR.js} +10 -10
  4. package/{addContentAction-O7R66HEX.js → addContentAction-B2DRF7P6.js} +9 -9
  5. package/{addDialogAgentAction-74OA7KYP.js → addDialogAgentAction-T3I7IXPK.js} +15 -17
  6. package/{agentDeleteCommand-QT7KPGJC.js → agentDeleteCommand-QYCCUQ35.js} +47 -43
  7. package/{agentEmailCommands-EGD3UOFY.js → agentEmailCommands-GJ7KXHA6.js} +89 -82
  8. package/{agentListCommands-PBY5LTDT.js → agentListCommands-JDU7V3M5.js} +77 -82
  9. package/{agentMachineCommands-WCCBD7CE.js → agentMachineCommands-PXJG3EDI.js} +42 -38
  10. package/{agentProviderCommands-GNPTL5XR.js → agentProviderCommands-YK2BIIXZ.js} +1 -1
  11. package/{agentPullCommand-O5MPVJ5E.js → agentPullCommand-HF4A42D4.js} +1 -1
  12. package/agentRecordCommands-3ONMYU6P.js +135 -0
  13. package/{agentRunCommand-UQBDIINO.js → agentRunCommand-L6NJGDBA.js} +88 -80
  14. package/{agentRunControl-XLGD3UZ5.js → agentRunControl-5T64LM2M.js} +2 -2
  15. package/{agentRuntimeLocal-TT57XSVO.js → agentRuntimeLocal-SYLNOKCT.js} +44 -36
  16. package/{agentSlice-KTVOEUDX.js → agentSlice-X63VSE6R.js} +11 -11
  17. package/{appDeleteCommands-XMJJB6UT.js → appDeleteCommands-IP22BHZE.js} +42 -38
  18. package/{appDeployCommands-DORRXKWU.js → appDeployCommands-5ZTQL6UL.js} +42 -38
  19. package/{appDeployStatusCommands-BWEE72UH.js → appDeployStatusCommands-G6EMAT75.js} +42 -38
  20. package/{appGetCommands-WN6KKQHQ.js → appGetCommands-UXBDAYEM.js} +42 -38
  21. package/{appListCommands-W2WE5TD5.js → appListCommands-J274GTVP.js} +42 -38
  22. package/{authCommand-F4EFRRX6.js → authCommand-W6I6GD3F.js} +115 -23
  23. package/{authCommands-RGOGCPP6.js → authCommands-GBIFZWD3.js} +5 -5
  24. package/{builtinSkillRegistry-FUAVTRVZ.js → builtinSkillRegistry-ZMF6YGNO.js} +6 -5
  25. package/{chatQueueReduxAdapter-4YQF4NHY.js → chatQueueReduxAdapter-KN774OKJ.js} +30 -29
  26. package/{chromeCommands-FZYAU75D.js → chromeCommands-K27J4OVZ.js} +124 -28
  27. package/{chromeOpsCommands-62P2Q2YB.js → chromeOpsCommands-IXRLN57H.js} +4 -3
  28. package/{chunk-6OZ36FXI.js → chunk-27ONFIEY.js} +22 -4
  29. package/{chunk-HMPEO3ZE.js → chunk-2JCOP36I.js} +100 -100
  30. package/{chunk-JEDZAO7L.js → chunk-2SYTUTLI.js} +257 -37
  31. package/{chunk-OIVSQH2O.js → chunk-3BXNTXYI.js} +299 -5
  32. package/{chunk-EYAQT56M.js → chunk-4DPP773Q.js} +2 -2
  33. package/chunk-4LCOCOR5.js +50 -0
  34. package/{chunk-2GRGFCF6.js → chunk-4VJAC32I.js} +2 -1
  35. package/{chunk-MC4XLIJ7.js → chunk-523DITKR.js} +1 -1
  36. package/{chunk-IAO6JBYW.js → chunk-5B7XS6UO.js} +164 -14
  37. package/{chunk-E4MARS3Q.js → chunk-5GVBDNTO.js} +1 -1
  38. package/chunk-5J3PYNUP.js +255 -0
  39. package/chunk-5MMAK75Q.js +15 -0
  40. package/{chunk-JPGCXHNM.js → chunk-5OA5HMTL.js} +1 -1
  41. package/{chunk-EFVDQUCT.js → chunk-5T2W2ZZN.js} +15 -20
  42. package/{chunk-DWUCB2A3.js → chunk-62IL3KQV.js} +4 -34
  43. package/{chunk-YQTQQX2H.js → chunk-67HHBCFJ.js} +1 -1
  44. package/{chunk-SNPMM7H3.js → chunk-67T7O467.js} +13 -13
  45. package/{chunk-6YTOJY35.js → chunk-6D2JFXLY.js} +35 -0
  46. package/{chunk-4MY4GLIW.js → chunk-6IHBIRPK.js} +969 -1090
  47. package/{chunk-3BMYXEUW.js → chunk-6O4IK4V2.js} +1 -1
  48. package/{chunk-DHDMC6FO.js → chunk-6TPOEJMQ.js} +9 -4
  49. package/{chunk-LGCTKGQ3.js → chunk-6UPZ63YT.js} +24 -5
  50. package/{chunk-WADCY6G6.js → chunk-6ZWMH6TJ.js} +111 -41
  51. package/{chunk-ABQYVJBJ.js → chunk-7CHC4W22.js} +1 -1
  52. package/{chunk-GQBOR3G6.js → chunk-7KVZ5LDQ.js} +2 -2
  53. package/{chunk-4OZYL5FG.js → chunk-7VJHIB2S.js} +573 -476
  54. package/{chunk-OA6Q2A4I.js → chunk-A7RSPKU6.js} +98 -22
  55. package/{chunk-KQ4ONNQD.js → chunk-ALFH24P3.js} +56 -7
  56. package/{chunk-Q554LLSI.js → chunk-AUDNYVRC.js} +1 -1
  57. package/{chunk-GPCZ7UXG.js → chunk-AZRHIN5B.js} +1 -1
  58. package/{chunk-JRQFUXY7.js → chunk-B2XUQXQX.js} +96 -19
  59. package/chunk-BMQ2MJUK.js +153 -0
  60. package/{chunk-3IIEFNGY.js → chunk-C53ZG23R.js} +2 -2
  61. package/chunk-CHOZJMJS.js +78 -0
  62. package/{chunk-3ZFOWBZF.js → chunk-CJXHT3S7.js} +13 -13
  63. package/{chunk-HJUYAD4A.js → chunk-CPUFH46E.js} +8 -8
  64. package/{chunk-2POGRYTM.js → chunk-CQMQXVFQ.js} +860 -142
  65. package/{chunk-LS2ZANRJ.js → chunk-CTUQJVQM.js} +1 -1
  66. package/{chunk-BP4XNZRM.js → chunk-CU3QB4HW.js} +3 -3
  67. package/{chunk-ACTMNVHM.js → chunk-CYSYR67N.js} +1 -1
  68. package/{chunk-SQZDZXP5.js → chunk-DA54MHPJ.js} +236 -36
  69. package/{chunk-VLTIYV3X.js → chunk-DCLMZ5TX.js} +4 -4
  70. package/{chunk-UKZDAFYT.js → chunk-DSSTTEKI.js} +6 -10
  71. package/{chunk-HVURBGF3.js → chunk-ESRMFY7G.js} +2 -2
  72. package/{chunk-TRV2MIDW.js → chunk-EXAJ6DCR.js} +1 -0
  73. package/chunk-GMZLP5DV.js +82 -0
  74. package/{chunk-CJCJF5XB.js → chunk-H6A6X4EK.js} +36 -3
  75. package/{chunk-DVINR3PL.js → chunk-HDLLCBRF.js} +1 -1
  76. package/{chunk-ONXOABJR.js → chunk-HNGRBWYF.js} +3 -0
  77. package/{chunk-H3PIH2EO.js → chunk-HWRQVJGX.js} +7 -7
  78. package/{chunk-H62HCIUP.js → chunk-HYZIYH2H.js} +11 -10
  79. package/{chunk-NTW5GWDM.js → chunk-I3QNET24.js} +32 -17
  80. package/{chunk-WV42OMV7.js → chunk-IAESIMK7.js} +4 -4
  81. package/{chunk-QIAVMDHY.js → chunk-IUVCUGQR.js} +4 -4
  82. package/{chunk-GFD4ALW3.js → chunk-IX27RP45.js} +1 -1
  83. package/{chunk-IIVGDG4I.js → chunk-LNPYTNMG.js} +8 -4
  84. package/{chunk-BLJWCTRL.js → chunk-LVITW736.js} +1 -1
  85. package/{chunk-76WEAXJB.js → chunk-M3LRSBOX.js} +18 -15
  86. package/{chunk-LIIKM7DD.js → chunk-M73PVOVS.js} +23 -76
  87. package/{chunk-7S4YWN7P.js → chunk-MX574M24.js} +1 -1
  88. package/{chunk-FZGV4FGK.js → chunk-NUHHBEJC.js} +378 -187
  89. package/{chunk-53HEEOTT.js → chunk-O26PCYLS.js} +80 -13
  90. package/{chunk-3DII57IT.js → chunk-O2OWEFII.js} +1 -1
  91. package/chunk-OCZKATRC.js +129 -0
  92. package/chunk-P6GMCCAT.js +870 -0
  93. package/{chunk-CPH3W5A7.js → chunk-Q4GP72HX.js} +94 -3
  94. package/{chunk-Z77CRGTW.js → chunk-R4SQ3LGW.js} +1 -1
  95. package/chunk-RE3CDVRX.js +7600 -0
  96. package/{chunk-DEUUPHOO.js → chunk-RKGKDQGJ.js} +74 -17
  97. package/{chunk-V4MJDUSR.js → chunk-RSEEDUMS.js} +2 -2
  98. package/{chunk-D2P6UDPQ.js → chunk-S3VFZW75.js} +66 -38
  99. package/{chunk-UZGQNTVW.js → chunk-S5XGT6GB.js} +5 -3
  100. package/{chunk-AFUORTY4.js → chunk-SONWNI3L.js} +21 -21
  101. package/{chunk-BYMV6QZG.js → chunk-TNIX77YM.js} +4 -0
  102. package/{chunk-OF7AQZUG.js → chunk-TU5NE4U3.js} +9 -84
  103. package/chunk-UNYJU5L6.js +780 -0
  104. package/{chunk-J4MOO56S.js → chunk-UQNS32WZ.js} +10 -2
  105. package/chunk-V2SAIXHE.js +13349 -0
  106. package/chunk-VIWDGTDA.js +8 -0
  107. package/chunk-VJVNU77E.js +83 -0
  108. package/{chunk-6D6VBVEW.js → chunk-VPFEPRME.js} +9 -9
  109. package/{chunk-JAXOVNM4.js → chunk-WILHZY7K.js} +45 -45
  110. package/{chunk-UKWGR5SS.js → chunk-WIWM4FE3.js} +187 -398
  111. package/{chunk-NKRYKK7T.js → chunk-XTDH3PGV.js} +6 -7
  112. package/{chunk-O6OSWFZQ.js → chunk-XUWRURDF.js} +6 -0
  113. package/{chunk-Q67DOFOO.js → chunk-Y3PMXGLH.js} +2 -0
  114. package/{chunk-SH43IESU.js → chunk-YUNJN43V.js} +44 -9
  115. package/{chunk-TOP2VXOR.js → chunk-Z4CSIXYP.js} +2 -2
  116. package/{chunk-2F7RJC6L.js → chunk-ZOVKKMF6.js} +1 -1
  117. package/chunk-ZRAU6T47.js +56 -0
  118. package/commandRegistry-NPS6IYBO.js +833 -0
  119. package/{contentThunks-2USKJBI4.js → contentThunks-EB4JFL4K.js} +32 -30
  120. package/{cooldownCommands-BSCH2W7P.js → cooldownCommands-ZLEPIB4A.js} +2 -2
  121. package/{createAgentAutomationAction-NTLU42X2.js → createAgentAutomationAction-NZS7N4AW.js} +32 -30
  122. package/{createDialogAction-UCYF4BUN.js → createDialogAction-4Q4J7P4T.js} +36 -33
  123. package/{createPageAction-QFGUGZ5M.js → createPageAction-FPKRGV7D.js} +38 -36
  124. package/{chunk-4LNCCQOB.js → cursorProvider-YGGNMVWX.js} +2560 -9879
  125. package/{dbSlice-XVWBAGYN.js → dbSlice-DQ32LYTJ.js} +8 -8
  126. package/{deleteFile-YG6QMJLU.js → deleteFile-NX6QHCWZ.js} +3 -3
  127. package/{dialogCommands-IIBAS4I2.js → dialogCommands-XXZH5K6U.js} +45 -41
  128. package/{dialogSlice-HQFQIQDZ.js → dialogSlice-DXEZ3PA3.js} +36 -29
  129. package/{dist-VODFSGNG.js → dist-NJC2W7I4.js} +61 -54
  130. package/{docCreateCommands-RJBSWEY4.js → docCreateCommands-FLNUDWG6.js} +44 -40
  131. package/{docDeleteCommands-QSDETKEQ.js → docDeleteCommands-74OURFAB.js} +44 -40
  132. package/{docReadCommands-AJG2EFHB.js → docReadCommands-QENWDQVH.js} +43 -39
  133. package/{docStore-GVWEDN5E.js → docStore-2JTPJVFK.js} +11 -10
  134. package/{docUpdateCommands-KWG533GS.js → docUpdateCommands-J4HWJ5JO.js} +44 -40
  135. package/{fetchMessages-EIU7UFFK.js → fetchMessages-67MEFPZR.js} +2 -2
  136. package/{getPricing-LUSEABA6.js → getPricing-NMMFT3YI.js} +3 -3
  137. package/{handleSendMessageAction-TLB2SAU4.js → handleSendMessageAction-FGPHI364.js} +91 -83
  138. package/index.js +87 -884
  139. package/{localDialogRead-BTFJ4V2I.js → localDialogRead-EBRS242U.js} +2 -2
  140. package/{localRuntimeAuthority-6IR6BBXE.js → localRuntimeAuthority-5W6IJRAD.js} +6 -6
  141. package/{localRuntimeDb-SYQGUF4U.js → localRuntimeDb-3LRMNLCM.js} +1 -1
  142. package/{machineCommands-QZDDCLIW.js → machineCommands-26AZP4AS.js} +84 -77
  143. package/{machineWsRunDispatch-NYMX3H4L.js → machineWsRunDispatch-GQ5XJ2DL.js} +81 -74
  144. package/{memberThunks-QGFLFVCI.js → memberThunks-5ZXPR63F.js} +9 -9
  145. package/{models-T3SG6MJ5.js → models-ZPU5EDF4.js} +2 -2
  146. package/oauthTokenStore-ITEB663N.js +23 -0
  147. package/package.json +1 -1
  148. package/pdf-U6KSUEZZ.js +26435 -0
  149. package/processSpawn-SOAV3FEV.js +11 -0
  150. package/profileConfig-ZGOFORWV.js +43 -0
  151. package/{providerPresetApply-FG6NZ57W.js → providerPresetApply-DD6NGWW6.js} +7 -7
  152. package/{providerRegistry-757OWH3O.js → providerRegistry-XDRLMYGJ.js} +7 -7
  153. package/{read-COE3ZYR6.js → read-EPTJRAEF.js} +5 -5
  154. package/{readDocTool-5USN4A6V.js → readDocTool-W4NDXNEX.js} +5 -3
  155. package/{readlineWorkspace-VETAJAPP.js → readlineWorkspace-B7NBQCX6.js} +2448 -2022
  156. package/{removeDialogAgentAction-IX3MN2ZO.js → removeDialogAgentAction-BVAWQKXE.js} +17 -19
  157. package/{runAgentClientLoop-26DG6ZEY.js → runAgentClientLoop-RVB5K6R2.js} +61 -58
  158. package/{runtimeDoctorCommands-X6WDBEQX.js → runtimeDoctorCommands-3USD722U.js} +3 -3
  159. package/runtimeModeArgs-2Y7BALTO.js +31 -0
  160. package/{setDialogExtraReferencesAction-X4HCPNZL.js → setDialogExtraReferencesAction-LYY45IAD.js} +12 -11
  161. package/{setPrimaryDialogAgentAction-4GMIQLOD.js → setPrimaryDialogAgentAction-73IL7DLU.js} +18 -20
  162. package/{settingSlice-ZQZVUPKK.js → settingSlice-Q6EKL7EQ.js} +9 -9
  163. package/{skillDiscovery-CYUCJMAG.js → skillDiscovery-ZBU76COE.js} +3 -3
  164. package/{spaceCommands-WIJTLELT.js → spaceCommands-BYDGOMW7.js} +44 -40
  165. package/{streamAgentChatTurn-BY7IPY5C.js → streamAgentChatTurn-HV3FSRHN.js} +183 -91
  166. package/{switchDialogAgentAction-N52LRPA3.js → switchDialogAgentAction-UUXDSQ6X.js} +15 -17
  167. package/{tableCommands-O6NWHFKV.js → tableCommands-G7RV3RU3.js} +4 -4
  168. package/{toolApiClient-QVJ6HDNN.js → toolApiClient-INIQCPGY.js} +3 -3
  169. package/{tools-4Y2EYH5D.js → tools-AZR26MXC.js} +54 -51
  170. package/{tuiSummaryLlmCaller-T2SHYMDZ.js → tuiSummaryLlmCaller-74NRRLVW.js} +18 -16
  171. package/{updateCommands-2M74UL7P.js → updateCommands-4EHDLF5J.js} +3 -3
  172. package/{updateDialogTitleAction-2S4DCP35.js → updateDialogTitleAction-HEWCCXZZ.js} +81 -43
  173. package/agentRecordCommands-YQQKDLIA.js +0 -128
  174. package/chunk-LBEDNSMY.js +0 -18881
  175. package/chunk-M76ECQRD.js +0 -13658
  176. package/chunk-Q5FJJ6XI.js +0 -103
  177. package/chunk-S7Z2HMCN.js +0 -25
  178. package/{chunk-VMFTFOWF.js → chunk-3AH7LNUB.js} +7 -7
  179. package/{chunk-X7HHHIOZ.js → chunk-Y6ROFCZO.js} +0 -0
  180. package/{db-WK5MDZVN.js → db-VQSAOWAO.js} +1 -1
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  findPotentialSecrets
3
- } from "./chunk-S7Z2HMCN.js";
3
+ } from "./chunk-VJVNU77E.js";
4
4
  import {
5
5
  buildLocalRunEnv,
6
6
  isFullstackCodingAgentRef,
@@ -26,51 +26,62 @@ import {
26
26
  resolveFileWriteGateEnabled,
27
27
  resolveLocalUserId,
28
28
  t,
29
- toolLabel
30
- } from "./chunk-4LNCCQOB.js";
31
- import {
32
- createRunActivityTracker,
33
- popSingleQueueMessage,
34
- readRunRecord,
35
- resolveRunQueuePath,
36
- settleRunTerminalAuthoritatively,
37
- spawnLocalBackgroundRun
38
- } from "./chunk-CPH3W5A7.js";
29
+ toolLabel,
30
+ toolLabelVariants
31
+ } from "./chunk-RE3CDVRX.js";
39
32
  import {
40
33
  clearCredentialAvailability,
41
34
  readCredentialEntry,
42
- recordCredentialProbe,
43
- resolveCredentialKeyWithFallback
44
- } from "./chunk-DWUCB2A3.js";
35
+ recordCredentialProbe
36
+ } from "./chunk-62IL3KQV.js";
45
37
  import {
46
38
  getReadableCliDb
47
- } from "./chunk-LS2ZANRJ.js";
39
+ } from "./chunk-CTUQJVQM.js";
40
+ import {
41
+ resolveMachineId
42
+ } from "./chunk-ESHYE7WU.js";
48
43
  import {
49
44
  readDbRecord,
50
45
  resolveAgentRecordFromHybridStore
51
- } from "./chunk-76WEAXJB.js";
46
+ } from "./chunk-M3LRSBOX.js";
52
47
  import {
53
48
  isLocalCliAgentKey
54
49
  } from "./chunk-SV5IJK6K.js";
50
+ import {
51
+ extractGoogleValidationLink
52
+ } from "./chunk-BMQ2MJUK.js";
53
+ import {
54
+ createRunActivityTracker,
55
+ popSingleQueueMessage,
56
+ readRunRecord,
57
+ resolveRunQueuePath,
58
+ settleRunTerminalAuthoritatively,
59
+ spawnLocalBackgroundRun
60
+ } from "./chunk-Q4GP72HX.js";
61
+ import {
62
+ isCliAuthorityBrokerProtocolError,
63
+ isCliAuthorityBrokerTimeoutError,
64
+ isCliAuthorityBrokerUnavailableError
65
+ } from "./chunk-EXAJ6DCR.js";
66
+ import {
67
+ getDefaultCliLocalRuntimeDb
68
+ } from "./chunk-ZOVKKMF6.js";
55
69
  import {
56
70
  CliProviderQuotaError
57
71
  } from "./chunk-MP64VFGD.js";
58
- import {
59
- resolveMachineId
60
- } from "./chunk-ESHYE7WU.js";
61
72
  import {
62
73
  applyModelLayerOverride,
63
74
  buildModelLayerOverride
64
75
  } from "./chunk-LTRXGFMS.js";
65
76
  import {
66
77
  formatAgentListCard
67
- } from "./chunk-4OZYL5FG.js";
68
- import {
69
- isTransientFetchError
70
- } from "./chunk-5UTFL4QJ.js";
78
+ } from "./chunk-7VJHIB2S.js";
71
79
  import {
72
80
  isGatewayHttpStatus
73
81
  } from "./chunk-NF64D32W.js";
82
+ import {
83
+ isTransientFetchError
84
+ } from "./chunk-5UTFL4QJ.js";
74
85
  import {
75
86
  formatFinishedRunCard,
76
87
  formatListRunsCard,
@@ -79,43 +90,35 @@ import {
79
90
  formatStatusRunCard,
80
91
  formatStopRunCard,
81
92
  isAgentRunTerminalStatus
82
- } from "./chunk-NTW5GWDM.js";
93
+ } from "./chunk-I3QNET24.js";
83
94
  import {
84
95
  buildMemorySubjectsForAgent,
85
96
  chooseMemoryOwners,
86
97
  loadMemoryCandidatesFromDb,
87
98
  resolveAgentMemoryPolicy
88
- } from "./chunk-EFVDQUCT.js";
99
+ } from "./chunk-5T2W2ZZN.js";
89
100
  import {
90
101
  API_REPORTED_COST_MULTIPLIER,
91
102
  parseUiAskChoiceContent
92
- } from "./chunk-LBEDNSMY.js";
103
+ } from "./chunk-V2SAIXHE.js";
93
104
  import {
94
105
  isOAuthApiKeyRef
95
106
  } from "./chunk-YYLHWIW6.js";
96
- import {
97
- isCliAuthorityBrokerProtocolError,
98
- isCliAuthorityBrokerTimeoutError,
99
- isCliAuthorityBrokerUnavailableError
100
- } from "./chunk-TRV2MIDW.js";
101
- import {
102
- getDefaultCliLocalRuntimeDb
103
- } from "./chunk-2F7RJC6L.js";
104
107
  import {
105
108
  buildSkillDiscoveryContextLayer
106
- } from "./chunk-E4MARS3Q.js";
109
+ } from "./chunk-5GVBDNTO.js";
107
110
  import {
108
111
  parseExternalSkillMarkdown,
109
112
  parseSkillDocProtocol
110
- } from "./chunk-Q554LLSI.js";
113
+ } from "./chunk-AUDNYVRC.js";
111
114
  import {
112
115
  LOCAL_AGENT_CONFIG_MISSING_CODE,
113
116
  LOCAL_TURN_ABORTED_CODE,
114
117
  readActionGate
115
- } from "./chunk-4MY4GLIW.js";
118
+ } from "./chunk-6IHBIRPK.js";
116
119
  import {
117
120
  resolveAgentRuntimeConfigFromRecord
118
- } from "./chunk-3IIEFNGY.js";
121
+ } from "./chunk-C53ZG23R.js";
119
122
  import {
120
123
  createThinkParserState,
121
124
  flushThinkParser,
@@ -126,60 +129,68 @@ import {
126
129
  isQuotaExhaustedError,
127
130
  isQuotaLimited403Body,
128
131
  mergeAvailabilityDeadline,
129
- resolveCooldownGate
130
- } from "./chunk-CJCJF5XB.js";
132
+ resolveCooldownGate,
133
+ resolveCredentialKeyWithFallback
134
+ } from "./chunk-H6A6X4EK.js";
131
135
  import {
132
136
  isAntigravityOAuthAgent
133
- } from "./chunk-UZGQNTVW.js";
137
+ } from "./chunk-S5XGT6GB.js";
134
138
  import {
135
139
  resolveClientVersion
136
- } from "./chunk-6OZ36FXI.js";
140
+ } from "./chunk-27ONFIEY.js";
137
141
  import {
138
142
  DEFAULT_CONTEXT_WINDOW,
139
143
  getModelContextWindow,
140
144
  normalizeUsage
141
- } from "./chunk-JAXOVNM4.js";
145
+ } from "./chunk-WILHZY7K.js";
142
146
  import {
143
147
  clipCompactText
144
- } from "./chunk-WADCY6G6.js";
145
- import {
146
- findModelConfig
147
- } from "./chunk-OIVSQH2O.js";
148
+ } from "./chunk-5MMAK75Q.js";
148
149
  import {
149
150
  compactWhitespace
150
151
  } from "./chunk-DWLEOOGR.js";
151
152
  import {
152
153
  toErrorMessage
153
154
  } from "./chunk-HNMXYYJR.js";
155
+ import {
156
+ findModelConfig
157
+ } from "./chunk-3BXNTXYI.js";
154
158
  import {
155
159
  buildAgentsMdLayer,
156
160
  buildMemoryOverlayLayer,
157
161
  buildMemoryUseGuidanceLayer,
158
162
  partitionScopedBlocks,
159
163
  renderTurnContextBlocksWithScope
160
- } from "./chunk-DVINR3PL.js";
164
+ } from "./chunk-HDLLCBRF.js";
161
165
  import {
162
- readPipeText,
163
- spawnProcess
164
- } from "./chunk-X7HHHIOZ.js";
166
+ getLogger,
167
+ normalizeError
168
+ } from "./chunk-UNYJU5L6.js";
165
169
  import {
166
170
  resolveAuthToken
167
171
  } from "./chunk-A7GB5UGH.js";
172
+ import {
173
+ readPipeText,
174
+ spawnProcess
175
+ } from "./chunk-Y6ROFCZO.js";
168
176
  import {
169
177
  CLIENT_VERSION_TOO_OLD_CODE,
170
178
  NOLO_CLIENT_VERSION_HEADER,
171
179
  buildClientVersionUpgradeMessage
172
- } from "./chunk-Q67DOFOO.js";
180
+ } from "./chunk-Y3PMXGLH.js";
173
181
  import {
174
182
  parsePositiveFiniteNumberOrFallback
175
183
  } from "./chunk-Y5GCAMGP.js";
176
184
  import {
177
185
  createMemoryKey,
178
186
  ulid
179
- } from "./chunk-VMFTFOWF.js";
187
+ } from "./chunk-3AH7LNUB.js";
180
188
  import {
181
189
  asTrimmedLowercaseString
182
190
  } from "./chunk-QSJ3HFEF.js";
191
+ import {
192
+ isLevelNotFoundError
193
+ } from "./chunk-OW765XBU.js";
183
194
  import {
184
195
  BUILTIN_NOLO_AGENT_KEY,
185
196
  BUILTIN_NOLO_AGENT_NAME,
@@ -188,9 +199,6 @@ import {
188
199
  import {
189
200
  parsePublicAgentId
190
201
  } from "./chunk-M2EJHDJP.js";
191
- import {
192
- isLevelNotFoundError
193
- } from "./chunk-OW765XBU.js";
194
202
  import {
195
203
  asTrimmedString
196
204
  } from "./chunk-3EUW3WEO.js";
@@ -386,6 +394,24 @@ function styleCliText(text, style, enabled = resolveCliColorEnabled()) {
386
394
  function dimCliText(text, enabled = resolveCliColorEnabled()) {
387
395
  return styleCliText(text, "dim", enabled);
388
396
  }
397
+ var OSC8_OPEN = "\x1B]8;;";
398
+ var OSC8_CLOSE = "\x1B\\";
399
+ function sanitizeHyperlinkLabel(label) {
400
+ return label.replace(/[\u0000-\u001f\u007f]/g, "");
401
+ }
402
+ function resolveCliHyperlinkEnabled(env = process.env, isTTY = Boolean(process.stdout.isTTY)) {
403
+ const setting = asTrimmedLowercaseString(env.NOLO_CLI_HYPERLINKS);
404
+ if (setting === "0" || setting === "false" || setting === "off") return false;
405
+ if (setting === "1" || setting === "true" || setting === "on") return true;
406
+ return isTTY;
407
+ }
408
+ function formatCliHyperlink(url, label, enabled = resolveCliHyperlinkEnabled()) {
409
+ if (!url) return label;
410
+ const safeLabel = sanitizeHyperlinkLabel(label);
411
+ if (!enabled) return `${safeLabel} (${url})`;
412
+ if (!safeLabel) return url;
413
+ return `${OSC8_OPEN}${url}${OSC8_CLOSE}${safeLabel}${OSC8_OPEN}${OSC8_CLOSE}`;
414
+ }
389
415
 
390
416
  // node_modules/ansi-regex/index.js
391
417
  function ansiRegex({ onlyFirst = false } = {}) {
@@ -620,8 +646,12 @@ function stringWidth(input, options = {}) {
620
646
 
621
647
  // packages/cli/tui/tuiAnsi.ts
622
648
  var ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
649
+ var OSC8_HYPERLINK_REGEX = /\x1b\]8;;[^\x1b]*\x1b\\/g;
623
650
  var ALL_ANSI_ESCAPE_REGEX = ansiRegex();
624
651
  var FIRST_ANSI_ESCAPE_REGEX = ansiRegex({ onlyFirst: true });
652
+ function stripOsc8Hyperlinks(text) {
653
+ return text.replace(OSC8_HYPERLINK_REGEX, "");
654
+ }
625
655
  function stripAnsi2(text) {
626
656
  return text.replace(ANSI_ESCAPE_REGEX, "").replace(ALL_ANSI_ESCAPE_REGEX, "");
627
657
  }
@@ -783,6 +813,7 @@ function visibleWidth(str) {
783
813
  }
784
814
  function truncateAnsi(text, maxWidth) {
785
815
  if (maxWidth <= 0) return "";
816
+ text = stripOsc8Hyperlinks(text);
786
817
  if (visibleWidth(text) <= maxWidth) return text;
787
818
  let width = 0;
788
819
  let out = "";
@@ -823,7 +854,7 @@ function countPhysicalLines(text, columns) {
823
854
  const lines = text.split("\n");
824
855
  let total = 0;
825
856
  for (const line of lines) {
826
- const width = displayWidth(line);
857
+ const width = visibleWidth(stripOsc8Hyperlinks(line));
827
858
  total += Math.max(1, Math.ceil(width / columns));
828
859
  }
829
860
  return Math.max(total, 1);
@@ -8180,7 +8211,12 @@ function emitPlainGap(text, keywords, info, accent, warning, reset) {
8180
8211
  var UNORDERED_LIST_RE = /^(\s*)([-*+])\s+(.+)$/;
8181
8212
  var ORDERED_LIST_RE = /^(\s*)(\d+)\.\s+(.+)$/;
8182
8213
  var TASK_LIST_RE = /^(\s*)([-*+])\s+\[([ xX])\]\s+(.+)$/;
8214
+ var THEMATIC_BREAK_PATTERN = "(?:(-[ \\t]*){3,}|(\\*[ \\t]*){3,}|(_[ \\t]*){3,})";
8215
+ var THEMATIC_BREAK_RE = new RegExp(`^[ ]{0,3}${THEMATIC_BREAK_PATTERN}$`);
8183
8216
  function normalizeListLine(line) {
8217
+ if (THEMATIC_BREAK_RE.test(line)) {
8218
+ return line;
8219
+ }
8184
8220
  const task = line.match(TASK_LIST_RE);
8185
8221
  if (task) {
8186
8222
  const checked = task[3] === "x" || task[3] === "X";
@@ -8196,12 +8232,99 @@ function normalizeListLine(line) {
8196
8232
  }
8197
8233
  return line;
8198
8234
  }
8235
+ var TOOL_TREE_HEADER_RE = /^•\s+(.+?)\s+\((\d+)\)$/;
8236
+ var TOOL_TREE_LEAF_RE = /^([├└]──\s+)(.*?)\s{2}(✓|✗|!)(?:\s+(.*))?$/;
8237
+ var TOOL_SINGLE_RE = /^▸\s+(.+?)(?:\s+·\s+(.*?))?(?:\s{2}(✓|✗|!)(?:\s+(.*))?)$/;
8238
+ function plainToolLine(line) {
8239
+ return stripAnsi2(line);
8240
+ }
8241
+ var TOOL_TREE_GROUP_LABELS = new Set(
8242
+ ["execShell", "readFile", "fetchWebpage", "exa_search"].flatMap(toolLabelVariants)
8243
+ );
8244
+ function isKnownToolGroupLabel(label) {
8245
+ return TOOL_TREE_GROUP_LABELS.has(label);
8246
+ }
8247
+ function toolTreeHeaderMatch(line) {
8248
+ const match = plainToolLine(line).match(TOOL_TREE_HEADER_RE);
8249
+ return match && isKnownToolGroupLabel(match[1]) ? match : null;
8250
+ }
8251
+ function isToolTreeHeaderLine(line) {
8252
+ return toolTreeHeaderMatch(line) !== null;
8253
+ }
8254
+ function isToolTreeLeafLine(line) {
8255
+ return TOOL_TREE_LEAF_RE.test(plainToolLine(line));
8256
+ }
8257
+ function isToolSingleLine(line) {
8258
+ return TOOL_SINGLE_RE.test(plainToolLine(line));
8259
+ }
8260
+ function isToolGroupBoundary(cur, next) {
8261
+ return isToolTreeLeafLine(cur) && isToolTreeHeaderLine(next);
8262
+ }
8263
+ function statusColorSeq(marker, brightness) {
8264
+ if (marker === "\u2713") return colorSeq("success", brightness);
8265
+ if (marker === "\u2717") return colorSeq("danger", brightness);
8266
+ return colorSeq("warning", brightness);
8267
+ }
8268
+ function styleTuiToolLine(line, brightness) {
8269
+ const plain = plainToolLine(line);
8270
+ const chrome = colorSeq("chrome", brightness);
8271
+ const muted = colorSeq("muted", brightness);
8272
+ const header = toolTreeHeaderMatch(plain);
8273
+ if (header) {
8274
+ return `${chrome}\u2022${STYLE.reset} ${STYLE.bold}${muted}${header[1]}${STYLE.reset} ${chrome}${STYLE.dim}(${header[2]})${STYLE.reset}`;
8275
+ }
8276
+ const leaf = plain.match(TOOL_TREE_LEAF_RE);
8277
+ if (leaf) {
8278
+ const [, connector, detail, marker, statusDetail] = leaf;
8279
+ let rendered = `${chrome}${connector}${STYLE.reset}${chrome}${detail}${STYLE.reset}`;
8280
+ rendered += ` ${statusColorSeq(marker, brightness)}${marker}${STYLE.reset}`;
8281
+ if (statusDetail) {
8282
+ const metaSeq = marker === "\u2713" ? chrome : statusColorSeq(marker, brightness);
8283
+ rendered += ` ${metaSeq}${STYLE.dim}${statusDetail}${STYLE.reset}`;
8284
+ }
8285
+ return rendered;
8286
+ }
8287
+ const single = plain.match(TOOL_SINGLE_RE);
8288
+ if (single) {
8289
+ const [, label, detail, marker, statusDetail] = single;
8290
+ let rendered = `${chrome}\u25B8${STYLE.reset} ${STYLE.bold}${muted}${label}${STYLE.reset}`;
8291
+ if (detail) rendered += ` ${chrome}\xB7 ${detail}${STYLE.reset}`;
8292
+ rendered += ` ${statusColorSeq(marker, brightness)}${marker}${STYLE.reset}`;
8293
+ if (statusDetail) {
8294
+ const metaSeq = marker === "\u2713" ? chrome : statusColorSeq(marker, brightness);
8295
+ rendered += ` ${metaSeq}${STYLE.dim}${statusDetail}${STYLE.reset}`;
8296
+ }
8297
+ return rendered;
8298
+ }
8299
+ return null;
8300
+ }
8199
8301
  function isPolishListLikeLine(line) {
8200
- return LIST_LIKE_RE_FOR_GUARD.test(normalizeListLine(line));
8302
+ return LIST_LIKE_RE_FOR_GUARD.test(normalizeListLine(plainToolLine(line)));
8303
+ }
8304
+ var LIST_LIKE_RE_FOR_GUARD = /^\s*(?:•|◦|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s|^\s*▸\s/;
8305
+ function isPolishFenceInteriorLine(line) {
8306
+ return /^\x00F\d+\x00$/.test(line);
8307
+ }
8308
+ function polishHeadingLevel(line) {
8309
+ const match = stripAnsi2(line).match(/^(#{1,6})\s/);
8310
+ return match ? match[1].length : null;
8311
+ }
8312
+ function isPolishHeadingLine(line) {
8313
+ return polishHeadingLevel(line) !== null;
8314
+ }
8315
+ function isPolishIntroLine(line) {
8316
+ const plain = stripAnsi2(line).trimEnd();
8317
+ return plain.endsWith("\uFF1A") || plain.endsWith(":");
8201
8318
  }
8202
- var LIST_LIKE_RE_FOR_GUARD = /^\s*(?:•|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s/;
8203
8319
  function polishBreathInsertsBlankBetween(cur, next) {
8204
8320
  if (cur === "" || next === "") return false;
8321
+ if (isPolishFenceInteriorLine(cur) || isPolishFenceInteriorLine(next)) {
8322
+ return false;
8323
+ }
8324
+ if (isPolishIntroLine(cur) && isPolishListLikeLine(next)) return false;
8325
+ if (isPolishHeadingLine(cur) || isPolishHeadingLine(next)) return false;
8326
+ if (isCodeFenceLine(cur) !== isCodeFenceLine(next)) return true;
8327
+ if (isToolGroupBoundary(cur, next)) return true;
8205
8328
  return isPolishListLikeLine(cur) !== isPolishListLikeLine(next);
8206
8329
  }
8207
8330
  function convertMarkdownTablesForTerminal(text) {
@@ -8270,17 +8393,15 @@ function polishAssistantStructure(text, options = {}) {
8270
8393
  }
8271
8394
  return line;
8272
8395
  });
8273
- 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");
8274
- const LIST_LIKE = /^\s*(?:•|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s/;
8396
+ const afterHeading = maskedLines.join("\n").replace(/([^\n])\n(#{1,6} )/g, "$1\n\n$2").replace(/^(#{1,2} .+)\n(?!\n)/gm, "$1\n\n").replace(new RegExp(`([^\\n])\\n([ ]{0,3}${THEMATIC_BREAK_PATTERN})$`, "gm"), "$1\n\n$2").replace(new RegExp(`^([ ]{0,3}${THEMATIC_BREAK_PATTERN})\\n(?!\\n)`, "gm"), "$1\n\n").replace(/\n{3,}/g, "\n\n");
8275
8397
  const headingLines = afterHeading.split("\n");
8276
8398
  const breathed = [];
8277
8399
  for (let i = 0; i < headingLines.length; i++) {
8278
8400
  breathed.push(headingLines[i]);
8279
8401
  const cur = headingLines[i];
8280
8402
  const next = headingLines[i + 1];
8281
- if (cur === "" || next === void 0 || next === "") continue;
8282
- if (LIST_LIKE.test(cur) === LIST_LIKE.test(next)) continue;
8283
- breathed.push("");
8403
+ if (next === void 0) continue;
8404
+ if (polishBreathInsertsBlankBetween(cur, next)) breathed.push("");
8284
8405
  }
8285
8406
  const polishedMasked = breathed.join("\n");
8286
8407
  const polished = polishedMasked.replace(
@@ -8290,17 +8411,23 @@ function polishAssistantStructure(text, options = {}) {
8290
8411
  return options.trimEdges === false ? polished : polished.trim();
8291
8412
  }
8292
8413
  function styleRichMarkdownLine(line, brightness) {
8293
- const heading = line.match(/^(#{1,3})\s+(.+)$/);
8414
+ const toolLine = styleTuiToolLine(line, brightness);
8415
+ if (toolLine !== null) return toolLine;
8416
+ const heading = line.match(/^(#{1,6})\s+(.+)$/);
8294
8417
  if (heading) {
8295
8418
  const level = heading[1].length;
8296
8419
  const title = heading[2];
8420
+ const styledTitle = styleInlineMarkdown(title, brightness);
8297
8421
  if (level === 1) {
8298
- return `${STYLE.bold}\x1B[4m${colorSeq("accent", brightness)}${title}${STYLE.reset}`;
8422
+ return `${STYLE.bold}${colorSeq("accent", brightness)}${styledTitle}${STYLE.reset}`;
8299
8423
  }
8300
8424
  if (level === 2) {
8301
- return `${STYLE.bold}${colorSeq("warning", brightness)}${title}${STYLE.reset}`;
8425
+ return `${STYLE.bold}${colorSeq("warning", brightness)}${styledTitle}${STYLE.reset}`;
8426
+ }
8427
+ if (level === 3) {
8428
+ return `${STYLE.bold}${colorSeq("info", brightness)}${styledTitle}${STYLE.reset}`;
8302
8429
  }
8303
- return `${STYLE.bold}${colorSeq("info", brightness)}${title}${STYLE.reset}`;
8430
+ return `${STYLE.bold}${colorSeq("muted", brightness)}${styledTitle}${STYLE.reset}`;
8304
8431
  }
8305
8432
  if (line.startsWith("\u8FDB\u5165 nolo-plan")) {
8306
8433
  return `${colorSeq("chrome", brightness)}${STYLE.dim}${line}${STYLE.reset}`;
@@ -8309,15 +8436,19 @@ function styleRichMarkdownLine(line, brightness) {
8309
8436
  if (blockquote) {
8310
8437
  const border = colorSeq("chrome", brightness);
8311
8438
  const content = blockquote[1];
8312
- return `${border}\u2502${STYLE.reset} ${STYLE.dim}${content}${STYLE.reset}`;
8439
+ const styled = styleInlineMarkdown(content, brightness);
8440
+ return `${border}\u2502${STYLE.reset} ${STYLE.dim}${styled}${STYLE.reset}`;
8313
8441
  }
8314
- if (/^---+$/.test(line.trim())) {
8315
- return `${colorSeq("chrome", brightness)}${"\u2500".repeat(Math.min(line.trim().length, 40))}${STYLE.reset}`;
8442
+ if (THEMATIC_BREAK_RE.test(line)) {
8443
+ return `${colorSeq("chrome", brightness)}${STYLE.dim}${"\u2500".repeat(36)}${STYLE.reset}`;
8316
8444
  }
8317
8445
  const bullet = line.match(/^(\s*)(•)\s(.+)$/);
8318
8446
  if (bullet) {
8447
+ const indent = bullet[1];
8319
8448
  const styled = styleInlineMarkdown(bullet[3], brightness);
8320
- return `${bullet[1]}${colorSeq("accent", brightness)}\u2022${STYLE.reset} ${styled}`;
8449
+ const marker = indent.length >= 2 ? "\u25E6" : "\u2022";
8450
+ const markerColor = indent.length >= 2 ? colorSeq("chrome", brightness) : colorSeq("accent", brightness);
8451
+ return `${indent}${markerColor}${marker}${STYLE.reset} ${styled}`;
8321
8452
  }
8322
8453
  const ordered = line.match(/^(\s*)(\d+\.)\s(.+)$/);
8323
8454
  if (ordered) {
@@ -8441,16 +8572,28 @@ function emitFormattedAssistantBlock(write, text, trailingNewline = false) {
8441
8572
  }
8442
8573
  function classifyStreamLine(line) {
8443
8574
  if (line === "") return "blank";
8444
- if (TASK_LIST_RE.test(line) || UNORDERED_LIST_RE.test(line) || ORDERED_LIST_RE.test(line) || /^\s*(?:•|☐|☑)\s/.test(line) || /^\s*[\u2460-\u2473]/.test(line)) {
8575
+ const plain = plainToolLine(line);
8576
+ if (isToolTreeHeaderLine(plain)) return "tool-header";
8577
+ if (isToolTreeLeafLine(plain)) return "tool-leaf";
8578
+ if (isToolSingleLine(plain)) return "tool";
8579
+ if (TASK_LIST_RE.test(plain) || UNORDERED_LIST_RE.test(plain) || ORDERED_LIST_RE.test(plain) || /^\s*(?:•|◦|☐|☑)\s/.test(plain) || /^\s*[\u2460-\u2473]/.test(plain)) {
8445
8580
  return "list";
8446
8581
  }
8582
+ if (isPolishListLikeLine(plain)) return "list";
8583
+ if (polishHeadingLevel(plain) !== null) return "heading";
8447
8584
  return "prose";
8448
8585
  }
8449
- function needsListProseBreath(prev, next) {
8586
+ function isStreamListLike(kind) {
8587
+ return kind === "list" || kind === "tool-header" || kind === "tool-leaf" || kind === "tool";
8588
+ }
8589
+ function needsListProseBreath(prev, next, prevLine = "") {
8450
8590
  if (prev === null || prev === "blank" || next === "blank") return false;
8451
- const prevList = prev === "list";
8452
- const nextList = next === "list";
8453
- return prevList !== nextList;
8591
+ if (next === "heading") return true;
8592
+ if (prev === "heading") return (polishHeadingLevel(prevLine) ?? 7) <= 2;
8593
+ if (prev === "fence" !== (next === "fence")) return true;
8594
+ if (isStreamListLike(next) && isPolishIntroLine(prevLine)) return false;
8595
+ if (prev === "tool-leaf" && next === "tool-header") return true;
8596
+ return isStreamListLike(prev) !== isStreamListLike(next);
8454
8597
  }
8455
8598
  function createRenderAwareStreamWriter(args) {
8456
8599
  const brightness = resolveTuiBrightness();
@@ -8460,9 +8603,16 @@ function createRenderAwareStreamWriter(args) {
8460
8603
  let inMermaid = false;
8461
8604
  let mermaidBody = [];
8462
8605
  let lastKind = null;
8606
+ let lastLine = "";
8607
+ let pendingBlankRow = false;
8463
8608
  const PARTIAL_FLUSH_THRESHOLD = 48;
8464
8609
  const emitBreathIfNeeded = (nextKind) => {
8465
- if (needsListProseBreath(lastKind, nextKind)) args.write("\n");
8610
+ if (pendingBlankRow) {
8611
+ args.write("\n");
8612
+ pendingBlankRow = false;
8613
+ lastKind = "blank";
8614
+ }
8615
+ if (needsListProseBreath(lastKind, nextKind, lastLine)) args.write("\n");
8466
8616
  };
8467
8617
  const flushPartialProse = () => {
8468
8618
  if (inFence || buffer.length < PARTIAL_FLUSH_THRESHOLD) return;
@@ -8480,6 +8630,7 @@ function createRenderAwareStreamWriter(args) {
8480
8630
  emitBreathIfNeeded("prose");
8481
8631
  emitFormattedAssistantBlock(args.write, prefix, false);
8482
8632
  lastKind = "prose";
8633
+ lastLine = prefix;
8483
8634
  buffer = prefix.length === buffer.length ? "" : buffer.slice(prefix.length);
8484
8635
  };
8485
8636
  const flushCompleteBlocks = () => {
@@ -8495,10 +8646,11 @@ function createRenderAwareStreamWriter(args) {
8495
8646
  inMermaid = false;
8496
8647
  inFence = false;
8497
8648
  fenceLang = "unknown";
8498
- emitBreathIfNeeded("other");
8649
+ emitBreathIfNeeded("fence");
8499
8650
  args.write(`${STYLE.dim}${firstLine}${STYLE.reset}
8500
8651
  `);
8501
- lastKind = "other";
8652
+ lastKind = "fence";
8653
+ lastLine = firstLine;
8502
8654
  buffer = lines.slice(1).join("\n");
8503
8655
  continue;
8504
8656
  }
@@ -8514,10 +8666,11 @@ function createRenderAwareStreamWriter(args) {
8514
8666
  }
8515
8667
  inFence = true;
8516
8668
  }
8517
- emitBreathIfNeeded("other");
8669
+ emitBreathIfNeeded("fence");
8518
8670
  args.write(`${STYLE.dim}${firstLine}${STYLE.reset}
8519
8671
  `);
8520
- lastKind = "other";
8672
+ lastKind = "fence";
8673
+ lastLine = firstLine;
8521
8674
  buffer = lines.slice(1).join("\n");
8522
8675
  continue;
8523
8676
  }
@@ -8529,7 +8682,8 @@ function createRenderAwareStreamWriter(args) {
8529
8682
  if (inFence) {
8530
8683
  args.write(`${highlightCodeLine(firstLine, fenceLang, brightness)}
8531
8684
  `);
8532
- lastKind = "other";
8685
+ lastKind = "fence";
8686
+ lastLine = firstLine;
8533
8687
  buffer = lines.slice(1).join("\n");
8534
8688
  continue;
8535
8689
  }
@@ -8542,6 +8696,7 @@ function createRenderAwareStreamWriter(args) {
8542
8696
  const inner = trimmedFirst.slice(2, trimmedFirst.length - 2);
8543
8697
  args.write(renderMathBlock(inner) + "\n");
8544
8698
  lastKind = "other";
8699
+ lastLine = trimmedFirst;
8545
8700
  buffer = lines.slice(1).join("\n");
8546
8701
  continue;
8547
8702
  }
@@ -8568,6 +8723,7 @@ function createRenderAwareStreamWriter(args) {
8568
8723
  if (lastInner) innerParts.push(lastInner);
8569
8724
  args.write(renderMathBlock(innerParts.join("\n")) + "\n");
8570
8725
  lastKind = "other";
8726
+ lastLine = trimmedFirst;
8571
8727
  buffer = lines.slice(closeIndex + 1).join("\n");
8572
8728
  continue;
8573
8729
  }
@@ -8588,14 +8744,23 @@ function createRenderAwareStreamWriter(args) {
8588
8744
  true
8589
8745
  );
8590
8746
  lastKind = "list";
8747
+ lastLine = lines[end - 1] ?? firstLine;
8591
8748
  buffer = lines.slice(end).join("\n");
8592
8749
  continue;
8593
8750
  }
8594
8751
  }
8595
8752
  const kind = classifyStreamLine(firstLine);
8753
+ if (kind === "blank") {
8754
+ if (lastKind !== null && lastKind !== "blank") pendingBlankRow = true;
8755
+ lastKind = "blank";
8756
+ lastLine = "";
8757
+ buffer = lines.slice(1).join("\n");
8758
+ continue;
8759
+ }
8596
8760
  emitBreathIfNeeded(kind);
8597
8761
  emitFormattedAssistantBlock(args.write, firstLine, true);
8598
8762
  lastKind = kind;
8763
+ lastLine = firstLine;
8599
8764
  buffer = lines.slice(1).join("\n");
8600
8765
  }
8601
8766
  };
@@ -9808,6 +9973,7 @@ ${this.text}
9808
9973
  // packages/cli/client/agentRunOutput.ts
9809
9974
  var IDENTITY_LABEL_SEPARATOR = " > ";
9810
9975
  var THINKING_PREVIEW_BUFFER_LIMIT = 512;
9976
+ var TUI_PROGRESS_BUFFER_LIMIT = 1200;
9811
9977
  function appendThinkingPreview(current, chunk, limit = THINKING_PREVIEW_BUFFER_LIMIT) {
9812
9978
  if (limit <= 0) return "";
9813
9979
  const combined = current + chunk;
@@ -9821,6 +9987,14 @@ function formatCompactionSummaryLine(event) {
9821
9987
  return `${STYLE.dim}\u81EA\u52A8\u4E0A\u4E0B\u6587\u538B\u7F29\u5931\u8D25${reason}\uFF0C\u672C\u8F6E\u4EE5\u672A\u538B\u7F29\u4E0A\u4E0B\u6587\u7EE7\u7EED\u3002\u82E5\u53CD\u590D\u51FA\u73B0\u53EF\u624B\u52A8 /compact\u3002${STYLE.reset}
9822
9988
  `;
9823
9989
  }
9990
+ if (event.skipped) {
9991
+ if (event.skipReason === "adapter-missing-summary-methods" || event.skipReason === "load-summary-failed") {
9992
+ return `${STYLE.dim}\u81EA\u52A8\u4E0A\u4E0B\u6587\u538B\u7F29\u4E0D\u53EF\u7528\uFF08${event.skipReason}\uFF09\uFF0C\u672C\u8F6E\u4E0D\u538B\u7F29\u3002${STYLE.reset}
9993
+ `;
9994
+ }
9995
+ return "";
9996
+ }
9997
+ if (!event.summaryGenerated) return "";
9824
9998
  let detail = "\u751F\u6210\u5386\u53F2\u6458\u8981";
9825
9999
  const saved = typeof event.savedTokens === "number" ? event.savedTokens : void 0;
9826
10000
  let line = `\u5DF2\u538B\u7F29\u4E0A\u4E0B\u6587\uFF1A${detail}`;
@@ -9861,6 +10035,14 @@ function formatToolJsonEvent(event) {
9861
10035
  })}
9862
10036
  `;
9863
10037
  }
10038
+ function shouldPromoteTuiNarration(text) {
10039
+ if (text.length >= TUI_PROGRESS_BUFFER_LIMIT) return true;
10040
+ return /(^|\n)\s*(?:#{1,3}\s|```|[-*+]\s|\d+[.)]\s)/.test(text);
10041
+ }
10042
+ function narrationActivityLabel(text) {
10043
+ const oneLine = stripAnsi2(text).replace(/[`*_#>]/g, "").replace(/\s+/g, " ").trim();
10044
+ return truncateThinkingHint(oneLine, 60);
10045
+ }
9864
10046
  function createCliTurnOutput(params) {
9865
10047
  const { options } = params;
9866
10048
  const workingLabel = params.workingLabel ?? `${options.agentName} -> working`;
@@ -9869,14 +10051,36 @@ function createCliTurnOutput(params) {
9869
10051
  tuiTrees: options.output.tuiTrees === true
9870
10052
  });
9871
10053
  const eventMode = resolveAgentEventMode(options);
9872
- const showThinking = options.showThinking !== false;
10054
+ const assistantLabelManaged = options.output.assistantLabelManaged === true;
10055
+ const showThinking = !assistantLabelManaged && options.showThinking !== false;
10056
+ const hidesRoutineTuiToolDetail = (event) => {
10057
+ if (!assistantLabelManaged || event.toolName !== "editFile") return false;
10058
+ if (event.type === "tool-error") return false;
10059
+ if (readActionGate(event.metadata?.actionGate)) return false;
10060
+ if (event.metadata?.timedOut || event.metadata?.failed || event.metadata?.error) return false;
10061
+ if (typeof event.metadata?.exitCode === "number" && event.metadata.exitCode !== 0) return false;
10062
+ return true;
10063
+ };
9873
10064
  let streamedAssistantText = false;
9874
10065
  let everStreamedAnyText = false;
9875
10066
  let printedAssistantLabel = false;
9876
10067
  let thinkState = createThinkParserState();
9877
10068
  let thinkingFirstAt = null;
9878
10069
  let thinkingPreview = "";
10070
+ let tuiThinkingReported = false;
10071
+ const clearTuiThinkingLabel = () => {
10072
+ if (!tuiThinkingReported) return;
10073
+ tuiThinkingReported = false;
10074
+ options.activityReporter?.(null);
10075
+ };
9879
10076
  const markThinkingDelta = (chunk) => {
10077
+ if (assistantLabelManaged) {
10078
+ if (!tuiThinkingReported && !streamedAssistantText) {
10079
+ tuiThinkingReported = true;
10080
+ options.activityReporter?.(t("thinkingActive"));
10081
+ }
10082
+ return;
10083
+ }
9880
10084
  if (!showThinking) return;
9881
10085
  if (streamedAssistantText) return;
9882
10086
  if (thinkingFirstAt === null) {
@@ -9894,6 +10098,7 @@ function createCliTurnOutput(params) {
9894
10098
  options.activityReporter?.(label);
9895
10099
  };
9896
10100
  const endThinkingPhase = () => {
10101
+ clearTuiThinkingLabel();
9897
10102
  if (thinkingFirstAt === null) return;
9898
10103
  const seconds = Math.max(0, Math.round((Date.now() - thinkingFirstAt) / 1e3));
9899
10104
  thinkingFirstAt = null;
@@ -9906,7 +10111,6 @@ function createCliTurnOutput(params) {
9906
10111
  }
9907
10112
  };
9908
10113
  let compactionEvent = null;
9909
- const assistantLabelManaged = options.output.assistantLabelManaged === true;
9910
10114
  const writeToolOutput = (chunk) => {
9911
10115
  if (!chunk) return;
9912
10116
  if (typeof options.output.writeToolBlock === "function") {
@@ -9918,9 +10122,25 @@ function createCliTurnOutput(params) {
9918
10122
  const renderWriter = createRenderAwareStreamWriter({
9919
10123
  write: (chunk) => options.output.write(chunk)
9920
10124
  });
10125
+ let pendingTuiNarration = "";
10126
+ let tuiNarrationPromoted = false;
10127
+ const flushPendingTuiNarration = () => {
10128
+ if (!pendingTuiNarration) return;
10129
+ formatToolEvent.reset?.();
10130
+ renderWriter.push(pendingTuiNarration);
10131
+ pendingTuiNarration = "";
10132
+ tuiNarrationPromoted = true;
10133
+ streamedAssistantText = true;
10134
+ options.activityReporter?.(null);
10135
+ };
10136
+ const dropPendingTuiProgress = () => {
10137
+ pendingTuiNarration = "";
10138
+ tuiNarrationPromoted = false;
10139
+ options.activityReporter?.(null);
10140
+ };
9921
10141
  const writeVisibleAssistantChunk = (chunk) => {
9922
10142
  if (!chunk) return;
9923
- formatToolEvent.reset?.();
10143
+ if (!assistantLabelManaged) formatToolEvent.reset?.();
9924
10144
  const parsed = processThinkChunk(chunk, thinkState);
9925
10145
  thinkState = parsed.state;
9926
10146
  if (!parsed.content && !parsed.reasoning) return;
@@ -9936,8 +10156,23 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9936
10156
  }
9937
10157
  printedAssistantLabel = true;
9938
10158
  }
9939
- streamedAssistantText = true;
9940
10159
  everStreamedAnyText = true;
10160
+ if (assistantLabelManaged) {
10161
+ if (tuiNarrationPromoted) {
10162
+ renderWriter.push(parsed.content);
10163
+ streamedAssistantText = true;
10164
+ return;
10165
+ }
10166
+ pendingTuiNarration += parsed.content;
10167
+ if (shouldPromoteTuiNarration(pendingTuiNarration)) {
10168
+ flushPendingTuiNarration();
10169
+ } else {
10170
+ const label = narrationActivityLabel(pendingTuiNarration);
10171
+ if (label) options.activityReporter?.(label);
10172
+ }
10173
+ return;
10174
+ }
10175
+ streamedAssistantText = true;
9941
10176
  renderWriter.push(parsed.content);
9942
10177
  };
9943
10178
  const handleToolEvent = (event) => {
@@ -9953,13 +10188,19 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9953
10188
  return;
9954
10189
  }
9955
10190
  if (event.type === "tool-call") {
10191
+ if (assistantLabelManaged && pendingTuiNarration) {
10192
+ dropPendingTuiProgress();
10193
+ }
9956
10194
  renderWriter.flush();
9957
- formatToolEvent(event);
10195
+ if (!hidesRoutineTuiToolDetail(event)) {
10196
+ formatToolEvent(event);
10197
+ }
9958
10198
  endThinkingPhase();
9959
10199
  if (streamedAssistantText) {
9960
10200
  options.output.write("\n");
9961
10201
  streamedAssistantText = false;
9962
10202
  }
10203
+ if (assistantLabelManaged) tuiNarrationPromoted = false;
9963
10204
  const activeLabel = formatConservativeActiveToolLabel(event);
9964
10205
  spinner.show(activeLabel);
9965
10206
  options.activityReporter?.(activeLabel);
@@ -9971,6 +10212,9 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9971
10212
  }
9972
10213
  spinner.stop();
9973
10214
  options.activityReporter?.(null);
10215
+ if (hidesRoutineTuiToolDetail(event)) {
10216
+ return;
10217
+ }
9974
10218
  if (isLiveAgentRunObservation(event, parsedRunEvent)) {
9975
10219
  formatToolEvent.consume?.(event);
9976
10220
  return;
@@ -9983,6 +10227,26 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9983
10227
  return {
9984
10228
  spinner,
9985
10229
  eventMode,
10230
+ /**
10231
+ * Terminal cleanup for abort/error paths that never reach `finish()`.
10232
+ *
10233
+ * A user abort discards the transient TUI progress buffer: the user stopped
10234
+ * on purpose and the dock already showed that text as activity. A genuine
10235
+ * failure must not swallow prose that never got the chance to be *proven*
10236
+ * durable (only a following tool call proves "progress"), so it promotes the
10237
+ * pending buffer and flushes what was already promoted — otherwise a short
10238
+ * final answer followed by a transport error disappears from the transcript.
10239
+ */
10240
+ cancel(cleanup) {
10241
+ if (assistantLabelManaged && cleanup?.preservePendingNarration) {
10242
+ flushPendingTuiNarration();
10243
+ if (streamedAssistantText) {
10244
+ renderWriter.flush();
10245
+ options.output.write("\n");
10246
+ }
10247
+ }
10248
+ dropPendingTuiProgress();
10249
+ },
9986
10250
  pushText(chunk) {
9987
10251
  writeVisibleAssistantChunk(chunk);
9988
10252
  },
@@ -9990,21 +10254,39 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9990
10254
  markThinkingDelta(chunk);
9991
10255
  },
9992
10256
  handleToolEvent,
9993
- /** 记录一条 compaction 观测事件(TUI 在 turn 结束时渲染一行 dim 摘要)。 */
9994
10257
  recordCompaction(event) {
9995
- compactionEvent = event;
10258
+ const significance = (e) => e.failed ? 4 : e.summaryGenerated ? 3 : e.compressed ? 2 : 1;
10259
+ if (!compactionEvent || significance(event) >= significance(compactionEvent)) {
10260
+ compactionEvent = event;
10261
+ }
9996
10262
  },
9997
10263
  showWorking(label) {
9998
10264
  const activeLabel = label ?? workingLabel;
9999
10265
  spinner.show(activeLabel);
10000
10266
  options.activityReporter?.(activeLabel);
10001
10267
  },
10268
+ /**
10269
+ * Pre-delta turn phase label (ctx-overflow-feedback batch 3).
10270
+ *
10271
+ * localLoop 在首个 provider delta 之前依次发出 turn-phase 事件
10272
+ * (validating-context → compacting → waiting-provider);此前 CLI 只有
10273
+ * llm-start 才进入明确 working 状态,压缩期间 spinner 停在通用
10274
+ * working 文案上,用户无法区分「卡在检查上下文 / 压缩 / 等模型」。
10275
+ * 两个显示面(bare CLI 的 spinner 与 TUI 的 dock activityReporter)与
10276
+ * showWorking 走同一条投影,保证两端文案不漂移。
10277
+ */
10278
+ showPhase(phase) {
10279
+ const label = phase === "validating-context" ? t("contextChecking") : phase === "compacting" ? t("contextCompacting") : t("waitingForModel");
10280
+ spinner.show(label);
10281
+ options.activityReporter?.(label);
10282
+ },
10002
10283
  finish(fallbackContent) {
10003
10284
  const flushedThink = flushThinkParser(thinkState);
10004
10285
  thinkState = flushedThink.state;
10005
10286
  if (flushedThink.content) {
10006
10287
  writeVisibleAssistantChunk(flushedThink.content);
10007
10288
  }
10289
+ if (assistantLabelManaged) flushPendingTuiNarration();
10008
10290
  endThinkingPhase();
10009
10291
  spinner.stop();
10010
10292
  options.activityReporter?.(null);
@@ -10109,6 +10391,7 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10109
10391
  let content = "";
10110
10392
  let dialogId;
10111
10393
  let usage;
10394
+ let sawDone = false;
10112
10395
  const handlePayload = (payload) => {
10113
10396
  if (typeof payload?.dialogId === "string" && payload.dialogId.trim()) {
10114
10397
  dialogId = payload.dialogId;
@@ -10121,6 +10404,7 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10121
10404
  }
10122
10405
  if (payload?.type === "done") {
10123
10406
  usage = payload.usage;
10407
+ sawDone = true;
10124
10408
  return;
10125
10409
  }
10126
10410
  if (payload?.type === "dialog" || payload?.type === "status") {
@@ -10174,6 +10458,9 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10174
10458
  }
10175
10459
  } catch (error) {
10176
10460
  turnOutput.spinner.stop();
10461
+ turnOutput.cancel({
10462
+ preservePendingNarration: !options.abortSignal?.aborted
10463
+ });
10177
10464
  if (options.abortSignal?.aborted) {
10178
10465
  return {
10179
10466
  exitCode: 0,
@@ -10203,6 +10490,15 @@ ${describeClientVersionTooOldFailure(message, error)}`);
10203
10490
  `);
10204
10491
  return { exitCode: 1 };
10205
10492
  }
10493
+ if (options.abortSignal?.aborted && !sawDone) {
10494
+ turnOutput.spinner.stop();
10495
+ turnOutput.cancel();
10496
+ return {
10497
+ exitCode: 0,
10498
+ ...dialogId ? { dialogId } : {},
10499
+ streamInterrupted: true
10500
+ };
10501
+ }
10206
10502
  turnOutput.finish(content);
10207
10503
  const usageText = formatUsage(usage, dialogId);
10208
10504
  if (usageText && shouldShowUsage(options.env))
@@ -10419,7 +10715,7 @@ function findCollapsedPasteSpanAt(buffer, pos, opts = {}) {
10419
10715
  // packages/cli/client/agentRun.ts
10420
10716
  import { ulid as ulid2 } from "ulid";
10421
10717
  async function loadRunLocalAgentTurn() {
10422
- const { runLocalAgentTurn } = await import("./agentRuntimeLocal-TT57XSVO.js");
10718
+ const { runLocalAgentTurn } = await import("./agentRuntimeLocal-SYLNOKCT.js");
10423
10719
  return runLocalAgentTurn;
10424
10720
  }
10425
10721
  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();
@@ -10746,6 +11042,22 @@ var SERVER_FALLBACK_HINT = "or use --server to run on the server explicitly.";
10746
11042
  function buildAuthFailure(ctx) {
10747
11043
  const platformNoToken = ctx.where === "server chat proxy" && isAuthNoTokenBody(ctx.message);
10748
11044
  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`;
11045
+ const { url: validationUrl, text: validationText } = extractGoogleValidationLink(ctx.message);
11046
+ const validationLabel = validationText || "Verify your account";
11047
+ if (validationUrl) {
11048
+ const linkLine = `
11049
+ ${formatCliHyperlink(validationUrl, validationLabel)}`;
11050
+ const rawLine = resolveCliHyperlinkEnabled() ? `
11051
+ \u70B9\u4E0D\u4E86\u5C31\u590D\u5236\u8FD9\u884C: ${validationUrl}` : "";
11052
+ const verifyHint = `
11053
+ \u24D8 \u60F3\u4E00\u952E\u6253\u5F00\uFF1F\u8DD1 \`nolo auth antigravity --verify\` \u2014\u2014 \u5B83\u4F1A\u7528\u672C\u5730\u51ED\u8BC1\u62FF\u5230\u5F53\u524D\u9A8C\u8BC1\u94FE\u63A5\u5E76\u76F4\u63A5\u62C9\u8D77\u6D4F\u89C8\u5668\u3002`;
11054
+ const retryLine = `
11055
+ \u9A8C\u8BC1\u5B8C\u6210\u540E\u76F4\u63A5\u91CD\u8BD5\u521A\u624D\u7684\u547D\u4EE4\u5373\u53EF\uFF0Ctoken \u4E0D\u7528\u91CD\u65B0\u767B\u5F55\u3002`;
11056
+ return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}: Google requires a one-time account verification \u2014 your credential is fine).
11057
+ Open this link in a browser signed into ${ctx.credentialAccountId ? `\`${ctx.credentialAccountId}\`` : "the Google account behind this credential"}:${linkLine}${rawLine}${verifyHint}${retryLine}
11058
+ Detail: ${ctx.message} ${NO_FALLBACK} Use --server to run on the server explicitly.
11059
+ `;
11060
+ }
10749
11061
  return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}, auth rejected). Detail: ${ctx.message} ${NO_FALLBACK} ${fix}, ${SERVER_FALLBACK_HINT}.
10750
11062
  `;
10751
11063
  }
@@ -10781,6 +11093,17 @@ function buildUpstreamFailure(ctx) {
10781
11093
  return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}). Detail: ${ctx.message} ${NO_FALLBACK} ${fix}, ${SERVER_FALLBACK_HINT}.
10782
11094
  `;
10783
11095
  }
11096
+ function formatLocalTurnFailureLine(error) {
11097
+ const message = toErrorMessage(error);
11098
+ if (error?.code === "LLM_REQUEST_TIMEOUT") {
11099
+ const msMatch = /after (\d+)ms/.exec(message);
11100
+ const deadline = msMatch && Number.isFinite(Number(msMatch[1])) ? formatElapsed(Math.round(Number(msMatch[1]) / 1e3)) : "the configured window";
11101
+ return `[nolo] ${t("llmRequestTimedOut", deadline)}
11102
+ `;
11103
+ }
11104
+ return `[nolo] Local agent run failed: ${message}
11105
+ `;
11106
+ }
10784
11107
  var FAILURE_BUILDERS = {
10785
11108
  auth: buildAuthFailure,
10786
11109
  "rejected-payload": buildRejectedPayloadFailure,
@@ -10789,6 +11112,7 @@ var FAILURE_BUILDERS = {
10789
11112
  upstream: buildUpstreamFailure
10790
11113
  };
10791
11114
  function describeLocalRunFailure(message, rawError) {
11115
+ const credentialAccountId = rawError && typeof rawError === "object" && typeof rawError.credentialAccountId === "string" ? rawError.credentialAccountId.trim() || void 0 : void 0;
10792
11116
  if (rawError && typeof rawError === "object" && "code" in rawError && rawError.code === "PLATFORM_STREAM_INTERRUPTED") {
10793
11117
  return "[nolo] The platform LLM stream was interrupted before the turn completed. Your conversation was preserved. Send another message to continue.\n";
10794
11118
  }
@@ -10866,7 +11190,8 @@ function describeLocalRunFailure(message, rawError) {
10866
11190
  status: cls.status,
10867
11191
  ...cls.statusInferred ? { statusInferred: true } : {},
10868
11192
  ...cls.quotaExhausted ? { quotaExhausted: true } : {},
10869
- ...cooldownUntil ? { cooldownUntil } : {}
11193
+ ...cooldownUntil ? { cooldownUntil } : {},
11194
+ ...credentialAccountId ? { credentialAccountId } : {}
10870
11195
  };
10871
11196
  return FAILURE_BUILDERS[cls.kind](ctx);
10872
11197
  }
@@ -11183,6 +11508,18 @@ async function runLocalAgentTurnForCli(options, settings) {
11183
11508
  if (event.kind === "llm-start") {
11184
11509
  turnOutput.showWorking();
11185
11510
  }
11511
+ if (event.kind === "turn-phase") {
11512
+ turnOutput.showPhase(event.phase);
11513
+ }
11514
+ if (event.kind === "compaction-start") {
11515
+ turnOutput.showPhase("compacting");
11516
+ }
11517
+ if (event.kind === "compaction-end" || // 压缩失败(timeout/provider-error)时 localLoop 按失败原子性语义
11518
+ // 带着裁剪后的历史继续本轮,切回等待模型文案;aborted 时 turn 随即
11519
+ // 结束,不再切文案(终态由 abort 路径收尾)。
11520
+ event.kind === "compaction-failed" && event.reason !== "aborted") {
11521
+ turnOutput.showPhase("waiting-provider");
11522
+ }
11186
11523
  if (event.kind === "image-downgraded") {
11187
11524
  options.output.write(
11188
11525
  "[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"
@@ -11228,6 +11565,9 @@ async function runLocalAgentTurnForCli(options, settings) {
11228
11565
  };
11229
11566
  } catch (error) {
11230
11567
  turnOutput.spinner.stop();
11568
+ turnOutput.cancel({
11569
+ preservePendingNarration: error?.code !== LOCAL_TURN_ABORTED_CODE && !options.abortSignal?.aborted
11570
+ });
11231
11571
  const savedDialogId = error?.dialogId;
11232
11572
  const abortedUsageRecords = error?.usageRecords;
11233
11573
  const abortedTurnCredits = sumPlatformCredits(abortedUsageRecords);
@@ -11251,10 +11591,12 @@ async function runLocalAgentTurnForCli(options, settings) {
11251
11591
  error.cooldownUntil = cooldownUntil;
11252
11592
  }
11253
11593
  if (settings.reportFailure) {
11254
- options.output.write(
11255
- `[nolo] Local agent run failed: ${toErrorMessage(error)}
11256
- `
11257
- );
11594
+ const failureLine = formatLocalTurnFailureLine(error);
11595
+ if (typeof options.output.writeErr === "function") {
11596
+ options.output.writeErr(failureLine);
11597
+ } else {
11598
+ options.output.write(failureLine);
11599
+ }
11258
11600
  if (cooldownUntil) {
11259
11601
  options.output.write(
11260
11602
  `[nolo] \u5DF2\u6807\u8BB0\u51B7\u5374\u81F3 ${cooldownUntil}\uFF0C\u5230\u671F\u524D\u6D3E\u53D1\u8BE5 agent \u4F1A\u88AB\u51B7\u5374\u95E8\u63A7\u62E6\u622A\u3002
@@ -11392,11 +11734,11 @@ async function runAgentTurn(options) {
11392
11734
  return { exitCode: 1 };
11393
11735
  }
11394
11736
  const localAvailability = await checkLocalAvailabilityBeforeHttpDispatch(options);
11395
- if (localAvailability?.exitCode) {
11737
+ if (localAvailability && "exitCode" in localAvailability) {
11396
11738
  return { exitCode: localAvailability.exitCode };
11397
11739
  }
11398
11740
  const httpResult = await runHttpAgentTurn(options, authToken);
11399
- if (httpResult.exitCode === 0 && localAvailability?.credentialKey) {
11741
+ if (httpResult.exitCode === 0 && !httpResult.streamInterrupted && localAvailability?.credentialKey) {
11400
11742
  await clearCredentialAvailability(
11401
11743
  localAvailability.credentialKey,
11402
11744
  options.env
@@ -12165,6 +12507,11 @@ var listMemoryEntitiesVNext = async (db, ownerId) => {
12165
12507
  }
12166
12508
  return rows;
12167
12509
  };
12510
+ var loadMemoryVNextCatalog = async (db, ownerId) => {
12511
+ const entities = await listMemoryEntitiesVNext(db, ownerId);
12512
+ const states = (await Promise.all(entities.map((entity) => listMemoryStatesForEntityVNext(db, ownerId, entity.id)))).flat();
12513
+ return { entities, states };
12514
+ };
12168
12515
  var getMemoryStateVNext = async (db, ownerId, stateId) => db.get(stateKey(ownerId, stateId)).catch(() => null);
12169
12516
  var listMemoryStatesForEntityVNext = (db, ownerId, entityId) => readIndexed(db, stateEntityIndexPrefix(ownerId, entityId));
12170
12517
  var putMemoryEvidenceVNext = async (db, evidence) => {
@@ -12229,14 +12576,6 @@ var parseSelection = (raw) => {
12229
12576
  reason: obj.reason
12230
12577
  };
12231
12578
  };
12232
- var buildCatalog = async (db, ownerId) => {
12233
- const entities = await listMemoryEntitiesVNext(db, ownerId);
12234
- const states = [];
12235
- for (const entity of entities) {
12236
- states.push(...await listMemoryStatesForEntityVNext(db, ownerId, entity.id));
12237
- }
12238
- return { entities, states };
12239
- };
12240
12579
  var catalogText = (entities, states) => JSON.stringify(
12241
12580
  {
12242
12581
  entities: entities.map((entity) => ({
@@ -12262,7 +12601,7 @@ var catalogText = (entities, states) => JSON.stringify(
12262
12601
  );
12263
12602
  var createMemoryVNextRecall = (input) => async (query) => {
12264
12603
  const startedAt = performance.now();
12265
- const { entities, states } = await buildCatalog(input.db, input.ownerId);
12604
+ const { entities, states } = await loadMemoryVNextCatalog(input.db, input.ownerId);
12266
12605
  if (entities.length === 0 && states.length === 0) {
12267
12606
  return {
12268
12607
  query,
@@ -13133,14 +13472,74 @@ var shortError2 = (error) => {
13133
13472
  return message.length > ERROR_MESSAGE_MAX2 ? `${message.slice(0, ERROR_MESSAGE_MAX2)}\u2026` : message;
13134
13473
  };
13135
13474
  var loadExistingContext = async (db, ownerId) => {
13136
- const entities = await listMemoryEntitiesVNext(db, ownerId);
13137
- const states = (await Promise.all(
13138
- entities.map((entity) => listMemoryStatesForEntityVNext(db, ownerId, entity.id))
13139
- )).flat();
13140
- return {
13141
- entityIds: entities.map((entity) => entity.id),
13142
- states
13475
+ const { entities, states } = await loadMemoryVNextCatalog(db, ownerId);
13476
+ return { entityIds: entities.map((entity) => entity.id), states };
13477
+ };
13478
+ var currentStatesCitingEvidence = (states, evidenceId) => states.filter((state2) => !state2.retiredAt && (state2.evidenceIds ?? []).includes(evidenceId));
13479
+ var isEvidenceCoveredByCurrentStates = (states, evidenceId) => currentStatesCitingEvidence(states, evidenceId).length > 0;
13480
+ var memoryVNextContextFingerprint = (existing) => {
13481
+ const states = existing.states ?? [];
13482
+ const entityIds = existing.entityIds ?? [];
13483
+ const canonical = [
13484
+ ...entityIds.map((id) => `e\0${id}`),
13485
+ ...states.map((state2) => `s\0${state2.id}\0${state2.updatedAt}\0${state2.retiredAt ?? ""}`)
13486
+ ].sort().join("");
13487
+ let hash = 2166136261;
13488
+ for (let i = 0; i < canonical.length; i++) {
13489
+ hash ^= canonical.charCodeAt(i);
13490
+ hash = Math.imul(hash, 16777619);
13491
+ }
13492
+ return `${entityIds.length}.${states.length}:${(hash >>> 0).toString(16)}`;
13493
+ };
13494
+ var MAX_NOOP_SUPPRESSIONS = 512;
13495
+ var noOpSuppressions = /* @__PURE__ */ new Map();
13496
+ var suppressionKey = (ownerId, evidenceId) => `${ownerId}\0${evidenceId}`;
13497
+ var recordNoOpSuppression = (ownerId, evidenceId, fingerprint) => {
13498
+ const key = suppressionKey(ownerId, evidenceId);
13499
+ noOpSuppressions.delete(key);
13500
+ noOpSuppressions.set(key, fingerprint);
13501
+ while (noOpSuppressions.size > MAX_NOOP_SUPPRESSIONS) {
13502
+ noOpSuppressions.delete(noOpSuppressions.keys().next().value);
13503
+ }
13504
+ };
13505
+ var noOpHistory = (ownerId, evidenceId, fingerprint) => {
13506
+ const recorded = noOpSuppressions.get(suppressionKey(ownerId, evidenceId));
13507
+ if (recorded === void 0) return "fresh";
13508
+ return recorded === fingerprint ? "suppressed" : "stale";
13509
+ };
13510
+ var pickFirstUncoveredLazyPromotionItem = async (db, selected) => {
13511
+ const contextByOwner = /* @__PURE__ */ new Map();
13512
+ const contextFor = (ownerId) => {
13513
+ let pending = contextByOwner.get(ownerId);
13514
+ if (!pending) {
13515
+ pending = loadExistingContext(db, ownerId).then((existing) => ({
13516
+ states: existing.states ?? [],
13517
+ fingerprint: memoryVNextContextFingerprint(existing)
13518
+ }));
13519
+ contextByOwner.set(ownerId, pending);
13520
+ }
13521
+ return pending;
13143
13522
  };
13523
+ let skippedCoveredCount = 0;
13524
+ let skippedNoOpCount = 0;
13525
+ let firstStale = null;
13526
+ for (const [selectedIndex, item] of selected.entries()) {
13527
+ const evidence = buildLegacyMemoryEvidence(item);
13528
+ const context = await contextFor(evidence.ownerId);
13529
+ if (isEvidenceCoveredByCurrentStates(context.states, evidence.id)) {
13530
+ skippedCoveredCount++;
13531
+ continue;
13532
+ }
13533
+ const history = noOpHistory(evidence.ownerId, evidence.id, context.fingerprint);
13534
+ if (history === "fresh") {
13535
+ return { item, selectedIndex, skippedCoveredCount, skippedNoOpCount };
13536
+ }
13537
+ if (history === "stale" && !firstStale) {
13538
+ firstStale = { item, selectedIndex, skippedCoveredCount, skippedNoOpCount };
13539
+ }
13540
+ skippedNoOpCount++;
13541
+ }
13542
+ return firstStale;
13144
13543
  };
13145
13544
  var withoutImportedEvidence = (mutation, importedEvidenceId) => ({
13146
13545
  ...mutation,
@@ -13156,6 +13555,11 @@ var runMemoryVNextLazyPromotion = async (input) => {
13156
13555
  }));
13157
13556
  const finish = (partial) => {
13158
13557
  const observation = {
13558
+ legacyItemId: input.item.id,
13559
+ evidenceId: deterministicEvidence.id,
13560
+ ...input.selectedIndex === void 0 ? {} : { selectedIndex: input.selectedIndex },
13561
+ ...input.skippedCoveredCount === void 0 ? {} : { skippedCoveredCount: input.skippedCoveredCount },
13562
+ ...input.skippedNoOpCount === void 0 ? {} : { skippedNoOpCount: input.skippedNoOpCount },
13159
13563
  ...partial,
13160
13564
  latencyMs: Math.round((clock() - startedAt) * 10) / 10
13161
13565
  };
@@ -13178,8 +13582,9 @@ var runMemoryVNextLazyPromotion = async (input) => {
13178
13582
  }
13179
13583
  const evidence = evidenceResult.evidence;
13180
13584
  const existing = await loadExistingContext(input.db, evidence.ownerId);
13181
- const alreadyCovered = (existing.states ?? []).some(
13182
- (state2) => !state2.retiredAt && state2.evidenceIds.includes(evidence.id)
13585
+ const alreadyCovered = isEvidenceCoveredByCurrentStates(
13586
+ existing.states ?? [],
13587
+ evidence.id
13183
13588
  );
13184
13589
  if (alreadyCovered) {
13185
13590
  return finish({ status: "already_covered" });
@@ -13194,6 +13599,11 @@ var runMemoryVNextLazyPromotion = async (input) => {
13194
13599
  });
13195
13600
  const semanticMutation = withoutImportedEvidence(interpreted.mutation, evidence.id);
13196
13601
  if (!hasWrites(semanticMutation)) {
13602
+ recordNoOpSuppression(
13603
+ evidence.ownerId,
13604
+ evidence.id,
13605
+ memoryVNextContextFingerprint(existing)
13606
+ );
13197
13607
  return finish({ status: "no_op", action: semanticMutation.action });
13198
13608
  }
13199
13609
  await applyMemoryInterpreterMutation(input.db, evidence.ownerId, semanticMutation);
@@ -13206,6 +13616,179 @@ var runMemoryVNextLazyPromotion = async (input) => {
13206
13616
  };
13207
13617
  var isMemoryVNextLazyPromotionEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_LAZY_PROMOTION === "1" || env.NOLO_MEMORY_VNEXT_LAZY_PROMOTION === "true";
13208
13618
 
13619
+ // packages/ai/memory/vnext/pureReadGate.ts
13620
+ var isMemoryVNextPureReadEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_PURE_READ === "1" || env.NOLO_MEMORY_VNEXT_PURE_READ === "true";
13621
+
13622
+ // packages/ai/memory/vnext/localRecall.ts
13623
+ var MIN_SHARED_TOKENS = 2;
13624
+ var MAX_LOCAL_RECALL_STATES = 8;
13625
+ var SAFE_TECHNICAL_SYNONYMS = {
13626
+ pr: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5", "diff"],
13627
+ diff: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5"],
13628
+ review: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5"],
13629
+ deploy: ["\u90E8\u7F72", "\u53D1\u7248"],
13630
+ release: ["\u53D1\u7248", "\u53D1\u5E03"],
13631
+ desktop: ["\u684C\u9762", "\u684C\u9762\u7AEF"]
13632
+ };
13633
+ var distinctTokens = (text) => new Set(tokenize2(text).filter((token) => token.length >= 2));
13634
+ var recallMemoryVNextLocal = (input) => {
13635
+ const rawTokens = distinctTokens(input.query);
13636
+ if (rawTokens.size === 0) return [];
13637
+ const queryTokens = new Set(rawTokens);
13638
+ for (const token of rawTokens) {
13639
+ const syns = SAFE_TECHNICAL_SYNONYMS[token.toLowerCase()];
13640
+ if (syns) {
13641
+ for (const syn of syns) {
13642
+ for (const t2 of distinctTokens(syn)) queryTokens.add(t2);
13643
+ }
13644
+ }
13645
+ }
13646
+ const entityById = new Map(input.entities.map((entity) => [entity.id, entity]));
13647
+ const hits = [];
13648
+ for (const state2 of input.states) {
13649
+ if (state2.retiredAt || !state2.text.trim()) continue;
13650
+ const entity = entityById.get(state2.entityId);
13651
+ const haystack = distinctTokens(
13652
+ [state2.facet, state2.text, entity?.name ?? "", ...entity?.aliases ?? []].join(" ")
13653
+ );
13654
+ let sharedTokens = 0;
13655
+ for (const token of queryTokens) if (haystack.has(token)) sharedTokens++;
13656
+ if (sharedTokens >= MIN_SHARED_TOKENS) hits.push({ state: state2, sharedTokens });
13657
+ }
13658
+ return hits.sort((a, b) => b.sharedTokens - a.sharedTokens || a.state.id.localeCompare(b.state.id)).slice(0, input.limit ?? MAX_LOCAL_RECALL_STATES);
13659
+ };
13660
+
13661
+ // packages/ai/memory/vnext/pureVNextRuntime.ts
13662
+ var buildSynthesizedStateItem = (state2, entity, ownerType, ownerId) => ({
13663
+ id: `vnext-state-${state2.id}`,
13664
+ ownerType,
13665
+ ownerId,
13666
+ visibility: "private",
13667
+ subjectType: "user",
13668
+ subjectId: ownerId,
13669
+ kind: "semantic",
13670
+ content: state2.text.trim(),
13671
+ createdAt: state2.createdAt,
13672
+ lastActivatedAt: state2.createdAt,
13673
+ activationCount: 1,
13674
+ importance: 0.9,
13675
+ confidence: 0.9,
13676
+ resident: state2.facet === "preference" || state2.facet === "style"
13677
+ });
13678
+ async function resolvePureVNextRuntime(input) {
13679
+ const { db, owners, userInput } = input;
13680
+ if (owners.length === 0 || !userInput.trim()) {
13681
+ return { selectedItems: [], promptBlock: null, recalledStateCount: 0 };
13682
+ }
13683
+ const ownerIds = owners.map((o) => `${o.ownerType}:${encodeURIComponent(o.ownerId)}`);
13684
+ const catalogs = await Promise.all(
13685
+ ownerIds.map((ownerId) => loadMemoryVNextCatalog(db, ownerId))
13686
+ );
13687
+ const selectedItems = [];
13688
+ const seenStateKeys = /* @__PURE__ */ new Set();
13689
+ for (let i = 0; i < owners.length; i++) {
13690
+ const owner = owners[i];
13691
+ const catalog = catalogs[i];
13692
+ const currentStates = catalog.states.filter((s) => !s.retiredAt && s.text.trim());
13693
+ const hits = recallMemoryVNextLocal({
13694
+ query: userInput,
13695
+ entities: catalog.entities,
13696
+ states: currentStates
13697
+ });
13698
+ const entityById = new Map(catalog.entities.map((e) => [e.id, e]));
13699
+ for (const hit of hits) {
13700
+ const stateKey2 = `${hit.state.ownerId}\0${hit.state.id}`;
13701
+ if (seenStateKeys.has(stateKey2)) continue;
13702
+ seenStateKeys.add(stateKey2);
13703
+ selectedItems.push(
13704
+ buildSynthesizedStateItem(hit.state, entityById.get(hit.state.entityId), owner.ownerType, owner.ownerId)
13705
+ );
13706
+ }
13707
+ }
13708
+ const promptBlock = selectedItems.length === 0 ? null : buildMemoryOverlay(selectedItems, {
13709
+ maxTokens: input.maxTokens ?? DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET
13710
+ });
13711
+ return {
13712
+ selectedItems,
13713
+ promptBlock,
13714
+ recalledStateCount: selectedItems.length
13715
+ };
13716
+ }
13717
+
13718
+ // packages/ai/memory/vnext/primaryRead.ts
13719
+ var MEMORY_VNEXT_PRIMARY_READ_TIMEOUT_MS = 300;
13720
+ var isMemoryVNextPrimaryReadEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_PRIMARY_READ === "1" || env.NOLO_MEMORY_VNEXT_PRIMARY_READ === "true";
13721
+ var buildSynthesizedStateItem2 = (state2, entity, ownerType, ownerId) => ({
13722
+ id: `vnext-state-${state2.id}`,
13723
+ ownerType,
13724
+ ownerId,
13725
+ visibility: "private",
13726
+ subjectType: "user",
13727
+ subjectId: ownerId,
13728
+ kind: "semantic",
13729
+ content: state2.text.trim(),
13730
+ createdAt: state2.createdAt,
13731
+ importance: 0.9,
13732
+ confidence: 0.9,
13733
+ // Flag resident preferences so they flow into overlay's resident section.
13734
+ resident: state2.facet === "preference" || state2.facet === "style",
13735
+ lastActivatedAt: state2.createdAt,
13736
+ activationCount: 1
13737
+ });
13738
+ var resolveMemoryVNextM4Selection = async (input) => {
13739
+ const { db, owners, query, selected } = input;
13740
+ const ownerIds = owners.map((o) => `${o.ownerType}:${encodeURIComponent(o.ownerId)}`);
13741
+ const catalogs = new Map(
13742
+ await Promise.all(
13743
+ ownerIds.map(async (ownerId) => [
13744
+ ownerId,
13745
+ await loadMemoryVNextCatalog(db, ownerId)
13746
+ ])
13747
+ )
13748
+ );
13749
+ const recalledStates = [];
13750
+ const recalledStateIds = /* @__PURE__ */ new Set();
13751
+ for (const owner of owners) {
13752
+ const principalId = `${owner.ownerType}:${encodeURIComponent(owner.ownerId)}`;
13753
+ const catalog = catalogs.get(principalId);
13754
+ if (!catalog) continue;
13755
+ const currentStates = catalog.states.filter((s) => !s.retiredAt && s.text.trim());
13756
+ const hits = recallMemoryVNextLocal({
13757
+ query,
13758
+ entities: catalog.entities,
13759
+ states: currentStates
13760
+ });
13761
+ const entityById = new Map(catalog.entities.map((e) => [e.id, e]));
13762
+ for (const hit of hits) {
13763
+ if (recalledStateIds.has(hit.state.id)) continue;
13764
+ recalledStateIds.add(hit.state.id);
13765
+ recalledStates.push(
13766
+ buildSynthesizedStateItem2(hit.state, entityById.get(hit.state.entityId), owner.ownerType, owner.ownerId)
13767
+ );
13768
+ }
13769
+ }
13770
+ const uncoveredLegacy = [];
13771
+ let coveredSuppressedCount = 0;
13772
+ for (const item of selected) {
13773
+ const evidence = buildLegacyMemoryEvidence(item);
13774
+ const catalog = catalogs.get(evidence.ownerId);
13775
+ const states = catalog?.states ?? [];
13776
+ const covering = currentStatesCitingEvidence(states, evidence.id);
13777
+ if (covering.length > 0) {
13778
+ coveredSuppressedCount++;
13779
+ } else {
13780
+ uncoveredLegacy.push(item);
13781
+ }
13782
+ }
13783
+ const renderItems = [...recalledStates, ...uncoveredLegacy];
13784
+ return {
13785
+ renderItems,
13786
+ recalledStateCount: recalledStates.length,
13787
+ uncoveredLegacyCount: uncoveredLegacy.length,
13788
+ coveredSuppressedCount
13789
+ };
13790
+ };
13791
+
13209
13792
  // packages/ai/memory/runtime.ts
13210
13793
  var COLD_STORAGE_CONFIDENCE = 0.3;
13211
13794
  var MEMORY_OVERLAY_TOKEN_BUDGET = DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET;
@@ -13328,6 +13911,18 @@ var resolveMemoryRuntime = async (input) => {
13328
13911
  if (owners.length === 0) {
13329
13912
  return { selectedItems: [], promptBlock: null };
13330
13913
  }
13914
+ if (isMemoryVNextPureReadEnabled()) {
13915
+ const pure = await resolvePureVNextRuntime({
13916
+ db: input.db,
13917
+ owners,
13918
+ userInput: input.userInput,
13919
+ maxTokens: MEMORY_OVERLAY_TOKEN_BUDGET
13920
+ });
13921
+ return {
13922
+ selectedItems: pure.selectedItems,
13923
+ promptBlock: pure.promptBlock
13924
+ };
13925
+ }
13331
13926
  const policy = resolveAgentMemoryPolicy({ agentKey: input.agentKey });
13332
13927
  const legacyStartedAt = performance.now();
13333
13928
  const candidates = await loadMemoryCandidatesFromDb(input.db, {
@@ -13357,10 +13952,62 @@ var resolveMemoryRuntime = async (input) => {
13357
13952
  );
13358
13953
  const selected = [...residentItems, ...ranked];
13359
13954
  const legacyLatencyMs = Math.round((performance.now() - legacyStartedAt) * 10) / 10;
13360
- const promptBlock = selected.length === 0 ? null : buildMemoryOverlay(selected, { maxTokens: MEMORY_OVERLAY_TOKEN_BUDGET });
13361
- const shadowEnabled = input.vNextShadowProvider != null && isMemoryVNextShadowReadEnabled();
13955
+ const renderOverlay = (items) => items.length === 0 ? null : buildMemoryOverlay(items, { maxTokens: MEMORY_OVERLAY_TOKEN_BUDGET });
13956
+ let promptBlock = renderOverlay(selected);
13957
+ const primaryRead = isMemoryVNextPrimaryReadEnabled();
13958
+ let allCoveredByVNext = false;
13959
+ if (primaryRead) {
13960
+ const emitPrimary = (observation) => {
13961
+ try {
13962
+ (input.primaryReadEmit ?? ((o) => console.info("[memory] vnext primary read", { event: "memory_vnext_primary_read", ...o })))(observation);
13963
+ } catch {
13964
+ }
13965
+ };
13966
+ const base = { legacyHitCount: selected.length, legacyLatencyMs };
13967
+ const vnextStartedAt = performance.now();
13968
+ const vnextLatency = () => Math.round((performance.now() - vnextStartedAt) * 10) / 10;
13969
+ if (selected.length === 0) {
13970
+ emitPrimary({ ...base, source: "none" });
13971
+ } else {
13972
+ try {
13973
+ let timer;
13974
+ const m4 = await Promise.race([
13975
+ resolveMemoryVNextM4Selection({ db: input.db, owners, query: input.userInput, selected }),
13976
+ new Promise((_, reject) => {
13977
+ timer = setTimeout(
13978
+ () => reject(Object.assign(new Error("timeout"), { name: "TimeoutError" })),
13979
+ MEMORY_VNEXT_PRIMARY_READ_TIMEOUT_MS
13980
+ );
13981
+ })
13982
+ ]).finally(() => clearTimeout(timer));
13983
+ promptBlock = renderOverlay(m4.renderItems);
13984
+ allCoveredByVNext = m4.uncoveredLegacyCount === 0 && m4.recalledStateCount > 0;
13985
+ const source = m4.recalledStateCount > 0 ? m4.uncoveredLegacyCount === 0 ? "vnext" : "hybrid" : m4.uncoveredLegacyCount > 0 ? "legacy_fallback" : "none";
13986
+ emitPrimary({
13987
+ ...base,
13988
+ source,
13989
+ uncoveredLegacyCount: m4.uncoveredLegacyCount,
13990
+ coveredSuppressedCount: m4.coveredSuppressedCount,
13991
+ recalledStateCount: m4.recalledStateCount,
13992
+ vnextLatencyMs: vnextLatency(),
13993
+ contextChars: promptBlock?.length ?? 0,
13994
+ ...source === "legacy_fallback" ? { fallbackReason: "no_vnext_context" } : {}
13995
+ });
13996
+ } catch (error) {
13997
+ emitPrimary({
13998
+ ...base,
13999
+ source: "legacy_fallback",
14000
+ vnextLatencyMs: vnextLatency(),
14001
+ contextChars: promptBlock?.length ?? 0,
14002
+ fallbackReason: "vnext_error",
14003
+ error: error instanceof Error ? error.name : "UnknownError"
14004
+ });
14005
+ }
14006
+ }
14007
+ }
14008
+ const shadowEnabled = !primaryRead && input.vNextShadowProvider != null && isMemoryVNextShadowReadEnabled();
13362
14009
  if (shadowEnabled) {
13363
- await runMemoryVNextShadowRead({
14010
+ void runMemoryVNextShadowRead({
13364
14011
  ctx: {
13365
14012
  db: input.db,
13366
14013
  owners,
@@ -13370,17 +14017,28 @@ var resolveMemoryRuntime = async (input) => {
13370
14017
  legacyItems: selected,
13371
14018
  legacyLatencyMs,
13372
14019
  legacyContextChars: promptBlock?.length ?? 0
14020
+ }).catch(() => {
13373
14021
  });
13374
14022
  }
13375
- const promotionCandidate = selected[0];
13376
14023
  const lazyPromotionEnabled = input.vNextShadowProvider != null && isMemoryVNextLazyPromotionEnabled();
13377
- if (lazyPromotionEnabled && promotionCandidate) {
13378
- void runMemoryVNextLazyPromotion({
13379
- db: input.db,
13380
- item: promotionCandidate,
13381
- provider: input.vNextShadowProvider,
13382
- ...input.lazyPromotionEmit ? { emit: input.lazyPromotionEmit } : {}
13383
- }).catch(() => {
14024
+ if (lazyPromotionEnabled && selected.length > 0 && !allCoveredByVNext) {
14025
+ void (async () => {
14026
+ const promotionPick = await pickFirstUncoveredLazyPromotionItem(
14027
+ input.db,
14028
+ selected
14029
+ );
14030
+ if (promotionPick) {
14031
+ await runMemoryVNextLazyPromotion({
14032
+ db: input.db,
14033
+ item: promotionPick.item,
14034
+ selectedIndex: promotionPick.selectedIndex,
14035
+ skippedCoveredCount: promotionPick.skippedCoveredCount,
14036
+ skippedNoOpCount: promotionPick.skippedNoOpCount,
14037
+ provider: input.vNextShadowProvider,
14038
+ ...input.lazyPromotionEmit ? { emit: input.lazyPromotionEmit } : {}
14039
+ });
14040
+ }
14041
+ })().catch(() => {
13384
14042
  });
13385
14043
  }
13386
14044
  if (selected.length === 0) {
@@ -13394,6 +14052,52 @@ var resolveMemoryRuntime = async (input) => {
13394
14052
  };
13395
14053
 
13396
14054
  // packages/cli/memoryRecall.ts
14055
+ var logger = getLogger("cli.memoryRecall");
14056
+ var DEDUP_WINDOW_MS = 5 * 60 * 1e3;
14057
+ var DEDUP_MAX_KEYS = 100;
14058
+ var dedupMap = /* @__PURE__ */ new Map();
14059
+ function evictDedupIfNeeded() {
14060
+ if (dedupMap.size < DEDUP_MAX_KEYS) return;
14061
+ let oldestKey = null;
14062
+ let oldestTs = Infinity;
14063
+ for (const [k, v] of dedupMap) {
14064
+ if (v.lastLog < oldestTs) {
14065
+ oldestTs = v.lastLog;
14066
+ oldestKey = k;
14067
+ }
14068
+ }
14069
+ if (oldestKey !== null) dedupMap.delete(oldestKey);
14070
+ }
14071
+ function logDeduped(level, fingerprint, message, error) {
14072
+ const now = Date.now();
14073
+ const entry = dedupMap.get(fingerprint);
14074
+ if (!entry) {
14075
+ evictDedupIfNeeded();
14076
+ dedupMap.set(fingerprint, { count: 1, suppressed: 0, lastLog: now });
14077
+ if (error !== void 0) logger[level](message, error);
14078
+ else logger[level](message);
14079
+ return;
14080
+ }
14081
+ entry.count += 1;
14082
+ if (now - entry.lastLog >= DEDUP_WINDOW_MS) {
14083
+ const suppressed = entry.suppressed;
14084
+ const summary = `${message} (deduplicated: ${entry.count} occurrences, ${suppressed} suppressed over ${Math.round((now - entry.lastLog) / 1e3)}s)`;
14085
+ if (error !== void 0) logger[level](summary, error);
14086
+ else logger[level](summary);
14087
+ entry.count = 1;
14088
+ entry.suppressed = 0;
14089
+ entry.lastLog = now;
14090
+ } else {
14091
+ entry.suppressed += 1;
14092
+ }
14093
+ }
14094
+ function fingerprintFor(kind, detail) {
14095
+ const d = detail === void 0 ? "" : sanitizeFp(String(detail));
14096
+ return `mem-${kind}:${d}`;
14097
+ }
14098
+ function sanitizeFp(s) {
14099
+ return s.replace(/\s+/g, " ").slice(0, 80);
14100
+ }
13397
14101
  var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceId) => {
13398
14102
  try {
13399
14103
  const response = await fetch(`${serverUrl}/api/memory/query`, {
@@ -13410,10 +14114,10 @@ var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceI
13410
14114
  signal: AbortSignal.timeout(5e3)
13411
14115
  });
13412
14116
  if (!response.ok) {
13413
- console.warn(
13414
- "[cli-memory] remote query returned non-ok status:",
13415
- response.status,
13416
- "\u2014 falling back to local"
14117
+ logDeduped(
14118
+ "warn",
14119
+ fingerprintFor("remote-nonok", response.status),
14120
+ `remote query returned non-ok status ${response.status} \u2014 falling back to local`
13417
14121
  );
13418
14122
  return null;
13419
14123
  }
@@ -13421,7 +14125,12 @@ var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceI
13421
14125
  const block = typeof payload?.promptBlock === "string" ? payload.promptBlock.trim() : "";
13422
14126
  return block || null;
13423
14127
  } catch (error) {
13424
- console.warn("[cli-memory] remote query failed, falling back to local:", error);
14128
+ logDeduped(
14129
+ "info",
14130
+ fingerprintFor("remote-failed", error instanceof Error ? error.name : void 0),
14131
+ "remote query failed, falling back to local",
14132
+ normalizeError(error)
14133
+ );
13425
14134
  return null;
13426
14135
  }
13427
14136
  };
@@ -13457,7 +14166,12 @@ var resolveCliMemory = async (input) => {
13457
14166
  input.spaceId
13458
14167
  );
13459
14168
  } catch (error) {
13460
- console.warn("[cli-memory] local recall failed, omitting memory layer:", error);
14169
+ logDeduped(
14170
+ "warn",
14171
+ fingerprintFor("local-failed", error instanceof Error ? error.name : void 0),
14172
+ "local recall failed, omitting memory layer",
14173
+ normalizeError(error)
14174
+ );
13461
14175
  return null;
13462
14176
  }
13463
14177
  };
@@ -13512,7 +14226,10 @@ async function resolveAgentRunAgentKey(args) {
13512
14226
  }
13513
14227
  async function runAgentRunCommand(args, deps) {
13514
14228
  const env = deps.env ?? process.env;
13515
- const output = deps.output ?? process.stdout;
14229
+ const output = deps.output ?? {
14230
+ write: (chunk) => process.stdout.write(chunk),
14231
+ writeErr: (chunk) => process.stderr.write(chunk)
14232
+ };
13516
14233
  if (args.includes("--help") || args.includes("-h")) {
13517
14234
  writeUsage(output, deps.commandPath);
13518
14235
  return 0;
@@ -14054,12 +14771,6 @@ function isBalanceExhaustedError(error) {
14054
14771
  }
14055
14772
 
14056
14773
  export {
14057
- resolveAgentModelIdentity,
14058
- resolveAgentContextWindow,
14059
- platformCreditsFromUsage,
14060
- formatCreditsChip,
14061
- formatTokenCount,
14062
- renderTokenStatus,
14063
14774
  resolveCliColorEnabled,
14064
14775
  dimCliText,
14065
14776
  ANSI_ESCAPE_REGEX,
@@ -14100,6 +14811,12 @@ export {
14100
14811
  formatAssistantDisplay,
14101
14812
  redactSecrets,
14102
14813
  TUI_TREE_MARKER,
14814
+ resolveAgentModelIdentity,
14815
+ resolveAgentContextWindow,
14816
+ platformCreditsFromUsage,
14817
+ formatCreditsChip,
14818
+ formatTokenCount,
14819
+ renderTokenStatus,
14103
14820
  COLLAPSED_PASTE_PLACEHOLDER_RE,
14104
14821
  shouldCollapsePaste,
14105
14822
  createCollapsedPasteStore,
@@ -14110,15 +14827,16 @@ export {
14110
14827
  releaseCollapsedPasteReferences,
14111
14828
  expandRangeToCollapsedPasteChips,
14112
14829
  findCollapsedPasteSpanAt,
14830
+ formatElapsed,
14113
14831
  runAgentTurn,
14114
- readAgentsMdLayerFromDisk,
14115
14832
  resolveWorkflowReference,
14116
14833
  resolveSkillReference,
14117
14834
  buildSkillContextBlocks,
14118
14835
  prependSubjectDialogMarker,
14119
14836
  normalizeCliImageInput,
14120
- inspectLocalRunWorkspace,
14837
+ readAgentsMdLayerFromDisk,
14121
14838
  resolveCliMemory,
14839
+ inspectLocalRunWorkspace,
14122
14840
  resolveRunOutcome,
14123
14841
  isRunResultStalledOrTruncated,
14124
14842
  resolveRunSettlementNote,