nolo-cli 0.103.0-alpha.2 → 0.103.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 (209) hide show
  1. package/README.md +1 -1
  2. package/{_executeModel-3UCNJCQA.js → _executeModel-7J7Q3WXY.js} +75 -68
  3. package/action-C4KMTCJF.js +20 -0
  4. package/{addContentAction-O7R66HEX.js → addContentAction-7TNIOVZI.js} +12 -11
  5. package/{addDialogAgentAction-74OA7KYP.js → addDialogAgentAction-O47J3MVW.js} +18 -19
  6. package/{agentDeleteCommand-2YAHAZFJ.js → agentDeleteCommand-YPJHK7JA.js} +117 -42
  7. package/{agentEmailCommands-WLYF3JRS.js → agentEmailCommands-AWEXOHWM.js} +98 -88
  8. package/agentListCommands-2DTLLJZD.js +742 -0
  9. package/{agentMachineCommands-HNGAR5GI.js → agentMachineCommands-PGEEQ4JJ.js} +48 -43
  10. package/{agentProviderCommands-GNPTL5XR.js → agentProviderCommands-XPJYZSCE.js} +97 -2
  11. package/{agentPullCommand-O5MPVJ5E.js → agentPullCommand-B4T2DJ5H.js} +1 -1
  12. package/agentRecordCommands-DZVLCPLJ.js +138 -0
  13. package/agentRunCommand-AX5CYQ46.js +167 -0
  14. package/{agentRunControl-AVJR4JW4.js → agentRunControl-3HWA2LLQ.js} +2 -2
  15. package/{agentRuntimeLocal-VXZSDIGT.js → agentRuntimeLocal-PITRQ2EU.js} +48 -39
  16. package/{agentSlice-SICQBMCM.js → agentSlice-4TLSG6FB.js} +14 -13
  17. package/{appDeleteCommands-32MHLR4L.js → appDeleteCommands-UC2JW5FJ.js} +46 -41
  18. package/{appDeployCommands-WCQOUSOB.js → appDeployCommands-OL2RKVJ3.js} +46 -41
  19. package/{appDeployStatusCommands-6QKB7DYN.js → appDeployStatusCommands-B3PLC62M.js} +46 -41
  20. package/{appGetCommands-SFAPP5PB.js → appGetCommands-REESA2XQ.js} +46 -41
  21. package/{appListCommands-EKUBDRUO.js → appListCommands-UF6XX7HR.js} +46 -41
  22. package/{authCommand-F4EFRRX6.js → authCommand-NQPMGYHP.js} +118 -24
  23. package/{authCommands-RGOGCPP6.js → authCommands-LWLOZETU.js} +7 -5
  24. package/{builtinSkillRegistry-FUAVTRVZ.js → builtinSkillRegistry-GFY77VRN.js} +10 -8
  25. package/{chromeCommands-FZYAU75D.js → chromeCommands-K27J4OVZ.js} +124 -28
  26. package/{chromeOpsCommands-62P2Q2YB.js → chromeOpsCommands-IXRLN57H.js} +4 -3
  27. package/{chunk-UKZDAFYT.js → chunk-22RVE2PC.js} +6 -10
  28. package/{chunk-6OZ36FXI.js → chunk-27ONFIEY.js} +22 -4
  29. package/{chunk-HVURBGF3.js → chunk-2H6SEVDS.js} +6 -6
  30. package/{chunk-TOP2VXOR.js → chunk-2K4TM6AW.js} +5 -5
  31. package/{chunk-JEDZAO7L.js → chunk-2SYTUTLI.js} +257 -37
  32. package/{chunk-53HEEOTT.js → chunk-2WJ57RJA.js} +83 -16
  33. package/{chunk-OIVSQH2O.js → chunk-3BXNTXYI.js} +299 -5
  34. package/chunk-4A2R7KHG.js +13545 -0
  35. package/{chunk-EYAQT56M.js → chunk-4DPP773Q.js} +2 -2
  36. package/{chunk-JRQFUXY7.js → chunk-4G4C5SXT.js} +99 -22
  37. package/{chunk-DHDMC6FO.js → chunk-4HTMUQIZ.js} +14 -9
  38. package/{chunk-B3TVQ6PI.js → chunk-4IVA6UUE.js} +20 -11
  39. package/chunk-4LCOCOR5.js +50 -0
  40. package/{chunk-2GRGFCF6.js → chunk-4VJAC32I.js} +2 -1
  41. package/{chunk-MC4XLIJ7.js → chunk-523DITKR.js} +1 -1
  42. package/{chunk-H62HCIUP.js → chunk-56HJ2LAA.js} +35 -22
  43. package/{chunk-V4MJDUSR.js → chunk-5EPHWMP5.js} +2 -2
  44. package/{chunk-E4MARS3Q.js → chunk-5GVBDNTO.js} +1 -1
  45. package/{chunk-3WLK2JQ5.js → chunk-5IWONK6X.js} +68 -46
  46. package/chunk-5J3PYNUP.js +255 -0
  47. package/chunk-5MMAK75Q.js +15 -0
  48. package/{chunk-LW4VFPAY.js → chunk-5ZDLVKNG.js} +873 -228
  49. package/{chunk-42V6BK2E.js → chunk-62IL3KQV.js} +4 -34
  50. package/{chunk-AEOE4Z6Q.js → chunk-6UEJDFF7.js} +39 -15
  51. package/{chunk-JPGCXHNM.js → chunk-7JWCVINR.js} +1 -1
  52. package/{chunk-GQBOR3G6.js → chunk-7KVZ5LDQ.js} +2 -2
  53. package/{chunk-IIVGDG4I.js → chunk-7KWFIKKK.js} +13 -7
  54. package/chunk-A4SQRTZ6.js +15 -0
  55. package/chunk-AGIM7IMJ.js +147 -0
  56. package/{chunk-5UTFL4QJ.js → chunk-AOTBKDRK.js} +7 -0
  57. package/{chunk-L5UXH3B2.js → chunk-B455PEFD.js} +27 -8
  58. package/{chunk-XS5SWEDQ.js → chunk-BELZY72F.js} +1 -1
  59. package/chunk-BMQ2MJUK.js +153 -0
  60. package/{chunk-6YTOJY35.js → chunk-BZ7NPA6G.js} +35 -2
  61. package/chunk-CHOZJMJS.js +78 -0
  62. package/{chunk-3BMYXEUW.js → chunk-CUF4MYKI.js} +1 -1
  63. package/{chunk-ACTMNVHM.js → chunk-CYSYR67N.js} +1 -1
  64. package/{chunk-WV42OMV7.js → chunk-D2GQE6AF.js} +8 -8
  65. package/{chunk-GBRG75BQ.js → chunk-D2MDMY2M.js} +1 -0
  66. package/chunk-DZ7R5V3Y.js +164 -0
  67. package/{chunk-3VNWWVKB.js → chunk-E3YWHWCR.js} +50 -18
  68. package/{chunk-KQ4ONNQD.js → chunk-EKPKW6RM.js} +155 -8
  69. package/{chunk-ABQYVJBJ.js → chunk-EV235ILT.js} +5 -5
  70. package/{chunk-TRV2MIDW.js → chunk-EXAJ6DCR.js} +1 -0
  71. package/{chunk-AGVEIAQA.js → chunk-F442UK5V.js} +29 -78
  72. package/{chunk-HJUYAD4A.js → chunk-FBTNYNAL.js} +5 -5
  73. package/{chunk-2F7RJC6L.js → chunk-FOXQ7BAB.js} +1 -1
  74. package/{chunk-ETI2NYVF.js → chunk-GCTKWVLU.js} +4 -4
  75. package/chunk-GMZLP5DV.js +82 -0
  76. package/{chunk-FDTR4QJ6.js → chunk-H6A6X4EK.js} +32 -1
  77. package/{chunk-6VFARHZW.js → chunk-H7TQORR4.js} +994 -1079
  78. package/{chunk-5H7KJX7J.js → chunk-HD3S2F7U.js} +5 -5
  79. package/chunk-HDJRLWTG.js +8002 -0
  80. package/{chunk-DVINR3PL.js → chunk-HDLLCBRF.js} +1 -1
  81. package/{chunk-QOKAKDPE.js → chunk-HIM3FCLF.js} +0 -1
  82. package/{chunk-ONXOABJR.js → chunk-HNGRBWYF.js} +3 -0
  83. package/{chunk-VLTIYV3X.js → chunk-HP57OUJO.js} +4 -4
  84. package/{chunk-4OEFYTWL.js → chunk-IRZTHHNM.js} +67 -48
  85. package/{chunk-GPCZ7UXG.js → chunk-K6U4NKFJ.js} +1 -1
  86. package/{chunk-OZGZPSEG.js → chunk-KGRP4VOK.js} +47 -67
  87. package/{chunk-DNCEALKX.js → chunk-LB5A6JTU.js} +22 -29
  88. package/{chunk-LS2ZANRJ.js → chunk-LOCNXNOU.js} +1 -1
  89. package/{chunk-PUOC4YRO.js → chunk-M7VLQGQP.js} +11 -0
  90. package/{chunk-Z77CRGTW.js → chunk-MSFZ7FMO.js} +1 -1
  91. package/chunk-NKWIS6G2.js +442 -0
  92. package/{chunk-BFU6C242.js → chunk-NMFV26UG.js} +1 -1
  93. package/{chunk-FZGV4FGK.js → chunk-NUHHBEJC.js} +378 -187
  94. package/chunk-NWENLDMM.js +42 -0
  95. package/chunk-O7SVKKLY.js +875 -0
  96. package/chunk-OCZKATRC.js +129 -0
  97. package/{chunk-PQFHGD77.js → chunk-OM2RUOEU.js} +161 -14
  98. package/{chunk-KQHGZWSV.js → chunk-OXME3PEE.js} +1 -1
  99. package/{chunk-TQBHNYVR.js → chunk-PLRFCQ7C.js} +567 -519
  100. package/{chunk-6D6VBVEW.js → chunk-Q7O72MF5.js} +80 -14
  101. package/{chunk-J4MOO56S.js → chunk-RILRSUGC.js} +10 -2
  102. package/{chunk-RSONHHPE.js → chunk-RNUDNZJW.js} +10 -10
  103. package/{chunk-3N3W7KBB.js → chunk-RZJAZVCF.js} +11 -9
  104. package/{chunk-BYMV6QZG.js → chunk-TNIX77YM.js} +4 -0
  105. package/{chunk-GEPUP7OO.js → chunk-TSXNDTXL.js} +3 -3
  106. package/chunk-TY3TIUJK.js +89 -0
  107. package/{chunk-I3TQJXQ7.js → chunk-U3C3IA32.js} +9 -2
  108. package/{chunk-UZGQNTVW.js → chunk-UA324D4O.js} +8 -6
  109. package/{chunk-YYLHWIW6.js → chunk-UKZX3NHN.js} +1 -1
  110. package/{chunk-BP4XNZRM.js → chunk-UNAOTLKO.js} +4 -4
  111. package/{chunk-CUQEXCAU.js → chunk-UQ5P2WHS.js} +29 -9
  112. package/{chunk-NA35QHCF.js → chunk-V6YASAZR.js} +1 -1
  113. package/{chunk-3DII57IT.js → chunk-VCAQFMVN.js} +1 -1
  114. package/chunk-VIWDGTDA.js +8 -0
  115. package/chunk-VJVNU77E.js +83 -0
  116. package/{chunk-ZCYXJSTU.js → chunk-VL3H5ZU3.js} +66 -94
  117. package/{chunk-Q554LLSI.js → chunk-VLGL7FOL.js} +1 -1
  118. package/{chunk-UKWGR5SS.js → chunk-VY6VFGKR.js} +194 -1144
  119. package/{chunk-4EG4QFTK.js → chunk-WI6TUGLJ.js} +19 -17
  120. package/{chunk-QDSINZM3.js → chunk-WJ3B6FX6.js} +1 -14
  121. package/{chunk-OEVAY4J6.js → chunk-XMUZHRSB.js} +18 -20
  122. package/{chunk-O6OSWFZQ.js → chunk-XUWRURDF.js} +6 -0
  123. package/{chunk-Q67DOFOO.js → chunk-Y3PMXGLH.js} +2 -0
  124. package/{chunk-7S4YWN7P.js → chunk-YDO5ERB4.js} +4 -4
  125. package/chunk-YK5MHOWM.js +915 -0
  126. package/{chunk-SH43IESU.js → chunk-YUNJN43V.js} +44 -9
  127. package/chunk-YV25TM3R.js +780 -0
  128. package/{chunk-IONPPCL5.js → chunk-YZZREBID.js} +86 -16
  129. package/{chunk-DNUUJ45N.js → chunk-Z3WSAK6A.js} +23 -28
  130. package/chunk-ZRAU6T47.js +56 -0
  131. package/commandRegistry-VQPFWVDH.js +833 -0
  132. package/{contentThunks-S4S7QPSO.js → contentThunks-A26ME6OJ.js} +37 -35
  133. package/{cooldownCommands-REAWYVTY.js → cooldownCommands-ZLEPIB4A.js} +2 -2
  134. package/{createAgentAutomationAction-ODGL2YGP.js → createAgentAutomationAction-BSAMZJ5W.js} +39 -37
  135. package/createDialogAction-CMCQXYHD.js +69 -0
  136. package/{createPageAction-FBV3OWX7.js → createPageAction-ANGKJTK2.js} +46 -43
  137. package/{chunk-F2RNI7ZR.js → cursorProvider-YGGNMVWX.js} +2496 -9897
  138. package/{dbSlice-XVWBAGYN.js → dbSlice-QOLNF5GN.js} +11 -10
  139. package/{deleteFile-YG6QMJLU.js → deleteFile-KESP65GC.js} +7 -6
  140. package/{dialogCommands-5J56DFWN.js → dialogCommands-AMPAWLX4.js} +49 -45
  141. package/{dialogSlice-LEO27SQG.js → dialogSlice-DGWDEBYC.js} +41 -34
  142. package/{dist-VODFSGNG.js → dist-NJC2W7I4.js} +61 -54
  143. package/{docCreateCommands-KYI2DC2U.js → docCreateCommands-7NMIYL5D.js} +48 -43
  144. package/{docDeleteCommands-67REUSRY.js → docDeleteCommands-BD4OM5PV.js} +49 -44
  145. package/{docReadCommands-HOSVSBDJ.js → docReadCommands-5IOVAKU2.js} +47 -42
  146. package/{docStore-MNX5MHA5.js → docStore-TP4QDER4.js} +16 -12
  147. package/{docUpdateCommands-EMGCSMXY.js → docUpdateCommands-ZTKJ6UPC.js} +48 -43
  148. package/{fetchMessages-EIU7UFFK.js → fetchMessages-5L7OVM5Y.js} +5 -5
  149. package/{getPricing-LUSEABA6.js → getPricing-NMMFT3YI.js} +4 -4
  150. package/{handleSendMessageAction-YB6KQFJS.js → handleSendMessageAction-N4WKFRSQ.js} +111 -87
  151. package/index.js +87 -884
  152. package/{lib-FRRS27KN.js → lib-PU2G2MSO.js} +523 -191
  153. package/{localDialogRead-BTFJ4V2I.js → localDialogRead-O5A26FDK.js} +2 -2
  154. package/{localRuntimeAuthority-6IR6BBXE.js → localRuntimeAuthority-TU6OBC76.js} +9 -6
  155. package/{localRuntimeDb-SYQGUF4U.js → localRuntimeDb-VKWVOPPI.js} +1 -1
  156. package/{machineCommands-7GVQCUAK.js → machineCommands-47WKGY5Z.js} +92 -82
  157. package/machineWsRunDispatch-CYW5FJ52.js +154 -0
  158. package/{memberThunks-QGFLFVCI.js → memberThunks-25K6DDRA.js} +20 -18
  159. package/{models-T3SG6MJ5.js → models-ZPU5EDF4.js} +2 -2
  160. package/oauthTokenStore-ITEB663N.js +23 -0
  161. package/package.json +1 -1
  162. package/pdf-U6KSUEZZ.js +26435 -0
  163. package/processSpawn-SOAV3FEV.js +11 -0
  164. package/profileConfig-ZGOFORWV.js +43 -0
  165. package/{providerPresetApply-FG6NZ57W.js → providerPresetApply-TEBH7FDX.js} +7 -7
  166. package/{providerRegistry-757OWH3O.js → providerRegistry-CBJLNCET.js} +11 -7
  167. package/{read-COE3ZYR6.js → read-PJIT2YEJ.js} +7 -6
  168. package/{readDocTool-5USN4A6V.js → readDocTool-DRSXHGNL.js} +5 -3
  169. package/{readlineWorkspace-WA7JNI6J.js → readlineWorkspace-CK7GOVOC.js} +2698 -2055
  170. package/{removeDialogAgentAction-IX3MN2ZO.js → removeDialogAgentAction-VIWJL6MX.js} +21 -25
  171. package/{runAgentClientLoop-JGFQ6KIR.js → runAgentClientLoop-BGHGP5AR.js} +76 -70
  172. package/{runtimeDoctorCommands-X6WDBEQX.js → runtimeDoctorCommands-PIVSBZRZ.js} +4 -4
  173. package/runtimeModeArgs-2Y7BALTO.js +31 -0
  174. package/{setDialogExtraReferencesAction-X4HCPNZL.js → setDialogExtraReferencesAction-A7VA3NFM.js} +15 -13
  175. package/{setPrimaryDialogAgentAction-4GMIQLOD.js → setPrimaryDialogAgentAction-B4P7YQX2.js} +22 -26
  176. package/{chunk-AFUORTY4.js → settingThunks-KOYSAT65.js} +226 -940
  177. package/{skillDiscovery-CYUCJMAG.js → skillDiscovery-ZBU76COE.js} +3 -3
  178. package/{slateUtils-RIZES3PV.js → slateUtils-NGV2NMKM.js} +1 -1
  179. package/{spaceCommands-NKJVJCQQ.js → spaceCommands-QJCYG27F.js} +51 -46
  180. package/{streamAgentChatTurn-XLFZ66UC.js → streamAgentChatTurn-ANE7OTCZ.js} +214 -108
  181. package/{switchDialogAgentAction-N52LRPA3.js → switchDialogAgentAction-3VYWHZKH.js} +18 -19
  182. package/{tableCommands-O6NWHFKV.js → tableCommands-6U4BMLRR.js} +10 -10
  183. package/{toolApiClient-QVJ6HDNN.js → toolApiClient-EJT6TMFG.js} +3 -3
  184. package/tools-WPOVVP7M.js +116 -0
  185. package/{tuiSummaryLlmCaller-WFRWERGK.js → tuiSummaryLlmCaller-QCHCULPM.js} +25 -22
  186. package/{updateCommands-2M74UL7P.js → updateCommands-4EHDLF5J.js} +3 -3
  187. package/{updateDialogTitleAction-6MBTD4UE.js → updateDialogTitleAction-C4GRCXL4.js} +82 -44
  188. package/action-YVYQEAAV.js +0 -31
  189. package/agentListCommands-JP7S7PT2.js +0 -469
  190. package/agentRecordCommands-SXFPW3DL.js +0 -128
  191. package/agentRunCommand-JIQ4HY4D.js +0 -155
  192. package/browser-image-compression-MFDTD7K6.js +0 -1763
  193. package/chatQueueReduxAdapter-HHMUDNXL.js +0 -186
  194. package/chunk-CQ3WA2NE.js +0 -299
  195. package/chunk-M76ECQRD.js +0 -13658
  196. package/chunk-MEYIRKDN.js +0 -8967
  197. package/chunk-Q5FJJ6XI.js +0 -103
  198. package/chunk-S7Z2HMCN.js +0 -25
  199. package/chunk-XVZ22N6C.js +0 -20782
  200. package/chunk-Y5GCAMGP.js +0 -9
  201. package/chunk-YPREESF4.js +0 -225
  202. package/createDialogAction-GFKRXTK4.js +0 -65
  203. package/machineWsRunDispatch-XA7TD7Z7.js +0 -144
  204. package/settingSlice-ZQZVUPKK.js +0 -204
  205. package/syncMapping-N6RGXGBW.js +0 -437
  206. package/tools-NF5AB34X.js +0 -110
  207. package/{chunk-VMFTFOWF.js → chunk-ODAPITXL.js} +7 -7
  208. package/{chunk-X7HHHIOZ.js → chunk-Y6ROFCZO.js} +0 -0
  209. 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,29 +26,35 @@ import {
26
26
  resolveFileWriteGateEnabled,
27
27
  resolveLocalUserId,
28
28
  t,
29
- toolLabel
30
- } from "./chunk-F2RNI7ZR.js";
31
- import {
32
- createRunActivityTracker,
33
- popSingleQueueMessage,
34
- readRunRecord,
35
- resolveRunQueuePath,
36
- settleRunTerminalAuthoritatively,
37
- spawnLocalBackgroundRun
38
- } from "./chunk-I3TQJXQ7.js";
29
+ toolLabel,
30
+ toolLabelVariants
31
+ } from "./chunk-HDJRLWTG.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-LOCNXNOU.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";
48
54
  import {
49
55
  readDbRecord,
50
56
  resolveAgentRecordFromHybridStore
51
- } from "./chunk-AEOE4Z6Q.js";
57
+ } from "./chunk-6UEJDFF7.js";
52
58
  import {
53
59
  isLocalCliAgentKey
54
60
  } from "./chunk-SV5IJK6K.js";
