nolo-cli 0.97.0-alpha.2 → 0.97.1

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 (182) hide show
  1. package/README.md +1 -1
  2. package/{_executeModel-G2MRKK2K.js → _executeModel-DYHTQJZC.js} +68 -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-4427YKQF.js → agentDeleteCommand-LLNNP3AM.js} +47 -43
  7. package/{agentEmailCommands-RNBKKO7Q.js → agentEmailCommands-MQOP76DK.js} +90 -82
  8. package/agentListCommands-J3MWAZWO.js +741 -0
  9. package/{agentMachineCommands-FOFX5S2Q.js → agentMachineCommands-EQIRKAZO.js} +42 -38
  10. package/{agentProviderCommands-GNPTL5XR.js → agentProviderCommands-EMZCM6VA.js} +1 -1
  11. package/{agentPullCommand-O5MPVJ5E.js → agentPullCommand-HF4A42D4.js} +1 -1
  12. package/agentRecordCommands-7MQRBMWZ.js +136 -0
  13. package/{agentRunCommand-2W3Q3A7M.js → agentRunCommand-H6BYSTJ7.js} +90 -80
  14. package/{agentRunControl-WCTKX5VL.js → agentRunControl-2TTTUTSW.js} +2 -2
  15. package/{agentRuntimeLocal-IW3IM5P6.js → agentRuntimeLocal-AY6YNUAL.js} +44 -36
  16. package/{agentSlice-SK47GTN7.js → agentSlice-FOZUXW7X.js} +11 -11
  17. package/{appDeleteCommands-ZXLXNRHF.js → appDeleteCommands-QTTL3QF3.js} +42 -38
  18. package/{appDeployCommands-PWB4YERK.js → appDeployCommands-43LJECGV.js} +42 -38
  19. package/{appDeployStatusCommands-2EZKZP7Y.js → appDeployStatusCommands-L5BKOLYW.js} +42 -38
  20. package/{appGetCommands-JNUKOWHO.js → appGetCommands-HOFZKOPC.js} +42 -38
  21. package/{appListCommands-6X3H67SS.js → appListCommands-I7C3SJCE.js} +42 -38
  22. package/{authCommand-F4EFRRX6.js → authCommand-2YPMMIJN.js} +117 -23
  23. package/{authCommands-RGOGCPP6.js → authCommands-FFDS4FVX.js} +7 -5
  24. package/{builtinSkillRegistry-FUAVTRVZ.js → builtinSkillRegistry-CALVIJTX.js} +6 -5
  25. package/{chatQueueReduxAdapter-ZJ555AT2.js → chatQueueReduxAdapter-NMEZRYC2.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-JEDZAO7L.js → chunk-2SYTUTLI.js} +257 -37
  30. package/{chunk-YQTQQX2H.js → chunk-2UV22D2F.js} +1 -1
  31. package/{chunk-7D6Z6AA4.js → chunk-3BFMH6GE.js} +6 -7
  32. package/{chunk-OIVSQH2O.js → chunk-3BXNTXYI.js} +299 -5
  33. package/{chunk-QIAVMDHY.js → chunk-3LX6YE3P.js} +4 -4
  34. package/{chunk-EYAQT56M.js → chunk-4DPP773Q.js} +2 -2
  35. package/chunk-4LCOCOR5.js +50 -0
  36. package/{chunk-2GRGFCF6.js → chunk-4VJAC32I.js} +2 -1
  37. package/{chunk-MC4XLIJ7.js → chunk-523DITKR.js} +1 -1
  38. package/{chunk-E4MARS3Q.js → chunk-5GVBDNTO.js} +1 -1
  39. package/chunk-5J3PYNUP.js +255 -0
  40. package/chunk-5MMAK75Q.js +15 -0
  41. package/{chunk-JPGCXHNM.js → chunk-5OA5HMTL.js} +1 -1
  42. package/{chunk-42V6BK2E.js → chunk-62IL3KQV.js} +4 -34
  43. package/{chunk-6YTOJY35.js → chunk-6D2JFXLY.js} +35 -0
  44. package/{chunk-3BMYXEUW.js → chunk-6O4IK4V2.js} +1 -1
  45. package/{chunk-IIVGDG4I.js → chunk-6PHKBY2Q.js} +10 -4
  46. package/{chunk-ASQYTZTR.js → chunk-6ZWMH6TJ.js} +69 -36
  47. package/{chunk-ABQYVJBJ.js → chunk-7CHC4W22.js} +1 -1
  48. package/{chunk-GQBOR3G6.js → chunk-7KVZ5LDQ.js} +2 -2
  49. package/{chunk-SDTTBMBU.js → chunk-7WCQEMPB.js} +888 -1079
  50. package/{chunk-BLJWCTRL.js → chunk-AOPCEXTB.js} +1 -1
  51. package/{chunk-WGR3J4Q6.js → chunk-APMUYAPK.js} +17 -4
  52. package/{chunk-Q554LLSI.js → chunk-AUDNYVRC.js} +1 -1
  53. package/{chunk-RG6JBBX5.js → chunk-AWF3WO5R.js} +166 -13
  54. package/{chunk-GPCZ7UXG.js → chunk-AZRHIN5B.js} +1 -1
  55. package/chunk-BMQ2MJUK.js +153 -0
  56. package/{chunk-B4ZH7KVO.js → chunk-C3VLSD4K.js} +236 -36
  57. package/{chunk-4EZHSKTB.js → chunk-C53ZG23R.js} +2 -2
  58. package/chunk-CHOZJMJS.js +78 -0
  59. package/{chunk-HJUYAD4A.js → chunk-CPUFH46E.js} +8 -8
  60. package/{chunk-LS2ZANRJ.js → chunk-CTUQJVQM.js} +1 -1
  61. package/{chunk-BP4XNZRM.js → chunk-CU3QB4HW.js} +3 -3
  62. package/{chunk-ACTMNVHM.js → chunk-CYSYR67N.js} +1 -1
  63. package/{chunk-KQ4ONNQD.js → chunk-DAWDCRIG.js} +82 -8
  64. package/{chunk-VLTIYV3X.js → chunk-DCLMZ5TX.js} +4 -4
  65. package/{chunk-UKZDAFYT.js → chunk-DSSTTEKI.js} +6 -10
  66. package/{chunk-L7I247DF.js → chunk-EKS2APRJ.js} +21 -5
  67. package/{chunk-HVURBGF3.js → chunk-ESRMFY7G.js} +2 -2
  68. package/{chunk-TRV2MIDW.js → chunk-EXAJ6DCR.js} +1 -0
  69. package/chunk-GMZLP5DV.js +82 -0
  70. package/{chunk-FDTR4QJ6.js → chunk-H6A6X4EK.js} +32 -1
  71. package/{chunk-DVINR3PL.js → chunk-HDLLCBRF.js} +1 -1
  72. package/{chunk-OIMN34NA.js → chunk-HKTIX4ZE.js} +23 -76
  73. package/{chunk-ONXOABJR.js → chunk-HNGRBWYF.js} +3 -0
  74. package/{chunk-H62HCIUP.js → chunk-HYZIYH2H.js} +11 -10
  75. package/{chunk-3VNWWVKB.js → chunk-I3QNET24.js} +30 -17
  76. package/{chunk-WV42OMV7.js → chunk-IAESIMK7.js} +4 -4
  77. package/chunk-JBOO3DKI.js +7808 -0
  78. package/{chunk-O35EJJVP.js → chunk-JJ7P5CIY.js} +56 -34
  79. package/{chunk-OZPMVBJI.js → chunk-JZ5II5UV.js} +15 -20
  80. package/{chunk-JRQFUXY7.js → chunk-KCDUTE5V.js} +96 -19
  81. package/{chunk-QLNJRTKI.js → chunk-KHVJXNRY.js} +100 -100
  82. package/{chunk-ADTY7BWR.js → chunk-L76GP4ER.js} +24 -5
  83. package/{chunk-7S4YWN7P.js → chunk-MX574M24.js} +1 -1
  84. package/{chunk-FZGV4FGK.js → chunk-NUHHBEJC.js} +378 -187
  85. package/{chunk-53HEEOTT.js → chunk-O26PCYLS.js} +80 -13
  86. package/{chunk-3DII57IT.js → chunk-O2OWEFII.js} +1 -1
  87. package/{chunk-TDRTS7QW.js → chunk-O6JPWEEK.js} +77 -17
  88. package/chunk-OCZKATRC.js +129 -0
  89. package/{chunk-6D6VBVEW.js → chunk-OTEMQQZI.js} +80 -14
  90. package/chunk-P6GMCCAT.js +870 -0
  91. package/{chunk-3SK4LEIH.js → chunk-PLRLUZWS.js} +853 -209
  92. package/{chunk-DHDMC6FO.js → chunk-QKUMVP3O.js} +11 -6
  93. package/{chunk-X4QAVDFE.js → chunk-RMAWULCS.js} +498 -480
  94. package/{chunk-V4MJDUSR.js → chunk-RSEEDUMS.js} +2 -2
  95. package/{chunk-UZGQNTVW.js → chunk-S5XGT6GB.js} +5 -3
  96. package/{chunk-76WEAXJB.js → chunk-SACTCJAC.js} +18 -15
  97. package/{chunk-AFUORTY4.js → chunk-SONWNI3L.js} +21 -21
  98. package/{chunk-BYMV6QZG.js → chunk-TNIX77YM.js} +4 -0
  99. package/{chunk-2YMRWISD.js → chunk-TU5NE4U3.js} +9 -84
  100. package/chunk-TY3TIUJK.js +89 -0
  101. package/chunk-UEGYKNHO.js +13349 -0
  102. package/chunk-UNYJU5L6.js +780 -0
  103. package/{chunk-J4MOO56S.js → chunk-UQNS32WZ.js} +10 -2
  104. package/chunk-VIWDGTDA.js +8 -0
  105. package/chunk-VJVNU77E.js +83 -0
  106. package/{chunk-EHKBVWKL.js → chunk-VYN7O3OY.js} +1 -1
  107. package/{chunk-NEDZDG3M.js → chunk-WILHZY7K.js} +45 -45
  108. package/{chunk-UKWGR5SS.js → chunk-WIWM4FE3.js} +187 -398
  109. package/{chunk-R7N5TMTV.js → chunk-X7YLNILS.js} +13 -13
  110. package/{chunk-O6OSWFZQ.js → chunk-XUWRURDF.js} +6 -0
  111. package/{chunk-Q67DOFOO.js → chunk-Y3PMXGLH.js} +2 -0
  112. package/{chunk-SNPMM7H3.js → chunk-Y6AZRODX.js} +13 -13
  113. package/{chunk-RSJECD7I.js → chunk-YJKDTJ2X.js} +7 -7
  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/{chunk-Z77CRGTW.js → chunk-ZYWQNCBN.js} +1 -1
  119. package/commandRegistry-HUFXCF7Z.js +833 -0
  120. package/{contentThunks-YLWTUILV.js → contentThunks-TD5YOAQM.js} +32 -30
  121. package/{cooldownCommands-REAWYVTY.js → cooldownCommands-ZLEPIB4A.js} +2 -2
  122. package/{createAgentAutomationAction-HFLPOBWQ.js → createAgentAutomationAction-XUG62ANM.js} +32 -30
  123. package/{createDialogAction-4H52MURR.js → createDialogAction-L3CMZKNL.js} +36 -33
  124. package/{createPageAction-5YDRMJOS.js → createPageAction-WJ3MX6JS.js} +38 -36
  125. package/{chunk-NUVMWYJM.js → cursorProvider-YGGNMVWX.js} +2494 -9892
  126. package/{dbSlice-XVWBAGYN.js → dbSlice-DQ32LYTJ.js} +8 -8
  127. package/{deleteFile-YG6QMJLU.js → deleteFile-NX6QHCWZ.js} +3 -3
  128. package/{dialogCommands-KFK2FF5B.js → dialogCommands-VM3I4HBW.js} +45 -41
  129. package/{dialogSlice-TMSHUGEM.js → dialogSlice-DSHG3YUE.js} +36 -29
  130. package/{dist-VODFSGNG.js → dist-NJC2W7I4.js} +61 -54
  131. package/{docCreateCommands-V777WOZ7.js → docCreateCommands-TYUJPCOP.js} +44 -40
  132. package/{docDeleteCommands-5KHT7Z5Q.js → docDeleteCommands-5XEG2LXO.js} +44 -40
  133. package/{docReadCommands-BLROGWP3.js → docReadCommands-M6RO6QHV.js} +43 -39
  134. package/{docStore-OBC5QOW7.js → docStore-RYOGMPEF.js} +11 -10
  135. package/{docUpdateCommands-QXOZHQ5H.js → docUpdateCommands-DKOFTZRX.js} +44 -40
  136. package/{fetchMessages-EIU7UFFK.js → fetchMessages-67MEFPZR.js} +2 -2
  137. package/{getPricing-LUSEABA6.js → getPricing-NMMFT3YI.js} +3 -3
  138. package/{handleSendMessageAction-4LGNXH6T.js → handleSendMessageAction-XH742B27.js} +91 -83
  139. package/index.js +87 -884
  140. package/{localDialogRead-BTFJ4V2I.js → localDialogRead-EBRS242U.js} +2 -2
  141. package/{localRuntimeAuthority-6IR6BBXE.js → localRuntimeAuthority-5W6IJRAD.js} +6 -6
  142. package/{localRuntimeDb-SYQGUF4U.js → localRuntimeDb-3LRMNLCM.js} +1 -1
  143. package/{machineCommands-SNLCRHQK.js → machineCommands-EY3SKJCP.js} +85 -77
  144. package/{machineWsRunDispatch-ZGZVDQSO.js → machineWsRunDispatch-OJ77YNRD.js} +82 -74
  145. package/{memberThunks-QGFLFVCI.js → memberThunks-5ZXPR63F.js} +9 -9
  146. package/{models-T3SG6MJ5.js → models-ZPU5EDF4.js} +2 -2
  147. package/oauthTokenStore-ITEB663N.js +23 -0
  148. package/package.json +1 -1
  149. package/pdf-U6KSUEZZ.js +26435 -0
  150. package/processSpawn-SOAV3FEV.js +11 -0
  151. package/profileConfig-ZGOFORWV.js +43 -0
  152. package/{providerPresetApply-FG6NZ57W.js → providerPresetApply-76AVU3HD.js} +7 -7
  153. package/{providerRegistry-757OWH3O.js → providerRegistry-Z62NC45X.js} +11 -7
  154. package/{read-COE3ZYR6.js → read-EPTJRAEF.js} +5 -5
  155. package/{readDocTool-5USN4A6V.js → readDocTool-W4NDXNEX.js} +5 -3
  156. package/{readlineWorkspace-OUL7ZN7D.js → readlineWorkspace-PMTHAVMB.js} +2447 -2022
  157. package/{removeDialogAgentAction-IX3MN2ZO.js → removeDialogAgentAction-BVAWQKXE.js} +17 -19
  158. package/{runAgentClientLoop-GD3APV7V.js → runAgentClientLoop-7WXN6I7L.js} +62 -58
  159. package/{runtimeDoctorCommands-X6WDBEQX.js → runtimeDoctorCommands-3USD722U.js} +3 -3
  160. package/runtimeModeArgs-2Y7BALTO.js +31 -0
  161. package/{setDialogExtraReferencesAction-X4HCPNZL.js → setDialogExtraReferencesAction-LYY45IAD.js} +12 -11
  162. package/{setPrimaryDialogAgentAction-4GMIQLOD.js → setPrimaryDialogAgentAction-73IL7DLU.js} +18 -20
  163. package/{settingSlice-ZQZVUPKK.js → settingSlice-Q6EKL7EQ.js} +9 -9
  164. package/{skillDiscovery-CYUCJMAG.js → skillDiscovery-ZBU76COE.js} +3 -3
  165. package/{spaceCommands-TIDVUPDV.js → spaceCommands-QFP4ZXKG.js} +44 -40
  166. package/{streamAgentChatTurn-M73KWCCU.js → streamAgentChatTurn-B4PXPJJS.js} +184 -91
  167. package/{switchDialogAgentAction-N52LRPA3.js → switchDialogAgentAction-UUXDSQ6X.js} +15 -17
  168. package/{tableCommands-O6NWHFKV.js → tableCommands-G7RV3RU3.js} +4 -4
  169. package/{toolApiClient-QVJ6HDNN.js → toolApiClient-INIQCPGY.js} +3 -3
  170. package/{tools-DXXDQ2CP.js → tools-QFS2L7BU.js} +55 -51
  171. package/{tuiSummaryLlmCaller-VJY3YD2Q.js → tuiSummaryLlmCaller-74NRRLVW.js} +18 -16
  172. package/{updateCommands-2M74UL7P.js → updateCommands-4EHDLF5J.js} +3 -3
  173. package/{updateDialogTitleAction-XI73NQMU.js → updateDialogTitleAction-HTDYCNNZ.js} +81 -43
  174. package/agentListCommands-O4AEMQVV.js +0 -406
  175. package/agentRecordCommands-6QK7AMXQ.js +0 -128
  176. package/chunk-M76ECQRD.js +0 -13658
  177. package/chunk-Q5FJJ6XI.js +0 -103
  178. package/chunk-S7Z2HMCN.js +0 -25
  179. package/chunk-WRFW73PB.js +0 -18881
  180. package/{chunk-VMFTFOWF.js → chunk-3AH7LNUB.js} +7 -7
  181. package/{chunk-X7HHHIOZ.js → chunk-Y6ROFCZO.js} +0 -0
  182. 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,76 @@ import {
26
26
  resolveFileWriteGateEnabled,
27
27
  resolveLocalUserId,
28
28
  t,
29
- toolLabel
30
- } from "./chunk-NUVMWYJM.js";
31
- import {
32
- createRunActivityTracker,
33
- popSingleQueueMessage,
34
- readRunRecord,
35
- resolveRunQueuePath,
36
- settleRunTerminalAuthoritatively,
37
- spawnLocalBackgroundRun
38
- } from "./chunk-WGR3J4Q6.js";
29
+ toolLabel,
30
+ toolLabelVariants
31
+ } from "./chunk-JBOO3DKI.js";
39
32
  import {
40
33
  clearCredentialAvailability,
41
34
  readCredentialEntry,
42
- recordCredentialProbe,
43
- resolveCredentialKeyWithFallback
44
- } from "./chunk-42V6BK2E.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
+ _appendEntityBatch,
42
+ _appendEvidenceBatch,
43
+ _appendRelationBatch,
44
+ _appendRetiredStateBatch,
45
+ _appendStateBatch,
46
+ getMemoryEntityVNext,
47
+ getMemoryEvidenceVNext,
48
+ getMemoryEvidenceVNextStrict,
49
+ getMemoryStateVNext,
50
+ listMemoryStatesForEntityVNext,
51
+ loadMemoryVNextCatalog,
52
+ putMemoryEvidenceVNext
53
+ } from "./chunk-TY3TIUJK.js";
54
+ import {
55
+ resolveMachineId
56
+ } from "./chunk-ESHYE7WU.js";
48
57
  import {
49
58
  readDbRecord,
50
59
  resolveAgentRecordFromHybridStore
51
- } from "./chunk-76WEAXJB.js";
60
+ } from "./chunk-SACTCJAC.js";
52
61
  import {
53
62
  isLocalCliAgentKey
54
63
  } from "./chunk-SV5IJK6K.js";