@@ -62,60 +68,70 @@ import {
62
68
  applyModelLayerOverride,
63
69
  buildModelLayerOverride
64
70
  } from "./chunk-LTRXGFMS.js";
65
- import {
66
- formatAgentListCard
67
- } from "./chunk-TQBHNYVR.js";
68
- import {
69
- isTransientFetchError
70
- } from "./chunk-5UTFL4QJ.js";
71
71
  import {
72
72
  isGatewayHttpStatus
73
73
  } from "./chunk-NF64D32W.js";
74
74
  import {
75
- formatFinishedRunCard,
76
- formatListRunsCard,
77
- formatNotFoundRunCard,
78
- formatStartRunCard,
79
- formatStatusRunCard,
80
- formatStopRunCard,
81
- isAgentRunTerminalStatus
82
- } from "./chunk-3VNWWVKB.js";
75
+ isTransientFetchError,
76
+ parsePositiveFiniteNumberOrFallback
77
+ } from "./chunk-AOTBKDRK.js";
78
+ import {
79
+ extractGoogleValidationLink
80
+ } from "./chunk-BMQ2MJUK.js";
83
81
  import {
84
82
  buildMemorySubjectsForAgent,
85
83
  chooseMemoryOwners,
86
84
  loadMemoryCandidatesFromDb,
87
85
  resolveAgentMemoryPolicy
88
- } from "./chunk-DNUUJ45N.js";
86
+ } from "./chunk-Z3WSAK6A.js";
89
87
  import {
90
- API_REPORTED_COST_MULTIPLIER,
91
- parseUiAskChoiceContent
92
- } from "./chunk-XVZ22N6C.js";
88
+ createRunActivityTracker,
89
+ popSingleQueueMessage,
90
+ readRunRecord,
91
+ resolveRunQueuePath,
92
+ settleRunTerminalAuthoritatively,
93
+ spawnLocalBackgroundRun
94
+ } from "./chunk-U3C3IA32.js";
93
95
  import {
94
- isOAuthApiKeyRef
95
- } from "./chunk-YYLHWIW6.js";
96
+ formatAgentListCard,
97
+ formatFinishedRunCard,
98
+ formatListRunsCard,
99
+ formatNotFoundRunCard,
100
+ formatStartRunCard,
101
+ formatStatusRunCard,
102
+ formatStopRunCard,
103
+ isAgentRunTerminalStatus
104
+ } from "./chunk-E3YWHWCR.js";
96
105
  import {
97
106
  isCliAuthorityBrokerProtocolError,
98
107
  isCliAuthorityBrokerTimeoutError,
99
108
  isCliAuthorityBrokerUnavailableError
100
- } from "./chunk-TRV2MIDW.js";
109
+ } from "./chunk-EXAJ6DCR.js";
101
110
  import {
102
111
  getDefaultCliLocalRuntimeDb
103
- } from "./chunk-2F7RJC6L.js";
112
+ } from "./chunk-FOXQ7BAB.js";
113
+ import {
114
+ API_REPORTED_COST_MULTIPLIER,
115
+ parseUiAskChoiceContent
116
+ } from "./chunk-4A2R7KHG.js";
117
+ import {
118
+ isOAuthApiKeyRef
119
+ } from "./chunk-UKZX3NHN.js";
104
120
  import {
105
121
  buildSkillDiscoveryContextLayer
106
- } from "./chunk-E4MARS3Q.js";
122
+ } from "./chunk-5GVBDNTO.js";
107
123
  import {
108
124
  parseExternalSkillMarkdown,
109
125
  parseSkillDocProtocol
110
- } from "./chunk-Q554LLSI.js";
126
+ } from "./chunk-VLGL7FOL.js";
111
127
  import {
112
128
  LOCAL_AGENT_CONFIG_MISSING_CODE,
113
129
  LOCAL_TURN_ABORTED_CODE,
114
130
  readActionGate
115
- } from "./chunk-6VFARHZW.js";
131
+ } from "./chunk-H7TQORR4.js";
116
132
  import {
117
133
  resolveAgentRuntimeConfigFromRecord
118
- } from "./chunk-5H7KJX7J.js";
134
+ } from "./chunk-HD3S2F7U.js";
119
135
  import {
120
136
  createThinkParserState,
121
137
  flushThinkParser,
@@ -126,57 +142,55 @@ import {
126
142
  isQuotaExhaustedError,
127
143
  isQuotaLimited403Body,
128
144
  mergeAvailabilityDeadline,
129
- resolveCooldownGate
130
- } from "./chunk-FDTR4QJ6.js";
131
- import {
132
- isAntigravityOAuthAgent
133
- } from "./chunk-UZGQNTVW.js";
134
- import {
135
- resolveClientVersion
136
- } from "./chunk-6OZ36FXI.js";
145
+ resolveCooldownGate,
146
+ resolveCredentialKeyWithFallback
147
+ } from "./chunk-H6A6X4EK.js";
137
148
  import {
138
149
  DEFAULT_CONTEXT_WINDOW,
139
150
  getModelContextWindow,
140
151
  normalizeUsage
141
- } from "./chunk-4OEFYTWL.js";
152
+ } from "./chunk-IRZTHHNM.js";
142
153
  import {
143
154
  clipCompactText
144
- } from "./chunk-DNCEALKX.js";
145
- import {
146
- findModelConfig
147
- } from "./chunk-OIVSQH2O.js";
155
+ } from "./chunk-5MMAK75Q.js";
148
156
  import {
149
157
  compactWhitespace
150
158
  } from "./chunk-DWLEOOGR.js";