64
+ import {
65
+ extractGoogleValidationLink
66
+ } from "./chunk-BMQ2MJUK.js";
67
+ import {
68
+ createRunActivityTracker,
69
+ popSingleQueueMessage,
70
+ readRunRecord,
71
+ resolveRunQueuePath,
72
+ settleRunTerminalAuthoritatively,
73
+ spawnLocalBackgroundRun
74
+ } from "./chunk-APMUYAPK.js";
75
+ import {
76
+ isCliAuthorityBrokerProtocolError,
77
+ isCliAuthorityBrokerTimeoutError,
78
+ isCliAuthorityBrokerUnavailableError
79
+ } from "./chunk-EXAJ6DCR.js";
80
+ import {
81
+ getDefaultCliLocalRuntimeDb
82
+ } from "./chunk-ZOVKKMF6.js";
55
83
  import {
56
84
  CliProviderQuotaError
57
85
  } from "./chunk-MP64VFGD.js";
58
- import {
59
- resolveMachineId
60
- } from "./chunk-ESHYE7WU.js";
61
86
  import {
62
87
  applyModelLayerOverride,
63
88
  buildModelLayerOverride
64
89
  } from "./chunk-LTRXGFMS.js";
65
90
  import {
66
91
  formatAgentListCard
67
- } from "./chunk-X4QAVDFE.js";
68
- import {
69
- isTransientFetchError
70
- } from "./chunk-5UTFL4QJ.js";
92
+ } from "./chunk-RMAWULCS.js";
71
93
  import {
72
94
  isGatewayHttpStatus
73
95
  } from "./chunk-NF64D32W.js";
96
+ import {
97
+ isTransientFetchError
98
+ } from "./chunk-5UTFL4QJ.js";
74
99
  import {
75
100
  formatFinishedRunCard,
76
101
  formatListRunsCard,
@@ -79,43 +104,35 @@ import {
79
104
  formatStatusRunCard,
80
105
  formatStopRunCard,
81
106
  isAgentRunTerminalStatus
82
- } from "./chunk-3VNWWVKB.js";
107
+ } from "./chunk-I3QNET24.js";
83
108
  import {
84
109
  buildMemorySubjectsForAgent,
85
110
  chooseMemoryOwners,
86
111
  loadMemoryCandidatesFromDb,
87
112
  resolveAgentMemoryPolicy
88
- } from "./chunk-OZPMVBJI.js";
113
+ } from "./chunk-JZ5II5UV.js";
89
114
  import {
90
115
  API_REPORTED_COST_MULTIPLIER,
91
116
  parseUiAskChoiceContent
92
- } from "./chunk-WRFW73PB.js";
117
+ } from "./chunk-UEGYKNHO.js";
93
118
  import {
94
119
  isOAuthApiKeyRef
95
120
  } 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
121
  import {
105
122
  buildSkillDiscoveryContextLayer
106
- } from "./chunk-E4MARS3Q.js";
123
+ } from "./chunk-5GVBDNTO.js";
107
124
  import {
108
125
  parseExternalSkillMarkdown,
109
126
  parseSkillDocProtocol
110
- } from "./chunk-Q554LLSI.js";
127
+ } from "./chunk-AUDNYVRC.js";
111
128
  import {
112
129
  LOCAL_AGENT_CONFIG_MISSING_CODE,
113
130
  LOCAL_TURN_ABORTED_CODE,
114
131
  readActionGate
115
- } from "./chunk-SDTTBMBU.js";
132
+ } from "./chunk-7WCQEMPB.js";
116
133
  import {
117
134
  resolveAgentRuntimeConfigFromRecord
118
- } from "./chunk-4EZHSKTB.js";
135
+ } from "./chunk-C53ZG23R.js";
119
136
  import {
120
137
  createThinkParserState,
121
138
  flushThinkParser,
@@ -126,57 +143,62 @@ import {
126
143
  isQuotaExhaustedError,
127
144
  isQuotaLimited403Body,
128
145
  mergeAvailabilityDeadline,
129
- resolveCooldownGate
130
- } from "./chunk-FDTR4QJ6.js";
146
+ resolveCooldownGate,
147
+ resolveCredentialKeyWithFallback
148
+ } from "./chunk-H6A6X4EK.js";
131
149
  import {
132
150
  isAntigravityOAuthAgent
133
- } from "./chunk-UZGQNTVW.js";
151
+ } from "./chunk-S5XGT6GB.js";
134
152
  import {
135
153
  resolveClientVersion
136
- } from "./chunk-6OZ36FXI.js";
154
+ } from "./chunk-27ONFIEY.js";
137
155
  import {
138
156
  DEFAULT_CONTEXT_WINDOW,
139
157
  getModelContextWindow,
140
158
  normalizeUsage
141
- } from "./chunk-NEDZDG3M.js";
159
+ } from "./chunk-WILHZY7K.js";
142
160
  import {
143
161
  clipCompactText
144
- } from "./chunk-ASQYTZTR.js";
145
- import {
146
- findModelConfig
147
- } from "./chunk-OIVSQH2O.js";
162
+ } from "./chunk-5MMAK75Q.js";
148
163
  import {
149
164
  compactWhitespace
150
165
  } from "./chunk-DWLEOOGR.js";
151
166
  import {
152
167
  toErrorMessage
153
168
  } from "./chunk-HNMXYYJR.js";
169
+ import {
170
+ findModelConfig
171
+ } from "./chunk-3BXNTXYI.js";
154
172
  import {
155
173
  buildAgentsMdLayer,
156
174
  buildMemoryOverlayLayer,
157
175
  buildMemoryUseGuidanceLayer,
158
176
  partitionScopedBlocks,
159
177
  renderTurnContextBlocksWithScope
160
- } from "./chunk-DVINR3PL.js";
178
+ } from "./chunk-HDLLCBRF.js";
161
179
  import {
162
- readPipeText,
163
- spawnProcess
164
- } from "./chunk-X7HHHIOZ.js";
180
+ getLogger,
181
+ normalizeError
182
+ } from "./chunk-UNYJU5L6.js";
165
183
  import {
166
184
  resolveAuthToken
167
185
  } from "./chunk-A7GB5UGH.js";
186
+ import {
187
+ readPipeText,
188
+ spawnProcess
189
+ } from "./chunk-Y6ROFCZO.js";
168
190
  import {
169
191
  CLIENT_VERSION_TOO_OLD_CODE,
170
192
  NOLO_CLIENT_VERSION_HEADER,
171
193
  buildClientVersionUpgradeMessage
172
- } from "./chunk-Q67DOFOO.js";
194
+ } from "./chunk-Y3PMXGLH.js";
173
195
  import {
174
196
  parsePositiveFiniteNumberOrFallback
175
197
  } from "./chunk-Y5GCAMGP.js";
176
198
  import {
177
199
  createMemoryKey,
178
200
  ulid
179
- } from "./chunk-VMFTFOWF.js";
201
+ } from "./chunk-3AH7LNUB.js";
180
202
  import {
181
203
  asTrimmedLowercaseString
182
204
  } from "./chunk-QSJ3HFEF.js";
@@ -188,9 +210,6 @@ import {
188
210
  import {
189
211
  parsePublicAgentId
190
212
  } from "./chunk-M2EJHDJP.js";
191
- import {
192
- isLevelNotFoundError
193
- } from "./chunk-OW765XBU.js";
194
213
  import {
195
214
  asTrimmedString
196
215
  } from "./chunk-3EUW3WEO.js";
@@ -386,6 +405,24 @@ function styleCliText(text, style, enabled = resolveCliColorEnabled()) {
386
405
  function dimCliText(text, enabled = resolveCliColorEnabled()) {
387
406
  return styleCliText(text, "dim", enabled);
388
407
  }
408
+ var OSC8_OPEN = "\x1B]8;;";
409
+ var OSC8_CLOSE = "\x1B\\";
410
+ function sanitizeHyperlinkLabel(label) {
411
+ return label.replace(/[\u0000-\u001f\u007f]/g, "");
412
+ }
413
+ function resolveCliHyperlinkEnabled(env = process.env, isTTY = Boolean(process.stdout.isTTY)) {
414
+ const setting = asTrimmedLowercaseString(env.NOLO_CLI_HYPERLINKS);
415
+ if (setting === "0" || setting === "false" || setting === "off") return false;
416
+ if (setting === "1" || setting === "true" || setting === "on") return true;
417
+ return isTTY;
418
+ }
419
+ function formatCliHyperlink(url, label, enabled = resolveCliHyperlinkEnabled()) {
420
+ if (!url) return label;
421
+ const safeLabel = sanitizeHyperlinkLabel(label);
422
+ if (!enabled) return `${safeLabel} (${url})`;
423
+ if (!safeLabel) return url;
424
+ return `${OSC8_OPEN}${url}${OSC8_CLOSE}${safeLabel}${OSC8_OPEN}${OSC8_CLOSE}`;
425
+ }
389
426
 
390
427
  // node_modules/ansi-regex/index.js
391
428
  function ansiRegex({ onlyFirst = false } = {}) {
@@ -620,8 +657,12 @@ function stringWidth(input, options = {}) {
620
657
 
621
658
  // packages/cli/tui/tuiAnsi.ts
622
659
  var ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
660
+ var OSC8_HYPERLINK_REGEX = /\x1b\]8;;[^\x1b]*\x1b\\/g;
623
661
  var ALL_ANSI_ESCAPE_REGEX = ansiRegex();
624
662
  var FIRST_ANSI_ESCAPE_REGEX = ansiRegex({ onlyFirst: true });
663
+ function stripOsc8Hyperlinks(text) {
664
+ return text.replace(OSC8_HYPERLINK_REGEX, "");
665
+ }
625
666
  function stripAnsi2(text) {
626
667
  return text.replace(ANSI_ESCAPE_REGEX, "").replace(ALL_ANSI_ESCAPE_REGEX, "");
627
668
  }
@@ -783,6 +824,7 @@ function visibleWidth(str) {
783
824
  }
784
825
  function truncateAnsi(text, maxWidth) {
785
826
  if (maxWidth <= 0) return "";
827
+ text = stripOsc8Hyperlinks(text);
786
828
  if (visibleWidth(text) <= maxWidth) return text;
787
829
  let width = 0;
788
830
  let out = "";
@@ -823,7 +865,7 @@ function countPhysicalLines(text, columns) {
823
865
  const lines = text.split("\n");
824
866
  let total = 0;
825
867
  for (const line of lines) {
826
- const width = displayWidth(line);
868
+ const width = visibleWidth(stripOsc8Hyperlinks(line));
827
869
  total += Math.max(1, Math.ceil(width / columns));
828
870
  }
829
871
  return Math.max(total, 1);
@@ -8180,7 +8222,12 @@ function emitPlainGap(text, keywords, info, accent, warning, reset) {
8180
8222
  var UNORDERED_LIST_RE = /^(\s*)([-*+])\s+(.+)$/;
8181
8223
  var ORDERED_LIST_RE = /^(\s*)(\d+)\.\s+(.+)$/;
8182
8224
  var TASK_LIST_RE = /^(\s*)([-*+])\s+\[([ xX])\]\s+(.+)$/;
8225
+ var THEMATIC_BREAK_PATTERN = "(?:(-[ \\t]*){3,}|(\\*[ \\t]*){3,}|(_[ \\t]*){3,})";
8226
+ var THEMATIC_BREAK_RE = new RegExp(`^[ ]{0,3}${THEMATIC_BREAK_PATTERN}$`);
8183
8227
  function normalizeListLine(line) {
8228
+ if (THEMATIC_BREAK_RE.test(line)) {
8229
+ return line;
8230
+ }
8184
8231
  const task = line.match(TASK_LIST_RE);
8185
8232
  if (task) {
8186
8233
  const checked = task[3] === "x" || task[3] === "X";
@@ -8196,12 +8243,99 @@ function normalizeListLine(line) {
8196
8243
  }
8197
8244
  return line;
8198
8245
  }
8246
+ var TOOL_TREE_HEADER_RE = /^•\s+(.+?)\s+\((\d+)\)$/;
8247
+ var TOOL_TREE_LEAF_RE = /^([├└]──\s+)(.*?)\s{2}(✓|✗|!)(?:\s+(.*))?$/;
8248
+ var TOOL_SINGLE_RE = /^▸\s+(.+?)(?:\s+·\s+(.*?))?(?:\s{2}(✓|✗|!)(?:\s+(.*))?)$/;
8249
+ function plainToolLine(line) {
8250
+ return stripAnsi2(line);
8251
+ }
8252
+ var TOOL_TREE_GROUP_LABELS = new Set(
8253
+ ["execShell", "readFile", "fetchWebpage", "exa_search"].flatMap(toolLabelVariants)
8254
+ );
8255
+ function isKnownToolGroupLabel(label) {
8256
+ return TOOL_TREE_GROUP_LABELS.has(label);
8257
+ }
8258
+ function toolTreeHeaderMatch(line) {
8259
+ const match = plainToolLine(line).match(TOOL_TREE_HEADER_RE);
8260
+ return match && isKnownToolGroupLabel(match[1]) ? match : null;
8261
+ }
8262
+ function isToolTreeHeaderLine(line) {
8263
+ return toolTreeHeaderMatch(line) !== null;
8264
+ }
8265
+ function isToolTreeLeafLine(line) {
8266
+ return TOOL_TREE_LEAF_RE.test(plainToolLine(line));
8267
+ }
8268
+ function isToolSingleLine(line) {
8269
+ return TOOL_SINGLE_RE.test(plainToolLine(line));
8270
+ }
8271
+ function isToolGroupBoundary(cur, next) {
8272
+ return isToolTreeLeafLine(cur) && isToolTreeHeaderLine(next);
8273
+ }
8274
+ function statusColorSeq(marker, brightness) {
8275
+ if (marker === "\u2713") return colorSeq("success", brightness);
8276
+ if (marker === "\u2717") return colorSeq("danger", brightness);
8277
+ return colorSeq("warning", brightness);
8278
+ }
8279
+ function styleTuiToolLine(line, brightness) {
8280
+ const plain = plainToolLine(line);
8281
+ const chrome = colorSeq("chrome", brightness);
8282
+ const muted = colorSeq("muted", brightness);
8283
+ const header = toolTreeHeaderMatch(plain);
8284
+ if (header) {
8285
+ return `${chrome}\u2022${STYLE.reset} ${STYLE.bold}${muted}${header[1]}${STYLE.reset} ${chrome}${STYLE.dim}(${header[2]})${STYLE.reset}`;
8286
+ }
8287
+ const leaf = plain.match(TOOL_TREE_LEAF_RE);
8288
+ if (leaf) {
8289
+ const [, connector, detail, marker, statusDetail] = leaf;
8290
+ let rendered = `${chrome}${connector}${STYLE.reset}${chrome}${detail}${STYLE.reset}`;
8291
+ rendered += ` ${statusColorSeq(marker, brightness)}${marker}${STYLE.reset}`;
8292
+ if (statusDetail) {
8293
+ const metaSeq = marker === "\u2713" ? chrome : statusColorSeq(marker, brightness);
8294
+ rendered += ` ${metaSeq}${STYLE.dim}${statusDetail}${STYLE.reset}`;
8295
+ }
8296
+ return rendered;
8297
+ }
8298
+ const single = plain.match(TOOL_SINGLE_RE);
8299
+ if (single) {
8300
+ const [, label, detail, marker, statusDetail] = single;
8301
+ let rendered = `${chrome}\u25B8${STYLE.reset} ${STYLE.bold}${muted}${label}${STYLE.reset}`;
8302
+ if (detail) rendered += ` ${chrome}\xB7 ${detail}${STYLE.reset}`;
8303
+ rendered += ` ${statusColorSeq(marker, brightness)}${marker}${STYLE.reset}`;
8304
+ if (statusDetail) {
8305
+ const metaSeq = marker === "\u2713" ? chrome : statusColorSeq(marker, brightness);
8306
+ rendered += ` ${metaSeq}${STYLE.dim}${statusDetail}${STYLE.reset}`;
8307
+ }
8308
+ return rendered;
8309
+ }
8310
+ return null;
8311
+ }
8199
8312
  function isPolishListLikeLine(line) {
8200
- return LIST_LIKE_RE_FOR_GUARD.test(normalizeListLine(line));
8313
+ return LIST_LIKE_RE_FOR_GUARD.test(normalizeListLine(plainToolLine(line)));
8314
+ }
8315
+ var LIST_LIKE_RE_FOR_GUARD = /^\s*(?:•|◦|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s|^\s*▸\s/;
8316
+ function isPolishFenceInteriorLine(line) {
8317
+ return /^\x00F\d+\x00$/.test(line);
8318
+ }
8319
+ function polishHeadingLevel(line) {
8320
+ const match = stripAnsi2(line).match(/^(#{1,6})\s/);
8321
+ return match ? match[1].length : null;
8322
+ }
8323
+ function isPolishHeadingLine(line) {
8324
+ return polishHeadingLevel(line) !== null;
8325
+ }
8326
+ function isPolishIntroLine(line) {
8327
+ const plain = stripAnsi2(line).trimEnd();
8328
+ return plain.endsWith("\uFF1A") || plain.endsWith(":");
8201
8329
  }
8202
- var LIST_LIKE_RE_FOR_GUARD = /^\s*(?:•|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s/;
8203
8330
  function polishBreathInsertsBlankBetween(cur, next) {
8204
8331
  if (cur === "" || next === "") return false;
8332
+ if (isPolishFenceInteriorLine(cur) || isPolishFenceInteriorLine(next)) {
8333
+ return false;
8334
+ }
8335
+ if (isPolishIntroLine(cur) && isPolishListLikeLine(next)) return false;
8336
+ if (isPolishHeadingLine(cur) || isPolishHeadingLine(next)) return false;
8337
+ if (isCodeFenceLine(cur) !== isCodeFenceLine(next)) return true;
8338
+ if (isToolGroupBoundary(cur, next)) return true;
8205
8339
  return isPolishListLikeLine(cur) !== isPolishListLikeLine(next);
8206
8340
  }
8207
8341
  function convertMarkdownTablesForTerminal(text) {
@@ -8270,17 +8404,15 @@ function polishAssistantStructure(text, options = {}) {
8270
8404
  }
8271
8405
  return line;
8272
8406
  });
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/;
8407
+ 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
8408
  const headingLines = afterHeading.split("\n");
8276
8409
  const breathed = [];
8277
8410
  for (let i = 0; i < headingLines.length; i++) {
8278
8411
  breathed.push(headingLines[i]);
8279
8412
  const cur = headingLines[i];
8280
8413
  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("");
8414
+ if (next === void 0) continue;
8415
+ if (polishBreathInsertsBlankBetween(cur, next)) breathed.push("");
8284
8416
  }
8285
8417
  const polishedMasked = breathed.join("\n");
8286
8418
  const polished = polishedMasked.replace(
@@ -8290,17 +8422,23 @@ function polishAssistantStructure(text, options = {}) {
8290
8422
  return options.trimEdges === false ? polished : polished.trim();
8291
8423
  }
8292
8424
  function styleRichMarkdownLine(line, brightness) {
8293
- const heading = line.match(/^(#{1,3})\s+(.+)$/);
8425
+ const toolLine = styleTuiToolLine(line, brightness);
8426
+ if (toolLine !== null) return toolLine;
8427
+ const heading = line.match(/^(#{1,6})\s+(.+)$/);
8294
8428
  if (heading) {
8295
8429
  const level = heading[1].length;
8296
8430
  const title = heading[2];
8431
+ const styledTitle = styleInlineMarkdown(title, brightness);
8297
8432
  if (level === 1) {
8298
- return `${STYLE.bold}\x1B[4m${colorSeq("accent", brightness)}${title}${STYLE.reset}`;
8433
+ return `${STYLE.bold}${colorSeq("accent", brightness)}${styledTitle}${STYLE.reset}`;
8299
8434
  }
8300
8435
  if (level === 2) {
8301
- return `${STYLE.bold}${colorSeq("warning", brightness)}${title}${STYLE.reset}`;
8436
+ return `${STYLE.bold}${colorSeq("warning", brightness)}${styledTitle}${STYLE.reset}`;
8437
+ }
8438
+ if (level === 3) {
8439
+ return `${STYLE.bold}${colorSeq("info", brightness)}${styledTitle}${STYLE.reset}`;
8302
8440
  }
8303
- return `${STYLE.bold}${colorSeq("info", brightness)}${title}${STYLE.reset}`;
8441
+ return `${STYLE.bold}${colorSeq("muted", brightness)}${styledTitle}${STYLE.reset}`;
8304
8442
  }
8305
8443
  if (line.startsWith("\u8FDB\u5165 nolo-plan")) {
8306
8444
  return `${colorSeq("chrome", brightness)}${STYLE.dim}${line}${STYLE.reset}`;
@@ -8309,15 +8447,19 @@ function styleRichMarkdownLine(line, brightness) {
8309
8447
  if (blockquote) {
8310
8448
  const border = colorSeq("chrome", brightness);
8311
8449
  const content = blockquote[1];
8312
- return `${border}\u2502${STYLE.reset} ${STYLE.dim}${content}${STYLE.reset}`;
8450
+ const styled = styleInlineMarkdown(content, brightness);
8451
+ return `${border}\u2502${STYLE.reset} ${STYLE.dim}${styled}${STYLE.reset}`;
8313
8452
  }
8314
- if (/^---+$/.test(line.trim())) {
8315
- return `${colorSeq("chrome", brightness)}${"\u2500".repeat(Math.min(line.trim().length, 40))}${STYLE.reset}`;
8453
+ if (THEMATIC_BREAK_RE.test(line)) {
8454
+ return `${colorSeq("chrome", brightness)}${STYLE.dim}${"\u2500".repeat(36)}${STYLE.reset}`;
8316
8455
  }
8317
8456
  const bullet = line.match(/^(\s*)(•)\s(.+)$/);
8318
8457
  if (bullet) {
8458
+ const indent = bullet[1];
8319
8459
  const styled = styleInlineMarkdown(bullet[3], brightness);
8320
- return `${bullet[1]}${colorSeq("accent", brightness)}\u2022${STYLE.reset} ${styled}`;
8460
+ const marker = indent.length >= 2 ? "\u25E6" : "\u2022";
8461
+ const markerColor = indent.length >= 2 ? colorSeq("chrome", brightness) : colorSeq("accent", brightness);
8462
+ return `${indent}${markerColor}${marker}${STYLE.reset} ${styled}`;
8321
8463
  }
8322
8464
  const ordered = line.match(/^(\s*)(\d+\.)\s(.+)$/);
8323
8465
  if (ordered) {
@@ -8441,16 +8583,28 @@ function emitFormattedAssistantBlock(write, text, trailingNewline = false) {
8441
8583
  }
8442
8584
  function classifyStreamLine(line) {
8443
8585
  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)) {
8586
+ const plain = plainToolLine(line);
8587
+ if (isToolTreeHeaderLine(plain)) return "tool-header";
8588
+ if (isToolTreeLeafLine(plain)) return "tool-leaf";
8589
+ if (isToolSingleLine(plain)) return "tool";
8590
+ 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
8591
  return "list";
8446
8592
  }
8593
+ if (isPolishListLikeLine(plain)) return "list";
8594
+ if (polishHeadingLevel(plain) !== null) return "heading";
8447
8595
  return "prose";
8448
8596
  }
8449
- function needsListProseBreath(prev, next) {
8597
+ function isStreamListLike(kind) {
8598
+ return kind === "list" || kind === "tool-header" || kind === "tool-leaf" || kind === "tool";
8599
+ }
8600
+ function needsListProseBreath(prev, next, prevLine = "") {
8450
8601
  if (prev === null || prev === "blank" || next === "blank") return false;
8451
- const prevList = prev === "list";
8452
- const nextList = next === "list";
8453
- return prevList !== nextList;
8602
+ if (next === "heading") return true;
8603
+ if (prev === "heading") return (polishHeadingLevel(prevLine) ?? 7) <= 2;
8604
+ if (prev === "fence" !== (next === "fence")) return true;
8605
+ if (isStreamListLike(next) && isPolishIntroLine(prevLine)) return false;
8606
+ if (prev === "tool-leaf" && next === "tool-header") return true;
8607
+ return isStreamListLike(prev) !== isStreamListLike(next);
8454
8608
  }
8455
8609
  function createRenderAwareStreamWriter(args) {
8456
8610
  const brightness = resolveTuiBrightness();
@@ -8460,9 +8614,16 @@ function createRenderAwareStreamWriter(args) {
8460
8614
  let inMermaid = false;
8461
8615
  let mermaidBody = [];
8462
8616
  let lastKind = null;
8617
+ let lastLine = "";
8618
+ let pendingBlankRow = false;
8463
8619
  const PARTIAL_FLUSH_THRESHOLD = 48;
8464
8620
  const emitBreathIfNeeded = (nextKind) => {
8465
- if (needsListProseBreath(lastKind, nextKind)) args.write("\n");
8621
+ if (pendingBlankRow) {
8622
+ args.write("\n");
8623
+ pendingBlankRow = false;
8624
+ lastKind = "blank";
8625
+ }
8626
+ if (needsListProseBreath(lastKind, nextKind, lastLine)) args.write("\n");
8466
8627
  };
8467
8628
  const flushPartialProse = () => {
8468
8629
  if (inFence || buffer.length < PARTIAL_FLUSH_THRESHOLD) return;
@@ -8480,6 +8641,7 @@ function createRenderAwareStreamWriter(args) {
8480
8641
  emitBreathIfNeeded("prose");
8481
8642
  emitFormattedAssistantBlock(args.write, prefix, false);
8482
8643
  lastKind = "prose";
8644
+ lastLine = prefix;
8483
8645
  buffer = prefix.length === buffer.length ? "" : buffer.slice(prefix.length);
8484
8646
  };
8485
8647
  const flushCompleteBlocks = () => {
@@ -8495,10 +8657,11 @@ function createRenderAwareStreamWriter(args) {
8495
8657
  inMermaid = false;
8496
8658
  inFence = false;
8497
8659
  fenceLang = "unknown";
8498
- emitBreathIfNeeded("other");
8660
+ emitBreathIfNeeded("fence");
8499
8661
  args.write(`${STYLE.dim}${firstLine}${STYLE.reset}
8500
8662
  `);
8501
- lastKind = "other";
8663
+ lastKind = "fence";
8664
+ lastLine = firstLine;
8502
8665
  buffer = lines.slice(1).join("\n");
8503
8666
  continue;
8504
8667
  }
@@ -8514,10 +8677,11 @@ function createRenderAwareStreamWriter(args) {
8514
8677
  }
8515
8678
  inFence = true;
8516
8679
  }
8517
- emitBreathIfNeeded("other");
8680
+ emitBreathIfNeeded("fence");
8518
8681
  args.write(`${STYLE.dim}${firstLine}${STYLE.reset}
8519
8682
  `);
8520
- lastKind = "other";
8683
+ lastKind = "fence";
8684
+ lastLine = firstLine;
8521
8685
  buffer = lines.slice(1).join("\n");
8522
8686
  continue;
8523
8687
  }
@@ -8529,7 +8693,8 @@ function createRenderAwareStreamWriter(args) {
8529
8693
  if (inFence) {
8530
8694
  args.write(`${highlightCodeLine(firstLine, fenceLang, brightness)}
8531
8695
  `);
8532
- lastKind = "other";
8696
+ lastKind = "fence";
8697
+ lastLine = firstLine;
8533
8698
  buffer = lines.slice(1).join("\n");
8534
8699
  continue;
8535
8700
  }
@@ -8542,6 +8707,7 @@ function createRenderAwareStreamWriter(args) {
8542
8707
  const inner = trimmedFirst.slice(2, trimmedFirst.length - 2);
8543
8708
  args.write(renderMathBlock(inner) + "\n");
8544
8709
  lastKind = "other";
8710
+ lastLine = trimmedFirst;
8545
8711
  buffer = lines.slice(1).join("\n");
8546
8712
  continue;
8547
8713
  }
@@ -8568,6 +8734,7 @@ function createRenderAwareStreamWriter(args) {
8568
8734
  if (lastInner) innerParts.push(lastInner);
8569
8735
  args.write(renderMathBlock(innerParts.join("\n")) + "\n");
8570
8736
  lastKind = "other";
8737
+ lastLine = trimmedFirst;
8571
8738
  buffer = lines.slice(closeIndex + 1).join("\n");
8572
8739
  continue;
8573
8740
  }
@@ -8588,14 +8755,23 @@ function createRenderAwareStreamWriter(args) {
8588
8755
  true
8589
8756
  );
8590
8757
  lastKind = "list";
8758
+ lastLine = lines[end - 1] ?? firstLine;
8591
8759
  buffer = lines.slice(end).join("\n");
8592
8760
  continue;
8593
8761
  }
8594
8762
  }
8595
8763
  const kind = classifyStreamLine(firstLine);
8764
+ if (kind === "blank") {
8765
+ if (lastKind !== null && lastKind !== "blank") pendingBlankRow = true;
8766
+ lastKind = "blank";
8767
+ lastLine = "";
8768
+ buffer = lines.slice(1).join("\n");
8769
+ continue;
8770
+ }
8596
8771
  emitBreathIfNeeded(kind);
8597
8772
  emitFormattedAssistantBlock(args.write, firstLine, true);
8598
8773
  lastKind = kind;
8774
+ lastLine = firstLine;
8599
8775
  buffer = lines.slice(1).join("\n");
8600
8776
  }
8601
8777
  };
@@ -9808,6 +9984,7 @@ ${this.text}
9808
9984
  // packages/cli/client/agentRunOutput.ts
9809
9985
  var IDENTITY_LABEL_SEPARATOR = " > ";
9810
9986
  var THINKING_PREVIEW_BUFFER_LIMIT = 512;
9987
+ var TUI_PROGRESS_BUFFER_LIMIT = 1200;
9811
9988
  function appendThinkingPreview(current, chunk, limit = THINKING_PREVIEW_BUFFER_LIMIT) {
9812
9989
  if (limit <= 0) return "";
9813
9990
  const combined = current + chunk;
@@ -9869,6 +10046,14 @@ function formatToolJsonEvent(event) {
9869
10046
  })}
9870
10047
  `;
9871
10048
  }
10049
+ function shouldPromoteTuiNarration(text) {
10050
+ if (text.length >= TUI_PROGRESS_BUFFER_LIMIT) return true;
10051
+ return /(^|\n)\s*(?:#{1,3}\s|```|[-*+]\s|\d+[.)]\s)/.test(text);
10052
+ }
10053
+ function narrationActivityLabel(text) {
10054
+ const oneLine = stripAnsi2(text).replace(/[`*_#>]/g, "").replace(/\s+/g, " ").trim();
10055
+ return truncateThinkingHint(oneLine, 60);
10056
+ }
9872
10057
  function createCliTurnOutput(params) {
9873
10058
  const { options } = params;
9874
10059
  const workingLabel = params.workingLabel ?? `${options.agentName} -> working`;
@@ -9877,14 +10062,36 @@ function createCliTurnOutput(params) {
9877
10062
  tuiTrees: options.output.tuiTrees === true
9878
10063
  });
9879
10064
  const eventMode = resolveAgentEventMode(options);
9880
- const showThinking = options.showThinking !== false;
10065
+ const assistantLabelManaged = options.output.assistantLabelManaged === true;
10066
+ const showThinking = !assistantLabelManaged && options.showThinking !== false;
10067
+ const hidesRoutineTuiToolDetail = (event) => {
10068
+ if (!assistantLabelManaged || event.toolName !== "editFile") return false;
10069
+ if (event.type === "tool-error") return false;
10070
+ if (readActionGate(event.metadata?.actionGate)) return false;
10071
+ if (event.metadata?.timedOut || event.metadata?.failed || event.metadata?.error) return false;
10072
+ if (typeof event.metadata?.exitCode === "number" && event.metadata.exitCode !== 0) return false;
10073
+ return true;
10074
+ };
9881
10075
  let streamedAssistantText = false;
9882
10076
  let everStreamedAnyText = false;
9883
10077
  let printedAssistantLabel = false;
9884
10078
  let thinkState = createThinkParserState();
9885
10079
  let thinkingFirstAt = null;
9886
10080
  let thinkingPreview = "";
10081
+ let tuiThinkingReported = false;
10082
+ const clearTuiThinkingLabel = () => {
10083
+ if (!tuiThinkingReported) return;
10084
+ tuiThinkingReported = false;
10085
+ options.activityReporter?.(null);
10086
+ };
9887
10087
  const markThinkingDelta = (chunk) => {
10088
+ if (assistantLabelManaged) {
10089
+ if (!tuiThinkingReported && !streamedAssistantText) {
10090
+ tuiThinkingReported = true;
10091
+ options.activityReporter?.(t("thinkingActive"));
10092
+ }
10093
+ return;
10094
+ }
9888
10095
  if (!showThinking) return;
9889
10096
  if (streamedAssistantText) return;
9890
10097
  if (thinkingFirstAt === null) {
@@ -9902,6 +10109,7 @@ function createCliTurnOutput(params) {
9902
10109
  options.activityReporter?.(label);
9903
10110
  };
9904
10111
  const endThinkingPhase = () => {
10112
+ clearTuiThinkingLabel();
9905
10113
  if (thinkingFirstAt === null) return;
9906
10114
  const seconds = Math.max(0, Math.round((Date.now() - thinkingFirstAt) / 1e3));
9907
10115
  thinkingFirstAt = null;
@@ -9914,7 +10122,6 @@ function createCliTurnOutput(params) {
9914
10122
  }
9915
10123
  };
9916
10124
  let compactionEvent = null;
9917
- const assistantLabelManaged = options.output.assistantLabelManaged === true;
9918
10125
  const writeToolOutput = (chunk) => {
9919
10126
  if (!chunk) return;
9920
10127
  if (typeof options.output.writeToolBlock === "function") {
@@ -9926,9 +10133,25 @@ function createCliTurnOutput(params) {
9926
10133
  const renderWriter = createRenderAwareStreamWriter({
9927
10134
  write: (chunk) => options.output.write(chunk)
9928
10135
  });
10136
+ let pendingTuiNarration = "";
10137
+ let tuiNarrationPromoted = false;
10138
+ const flushPendingTuiNarration = () => {
10139
+ if (!pendingTuiNarration) return;
10140
+ formatToolEvent.reset?.();
10141
+ renderWriter.push(pendingTuiNarration);
10142
+ pendingTuiNarration = "";
10143
+ tuiNarrationPromoted = true;
10144
+ streamedAssistantText = true;
10145
+ options.activityReporter?.(null);
10146
+ };
10147
+ const dropPendingTuiProgress = () => {
10148
+ pendingTuiNarration = "";
10149
+ tuiNarrationPromoted = false;
10150
+ options.activityReporter?.(null);
10151
+ };
9929
10152
  const writeVisibleAssistantChunk = (chunk) => {
9930
10153
  if (!chunk) return;
9931
- formatToolEvent.reset?.();
10154
+ if (!assistantLabelManaged) formatToolEvent.reset?.();
9932
10155
  const parsed = processThinkChunk(chunk, thinkState);
9933
10156
  thinkState = parsed.state;
9934
10157
  if (!parsed.content && !parsed.reasoning) return;
@@ -9944,8 +10167,23 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9944
10167
  }
9945
10168
  printedAssistantLabel = true;
9946
10169
  }
9947
- streamedAssistantText = true;
9948
10170
  everStreamedAnyText = true;
10171
+ if (assistantLabelManaged) {
10172
+ if (tuiNarrationPromoted) {
10173
+ renderWriter.push(parsed.content);
10174
+ streamedAssistantText = true;
10175
+ return;
10176
+ }
10177
+ pendingTuiNarration += parsed.content;
10178
+ if (shouldPromoteTuiNarration(pendingTuiNarration)) {
10179
+ flushPendingTuiNarration();
10180
+ } else {
10181
+ const label = narrationActivityLabel(pendingTuiNarration);
10182
+ if (label) options.activityReporter?.(label);
10183
+ }
10184
+ return;
10185
+ }
10186
+ streamedAssistantText = true;
9949
10187
  renderWriter.push(parsed.content);
9950
10188
  };
9951
10189
  const handleToolEvent = (event) => {
@@ -9961,13 +10199,19 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9961
10199
  return;
9962
10200
  }
9963
10201
  if (event.type === "tool-call") {
10202
+ if (assistantLabelManaged && pendingTuiNarration) {
10203
+ dropPendingTuiProgress();
10204
+ }
9964
10205
  renderWriter.flush();
9965
- formatToolEvent(event);
10206
+ if (!hidesRoutineTuiToolDetail(event)) {
10207
+ formatToolEvent(event);
10208
+ }
9966
10209
  endThinkingPhase();
9967
10210
  if (streamedAssistantText) {
9968
10211
  options.output.write("\n");
9969
10212
  streamedAssistantText = false;
9970
10213
  }
10214
+ if (assistantLabelManaged) tuiNarrationPromoted = false;
9971
10215
  const activeLabel = formatConservativeActiveToolLabel(event);
9972
10216
  spinner.show(activeLabel);
9973
10217
  options.activityReporter?.(activeLabel);
@@ -9979,6 +10223,9 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9979
10223
  }
9980
10224
  spinner.stop();
9981
10225
  options.activityReporter?.(null);
10226
+ if (hidesRoutineTuiToolDetail(event)) {
10227
+ return;
10228
+ }
9982
10229
  if (isLiveAgentRunObservation(event, parsedRunEvent)) {
9983
10230
  formatToolEvent.consume?.(event);
9984
10231
  return;
@@ -9991,6 +10238,26 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9991
10238
  return {
9992
10239
  spinner,
9993
10240
  eventMode,
10241
+ /**
10242
+ * Terminal cleanup for abort/error paths that never reach `finish()`.
10243
+ *
10244
+ * A user abort discards the transient TUI progress buffer: the user stopped
10245
+ * on purpose and the dock already showed that text as activity. A genuine
10246
+ * failure must not swallow prose that never got the chance to be *proven*
10247
+ * durable (only a following tool call proves "progress"), so it promotes the
10248
+ * pending buffer and flushes what was already promoted — otherwise a short
10249
+ * final answer followed by a transport error disappears from the transcript.
10250
+ */
10251
+ cancel(cleanup) {
10252
+ if (assistantLabelManaged && cleanup?.preservePendingNarration) {
10253
+ flushPendingTuiNarration();
10254
+ if (streamedAssistantText) {
10255
+ renderWriter.flush();
10256
+ options.output.write("\n");
10257
+ }
10258
+ }
10259
+ dropPendingTuiProgress();
10260
+ },
9994
10261
  pushText(chunk) {
9995
10262
  writeVisibleAssistantChunk(chunk);
9996
10263
  },
@@ -9998,10 +10265,6 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9998
10265
  markThinkingDelta(chunk);
9999
10266
  },
10000
10267
  handleToolEvent,
10001
- /** 记录一条 compaction 观测事件(TUI 在 turn 结束时渲染一行 dim 摘要)。
10002
- * 一轮内可能来多条(轮开始 + 每个 round),按显著性保留最高者:
10003
- * 失败 > 新生成摘要 > 投影复用 > 跳过,避免末尾的例行跳过事件
10004
- * 覆盖掉中途真正发生的压缩。 */
10005
10268
  recordCompaction(event) {
10006
10269
  const significance = (e) => e.failed ? 4 : e.summaryGenerated ? 3 : e.compressed ? 2 : 1;
10007
10270
  if (!compactionEvent || significance(event) >= significance(compactionEvent)) {
@@ -10013,12 +10276,28 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
10013
10276
  spinner.show(activeLabel);
10014
10277
  options.activityReporter?.(activeLabel);
10015
10278
  },
10279
+ /**
10280
+ * Pre-delta turn phase label (ctx-overflow-feedback batch 3).
10281
+ *
10282
+ * localLoop 在首个 provider delta 之前依次发出 turn-phase 事件
10283
+ * (validating-context → compacting → waiting-provider);此前 CLI 只有
10284
+ * llm-start 才进入明确 working 状态,压缩期间 spinner 停在通用
10285
+ * working 文案上,用户无法区分「卡在检查上下文 / 压缩 / 等模型」。
10286
+ * 两个显示面(bare CLI 的 spinner 与 TUI 的 dock activityReporter)与
10287
+ * showWorking 走同一条投影,保证两端文案不漂移。
10288
+ */
10289
+ showPhase(phase) {
10290
+ const label = phase === "validating-context" ? t("contextChecking") : phase === "compacting" ? t("contextCompacting") : t("waitingForModel");
10291
+ spinner.show(label);
10292
+ options.activityReporter?.(label);
10293
+ },
10016
10294
  finish(fallbackContent) {
10017
10295
  const flushedThink = flushThinkParser(thinkState);
10018
10296
  thinkState = flushedThink.state;
10019
10297
  if (flushedThink.content) {
10020
10298
  writeVisibleAssistantChunk(flushedThink.content);
10021
10299
  }
10300
+ if (assistantLabelManaged) flushPendingTuiNarration();
10022
10301
  endThinkingPhase();
10023
10302
  spinner.stop();
10024
10303
  options.activityReporter?.(null);
@@ -10123,6 +10402,7 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10123
10402
  let content = "";
10124
10403
  let dialogId;
10125
10404
  let usage;
10405
+ let sawDone = false;
10126
10406
  const handlePayload = (payload) => {
10127
10407
  if (typeof payload?.dialogId === "string" && payload.dialogId.trim()) {
10128
10408
  dialogId = payload.dialogId;
@@ -10135,6 +10415,7 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10135
10415
  }
10136
10416
  if (payload?.type === "done") {
10137
10417
  usage = payload.usage;
10418
+ sawDone = true;
10138
10419
  return;
10139
10420
  }
10140
10421
  if (payload?.type === "dialog" || payload?.type === "status") {
@@ -10188,6 +10469,9 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10188
10469
  }
10189
10470
  } catch (error) {
10190
10471
  turnOutput.spinner.stop();
10472
+ turnOutput.cancel({
10473
+ preservePendingNarration: !options.abortSignal?.aborted
10474
+ });
10191
10475
  if (options.abortSignal?.aborted) {
10192
10476
  return {
10193
10477
  exitCode: 0,
@@ -10217,6 +10501,15 @@ ${describeClientVersionTooOldFailure(message, error)}`);
10217
10501
  `);
10218
10502
  return { exitCode: 1 };
10219
10503
  }
10504
+ if (options.abortSignal?.aborted && !sawDone) {
10505
+ turnOutput.spinner.stop();
10506
+ turnOutput.cancel();
10507
+ return {
10508
+ exitCode: 0,
10509
+ ...dialogId ? { dialogId } : {},
10510
+ streamInterrupted: true
10511
+ };
10512
+ }
10220
10513
  turnOutput.finish(content);
10221
10514
  const usageText = formatUsage(usage, dialogId);
10222
10515
  if (usageText && shouldShowUsage(options.env))
@@ -10433,7 +10726,7 @@ function findCollapsedPasteSpanAt(buffer, pos, opts = {}) {
10433
10726
  // packages/cli/client/agentRun.ts
10434
10727
  import { ulid as ulid2 } from "ulid";
10435
10728
  async function loadRunLocalAgentTurn() {
10436
- const { runLocalAgentTurn } = await import("./agentRuntimeLocal-IW3IM5P6.js");
10729
+ const { runLocalAgentTurn } = await import("./agentRuntimeLocal-AY6YNUAL.js");
10437
10730
  return runLocalAgentTurn;
10438
10731
  }
10439
10732
  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();
@@ -10760,6 +11053,22 @@ var SERVER_FALLBACK_HINT = "or use --server to run on the server explicitly.";
10760
11053
  function buildAuthFailure(ctx) {
10761
11054
  const platformNoToken = ctx.where === "server chat proxy" && isAuthNoTokenBody(ctx.message);
10762
11055
  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`;
11056
+ const { url: validationUrl, text: validationText } = extractGoogleValidationLink(ctx.message);
11057
+ const validationLabel = validationText || "Verify your account";
11058
+ if (validationUrl) {
11059
+ const linkLine = `
11060
+ ${formatCliHyperlink(validationUrl, validationLabel)}`;
11061
+ const rawLine = resolveCliHyperlinkEnabled() ? `
11062
+ \u70B9\u4E0D\u4E86\u5C31\u590D\u5236\u8FD9\u884C: ${validationUrl}` : "";
11063
+ const verifyHint = `
11064
+ \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`;
11065
+ const retryLine = `
11066
+ \u9A8C\u8BC1\u5B8C\u6210\u540E\u76F4\u63A5\u91CD\u8BD5\u521A\u624D\u7684\u547D\u4EE4\u5373\u53EF\uFF0Ctoken \u4E0D\u7528\u91CD\u65B0\u767B\u5F55\u3002`;
11067
+ return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}: Google requires a one-time account verification \u2014 your credential is fine).
11068
+ Open this link in a browser signed into ${ctx.credentialAccountId ? `\`${ctx.credentialAccountId}\`` : "the Google account behind this credential"}:${linkLine}${rawLine}${verifyHint}${retryLine}
11069
+ Detail: ${ctx.message} ${NO_FALLBACK} Use --server to run on the server explicitly.
11070
+ `;
11071
+ }
10763
11072
  return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}, auth rejected). Detail: ${ctx.message} ${NO_FALLBACK} ${fix}, ${SERVER_FALLBACK_HINT}.
10764
11073
  `;
10765
11074
  }
@@ -10795,6 +11104,17 @@ function buildUpstreamFailure(ctx) {
10795
11104
  return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}). Detail: ${ctx.message} ${NO_FALLBACK} ${fix}, ${SERVER_FALLBACK_HINT}.
10796
11105
  `;
10797
11106
  }
11107
+ function formatLocalTurnFailureLine(error) {
11108
+ const message = toErrorMessage(error);
11109
+ if (error?.code === "LLM_REQUEST_TIMEOUT") {
11110
+ const msMatch = /after (\d+)ms/.exec(message);
11111
+ const deadline = msMatch && Number.isFinite(Number(msMatch[1])) ? formatElapsed(Math.round(Number(msMatch[1]) / 1e3)) : "the configured window";
11112
+ return `[nolo] ${t("llmRequestTimedOut", deadline)}
11113
+ `;
11114
+ }
11115
+ return `[nolo] Local agent run failed: ${message}
11116
+ `;
11117
+ }
10798
11118
  var FAILURE_BUILDERS = {
10799
11119
  auth: buildAuthFailure,
10800
11120
  "rejected-payload": buildRejectedPayloadFailure,
@@ -10803,6 +11123,7 @@ var FAILURE_BUILDERS = {
10803
11123
  upstream: buildUpstreamFailure
10804
11124
  };
10805
11125
  function describeLocalRunFailure(message, rawError) {
11126
+ const credentialAccountId = rawError && typeof rawError === "object" && typeof rawError.credentialAccountId === "string" ? rawError.credentialAccountId.trim() || void 0 : void 0;
10806
11127
  if (rawError && typeof rawError === "object" && "code" in rawError && rawError.code === "PLATFORM_STREAM_INTERRUPTED") {
10807
11128
  return "[nolo] The platform LLM stream was interrupted before the turn completed. Your conversation was preserved. Send another message to continue.\n";
10808
11129
  }
@@ -10880,7 +11201,8 @@ function describeLocalRunFailure(message, rawError) {
10880
11201
  status: cls.status,
10881
11202
  ...cls.statusInferred ? { statusInferred: true } : {},
10882
11203
  ...cls.quotaExhausted ? { quotaExhausted: true } : {},
10883
- ...cooldownUntil ? { cooldownUntil } : {}
11204
+ ...cooldownUntil ? { cooldownUntil } : {},
11205
+ ...credentialAccountId ? { credentialAccountId } : {}
10884
11206
  };
10885
11207
  return FAILURE_BUILDERS[cls.kind](ctx);
10886
11208
  }
@@ -11197,6 +11519,18 @@ async function runLocalAgentTurnForCli(options, settings) {
11197
11519
  if (event.kind === "llm-start") {
11198
11520
  turnOutput.showWorking();
11199
11521
  }
11522
+ if (event.kind === "turn-phase") {
11523
+ turnOutput.showPhase(event.phase);
11524
+ }
11525
+ if (event.kind === "compaction-start") {
11526
+ turnOutput.showPhase("compacting");
11527
+ }
11528
+ if (event.kind === "compaction-end" || // 压缩失败(timeout/provider-error)时 localLoop 按失败原子性语义
11529
+ // 带着裁剪后的历史继续本轮,切回等待模型文案;aborted 时 turn 随即
11530
+ // 结束,不再切文案(终态由 abort 路径收尾)。
11531
+ event.kind === "compaction-failed" && event.reason !== "aborted") {
11532
+ turnOutput.showPhase("waiting-provider");
11533
+ }
11200
11534
  if (event.kind === "image-downgraded") {
11201
11535
  options.output.write(
11202
11536
  "[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"
@@ -11242,6 +11576,9 @@ async function runLocalAgentTurnForCli(options, settings) {
11242
11576
  };
11243
11577
  } catch (error) {
11244
11578
  turnOutput.spinner.stop();
11579
+ turnOutput.cancel({
11580
+ preservePendingNarration: error?.code !== LOCAL_TURN_ABORTED_CODE && !options.abortSignal?.aborted
11581
+ });
11245
11582
  const savedDialogId = error?.dialogId;
11246
11583
  const abortedUsageRecords = error?.usageRecords;
11247
11584
  const abortedTurnCredits = sumPlatformCredits(abortedUsageRecords);
@@ -11265,10 +11602,12 @@ async function runLocalAgentTurnForCli(options, settings) {
11265
11602
  error.cooldownUntil = cooldownUntil;
11266
11603
  }
11267
11604
  if (settings.reportFailure) {
11268
- options.output.write(
11269
- `[nolo] Local agent run failed: ${toErrorMessage(error)}
11270
- `
11271
- );
11605
+ const failureLine = formatLocalTurnFailureLine(error);
11606
+ if (typeof options.output.writeErr === "function") {
11607
+ options.output.writeErr(failureLine);
11608
+ } else {
11609
+ options.output.write(failureLine);
11610
+ }
11272
11611
  if (cooldownUntil) {
11273
11612
  options.output.write(
11274
11613
  `[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
@@ -11406,7 +11745,7 @@ async function runAgentTurn(options) {
11406
11745
  return { exitCode: 1 };
11407
11746
  }
11408
11747
  const localAvailability = await checkLocalAvailabilityBeforeHttpDispatch(options);
11409
- if (localAvailability?.exitCode) {
11748
+ if (localAvailability && "exitCode" in localAvailability) {
11410
11749
  return { exitCode: localAvailability.exitCode };
11411
11750
  }
11412
11751
  const httpResult = await runHttpAgentTurn(options, authToken);
@@ -12148,72 +12487,6 @@ var rankMemoryCandidates = (items, query, context) => {
12148
12487
  });
12149
12488
  };
12150
12489
 
12151
- // packages/ai/memory/vnext/store.ts
12152
- var enc = (value) => encodeURIComponent(value).replace(/-/g, "%2D");
12153
- var rangeOf = (prefix) => ({ gte: prefix, lte: `${prefix}\uFFFF` });
12154
- var entityKey = (ownerId, id) => `mem2-e-${enc(ownerId)}-${enc(id)}`;
12155
- var entityOwnerPrefix = (ownerId) => `mem2-e-${enc(ownerId)}-`;
12156
- var stateKey = (ownerId, id) => `mem2-s-${enc(ownerId)}-${enc(id)}`;
12157
- var stateEntityIndexKey = (ownerId, entityId, stateId) => `mem2-si-${enc(ownerId)}-${enc(entityId)}-${enc(stateId)}`;
12158
- var stateEntityIndexPrefix = (ownerId, entityId) => `mem2-si-${enc(ownerId)}-${enc(entityId)}-`;
12159
- var evidenceKey = (ownerId, id) => `mem2-v-${enc(ownerId)}-${enc(id)}`;
12160
- var relationKey = (ownerId, id) => `mem2-r-${enc(ownerId)}-${enc(id)}`;
12161
- var relationFromIndexKey = (ownerId, from, relationId) => `mem2-rf-${enc(ownerId)}-${enc(from)}-${enc(relationId)}`;
12162
- var relationToIndexKey = (ownerId, to, relationId) => `mem2-rt-${enc(ownerId)}-${enc(to)}-${enc(relationId)}`;
12163
- var readIndexed = async (db, prefix) => {
12164
- const refs = [];
12165
- for await (const [, value] of db.iterator({ ...rangeOf(prefix), reverse: false })) {
12166
- if (typeof value?.key === "string") refs.push(value.key);
12167
- }
12168
- const rows = await Promise.all(refs.map((key) => db.get(key).catch(() => null)));
12169
- return rows.filter((row) => !!row);
12170
- };
12171
- var getMemoryEntityVNext = async (db, ownerId, entityId) => db.get(entityKey(ownerId, entityId)).catch(() => null);
12172
- var listMemoryEntitiesVNext = async (db, ownerId) => {
12173
- const rows = [];
12174
- for await (const [, value] of db.iterator({
12175
- ...rangeOf(entityOwnerPrefix(ownerId)),
12176
- reverse: false
12177
- })) {
12178
- if (value) rows.push(value);
12179
- }
12180
- return rows;
12181
- };
12182
- var getMemoryStateVNext = async (db, ownerId, stateId) => db.get(stateKey(ownerId, stateId)).catch(() => null);
12183
- var listMemoryStatesForEntityVNext = (db, ownerId, entityId) => readIndexed(db, stateEntityIndexPrefix(ownerId, entityId));
12184
- var putMemoryEvidenceVNext = async (db, evidence) => {
12185
- await db.put(evidenceKey(evidence.ownerId, evidence.id), evidence);
12186
- };
12187
- var getMemoryEvidenceVNext = async (db, ownerId, evidenceId) => db.get(evidenceKey(ownerId, evidenceId)).catch(() => null);
12188
- var getMemoryEvidenceVNextStrict = async (db, ownerId, evidenceId) => {
12189
- try {
12190
- return await db.get(evidenceKey(ownerId, evidenceId));
12191
- } catch (error) {
12192
- if (isLevelNotFoundError(error)) return null;
12193
- throw error;
12194
- }
12195
- };
12196
- var _appendEntityBatch = (batch, entity) => {
12197
- batch.put(entityKey(entity.ownerId, entity.id), entity);
12198
- };
12199
- var _appendEvidenceBatch = (batch, evidence) => {
12200
- batch.put(evidenceKey(evidence.ownerId, evidence.id), evidence);
12201
- };
12202
- var _appendStateBatch = (batch, state2) => {
12203
- const key = stateKey(state2.ownerId, state2.id);
12204
- batch.put(key, state2);
12205
- batch.put(stateEntityIndexKey(state2.ownerId, state2.entityId, state2.id), { key });
12206
- };
12207
- var _appendRetiredStateBatch = (batch, state2) => {
12208
- batch.put(stateKey(state2.ownerId, state2.id), state2);
12209
- };
12210
- var _appendRelationBatch = (batch, relation) => {
12211
- const key = relationKey(relation.ownerId, relation.id);
12212
- batch.put(key, relation);
12213
- batch.put(relationFromIndexKey(relation.ownerId, relation.from, relation.id), { key });
12214
- batch.put(relationToIndexKey(relation.ownerId, relation.to, relation.id), { key });
12215
- };
12216
-
12217
12490
  // packages/ai/memory/vnext/recall.ts
12218
12491
  var MAX_RECALL_REFS = 6;
12219
12492
  var stripFence = (raw) => {
@@ -12243,14 +12516,6 @@ var parseSelection = (raw) => {
12243
12516
  reason: obj.reason
12244
12517
  };
12245
12518
  };
12246
- var buildCatalog = async (db, ownerId) => {
12247
- const entities = await listMemoryEntitiesVNext(db, ownerId);
12248
- const states = [];
12249
- for (const entity of entities) {
12250
- states.push(...await listMemoryStatesForEntityVNext(db, ownerId, entity.id));
12251
- }
12252
- return { entities, states };
12253
- };
12254
12519
  var catalogText = (entities, states) => JSON.stringify(
12255
12520
  {
12256
12521
  entities: entities.map((entity) => ({
@@ -12276,7 +12541,7 @@ var catalogText = (entities, states) => JSON.stringify(
12276
12541
  );
12277
12542
  var createMemoryVNextRecall = (input) => async (query) => {
12278
12543
  const startedAt = performance.now();
12279
- const { entities, states } = await buildCatalog(input.db, input.ownerId);
12544
+ const { entities, states } = await loadMemoryVNextCatalog(input.db, input.ownerId);
12280
12545
  if (entities.length === 0 && states.length === 0) {
12281
12546
  return {
12282
12547
  query,
@@ -13147,14 +13412,74 @@ var shortError2 = (error) => {
13147
13412
  return message.length > ERROR_MESSAGE_MAX2 ? `${message.slice(0, ERROR_MESSAGE_MAX2)}\u2026` : message;
13148
13413
  };
13149
13414
  var loadExistingContext = async (db, ownerId) => {
13150
- const entities = await listMemoryEntitiesVNext(db, ownerId);
13151
- const states = (await Promise.all(
13152
- entities.map((entity) => listMemoryStatesForEntityVNext(db, ownerId, entity.id))
13153
- )).flat();
13154
- return {
13155
- entityIds: entities.map((entity) => entity.id),
13156
- states
13415
+ const { entities, states } = await loadMemoryVNextCatalog(db, ownerId);
13416
+ return { entityIds: entities.map((entity) => entity.id), states };
13417
+ };
13418
+ var currentStatesCitingEvidence = (states, evidenceId) => states.filter((state2) => !state2.retiredAt && (state2.evidenceIds ?? []).includes(evidenceId));
13419
+ var isEvidenceCoveredByCurrentStates = (states, evidenceId) => currentStatesCitingEvidence(states, evidenceId).length > 0;
13420
+ var memoryVNextContextFingerprint = (existing) => {
13421
+ const states = existing.states ?? [];
13422
+ const entityIds = existing.entityIds ?? [];
13423
+ const canonical = [
13424
+ ...entityIds.map((id) => `e\0${id}`),
13425
+ ...states.map((state2) => `s\0${state2.id}\0${state2.updatedAt}\0${state2.retiredAt ?? ""}`)
13426
+ ].sort().join("");
13427
+ let hash = 2166136261;
13428
+ for (let i = 0; i < canonical.length; i++) {
13429
+ hash ^= canonical.charCodeAt(i);
13430
+ hash = Math.imul(hash, 16777619);
13431
+ }
13432
+ return `${entityIds.length}.${states.length}:${(hash >>> 0).toString(16)}`;
13433
+ };
13434
+ var MAX_NOOP_SUPPRESSIONS = 512;
13435
+ var noOpSuppressions = /* @__PURE__ */ new Map();
13436
+ var suppressionKey = (ownerId, evidenceId) => `${ownerId}\0${evidenceId}`;
13437
+ var recordNoOpSuppression = (ownerId, evidenceId, fingerprint) => {
13438
+ const key = suppressionKey(ownerId, evidenceId);
13439
+ noOpSuppressions.delete(key);
13440
+ noOpSuppressions.set(key, fingerprint);
13441
+ while (noOpSuppressions.size > MAX_NOOP_SUPPRESSIONS) {
13442
+ noOpSuppressions.delete(noOpSuppressions.keys().next().value);
13443
+ }
13444
+ };
13445
+ var noOpHistory = (ownerId, evidenceId, fingerprint) => {
13446
+ const recorded = noOpSuppressions.get(suppressionKey(ownerId, evidenceId));
13447
+ if (recorded === void 0) return "fresh";
13448
+ return recorded === fingerprint ? "suppressed" : "stale";
13449
+ };
13450
+ var pickFirstUncoveredLazyPromotionItem = async (db, selected) => {
13451
+ const contextByOwner = /* @__PURE__ */ new Map();
13452
+ const contextFor = (ownerId) => {
13453
+ let pending = contextByOwner.get(ownerId);
13454
+ if (!pending) {
13455
+ pending = loadExistingContext(db, ownerId).then((existing) => ({
13456
+ states: existing.states ?? [],
13457
+ fingerprint: memoryVNextContextFingerprint(existing)
13458
+ }));
13459
+ contextByOwner.set(ownerId, pending);
13460
+ }
13461
+ return pending;
13157
13462
  };
13463
+ let skippedCoveredCount = 0;
13464
+ let skippedNoOpCount = 0;
13465
+ let firstStale = null;
13466
+ for (const [selectedIndex, item] of selected.entries()) {
13467
+ const evidence = buildLegacyMemoryEvidence(item);
13468
+ const context = await contextFor(evidence.ownerId);
13469
+ if (isEvidenceCoveredByCurrentStates(context.states, evidence.id)) {
13470
+ skippedCoveredCount++;
13471
+ continue;
13472
+ }
13473
+ const history = noOpHistory(evidence.ownerId, evidence.id, context.fingerprint);
13474
+ if (history === "fresh") {
13475
+ return { item, selectedIndex, skippedCoveredCount, skippedNoOpCount };
13476
+ }
13477
+ if (history === "stale" && !firstStale) {
13478
+ firstStale = { item, selectedIndex, skippedCoveredCount, skippedNoOpCount };
13479
+ }
13480
+ skippedNoOpCount++;
13481
+ }
13482
+ return firstStale;
13158
13483
  };
13159
13484
  var withoutImportedEvidence = (mutation, importedEvidenceId) => ({
13160
13485
  ...mutation,
@@ -13170,6 +13495,11 @@ var runMemoryVNextLazyPromotion = async (input) => {
13170
13495
  }));
13171
13496
  const finish = (partial) => {
13172
13497
  const observation = {
13498
+ legacyItemId: input.item.id,
13499
+ evidenceId: deterministicEvidence.id,
13500
+ ...input.selectedIndex === void 0 ? {} : { selectedIndex: input.selectedIndex },
13501
+ ...input.skippedCoveredCount === void 0 ? {} : { skippedCoveredCount: input.skippedCoveredCount },
13502
+ ...input.skippedNoOpCount === void 0 ? {} : { skippedNoOpCount: input.skippedNoOpCount },
13173
13503
  ...partial,
13174
13504
  latencyMs: Math.round((clock() - startedAt) * 10) / 10
13175
13505
  };
@@ -13192,8 +13522,9 @@ var runMemoryVNextLazyPromotion = async (input) => {
13192
13522
  }
13193
13523
  const evidence = evidenceResult.evidence;
13194
13524
  const existing = await loadExistingContext(input.db, evidence.ownerId);
13195
- const alreadyCovered = (existing.states ?? []).some(
13196
- (state2) => !state2.retiredAt && state2.evidenceIds.includes(evidence.id)
13525
+ const alreadyCovered = isEvidenceCoveredByCurrentStates(
13526
+ existing.states ?? [],
13527
+ evidence.id
13197
13528
  );
13198
13529
  if (alreadyCovered) {
13199
13530
  return finish({ status: "already_covered" });
@@ -13208,6 +13539,11 @@ var runMemoryVNextLazyPromotion = async (input) => {
13208
13539
  });
13209
13540
  const semanticMutation = withoutImportedEvidence(interpreted.mutation, evidence.id);
13210
13541
  if (!hasWrites(semanticMutation)) {
13542
+ recordNoOpSuppression(
13543
+ evidence.ownerId,
13544
+ evidence.id,
13545
+ memoryVNextContextFingerprint(existing)
13546
+ );
13211
13547
  return finish({ status: "no_op", action: semanticMutation.action });
13212
13548
  }
13213
13549
  await applyMemoryInterpreterMutation(input.db, evidence.ownerId, semanticMutation);
@@ -13220,6 +13556,179 @@ var runMemoryVNextLazyPromotion = async (input) => {
13220
13556
  };
13221
13557
  var isMemoryVNextLazyPromotionEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_LAZY_PROMOTION === "1" || env.NOLO_MEMORY_VNEXT_LAZY_PROMOTION === "true";
13222
13558
 
13559
+ // packages/ai/memory/vnext/pureReadGate.ts
13560
+ var isMemoryVNextPureReadEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_PURE_READ === "1" || env.NOLO_MEMORY_VNEXT_PURE_READ === "true";
13561
+
13562
+ // packages/ai/memory/vnext/localRecall.ts
13563
+ var MIN_SHARED_TOKENS = 2;
13564
+ var MAX_LOCAL_RECALL_STATES = 8;
13565
+ var SAFE_TECHNICAL_SYNONYMS = {
13566
+ pr: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5", "diff"],
13567
+ diff: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5"],
13568
+ review: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5"],
13569
+ deploy: ["\u90E8\u7F72", "\u53D1\u7248"],
13570
+ release: ["\u53D1\u7248", "\u53D1\u5E03"],
13571
+ desktop: ["\u684C\u9762", "\u684C\u9762\u7AEF"]
13572
+ };
13573
+ var distinctTokens = (text) => new Set(tokenize2(text).filter((token) => token.length >= 2));
13574
+ var recallMemoryVNextLocal = (input) => {
13575
+ const rawTokens = distinctTokens(input.query);
13576
+ if (rawTokens.size === 0) return [];
13577
+ const queryTokens = new Set(rawTokens);
13578
+ for (const token of rawTokens) {
13579
+ const syns = SAFE_TECHNICAL_SYNONYMS[token.toLowerCase()];
13580
+ if (syns) {
13581
+ for (const syn of syns) {
13582
+ for (const t2 of distinctTokens(syn)) queryTokens.add(t2);
13583
+ }
13584
+ }
13585
+ }
13586
+ const entityById = new Map(input.entities.map((entity) => [entity.id, entity]));
13587
+ const hits = [];
13588
+ for (const state2 of input.states) {
13589
+ if (state2.retiredAt || !state2.text.trim()) continue;
13590
+ const entity = entityById.get(state2.entityId);
13591
+ const haystack = distinctTokens(
13592
+ [state2.facet, state2.text, entity?.name ?? "", ...entity?.aliases ?? []].join(" ")
13593
+ );
13594
+ let sharedTokens = 0;
13595
+ for (const token of queryTokens) if (haystack.has(token)) sharedTokens++;
13596
+ if (sharedTokens >= MIN_SHARED_TOKENS) hits.push({ state: state2, sharedTokens });
13597
+ }
13598
+ return hits.sort((a, b) => b.sharedTokens - a.sharedTokens || a.state.id.localeCompare(b.state.id)).slice(0, input.limit ?? MAX_LOCAL_RECALL_STATES);
13599
+ };
13600
+
13601
+ // packages/ai/memory/vnext/pureVNextRuntime.ts
13602
+ var buildSynthesizedStateItem = (state2, entity, ownerType, ownerId) => ({
13603
+ id: `vnext-state-${state2.id}`,
13604
+ ownerType,
13605
+ ownerId,
13606
+ visibility: "private",
13607
+ subjectType: "user",
13608
+ subjectId: ownerId,
13609
+ kind: "semantic",
13610
+ content: state2.text.trim(),
13611
+ createdAt: state2.createdAt,
13612
+ lastActivatedAt: state2.createdAt,
13613
+ activationCount: 1,
13614
+ importance: 0.9,
13615
+ confidence: 0.9,
13616
+ resident: state2.facet === "preference" || state2.facet === "style"
13617
+ });
13618
+ async function resolvePureVNextRuntime(input) {
13619
+ const { db, owners, userInput } = input;
13620
+ if (owners.length === 0 || !userInput.trim()) {
13621
+ return { selectedItems: [], promptBlock: null, recalledStateCount: 0 };
13622
+ }
13623
+ const ownerIds = owners.map((o) => `${o.ownerType}:${encodeURIComponent(o.ownerId)}`);
13624
+ const catalogs = await Promise.all(
13625
+ ownerIds.map((ownerId) => loadMemoryVNextCatalog(db, ownerId))
13626
+ );
13627
+ const selectedItems = [];
13628
+ const seenStateKeys = /* @__PURE__ */ new Set();
13629
+ for (let i = 0; i < owners.length; i++) {
13630
+ const owner = owners[i];
13631
+ const catalog = catalogs[i];
13632
+ const currentStates = catalog.states.filter((s) => !s.retiredAt && s.text.trim());
13633
+ const hits = recallMemoryVNextLocal({
13634
+ query: userInput,
13635
+ entities: catalog.entities,
13636
+ states: currentStates
13637
+ });
13638
+ const entityById = new Map(catalog.entities.map((e) => [e.id, e]));
13639
+ for (const hit of hits) {
13640
+ const stateKey = `${hit.state.ownerId}\0${hit.state.id}`;
13641
+ if (seenStateKeys.has(stateKey)) continue;
13642
+ seenStateKeys.add(stateKey);
13643
+ selectedItems.push(
13644
+ buildSynthesizedStateItem(hit.state, entityById.get(hit.state.entityId), owner.ownerType, owner.ownerId)
13645
+ );
13646
+ }
13647
+ }
13648
+ const promptBlock = selectedItems.length === 0 ? null : buildMemoryOverlay(selectedItems, {
13649
+ maxTokens: input.maxTokens ?? DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET
13650
+ });
13651
+ return {
13652
+ selectedItems,
13653
+ promptBlock,
13654
+ recalledStateCount: selectedItems.length
13655
+ };
13656
+ }
13657
+
13658
+ // packages/ai/memory/vnext/primaryRead.ts
13659
+ var MEMORY_VNEXT_PRIMARY_READ_TIMEOUT_MS = 300;
13660
+ var isMemoryVNextPrimaryReadEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_PRIMARY_READ === "1" || env.NOLO_MEMORY_VNEXT_PRIMARY_READ === "true";
13661
+ var buildSynthesizedStateItem2 = (state2, entity, ownerType, ownerId) => ({
13662
+ id: `vnext-state-${state2.id}`,
13663
+ ownerType,
13664
+ ownerId,
13665
+ visibility: "private",
13666
+ subjectType: "user",
13667
+ subjectId: ownerId,
13668
+ kind: "semantic",
13669
+ content: state2.text.trim(),
13670
+ createdAt: state2.createdAt,
13671
+ importance: 0.9,
13672
+ confidence: 0.9,
13673
+ // Flag resident preferences so they flow into overlay's resident section.
13674
+ resident: state2.facet === "preference" || state2.facet === "style",
13675
+ lastActivatedAt: state2.createdAt,
13676
+ activationCount: 1
13677
+ });
13678
+ var resolveMemoryVNextM4Selection = async (input) => {
13679
+ const { db, owners, query, selected } = input;
13680
+ const ownerIds = owners.map((o) => `${o.ownerType}:${encodeURIComponent(o.ownerId)}`);
13681
+ const catalogs = new Map(
13682
+ await Promise.all(
13683
+ ownerIds.map(async (ownerId) => [
13684
+ ownerId,
13685
+ await loadMemoryVNextCatalog(db, ownerId)
13686
+ ])
13687
+ )
13688
+ );
13689
+ const recalledStates = [];
13690
+ const recalledStateIds = /* @__PURE__ */ new Set();
13691
+ for (const owner of owners) {
13692
+ const principalId = `${owner.ownerType}:${encodeURIComponent(owner.ownerId)}`;
13693
+ const catalog = catalogs.get(principalId);
13694
+ if (!catalog) continue;
13695
+ const currentStates = catalog.states.filter((s) => !s.retiredAt && s.text.trim());
13696
+ const hits = recallMemoryVNextLocal({
13697
+ query,
13698
+ entities: catalog.entities,
13699
+ states: currentStates
13700
+ });
13701
+ const entityById = new Map(catalog.entities.map((e) => [e.id, e]));
13702
+ for (const hit of hits) {
13703
+ if (recalledStateIds.has(hit.state.id)) continue;
13704
+ recalledStateIds.add(hit.state.id);
13705
+ recalledStates.push(
13706
+ buildSynthesizedStateItem2(hit.state, entityById.get(hit.state.entityId), owner.ownerType, owner.ownerId)
13707
+ );
13708
+ }
13709
+ }
13710
+ const uncoveredLegacy = [];
13711
+ let coveredSuppressedCount = 0;
13712
+ for (const item of selected) {
13713
+ const evidence = buildLegacyMemoryEvidence(item);
13714
+ const catalog = catalogs.get(evidence.ownerId);
13715
+ const states = catalog?.states ?? [];
13716
+ const covering = currentStatesCitingEvidence(states, evidence.id);
13717
+ if (covering.length > 0) {
13718
+ coveredSuppressedCount++;
13719
+ } else {
13720
+ uncoveredLegacy.push(item);
13721
+ }
13722
+ }
13723
+ const renderItems = [...recalledStates, ...uncoveredLegacy];
13724
+ return {
13725
+ renderItems,
13726
+ recalledStateCount: recalledStates.length,
13727
+ uncoveredLegacyCount: uncoveredLegacy.length,
13728
+ coveredSuppressedCount
13729
+ };
13730
+ };
13731
+
13223
13732
  // packages/ai/memory/runtime.ts
13224
13733
  var COLD_STORAGE_CONFIDENCE = 0.3;
13225
13734
  var MEMORY_OVERLAY_TOKEN_BUDGET = DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET;
@@ -13342,6 +13851,18 @@ var resolveMemoryRuntime = async (input) => {
13342
13851
  if (owners.length === 0) {
13343
13852
  return { selectedItems: [], promptBlock: null };
13344
13853
  }
13854
+ if (isMemoryVNextPureReadEnabled()) {
13855
+ const pure = await resolvePureVNextRuntime({
13856
+ db: input.db,
13857
+ owners,
13858
+ userInput: input.userInput,
13859
+ maxTokens: MEMORY_OVERLAY_TOKEN_BUDGET
13860
+ });
13861
+ return {
13862
+ selectedItems: pure.selectedItems,
13863
+ promptBlock: pure.promptBlock
13864
+ };
13865
+ }
13345
13866
  const policy = resolveAgentMemoryPolicy({ agentKey: input.agentKey });
13346
13867
  const legacyStartedAt = performance.now();
13347
13868
  const candidates = await loadMemoryCandidatesFromDb(input.db, {
@@ -13371,10 +13892,62 @@ var resolveMemoryRuntime = async (input) => {
13371
13892
  );
13372
13893
  const selected = [...residentItems, ...ranked];
13373
13894
  const legacyLatencyMs = Math.round((performance.now() - legacyStartedAt) * 10) / 10;
13374
- const promptBlock = selected.length === 0 ? null : buildMemoryOverlay(selected, { maxTokens: MEMORY_OVERLAY_TOKEN_BUDGET });
13375
- const shadowEnabled = input.vNextShadowProvider != null && isMemoryVNextShadowReadEnabled();
13895
+ const renderOverlay = (items) => items.length === 0 ? null : buildMemoryOverlay(items, { maxTokens: MEMORY_OVERLAY_TOKEN_BUDGET });
13896
+ let promptBlock = renderOverlay(selected);
13897
+ const primaryRead = isMemoryVNextPrimaryReadEnabled();
13898
+ let allCoveredByVNext = false;
13899
+ if (primaryRead) {
13900
+ const emitPrimary = (observation) => {
13901
+ try {
13902
+ (input.primaryReadEmit ?? ((o) => console.info("[memory] vnext primary read", { event: "memory_vnext_primary_read", ...o })))(observation);
13903
+ } catch {
13904
+ }
13905
+ };
13906
+ const base = { legacyHitCount: selected.length, legacyLatencyMs };
13907
+ const vnextStartedAt = performance.now();
13908
+ const vnextLatency = () => Math.round((performance.now() - vnextStartedAt) * 10) / 10;
13909
+ if (selected.length === 0) {
13910
+ emitPrimary({ ...base, source: "none" });
13911
+ } else {
13912
+ try {
13913
+ let timer;
13914
+ const m4 = await Promise.race([
13915
+ resolveMemoryVNextM4Selection({ db: input.db, owners, query: input.userInput, selected }),
13916
+ new Promise((_, reject) => {
13917
+ timer = setTimeout(
13918
+ () => reject(Object.assign(new Error("timeout"), { name: "TimeoutError" })),
13919
+ MEMORY_VNEXT_PRIMARY_READ_TIMEOUT_MS
13920
+ );
13921
+ })
13922
+ ]).finally(() => clearTimeout(timer));
13923
+ promptBlock = renderOverlay(m4.renderItems);
13924
+ allCoveredByVNext = m4.uncoveredLegacyCount === 0 && m4.recalledStateCount > 0;
13925
+ const source = m4.recalledStateCount > 0 ? m4.uncoveredLegacyCount === 0 ? "vnext" : "hybrid" : m4.uncoveredLegacyCount > 0 ? "legacy_fallback" : "none";
13926
+ emitPrimary({
13927
+ ...base,
13928
+ source,
13929
+ uncoveredLegacyCount: m4.uncoveredLegacyCount,
13930
+ coveredSuppressedCount: m4.coveredSuppressedCount,
13931
+ recalledStateCount: m4.recalledStateCount,
13932
+ vnextLatencyMs: vnextLatency(),
13933
+ contextChars: promptBlock?.length ?? 0,
13934
+ ...source === "legacy_fallback" ? { fallbackReason: "no_vnext_context" } : {}
13935
+ });
13936
+ } catch (error) {
13937
+ emitPrimary({
13938
+ ...base,
13939
+ source: "legacy_fallback",
13940
+ vnextLatencyMs: vnextLatency(),
13941
+ contextChars: promptBlock?.length ?? 0,
13942
+ fallbackReason: "vnext_error",
13943
+ error: error instanceof Error ? error.name : "UnknownError"
13944
+ });
13945
+ }
13946
+ }
13947
+ }
13948
+ const shadowEnabled = !primaryRead && input.vNextShadowProvider != null && isMemoryVNextShadowReadEnabled();
13376
13949
  if (shadowEnabled) {
13377
- await runMemoryVNextShadowRead({
13950
+ void runMemoryVNextShadowRead({
13378
13951
  ctx: {
13379
13952
  db: input.db,
13380
13953
  owners,
@@ -13384,17 +13957,28 @@ var resolveMemoryRuntime = async (input) => {
13384
13957
  legacyItems: selected,
13385
13958
  legacyLatencyMs,
13386
13959
  legacyContextChars: promptBlock?.length ?? 0
13960
+ }).catch(() => {
13387
13961
  });
13388
13962
  }
13389
- const promotionCandidate = selected[0];
13390
13963
  const lazyPromotionEnabled = input.vNextShadowProvider != null && isMemoryVNextLazyPromotionEnabled();
13391
- if (lazyPromotionEnabled && promotionCandidate) {
13392
- void runMemoryVNextLazyPromotion({
13393
- db: input.db,
13394
- item: promotionCandidate,
13395
- provider: input.vNextShadowProvider,
13396
- ...input.lazyPromotionEmit ? { emit: input.lazyPromotionEmit } : {}
13397
- }).catch(() => {
13964
+ if (lazyPromotionEnabled && selected.length > 0 && !allCoveredByVNext) {
13965
+ void (async () => {
13966
+ const promotionPick = await pickFirstUncoveredLazyPromotionItem(
13967
+ input.db,
13968
+ selected
13969
+ );
13970
+ if (promotionPick) {
13971
+ await runMemoryVNextLazyPromotion({
13972
+ db: input.db,
13973
+ item: promotionPick.item,
13974
+ selectedIndex: promotionPick.selectedIndex,
13975
+ skippedCoveredCount: promotionPick.skippedCoveredCount,
13976
+ skippedNoOpCount: promotionPick.skippedNoOpCount,
13977
+ provider: input.vNextShadowProvider,
13978
+ ...input.lazyPromotionEmit ? { emit: input.lazyPromotionEmit } : {}
13979
+ });
13980
+ }
13981
+ })().catch(() => {
13398
13982
  });
13399
13983
  }
13400
13984
  if (selected.length === 0) {
@@ -13408,6 +13992,52 @@ var resolveMemoryRuntime = async (input) => {
13408
13992
  };
13409
13993
 
13410
13994
  // packages/cli/memoryRecall.ts
13995
+ var logger = getLogger("cli.memoryRecall");
13996
+ var DEDUP_WINDOW_MS = 5 * 60 * 1e3;
13997
+ var DEDUP_MAX_KEYS = 100;
13998
+ var dedupMap = /* @__PURE__ */ new Map();
13999
+ function evictDedupIfNeeded() {
14000
+ if (dedupMap.size < DEDUP_MAX_KEYS) return;
14001
+ let oldestKey = null;
14002
+ let oldestTs = Infinity;
14003
+ for (const [k, v] of dedupMap) {
14004
+ if (v.lastLog < oldestTs) {
14005
+ oldestTs = v.lastLog;
14006
+ oldestKey = k;
14007
+ }
14008
+ }
14009
+ if (oldestKey !== null) dedupMap.delete(oldestKey);
14010
+ }
14011
+ function logDeduped(level, fingerprint, message, error) {
14012
+ const now = Date.now();
14013
+ const entry = dedupMap.get(fingerprint);
14014
+ if (!entry) {
14015
+ evictDedupIfNeeded();
14016
+ dedupMap.set(fingerprint, { count: 1, suppressed: 0, lastLog: now });
14017
+ if (error !== void 0) logger[level](message, error);
14018
+ else logger[level](message);
14019
+ return;
14020
+ }
14021
+ entry.count += 1;
14022
+ if (now - entry.lastLog >= DEDUP_WINDOW_MS) {
14023
+ const suppressed = entry.suppressed;
14024
+ const summary = `${message} (deduplicated: ${entry.count} occurrences, ${suppressed} suppressed over ${Math.round((now - entry.lastLog) / 1e3)}s)`;
14025
+ if (error !== void 0) logger[level](summary, error);
14026
+ else logger[level](summary);
14027
+ entry.count = 1;
14028
+ entry.suppressed = 0;
14029
+ entry.lastLog = now;
14030
+ } else {
14031
+ entry.suppressed += 1;
14032
+ }
14033
+ }
14034
+ function fingerprintFor(kind, detail) {
14035
+ const d = detail === void 0 ? "" : sanitizeFp(String(detail));
14036
+ return `mem-${kind}:${d}`;
14037
+ }
14038
+ function sanitizeFp(s) {
14039
+ return s.replace(/\s+/g, " ").slice(0, 80);
14040
+ }
13411
14041
  var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceId) => {
13412
14042
  try {
13413
14043
  const response = await fetch(`${serverUrl}/api/memory/query`, {
@@ -13424,10 +14054,10 @@ var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceI
13424
14054
  signal: AbortSignal.timeout(5e3)
13425
14055
  });
13426
14056
  if (!response.ok) {
13427
- console.warn(
13428
- "[cli-memory] remote query returned non-ok status:",
13429
- response.status,
13430
- "\u2014 falling back to local"
14057
+ logDeduped(
14058
+ "warn",
14059
+ fingerprintFor("remote-nonok", response.status),
14060
+ `remote query returned non-ok status ${response.status} \u2014 falling back to local`
13431
14061
  );
13432
14062
  return null;
13433
14063
  }
@@ -13435,7 +14065,12 @@ var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceI
13435
14065
  const block = typeof payload?.promptBlock === "string" ? payload.promptBlock.trim() : "";
13436
14066
  return block || null;
13437
14067
  } catch (error) {
13438
- console.warn("[cli-memory] remote query failed, falling back to local:", error);
14068
+ logDeduped(
14069
+ "info",
14070
+ fingerprintFor("remote-failed", error instanceof Error ? error.name : void 0),
14071
+ "remote query failed, falling back to local",
14072
+ normalizeError(error)
14073
+ );
13439
14074
  return null;
13440
14075
  }
13441
14076
  };
@@ -13471,7 +14106,12 @@ var resolveCliMemory = async (input) => {
13471
14106
  input.spaceId
13472
14107
  );
13473
14108
  } catch (error) {
13474
- console.warn("[cli-memory] local recall failed, omitting memory layer:", error);
14109
+ logDeduped(
14110
+ "warn",
14111
+ fingerprintFor("local-failed", error instanceof Error ? error.name : void 0),
14112
+ "local recall failed, omitting memory layer",
14113
+ normalizeError(error)
14114
+ );
13475
14115
  return null;
13476
14116
  }
13477
14117
  };
@@ -13526,7 +14166,10 @@ async function resolveAgentRunAgentKey(args) {
13526
14166
  }
13527
14167
  async function runAgentRunCommand(args, deps) {
13528
14168
  const env = deps.env ?? process.env;
13529
- const output = deps.output ?? process.stdout;
14169
+ const output = deps.output ?? {
14170
+ write: (chunk) => process.stdout.write(chunk),
14171
+ writeErr: (chunk) => process.stderr.write(chunk)
14172
+ };
13530
14173
  if (args.includes("--help") || args.includes("-h")) {
13531
14174
  writeUsage(output, deps.commandPath);
13532
14175
  return 0;
@@ -14068,12 +14711,6 @@ function isBalanceExhaustedError(error) {
14068
14711
  }
14069
14712
 
14070
14713
  export {
14071
- resolveAgentModelIdentity,
14072
- resolveAgentContextWindow,
14073
- platformCreditsFromUsage,
14074
- formatCreditsChip,
14075
- formatTokenCount,
14076
- renderTokenStatus,
14077
14714
  resolveCliColorEnabled,
14078
14715
  dimCliText,
14079
14716
  ANSI_ESCAPE_REGEX,
@@ -14114,6 +14751,12 @@ export {
14114
14751
  formatAssistantDisplay,
14115
14752
  redactSecrets,
14116
14753
  TUI_TREE_MARKER,
14754
+ resolveAgentModelIdentity,
14755
+ resolveAgentContextWindow,
14756
+ platformCreditsFromUsage,
14757
+ formatCreditsChip,
14758
+ formatTokenCount,
14759
+ renderTokenStatus,
14117
14760
  COLLAPSED_PASTE_PLACEHOLDER_RE,
14118
14761
  shouldCollapsePaste,
14119
14762
  createCollapsedPasteStore,
@@ -14124,15 +14767,16 @@ export {
14124
14767
  releaseCollapsedPasteReferences,
14125
14768
  expandRangeToCollapsedPasteChips,
14126
14769
  findCollapsedPasteSpanAt,
14770
+ formatElapsed,
14127
14771
  runAgentTurn,
14128
- readAgentsMdLayerFromDisk,
14129
14772
  resolveWorkflowReference,
14130
14773
  resolveSkillReference,
14131
14774
  buildSkillContextBlocks,
14132
14775
  prependSubjectDialogMarker,
14133
14776
  normalizeCliImageInput,
14134
- inspectLocalRunWorkspace,
14777
+ readAgentsMdLayerFromDisk,
14135
14778
  resolveCliMemory,
14779
+ inspectLocalRunWorkspace,
14136
14780
  resolveRunOutcome,
14137
14781
  isRunResultStalledOrTruncated,
14138
14782
  resolveRunSettlementNote,