151
- import {
152
- toErrorMessage
153
- } from "./chunk-HNMXYYJR.js";
154
159
  import {
155
160
  buildAgentsMdLayer,
156
161
  buildMemoryOverlayLayer,
157
162
  buildMemoryUseGuidanceLayer,
158
163
  partitionScopedBlocks,
159
164
  renderTurnContextBlocksWithScope
160
- } from "./chunk-DVINR3PL.js";
165
+ } from "./chunk-HDLLCBRF.js";
161
166
  import {
162
- readPipeText,
163
- spawnProcess
164
- } from "./chunk-X7HHHIOZ.js";
167
+ isAntigravityOAuthAgent
168
+ } from "./chunk-UA324D4O.js";
169
+ import {
170
+ resolveClientVersion
171
+ } from "./chunk-27ONFIEY.js";
172
+ import {
173
+ findModelConfig
174
+ } from "./chunk-3BXNTXYI.js";
175
+ import {
176
+ toErrorMessage
177
+ } from "./chunk-HNMXYYJR.js";
178
+ import {
179
+ getLogger,
180
+ normalizeError
181
+ } from "./chunk-YV25TM3R.js";
165
182
  import {
166
183
  resolveAuthToken
167
184
  } from "./chunk-A7GB5UGH.js";
185
+ import {
186
+ readPipeText,
187
+ spawnProcess
188
+ } from "./chunk-Y6ROFCZO.js";
168
189
  import {
169
190
  CLIENT_VERSION_TOO_OLD_CODE,
170
191
  NOLO_CLIENT_VERSION_HEADER,
171
192
  buildClientVersionUpgradeMessage
172
- } from "./chunk-Q67DOFOO.js";
173
- import {
174
- parsePositiveFiniteNumberOrFallback
175
- } from "./chunk-Y5GCAMGP.js";
176
- import {
177
- createMemoryKey,
178
- ulid
179
- } from "./chunk-VMFTFOWF.js";
193
+ } from "./chunk-Y3PMXGLH.js";
180
194
  import {
181
195
  asTrimmedLowercaseString
182
196
  } from "./chunk-QSJ3HFEF.js";
@@ -189,8 +203,9 @@ import {
189
203
  parsePublicAgentId
190
204
  } from "./chunk-M2EJHDJP.js";
191
205
  import {
192
- isLevelNotFoundError
193
- } from "./chunk-OW765XBU.js";
206
+ createMemoryKey,
207
+ ulid
208
+ } from "./chunk-ODAPITXL.js";
194
209
  import {
195
210
  asTrimmedString
196
211
  } from "./chunk-3EUW3WEO.js";
@@ -386,6 +401,24 @@ function styleCliText(text, style, enabled = resolveCliColorEnabled()) {
386
401
  function dimCliText(text, enabled = resolveCliColorEnabled()) {
387
402
  return styleCliText(text, "dim", enabled);
388
403
  }
404
+ var OSC8_OPEN = "\x1B]8;;";
405
+ var OSC8_CLOSE = "\x1B\\";
406
+ function sanitizeHyperlinkLabel(label) {
407
+ return label.replace(/[\u0000-\u001f\u007f]/g, "");
408
+ }
409
+ function resolveCliHyperlinkEnabled(env = process.env, isTTY = Boolean(process.stdout.isTTY)) {
410
+ const setting = asTrimmedLowercaseString(env.NOLO_CLI_HYPERLINKS);
411
+ if (setting === "0" || setting === "false" || setting === "off") return false;
412
+ if (setting === "1" || setting === "true" || setting === "on") return true;
413
+ return isTTY;
414
+ }
415
+ function formatCliHyperlink(url, label, enabled = resolveCliHyperlinkEnabled()) {
416
+ if (!url) return label;
417
+ const safeLabel = sanitizeHyperlinkLabel(label);
418
+ if (!enabled) return `${safeLabel} (${url})`;
419
+ if (!safeLabel) return url;
420
+ return `${OSC8_OPEN}${url}${OSC8_CLOSE}${safeLabel}${OSC8_OPEN}${OSC8_CLOSE}`;
421
+ }
389
422
 
390
423
  // node_modules/ansi-regex/index.js
391
424
  function ansiRegex({ onlyFirst = false } = {}) {
@@ -620,8 +653,12 @@ function stringWidth(input, options = {}) {
620
653
 
621
654
  // packages/cli/tui/tuiAnsi.ts
622
655
  var ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
656
+ var OSC8_HYPERLINK_REGEX = /\x1b\]8;;[^\x1b]*\x1b\\/g;
623
657
  var ALL_ANSI_ESCAPE_REGEX = ansiRegex();
624
658
  var FIRST_ANSI_ESCAPE_REGEX = ansiRegex({ onlyFirst: true });
659
+ function stripOsc8Hyperlinks(text) {
660
+ return text.replace(OSC8_HYPERLINK_REGEX, "");
661
+ }
625
662
  function stripAnsi2(text) {
626
663
  return text.replace(ANSI_ESCAPE_REGEX, "").replace(ALL_ANSI_ESCAPE_REGEX, "");
627
664
  }
@@ -783,6 +820,7 @@ function visibleWidth(str) {
783
820
  }
784
821
  function truncateAnsi(text, maxWidth) {
785
822
  if (maxWidth <= 0) return "";
823
+ text = stripOsc8Hyperlinks(text);
786
824
  if (visibleWidth(text) <= maxWidth) return text;
787
825
  let width = 0;
788
826
  let out = "";
@@ -823,7 +861,7 @@ function countPhysicalLines(text, columns) {
823
861
  const lines = text.split("\n");
824
862
  let total = 0;
825
863
  for (const line of lines) {
826
- const width = displayWidth(line);
864
+ const width = visibleWidth(stripOsc8Hyperlinks(line));
827
865
  total += Math.max(1, Math.ceil(width / columns));
828
866
  }
829
867
  return Math.max(total, 1);
@@ -8180,7 +8218,12 @@ function emitPlainGap(text, keywords, info, accent, warning, reset) {
8180
8218
  var UNORDERED_LIST_RE = /^(\s*)([-*+])\s+(.+)$/;
8181
8219
  var ORDERED_LIST_RE = /^(\s*)(\d+)\.\s+(.+)$/;
8182
8220
  var TASK_LIST_RE = /^(\s*)([-*+])\s+\[([ xX])\]\s+(.+)$/;
8221
+ var THEMATIC_BREAK_PATTERN = "(?:(-[ \\t]*){3,}|(\\*[ \\t]*){3,}|(_[ \\t]*){3,})";
8222
+ var THEMATIC_BREAK_RE = new RegExp(`^[ ]{0,3}${THEMATIC_BREAK_PATTERN}$`);
8183
8223
  function normalizeListLine(line) {
8224
+ if (THEMATIC_BREAK_RE.test(line)) {
8225
+ return line;
8226
+ }
8184
8227
  const task = line.match(TASK_LIST_RE);
8185
8228
  if (task) {
8186
8229
  const checked = task[3] === "x" || task[3] === "X";
@@ -8196,12 +8239,99 @@ function normalizeListLine(line) {
8196
8239
  }
8197
8240
  return line;
8198
8241
  }
8242
+ var TOOL_TREE_HEADER_RE = /^•\s+(.+?)\s+\((\d+)\)$/;
8243
+ var TOOL_TREE_LEAF_RE = /^([├└]──\s+)(.*?)\s{2}(✓|✗|!)(?:\s+(.*))?$/;
8244
+ var TOOL_SINGLE_RE = /^▸\s+(.+?)(?:\s+·\s+(.*?))?(?:\s{2}(✓|✗|!)(?:\s+(.*))?)$/;
8245
+ function plainToolLine(line) {
8246
+ return stripAnsi2(line);
8247
+ }
8248
+ var TOOL_TREE_GROUP_LABELS = new Set(
8249
+ ["execShell", "readFile", "fetchWebpage", "exa_search"].flatMap(toolLabelVariants)
8250
+ );
8251
+ function isKnownToolGroupLabel(label) {
8252
+ return TOOL_TREE_GROUP_LABELS.has(label);
8253
+ }
8254
+ function toolTreeHeaderMatch(line) {
8255
+ const match = plainToolLine(line).match(TOOL_TREE_HEADER_RE);
8256
+ return match && isKnownToolGroupLabel(match[1]) ? match : null;
8257
+ }
8258
+ function isToolTreeHeaderLine(line) {
8259
+ return toolTreeHeaderMatch(line) !== null;
8260
+ }
8261
+ function isToolTreeLeafLine(line) {
8262
+ return TOOL_TREE_LEAF_RE.test(plainToolLine(line));
8263
+ }
8264
+ function isToolSingleLine(line) {
8265
+ return TOOL_SINGLE_RE.test(plainToolLine(line));
8266
+ }
8267
+ function isToolGroupBoundary(cur, next) {
8268
+ return isToolTreeLeafLine(cur) && isToolTreeHeaderLine(next);
8269
+ }
8270
+ function statusColorSeq(marker, brightness) {
8271
+ if (marker === "\u2713") return colorSeq("success", brightness);
8272
+ if (marker === "\u2717") return colorSeq("danger", brightness);
8273
+ return colorSeq("warning", brightness);
8274
+ }
8275
+ function styleTuiToolLine(line, brightness) {
8276
+ const plain = plainToolLine(line);
8277
+ const chrome = colorSeq("chrome", brightness);
8278
+ const muted = colorSeq("muted", brightness);
8279
+ const header = toolTreeHeaderMatch(plain);
8280
+ if (header) {
8281
+ return `${chrome}\u2022${STYLE.reset} ${STYLE.bold}${muted}${header[1]}${STYLE.reset} ${chrome}${STYLE.dim}(${header[2]})${STYLE.reset}`;
8282
+ }
8283
+ const leaf = plain.match(TOOL_TREE_LEAF_RE);
8284
+ if (leaf) {
8285
+ const [, connector, detail, marker, statusDetail] = leaf;
8286
+ let rendered = `${chrome}${connector}${STYLE.reset}${chrome}${detail}${STYLE.reset}`;
8287
+ rendered += ` ${statusColorSeq(marker, brightness)}${marker}${STYLE.reset}`;
8288
+ if (statusDetail) {
8289
+ const metaSeq = marker === "\u2713" ? chrome : statusColorSeq(marker, brightness);
8290
+ rendered += ` ${metaSeq}${STYLE.dim}${statusDetail}${STYLE.reset}`;
8291
+ }
8292
+ return rendered;
8293
+ }
8294
+ const single = plain.match(TOOL_SINGLE_RE);
8295
+ if (single) {
8296
+ const [, label, detail, marker, statusDetail] = single;
8297
+ let rendered = `${chrome}\u25B8${STYLE.reset} ${STYLE.bold}${muted}${label}${STYLE.reset}`;
8298
+ if (detail) rendered += ` ${chrome}\xB7 ${detail}${STYLE.reset}`;
8299
+ rendered += ` ${statusColorSeq(marker, brightness)}${marker}${STYLE.reset}`;
8300
+ if (statusDetail) {
8301
+ const metaSeq = marker === "\u2713" ? chrome : statusColorSeq(marker, brightness);
8302
+ rendered += ` ${metaSeq}${STYLE.dim}${statusDetail}${STYLE.reset}`;
8303
+ }
8304
+ return rendered;
8305
+ }
8306
+ return null;
8307
+ }
8199
8308
  function isPolishListLikeLine(line) {
8200
- return LIST_LIKE_RE_FOR_GUARD.test(normalizeListLine(line));
8309
+ return LIST_LIKE_RE_FOR_GUARD.test(normalizeListLine(plainToolLine(line)));
8310
+ }
8311
+ var LIST_LIKE_RE_FOR_GUARD = /^\s*(?:•|◦|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s|^\s*▸\s/;
8312
+ function isPolishFenceInteriorLine(line) {
8313
+ return /^\x00F\d+\x00$/.test(line);
8314
+ }
8315
+ function polishHeadingLevel(line) {
8316
+ const match = stripAnsi2(line).match(/^(#{1,6})\s/);
8317
+ return match ? match[1].length : null;
8318
+ }
8319
+ function isPolishHeadingLine(line) {
8320
+ return polishHeadingLevel(line) !== null;
8321
+ }
8322
+ function isPolishIntroLine(line) {
8323
+ const plain = stripAnsi2(line).trimEnd();
8324
+ return plain.endsWith("\uFF1A") || plain.endsWith(":");
8201
8325
  }
8202
- var LIST_LIKE_RE_FOR_GUARD = /^\s*(?:•|☐|☑|\d+\.)\s|^\s*[\u2460-\u2473]|^\s*[├└]──\s/;
8203
8326
  function polishBreathInsertsBlankBetween(cur, next) {
8204
8327
  if (cur === "" || next === "") return false;
8328
+ if (isPolishFenceInteriorLine(cur) || isPolishFenceInteriorLine(next)) {
8329
+ return false;
8330
+ }
8331
+ if (isPolishIntroLine(cur) && isPolishListLikeLine(next)) return false;
8332
+ if (isPolishHeadingLine(cur) || isPolishHeadingLine(next)) return false;
8333
+ if (isCodeFenceLine(cur) !== isCodeFenceLine(next)) return true;
8334
+ if (isToolGroupBoundary(cur, next)) return true;
8205
8335
  return isPolishListLikeLine(cur) !== isPolishListLikeLine(next);
8206
8336
  }
8207
8337
  function convertMarkdownTablesForTerminal(text) {
@@ -8270,17 +8400,15 @@ function polishAssistantStructure(text, options = {}) {
8270
8400
  }
8271
8401
  return line;
8272
8402
  });
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/;
8403
+ 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
8404
  const headingLines = afterHeading.split("\n");
8276
8405
  const breathed = [];
8277
8406
  for (let i = 0; i < headingLines.length; i++) {
8278
8407
  breathed.push(headingLines[i]);
8279
8408
  const cur = headingLines[i];
8280
8409
  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("");
8410
+ if (next === void 0) continue;
8411
+ if (polishBreathInsertsBlankBetween(cur, next)) breathed.push("");
8284
8412
  }
8285
8413
  const polishedMasked = breathed.join("\n");
8286
8414
  const polished = polishedMasked.replace(
@@ -8290,17 +8418,23 @@ function polishAssistantStructure(text, options = {}) {
8290
8418
  return options.trimEdges === false ? polished : polished.trim();
8291
8419
  }
8292
8420
  function styleRichMarkdownLine(line, brightness) {
8293
- const heading = line.match(/^(#{1,3})\s+(.+)$/);
8421
+ const toolLine = styleTuiToolLine(line, brightness);
8422
+ if (toolLine !== null) return toolLine;
8423
+ const heading = line.match(/^(#{1,6})\s+(.+)$/);
8294
8424
  if (heading) {
8295
8425
  const level = heading[1].length;
8296
8426
  const title = heading[2];
8427
+ const styledTitle = styleInlineMarkdown(title, brightness);
8297
8428
  if (level === 1) {
8298
- return `${STYLE.bold}\x1B[4m${colorSeq("accent", brightness)}${title}${STYLE.reset}`;
8429
+ return `${STYLE.bold}${colorSeq("accent", brightness)}${styledTitle}${STYLE.reset}`;
8299
8430
  }
8300
8431
  if (level === 2) {
8301
- return `${STYLE.bold}${colorSeq("warning", brightness)}${title}${STYLE.reset}`;
8432
+ return `${STYLE.bold}${colorSeq("warning", brightness)}${styledTitle}${STYLE.reset}`;
8433
+ }
8434
+ if (level === 3) {
8435
+ return `${STYLE.bold}${colorSeq("info", brightness)}${styledTitle}${STYLE.reset}`;
8302
8436
  }
8303
- return `${STYLE.bold}${colorSeq("info", brightness)}${title}${STYLE.reset}`;
8437
+ return `${STYLE.bold}${colorSeq("muted", brightness)}${styledTitle}${STYLE.reset}`;
8304
8438
  }
8305
8439
  if (line.startsWith("\u8FDB\u5165 nolo-plan")) {
8306
8440
  return `${colorSeq("chrome", brightness)}${STYLE.dim}${line}${STYLE.reset}`;
@@ -8309,15 +8443,19 @@ function styleRichMarkdownLine(line, brightness) {
8309
8443
  if (blockquote) {
8310
8444
  const border = colorSeq("chrome", brightness);
8311
8445
  const content = blockquote[1];
8312
- return `${border}\u2502${STYLE.reset} ${STYLE.dim}${content}${STYLE.reset}`;
8446
+ const styled = styleInlineMarkdown(content, brightness);
8447
+ return `${border}\u2502${STYLE.reset} ${STYLE.dim}${styled}${STYLE.reset}`;
8313
8448
  }
8314
- if (/^---+$/.test(line.trim())) {
8315
- return `${colorSeq("chrome", brightness)}${"\u2500".repeat(Math.min(line.trim().length, 40))}${STYLE.reset}`;
8449
+ if (THEMATIC_BREAK_RE.test(line)) {
8450
+ return `${colorSeq("chrome", brightness)}${STYLE.dim}${"\u2500".repeat(36)}${STYLE.reset}`;
8316
8451
  }
8317
8452
  const bullet = line.match(/^(\s*)(•)\s(.+)$/);
8318
8453
  if (bullet) {
8454
+ const indent = bullet[1];
8319
8455
  const styled = styleInlineMarkdown(bullet[3], brightness);
8320
- return `${bullet[1]}${colorSeq("accent", brightness)}\u2022${STYLE.reset} ${styled}`;
8456
+ const marker = indent.length >= 2 ? "\u25E6" : "\u2022";
8457
+ const markerColor = indent.length >= 2 ? colorSeq("chrome", brightness) : colorSeq("accent", brightness);
8458
+ return `${indent}${markerColor}${marker}${STYLE.reset} ${styled}`;
8321
8459
  }
8322
8460
  const ordered = line.match(/^(\s*)(\d+\.)\s(.+)$/);
8323
8461
  if (ordered) {
@@ -8441,16 +8579,28 @@ function emitFormattedAssistantBlock(write, text, trailingNewline = false) {
8441
8579
  }
8442
8580
  function classifyStreamLine(line) {
8443
8581
  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)) {
8582
+ const plain = plainToolLine(line);
8583
+ if (isToolTreeHeaderLine(plain)) return "tool-header";
8584
+ if (isToolTreeLeafLine(plain)) return "tool-leaf";
8585
+ if (isToolSingleLine(plain)) return "tool";
8586
+ 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
8587
  return "list";
8446
8588
  }
8589
+ if (isPolishListLikeLine(plain)) return "list";
8590
+ if (polishHeadingLevel(plain) !== null) return "heading";
8447
8591
  return "prose";
8448
8592
  }
8449
- function needsListProseBreath(prev, next) {
8593
+ function isStreamListLike(kind) {
8594
+ return kind === "list" || kind === "tool-header" || kind === "tool-leaf" || kind === "tool";
8595
+ }
8596
+ function needsListProseBreath(prev, next, prevLine = "") {
8450
8597
  if (prev === null || prev === "blank" || next === "blank") return false;
8451
- const prevList = prev === "list";
8452
- const nextList = next === "list";
8453
- return prevList !== nextList;
8598
+ if (next === "heading") return true;
8599
+ if (prev === "heading") return (polishHeadingLevel(prevLine) ?? 7) <= 2;
8600
+ if (prev === "fence" !== (next === "fence")) return true;
8601
+ if (isStreamListLike(next) && isPolishIntroLine(prevLine)) return false;
8602
+ if (prev === "tool-leaf" && next === "tool-header") return true;
8603
+ return isStreamListLike(prev) !== isStreamListLike(next);
8454
8604
  }
8455
8605
  function createRenderAwareStreamWriter(args) {
8456
8606
  const brightness = resolveTuiBrightness();
@@ -8460,9 +8610,16 @@ function createRenderAwareStreamWriter(args) {
8460
8610
  let inMermaid = false;
8461
8611
  let mermaidBody = [];
8462
8612
  let lastKind = null;
8613
+ let lastLine = "";
8614
+ let pendingBlankRow = false;
8463
8615
  const PARTIAL_FLUSH_THRESHOLD = 48;
8464
8616
  const emitBreathIfNeeded = (nextKind) => {
8465
- if (needsListProseBreath(lastKind, nextKind)) args.write("\n");
8617
+ if (pendingBlankRow) {
8618
+ args.write("\n");
8619
+ pendingBlankRow = false;
8620
+ lastKind = "blank";
8621
+ }
8622
+ if (needsListProseBreath(lastKind, nextKind, lastLine)) args.write("\n");
8466
8623
  };
8467
8624
  const flushPartialProse = () => {
8468
8625
  if (inFence || buffer.length < PARTIAL_FLUSH_THRESHOLD) return;
@@ -8480,6 +8637,7 @@ function createRenderAwareStreamWriter(args) {
8480
8637
  emitBreathIfNeeded("prose");
8481
8638
  emitFormattedAssistantBlock(args.write, prefix, false);
8482
8639
  lastKind = "prose";
8640
+ lastLine = prefix;
8483
8641
  buffer = prefix.length === buffer.length ? "" : buffer.slice(prefix.length);
8484
8642
  };
8485
8643
  const flushCompleteBlocks = () => {
@@ -8495,10 +8653,11 @@ function createRenderAwareStreamWriter(args) {
8495
8653
  inMermaid = false;
8496
8654
  inFence = false;
8497
8655
  fenceLang = "unknown";
8498
- emitBreathIfNeeded("other");
8656
+ emitBreathIfNeeded("fence");
8499
8657
  args.write(`${STYLE.dim}${firstLine}${STYLE.reset}
8500
8658
  `);
8501
- lastKind = "other";
8659
+ lastKind = "fence";
8660
+ lastLine = firstLine;
8502
8661
  buffer = lines.slice(1).join("\n");
8503
8662
  continue;
8504
8663
  }
@@ -8514,10 +8673,11 @@ function createRenderAwareStreamWriter(args) {
8514
8673
  }
8515
8674
  inFence = true;
8516
8675
  }
8517
- emitBreathIfNeeded("other");
8676
+ emitBreathIfNeeded("fence");
8518
8677
  args.write(`${STYLE.dim}${firstLine}${STYLE.reset}
8519
8678
  `);
8520
- lastKind = "other";
8679
+ lastKind = "fence";
8680
+ lastLine = firstLine;
8521
8681
  buffer = lines.slice(1).join("\n");
8522
8682
  continue;
8523
8683
  }
@@ -8529,7 +8689,8 @@ function createRenderAwareStreamWriter(args) {
8529
8689
  if (inFence) {
8530
8690
  args.write(`${highlightCodeLine(firstLine, fenceLang, brightness)}
8531
8691
  `);
8532
- lastKind = "other";
8692
+ lastKind = "fence";
8693
+ lastLine = firstLine;
8533
8694
  buffer = lines.slice(1).join("\n");
8534
8695
  continue;
8535
8696
  }
@@ -8542,6 +8703,7 @@ function createRenderAwareStreamWriter(args) {
8542
8703
  const inner = trimmedFirst.slice(2, trimmedFirst.length - 2);
8543
8704
  args.write(renderMathBlock(inner) + "\n");
8544
8705
  lastKind = "other";
8706
+ lastLine = trimmedFirst;
8545
8707
  buffer = lines.slice(1).join("\n");
8546
8708
  continue;
8547
8709
  }
@@ -8568,6 +8730,7 @@ function createRenderAwareStreamWriter(args) {
8568
8730
  if (lastInner) innerParts.push(lastInner);
8569
8731
  args.write(renderMathBlock(innerParts.join("\n")) + "\n");
8570
8732
  lastKind = "other";
8733
+ lastLine = trimmedFirst;
8571
8734
  buffer = lines.slice(closeIndex + 1).join("\n");
8572
8735
  continue;
8573
8736
  }
@@ -8588,14 +8751,23 @@ function createRenderAwareStreamWriter(args) {
8588
8751
  true
8589
8752
  );
8590
8753
  lastKind = "list";
8754
+ lastLine = lines[end - 1] ?? firstLine;
8591
8755
  buffer = lines.slice(end).join("\n");
8592
8756
  continue;
8593
8757
  }
8594
8758
  }
8595
8759
  const kind = classifyStreamLine(firstLine);
8760
+ if (kind === "blank") {
8761
+ if (lastKind !== null && lastKind !== "blank") pendingBlankRow = true;
8762
+ lastKind = "blank";
8763
+ lastLine = "";
8764
+ buffer = lines.slice(1).join("\n");
8765
+ continue;
8766
+ }
8596
8767
  emitBreathIfNeeded(kind);
8597
8768
  emitFormattedAssistantBlock(args.write, firstLine, true);
8598
8769
  lastKind = kind;
8770
+ lastLine = firstLine;
8599
8771
  buffer = lines.slice(1).join("\n");
8600
8772
  }
8601
8773
  };
@@ -9808,6 +9980,7 @@ ${this.text}
9808
9980
  // packages/cli/client/agentRunOutput.ts
9809
9981
  var IDENTITY_LABEL_SEPARATOR = " > ";
9810
9982
  var THINKING_PREVIEW_BUFFER_LIMIT = 512;
9983
+ var TUI_PROGRESS_BUFFER_LIMIT = 1200;
9811
9984
  function appendThinkingPreview(current, chunk, limit = THINKING_PREVIEW_BUFFER_LIMIT) {
9812
9985
  if (limit <= 0) return "";
9813
9986
  const combined = current + chunk;
@@ -9869,6 +10042,14 @@ function formatToolJsonEvent(event) {
9869
10042
  })}
9870
10043
  `;
9871
10044
  }
10045
+ function shouldPromoteTuiNarration(text) {
10046
+ if (text.length >= TUI_PROGRESS_BUFFER_LIMIT) return true;
10047
+ return /(^|\n)\s*(?:#{1,3}\s|```|[-*+]\s|\d+[.)]\s)/.test(text);
10048
+ }
10049
+ function narrationActivityLabel(text) {
10050
+ const oneLine = stripAnsi2(text).replace(/[`*_#>]/g, "").replace(/\s+/g, " ").trim();
10051
+ return truncateThinkingHint(oneLine, 60);
10052
+ }
9872
10053
  function createCliTurnOutput(params) {
9873
10054
  const { options } = params;
9874
10055
  const workingLabel = params.workingLabel ?? `${options.agentName} -> working`;
@@ -9877,14 +10058,36 @@ function createCliTurnOutput(params) {
9877
10058
  tuiTrees: options.output.tuiTrees === true
9878
10059
  });
9879
10060
  const eventMode = resolveAgentEventMode(options);
9880
- const showThinking = options.showThinking !== false;
10061
+ const assistantLabelManaged = options.output.assistantLabelManaged === true;
10062
+ const showThinking = !assistantLabelManaged && options.showThinking !== false;
10063
+ const hidesRoutineTuiToolDetail = (event) => {
10064
+ if (!assistantLabelManaged || event.toolName !== "editFile") return false;
10065
+ if (event.type === "tool-error") return false;
10066
+ if (readActionGate(event.metadata?.actionGate)) return false;
10067
+ if (event.metadata?.timedOut || event.metadata?.failed || event.metadata?.error) return false;
10068
+ if (typeof event.metadata?.exitCode === "number" && event.metadata.exitCode !== 0) return false;
10069
+ return true;
10070
+ };
9881
10071
  let streamedAssistantText = false;
9882
10072
  let everStreamedAnyText = false;
9883
10073
  let printedAssistantLabel = false;
9884
10074
  let thinkState = createThinkParserState();
9885
10075
  let thinkingFirstAt = null;
9886
10076
  let thinkingPreview = "";
10077
+ let tuiThinkingReported = false;
10078
+ const clearTuiThinkingLabel = () => {
10079
+ if (!tuiThinkingReported) return;
10080
+ tuiThinkingReported = false;
10081
+ options.activityReporter?.(null);
10082
+ };
9887
10083
  const markThinkingDelta = (chunk) => {
10084
+ if (assistantLabelManaged) {
10085
+ if (!tuiThinkingReported && !streamedAssistantText) {
10086
+ tuiThinkingReported = true;
10087
+ options.activityReporter?.(t("thinkingActive"));
10088
+ }
10089
+ return;
10090
+ }
9888
10091
  if (!showThinking) return;
9889
10092
  if (streamedAssistantText) return;
9890
10093
  if (thinkingFirstAt === null) {
@@ -9902,6 +10105,7 @@ function createCliTurnOutput(params) {
9902
10105
  options.activityReporter?.(label);
9903
10106
  };
9904
10107
  const endThinkingPhase = () => {
10108
+ clearTuiThinkingLabel();
9905
10109
  if (thinkingFirstAt === null) return;
9906
10110
  const seconds = Math.max(0, Math.round((Date.now() - thinkingFirstAt) / 1e3));
9907
10111
  thinkingFirstAt = null;
@@ -9914,7 +10118,6 @@ function createCliTurnOutput(params) {
9914
10118
  }
9915
10119
  };
9916
10120
  let compactionEvent = null;
9917
- const assistantLabelManaged = options.output.assistantLabelManaged === true;
9918
10121
  const writeToolOutput = (chunk) => {
9919
10122
  if (!chunk) return;
9920
10123
  if (typeof options.output.writeToolBlock === "function") {
@@ -9926,9 +10129,25 @@ function createCliTurnOutput(params) {
9926
10129
  const renderWriter = createRenderAwareStreamWriter({
9927
10130
  write: (chunk) => options.output.write(chunk)
9928
10131
  });
10132
+ let pendingTuiNarration = "";
10133
+ let tuiNarrationPromoted = false;
10134
+ const flushPendingTuiNarration = () => {
10135
+ if (!pendingTuiNarration) return;
10136
+ formatToolEvent.reset?.();
10137
+ renderWriter.push(pendingTuiNarration);
10138
+ pendingTuiNarration = "";
10139
+ tuiNarrationPromoted = true;
10140
+ streamedAssistantText = true;
10141
+ options.activityReporter?.(null);
10142
+ };
10143
+ const dropPendingTuiProgress = () => {
10144
+ pendingTuiNarration = "";
10145
+ tuiNarrationPromoted = false;
10146
+ options.activityReporter?.(null);
10147
+ };
9929
10148
  const writeVisibleAssistantChunk = (chunk) => {
9930
10149
  if (!chunk) return;
9931
- formatToolEvent.reset?.();
10150
+ if (!assistantLabelManaged) formatToolEvent.reset?.();
9932
10151
  const parsed = processThinkChunk(chunk, thinkState);
9933
10152
  thinkState = parsed.state;
9934
10153
  if (!parsed.content && !parsed.reasoning) return;
@@ -9944,8 +10163,23 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9944
10163
  }
9945
10164
  printedAssistantLabel = true;
9946
10165
  }
9947
- streamedAssistantText = true;
9948
10166
  everStreamedAnyText = true;
10167
+ if (assistantLabelManaged) {
10168
+ if (tuiNarrationPromoted) {
10169
+ renderWriter.push(parsed.content);
10170
+ streamedAssistantText = true;
10171
+ return;
10172
+ }
10173
+ pendingTuiNarration += parsed.content;
10174
+ if (shouldPromoteTuiNarration(pendingTuiNarration)) {
10175
+ flushPendingTuiNarration();
10176
+ } else {
10177
+ const label = narrationActivityLabel(pendingTuiNarration);
10178
+ if (label) options.activityReporter?.(label);
10179
+ }
10180
+ return;
10181
+ }
10182
+ streamedAssistantText = true;
9949
10183
  renderWriter.push(parsed.content);
9950
10184
  };
9951
10185
  const handleToolEvent = (event) => {
@@ -9961,13 +10195,19 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9961
10195
  return;
9962
10196
  }
9963
10197
  if (event.type === "tool-call") {
10198
+ if (assistantLabelManaged && pendingTuiNarration) {
10199
+ dropPendingTuiProgress();
10200
+ }
9964
10201
  renderWriter.flush();
9965
- formatToolEvent(event);
10202
+ if (!hidesRoutineTuiToolDetail(event)) {
10203
+ formatToolEvent(event);
10204
+ }
9966
10205
  endThinkingPhase();
9967
10206
  if (streamedAssistantText) {
9968
10207
  options.output.write("\n");
9969
10208
  streamedAssistantText = false;
9970
10209
  }
10210
+ if (assistantLabelManaged) tuiNarrationPromoted = false;
9971
10211
  const activeLabel = formatConservativeActiveToolLabel(event);
9972
10212
  spinner.show(activeLabel);
9973
10213
  options.activityReporter?.(activeLabel);
@@ -9979,6 +10219,9 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9979
10219
  }
9980
10220
  spinner.stop();
9981
10221
  options.activityReporter?.(null);
10222
+ if (hidesRoutineTuiToolDetail(event)) {
10223
+ return;
10224
+ }
9982
10225
  if (isLiveAgentRunObservation(event, parsedRunEvent)) {
9983
10226
  formatToolEvent.consume?.(event);
9984
10227
  return;
@@ -9991,6 +10234,26 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9991
10234
  return {
9992
10235
  spinner,
9993
10236
  eventMode,
10237
+ /**
10238
+ * Terminal cleanup for abort/error paths that never reach `finish()`.
10239
+ *
10240
+ * A user abort discards the transient TUI progress buffer: the user stopped
10241
+ * on purpose and the dock already showed that text as activity. A genuine
10242
+ * failure must not swallow prose that never got the chance to be *proven*
10243
+ * durable (only a following tool call proves "progress"), so it promotes the
10244
+ * pending buffer and flushes what was already promoted — otherwise a short
10245
+ * final answer followed by a transport error disappears from the transcript.
10246
+ */
10247
+ cancel(cleanup) {
10248
+ if (assistantLabelManaged && cleanup?.preservePendingNarration) {
10249
+ flushPendingTuiNarration();
10250
+ if (streamedAssistantText) {
10251
+ renderWriter.flush();
10252
+ options.output.write("\n");
10253
+ }
10254
+ }
10255
+ dropPendingTuiProgress();
10256
+ },
9994
10257
  pushText(chunk) {
9995
10258
  writeVisibleAssistantChunk(chunk);
9996
10259
  },
@@ -9998,10 +10261,6 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
9998
10261
  markThinkingDelta(chunk);
9999
10262
  },
10000
10263
  handleToolEvent,
10001
- /** 记录一条 compaction 观测事件(TUI 在 turn 结束时渲染一行 dim 摘要)。
10002
- * 一轮内可能来多条(轮开始 + 每个 round),按显著性保留最高者:
10003
- * 失败 > 新生成摘要 > 投影复用 > 跳过,避免末尾的例行跳过事件
10004
- * 覆盖掉中途真正发生的压缩。 */
10005
10264
  recordCompaction(event) {
10006
10265
  const significance = (e) => e.failed ? 4 : e.summaryGenerated ? 3 : e.compressed ? 2 : 1;
10007
10266
  if (!compactionEvent || significance(event) >= significance(compactionEvent)) {
@@ -10013,12 +10272,28 @@ ${options.agentName}${IDENTITY_LABEL_SEPARATOR}`);
10013
10272
  spinner.show(activeLabel);
10014
10273
  options.activityReporter?.(activeLabel);
10015
10274
  },
10275
+ /**
10276
+ * Pre-delta turn phase label (ctx-overflow-feedback batch 3).
10277
+ *
10278
+ * localLoop 在首个 provider delta 之前依次发出 turn-phase 事件
10279
+ * (validating-context → compacting → waiting-provider);此前 CLI 只有
10280
+ * llm-start 才进入明确 working 状态,压缩期间 spinner 停在通用
10281
+ * working 文案上,用户无法区分「卡在检查上下文 / 压缩 / 等模型」。
10282
+ * 两个显示面(bare CLI 的 spinner 与 TUI 的 dock activityReporter)与
10283
+ * showWorking 走同一条投影,保证两端文案不漂移。
10284
+ */
10285
+ showPhase(phase) {
10286
+ const label = phase === "validating-context" ? t("contextChecking") : phase === "compacting" ? t("contextCompacting") : t("waitingForModel");
10287
+ spinner.show(label);
10288
+ options.activityReporter?.(label);
10289
+ },
10016
10290
  finish(fallbackContent) {
10017
10291
  const flushedThink = flushThinkParser(thinkState);
10018
10292
  thinkState = flushedThink.state;
10019
10293
  if (flushedThink.content) {
10020
10294
  writeVisibleAssistantChunk(flushedThink.content);
10021
10295
  }
10296
+ if (assistantLabelManaged) flushPendingTuiNarration();
10022
10297
  endThinkingPhase();
10023
10298
  spinner.stop();
10024
10299
  options.activityReporter?.(null);
@@ -10123,6 +10398,7 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10123
10398
  let content = "";
10124
10399
  let dialogId;
10125
10400
  let usage;
10401
+ let sawDone = false;
10126
10402
  const handlePayload = (payload) => {
10127
10403
  if (typeof payload?.dialogId === "string" && payload.dialogId.trim()) {
10128
10404
  dialogId = payload.dialogId;
@@ -10135,6 +10411,7 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10135
10411
  }
10136
10412
  if (payload?.type === "done") {
10137
10413
  usage = payload.usage;
10414
+ sawDone = true;
10138
10415
  return;
10139
10416
  }
10140
10417
  if (payload?.type === "dialog" || payload?.type === "status") {
@@ -10188,6 +10465,9 @@ async function readStreamingAgentRun(options, res, existingSpinner) {
10188
10465
  }
10189
10466
  } catch (error) {
10190
10467
  turnOutput.spinner.stop();
10468
+ turnOutput.cancel({
10469
+ preservePendingNarration: !options.abortSignal?.aborted
10470
+ });
10191
10471
  if (options.abortSignal?.aborted) {
10192
10472
  return {
10193
10473
  exitCode: 0,
@@ -10217,6 +10497,15 @@ ${describeClientVersionTooOldFailure(message, error)}`);
10217
10497
  `);
10218
10498
  return { exitCode: 1 };
10219
10499
  }
10500
+ if (options.abortSignal?.aborted && !sawDone) {
10501
+ turnOutput.spinner.stop();
10502
+ turnOutput.cancel();
10503
+ return {
10504
+ exitCode: 0,
10505
+ ...dialogId ? { dialogId } : {},
10506
+ streamInterrupted: true
10507
+ };
10508
+ }
10220
10509
  turnOutput.finish(content);
10221
10510
  const usageText = formatUsage(usage, dialogId);
10222
10511
  if (usageText && shouldShowUsage(options.env))
@@ -10433,7 +10722,7 @@ function findCollapsedPasteSpanAt(buffer, pos, opts = {}) {
10433
10722
  // packages/cli/client/agentRun.ts
10434
10723
  import { ulid as ulid2 } from "ulid";
10435
10724
  async function loadRunLocalAgentTurn() {
10436
- const { runLocalAgentTurn } = await import("./agentRuntimeLocal-VXZSDIGT.js");
10725
+ const { runLocalAgentTurn } = await import("./agentRuntimeLocal-PITRQ2EU.js");
10437
10726
  return runLocalAgentTurn;
10438
10727
  }
10439
10728
  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();
@@ -10753,13 +11042,30 @@ function classifyLocalRunError(message) {
10753
11042
  }
10754
11043
  return { kind: "generic" };
10755
11044
  }
10756
- var HISTORY_REPLAY_REJECTION_RE = /invalid_request_error|invalid\s+tool\s+call\s+arguments?/i;
11045
+ var HISTORY_REPLAY_REJECTION_RE = /invalid\s+tool\s+call\s+arguments?/i;
11046
+ var REASONING_REPLAY_CONTRACT_RE = /reasoning_content[^.]*must be passed back/i;
10757
11047
  var RUN_UNAVAILABLE_PREFIX = "[nolo] auto runtime: local run unavailable";
10758
11048
  var NO_FALLBACK = "Not falling back to server.";
10759
11049
  var SERVER_FALLBACK_HINT = "or use --server to run on the server explicitly.";
10760
11050
  function buildAuthFailure(ctx) {
10761
11051
  const platformNoToken = ctx.where === "server chat proxy" && isAuthNoTokenBody(ctx.message);
10762
11052
  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`;
11053
+ const { url: validationUrl, text: validationText } = extractGoogleValidationLink(ctx.message);
11054
+ const validationLabel = validationText || "Verify your account";
11055
+ if (validationUrl) {
11056
+ const linkLine = `
11057
+ ${formatCliHyperlink(validationUrl, validationLabel)}`;
11058
+ const rawLine = resolveCliHyperlinkEnabled() ? `
11059
+ \u70B9\u4E0D\u4E86\u5C31\u590D\u5236\u8FD9\u884C: ${validationUrl}` : "";
11060
+ const verifyHint = `
11061
+ \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`;
11062
+ const retryLine = `
11063
+ \u9A8C\u8BC1\u5B8C\u6210\u540E\u76F4\u63A5\u91CD\u8BD5\u521A\u624D\u7684\u547D\u4EE4\u5373\u53EF\uFF0Ctoken \u4E0D\u7528\u91CD\u65B0\u767B\u5F55\u3002`;
11064
+ return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}: Google requires a one-time account verification \u2014 your credential is fine).
11065
+ Open this link in a browser signed into ${ctx.credentialAccountId ? `\`${ctx.credentialAccountId}\`` : "the Google account behind this credential"}:${linkLine}${rawLine}${verifyHint}${retryLine}
11066
+ Detail: ${ctx.message} ${NO_FALLBACK} Use --server to run on the server explicitly.
11067
+ `;
11068
+ }
10763
11069
  return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}, auth rejected). Detail: ${ctx.message} ${NO_FALLBACK} ${fix}, ${SERVER_FALLBACK_HINT}.
10764
11070
  `;
10765
11071
  }
@@ -10767,8 +11073,9 @@ function isAuthNoTokenBody(message) {
10767
11073
  return /"authCode"\s*:\s*"AUTH_NO_TOKEN"/i.test(message) || /no authentication token provided/i.test(message);
10768
11074
  }
10769
11075
  function buildRejectedPayloadFailure(ctx) {
10770
- const looksLikeHistoryReplay = HISTORY_REPLAY_REJECTION_RE.test(ctx.message);
10771
- const cause = looksLikeHistoryReplay ? ` This usually happens when the dialog history contains tool_calls or reasoning produced by a different model/provider (e.g. after /switch); the new provider rejects that history. Start a fresh dialog, or clean the offending history.` : "";
11076
+ const looksLikeReasoningReplay = REASONING_REPLAY_CONTRACT_RE.test(ctx.message);
11077
+ const looksLikeHistoryReplay = !looksLikeReasoningReplay && HISTORY_REPLAY_REJECTION_RE.test(ctx.message);
11078
+ const cause = looksLikeReasoningReplay ? ` This is a thinking-mode replay contract violation: the history contains an assistant tool-call turn without reasoning_content, but this model requires every such turn to pass reasoning back to the API. The upstream may not have returned reasoning for that turn, or the history came from a different model.` : looksLikeHistoryReplay ? ` This usually happens when the dialog history contains tool_calls or reasoning produced by a different model/provider (e.g. after /switch); the new provider rejects that history. Start a fresh dialog, or clean the offending history.` : "";
10772
11079
  return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}, the provider rejected the request body \u2014 this is NOT a local credential/config issue). Detail: ${ctx.message}${cause} ${NO_FALLBACK} Use --server to run on the server explicitly, or start a fresh dialog.
10773
11080
  `;
10774
11081
  }
@@ -10795,6 +11102,17 @@ function buildUpstreamFailure(ctx) {
10795
11102
  return `${RUN_UNAVAILABLE_PREFIX} (${ctx.where} returned HTTP ${ctx.status}). Detail: ${ctx.message} ${NO_FALLBACK} ${fix}, ${SERVER_FALLBACK_HINT}.
10796
11103
  `;
10797
11104
  }
11105
+ function formatLocalTurnFailureLine(error) {
11106
+ const message = toErrorMessage(error);
11107
+ if (error?.code === "LLM_REQUEST_TIMEOUT") {
11108
+ const msMatch = /after (\d+)ms/.exec(message);
11109
+ const deadline = msMatch && Number.isFinite(Number(msMatch[1])) ? formatElapsed(Math.round(Number(msMatch[1]) / 1e3)) : "the configured window";
11110
+ return `[nolo] ${t("llmRequestTimedOut", deadline)}
11111
+ `;
11112
+ }
11113
+ return `[nolo] Local agent run failed: ${message}
11114
+ `;
11115
+ }
10798
11116
  var FAILURE_BUILDERS = {
10799
11117
  auth: buildAuthFailure,
10800
11118
  "rejected-payload": buildRejectedPayloadFailure,
@@ -10803,6 +11121,7 @@ var FAILURE_BUILDERS = {
10803
11121
  upstream: buildUpstreamFailure
10804
11122
  };
10805
11123
  function describeLocalRunFailure(message, rawError) {
11124
+ const credentialAccountId = rawError && typeof rawError === "object" && typeof rawError.credentialAccountId === "string" ? rawError.credentialAccountId.trim() || void 0 : void 0;
10806
11125
  if (rawError && typeof rawError === "object" && "code" in rawError && rawError.code === "PLATFORM_STREAM_INTERRUPTED") {
10807
11126
  return "[nolo] The platform LLM stream was interrupted before the turn completed. Your conversation was preserved. Send another message to continue.\n";
10808
11127
  }
@@ -10851,6 +11170,10 @@ function describeLocalRunFailure(message, rawError) {
10851
11170
  }
10852
11171
  if (/CLI authority broker could not attach or take ownership/i.test(message)) {
10853
11172
  const cleaned = stripDebugNoise(message);
11173
+ if (/EADDRINUSE/i.test(message)) {
11174
+ return `${RUN_UNAVAILABLE_PREFIX} (${cleaned}). ${NO_FALLBACK} Use --server to run on the server explicitly.
11175
+ `;
11176
+ }
10854
11177
  return `${RUN_UNAVAILABLE_PREFIX} (${cleaned}). ${NO_FALLBACK} The local runtime could not attach to an existing broker or take database ownership. Check running broker processes holding the local authority store or retry, ${SERVER_FALLBACK_HINT}.
10855
11178
  `;
10856
11179
  }
@@ -10880,7 +11203,8 @@ function describeLocalRunFailure(message, rawError) {
10880
11203
  status: cls.status,
10881
11204
  ...cls.statusInferred ? { statusInferred: true } : {},
10882
11205
  ...cls.quotaExhausted ? { quotaExhausted: true } : {},
10883
- ...cooldownUntil ? { cooldownUntil } : {}
11206
+ ...cooldownUntil ? { cooldownUntil } : {},
11207
+ ...credentialAccountId ? { credentialAccountId } : {}
10884
11208
  };
10885
11209
  return FAILURE_BUILDERS[cls.kind](ctx);
10886
11210
  }
@@ -11197,6 +11521,18 @@ async function runLocalAgentTurnForCli(options, settings) {
11197
11521
  if (event.kind === "llm-start") {
11198
11522
  turnOutput.showWorking();
11199
11523
  }
11524
+ if (event.kind === "turn-phase") {
11525
+ turnOutput.showPhase(event.phase);
11526
+ }
11527
+ if (event.kind === "compaction-start") {
11528
+ turnOutput.showPhase("compacting");
11529
+ }
11530
+ if (event.kind === "compaction-end" || // 压缩失败(timeout/provider-error)时 localLoop 按失败原子性语义
11531
+ // 带着裁剪后的历史继续本轮,切回等待模型文案;aborted 时 turn 随即
11532
+ // 结束,不再切文案(终态由 abort 路径收尾)。
11533
+ event.kind === "compaction-failed" && event.reason !== "aborted") {
11534
+ turnOutput.showPhase("waiting-provider");
11535
+ }
11200
11536
  if (event.kind === "image-downgraded") {
11201
11537
  options.output.write(
11202
11538
  "[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 +11578,9 @@ async function runLocalAgentTurnForCli(options, settings) {
11242
11578
  };
11243
11579
  } catch (error) {
11244
11580
  turnOutput.spinner.stop();
11581
+ turnOutput.cancel({
11582
+ preservePendingNarration: error?.code !== LOCAL_TURN_ABORTED_CODE && !options.abortSignal?.aborted
11583
+ });
11245
11584
  const savedDialogId = error?.dialogId;
11246
11585
  const abortedUsageRecords = error?.usageRecords;
11247
11586
  const abortedTurnCredits = sumPlatformCredits(abortedUsageRecords);
@@ -11265,10 +11604,12 @@ async function runLocalAgentTurnForCli(options, settings) {
11265
11604
  error.cooldownUntil = cooldownUntil;
11266
11605
  }
11267
11606
  if (settings.reportFailure) {
11268
- options.output.write(
11269
- `[nolo] Local agent run failed: ${toErrorMessage(error)}
11270
- `
11271
- );
11607
+ const failureLine = formatLocalTurnFailureLine(error);
11608
+ if (typeof options.output.writeErr === "function") {
11609
+ options.output.writeErr(failureLine);
11610
+ } else {
11611
+ options.output.write(failureLine);
11612
+ }
11272
11613
  if (cooldownUntil) {
11273
11614
  options.output.write(
11274
11615
  `[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 +11747,7 @@ async function runAgentTurn(options) {
11406
11747
  return { exitCode: 1 };
11407
11748
  }
11408
11749
  const localAvailability = await checkLocalAvailabilityBeforeHttpDispatch(options);
11409
- if (localAvailability?.exitCode) {
11750
+ if (localAvailability && "exitCode" in localAvailability) {
11410
11751
  return { exitCode: localAvailability.exitCode };
11411
11752
  }
11412
11753
  const httpResult = await runHttpAgentTurn(options, authToken);
@@ -12148,72 +12489,6 @@ var rankMemoryCandidates = (items, query, context) => {
12148
12489
  });
12149
12490
  };
12150
12491
 
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
12492
  // packages/ai/memory/vnext/recall.ts
12218
12493
  var MAX_RECALL_REFS = 6;
12219
12494
  var stripFence = (raw) => {
@@ -12243,14 +12518,6 @@ var parseSelection = (raw) => {
12243
12518
  reason: obj.reason
12244
12519
  };
12245
12520
  };
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
12521
  var catalogText = (entities, states) => JSON.stringify(
12255
12522
  {
12256
12523
  entities: entities.map((entity) => ({
@@ -12276,7 +12543,7 @@ var catalogText = (entities, states) => JSON.stringify(
12276
12543
  );
12277
12544
  var createMemoryVNextRecall = (input) => async (query) => {
12278
12545
  const startedAt = performance.now();
12279
- const { entities, states } = await buildCatalog(input.db, input.ownerId);
12546
+ const { entities, states } = await loadMemoryVNextCatalog(input.db, input.ownerId);
12280
12547
  if (entities.length === 0 && states.length === 0) {
12281
12548
  return {
12282
12549
  query,
@@ -13147,14 +13414,74 @@ var shortError2 = (error) => {
13147
13414
  return message.length > ERROR_MESSAGE_MAX2 ? `${message.slice(0, ERROR_MESSAGE_MAX2)}\u2026` : message;
13148
13415
  };
13149
13416
  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
13417
+ const { entities, states } = await loadMemoryVNextCatalog(db, ownerId);
13418
+ return { entityIds: entities.map((entity) => entity.id), states };
13419
+ };
13420
+ var currentStatesCitingEvidence = (states, evidenceId) => states.filter((state2) => !state2.retiredAt && (state2.evidenceIds ?? []).includes(evidenceId));
13421
+ var isEvidenceCoveredByCurrentStates = (states, evidenceId) => currentStatesCitingEvidence(states, evidenceId).length > 0;
13422
+ var memoryVNextContextFingerprint = (existing) => {
13423
+ const states = existing.states ?? [];
13424
+ const entityIds = existing.entityIds ?? [];
13425
+ const canonical = [
13426
+ ...entityIds.map((id) => `e\0${id}`),
13427
+ ...states.map((state2) => `s\0${state2.id}\0${state2.updatedAt}\0${state2.retiredAt ?? ""}`)
13428
+ ].sort().join("");
13429
+ let hash = 2166136261;
13430
+ for (let i = 0; i < canonical.length; i++) {
13431
+ hash ^= canonical.charCodeAt(i);
13432
+ hash = Math.imul(hash, 16777619);
13433
+ }
13434
+ return `${entityIds.length}.${states.length}:${(hash >>> 0).toString(16)}`;
13435
+ };
13436
+ var MAX_NOOP_SUPPRESSIONS = 512;
13437
+ var noOpSuppressions = /* @__PURE__ */ new Map();
13438
+ var suppressionKey = (ownerId, evidenceId) => `${ownerId}\0${evidenceId}`;
13439
+ var recordNoOpSuppression = (ownerId, evidenceId, fingerprint) => {
13440
+ const key = suppressionKey(ownerId, evidenceId);
13441
+ noOpSuppressions.delete(key);
13442
+ noOpSuppressions.set(key, fingerprint);
13443
+ while (noOpSuppressions.size > MAX_NOOP_SUPPRESSIONS) {
13444
+ noOpSuppressions.delete(noOpSuppressions.keys().next().value);
13445
+ }
13446
+ };
13447
+ var noOpHistory = (ownerId, evidenceId, fingerprint) => {
13448
+ const recorded = noOpSuppressions.get(suppressionKey(ownerId, evidenceId));
13449
+ if (recorded === void 0) return "fresh";
13450
+ return recorded === fingerprint ? "suppressed" : "stale";
13451
+ };
13452
+ var pickFirstUncoveredLazyPromotionItem = async (db, selected) => {
13453
+ const contextByOwner = /* @__PURE__ */ new Map();
13454
+ const contextFor = (ownerId) => {
13455
+ let pending = contextByOwner.get(ownerId);
13456
+ if (!pending) {
13457
+ pending = loadExistingContext(db, ownerId).then((existing) => ({
13458
+ states: existing.states ?? [],
13459
+ fingerprint: memoryVNextContextFingerprint(existing)
13460
+ }));
13461
+ contextByOwner.set(ownerId, pending);
13462
+ }
13463
+ return pending;
13157
13464
  };
13465
+ let skippedCoveredCount = 0;
13466
+ let skippedNoOpCount = 0;
13467
+ let firstStale = null;
13468
+ for (const [selectedIndex, item] of selected.entries()) {
13469
+ const evidence = buildLegacyMemoryEvidence(item);
13470
+ const context = await contextFor(evidence.ownerId);
13471
+ if (isEvidenceCoveredByCurrentStates(context.states, evidence.id)) {
13472
+ skippedCoveredCount++;
13473
+ continue;
13474
+ }
13475
+ const history = noOpHistory(evidence.ownerId, evidence.id, context.fingerprint);
13476
+ if (history === "fresh") {
13477
+ return { item, selectedIndex, skippedCoveredCount, skippedNoOpCount };
13478
+ }
13479
+ if (history === "stale" && !firstStale) {
13480
+ firstStale = { item, selectedIndex, skippedCoveredCount, skippedNoOpCount };
13481
+ }
13482
+ skippedNoOpCount++;
13483
+ }
13484
+ return firstStale;
13158
13485
  };
13159
13486
  var withoutImportedEvidence = (mutation, importedEvidenceId) => ({
13160
13487
  ...mutation,
@@ -13170,6 +13497,11 @@ var runMemoryVNextLazyPromotion = async (input) => {
13170
13497
  }));
13171
13498
  const finish = (partial) => {
13172
13499
  const observation = {
13500
+ legacyItemId: input.item.id,
13501
+ evidenceId: deterministicEvidence.id,
13502
+ ...input.selectedIndex === void 0 ? {} : { selectedIndex: input.selectedIndex },
13503
+ ...input.skippedCoveredCount === void 0 ? {} : { skippedCoveredCount: input.skippedCoveredCount },
13504
+ ...input.skippedNoOpCount === void 0 ? {} : { skippedNoOpCount: input.skippedNoOpCount },
13173
13505
  ...partial,
13174
13506
  latencyMs: Math.round((clock() - startedAt) * 10) / 10
13175
13507
  };
@@ -13192,8 +13524,9 @@ var runMemoryVNextLazyPromotion = async (input) => {
13192
13524
  }
13193
13525
  const evidence = evidenceResult.evidence;
13194
13526
  const existing = await loadExistingContext(input.db, evidence.ownerId);
13195
- const alreadyCovered = (existing.states ?? []).some(
13196
- (state2) => !state2.retiredAt && state2.evidenceIds.includes(evidence.id)
13527
+ const alreadyCovered = isEvidenceCoveredByCurrentStates(
13528
+ existing.states ?? [],
13529
+ evidence.id
13197
13530
  );
13198
13531
  if (alreadyCovered) {
13199
13532
  return finish({ status: "already_covered" });
@@ -13208,6 +13541,11 @@ var runMemoryVNextLazyPromotion = async (input) => {
13208
13541
  });
13209
13542
  const semanticMutation = withoutImportedEvidence(interpreted.mutation, evidence.id);
13210
13543
  if (!hasWrites(semanticMutation)) {
13544
+ recordNoOpSuppression(
13545
+ evidence.ownerId,
13546
+ evidence.id,
13547
+ memoryVNextContextFingerprint(existing)
13548
+ );
13211
13549
  return finish({ status: "no_op", action: semanticMutation.action });
13212
13550
  }
13213
13551
  await applyMemoryInterpreterMutation(input.db, evidence.ownerId, semanticMutation);
@@ -13220,6 +13558,179 @@ var runMemoryVNextLazyPromotion = async (input) => {
13220
13558
  };
13221
13559
  var isMemoryVNextLazyPromotionEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_LAZY_PROMOTION === "1" || env.NOLO_MEMORY_VNEXT_LAZY_PROMOTION === "true";
13222
13560
 
13561
+ // packages/ai/memory/vnext/pureReadGate.ts
13562
+ var isMemoryVNextPureReadEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_PURE_READ === "1" || env.NOLO_MEMORY_VNEXT_PURE_READ === "true";
13563
+
13564
+ // packages/ai/memory/vnext/localRecall.ts
13565
+ var MIN_SHARED_TOKENS = 2;
13566
+ var MAX_LOCAL_RECALL_STATES = 8;
13567
+ var SAFE_TECHNICAL_SYNONYMS = {
13568
+ pr: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5", "diff"],
13569
+ diff: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5"],
13570
+ review: ["\u5BA1\u67E5", "\u4EE3\u7801\u5BA1\u67E5"],
13571
+ deploy: ["\u90E8\u7F72", "\u53D1\u7248"],
13572
+ release: ["\u53D1\u7248", "\u53D1\u5E03"],
13573
+ desktop: ["\u684C\u9762", "\u684C\u9762\u7AEF"]
13574
+ };
13575
+ var distinctTokens = (text) => new Set(tokenize2(text).filter((token) => token.length >= 2));
13576
+ var recallMemoryVNextLocal = (input) => {
13577
+ const rawTokens = distinctTokens(input.query);
13578
+ if (rawTokens.size === 0) return [];
13579
+ const queryTokens = new Set(rawTokens);
13580
+ for (const token of rawTokens) {
13581
+ const syns = SAFE_TECHNICAL_SYNONYMS[token.toLowerCase()];
13582
+ if (syns) {
13583
+ for (const syn of syns) {
13584
+ for (const t2 of distinctTokens(syn)) queryTokens.add(t2);
13585
+ }
13586
+ }
13587
+ }
13588
+ const entityById = new Map(input.entities.map((entity) => [entity.id, entity]));
13589
+ const hits = [];
13590
+ for (const state2 of input.states) {
13591
+ if (state2.retiredAt || !state2.text.trim()) continue;
13592
+ const entity = entityById.get(state2.entityId);
13593
+ const haystack = distinctTokens(
13594
+ [state2.facet, state2.text, entity?.name ?? "", ...entity?.aliases ?? []].join(" ")
13595
+ );
13596
+ let sharedTokens = 0;
13597
+ for (const token of queryTokens) if (haystack.has(token)) sharedTokens++;
13598
+ if (sharedTokens >= MIN_SHARED_TOKENS) hits.push({ state: state2, sharedTokens });
13599
+ }
13600
+ return hits.sort((a, b) => b.sharedTokens - a.sharedTokens || a.state.id.localeCompare(b.state.id)).slice(0, input.limit ?? MAX_LOCAL_RECALL_STATES);
13601
+ };
13602
+
13603
+ // packages/ai/memory/vnext/pureVNextRuntime.ts
13604
+ var buildSynthesizedStateItem = (state2, entity, ownerType, ownerId) => ({
13605
+ id: `vnext-state-${state2.id}`,
13606
+ ownerType,
13607
+ ownerId,
13608
+ visibility: "private",
13609
+ subjectType: "user",
13610
+ subjectId: ownerId,
13611
+ kind: "semantic",
13612
+ content: state2.text.trim(),
13613
+ createdAt: state2.createdAt,
13614
+ lastActivatedAt: state2.createdAt,
13615
+ activationCount: 1,
13616
+ importance: 0.9,
13617
+ confidence: 0.9,
13618
+ resident: state2.facet === "preference" || state2.facet === "style"
13619
+ });
13620
+ async function resolvePureVNextRuntime(input) {
13621
+ const { db, owners, userInput } = input;
13622
+ if (owners.length === 0 || !userInput.trim()) {
13623
+ return { selectedItems: [], promptBlock: null, recalledStateCount: 0 };
13624
+ }
13625
+ const ownerIds = owners.map((o) => `${o.ownerType}:${encodeURIComponent(o.ownerId)}`);
13626
+ const catalogs = await Promise.all(
13627
+ ownerIds.map((ownerId) => loadMemoryVNextCatalog(db, ownerId))
13628
+ );
13629
+ const selectedItems = [];
13630
+ const seenStateKeys = /* @__PURE__ */ new Set();
13631
+ for (let i = 0; i < owners.length; i++) {
13632
+ const owner = owners[i];
13633
+ const catalog = catalogs[i];
13634
+ const currentStates = catalog.states.filter((s) => !s.retiredAt && s.text.trim());
13635
+ const hits = recallMemoryVNextLocal({
13636
+ query: userInput,
13637
+ entities: catalog.entities,
13638
+ states: currentStates
13639
+ });
13640
+ const entityById = new Map(catalog.entities.map((e) => [e.id, e]));
13641
+ for (const hit of hits) {
13642
+ const stateKey = `${hit.state.ownerId}\0${hit.state.id}`;
13643
+ if (seenStateKeys.has(stateKey)) continue;
13644
+ seenStateKeys.add(stateKey);
13645
+ selectedItems.push(
13646
+ buildSynthesizedStateItem(hit.state, entityById.get(hit.state.entityId), owner.ownerType, owner.ownerId)
13647
+ );
13648
+ }
13649
+ }
13650
+ const promptBlock = selectedItems.length === 0 ? null : buildMemoryOverlay(selectedItems, {
13651
+ maxTokens: input.maxTokens ?? DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET
13652
+ });
13653
+ return {
13654
+ selectedItems,
13655
+ promptBlock,
13656
+ recalledStateCount: selectedItems.length
13657
+ };
13658
+ }
13659
+
13660
+ // packages/ai/memory/vnext/primaryRead.ts
13661
+ var MEMORY_VNEXT_PRIMARY_READ_TIMEOUT_MS = 300;
13662
+ var isMemoryVNextPrimaryReadEnabled = (env = typeof process !== "undefined" ? process.env : {}) => env.NOLO_MEMORY_VNEXT_PRIMARY_READ === "1" || env.NOLO_MEMORY_VNEXT_PRIMARY_READ === "true";
13663
+ var buildSynthesizedStateItem2 = (state2, entity, ownerType, ownerId) => ({
13664
+ id: `vnext-state-${state2.id}`,
13665
+ ownerType,
13666
+ ownerId,
13667
+ visibility: "private",
13668
+ subjectType: "user",
13669
+ subjectId: ownerId,
13670
+ kind: "semantic",
13671
+ content: state2.text.trim(),
13672
+ createdAt: state2.createdAt,
13673
+ importance: 0.9,
13674
+ confidence: 0.9,
13675
+ // Flag resident preferences so they flow into overlay's resident section.
13676
+ resident: state2.facet === "preference" || state2.facet === "style",
13677
+ lastActivatedAt: state2.createdAt,
13678
+ activationCount: 1
13679
+ });
13680
+ var resolveMemoryVNextM4Selection = async (input) => {
13681
+ const { db, owners, query, selected } = input;
13682
+ const ownerIds = owners.map((o) => `${o.ownerType}:${encodeURIComponent(o.ownerId)}`);
13683
+ const catalogs = new Map(
13684
+ await Promise.all(
13685
+ ownerIds.map(async (ownerId) => [
13686
+ ownerId,
13687
+ await loadMemoryVNextCatalog(db, ownerId)
13688
+ ])
13689
+ )
13690
+ );
13691
+ const recalledStates = [];
13692
+ const recalledStateIds = /* @__PURE__ */ new Set();
13693
+ for (const owner of owners) {
13694
+ const principalId = `${owner.ownerType}:${encodeURIComponent(owner.ownerId)}`;
13695
+ const catalog = catalogs.get(principalId);
13696
+ if (!catalog) continue;
13697
+ const currentStates = catalog.states.filter((s) => !s.retiredAt && s.text.trim());
13698
+ const hits = recallMemoryVNextLocal({
13699
+ query,
13700
+ entities: catalog.entities,
13701
+ states: currentStates
13702
+ });
13703
+ const entityById = new Map(catalog.entities.map((e) => [e.id, e]));
13704
+ for (const hit of hits) {
13705
+ if (recalledStateIds.has(hit.state.id)) continue;
13706
+ recalledStateIds.add(hit.state.id);
13707
+ recalledStates.push(
13708
+ buildSynthesizedStateItem2(hit.state, entityById.get(hit.state.entityId), owner.ownerType, owner.ownerId)
13709
+ );
13710
+ }
13711
+ }
13712
+ const uncoveredLegacy = [];
13713
+ let coveredSuppressedCount = 0;
13714
+ for (const item of selected) {
13715
+ const evidence = buildLegacyMemoryEvidence(item);
13716
+ const catalog = catalogs.get(evidence.ownerId);
13717
+ const states = catalog?.states ?? [];
13718
+ const covering = currentStatesCitingEvidence(states, evidence.id);
13719
+ if (covering.length > 0) {
13720
+ coveredSuppressedCount++;
13721
+ } else {
13722
+ uncoveredLegacy.push(item);
13723
+ }
13724
+ }
13725
+ const renderItems = [...recalledStates, ...uncoveredLegacy];
13726
+ return {
13727
+ renderItems,
13728
+ recalledStateCount: recalledStates.length,
13729
+ uncoveredLegacyCount: uncoveredLegacy.length,
13730
+ coveredSuppressedCount
13731
+ };
13732
+ };
13733
+
13223
13734
  // packages/ai/memory/runtime.ts
13224
13735
  var COLD_STORAGE_CONFIDENCE = 0.3;
13225
13736
  var MEMORY_OVERLAY_TOKEN_BUDGET = DEFAULT_MEMORY_OVERLAY_TOKEN_BUDGET;
@@ -13342,6 +13853,18 @@ var resolveMemoryRuntime = async (input) => {
13342
13853
  if (owners.length === 0) {
13343
13854
  return { selectedItems: [], promptBlock: null };
13344
13855
  }
13856
+ if (isMemoryVNextPureReadEnabled()) {
13857
+ const pure = await resolvePureVNextRuntime({
13858
+ db: input.db,
13859
+ owners,
13860
+ userInput: input.userInput,
13861
+ maxTokens: MEMORY_OVERLAY_TOKEN_BUDGET
13862
+ });
13863
+ return {
13864
+ selectedItems: pure.selectedItems,
13865
+ promptBlock: pure.promptBlock
13866
+ };
13867
+ }
13345
13868
  const policy = resolveAgentMemoryPolicy({ agentKey: input.agentKey });
13346
13869
  const legacyStartedAt = performance.now();
13347
13870
  const candidates = await loadMemoryCandidatesFromDb(input.db, {
@@ -13371,10 +13894,62 @@ var resolveMemoryRuntime = async (input) => {
13371
13894
  );
13372
13895
  const selected = [...residentItems, ...ranked];
13373
13896
  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();
13897
+ const renderOverlay = (items) => items.length === 0 ? null : buildMemoryOverlay(items, { maxTokens: MEMORY_OVERLAY_TOKEN_BUDGET });
13898
+ let promptBlock = renderOverlay(selected);
13899
+ const primaryRead = isMemoryVNextPrimaryReadEnabled();
13900
+ let allCoveredByVNext = false;
13901
+ if (primaryRead) {
13902
+ const emitPrimary = (observation) => {
13903
+ try {
13904
+ (input.primaryReadEmit ?? ((o) => console.info("[memory] vnext primary read", { event: "memory_vnext_primary_read", ...o })))(observation);
13905
+ } catch {
13906
+ }
13907
+ };
13908
+ const base = { legacyHitCount: selected.length, legacyLatencyMs };
13909
+ const vnextStartedAt = performance.now();
13910
+ const vnextLatency = () => Math.round((performance.now() - vnextStartedAt) * 10) / 10;
13911
+ if (selected.length === 0) {
13912
+ emitPrimary({ ...base, source: "none" });
13913
+ } else {
13914
+ try {
13915
+ let timer;
13916
+ const m4 = await Promise.race([
13917
+ resolveMemoryVNextM4Selection({ db: input.db, owners, query: input.userInput, selected }),
13918
+ new Promise((_, reject) => {
13919
+ timer = setTimeout(
13920
+ () => reject(Object.assign(new Error("timeout"), { name: "TimeoutError" })),
13921
+ MEMORY_VNEXT_PRIMARY_READ_TIMEOUT_MS
13922
+ );
13923
+ })
13924
+ ]).finally(() => clearTimeout(timer));
13925
+ promptBlock = renderOverlay(m4.renderItems);
13926
+ allCoveredByVNext = m4.uncoveredLegacyCount === 0 && m4.recalledStateCount > 0;
13927
+ const source = m4.recalledStateCount > 0 ? m4.uncoveredLegacyCount === 0 ? "vnext" : "hybrid" : m4.uncoveredLegacyCount > 0 ? "legacy_fallback" : "none";
13928
+ emitPrimary({
13929
+ ...base,
13930
+ source,
13931
+ uncoveredLegacyCount: m4.uncoveredLegacyCount,
13932
+ coveredSuppressedCount: m4.coveredSuppressedCount,
13933
+ recalledStateCount: m4.recalledStateCount,
13934
+ vnextLatencyMs: vnextLatency(),
13935
+ contextChars: promptBlock?.length ?? 0,
13936
+ ...source === "legacy_fallback" ? { fallbackReason: "no_vnext_context" } : {}
13937
+ });
13938
+ } catch (error) {
13939
+ emitPrimary({
13940
+ ...base,
13941
+ source: "legacy_fallback",
13942
+ vnextLatencyMs: vnextLatency(),
13943
+ contextChars: promptBlock?.length ?? 0,
13944
+ fallbackReason: "vnext_error",
13945
+ error: error instanceof Error ? error.name : "UnknownError"
13946
+ });
13947
+ }
13948
+ }
13949
+ }
13950
+ const shadowEnabled = !primaryRead && input.vNextShadowProvider != null && isMemoryVNextShadowReadEnabled();
13376
13951
  if (shadowEnabled) {
13377
- await runMemoryVNextShadowRead({
13952
+ void runMemoryVNextShadowRead({
13378
13953
  ctx: {
13379
13954
  db: input.db,
13380
13955
  owners,
@@ -13384,17 +13959,28 @@ var resolveMemoryRuntime = async (input) => {
13384
13959
  legacyItems: selected,
13385
13960
  legacyLatencyMs,
13386
13961
  legacyContextChars: promptBlock?.length ?? 0
13962
+ }).catch(() => {
13387
13963
  });
13388
13964
  }
13389
- const promotionCandidate = selected[0];
13390
13965
  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(() => {
13966
+ if (lazyPromotionEnabled && selected.length > 0 && !allCoveredByVNext) {
13967
+ void (async () => {
13968
+ const promotionPick = await pickFirstUncoveredLazyPromotionItem(
13969
+ input.db,
13970
+ selected
13971
+ );
13972
+ if (promotionPick) {
13973
+ await runMemoryVNextLazyPromotion({
13974
+ db: input.db,
13975
+ item: promotionPick.item,
13976
+ selectedIndex: promotionPick.selectedIndex,
13977
+ skippedCoveredCount: promotionPick.skippedCoveredCount,
13978
+ skippedNoOpCount: promotionPick.skippedNoOpCount,
13979
+ provider: input.vNextShadowProvider,
13980
+ ...input.lazyPromotionEmit ? { emit: input.lazyPromotionEmit } : {}
13981
+ });
13982
+ }
13983
+ })().catch(() => {
13398
13984
  });
13399
13985
  }
13400
13986
  if (selected.length === 0) {
@@ -13408,6 +13994,52 @@ var resolveMemoryRuntime = async (input) => {
13408
13994
  };
13409
13995
 
13410
13996
  // packages/cli/memoryRecall.ts
13997
+ var logger = getLogger("cli.memoryRecall");
13998
+ var DEDUP_WINDOW_MS = 5 * 60 * 1e3;
13999
+ var DEDUP_MAX_KEYS = 100;
14000
+ var dedupMap = /* @__PURE__ */ new Map();
14001
+ function evictDedupIfNeeded() {
14002
+ if (dedupMap.size < DEDUP_MAX_KEYS) return;
14003
+ let oldestKey = null;
14004
+ let oldestTs = Infinity;
14005
+ for (const [k, v] of dedupMap) {
14006
+ if (v.lastLog < oldestTs) {
14007
+ oldestTs = v.lastLog;
14008
+ oldestKey = k;
14009
+ }
14010
+ }
14011
+ if (oldestKey !== null) dedupMap.delete(oldestKey);
14012
+ }
14013
+ function logDeduped(level, fingerprint, message, error) {
14014
+ const now = Date.now();
14015
+ const entry = dedupMap.get(fingerprint);
14016
+ if (!entry) {
14017
+ evictDedupIfNeeded();
14018
+ dedupMap.set(fingerprint, { count: 1, suppressed: 0, lastLog: now });
14019
+ if (error !== void 0) logger[level](message, error);
14020
+ else logger[level](message);
14021
+ return;
14022
+ }
14023
+ entry.count += 1;
14024
+ if (now - entry.lastLog >= DEDUP_WINDOW_MS) {
14025
+ const suppressed = entry.suppressed;
14026
+ const summary = `${message} (deduplicated: ${entry.count} occurrences, ${suppressed} suppressed over ${Math.round((now - entry.lastLog) / 1e3)}s)`;
14027
+ if (error !== void 0) logger[level](summary, error);
14028
+ else logger[level](summary);
14029
+ entry.count = 1;
14030
+ entry.suppressed = 0;
14031
+ entry.lastLog = now;
14032
+ } else {
14033
+ entry.suppressed += 1;
14034
+ }
14035
+ }
14036
+ function fingerprintFor(kind, detail) {
14037
+ const d = detail === void 0 ? "" : sanitizeFp(String(detail));
14038
+ return `mem-${kind}:${d}`;
14039
+ }
14040
+ function sanitizeFp(s) {
14041
+ return s.replace(/\s+/g, " ").slice(0, 80);
14042
+ }
13411
14043
  var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceId) => {
13412
14044
  try {
13413
14045
  const response = await fetch(`${serverUrl}/api/memory/query`, {
@@ -13424,10 +14056,10 @@ var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceI
13424
14056
  signal: AbortSignal.timeout(5e3)
13425
14057
  });
13426
14058
  if (!response.ok) {
13427
- console.warn(
13428
- "[cli-memory] remote query returned non-ok status:",
13429
- response.status,
13430
- "\u2014 falling back to local"
14059
+ logDeduped(
14060
+ "warn",
14061
+ fingerprintFor("remote-nonok", response.status),
14062
+ `remote query returned non-ok status ${response.status} \u2014 falling back to local`
13431
14063
  );
13432
14064
  return null;
13433
14065
  }
@@ -13435,7 +14067,12 @@ var queryRemoteMemory = async (serverUrl, authToken, agentKey, userInput, spaceI
13435
14067
  const block = typeof payload?.promptBlock === "string" ? payload.promptBlock.trim() : "";
13436
14068
  return block || null;
13437
14069
  } catch (error) {
13438
- console.warn("[cli-memory] remote query failed, falling back to local:", error);
14070
+ logDeduped(
14071
+ "info",
14072
+ fingerprintFor("remote-failed", error instanceof Error ? error.name : void 0),
14073
+ "remote query failed, falling back to local",
14074
+ normalizeError(error)
14075
+ );
13439
14076
  return null;
13440
14077
  }
13441
14078
  };
@@ -13471,7 +14108,12 @@ var resolveCliMemory = async (input) => {
13471
14108
  input.spaceId
13472
14109
  );
13473
14110
  } catch (error) {
13474
- console.warn("[cli-memory] local recall failed, omitting memory layer:", error);
14111
+ logDeduped(
14112
+ "warn",
14113
+ fingerprintFor("local-failed", error instanceof Error ? error.name : void 0),
14114
+ "local recall failed, omitting memory layer",
14115
+ normalizeError(error)
14116
+ );
13475
14117
  return null;
13476
14118
  }
13477
14119
  };
@@ -13526,7 +14168,10 @@ async function resolveAgentRunAgentKey(args) {
13526
14168
  }
13527
14169
  async function runAgentRunCommand(args, deps) {
13528
14170
  const env = deps.env ?? process.env;
13529
- const output = deps.output ?? process.stdout;
14171
+ const output = deps.output ?? {
14172
+ write: (chunk) => process.stdout.write(chunk),
14173
+ writeErr: (chunk) => process.stderr.write(chunk)
14174
+ };
13530
14175
  if (args.includes("--help") || args.includes("-h")) {
13531
14176
  writeUsage(output, deps.commandPath);
13532
14177
  return 0;
@@ -14068,12 +14713,6 @@ function isBalanceExhaustedError(error) {
14068
14713
  }
14069
14714
 
14070
14715
  export {
14071
- resolveAgentModelIdentity,
14072
- resolveAgentContextWindow,
14073
- platformCreditsFromUsage,
14074
- formatCreditsChip,
14075
- formatTokenCount,
14076
- renderTokenStatus,
14077
14716
  resolveCliColorEnabled,
14078
14717
  dimCliText,
14079
14718
  ANSI_ESCAPE_REGEX,
@@ -14114,6 +14753,12 @@ export {
14114
14753
  formatAssistantDisplay,
14115
14754
  redactSecrets,
14116
14755
  TUI_TREE_MARKER,
14756
+ resolveAgentModelIdentity,
14757
+ resolveAgentContextWindow,
14758
+ platformCreditsFromUsage,
14759
+ formatCreditsChip,
14760
+ formatTokenCount,
14761
+ renderTokenStatus,
14117
14762
  COLLAPSED_PASTE_PLACEHOLDER_RE,
14118
14763
  shouldCollapsePaste,
14119
14764
  createCollapsedPasteStore,
@@ -14125,14 +14770,14 @@ export {
14125
14770
  expandRangeToCollapsedPasteChips,
14126
14771
  findCollapsedPasteSpanAt,
14127
14772
  runAgentTurn,
14128
- readAgentsMdLayerFromDisk,
14129
14773
  resolveWorkflowReference,
14130
14774
  resolveSkillReference,
14131
14775
  buildSkillContextBlocks,
14132
14776
  prependSubjectDialogMarker,
14133
14777
  normalizeCliImageInput,
14134
- inspectLocalRunWorkspace,
14778
+ readAgentsMdLayerFromDisk,
14135
14779
  resolveCliMemory,
14780
+ inspectLocalRunWorkspace,
14136
14781
  resolveRunOutcome,
14137
14782
  isRunResultStalledOrTruncated,
14138
14783
  resolveRunSettlementNote,