nolo-cli 0.11.0 → 0.12.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (123) hide show
  1. package/{_executeModel-ZEDPX6OF.js → _executeModel-K23VU36L.js} +51 -50
  2. package/{action-AA4IJ5K2.js → action-RAXNQQKC.js} +8 -9
  3. package/{addContentAction-QYVO4SYP.js → addContentAction-ZHI7TVV3.js} +7 -9
  4. package/{addDialogAgentAction-WVVKT5WQ.js → addDialogAgentAction-JWXPKXNC.js} +9 -10
  5. package/{agentDeleteCommand-RDPGYIWF.js → agentDeleteCommand-MWB2LXG6.js} +38 -28
  6. package/{agentEmailCommands-2HJJKS5F.js → agentEmailCommands-7IBTXHNQ.js} +64 -62
  7. package/{agentListCommands-HFEVV3ZW.js → agentListCommands-SKUYB2RQ.js} +127 -31
  8. package/{agentMachineCommands-25ZOENJU.js → agentMachineCommands-5ZM2DB3X.js} +37 -26
  9. package/{agentPullCommand-GOL2S4W2.js → agentPullCommand-KRBRIFIY.js} +7 -7
  10. package/{agentRecordCommands-GTCOAM3L.js → agentRecordCommands-5IVBEJLP.js} +56 -54
  11. package/{agentRunCommand-YBS3JDLD.js → agentRunCommand-UCAEMXQF.js} +59 -59
  12. package/{agentRunControl-K4VKNEHF.js → agentRunControl-IX4F5W2C.js} +3 -3
  13. package/{agentRuntimeLocal-UQBMQI2M.js → agentRuntimeLocal-PR67XWQK.js} +30 -15
  14. package/{agentSlice-6EKOBCCS.js → agentSlice-LWIPUATN.js} +8 -9
  15. package/{authCommand-O2OWACN4.js → authCommand-DMW336GT.js} +15 -15
  16. package/{authCommands-H7365TZP.js → authCommands-GH5T6RYV.js} +6 -6
  17. package/{chunk-7D3JY6C2.js → chunk-3HHTVM6G.js} +64 -5
  18. package/{chunk-KJR5KAUQ.js → chunk-3LVXNJON.js} +20 -7
  19. package/{chunk-AFON4QUU.js → chunk-45JUQTYY.js} +19 -11
  20. package/{chunk-KQQVGRA3.js → chunk-47TVQ7LF.js} +35 -29
  21. package/{chunk-FXXSGWAJ.js → chunk-4GBNEA5B.js} +1 -1
  22. package/{chunk-PXZAAB4L.js → chunk-4LG74DRG.js} +4 -4
  23. package/{chunk-2FTTDCD4.js → chunk-4ON5AV72.js} +2 -1
  24. package/{chunk-IWX4UW2E.js → chunk-524BDL33.js} +89 -8
  25. package/{chunk-4SOKXIW4.js → chunk-5DVIMRVT.js} +8 -11
  26. package/{chunk-ISNCLGUZ.js → chunk-5NBHQD4D.js} +4 -3
  27. package/{chunk-NEM67FX7.js → chunk-672VQUVH.js} +1 -1
  28. package/{chunk-2W2VYVI5.js → chunk-6EFMBEQG.js} +528 -177
  29. package/{chunk-GBDSZATH.js → chunk-6LMFFG3K.js} +3 -3
  30. package/{chunk-CKOJQDKR.js → chunk-7JJCGV7N.js} +146 -3
  31. package/{chunk-MQI77IRB.js → chunk-7MYHLZ3F.js} +2 -2
  32. package/chunk-BYXBJQAS.js +0 -0
  33. package/{chunk-LAX2JSTX.js → chunk-CJIOTRWY.js} +20 -2
  34. package/{chunk-ZEYDOXHF.js → chunk-ESR6LPO5.js} +1467 -868
  35. package/{chunk-EVZKZF32.js → chunk-F22FKI27.js} +182 -75
  36. package/{chunk-OUI3ZHYD.js → chunk-FHTPQXHP.js} +1 -1
  37. package/{chunk-5MOUAAMK.js → chunk-FVGPOJYM.js} +194 -2580
  38. package/{chunk-AEZAORLG.js → chunk-FW4SQ6II.js} +5 -5
  39. package/chunk-IKXL2HZ3.js +70 -0
  40. package/{chunk-QNMFBBZK.js → chunk-IVAOVLM7.js} +1 -1
  41. package/{chunk-S3GS2PRL.js → chunk-JCU2JDCV.js} +597 -68
  42. package/{chunk-Q3UKJVU4.js → chunk-JJR3NP7R.js} +10 -10
  43. package/{chunk-PXQN7IBQ.js → chunk-JNMELOHI.js} +2 -2
  44. package/{chunk-XYZA7S7V.js → chunk-LNTQ7UXG.js} +6 -6
  45. package/{chunk-YOCHZD7D.js → chunk-NCGFB7NN.js} +5 -3
  46. package/{chunk-O26GI2JP.js → chunk-NITP2JDG.js} +39 -8
  47. package/{chunk-YPRZSPF3.js → chunk-OCDEWRE2.js} +1 -1
  48. package/{chunk-PNEW2Z3T.js → chunk-OHEKYYJF.js} +7 -7
  49. package/{chunk-DWGAEFJL.js → chunk-OILEWBXT.js} +1 -1
  50. package/chunk-OOIN7HSO.js +146 -0
  51. package/{chunk-C4FTUXVF.js → chunk-QLUFR47U.js} +11 -1
  52. package/{chunk-BX6U3ETE.js → chunk-RNYKVIND.js} +293 -89
  53. package/{chunk-L53FGHA4.js → chunk-RSEUHW6T.js} +1 -1
  54. package/chunk-S3UTETIC.js +4885 -0
  55. package/chunk-S73OEOHH.js +2286 -0
  56. package/{chunk-E4HNJSHC.js → chunk-TEOXBCYU.js} +81 -19
  57. package/{chunk-YTBMA7NO.js → chunk-TSKWE74T.js} +58 -8
  58. package/{chunk-5OIFWVX7.js → chunk-UG3WOFU6.js} +1 -1
  59. package/{chunk-LP65VRCI.js → chunk-UJ5L6X7H.js} +6 -6
  60. package/{chunk-4ZDM73SD.js → chunk-V2J635L5.js} +1 -1
  61. package/{chunk-IPYUUY4E.js → chunk-WPHL6ALY.js} +1 -1
  62. package/{chunk-3NSIQZZ6.js → chunk-WTYKCU4W.js} +9 -9
  63. package/{chunk-XFOLQLDN.js → chunk-XHQWJUW4.js} +2 -2
  64. package/{chunk-TACHTH5D.js → chunk-XJFP4EXZ.js} +18 -18
  65. package/{chunk-C2MDQQ4O.js → chunk-XRFEX5ZP.js} +1 -1
  66. package/{chunk-D6OQHXVG.js → chunk-YDCZVUFP.js} +7 -7
  67. package/{chunk-SV5MWASH.js → chunk-Z6ZZXQOZ.js} +12 -12
  68. package/{chunk-X2S7JTIG.js → chunk-ZR4RO4ZC.js} +1240 -136
  69. package/{chunk-ZPRK73XY.js → chunk-ZR4VHQ5D.js} +14 -13
  70. package/cliEnvHelpers-VYC2OPTB.js +30 -0
  71. package/{createAgentAutomationAction-LTI5QU35.js → createAgentAutomationAction-PJTUHFYB.js} +25 -26
  72. package/{createDialogAction-OJJ7L3L3.js → createDialogAction-QUCXTRAC.js} +26 -27
  73. package/{createPageAction-5MXWVRGY.js → createPageAction-2EWMGYFH.js} +26 -27
  74. package/{dbSlice-RQFQQVHT.js → dbSlice-WDP2ZZHK.js} +6 -7
  75. package/{deleteFile-7XP5BGC7.js → deleteFile-M7UNIUOO.js} +4 -4
  76. package/{dialogCommands-JTJ3RPPW.js → dialogCommands-BTHTTSE2.js} +33 -23
  77. package/{dialogSlice-OWROKURJ.js → dialogSlice-724QVE7A.js} +26 -27
  78. package/{docCreateCommands-WJBEW2V7.js → docCreateCommands-PQEX44Q7.js} +33 -23
  79. package/{docDeleteCommands-BVEHJOY5.js → docDeleteCommands-B3Q2M42N.js} +34 -25
  80. package/{docReadCommands-NEWOZIJV.js → docReadCommands-RCUVTX3Q.js} +33 -23
  81. package/{docStore-3DXRYBMD.js → docStore-R3US5ZU5.js} +25 -26
  82. package/{docUpdateCommands-C7WHT7UU.js → docUpdateCommands-NS5QAUAJ.js} +33 -23
  83. package/fetchMessages-KTNM7QAR.js +1 -1
  84. package/{getPricing-3E6UNPKL.js → getPricing-6TOZXPAU.js} +7 -3
  85. package/{handleSendMessageAction-B5PRR7BE.js → handleSendMessageAction-NTK7QUU2.js} +29 -30
  86. package/index.js +77 -76
  87. package/{localDialogRead-YSKFFRTT.js → localDialogRead-2VRI24F4.js} +1 -1
  88. package/{machineCommands-IIIREAEK.js → machineCommands-XOU6Q7Y2.js} +63 -61
  89. package/{machineWsRunDispatch-3SIU6ILW.js → machineWsRunDispatch-QRI3MSNV.js} +55 -53
  90. package/{memoryCommands-O4MIPIWQ.js → memoryCommands-AFMES3LN.js} +5 -5
  91. package/{models-4OPOOLFS.js → models-LSCRJJ6P.js} +2 -2
  92. package/package.json +1 -1
  93. package/{read-QJNKRROM.js → read-2MIMRBZ2.js} +4 -4
  94. package/{readDocTool-H6X6KO6X.js → readDocTool-QHVGQHUJ.js} +1 -1
  95. package/{readlineWorkspace-HGP3I3OC.js → readlineWorkspace-3MDU7AYQ.js} +1113 -678
  96. package/{removeDialogAgentAction-TCT35SOF.js → removeDialogAgentAction-GTX5AN54.js} +13 -13
  97. package/{runAgentClientLoop-EFM4PTVI.js → runAgentClientLoop-ZIQQIOUB.js} +47 -47
  98. package/{runtimeDoctorCommands-ID43Z7VX.js → runtimeDoctorCommands-QNF3J3UV.js} +6 -6
  99. package/{setDialogExtraReferencesAction-CGYLZMFH.js → setDialogExtraReferencesAction-WFQ63KYO.js} +9 -10
  100. package/{setPrimaryDialogAgentAction-F6BFQDJU.js → setPrimaryDialogAgentAction-P57FXTSU.js} +13 -13
  101. package/{settingSlice-2I5HMG47.js → settingSlice-CK5YZGNI.js} +7 -8
  102. package/{skillDiscovery-UGSQGX2U.js → skillDiscovery-SZEA7TH6.js} +3 -3
  103. package/{spaceCommands-MT7BWCIL.js → spaceCommands-VTJYPRFQ.js} +37 -29
  104. package/{spaceSlice-BS5TSW3W.js → spaceSlice-DX7Y4RUE.js} +28 -27
  105. package/{streamAgentChatTurn-I3VBFNR3.js → streamAgentChatTurn-7OF2I3KI.js} +222 -128
  106. package/{toolApiClient-C7P7YSE4.js → toolApiClient-QI3YBNWB.js} +2 -2
  107. package/{tools-XSD2BOEN.js → tools-4IILQ24N.js} +34 -34
  108. package/{tuiSummaryLlmCaller-32NRHTT2.js → tuiSummaryLlmCaller-TXLF4MEI.js} +8 -6
  109. package/{updateCommands-VOSPKXFF.js → updateCommands-XZDOOYFH.js} +13 -5
  110. package/{updateDialogTitleAction-7FYNJOGP.js → updateDialogTitleAction-GNQXACIP.js} +29 -29
  111. package/chunk-5MMAK75Q.js +0 -15
  112. package/chunk-AZPCASRE.js +0 -36
  113. package/chunk-BBYVOSU2.js +0 -792
  114. package/chunk-DCOA4QSN.js +0 -105
  115. package/chunk-UAD2WT54.js +0 -64
  116. package/{chunk-JK7VW2FN.js → chunk-5MIDPSSK.js} +3 -3
  117. package/{chunk-5CS33IBL.js → chunk-PDL2AV3E.js} +3 -3
  118. package/{chunk-5MMZUWSG.js → chunk-TOILAPLH.js} +5 -5
  119. package/{chunk-OOM6SJNR.js → chunk-TSUJOM6N.js} +6 -6
  120. package/{db-6QED3ZVO.js → db-HCJ5PRB5.js} +3 -3
  121. package/{offlineMarxistsAgentCommand-BCPJITJL.js → offlineMarxistsAgentCommand-5OOWZLJI.js} +3 -3
  122. package/{tableCommands-M3DJUETS.js → tableCommands-E4SQWDOX.js} +6 -6
  123. package/{understanding-ZOESBLF3.js → understanding-3CUQQ6SV.js} +3 -3
@@ -1,6 +1,3 @@
1
- import {
2
- resolveMachineId
3
- } from "./chunk-6HYVJV7B.js";
4
1
  import {
5
2
  buildLocalRunEnv,
6
3
  isFullstackCodingAgentRef,
@@ -11,10 +8,17 @@ import {
11
8
  writeUsage
12
9
  } from "./chunk-3QAF2LTL.js";
13
10
  import {
11
+ resolveMachineId
12
+ } from "./chunk-6HYVJV7B.js";
13
+ import {
14
+ agentRunCardLabels,
14
15
  createCliCallAgentToolExecutor,
15
16
  createCliLocalRuntimeAdapter,
16
- isBuiltinNoloAgentRef
17
- } from "./chunk-X2S7JTIG.js";
17
+ getCliLocale,
18
+ isBuiltinNoloAgentRef,
19
+ t,
20
+ toolLabel
21
+ } from "./chunk-ZR4RO4ZC.js";
18
22
  import {
19
23
  CliProviderQuotaError
20
24
  } from "./chunk-CMKUBIGW.js";
@@ -24,10 +28,10 @@ import {
24
28
  import {
25
29
  readDbRecord,
26
30
  resolveAgentRecordFromHybridStore
27
- } from "./chunk-AEZAORLG.js";
31
+ } from "./chunk-FW4SQ6II.js";
28
32
  import {
29
33
  normalizeAgentHandle
30
- } from "./chunk-C2MDQQ4O.js";
34
+ } from "./chunk-XRFEX5ZP.js";
31
35
  import {
32
36
  NOLO_PROJECT_MANAGER_AGENT_KEY,
33
37
  isLocalCliAgentKey
@@ -36,78 +40,67 @@ import {
36
40
  applyModelLayerOverride,
37
41
  buildModelLayerOverride
38
42
  } from "./chunk-LTRXGFMS.js";
43
+ import {
44
+ formatAgentListCard,
45
+ formatListRunsCard,
46
+ formatNotFoundRunCard,
47
+ formatStartRunCard,
48
+ formatStatusRunCard,
49
+ formatStopRunCard,
50
+ isAgentRunTerminalStatus
51
+ } from "./chunk-6EFMBEQG.js";
39
52
  import {
40
53
  isGatewayHttpStatus
41
- } from "./chunk-D6OQHXVG.js";
54
+ } from "./chunk-YDCZVUFP.js";
42
55
  import {
43
56
  buildMemorySubjectsForAgent,
44
57
  resolveAgentMemoryPolicy
45
- } from "./chunk-E4HNJSHC.js";
58
+ } from "./chunk-TEOXBCYU.js";
46
59
  import {
47
60
  parseExternalSkillMarkdown,
48
61
  parseSkillDocProtocol
49
62
  } from "./chunk-VC6OZXO5.js";
50
63
  import {
51
- getModelContextWindow,
64
+ API_REPORTED_COST_MULTIPLIER,
65
+ normalizeUsage,
52
66
  parseUiAskChoiceContent
53
- } from "./chunk-5MOUAAMK.js";
54
- import {
55
- parsePositiveFiniteNumberOrFallback
56
- } from "./chunk-Y5GCAMGP.js";
57
- import {
58
- touchMemoryItemsInDb
59
- } from "./chunk-HNW7IJSK.js";
60
- import {
61
- chooseMemoryOwners,
62
- loadMemoryCandidatesFromDb
63
- } from "./chunk-XENYHRUE.js";
64
- import {
65
- readPipeText,
66
- spawnProcess
67
- } from "./chunk-IDZTNRP2.js";
67
+ } from "./chunk-FVGPOJYM.js";
68
68
  import {
69
69
  buildSkillDiscoveryContextBlock
70
- } from "./chunk-AFON4QUU.js";
71
- import {
72
- buildMemoryOverlayLayer,
73
- buildMemoryUseGuidanceLayer
74
- } from "./chunk-C4FTUXVF.js";
70
+ } from "./chunk-45JUQTYY.js";
75
71
  import {
76
72
  buildPlatformChatCompletionRequest,
77
73
  parsePlatformChatCompletionData
78
- } from "./chunk-ZPRK73XY.js";
74
+ } from "./chunk-ZR4VHQ5D.js";
79
75
  import {
80
76
  resolveAgentRuntimeConfigFromRecord
81
- } from "./chunk-YOCHZD7D.js";
77
+ } from "./chunk-NCGFB7NN.js";
82
78
  import {
83
79
  LOCAL_AGENT_CONFIG_MISSING_CODE,
84
80
  LOCAL_TURN_ABORTED_CODE,
85
81
  readActionGate,
86
82
  readCommandActionGatePayload
87
- } from "./chunk-S3GS2PRL.js";
83
+ } from "./chunk-JCU2JDCV.js";
88
84
  import {
89
85
  resolvePlatformChatCompletionsEndpoint
90
- } from "./chunk-YTBMA7NO.js";
86
+ } from "./chunk-TSKWE74T.js";
91
87
  import {
92
- clipCompactText
93
- } from "./chunk-5MMAK75Q.js";
88
+ DEFAULT_CONTEXT_WINDOW,
89
+ clipCompactText,
90
+ getModelContextWindow
91
+ } from "./chunk-S73OEOHH.js";
94
92
  import {
95
93
  findModelConfig
96
- } from "./chunk-BBYVOSU2.js";
94
+ } from "./chunk-S3UTETIC.js";
97
95
  import {
98
- asTrimmedLowercaseString
99
- } from "./chunk-QSJ3HFEF.js";
100
- import {
101
- compactWhitespace
102
- } from "./chunk-DWLEOOGR.js";
96
+ buildMemoryOverlayLayer,
97
+ buildMemoryUseGuidanceLayer
98
+ } from "./chunk-QLUFR47U.js";
103
99
  import {
104
100
  createRunActivityTracker,
105
101
  finalizeRunRecord,
106
102
  spawnLocalBackgroundRun
107
- } from "./chunk-2FTTDCD4.js";
108
- import {
109
- resolveAuthToken
110
- } from "./chunk-ISNCLGUZ.js";
103
+ } from "./chunk-4ON5AV72.js";
111
104
  import {
112
105
  toErrorMessage
113
106
  } from "./chunk-HNMXYYJR.js";
@@ -115,14 +108,36 @@ import {
115
108
  getDefaultCliLocalRuntimeDb
116
109
  } from "./chunk-H33743XH.js";
117
110
  import {
111
+ touchMemoryItemsInDb
112
+ } from "./chunk-HNW7IJSK.js";
113
+ import {
114
+ chooseMemoryOwners,
115
+ loadMemoryCandidatesFromDb
116
+ } from "./chunk-XENYHRUE.js";
117
+ import {
118
+ compactWhitespace
119
+ } from "./chunk-DWLEOOGR.js";
120
+ import {
121
+ readPipeText,
122
+ spawnProcess
123
+ } from "./chunk-IDZTNRP2.js";
124
+ import {
125
+ parsePositiveFiniteNumberOrFallback
126
+ } from "./chunk-Y5GCAMGP.js";
127
+ import {
128
+ asTrimmedLowercaseString
129
+ } from "./chunk-QSJ3HFEF.js";
130
+ import {
131
+ BUILTIN_NOLO_AGENT_KEY,
118
132
  PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY,
119
- PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
120
- PUBLIC_GLM_52_AGENT_KEY,
121
133
  PUBLIC_KIMI_K26_IMAGE_AGENT_KEY
122
- } from "./chunk-XFOLQLDN.js";
134
+ } from "./chunk-XHQWJUW4.js";
123
135
  import {
124
136
  asTrimmedString
125
137
  } from "./chunk-3EUW3WEO.js";
138
+ import {
139
+ resolveAuthToken
140
+ } from "./chunk-5NBHQD4D.js";
126
141
  import {
127
142
  isLoopbackUrl
128
143
  } from "./chunk-4SN6J65J.js";
@@ -130,7 +145,236 @@ import {
130
145
  asOptionalTrimmedString
131
146
  } from "./chunk-G3SUCT4W.js";
132
147
 
148
+ // packages/agent-runtime/quickChatIntentCore.ts
149
+ var INTENT_MODEL = "deepseek-v4-flash";
150
+ var INTENT_PROVIDER = "deepseek";
151
+ var QUICK_CHAT_INTENT_TIMEOUT_MS = 4e3;
152
+ var SHORT_GREETING_MAX_LENGTH = 20;
153
+ var SHORT_GREETING_PATTERN = /^(?:hi|hello|hey|hiya|yo|sup|howdy|嗨|哈喽|哈囉|你好|您好|在吗|在嘛|喂|早上好|中午好|下午好|晚上好|拜拜|再见|谢谢|thanks|thx|ok|好的|收到|了解)[!.。,、~~]?$/iu;
154
+ function isShortGreeting(text) {
155
+ const trimmed = text.trim();
156
+ if (!trimmed) return false;
157
+ if (trimmed.length > SHORT_GREETING_MAX_LENGTH) return false;
158
+ return SHORT_GREETING_PATTERN.test(trimmed);
159
+ }
160
+ var COMPLEXITY_SIMPLE_MAX_LENGTH = 80;
161
+ var COMPLEXITY_MEDIUM_MAX_LENGTH = 500;
162
+ var COMPLEXITY_KEYWORDS = /为什么|如何|分析|对比|比较|设计|架构|实现|原理|推导|评价|区别|关系|影响|优化|重构/;
163
+ var COMPLEXITY_CODE_BLOCK = /```[\s\S]*```/;
164
+ function estimateComplexity(text) {
165
+ const trimmed = text.trim();
166
+ const len = trimmed.length;
167
+ if (len > COMPLEXITY_MEDIUM_MAX_LENGTH) return "complex";
168
+ if (COMPLEXITY_CODE_BLOCK.test(trimmed)) return "complex";
169
+ if (len > COMPLEXITY_SIMPLE_MAX_LENGTH) return "medium";
170
+ if (COMPLEXITY_KEYWORDS.test(trimmed)) return "medium";
171
+ return "simple";
172
+ }
173
+ var TIER_DESCRIPTIONS = {
174
+ flash: "\u5FEB\u901F\u7B80\u5355\uFF1A\u95EE\u5019\u3001\u95F2\u804A\u3001\u5FEB\u901F\u95EE\u7B54\u3001\u7FFB\u8BD1\u3001\u77ED\u6587",
175
+ balanced: "\u5E73\u8861\u63A8\u7406\uFF1A\u5206\u6790\u3001\u4E2D\u7B49\u957F\u5EA6\u5199\u4F5C\u3001\u4EE3\u7801\u3001\u63A8\u7406\uFF08\u5F53\u524D\u8DEF\u7531\u81F3 DeepSeek V4 Flash\uFF09",
176
+ quality: "\u9AD8\u8D28\u91CF\u6DF1\u5EA6\uFF1A\u590D\u6742\u63A8\u7406\u3001\u957F\u6587\u3001\u67B6\u6784\u8BBE\u8BA1\u3001\u6DF1\u5EA6\u5206\u6790\uFF08\u5F53\u524D\u8DEF\u7531\u81F3 DeepSeek V4 Flash\uFF09"
177
+ };
178
+ function buildQuickChatIntentSystemPrompt(tierAgents) {
179
+ const agentList = tierAgents.map((t2) => ` - "${t2.agentKey}"\uFF1A${t2.description}`).join("\n");
180
+ return `\u4F60\u662F\u4E00\u4E2A\u610F\u56FE\u8DEF\u7531\u5668\u3002\u6839\u636E\u7528\u6237\u6D88\u606F\uFF0C\u5224\u65AD\u5E94\u8BE5\u4EA4\u7ED9\u54EA\u4E2A agent \u5904\u7406\u3002
181
+
182
+ \u53EF\u9009 agent \u5217\u8868\uFF08agentKey \u4E0E\u63CF\u8FF0\uFF09\uFF1A
183
+ ${agentList}
184
+
185
+ \u5224\u65AD\u539F\u5219\uFF08\u9ED8\u8BA4\u504F\u5411\u901A\u7528\u6863\u4F4D\uFF1B\u4E13\u804C agent \u5728\u660E\u786E\u5339\u914D\u65F6\u4F7F\u7528\uFF1B**\u7F16\u7801/\u672C\u5730\u4ED3\u5E93\u4EFB\u52A1\u8D70\u901A\u7528\u6863 + needsWorkspace=true**\uFF09\uFF1A
186
+ - \u9ED8\u8BA4\u60C5\u51B5\u4E0B\uFF0C**\u9664\u975E\u7528\u6237\u660E\u786E\u8868\u8FBE\u8981\u5EFA\u5E94\u7528/\u5EFA Agent/\u63D0\u4EA4\u53CD\u9988/\u591A Agent \u7F16\u6392**\uFF0C\u5426\u5219\u9009\u901A\u7528\u6863\u4F4D\uFF08flash/balanced/quality\uFF09\uFF1A
187
+ - \u7B80\u5355\u95EE\u5019\u3001\u95F2\u804A\u3001\u5FEB\u901F\u95EE\u7B54\u3001\u7FFB\u8BD1\u3001\u77ED\u6587 \u2192 \u9009 flash \u6863
188
+ - \u9700\u8981\u63A8\u7406\u3001\u5206\u6790\u3001\u4E2D\u7B49\u957F\u5EA6\u5199\u4F5C\u3001\u666E\u901A\u4EE3\u7801\u89E3\u91CA/\u67B6\u6784\u95EE\u7B54 \u2192 \u9009 balanced \u6863
189
+ - \u590D\u6742\u63A8\u7406\u3001\u957F\u6587\u3001\u67B6\u6784\u8BBE\u8BA1\u3001\u6DF1\u5EA6\u5206\u6790 \u2192 \u9009 quality \u6863
190
+ - **\u660E\u786E\u7F16\u7801\u4EFB\u52A1\uFF08\u5B9E\u73B0\u529F\u80FD\u3001\u4FEE bug\u3001refactor\u3001\u5199/\u8865\u6D4B\u8BD5\u3001\u8DD1 build/tests/ci\uFF09\u6216\u67E5\u770B\u672C\u673A\u4ED3\u5E93/\u4EE3\u7801\u72B6\u6001\uFF08git/\u5206\u652F/commit/\u672C\u5730\u4E0E\u8FDC\u7A0B\u5DEE\u8DDD/\u672A\u63D0\u4EA4\u6539\u52A8\u7B49\uFF09** \u2192 \u9009 balanced \u6216 quality \u6863\uFF08\u6309\u590D\u6742\u5EA6\uFF1B**\u4E0D\u8981\u9009 flash**\uFF09\uFF0C\u4E14 needsWorkspace=true
191
+ - \u4E13\u804C agent \u8DEF\u7531\u89C4\u5219\uFF08\u6709\u660E\u786E\u5339\u914D\u65F6\u4F7F\u7528\uFF09\uFF1A
192
+ - \u8981\u63D0\u4EA4/\u8BB0\u5F55 bug\u3001\u4F53\u9A8C\u95EE\u9898\u3001\u6570\u636E\u5F02\u5E38\u3001\u4EA7\u54C1\u5EFA\u8BAE\uFF0C\u6216\u53E3\u8BED\u5982\u300C\u60F3\u53CD\u9988\u4E00\u4E9B\u95EE\u9898\u300D\u300C\u53CD\u9988\u4E00\u4E0B\u300D\u2192 \u9009\u610F\u89C1\u53CD\u9988\u4E13\u804C agent
193
+ - \u8981\u65B0\u5EFA\u6216\u5B9A\u5236 AI/Agent/\u667A\u80FD\u4F53\u52A9\u624B\uFF08\u542B\u914D\u7F6E\u5DE5\u5177\u3001\u77E5\u8BC6\u3001\u786E\u8BA4\u521B\u5EFA\uFF09\u2192 \u9009\u521B\u5EFA Agent \u4E13\u804C agent
194
+ - \u8981\u505A/\u6539/\u53D1\u5E03\u7F51\u7AD9\u3001\u7F51\u9875\u3001\u5C0F\u5E94\u7528\u3001\u9884\u7EA6\u9875\u3001\u535A\u5BA2\u3001\u770B\u677F \u2192 \u9009\u5E94\u7528\u6784\u5EFA\u4E13\u804C agent
195
+ - \u8981\u6D3E\u591A\u4E2A agent\u3001\u591A agent \u5E76\u884C\u3001\u62C6\u6210\u4EFB\u52A1\u540E\u53F0\u6267\u884C\u3001\u591A\u4E2A agent review\u3001\u8BA9\u4E0D\u540C agent \u8BA8\u8BBA/\u4F1A\u5546 \u2192 \u9009\u591A Agent \u7F16\u6392\u4E13\u804C agent\uFF08\u663E\u5F0F multi-agent \u4F18\u5148\uFF09
196
+ - **\u62FF\u4E0D\u51C6\u65F6**\uFF1A\u7EAF\u95F2\u804A\u9009 flash\uFF1B**\u82E5\u6CBE\u8FB9\u672C\u5730\u4ED3\u5E93/\u5F53\u524D\u4EE3\u7801\u72B6\u6001\uFF0C\u9009 balanced/quality + needsWorkspace=true**\u3002
197
+
198
+ \u540C\u65F6\u5224\u65AD\u672C\u8F6E\u662F\u5426\u9700\u8981\u6CE8\u5165\u300C\u5DE5\u4F5C\u533A\u53EA\u8BFB\u5DE5\u5177\u300D\uFF08listFiles/globFiles/searchFiles/readFile/execShell \u7B49\uFF09\uFF1A
199
+ - needsWorkspace=true \u7684\u573A\u666F\uFF1A\u7528\u6237\u8981\u8BFB/\u6539/\u5206\u6790\u6587\u4EF6\u6216\u4EE3\u7801\u3001\u63D0\u5230\u4E86\u6587\u4EF6\u8DEF\u5F84/\u6269\u5C55\u540D\uFF08.md/.csv/.ts \u7B49\uFF09\u3001\u63D0\u5230\u5DE5\u4F5C\u533A/\u4EE3\u7801\u5E93/\u4ED3\u5E93/\u76EE\u5F55/git/\u5206\u652F\u3001\u8981\u770B\u5F53\u524D\u4EE3\u7801\u6216\u4ED3\u5E93\u72B6\u6001\u3001\u672C\u5730\u641C\u7D22/\u67E5\u770B\u4EE3\u7801\u3002
200
+ - needsWorkspace=false \u7684\u573A\u666F\uFF1A\u901A\u7528\u77E5\u8BC6\u95EE\u7B54\uFF08\u5982\u300C\u5E7F\u4E1C\u7ECF\u6D4E\u6570\u636E\u300D\u300C\u5199\u4E00\u9996\u8BD7\u300D\uFF09\u3001\u7EAF\u95F2\u804A\u95EE\u5019\u3001\u7FFB\u8BD1\u3001\u4E0D\u6D89\u53CA\u672C\u5730\u6587\u4EF6/\u4ED3\u5E93\u3002
201
+ - \u6F0F\u5224\uFF08\u7528\u6237\u8981\u6587\u4EF6\u800C\u6CA1\u5E26\u5DE5\u5177\uFF09\u6BD4\u8BEF\u5224\uFF08\u767D\u641C\u51E0\u8F6E\uFF09\u4EE3\u4EF7\u66F4\u9AD8\uFF0C\u5B81\u53EF\u504F\u5BBD\u5224 true\u3002
202
+
203
+ \u5728\u7ED9\u51FA agentKey \u4E4B\u524D\uFF0C\u5148\u5728\u5FC3\u91CC\u533A\u5206\u5019\u9009\u6863\u4F4D\u7684\u8FB9\u754C\u518D\u7ED9\u7F6E\u4FE1\u5EA6\uFF1Abalanced \u4E0E quality \u7684\u8FB9\u754C\u5728\u4E8E\u590D\u6742\u5EA6/\u7BC7\u5E45/\u662F\u5426\u9700\u8981\u6DF1\u5EA6\u5206\u6790\uFF0C\u62FF\u4E0D\u51C6\u5C31\u7ED9\u4F4E confidence\u3002
204
+
205
+ \u540C\u65F6\u5224\u65AD\u672C\u8F6E\u6D88\u606F\u662F\u5426\u9700\u8981\u6302\u8F7D\u5BF9\u8C61\u64CD\u4F5C\u6280\u80FD\uFF08skills \u6570\u7EC4\uFF0C\u672A\u547D\u4E2D\u7ED9 []\uFF09\uFF1A
206
+ - \u7528\u6237\u8981\u65B0\u5EFA/\u6574\u7406/\u5F55\u5165/\u6279\u91CF\u5904\u7406\u8868\u683C\u6570\u636E\uFF08\u5EFA\u8868\u3001\u52A0\u884C\u3001\u6539\u5217\u3001\u6309\u6761\u4EF6\u6574\u7406\u6570\u636E\uFF09\u2192 skills \u542B "table"
207
+ - \u7528\u6237\u8981\u5199/\u6DA6\u8272/\u6539\u5199/\u7EED\u5199/\u6392\u7248\u4E00\u7BC7\u6587\u6863\u6216\u6587\u7AE0 \u2192 skills \u542B "doc"
208
+ - \u7528\u6237\u8981\u5199/\u6539/\u5B9E\u73B0/\u4FEE bug/refactor/\u8865\u6D4B\u8BD5/\u5BA1\u67E5\u5E76\u4FEE\u6539\u4EE3\u7801 \u2192 skills \u542B "code"\uFF08\u4EC5\u95EE\u901A\u7528\u77E5\u8BC6\u3001\u7EAF\u95F2\u804A\u3001\u53EA\u67E5\u770B git/\u4ED3\u5E93\u72B6\u6001\u800C\u4E0D\u4FEE\u6539\u4EE3\u7801\u65F6\u4E0D\u6302 "code"\uFF09
209
+ - \u7528\u6237\u60F3\u8981\u4E00\u4E2A\u53EF\u4EA4\u4E92\u7684\u53EF\u89C6\u5316\u9875\u9762/\u62A5\u544A/\u770B\u677F/\u4E3B\u9875/\u6559\u7A0B/\u5BF9\u6BD4\u9875/\u8BA1\u5212\u9875\uFF08\u5982"\u505A\u4E2A\u65E5\u62A5""\u505A\u4E00\u4E2A\u4E2A\u4EBA\u4E3B\u9875""\u505A\u4E2A\u9500\u552E\u770B\u677F""\u505A\u4E2A\u65B9\u6848\u5BF9\u6BD4\u9875""\u505A\u4E2A\u5B66\u4E60\u8BA1\u5212\u9875"\uFF09\u2192 skills \u542B "pagebuilder"
210
+ - \u666E\u901A\u95EE\u7B54/\u7EAF\u95F2\u804A/\u5EFA\u5E94\u7528 \u2192 skills \u4E3A []
211
+
212
+ \u53EA\u8F93\u51FA JSON\uFF0C\u4E0D\u8981\u8F93\u51FA\u5176\u4ED6\u5185\u5BB9\uFF1A
213
+ {"confidence": <0\u52301\u4E4B\u95F4\u7684\u5C0F\u6570\uFF0C\u8868\u793A\u4F60\u5BF9\u8FD9\u4E2A\u5206\u7C7B\u5224\u65AD\u7684\u628A\u63E1\u7A0B\u5EA6>, "agentKey": "<\u4ECE\u5217\u8868\u4E2D\u9009\u62E9\u7684 agentKey>", "needsWorkspace": <true \u6216 false>, "skills": <\u5B57\u7B26\u4E32\u6570\u7EC4\uFF0C\u5143\u7D20\u53EA\u80FD\u662F "table" | "doc" | "code" | "pagebuilder"\uFF0C\u672A\u547D\u4E2D\u7ED9 []>}`;
214
+ }
215
+ function parseQuickChatIntentResult(content, tierAgents) {
216
+ try {
217
+ const parsed = JSON.parse(content.trim());
218
+ if (typeof parsed !== "object" || parsed === null || !("agentKey" in parsed)) return null;
219
+ const key = parsed.agentKey;
220
+ if (typeof key !== "string") return null;
221
+ if (!tierAgents.some((t2) => t2.agentKey === key)) return null;
222
+ const rawNeedsWorkspace = parsed.needsWorkspace;
223
+ const needsWorkspace = rawNeedsWorkspace === true;
224
+ const rawConfidence = parsed.confidence;
225
+ const confidence = typeof rawConfidence === "number" && Number.isFinite(rawConfidence) && rawConfidence >= 0 && rawConfidence <= 1 ? rawConfidence : void 0;
226
+ const rawSkills = parsed.skills;
227
+ let skills;
228
+ if (Array.isArray(rawSkills)) {
229
+ const filtered = [...new Set(rawSkills)].filter(
230
+ (s) => s === "table" || s === "doc" || s === "code" || s === "pagebuilder"
231
+ );
232
+ if (filtered.length > 0) skills = filtered;
233
+ }
234
+ return { agentKey: key, needsWorkspace, confidence, skills };
235
+ } catch {
236
+ return null;
237
+ }
238
+ }
239
+
240
+ // packages/cli/client/autoModelRouter.ts
241
+ var CLI_AUTO_TIER_AGENT_KEYS = {
242
+ flash: PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY,
243
+ balanced: PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY,
244
+ quality: PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY
245
+ };
246
+ var CLI_AUTO_TIER_MODELS = {
247
+ flash: "deepseek-v4-flash",
248
+ balanced: "deepseek-v4-flash",
249
+ quality: "deepseek-v4-flash"
250
+ };
251
+ var CLI_IMAGE_AGENT_KEY = PUBLIC_KIMI_K26_IMAGE_AGENT_KEY;
252
+ var CLI_IMAGE_AGENT_MODEL = "kimi-k2.6";
253
+ var CLI_AUTO_TIER_AGENT_KEY_TABLE = {
254
+ [CLI_AUTO_TIER_AGENT_KEYS.flash]: true,
255
+ [CLI_AUTO_TIER_AGENT_KEYS.balanced]: true,
256
+ [CLI_AUTO_TIER_AGENT_KEYS.quality]: true
257
+ };
258
+ function resolveCliAutoAgentModel(agentKey) {
259
+ if (agentKey === CLI_AUTO_TIER_AGENT_KEYS.flash) return CLI_AUTO_TIER_MODELS.flash;
260
+ if (agentKey === CLI_AUTO_TIER_AGENT_KEYS.balanced) {
261
+ return CLI_AUTO_TIER_MODELS.balanced;
262
+ }
263
+ if (agentKey === CLI_AUTO_TIER_AGENT_KEYS.quality) {
264
+ return CLI_AUTO_TIER_MODELS.quality;
265
+ }
266
+ if (agentKey === CLI_IMAGE_AGENT_KEY) return CLI_IMAGE_AGENT_MODEL;
267
+ return void 0;
268
+ }
269
+ var buildRouteOptions = () => ["flash", "balanced", "quality"].map((tier) => ({
270
+ tier,
271
+ agentKey: CLI_AUTO_TIER_AGENT_KEYS[tier],
272
+ description: TIER_DESCRIPTIONS[tier]
273
+ }));
274
+ var tierForAgentKey = (agentKey) => {
275
+ for (const tier of ["flash", "balanced", "quality"]) {
276
+ if (CLI_AUTO_TIER_AGENT_KEYS[tier] === agentKey) return tier;
277
+ }
278
+ return null;
279
+ };
280
+ function resolveCliAutoFallbackTier(text) {
281
+ switch (estimateComplexity(text)) {
282
+ case "complex":
283
+ return "quality";
284
+ case "medium":
285
+ return "balanced";
286
+ case "simple":
287
+ default:
288
+ return "flash";
289
+ }
290
+ }
291
+ async function classifyCliAutoRoute(text, options) {
292
+ const timeoutMs = options.timeoutMs ?? QUICK_CHAT_INTENT_TIMEOUT_MS;
293
+ const fallbackTier = resolveCliAutoFallbackTier(text);
294
+ const fallback = () => ({
295
+ agentKey: CLI_AUTO_TIER_AGENT_KEYS[fallbackTier],
296
+ tier: fallbackTier,
297
+ classified: false
298
+ });
299
+ if (!text.trim()) return fallback();
300
+ if (isShortGreeting(text)) {
301
+ return {
302
+ agentKey: CLI_AUTO_TIER_AGENT_KEYS.flash,
303
+ tier: "flash",
304
+ classified: true
305
+ };
306
+ }
307
+ if (!options.authToken) return fallback();
308
+ const fetchImpl = options.fetchImpl ?? globalThis.fetch;
309
+ const controller = new AbortController();
310
+ const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
311
+ try {
312
+ const routeOptions = buildRouteOptions();
313
+ const messages = [
314
+ { role: "system", content: buildQuickChatIntentSystemPrompt(routeOptions) },
315
+ { role: "user", content: text }
316
+ ];
317
+ const { url, init } = buildPlatformChatCompletionRequest({
318
+ providerConfig: {
319
+ serverUrl: options.serverUrl,
320
+ authToken: options.authToken,
321
+ agentKey: CLI_AUTO_TIER_AGENT_KEYS.flash,
322
+ model: INTENT_MODEL,
323
+ provider: INTENT_PROVIDER,
324
+ endpoint: resolvePlatformChatCompletionsEndpoint(INTENT_PROVIDER) ?? "",
325
+ requestOptions: {}
326
+ },
327
+ messages,
328
+ stream: false
329
+ });
330
+ const response = await fetchImpl(url, {
331
+ ...init,
332
+ signal: controller.signal
333
+ });
334
+ if (!response.ok) return fallback();
335
+ const data = parsePlatformChatCompletionData(await response.text());
336
+ const content = data?.choices?.[0]?.message?.content;
337
+ if (typeof content !== "string" || !content.trim()) return fallback();
338
+ const parsed = parseQuickChatIntentResult(content, routeOptions);
339
+ if (!parsed) return fallback();
340
+ const tier = tierForAgentKey(parsed.agentKey) ?? fallbackTier;
341
+ return {
342
+ agentKey: parsed.agentKey,
343
+ tier,
344
+ classified: true,
345
+ confidence: parsed.confidence,
346
+ needsWorkspace: parsed.needsWorkspace,
347
+ skills: parsed.skills
348
+ };
349
+ } catch {
350
+ return fallback();
351
+ } finally {
352
+ clearTimeout(timeoutHandle);
353
+ }
354
+ }
355
+
133
356
  // packages/cli/client/tokenUsage.ts
357
+ var isUsableModelId = (model) => {
358
+ const raw = model?.trim();
359
+ return Boolean(raw) && raw !== "-" && raw !== "auto";
360
+ };
361
+ function resolveAgentContextWindow(opts) {
362
+ if (isUsableModelId(opts.model)) {
363
+ return getModelContextWindow(opts.model);
364
+ }
365
+ const agentKey = opts.agentKey?.trim();
366
+ if (agentKey) {
367
+ const tierModel = resolveCliAutoAgentModel(agentKey);
368
+ if (tierModel) return getModelContextWindow(tierModel);
369
+ if (opts.autoRouteDefault !== false && agentKey === BUILTIN_NOLO_AGENT_KEY) {
370
+ return getModelContextWindow(CLI_AUTO_TIER_MODELS.flash);
371
+ }
372
+ }
373
+ if (opts.agentName?.trim()) {
374
+ return getModelContextWindow(opts.agentName);
375
+ }
376
+ return DEFAULT_CONTEXT_WINDOW;
377
+ }
134
378
  var PROVIDER_LOOKUP_ORDER = [
135
379
  "openrouter",
136
380
  "fireworks",
@@ -150,7 +394,15 @@ function parseUsageRecord(usage) {
150
394
  const output = Number(usage.output_tokens ?? usage.completion_tokens ?? 0);
151
395
  if (!Number.isFinite(input) || !Number.isFinite(output)) return void 0;
152
396
  if (!input && !output) return void 0;
153
- return { input, output };
397
+ const normalized = normalizeUsage(usage);
398
+ const cacheRead = normalized.cache_read_input_tokens || void 0;
399
+ const cacheWrite = normalized.cache_creation_input_tokens || void 0;
400
+ return {
401
+ input,
402
+ output,
403
+ ...cacheRead === void 0 ? {} : { cacheRead },
404
+ ...cacheWrite === void 0 ? {} : { cacheWrite }
405
+ };
154
406
  }
155
407
  function resolveContextWindow(model) {
156
408
  const raw = model?.trim();
@@ -166,10 +418,13 @@ function buildTurnTokenUsage(usage, model) {
166
418
  if (!parsed) return void 0;
167
419
  const contextWindow = resolveContextWindow(model);
168
420
  const remaining = contextWindow && parsed.input > 0 ? Math.max(0, contextWindow - parsed.input) : void 0;
421
+ const rawCost = typeof usage?.cost === "number" ? usage.cost : void 0;
422
+ const credits = rawCost !== void 0 && rawCost > 0 ? rawCost * API_REPORTED_COST_MULTIPLIER : void 0;
169
423
  return {
170
424
  ...parsed,
171
425
  ...contextWindow ? { contextWindow } : {},
172
- ...remaining != null ? { remaining } : {}
426
+ ...remaining != null ? { remaining } : {},
427
+ ...credits !== void 0 ? { credits } : {}
173
428
  };
174
429
  }
175
430
  function formatTokenCount(value) {
@@ -186,7 +441,8 @@ function formatTokenCount(value) {
186
441
  function renderTokenStatus(tokens) {
187
442
  if (!tokens) return "in \u2014 out \u2014 left \u2014";
188
443
  const left = tokens.remaining != null ? formatTokenCount(tokens.remaining) : tokens.contextWindow ? "\u2014" : "\u2014";
189
- return `in ${formatTokenCount(tokens.input)} out ${formatTokenCount(tokens.output)} left ${left}`;
444
+ const cache = tokens.cacheRead != null && tokens.cacheRead > 0 ? ` (cache ${formatTokenCount(tokens.cacheRead)})` : "";
445
+ return `in ${formatTokenCount(tokens.input)}${cache} out ${formatTokenCount(tokens.output)} left ${left}`;
190
446
  }
191
447
  function shouldShowUsage(env) {
192
448
  return env.NOLO_DEBUG === "1" || env.NOLO_SHOW_USAGE === "1";
@@ -232,14 +488,283 @@ function resolveCliColorEnabled(env = process.env, isTTY = Boolean(process.stdou
232
488
  if (setting === "1" || setting === "true" || setting === "on") return true;
233
489
  return isTTY;
234
490
  }
235
- function styleCliText(text, style, enabled = resolveCliColorEnabled()) {
236
- if (!enabled || !text) return text;
237
- const code = ANSI_FG[style] ?? ANSI_BG[style];
238
- if (!code) return text;
239
- return `${code}${text}${RESET}`;
491
+ function styleCliText(text, style, enabled = resolveCliColorEnabled()) {
492
+ if (!enabled || !text) return text;
493
+ const code = ANSI_FG[style] ?? ANSI_BG[style];
494
+ if (!code) return text;
495
+ return `${code}${text}${RESET}`;
496
+ }
497
+ function dimCliText(text, enabled = resolveCliColorEnabled()) {
498
+ return styleCliText(text, "dim", enabled);
499
+ }
500
+
501
+ // packages/cli/tui/tuiAnsi.ts
502
+ var ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
503
+ var OSC_HYPERLINK_REGEX = /\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)\x1b\]8;;(?:\x07|\x1b\\)|\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
504
+ function stripAnsi(text) {
505
+ return text.replace(OSC_HYPERLINK_REGEX, "").replace(ANSI_ESCAPE_REGEX, "");
506
+ }
507
+ var SGR_SEQUENCE_REGEX = /^\x1b\[[0-9;]*m/;
508
+ var TRAILING_SGR_REGEX = /(?:\x1b\[[0-9;]*m)+$/;
509
+ function applyTerminalOutputToText(existing, chunk) {
510
+ if (!chunk) return existing;
511
+ let text = existing;
512
+ let index = 0;
513
+ while (index < chunk.length) {
514
+ if (chunk[index] === "\x1B") {
515
+ const sgr = SGR_SEQUENCE_REGEX.exec(chunk.slice(index));
516
+ if (sgr) {
517
+ text += sgr[0];
518
+ index += sgr[0].length;
519
+ continue;
520
+ }
521
+ const osc = chunk.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
522
+ if (osc) {
523
+ index += osc[0].length;
524
+ continue;
525
+ }
526
+ const csi = chunk.slice(index).match(/^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/);
527
+ if (csi) {
528
+ index += csi[0].length;
529
+ continue;
530
+ }
531
+ index += 1;
532
+ continue;
533
+ }
534
+ const ch = chunk[index];
535
+ if (ch === "\r") {
536
+ const lastNl = text.lastIndexOf("\n");
537
+ text = lastNl === -1 ? "" : text.slice(0, lastNl + 1);
538
+ index += 1;
539
+ continue;
540
+ }
541
+ if (ch === "\n") {
542
+ text += "\n";
543
+ index += 1;
544
+ continue;
545
+ }
546
+ if (ch === "\b") {
547
+ const trailing = TRAILING_SGR_REGEX.exec(text);
548
+ const sgrTail = trailing ? trailing[0] : "";
549
+ const head = sgrTail ? text.slice(0, -sgrTail.length) : text;
550
+ if (head.length > 0 && head[head.length - 1] !== "\n") {
551
+ text = head.slice(0, -1) + sgrTail;
552
+ }
553
+ index += 1;
554
+ continue;
555
+ }
556
+ const code = ch.charCodeAt(0);
557
+ if (code < 32 && ch !== " " || code === 127) {
558
+ index += 1;
559
+ continue;
560
+ }
561
+ text += ch;
562
+ index += 1;
563
+ }
564
+ return text;
565
+ }
566
+ function displayWidth(str) {
567
+ let width = 0;
568
+ for (const char of str) {
569
+ const code = char.codePointAt(0) ?? 0;
570
+ if (code < 32 || code === 127) continue;
571
+ if (code >= 4352 && code <= 4447 || // 0x2768-0x2775 (ornamental brackets, incl. the ❯ prompt at U+276F)
572
+ // render narrow in terminals; counting them wide drifts the cursor.
573
+ code >= 9728 && code <= 10175 && !(code >= 10088 && code <= 10101) || // 0x2B00-0x2BFF (Misc Symbols and Arrows, incl. ⬢ U+2B22 used as the
574
+ // status-line agent icon) render double-wide in common monospace fonts;
575
+ // counting ⬢ as width 1 drifts the whole status line right of the icon.
576
+ code >= 11008 && code <= 11263 || code >= 11904 && code <= 12350 || code >= 12352 && code <= 13247 || code >= 13312 && code <= 19903 || code >= 19968 && code <= 42191 || code >= 44032 && code <= 55203 || code >= 63744 && code <= 64255 || code >= 65072 && code <= 65135 || code >= 65281 && code <= 65376 || code >= 65504 && code <= 65510 || code >= 127744 && code <= 129791 || code >= 131072 && code <= 196605 || code >= 196608 && code <= 262141 || // East Asian Ambiguous CJK quotation marks (U+201C/D “ ”, U+2018/9 ‘ ’).
577
+ // In CJK locale + CJK fonts these render double-wide like 全角 punctuation;
578
+ // in English fonts they stay width 1. Follow the active locale so Chinese
579
+ // replies align correctly without breaking English terminal output.
580
+ getCliLocale() === "zh" && (code === 8220 || code === 8221 || code === 8216 || code === 8217)) {
581
+ width += 2;
582
+ } else {
583
+ width += 1;
584
+ }
585
+ }
586
+ return width;
587
+ }
588
+ function visibleWidth(str) {
589
+ return displayWidth(stripAnsi(str));
590
+ }
591
+ function truncateAnsi(text, maxWidth) {
592
+ if (maxWidth <= 0) return "";
593
+ if (visibleWidth(text) <= maxWidth) return text;
594
+ let width = 0;
595
+ let out = "";
596
+ let i = 0;
597
+ let sawAnsi = false;
598
+ while (i < text.length) {
599
+ if (text[i] === "\x1B" && text[i + 1] === "[") {
600
+ sawAnsi = true;
601
+ let j = i + 2;
602
+ while (j < text.length) {
603
+ const code = text.charCodeAt(j);
604
+ j += 1;
605
+ if (code >= 64 && code <= 126) break;
606
+ }
607
+ out += text.slice(i, j);
608
+ i = j;
609
+ continue;
610
+ }
611
+ const codePoint = text.codePointAt(i) ?? 0;
612
+ const char = String.fromCodePoint(codePoint);
613
+ const charWidth = displayWidth(char);
614
+ if (width + charWidth > maxWidth) break;
615
+ out += char;
616
+ width += charWidth;
617
+ i += char.length;
618
+ }
619
+ return sawAnsi ? `${out}\x1B[0m` : out;
620
+ }
621
+ function fitAnsiLine(text, width, ellipsis = "\u2026") {
622
+ if (width <= 0) return "";
623
+ if (visibleWidth(text) <= width) return text;
624
+ const ellipsisWidth = displayWidth(ellipsis);
625
+ if (width < ellipsisWidth) return truncateAnsi(text, width);
626
+ if (width === ellipsisWidth) return truncateAnsi(ellipsis, width) || truncateAnsi(text, width);
627
+ return `${truncateAnsi(text, width - ellipsisWidth)}${ellipsis}`;
628
+ }
629
+ function countPhysicalLines(text, columns) {
630
+ const lines = text.split("\n");
631
+ let total = 0;
632
+ for (const line of lines) {
633
+ const width = displayWidth(line);
634
+ total += Math.max(1, Math.ceil(width / columns));
635
+ }
636
+ return Math.max(total, 1);
637
+ }
638
+ function takeDisplayWidth(text, width) {
639
+ let used = 0;
640
+ let index = 0;
641
+ for (const char of text) {
642
+ const charWidth = displayWidth(char);
643
+ if (used + charWidth > width && used > 0) break;
644
+ used += charWidth;
645
+ index += char.length;
646
+ }
647
+ return { prefix: text.slice(0, index), rest: text.slice(index) };
648
+ }
649
+ function padOrTruncateToWidth(text, width) {
650
+ const textWidth = visibleWidth(text);
651
+ if (textWidth > width) {
652
+ return truncateAnsi(text, width);
653
+ }
654
+ return `${text}${" ".repeat(width - textWidth)}`;
655
+ }
656
+ var SGR_RESET_REGEX = /^\x1b\[0?m$/;
657
+ function tokenizeAnsiLine(line) {
658
+ const tokens = [];
659
+ let index = 0;
660
+ while (index < line.length) {
661
+ if (line[index] === "\x1B") {
662
+ const osc = line.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
663
+ if (osc) {
664
+ tokens.push({ kind: "sgr", value: osc[0], width: 0 });
665
+ index += osc[0].length;
666
+ continue;
667
+ }
668
+ const sgr = SGR_SEQUENCE_REGEX.exec(line.slice(index));
669
+ if (sgr) {
670
+ tokens.push({ kind: "sgr", value: sgr[0], width: 0 });
671
+ index += sgr[0].length;
672
+ continue;
673
+ }
674
+ }
675
+ const codePoint = line.codePointAt(index) ?? 0;
676
+ const value = String.fromCodePoint(codePoint);
677
+ tokens.push({ kind: "char", value, width: displayWidth(value) });
678
+ index += value.length;
679
+ }
680
+ return tokens;
240
681
  }
241
- function dimCliText(text, enabled = resolveCliColorEnabled()) {
242
- return styleCliText(text, "dim", enabled);
682
+ function wrapTranscriptLine(line, columns, hangingIndent = "") {
683
+ if (line === "") return [""];
684
+ const tokens = tokenizeAnsiLine(line);
685
+ const result = [];
686
+ let activeStyles = [];
687
+ const applyStyleToken = (value) => {
688
+ if (SGR_RESET_REGEX.test(value)) {
689
+ activeStyles = [];
690
+ } else {
691
+ activeStyles.push(value);
692
+ }
693
+ };
694
+ let start = 0;
695
+ while (start < tokens.length) {
696
+ if (tokens.slice(start).every((token) => token.kind === "sgr")) {
697
+ if (result.length > 0) break;
698
+ }
699
+ const openingStyles = [...activeStyles];
700
+ const isContinuation = result.length > 0 && hangingIndent.length > 0;
701
+ const indentWidth = isContinuation ? displayWidth(hangingIndent) : 0;
702
+ const maxSegmentWidth = Math.max(1, columns - indentWidth);
703
+ let width = 0;
704
+ let end = start;
705
+ let lastBreak = -1;
706
+ while (end < tokens.length) {
707
+ const token = tokens[end];
708
+ if (token.kind === "sgr") {
709
+ end += 1;
710
+ continue;
711
+ }
712
+ if (width + token.width > maxSegmentWidth && width > 0) break;
713
+ width += token.width;
714
+ end += 1;
715
+ if (token.value === " " || token.value === " ") {
716
+ lastBreak = end;
717
+ }
718
+ }
719
+ let segmentEnd = end;
720
+ if (end < tokens.length && lastBreak > start) {
721
+ const overflowToken = tokens[end];
722
+ if (overflowToken.kind === "char" && overflowToken.value !== " " && overflowToken.width === 1) {
723
+ segmentEnd = lastBreak;
724
+ }
725
+ }
726
+ if (segmentEnd === start) segmentEnd = start + 1;
727
+ let segment = "";
728
+ let sawStyle = openingStyles.length > 0;
729
+ for (let i = start; i < segmentEnd; i += 1) {
730
+ const token = tokens[i];
731
+ segment += token.value;
732
+ if (token.kind === "sgr") {
733
+ sawStyle = true;
734
+ applyStyleToken(token.value);
735
+ }
736
+ }
737
+ const prefix = openingStyles.join("");
738
+ const needsReset = (sawStyle || activeStyles.length > 0) && !segment.endsWith("\x1B[0m");
739
+ const lineContent = `${prefix}${segment}${needsReset ? "\x1B[0m" : ""}`;
740
+ result.push(isContinuation ? `${hangingIndent}${lineContent}` : lineContent);
741
+ start = segmentEnd;
742
+ while (start < tokens.length) {
743
+ const token = tokens[start];
744
+ if (token.kind === "char" && token.value === " ") {
745
+ start += 1;
746
+ continue;
747
+ }
748
+ break;
749
+ }
750
+ }
751
+ return result.length > 0 ? result : [""];
752
+ }
753
+ function wrapTextToLines(text, columns) {
754
+ const result = [];
755
+ for (const logicalLine of text.split("\n")) {
756
+ if (logicalLine === "") {
757
+ result.push("");
758
+ continue;
759
+ }
760
+ let remaining = logicalLine;
761
+ while (remaining.length > 0) {
762
+ const { prefix, rest } = takeDisplayWidth(remaining, columns);
763
+ result.push(prefix);
764
+ remaining = rest;
765
+ }
766
+ }
767
+ return result;
243
768
  }
244
769
 
245
770
  // packages/cli/tui/theme.ts
@@ -402,8 +927,24 @@ function getActiveDensity() {
402
927
  function setActiveDensity(density) {
403
928
  activeDensity = density;
404
929
  }
930
+ var TRUECOLOR_TERM_PROGRAMS = /* @__PURE__ */ new Set([
931
+ "iterm.app",
932
+ "wezterm",
933
+ "ghostty",
934
+ "vscode",
935
+ "hyper",
936
+ "tabby",
937
+ "rio",
938
+ "warpterminal"
939
+ ]);
405
940
  function supportsTruecolor(env = process.env) {
406
- return /truecolor|24bit/i.test(env.COLORTERM ?? "");
941
+ const explicit = (env.NOLO_TUI_TRUECOLOR ?? "").trim().toLowerCase();
942
+ if (explicit === "1" || explicit === "true") return true;
943
+ if (explicit === "0" || explicit === "false") return false;
944
+ if (/truecolor|24bit/i.test(env.COLORTERM ?? "")) return true;
945
+ if (/direct|24bit/i.test(env.TERM ?? "")) return true;
946
+ const program = (env.TERM_PROGRAM ?? "").toLowerCase();
947
+ return TRUECOLOR_TERM_PROGRAMS.has(program);
407
948
  }
408
949
  function resolveTuiBrightness(env = process.env) {
409
950
  const explicit = (env.NOLO_TUI_THEME ?? "").trim().toLowerCase();
@@ -437,6 +978,17 @@ var TERMINAL_BASE = {
437
978
  dark: "1E1E2E",
438
979
  light: "FFFFFF"
439
980
  };
981
+ var activeTerminalBaseHex = null;
982
+ function setActiveTerminalBaseHex(hex) {
983
+ if (hex === null) {
984
+ activeTerminalBaseHex = null;
985
+ return;
986
+ }
987
+ activeTerminalBaseHex = readHexChannels(hex.replace(/^#/, "").toUpperCase()) ? hex.replace(/^#/, "").toUpperCase() : null;
988
+ }
989
+ function resolveTerminalBaseHex(brightness) {
990
+ return activeTerminalBaseHex ?? TERMINAL_BASE[brightness];
991
+ }
440
992
  function readHexChannels(hex) {
441
993
  if (!/^[0-9A-F]{6}$/.test(hex)) return null;
442
994
  return [
@@ -474,21 +1026,49 @@ function diffLineSequences(env = process.env, brightness = resolveTuiBrightness(
474
1026
  const palette = THEME_PALETTES[activeThemeName] ?? THEME_PALETTES.trail;
475
1027
  const successHex = palette[brightness].success.hex;
476
1028
  const dangerHex = palette[brightness].danger.hex;
477
- const weight = brightness === "dark" ? 0.14 : 0.1;
478
- const baseHex = TERMINAL_BASE[brightness];
1029
+ const infoHex = palette[brightness].info.hex;
1030
+ const weight = brightness === "dark" ? 0.18 : 0.12;
1031
+ const baseHex = resolveTerminalBaseHex(brightness);
479
1032
  const addedBgHex = blendHex(successHex, baseHex, weight);
480
1033
  const removedBgHex = blendHex(dangerHex, baseHex, weight);
1034
+ const hunkBgHex = blendHex(infoHex, baseHex, weight * 0.6);
1035
+ const successSgr = hexToSgr(successHex);
1036
+ const dangerSgr = hexToSgr(dangerHex);
1037
+ const infoSgr = hexToSgr(infoHex);
481
1038
  return {
482
1039
  added: {
483
- fg: hexToSgr(successHex),
484
- bg: hexToBgSgr(addedBgHex)
1040
+ fg: successSgr,
1041
+ bg: hexToBgSgr(addedBgHex),
1042
+ bar: `${successSgr}\u258C\x1B[39m`
485
1043
  },
486
1044
  removed: {
487
- fg: hexToSgr(dangerHex),
488
- bg: hexToBgSgr(removedBgHex)
489
- }
1045
+ fg: dangerSgr,
1046
+ bg: hexToBgSgr(removedBgHex),
1047
+ bar: `${dangerSgr}\u258C\x1B[39m`
1048
+ },
1049
+ hunk: {
1050
+ fg: infoSgr,
1051
+ bg: hexToBgSgr(hunkBgHex),
1052
+ bar: " "
1053
+ },
1054
+ context: { fg: "", bg: "", bar: " " }
490
1055
  };
491
1056
  }
1057
+ function renderDiffLine(args) {
1058
+ const { kind, text } = args;
1059
+ const env = args.env ?? process.env;
1060
+ const colorEnabled = args.colorEnabled ?? resolveCliColorEnabled();
1061
+ if (!colorEnabled) return text;
1062
+ const seqs = diffLineSequences(env);
1063
+ if (!seqs) {
1064
+ if (kind === "context") return text;
1065
+ const token = kind === "added" ? "success" : kind === "removed" ? "danger" : "info";
1066
+ return `${themeColorSequence(token, env)}${text}\x1B[39m`;
1067
+ }
1068
+ const seq = seqs[kind];
1069
+ const padding = args.padTo === void 0 ? "" : " ".repeat(Math.max(0, args.padTo - displayWidth(text)));
1070
+ return `${seq.bar}${seq.bg}${seq.fg}${text}${padding}\x1B[0m`;
1071
+ }
492
1072
  function surfaceBackgroundSequence(env = process.env, brightness = resolveTuiBrightness(env)) {
493
1073
  if (!supportsTruecolor(env)) return "";
494
1074
  return hexToBgSgr((SURFACE_HEX[activeThemeName] ?? SURFACE_HEX.trail)[brightness]);
@@ -502,69 +1082,11 @@ function themeText(text, token, colorEnabled = resolveCliColorEnabled(), env = p
502
1082
  if (!colorEnabled) return text;
503
1083
  return `${themeColorSequence(token, env)}${text}\x1B[39m`;
504
1084
  }
505
- function renderDiffCodeBlock(code, env = process.env) {
506
- const border = themeText("\u2502", "chrome", true, env);
507
- const addedColor = themeColorSequence("success", env);
508
- const deletedColor = themeColorSequence("danger", env);
509
- const hunkColor = themeColorSequence("info", env);
510
- const contextColor = themeColorSequence("chrome", env);
511
- const reset = "\x1B[0m";
512
- const lines = code.split("\n").map((line) => {
513
- let color = contextColor;
514
- if (line.startsWith("@@")) {
515
- color = hunkColor;
516
- } else if (line.startsWith("+") && !line.startsWith("+++")) {
517
- color = addedColor;
518
- } else if (line.startsWith("-") && !line.startsWith("---")) {
519
- color = deletedColor;
520
- }
521
- return ` ${border} ${color}${line}${reset}`;
522
- });
523
- return ` ${themeText("\u250C\u2500\u2500\u2500", "chrome", true, env)}
524
- ${lines.join("\n")}
525
- ${themeText("\u2514\u2500\u2500\u2500", "chrome", true, env)}`;
526
- }
527
- function highlightMarkdown(text, colorEnabled = resolveCliColorEnabled(), env = process.env) {
528
- if (!colorEnabled) return text;
529
- let result = text;
530
- result = result.replace(/```([a-zA-Z-]*)\n([\s\S]*?)\n```/g, (match, lang, code) => {
531
- if (lang.toLowerCase() === "diff") {
532
- return renderDiffCodeBlock(code, env);
533
- }
534
- const infoColor = themeColorSequence("info", env);
535
- const reset2 = "\x1B[39m\x1B[22m";
536
- const border = themeText("\u2502", "chrome", true, env);
537
- const formattedCode = code.split("\n").map((line) => ` ${border} ${infoColor}${line}${reset2}`).join("\n");
538
- return ` ${themeText("\u250C\u2500\u2500\u2500", "chrome", true, env)}
539
- ${formattedCode}
540
- ${themeText("\u2514\u2500\u2500\u2500", "chrome", true, env)}`;
541
- });
542
- result = result.replace(/^(#{1,3})\s+(.+)$/gm, (match, hashes, title) => {
543
- const level = hashes.length;
544
- const reset2 = "\x1B[0m";
545
- if (level === 1) {
546
- return `\x1B[1m\x1B[4m${themeColorSequence("accent", env)}${title}${reset2}`;
547
- }
548
- if (level === 2) {
549
- return `\x1B[1m${themeColorSequence("warning", env)}${title}${reset2}`;
550
- }
551
- return `\x1B[1m${themeColorSequence("info", env)}${title}${reset2}`;
552
- });
553
- result = result.replace(
554
- /^(进入 nolo-plan[^\n]*)$/gm,
555
- (match, content) => `${themeColorSequence("chrome", env)}\x1B[2m${content}\x1B[0m`
556
- );
557
- result = result.replace(/^>\s?(.*)$/gm, (match, content) => {
558
- const border = themeColorSequence("chrome", env);
559
- return `${border}\u2502\x1B[39m \x1B[2m${content}\x1B[22m`;
560
- });
561
- result = result.replace(/\*\*([\s\S]*?)\*\*/g, "\x1B[1m$1\x1B[22m");
562
- const mutedColor = themeColorSequence("muted", env);
563
- const reset = "\x1B[39m";
564
- result = result.replace(/`([^`\n]+)`/g, `${mutedColor}$1${reset}`);
565
- result = result.replace(/(?<!\*)\*([^*\n]+?)\*(?!\*)/g, `\x1B[2m$1\x1B[22m`);
566
- result = result.replace(/~~([^~\n]+?)~~/g, `\x1B[2m\x1B[9m$1\x1B[29m\x1B[22m`);
567
- return result;
1085
+ function classifyDiffLine(line) {
1086
+ if (line.startsWith("@@")) return "hunk";
1087
+ if (line.startsWith("+") && !line.startsWith("+++")) return "added";
1088
+ if (line.startsWith("-") && !line.startsWith("---")) return "removed";
1089
+ return "context";
568
1090
  }
569
1091
 
570
1092
  // packages/cli/client/assistantOutput.ts
@@ -743,20 +1265,7 @@ function highlightCodeLine(line, lang, brightness) {
743
1265
  return `${info}${line}${STYLE.reset}`;
744
1266
  }
745
1267
  if (lang === "diff") {
746
- const added = colorSeq("success", brightness);
747
- const deleted = colorSeq("danger", brightness);
748
- const hunk = colorSeq("info", brightness);
749
- const context = colorSeq("chrome", brightness);
750
- const reset2 = STYLE.reset;
751
- let color = context;
752
- if (line.startsWith("@@")) {
753
- color = hunk;
754
- } else if (line.startsWith("+") && !line.startsWith("+++")) {
755
- color = added;
756
- } else if (line.startsWith("-") && !line.startsWith("---")) {
757
- color = deleted;
758
- }
759
- return `${color}${line}${reset2}`;
1268
+ return renderDiffLine({ kind: classifyDiffLine(line), text: line, colorEnabled: true });
760
1269
  }
761
1270
  const regions = scanStringCommentRegions(line, lang);
762
1271
  const keywords = KEYWORDS[lang];
@@ -953,7 +1462,7 @@ function styleRichMarkdownLine(line, brightness) {
953
1462
  const ordered = line.match(/^(\s*)(\d+\.)\s(.+)$/);
954
1463
  if (ordered) {
955
1464
  const styled = styleInlineMarkdown(ordered[3], brightness);
956
- return `${ordered[1]}${colorSeq("accent", brightness)}${ordered[2]}${STYLE.reset} ${styled}`;
1465
+ return `${ordered[1]}${colorSeq("chrome", brightness)}${ordered[2]}${STYLE.reset} ${styled}`;
957
1466
  }
958
1467
  const task = line.match(/^(\s*)(☐|☑)\s(.+)$/);
959
1468
  if (task) {
@@ -1354,456 +1863,254 @@ function formatFetchTreeLines(items) {
1354
1863
  return { header, count, lines };
1355
1864
  }
1356
1865
 
1357
- // packages/cli/tui/i18n.ts
1358
- var ZH_PATTERNS = /^zh/i;
1359
- function parseCliLocale(raw) {
1360
- const normalized = raw?.trim().toLowerCase();
1361
- if (!normalized) return null;
1362
- if (ZH_PATTERNS.test(normalized)) return "zh";
1363
- if (normalized === "en" || normalized.startsWith("en")) return "en";
1364
- return null;
1365
- }
1366
- function detectLocaleFromEnv(env) {
1367
- const explicit = parseCliLocale(env.NOLO_LANG);
1368
- if (explicit) return explicit;
1369
- const candidates = [env.LC_ALL, env.LC_CTYPE, env.LANG].filter(Boolean);
1370
- for (const candidate of candidates) {
1371
- if (ZH_PATTERNS.test(candidate)) return "zh";
1372
- if (candidate && !candidate.startsWith("C.") && !candidate.startsWith("POSIX")) {
1373
- return "en";
1866
+ // packages/cli/node_modules/diff/libesm/diff/base.js
1867
+ var Diff = class {
1868
+ diff(oldStr, newStr, options = {}) {
1869
+ let callback;
1870
+ if (typeof options === "function") {
1871
+ callback = options;
1872
+ options = {};
1873
+ } else if ("callback" in options) {
1874
+ callback = options.callback;
1875
+ }
1876
+ const oldString = this.castInput(oldStr, options);
1877
+ const newString = this.castInput(newStr, options);
1878
+ const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
1879
+ const newTokens = this.removeEmpty(this.tokenize(newString, options));
1880
+ return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
1881
+ }
1882
+ diffWithOptionsObj(oldTokens, newTokens, options, callback) {
1883
+ var _a;
1884
+ const done = (value) => {
1885
+ value = this.postProcess(value, options);
1886
+ if (callback) {
1887
+ setTimeout(function() {
1888
+ callback(value);
1889
+ }, 0);
1890
+ return void 0;
1891
+ } else {
1892
+ return value;
1893
+ }
1894
+ };
1895
+ const newLen = newTokens.length, oldLen = oldTokens.length;
1896
+ let editLength = 1;
1897
+ let maxEditLength = newLen + oldLen;
1898
+ if (options.maxEditLength != null) {
1899
+ maxEditLength = Math.min(maxEditLength, options.maxEditLength);
1900
+ }
1901
+ const maxExecutionTime = (_a = options.timeout) !== null && _a !== void 0 ? _a : Infinity;
1902
+ const abortAfterTimestamp = Date.now() + maxExecutionTime;
1903
+ const bestPath = [{ oldPos: -1, lastComponent: void 0 }];
1904
+ let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
1905
+ if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
1906
+ return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
1907
+ }
1908
+ let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
1909
+ const execEditLength = () => {
1910
+ for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
1911
+ let basePath;
1912
+ const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
1913
+ if (removePath) {
1914
+ bestPath[diagonalPath - 1] = void 0;
1915
+ }
1916
+ let canAdd = false;
1917
+ if (addPath) {
1918
+ const addPathNewPos = addPath.oldPos - diagonalPath;
1919
+ canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
1920
+ }
1921
+ const canRemove = removePath && removePath.oldPos + 1 < oldLen;
1922
+ if (!canAdd && !canRemove) {
1923
+ bestPath[diagonalPath] = void 0;
1924
+ continue;
1925
+ }
1926
+ if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
1927
+ basePath = this.addToPath(addPath, true, false, 0, options);
1928
+ } else {
1929
+ basePath = this.addToPath(removePath, false, true, 1, options);
1930
+ }
1931
+ newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
1932
+ if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
1933
+ return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
1934
+ } else {
1935
+ bestPath[diagonalPath] = basePath;
1936
+ if (basePath.oldPos + 1 >= oldLen) {
1937
+ maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
1938
+ }
1939
+ if (newPos + 1 >= newLen) {
1940
+ minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
1941
+ }
1942
+ }
1943
+ }
1944
+ editLength++;
1945
+ };
1946
+ if (callback) {
1947
+ (function exec() {
1948
+ setTimeout(function() {
1949
+ if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
1950
+ return callback(void 0);
1951
+ }
1952
+ if (!execEditLength()) {
1953
+ exec();
1954
+ }
1955
+ }, 0);
1956
+ })();
1957
+ } else {
1958
+ while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
1959
+ const ret = execEditLength();
1960
+ if (ret) {
1961
+ return ret;
1962
+ }
1963
+ }
1374
1964
  }
1375
1965
  }
1376
- return null;
1377
- }
1378
- function detectLocale(env) {
1379
- return detectLocaleFromEnv(env) ?? "zh";
1380
- }
1381
- var currentLocale = detectLocale(process.env);
1382
- function getCliLocale() {
1383
- return currentLocale;
1384
- }
1385
- function setCliLocale(locale) {
1386
- currentLocale = locale;
1387
- }
1388
- function initCliLocale(env = process.env) {
1389
- currentLocale = detectLocale(env);
1390
- }
1391
- var STRINGS = {
1392
- welcomeHint: {
1393
- en: "Tell nolo what you want. Use /help for commands. Shift+Enter for newline.",
1394
- zh: "\u544A\u8BC9 nolo \u4F60\u60F3\u8981\u4EC0\u4E48\u3002\u8F93\u5165 /help \u67E5\u770B\u547D\u4EE4\u3002Shift+Enter \u6362\u884C\u3002"
1395
- },
1396
- promptLabel: {
1397
- en: "\u276F ",
1398
- zh: "\u276F "
1399
- },
1400
- continueLabel: {
1401
- en: "\u2502 ",
1402
- zh: "\u2502 "
1403
- },
1404
- placeholder: {
1405
- en: "Type a message or / for commands...",
1406
- zh: "\u8F93\u5165\u6D88\u606F\uFF0C\u6216\u7528 / \u67E5\u770B\u547D\u4EE4\u2026"
1407
- },
1408
- newDialog: {
1409
- en: "new dialog",
1410
- zh: "\u65B0\u5BF9\u8BDD"
1411
- },
1412
- startedFreshDialog: {
1413
- en: "Started a fresh dialog.",
1414
- zh: "\u5DF2\u5F00\u59CB\u65B0\u5BF9\u8BDD\u3002"
1415
- },
1416
- bye: {
1417
- en: "Bye.",
1418
- zh: "\u518D\u89C1\u3002"
1419
- },
1420
- resumedDialogPrefix: {
1421
- en: "Resumed dialog",
1422
- zh: "\u5DF2\u6062\u590D\u5BF9\u8BDD"
1423
- },
1424
- resumeInvalidId: {
1425
- en: "does not look like a dialog id. Use /history to pick one.",
1426
- zh: "\u770B\u8D77\u6765\u4E0D\u662F dialog id\u3002\u7528 /history \u4ECE\u5217\u8868\u91CC\u9009\u4E00\u4E2A\u3002"
1427
- },
1428
- dialogResumeCancelled: {
1429
- en: "Dialog resume cancelled.",
1430
- zh: "\u5DF2\u53D6\u6D88\u6062\u590D\u5BF9\u8BDD\u3002"
1431
- },
1432
- agentSwitchCancelled: {
1433
- en: "Agent switch cancelled.",
1434
- zh: "\u5DF2\u53D6\u6D88\u5207\u6362 agent\u3002"
1435
- },
1436
- historyPickerTitle: {
1437
- en: "Resume dialog (\u2191\u2193 Enter Esc)",
1438
- zh: "\u6062\u590D\u5BF9\u8BDD\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Enter \u9009\u62E9 \xB7 Esc \u53D6\u6D88\uFF09"
1439
- },
1440
- noDialogsYet: {
1441
- en: "No dialogs yet.",
1442
- zh: "\u8FD8\u6CA1\u6709\u5386\u53F2\u5BF9\u8BDD\u3002"
1443
- },
1444
- langUsage: {
1445
- en: "Usage: /lang <zh|en>",
1446
- zh: "\u7528\u6CD5\uFF1A/lang <zh|en>"
1447
- },
1448
- stopHint: {
1449
- en: "Esc to stop",
1450
- zh: "Esc \u505C\u6B62\u56DE\u590D"
1451
- },
1452
- queuedHint: {
1453
- en: "queued",
1454
- zh: "\u6392\u961F"
1455
- },
1456
- turnStopped: {
1457
- en: "Stopped this reply.",
1458
- zh: "\u5DF2\u505C\u6B62\u672C\u6B21\u56DE\u590D\u3002"
1459
- },
1460
- turnFailed: {
1461
- en: "This reply failed. Queued messages are kept \u2014 press Enter to resend.",
1462
- zh: "\u672C\u6B21\u56DE\u590D\u51FA\u9519\u3002\u5DF2\u6392\u961F\u7684\u6D88\u606F\u4ECD\u4FDD\u7559\uFF0C\u6309 Enter \u53EF\u91CD\u65B0\u53D1\u9001\u3002"
1463
- },
1464
- quotaExhaustedHint: {
1465
- en: "[nolo] This agent seems to have hit a quota/rate limit (HTTP 429).\nUse /agent to switch to another agent and keep going \u2014 the dialog context is preserved.",
1466
- zh: "[nolo] \u5F53\u524D agent \u4F3C\u4E4E\u989D\u5EA6/\u901F\u7387\u53D7\u9650\uFF08429\uFF09\u3002\n\u53EF\u4EE5\u7528 /agent \u5207\u6362\u5230\u5176\u4ED6 agent \u540E\u7EE7\u7EED\uFF0C\u540C\u4E00\u5BF9\u8BDD\u4F1A\u4FDD\u7559\u4E0A\u4E0B\u6587\u3002"
1467
- },
1468
- balanceExhaustedHint: {
1469
- en: '[nolo] Insufficient balance. Your message is saved in this dialog \u2014 top up, then send again or say "continue".',
1470
- zh: "[nolo] \u4F59\u989D\u4E0D\u8DB3\u3002\u4F60\u521A\u53D1\u7684\u8BDD\u5DF2\u4FDD\u5B58\u5728\u5F53\u524D\u5BF9\u8BDD\u91CC\u2014\u2014\u5145\u503C\u540E\u76F4\u63A5\u518D\u8BF4\u4E00\u53E5\u6216\u8BF4\u300C\u7EE7\u7EED\u300D\u5373\u53EF\uFF0C\u4E0D\u4F1A\u4E22\u4E0A\u4E0B\u6587\u3002"
1471
- },
1472
- dialogPreservedHint: {
1473
- en: '[nolo] This turn failed, but the dialog is kept. Send another message (or say "continue") to keep going in the same conversation.',
1474
- zh: "[nolo] \u672C\u8F6E\u5931\u8D25\u4E86\uFF0C\u4F46\u5BF9\u8BDD\u5DF2\u4FDD\u7559\u3002\u76F4\u63A5\u518D\u8BF4\u4E00\u53E5\uFF08\u6216\u8BF4\u300C\u7EE7\u7EED\u300D\uFF09\u5373\u53EF\u5728\u540C\u4E00\u5BF9\u8BDD\u91CC\u63A5\u7740\u804A\u3002"
1475
- },
1476
- dialogNotSavedHint: {
1477
- en: "[nolo] This turn did not create a dialog. Your next message will start a new conversation \u2014 restate what you need.",
1478
- zh: "[nolo] \u672C\u8F6E\u6CA1\u6709\u5EFA\u6210\u5BF9\u8BDD\u3002\u4E0B\u4E00\u53E5\u4F1A\u662F\u65B0\u5BF9\u8BDD\u2014\u2014\u8BF7\u628A\u4F60\u60F3\u505A\u7684\u4E8B\u518D\u8BF4\u4E00\u904D\u3002"
1479
- },
1480
- copiedLastReply: {
1481
- en: "Copied the last reply to the clipboard.",
1482
- zh: "\u5DF2\u590D\u5236\u6700\u540E\u4E00\u6761\u56DE\u590D\u5230\u526A\u8D34\u677F\u3002"
1483
- },
1484
- copyNothing: {
1485
- en: "Nothing to copy yet.",
1486
- zh: "\u8FD8\u6CA1\u6709\u53EF\u590D\u5236\u7684\u5185\u5BB9\u3002"
1487
- },
1488
- copyFailed: {
1489
- en: "Copy failed",
1490
- zh: "\u590D\u5236\u5931\u8D25"
1491
- },
1492
- copyUnavailable: {
1493
- en: "Clipboard is unavailable in this environment. The last reply was printed above for manual copy.",
1494
- zh: "\u5F53\u524D\u73AF\u5883\u6CA1\u6709\u53EF\u7528\u7684\u526A\u8D34\u677F\u3002\u6700\u540E\u4E00\u6761\u56DE\u590D\u5DF2\u6253\u5370\u5728\u4E0A\u65B9\uFF0C\u53EF\u624B\u52A8\u590D\u5236\u3002"
1495
- },
1496
- copyUsage: {
1497
- en: "Usage: /copy or /copy view",
1498
- zh: "\u7528\u6CD5\uFF1A/copy \u6216 /copy view"
1499
- },
1500
- copyViewTitle: {
1501
- en: "Copy view \u2014 latest AI reply",
1502
- zh: "\u590D\u5236\u89C6\u56FE \u2014 \u6700\u65B0 AI \u56DE\u590D"
1503
- },
1504
- copyViewHint: {
1505
- en: "Drag to select; edge scrolling uses native terminal scrollback. Press Esc or Enter to return.",
1506
- zh: "\u76F4\u63A5\u62D6\u9009\uFF0C\u62D6\u5230\u8FB9\u7F18\u53EF\u7528\u7EC8\u7AEF\u539F\u751F\u56DE\u6EDA\u8DE8\u5C4F\u9009\u62E9\u3002\u6309 Esc \u6216 Enter \u8FD4\u56DE\u3002"
1507
- },
1508
- historyNoToken: {
1509
- en: "History requires an auth token. Run `nolo login` or set AUTH_TOKEN.",
1510
- zh: "\u67E5\u770B\u5386\u53F2\u5BF9\u8BDD\u9700\u8981\u767B\u5F55\u51ED\u8BC1\u3002\u8BF7\u8FD0\u884C `nolo login` \u6216\u8BBE\u7F6E AUTH_TOKEN\u3002"
1511
- },
1512
- historyBadToken: {
1513
- en: "Could not read a user id from AUTH_TOKEN. Run `nolo login` again.",
1514
- zh: "\u65E0\u6CD5\u4ECE AUTH_TOKEN \u89E3\u6790\u51FA\u7528\u6237 id\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C `nolo login`\u3002"
1515
- },
1516
- mouseOn: {
1517
- en: "Mouse mode on: wheel scrolls the transcript; hold Shift (or Option/Fn) to select text.",
1518
- zh: "\u9F20\u6807\u6A21\u5F0F\u5DF2\u5F00\u542F\uFF1A\u6EDA\u8F6E\u6EDA\u52A8\u5BF9\u8BDD\u8BB0\u5F55\uFF1B\u6309\u4F4F Shift\uFF08\u6216 Option/Fn\uFF09\u53EF\u62D6\u9009\u590D\u5236\u3002"
1519
- },
1520
- mouseOff: {
1521
- en: "Mouse mode off: drag to select/copy freely; scroll with PageUp/PageDown.",
1522
- zh: "\u9F20\u6807\u6A21\u5F0F\u5DF2\u5173\u95ED\uFF1A\u53EF\u76F4\u63A5\u62D6\u9009\u590D\u5236\uFF1B\u7528 PageUp/PageDown \u6EDA\u52A8\u5BF9\u8BDD\u8BB0\u5F55\u3002"
1523
- },
1524
- mouseUsage: {
1525
- en: "Usage: /mouse <on|off>",
1526
- zh: "\u7528\u6CD5\uFF1A/mouse <on|off>"
1527
- },
1528
- langSwitched: {
1529
- en: "Language switched to English.",
1530
- zh: "\u5DF2\u5207\u6362\u4E3A\u4E2D\u6587\u3002"
1531
- },
1532
- // --- Tool trace copy ------------------------------------------------------
1533
- // The compact trace shows only status, never timing or output size: a line
1534
- // count told the user nothing actionable and the ms figure read as noise.
1535
- toolNeedsAction: {
1536
- en: "needs action",
1537
- zh: "\u5F85\u786E\u8BA4"
1538
- },
1539
- toolTimedOut: {
1540
- en: "timed out",
1541
- zh: "\u5DF2\u8D85\u65F6"
1542
- },
1543
- toolExitCode: {
1544
- en: "exit",
1545
- zh: "\u9000\u51FA\u7801"
1546
- },
1547
- toolFailed: {
1548
- en: "failed",
1549
- zh: "\u5931\u8D25"
1550
- },
1551
- // --- Dialog (picker / confirm) copy --------------------------------------
1552
- // Key-hint wording is unified across select / multi-select / confirm so the
1553
- // three dialogs read as one family: "<Label> <↑↓ move · Enter choose ·
1554
- // Esc cancel> <count>". Connectors are "·" between keys, two spaces between
1555
- // the label, hint, and count. zh uses full-width parentheses to match the
1556
- // existing historyPickerTitle; en uses ASCII parentheses.
1557
- dialogSelectLabel: {
1558
- en: "Select",
1559
- zh: "\u9009\u62E9"
1560
- },
1561
- dialogSelectHint: {
1562
- en: "(\u2191\u2193 move \xB7 Enter choose \xB7 Esc cancel)",
1563
- zh: "\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Enter \u9009\u62E9 \xB7 Esc \u53D6\u6D88\uFF09"
1564
- },
1565
- dialogMultiSelectLabel: {
1566
- en: "Select",
1567
- zh: "\u9009\u62E9"
1568
- },
1569
- dialogMultiSelectHint: {
1570
- en: "(\u2191\u2193 move \xB7 Space toggle \xB7 Enter submit \xB7 Esc cancel)",
1571
- zh: "\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Space \u5207\u6362 \xB7 Enter \u63D0\u4EA4 \xB7 Esc \u53D6\u6D88\uFF09"
1572
- },
1573
- dialogMultiSelectSelected: {
1574
- en: "selected",
1575
- zh: "\u5DF2\u9009"
1576
- },
1577
- dialogConfirmHint: {
1578
- en: "(\u2191\u2193 move \xB7 Enter choose \xB7 Esc cancel)",
1579
- zh: "\uFF08\u2191\u2193 \u79FB\u52A8 \xB7 Enter \u9009\u62E9 \xB7 Esc \u53D6\u6D88\uFF09"
1580
- },
1581
- dialogConfirmTitle: {
1582
- en: "Confirm destructive shell command",
1583
- zh: "\u786E\u8BA4\u6267\u884C\u7834\u574F\u6027 shell \u547D\u4EE4"
1584
- },
1585
- dialogConfirmBody: {
1586
- en: "This command may delete or reset user content and needs explicit confirmation before it runs.",
1587
- zh: "\u8BE5\u547D\u4EE4\u53EF\u80FD\u5220\u9664\u6216\u91CD\u7F6E\u7528\u6237\u5185\u5BB9\uFF0C\u9700\u8981\u7528\u6237\u660E\u786E\u786E\u8BA4\u540E\u624D\u80FD\u6267\u884C\u3002"
1588
- },
1589
- dialogConfirmCommandLabel: {
1590
- en: "Command",
1591
- zh: "\u547D\u4EE4"
1592
- },
1593
- dialogConfirmCommandTruncated: {
1594
- en: "(truncated)",
1595
- zh: "\uFF08\u5DF2\u622A\u65AD\uFF09"
1596
- },
1597
- dialogConfirmAllowLabel: {
1598
- en: "Allow",
1599
- zh: "\u5141\u8BB8"
1600
- },
1601
- dialogConfirmAllowDetail: {
1602
- en: "execute this time",
1603
- zh: "\u672C\u6B21\u6267\u884C"
1604
- },
1605
- dialogConfirmCancelLabel: {
1606
- en: "Cancel",
1607
- zh: "\u53D6\u6D88"
1608
- },
1609
- dialogConfirmCancelDetail: {
1610
- en: "abort the operation",
1611
- zh: "\u4E2D\u6B62\u64CD\u4F5C"
1612
- },
1613
- contextTitle: {
1614
- en: "Workspace context",
1615
- zh: "\u5DE5\u4F5C\u533A\u4E0A\u4E0B\u6587"
1616
- },
1617
- contextNext: {
1618
- en: "Next:",
1619
- zh: "\u4E0B\u4E00\u6B65\uFF1A"
1620
- },
1621
- contextFieldAgent: {
1622
- en: "agent",
1623
- zh: "\u667A\u80FD\u4F53"
1624
- },
1625
- contextFieldTokens: {
1626
- en: "tokens",
1627
- zh: "\u4EE4\u724C"
1628
- },
1629
- contextFieldDialog: {
1630
- en: "dialog",
1631
- zh: "\u5BF9\u8BDD"
1632
- },
1633
- contextFieldDocs: {
1634
- en: "docs",
1635
- zh: "\u6587\u6863"
1636
- },
1637
- contextFieldSkills: {
1638
- en: "skills",
1639
- zh: "\u6280\u80FD"
1640
- },
1641
- contextFieldProfile: {
1642
- en: "profile",
1643
- zh: "\u914D\u7F6E"
1644
- },
1645
- contextFieldRuntime: {
1646
- en: "runtime",
1647
- zh: "\u8FD0\u884C\u65F6"
1648
- },
1649
- contextFieldTools: {
1650
- en: "tools",
1651
- zh: "\u5DE5\u5177"
1652
- },
1653
- contextFieldThinking: {
1654
- en: "thinking",
1655
- zh: "\u601D\u8003"
1656
- },
1657
- contextFieldServer: {
1658
- en: "server",
1659
- zh: "\u670D\u52A1\u7AEF"
1660
- },
1661
- contextNextAgents: {
1662
- en: "see specialist shortcuts",
1663
- zh: "\u67E5\u770B\u4E13\u7528\u667A\u80FD\u4F53\u5FEB\u6377\u65B9\u5F0F"
1664
- },
1665
- contextNextDoc: {
1666
- en: "add working context",
1667
- zh: "\u6DFB\u52A0\u5DE5\u4F5C\u4E0A\u4E0B\u6587"
1668
- },
1669
- contextNextSkill: {
1670
- en: "attach a skill to this workspace",
1671
- zh: "\u4E3A\u8BE5\u5DE5\u4F5C\u533A\u6302\u8F7D\u6280\u80FD"
1672
- },
1673
- contextNextNew: {
1674
- en: "start a clean dialog",
1675
- zh: "\u5F00\u59CB\u4E00\u4E2A\u5E72\u51C0\u7684\u5BF9\u8BDD"
1676
- },
1677
- agentsTitle: {
1678
- en: "Agents:",
1679
- zh: "\u667A\u80FD\u4F53\uFF1A"
1680
- },
1681
- agentsTip: {
1682
- en: "Tip: run /switch for the full picker, or /switch list for your private agents too.",
1683
- zh: "\u63D0\u793A\uFF1A\u7528 /switch \u6253\u5F00\u5B8C\u6574\u9009\u62E9\u5668\uFF0C\u6216 /switch list \u8FDE\u4F60\u7684\u79C1\u6709\u667A\u80FD\u4F53\u4E00\u8D77\u5217\u51FA\u3002"
1684
- },
1685
- helpText: {
1686
- en: [
1687
- "Commands:",
1688
- " /help Show this help",
1689
- " /new Clear screen and start a fresh dialog",
1690
- " /compact Compact current dialog and fork a new one",
1691
- " /context Show workspace context and next actions",
1692
- " /runtime <mode> Use auto, local, or server runtime",
1693
- " /tools <mode> Control tool trace: hide, compact, verbose",
1694
- " /thinking <mode> Control thinking output: hide, marker, show",
1695
- " /switch Pick an agent interactively (\u2191\u2193, Enter)",
1696
- " /switch list List agents as text",
1697
- " /switch <name> Switch directly by name, alias, or key (alias: /agent)",
1698
- " /agents List platform agent shortcuts",
1699
- " /history Pick a recent dialog to resume (\u2191\u2193, Enter)",
1700
- " /resume <dialogId> Resume a dialog directly by id",
1701
- " /lang <zh|en> Switch interface language",
1702
- " /copy Copy the last reply to the clipboard",
1703
- " /copy view Open native scrollback for partial selection (Ctrl+O)",
1704
- " /mouse <on|off> Toggle mouse mode (off = drag to select text)",
1705
- " /doc List attached docs",
1706
- " /doc attach <doc> Attach a doc to this workspace",
1707
- " /skill List attached skills",
1708
- " /skill attach <ref> Attach a skill (dbKey, name, or SKILL.md path)",
1709
- " /skill detach <ref> Detach a skill",
1710
- " /skill clear Detach all skills",
1711
- " /customize Describe how you want to tune nolo",
1712
- " /tasks List background process tasks (aliases: /jobs, /procs)",
1713
- " /stop <pid|all> Stop background process tasks",
1714
- " /login Show login/profile hint",
1715
- " /profile Show active profile",
1716
- " /update Update the nolo CLI install",
1717
- " /version Show version/update hint",
1718
- " /exit Leave the workspace",
1719
- "",
1720
- "You can also type normally. nolo routes simple read/status requests to CLI commands and sends the rest to the current agent."
1721
- ].join("\n"),
1722
- zh: [
1723
- "\u547D\u4EE4\uFF1A",
1724
- " /help \u663E\u793A\u672C\u5E2E\u52A9",
1725
- " /new \u6E05\u5C4F\u5E76\u5F00\u59CB\u65B0\u5BF9\u8BDD",
1726
- " /compact \u538B\u7F29\u5F53\u524D\u5BF9\u8BDD\u5E76\u5206\u53C9\u51FA\u65B0\u5BF9\u8BDD",
1727
- " /context \u67E5\u770B\u5DE5\u4F5C\u533A\u4E0A\u4E0B\u6587\u4E0E\u540E\u7EED\u64CD\u4F5C",
1728
- " /runtime <mode> \u5207\u6362 runtime\uFF1Aauto\u3001local\u3001server",
1729
- " /tools <mode> \u5DE5\u5177\u8F68\u8FF9\u663E\u793A\uFF1Ahide\u3001compact\u3001verbose",
1730
- " /thinking <mode> \u601D\u8003\u8FC7\u7A0B\u663E\u793A\uFF1Ahide\u3001marker\u3001show",
1731
- " /switch \u4EA4\u4E92\u5F0F\u9009\u62E9 agent\uFF08\u2191\u2193 \u79FB\u52A8\uFF0CEnter \u786E\u8BA4\uFF09",
1732
- " /switch list \u4EE5\u6587\u672C\u5217\u51FA\u5168\u90E8 agent",
1733
- " /switch <name> \u6309\u540D\u79F0\u3001\u522B\u540D\u6216 key \u76F4\u63A5\u5207\u6362\uFF08\u522B\u540D\uFF1A/agent\uFF09",
1734
- " /agents \u5217\u51FA\u5E73\u53F0 agent \u5FEB\u6377\u65B9\u5F0F",
1735
- " /history \u4ECE\u6700\u8FD1\u5BF9\u8BDD\u4E2D\u9009\u62E9\u5E76\u6062\u590D\uFF08\u2191\u2193\uFF0CEnter\uFF09",
1736
- " /resume <dialogId> \u6309 id \u76F4\u63A5\u6062\u590D\u5BF9\u8BDD",
1737
- " /lang <zh|en> \u5207\u6362\u754C\u9762\u8BED\u8A00",
1738
- " /copy \u590D\u5236\u6700\u540E\u4E00\u6761\u56DE\u590D\u5230\u526A\u8D34\u677F",
1739
- " /copy view \u6253\u5F00\u539F\u751F\u56DE\u6EDA\u8FDB\u884C\u8DE8\u5C4F\u62D6\u9009\uFF08Ctrl+O\uFF09",
1740
- " /mouse <on|off> \u5207\u6362\u9F20\u6807\u6A21\u5F0F\uFF08off \u540E\u53EF\u76F4\u63A5\u62D6\u9009\u6587\u672C\uFF09",
1741
- " /doc \u5217\u51FA\u5DF2\u6302\u8F7D\u7684\u6587\u6863",
1742
- " /doc attach <doc> \u6302\u8F7D\u6587\u6863\u5230\u5F53\u524D\u5DE5\u4F5C\u533A",
1743
- " /skill \u5217\u51FA\u5DF2\u6302\u8F7D\u7684\u6280\u80FD",
1744
- " /skill attach <ref> \u6302\u8F7D\u6280\u80FD\uFF08dbKey\u3001\u540D\u79F0\u6216 SKILL.md \u8DEF\u5F84\uFF09",
1745
- " /skill detach <ref> \u5378\u8F7D\u6307\u5B9A\u6280\u80FD",
1746
- " /skill clear \u5378\u8F7D\u5168\u90E8\u6280\u80FD",
1747
- " /customize \u63CF\u8FF0\u4F60\u60F3\u600E\u4E48\u8C03\u6559 nolo",
1748
- " /tasks \u5217\u51FA\u540E\u53F0\u5B50\u8FDB\u7A0B\u4EFB\u52A1\uFF08\u522B\u540D\uFF1A/jobs, /procs\uFF09",
1749
- " /stop <pid|all> \u505C\u6B62\u6307\u5B9A\u7684\u540E\u53F0\u4EFB\u52A1",
1750
- " /login \u67E5\u770B\u767B\u5F55 / \u914D\u7F6E\u63D0\u793A",
1751
- " /profile \u67E5\u770B\u5F53\u524D\u914D\u7F6E\u73AF\u5883",
1752
- " /update \u66F4\u65B0 nolo CLI",
1753
- " /version \u67E5\u770B\u7248\u672C\u4E0E\u66F4\u65B0\u63D0\u793A",
1754
- " /exit \u9000\u51FA\u5DE5\u4F5C\u533A",
1755
- "",
1756
- "\u4E5F\u53EF\u4EE5\u76F4\u63A5\u8F93\u5165\u81EA\u7136\u8BED\u8A00\u3002\u7B80\u5355\u7684\u8BFB\u53D6/\u72B6\u6001\u8BF7\u6C42\u4F1A\u8D70 CLI \u547D\u4EE4\uFF0C\u5176\u4F59\u4EA4\u7ED9\u5F53\u524D agent\u3002"
1757
- ].join("\n")
1966
+ addToPath(path, added, removed, oldPosInc, options) {
1967
+ const last = path.lastComponent;
1968
+ if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) {
1969
+ return {
1970
+ oldPos: path.oldPos + oldPosInc,
1971
+ lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
1972
+ };
1973
+ } else {
1974
+ return {
1975
+ oldPos: path.oldPos + oldPosInc,
1976
+ lastComponent: { count: 1, added, removed, previousComponent: last }
1977
+ };
1978
+ }
1979
+ }
1980
+ extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
1981
+ const newLen = newTokens.length, oldLen = oldTokens.length;
1982
+ let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
1983
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
1984
+ newPos++;
1985
+ oldPos++;
1986
+ commonCount++;
1987
+ if (options.oneChangePerToken) {
1988
+ basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
1989
+ }
1990
+ }
1991
+ if (commonCount && !options.oneChangePerToken) {
1992
+ basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
1993
+ }
1994
+ basePath.oldPos = oldPos;
1995
+ return newPos;
1996
+ }
1997
+ equals(left, right, options) {
1998
+ if (options.comparator) {
1999
+ return options.comparator(left, right);
2000
+ } else {
2001
+ return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
2002
+ }
2003
+ }
2004
+ removeEmpty(array) {
2005
+ const ret = [];
2006
+ for (let i = 0; i < array.length; i++) {
2007
+ if (array[i]) {
2008
+ ret.push(array[i]);
2009
+ }
2010
+ }
2011
+ return ret;
2012
+ }
2013
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2014
+ castInput(value, options) {
2015
+ return value;
2016
+ }
2017
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2018
+ tokenize(value, options) {
2019
+ return Array.from(value);
2020
+ }
2021
+ join(chars) {
2022
+ return chars.join("");
2023
+ }
2024
+ postProcess(changeObjects, options) {
2025
+ return changeObjects;
2026
+ }
2027
+ get useLongestToken() {
2028
+ return false;
2029
+ }
2030
+ buildValues(lastComponent, newTokens, oldTokens) {
2031
+ const components = [];
2032
+ let nextComponent;
2033
+ while (lastComponent) {
2034
+ components.push(lastComponent);
2035
+ nextComponent = lastComponent.previousComponent;
2036
+ delete lastComponent.previousComponent;
2037
+ lastComponent = nextComponent;
2038
+ }
2039
+ components.reverse();
2040
+ const componentLen = components.length;
2041
+ let componentPos = 0, newPos = 0, oldPos = 0;
2042
+ for (; componentPos < componentLen; componentPos++) {
2043
+ const component = components[componentPos];
2044
+ if (!component.removed) {
2045
+ if (!component.added && this.useLongestToken) {
2046
+ let value = newTokens.slice(newPos, newPos + component.count);
2047
+ value = value.map(function(value2, i) {
2048
+ const oldValue = oldTokens[oldPos + i];
2049
+ return oldValue.length > value2.length ? oldValue : value2;
2050
+ });
2051
+ component.value = this.join(value);
2052
+ } else {
2053
+ component.value = this.join(newTokens.slice(newPos, newPos + component.count));
2054
+ }
2055
+ newPos += component.count;
2056
+ if (!component.added) {
2057
+ oldPos += component.count;
2058
+ }
2059
+ } else {
2060
+ component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
2061
+ oldPos += component.count;
2062
+ }
2063
+ }
2064
+ return components;
1758
2065
  }
1759
2066
  };
1760
- function t(key) {
1761
- return STRINGS[key][currentLocale];
1762
- }
1763
- var TOOL_LABELS = {
1764
- // Local workspace tools (packages/agent-runtime/localWorkspaceTools.ts)
1765
- readFile: { en: "Read", zh: "\u8BFB\u53D6" },
1766
- writeFile: { en: "Write", zh: "\u5199\u5165" },
1767
- editFile: { en: "Edit", zh: "\u7F16\u8F91" },
1768
- listFiles: { en: "List", zh: "\u5217\u51FA" },
1769
- searchFiles: { en: "Search", zh: "\u641C\u7D22" },
1770
- globFiles: { en: "Glob", zh: "\u5339\u914D" },
1771
- execShell: { en: "Run", zh: "\u6267\u884C" },
1772
- runCommand: { en: "Run", zh: "\u6267\u884C" },
1773
- captureVisualState: { en: "Capture", zh: "\u622A\u5C4F" },
1774
- // Workspace / diagnostics
1775
- searchWorkspace: { en: "Search workspace", zh: "\u641C\u7D22\u5DE5\u4F5C\u533A" },
1776
- cliDoctor: { en: "Doctor", zh: "\u81EA\u68C0" },
1777
- cliWhoami: { en: "Whoami", zh: "\u67E5\u770B\u8EAB\u4EFD" },
1778
- checkEnv: { en: "Check env", zh: "\u68C0\u67E5\u73AF\u5883" },
1779
- configure: { en: "Configure", zh: "\u914D\u7F6E" },
1780
- notifyUser: { en: "Notify", zh: "\u901A\u77E5" },
1781
- // Docs / dialogs / spaces
1782
- readDoc: { en: "Read doc", zh: "\u8BFB\u53D6\u6587\u6863" },
1783
- createDoc: { en: "Create doc", zh: "\u65B0\u5EFA\u6587\u6863" },
1784
- updateDoc: { en: "Update doc", zh: "\u66F4\u65B0\u6587\u6863" },
1785
- readDialog: { en: "Read dialog", zh: "\u8BFB\u53D6\u5BF9\u8BDD" },
1786
- listDialogs: { en: "List dialogs", zh: "\u5217\u51FA\u5BF9\u8BDD" },
1787
- queryDialogsBySubjectRef: { en: "Query dialogs", zh: "\u67E5\u8BE2\u5BF9\u8BDD" },
1788
- searchDialogMessages: { en: "Search messages", zh: "\u641C\u7D22\u6D88\u606F" },
1789
- listSpaces: { en: "List spaces", zh: "\u5217\u51FA\u7A7A\u95F4" },
1790
- readSpace: { en: "Read space", zh: "\u8BFB\u53D6\u7A7A\u95F4" },
1791
- // Tables
1792
- createTable: { en: "Create table", zh: "\u521B\u5EFA\u8868" },
1793
- queryTableRows: { en: "Query rows", zh: "\u67E5\u8BE2\u8868\u884C" },
1794
- addTableRow: { en: "Add row", zh: "\u65B0\u589E\u8868\u884C" },
1795
- addTableRows: { en: "Add rows", zh: "\u65B0\u589E\u8868\u884C" },
1796
- updateTableRow: { en: "Update row", zh: "\u66F4\u65B0\u8868\u884C" },
1797
- deleteTableRow: { en: "Delete row", zh: "\u5220\u9664\u8868\u884C" },
1798
- // Web
1799
- fetchWebpage: { en: "Fetch page", zh: "\u6293\u53D6\u7F51\u9875" },
1800
- readPage: { en: "Read page", zh: "\u8BFB\u53D6\u7F51\u9875" },
1801
- exaSearch: { en: "Web search", zh: "\u8054\u7F51\u641C\u7D22" },
1802
- // Skill loading
1803
- loadSkill: { en: "Used Skill", zh: "\u4F7F\u7528\u6280\u80FD" }
2067
+
2068
+ // packages/cli/node_modules/diff/libesm/diff/line.js
2069
+ var LineDiff = class extends Diff {
2070
+ constructor() {
2071
+ super(...arguments);
2072
+ this.tokenize = tokenize;
2073
+ }
2074
+ equals(left, right, options) {
2075
+ if (options.ignoreWhitespace) {
2076
+ if (!options.newlineIsToken || !left.includes("\n")) {
2077
+ left = left.trim();
2078
+ }
2079
+ if (!options.newlineIsToken || !right.includes("\n")) {
2080
+ right = right.trim();
2081
+ }
2082
+ } else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
2083
+ if (left.endsWith("\n")) {
2084
+ left = left.slice(0, -1);
2085
+ }
2086
+ if (right.endsWith("\n")) {
2087
+ right = right.slice(0, -1);
2088
+ }
2089
+ }
2090
+ return super.equals(left, right, options);
2091
+ }
1804
2092
  };
1805
- function toolLabel(name) {
1806
- return TOOL_LABELS[name]?.[currentLocale] ?? name;
2093
+ var lineDiff = new LineDiff();
2094
+ function diffLines(oldStr, newStr, options) {
2095
+ return lineDiff.diff(oldStr, newStr, options);
2096
+ }
2097
+ function tokenize(value, options) {
2098
+ if (options.stripTrailingCr) {
2099
+ value = value.replace(/\r\n/g, "\n");
2100
+ }
2101
+ const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
2102
+ if (!linesAndNewlines[linesAndNewlines.length - 1]) {
2103
+ linesAndNewlines.pop();
2104
+ }
2105
+ for (let i = 0; i < linesAndNewlines.length; i++) {
2106
+ const line = linesAndNewlines[i];
2107
+ if (i % 2 && !options.newlineIsToken) {
2108
+ retLines[retLines.length - 1] += line;
2109
+ } else {
2110
+ retLines.push(line);
2111
+ }
2112
+ }
2113
+ return retLines;
1807
2114
  }
1808
2115
 
1809
2116
  // packages/cli/client/toolOutput.ts
@@ -1876,25 +2183,65 @@ function readReadFileRange(metadata) {
1876
2183
  if (!truncated && startLine === 1 && endLine === totalLines) return void 0;
1877
2184
  return `${startLine}-${endLine}/${totalLines}`;
1878
2185
  }
1879
- var EDIT_SNIPPET_MAX_LINES = 5;
2186
+ var EDIT_SNIPPET_MAX_LINES = 10;
1880
2187
  var EDIT_SNIPPET_MAX_WIDTH = 96;
1881
2188
  function formatEditFileSnippet(metadata) {
1882
2189
  const oldSnippet = typeof metadata.oldSnippet === "string" ? metadata.oldSnippet : void 0;
1883
2190
  const newSnippet = typeof metadata.newSnippet === "string" ? metadata.newSnippet : void 0;
1884
2191
  if (!oldSnippet && !newSnippet) return void 0;
1885
- const lines = [];
1886
- if (oldSnippet) {
1887
- for (const line of snippetLines(oldSnippet)) lines.push(`- ${line}`);
2192
+ if (oldSnippet && !newSnippet) {
2193
+ return snippetLinesWithKind(oldSnippet, "removed");
1888
2194
  }
1889
- if (newSnippet) {
1890
- for (const line of snippetLines(newSnippet)) lines.push(`+ ${line}`);
2195
+ if (newSnippet && !oldSnippet) {
2196
+ return snippetLinesWithKind(newSnippet, "added");
1891
2197
  }
1892
- return lines.length ? lines.join("\n") : void 0;
2198
+ const parts = diffLines(oldSnippet, newSnippet);
2199
+ const all = [];
2200
+ for (const part of parts) {
2201
+ const kind = part.added ? "added" : part.removed ? "removed" : "context";
2202
+ const raw = part.value.split("\n");
2203
+ if (raw.length > 0 && raw[raw.length - 1] === "") raw.pop();
2204
+ for (const line of raw) all.push(buildEditLine(kind, line));
2205
+ }
2206
+ const changeCount = all.filter((l) => l.kind !== "context").length;
2207
+ if (changeCount === 0) return void 0;
2208
+ return windowAndTruncate(all, EDIT_SNIPPET_MAX_LINES);
2209
+ }
2210
+ function prefixFor(kind) {
2211
+ return kind === "added" ? "+ " : kind === "removed" ? "- " : " ";
1893
2212
  }
1894
- function snippetLines(snippet) {
2213
+ function buildEditLine(kind, body) {
2214
+ return { kind, text: prefixFor(kind) + truncateByDisplayWidth(body, EDIT_SNIPPET_MAX_WIDTH) };
2215
+ }
2216
+ function snippetLinesWithKind(snippet, kind) {
1895
2217
  const lines = snippet.split(/\r?\n/).filter((line) => line.length > 0);
1896
- const shown = lines.slice(0, EDIT_SNIPPET_MAX_LINES);
1897
- return shown.map((line) => line.length > EDIT_SNIPPET_MAX_WIDTH ? `${line.slice(0, EDIT_SNIPPET_MAX_WIDTH)}\u2026` : line);
2218
+ return lines.slice(0, EDIT_SNIPPET_MAX_LINES).map((line) => buildEditLine(kind, line));
2219
+ }
2220
+ function truncateByDisplayWidth(line, maxWidth) {
2221
+ if (displayWidth(line) <= maxWidth) return line;
2222
+ let width = 0;
2223
+ let kept = "";
2224
+ for (const char of line) {
2225
+ const w = displayWidth(char);
2226
+ if (width + w + 1 > maxWidth) break;
2227
+ kept += char;
2228
+ width += w;
2229
+ }
2230
+ return `${kept}\u2026`;
2231
+ }
2232
+ function windowAndTruncate(lines, maxLines) {
2233
+ if (lines.length <= maxLines) return lines;
2234
+ const firstChange = lines.findIndex((l) => l.kind !== "context");
2235
+ if (firstChange === -1) return lines.slice(0, maxLines);
2236
+ const half = Math.floor(maxLines / 2);
2237
+ let start = Math.max(0, firstChange - half);
2238
+ if (start + maxLines > lines.length) start = Math.max(0, lines.length - maxLines);
2239
+ const kept = lines.slice(start, start + maxLines);
2240
+ const omitted = lines.length - kept.length;
2241
+ if (omitted > 0) {
2242
+ kept.push({ kind: "context", text: ` \u2026 +${omitted} more lines` });
2243
+ }
2244
+ return kept;
1898
2245
  }
1899
2246
  function isFailedToolResult(event) {
1900
2247
  const exitCode = event.metadata?.exitCode;
@@ -1905,6 +2252,22 @@ function isFailedToolResult(event) {
1905
2252
  function isNeedsActionToolResult(event) {
1906
2253
  return Boolean(event.metadata?.actionGate);
1907
2254
  }
2255
+ function readRunAgentName(parsed) {
2256
+ const agentName = typeof parsed.agentName === "string" ? parsed.agentName.trim() : "";
2257
+ if (agentName) return agentName;
2258
+ const name = typeof parsed.name === "string" ? parsed.name.trim() : "";
2259
+ return name || "agent";
2260
+ }
2261
+ function readRunLogLines(parsed) {
2262
+ if (Array.isArray(parsed.logLines)) return parsed.logLines;
2263
+ if (typeof parsed.logTail === "string" && parsed.logTail.trim()) {
2264
+ return parsed.logTail.split("\n");
2265
+ }
2266
+ return void 0;
2267
+ }
2268
+ function readRunErrorMessage(parsed) {
2269
+ return typeof parsed.errorMessage === "string" ? parsed.errorMessage : void 0;
2270
+ }
1908
2271
  function parseUiAskChoiceForCli(event) {
1909
2272
  if (event.toolName !== "ui_ask_choice" && !event.metadata?.uiAskChoice) {
1910
2273
  return null;
@@ -1916,18 +2279,66 @@ function parseUiAskChoiceForCli(event) {
1916
2279
  label: String(c.label ?? "").trim(),
1917
2280
  userMessage: typeof c.userMessage === "string" ? c.userMessage : void 0
1918
2281
  })).filter((c) => c.label.length > 0);
1919
- if (!question || choices.length === 0) return null;
1920
- return { question, choices };
2282
+ const selected = parsed.selected && typeof parsed.selected === "object" ? {
2283
+ label: String(parsed.selected.label ?? "").trim(),
2284
+ userMessage: String(parsed.selected.userMessage ?? "").trim()
2285
+ } : void 0;
2286
+ const answers = Array.isArray(parsed.answers) ? parsed.answers : void 0;
2287
+ const cancelled = Boolean(parsed.cancelled);
2288
+ const resolved = Boolean(
2289
+ event.metadata?.resolved || selected || cancelled || answers && answers.length > 0
2290
+ );
2291
+ if (!resolved && (!question || choices.length === 0)) return null;
2292
+ if (!question && !selected && !cancelled) return null;
2293
+ return {
2294
+ question,
2295
+ choices,
2296
+ ...selected ? { selected } : {},
2297
+ ...answers ? { answers } : {},
2298
+ ...cancelled ? { cancelled: true } : {},
2299
+ resolved
2300
+ };
1921
2301
  }
1922
2302
  function formatUiAskChoiceBlock(event, colorEnabled) {
1923
2303
  const parsed = parseUiAskChoiceForCli(event);
1924
2304
  if (!parsed) return null;
1925
2305
  const lines = [];
1926
2306
  lines.push("");
2307
+ const questionText = parsed.question || "";
1927
2308
  if (colorEnabled) {
1928
- lines.push(`${themeText("\u2753 ", "info", true)}${styleCliText(parsed.question, "cyan", true)}`);
2309
+ lines.push(`${themeText("\u2753 ", "info", true)}${styleCliText(questionText, "cyan", true)}`);
1929
2310
  } else {
1930
- lines.push(`\u2753 ${parsed.question}`);
2311
+ lines.push(`\u2753 ${questionText}`);
2312
+ }
2313
+ if (parsed.resolved) {
2314
+ if (parsed.cancelled) {
2315
+ const cancelled = t("askChoiceHistoryCancelled");
2316
+ lines.push(
2317
+ colorEnabled ? ` ${themeText("\xB7", "chrome", true)} ${themeText(cancelled, "muted", true)}` : ` \xB7 ${cancelled}`
2318
+ );
2319
+ return `${lines.join("\n")}
2320
+ `;
2321
+ }
2322
+ const selectedLabel = parsed.selected?.label || parsed.selected?.userMessage || (parsed.answers ? parsed.answers.map((a) => a.userMessage).filter(Boolean).join(", ") : "");
2323
+ const marker = t("askChoiceHistorySelected");
2324
+ const displayLabel = selectedLabel || "\u2014";
2325
+ if (colorEnabled) {
2326
+ lines.push(
2327
+ ` ${themeText("\u2713", "success", true)} ${themeText(marker, "muted", true)} ${displayLabel}`
2328
+ );
2329
+ } else {
2330
+ lines.push(` \u2713 ${marker} ${displayLabel}`);
2331
+ }
2332
+ if (parsed.answers && parsed.answers.length > 1) {
2333
+ for (const answer of parsed.answers) {
2334
+ if (!answer.userMessage) continue;
2335
+ lines.push(
2336
+ colorEnabled ? ` ${themeText("\xB7", "chrome", true)} ${answer.userMessage}` : ` \xB7 ${answer.userMessage}`
2337
+ );
2338
+ }
2339
+ }
2340
+ return `${lines.join("\n")}
2341
+ `;
1931
2342
  }
1932
2343
  parsed.choices.forEach((choice, i) => {
1933
2344
  const num = String(i + 1);
@@ -1940,7 +2351,7 @@ function formatUiAskChoiceBlock(event, colorEnabled) {
1940
2351
  lines.push(` ${num}. ${label}`);
1941
2352
  }
1942
2353
  });
1943
- const hint = "\u8BF7\u8F93\u5165\u5E8F\u53F7\u9009\u62E9\uFF0C\u6216\u76F4\u63A5\u56DE\u590D\uFF1A";
2354
+ const hint = t("askChoiceHistoryHint");
1944
2355
  if (colorEnabled) {
1945
2356
  lines.push(` ${dimCliText(hint, true)}`);
1946
2357
  } else {
@@ -1956,8 +2367,131 @@ function formatToolTraceLine(text, colorEnabled, accent = "none") {
1956
2367
  return `${themeText(text, "danger", true)}
1957
2368
  `;
1958
2369
  }
1959
- return `${dimCliText(text, true)}
2370
+ return `${dimCliText(text, true)}
2371
+ `;
2372
+ }
2373
+ function recoverOrchestrationDisplayFromContent(toolName, content) {
2374
+ const trimmed = content.trim();
2375
+ if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return content;
2376
+ const labels = agentRunCardLabels();
2377
+ try {
2378
+ const parsed = JSON.parse(trimmed);
2379
+ if (toolName === "listAgents") {
2380
+ const agents = Array.isArray(parsed.agents) ? parsed.agents : [];
2381
+ return formatAgentListCard(agents);
2382
+ }
2383
+ if (toolName === "startAgentRun") {
2384
+ const name = typeof parsed.agentName === "string" && parsed.agentName.trim() ? parsed.agentName.trim() : typeof parsed.name === "string" && parsed.name.trim() ? parsed.name.trim() : "agent";
2385
+ const status = typeof parsed.status === "string" ? parsed.status : "running";
2386
+ return formatStartRunCard(name, status, labels);
2387
+ }
2388
+ if (toolName === "controlAgentRun") {
2389
+ if (Array.isArray(parsed.runs)) {
2390
+ const runs = parsed.runs;
2391
+ return formatListRunsCard(runs, labels);
2392
+ }
2393
+ const status = typeof parsed.status === "string" ? parsed.status : void 0;
2394
+ if (parsed.found === false || status === "not_found") {
2395
+ return formatNotFoundRunCard(labels);
2396
+ }
2397
+ if (status === "killed" || status === "cancelled" || status === "cancelling") {
2398
+ return formatStopRunCard(status, labels);
2399
+ }
2400
+ return formatStatusRunCard(readRunAgentName(parsed), status ?? "\u2014", {
2401
+ errorMessage: readRunErrorMessage(parsed),
2402
+ logLines: readRunLogLines(parsed),
2403
+ labels
2404
+ });
2405
+ }
2406
+ } catch {
2407
+ }
2408
+ return content;
2409
+ }
2410
+ function parseControlAgentRunStatusEvent(event) {
2411
+ const raw = typeof event.content === "string" && event.content.trim() ? event.content.trim() : "";
2412
+ if (!raw.startsWith("{")) return null;
2413
+ try {
2414
+ const parsed = JSON.parse(raw);
2415
+ if (Array.isArray(parsed.runs)) return null;
2416
+ const status = typeof parsed.status === "string" ? parsed.status : void 0;
2417
+ if (parsed.found === false || status === "not_found") return null;
2418
+ if (status === "killed" || status === "cancelled" || status === "cancelling") return null;
2419
+ if (!status) return null;
2420
+ const runId = typeof parsed.runId === "string" && parsed.runId.trim() ? parsed.runId.trim() : typeof event.metadata?.runId === "string" ? event.metadata.runId : "";
2421
+ if (!runId) return null;
2422
+ const agentName = readRunAgentName(parsed);
2423
+ const errorMessage = readRunErrorMessage(parsed);
2424
+ const logLines = readRunLogLines(parsed);
2425
+ const logKey = logLines && logLines.length > 0 ? logLines.join("\n") : "";
2426
+ return { runId, status, agentName, errorMessage, logLines, logKey };
2427
+ } catch {
2428
+ return null;
2429
+ }
2430
+ }
2431
+ function formatOrchestrationCardBlock(event, toolName, colorEnabled) {
2432
+ const rawLabel = toolLabel(toolName);
2433
+ let rawDataStr = typeof event.metadata?.displayData === "string" && event.metadata.displayData.trim() ? event.metadata.displayData : typeof event.content === "string" ? event.content : "";
2434
+ if (typeof event.metadata?.displayData !== "string" && typeof event.content === "string" && event.content.trim()) {
2435
+ rawDataStr = recoverOrchestrationDisplayFromContent(toolName, event.content);
2436
+ }
2437
+ const failed = event.type === "tool-error" || isFailedToolResult(event) || Boolean(event.metadata?.failed) || /^Error:/i.test(rawDataStr.trim());
2438
+ if (failed) {
2439
+ const firstLine = rawDataStr.trim().split("\n")[0] || event.summary || event.message || t("toolFailed");
2440
+ const message = clip(firstLine, 96);
2441
+ if (!colorEnabled) {
2442
+ return `\u2717 ${rawLabel} ${message}
2443
+ `;
2444
+ }
2445
+ const cross = themeText("\u2717", "danger", true);
2446
+ const labelPart2 = themeText(rawLabel, "muted", true);
2447
+ const msgPart = themeText(message, "danger", true);
2448
+ return `${cross} ${labelPart2} ${msgPart}
2449
+ `;
2450
+ }
2451
+ const displayData = rawDataStr.trim();
2452
+ const lines = displayData ? displayData.split("\n").filter((line) => !/^\s*agent\s+agent\s*$/.test(line)) : [];
2453
+ if (!colorEnabled) {
2454
+ let out2 = `\u25CF ${rawLabel}
2455
+ `;
2456
+ for (const line of lines) {
2457
+ out2 += ` ${line}
2458
+ `;
2459
+ }
2460
+ return out2;
2461
+ }
2462
+ const bullet = themeText("\u25CF", "success", true);
2463
+ const labelPart = themeText(rawLabel, "muted", true);
2464
+ let out = `${bullet} ${labelPart}
1960
2465
  `;
2466
+ for (const line of lines) {
2467
+ out += ` ${themeText(line, "muted", true)}
2468
+ `;
2469
+ }
2470
+ return out;
2471
+ }
2472
+ function formatFoldedControlStatusCard(snapshot, colorEnabled) {
2473
+ const labels = agentRunCardLabels();
2474
+ const body = formatStatusRunCard(snapshot.agentName, snapshot.status, {
2475
+ errorMessage: snapshot.errorMessage,
2476
+ logLines: snapshot.logLines,
2477
+ pollCount: snapshot.pollCount,
2478
+ elapsedMs: snapshot.elapsedMs,
2479
+ includeLogTail: snapshot.includeLogTail,
2480
+ labels
2481
+ });
2482
+ return formatOrchestrationCardBlock(
2483
+ {
2484
+ type: "tool-result",
2485
+ round: 0,
2486
+ toolCallId: `fold-${snapshot.runId}`,
2487
+ toolName: "controlAgentRun",
2488
+ content: "",
2489
+ metadata: { displayData: body },
2490
+ elapsedMs: snapshot.elapsedMs
2491
+ },
2492
+ "controlAgentRun",
2493
+ colorEnabled
2494
+ );
1961
2495
  }
1962
2496
  function formatVerboseToolEvent(event, colorEnabled) {
1963
2497
  const round = event.round + 1;
@@ -2006,15 +2540,16 @@ function isRunResultFoldable(event) {
2006
2540
  function formatSearchTreeBlockForCli(items, colorEnabled) {
2007
2541
  if (items.length === 0) return "";
2008
2542
  const { count, lines } = formatSearchTreeLines(items);
2543
+ const titleText = toolLabel("searchFiles");
2009
2544
  if (!colorEnabled) {
2010
- const headerLine2 = `\u2022 Search (${count})
2545
+ const headerLine2 = `\u2022 ${titleText} (${count})
2011
2546
  `;
2012
2547
  const treeLines2 = lines.map((l) => ` ${l.connector}${l.queryText}`).join("\n");
2013
2548
  return `${headerLine2}${treeLines2}
2014
2549
  `;
2015
2550
  }
2016
2551
  const bullet = themeText("\u2022", "chrome", true);
2017
- const title = styleCliText("Search", "bold", true);
2552
+ const title = styleCliText(titleText, "bold", true);
2018
2553
  const countText = themeText(`(${count})`, "muted", true);
2019
2554
  const headerLine = `${bullet} ${title} ${countText}
2020
2555
  `;
@@ -2029,15 +2564,16 @@ function formatSearchTreeBlockForCli(items, colorEnabled) {
2029
2564
  function formatReadTreeBlockForCli(items, colorEnabled) {
2030
2565
  if (items.length === 0) return "";
2031
2566
  const { count, lines } = formatReadTreeLines(items);
2567
+ const titleText = toolLabel("readFile");
2032
2568
  if (!colorEnabled) {
2033
- const headerLine2 = `\u2022 Read (${count})
2569
+ const headerLine2 = `\u2022 ${titleText} (${count})
2034
2570
  `;
2035
2571
  const treeLines2 = lines.map((l) => ` ${l.connector}${l.pathWithRange}`).join("\n");
2036
2572
  return `${headerLine2}${treeLines2}
2037
2573
  `;
2038
2574
  }
2039
2575
  const bullet = themeText("\u2022", "chrome", true);
2040
- const title = styleCliText("Read", "bold", true);
2576
+ const title = styleCliText(titleText, "bold", true);
2041
2577
  const countText = themeText(`(${count})`, "muted", true);
2042
2578
  const headerLine = `${bullet} ${title} ${countText}
2043
2579
  `;
@@ -2052,15 +2588,16 @@ function formatReadTreeBlockForCli(items, colorEnabled) {
2052
2588
  function formatRunTreeBlockForCli(items, colorEnabled) {
2053
2589
  if (items.length === 0) return "";
2054
2590
  const { count, lines } = formatRunTreeLines(items);
2591
+ const titleText = toolLabel("execShell");
2055
2592
  if (!colorEnabled) {
2056
- const headerLine2 = `\u2022 Run (${count})
2593
+ const headerLine2 = `\u2022 ${titleText} (${count})
2057
2594
  `;
2058
2595
  const treeLines2 = lines.map((l) => ` ${l.connector}${l.commandText}`).join("\n");
2059
2596
  return `${headerLine2}${treeLines2}
2060
2597
  `;
2061
2598
  }
2062
2599
  const bullet = themeText("\u2022", "chrome", true);
2063
- const title = styleCliText("Run", "bold", true);
2600
+ const title = styleCliText(titleText, "bold", true);
2064
2601
  const countText = themeText(`(${count})`, "muted", true);
2065
2602
  const headerLine = `${bullet} ${title} ${countText}
2066
2603
  `;
@@ -2075,15 +2612,16 @@ function formatRunTreeBlockForCli(items, colorEnabled) {
2075
2612
  function formatFetchTreeBlockForCli(items, colorEnabled) {
2076
2613
  if (items.length === 0) return "";
2077
2614
  const { count, lines } = formatFetchTreeLines(items);
2615
+ const titleText = toolLabel("fetchWebpage");
2078
2616
  if (!colorEnabled) {
2079
- const headerLine2 = `\u2022 Fetch (${count})
2617
+ const headerLine2 = `\u2022 ${titleText} (${count})
2080
2618
  `;
2081
2619
  const treeLines2 = lines.map((l) => ` ${l.connector}${l.urlText}`).join("\n");
2082
2620
  return `${headerLine2}${treeLines2}
2083
2621
  `;
2084
2622
  }
2085
2623
  const bullet = themeText("\u2022", "chrome", true);
2086
- const title = styleCliText("Fetch", "bold", true);
2624
+ const title = styleCliText(titleText, "bold", true);
2087
2625
  const countText = themeText(`(${count})`, "muted", true);
2088
2626
  const headerLine = `${bullet} ${title} ${countText}
2089
2627
  `;
@@ -2137,24 +2675,24 @@ function formatCompactToolLine(event, pending, colorEnabled) {
2137
2675
  const skillName = resolveLoadSkillName(event);
2138
2676
  const content = typeof event.content === "string" ? event.content : "";
2139
2677
  const failed2 = /^Skill\s+"[^"]*"\s+not found/.test(content) || isFailedToolResult(event);
2678
+ const labelText = t("usedSkillLabel");
2140
2679
  if (failed2) {
2141
2680
  const message = clip(content.split("\n")[0] || t("toolFailed"), 96);
2142
- return formatToolTraceLine(`\u25B8 Used Skill (${skillName}) \u2717 ${message}`, colorEnabled, "error");
2681
+ return formatToolTraceLine(`\u25B8 ${labelText} (${skillName}) \u2717 ${message}`, colorEnabled, "error");
2143
2682
  }
2144
- const resultLine = `Skill "${skillName}" loaded inline. Follow its instructions.`;
2145
2683
  if (!colorEnabled) {
2146
- return `\u25CF Used Skill (${skillName})
2147
- ${resultLine}
2684
+ return `\u2726 ${labelText}: ${skillName}
2148
2685
  `;
2149
2686
  }
2150
- const bullet = themeText("\u25CF", "success", true);
2151
- const labelPart = themeText("Used Skill", "muted", true);
2152
- const namePart = themeText(`(${skillName})`, "chrome", true);
2153
- const detail = themeText(` ${resultLine}`, "muted", true);
2154
- return `${bullet} ${labelPart} ${namePart}
2155
- ${detail}
2687
+ const star = themeText("\u2726", "success", true);
2688
+ const labelPart = themeText(labelText, "muted", true);
2689
+ const namePart = themeText(skillName, "chrome", true);
2690
+ return `${star} ${labelPart}: ${namePart}
2156
2691
  `;
2157
2692
  }
2693
+ if (event.type === "tool-result" && (toolName === "listAgents" || toolName === "startAgentRun" || toolName === "controlAgentRun")) {
2694
+ return formatOrchestrationCardBlock(event, toolName, colorEnabled);
2695
+ }
2158
2696
  if (event.type === "tool-result" && (event.toolName === "ui_ask_choice" || event.metadata?.uiAskChoice)) {
2159
2697
  const block = formatUiAskChoiceBlock(event, colorEnabled);
2160
2698
  if (block) return block;
@@ -2176,36 +2714,17 @@ ${detail}
2176
2714
  mainLine = `${chromePointer} ${mutedLabel}${argsPart} ${statusToken}${suffixPart}
2177
2715
  `;
2178
2716
  }
2179
- if (!hint.detail) return mainLine;
2180
- const detailLines = hint.detail.split("\n").map((line) => formatEditDetailLine(line, colorEnabled)).join("");
2181
- return `${mainLine}${detailLines}`;
2717
+ if (!hint.detail?.length) return mainLine;
2718
+ return `${mainLine}${formatEditDetailBlock(hint.detail, colorEnabled)}`;
2182
2719
  }
2183
- function formatEditDetailLine(line, colorEnabled) {
2184
- const marker = line.slice(0, 2);
2185
- const rest = line.slice(2);
2186
- if (!colorEnabled) return ` ${line}
2187
- `;
2188
- const diff = diffLineSequences();
2189
- if (!diff) {
2190
- const color = marker === "- " ? "red" : marker === "+ " ? "green" : void 0;
2191
- if (color) {
2192
- return ` ${styleCliText(marker, color, true)}${dimCliText(rest, true)}
2193
- `;
2194
- }
2195
- return ` ${dimCliText(line, true)}
2196
- `;
2197
- }
2198
- const RESET2 = "\x1B[0m";
2199
- if (marker === "- ") {
2200
- return ` ${diff.removed.bg}${diff.removed.fg}- ${rest}${RESET2}
2201
- `;
2202
- }
2203
- if (marker === "+ ") {
2204
- return ` ${diff.added.bg}${diff.added.fg}+ ${rest}${RESET2}
2205
- `;
2720
+ function formatEditDetailBlock(lines, colorEnabled) {
2721
+ if (!colorEnabled) {
2722
+ return lines.map((line) => ` ${line.text}
2723
+ `).join("");
2206
2724
  }
2207
- return ` ${dimCliText(line, true)}
2208
- `;
2725
+ const padTo = Math.max(...lines.map((line) => displayWidth(line.text))) + 1;
2726
+ return lines.map((line) => ` ${renderDiffLine({ kind: line.kind, text: line.text, padTo, colorEnabled: true })}
2727
+ `).join("");
2209
2728
  }
2210
2729
  function createToolEventFormatter(mode, colorEnabled = resolveCliColorEnabled()) {
2211
2730
  const pending = /* @__PURE__ */ new Map();
@@ -2213,8 +2732,33 @@ function createToolEventFormatter(mode, colorEnabled = resolveCliColorEnabled())
2213
2732
  let searchBuffer = [];
2214
2733
  let runBuffer = [];
2215
2734
  let fetchBuffer = [];
2735
+ let statusFold = null;
2736
+ const lastEmittedLogByRunId = /* @__PURE__ */ new Map();
2737
+ const flushStatusFold = () => {
2738
+ if (!statusFold) return "";
2739
+ const fold = statusFold;
2740
+ statusFold = null;
2741
+ const prevLog = lastEmittedLogByRunId.get(fold.runId);
2742
+ const includeLogTail = Boolean(fold.logKey) && fold.logKey !== prevLog;
2743
+ if (fold.logKey) {
2744
+ lastEmittedLogByRunId.set(fold.runId, fold.logKey);
2745
+ }
2746
+ return formatFoldedControlStatusCard(
2747
+ {
2748
+ runId: fold.runId,
2749
+ status: fold.status,
2750
+ agentName: fold.agentName,
2751
+ errorMessage: fold.errorMessage,
2752
+ logLines: fold.logLines,
2753
+ pollCount: fold.pollCount,
2754
+ elapsedMs: fold.elapsedMs,
2755
+ includeLogTail
2756
+ },
2757
+ colorEnabled
2758
+ );
2759
+ };
2216
2760
  const flushBuffers = () => {
2217
- let out = "";
2761
+ let out = flushStatusFold();
2218
2762
  if (readBuffer.length > 0) {
2219
2763
  const items = readBuffer.map((evt) => {
2220
2764
  const call = pending.get(evt.toolCallId);
@@ -2263,6 +2807,51 @@ function createToolEventFormatter(mode, colorEnabled = resolveCliColorEnabled())
2263
2807
  const formatter = (event) => {
2264
2808
  if (mode === "hide") return "";
2265
2809
  if (mode === "verbose") return formatVerboseToolEvent(event, colorEnabled);
2810
+ if (event.toolName === "controlAgentRun") {
2811
+ if (event.type === "tool-call") {
2812
+ pending.set(event.toolCallId, {
2813
+ toolName: event.toolName,
2814
+ argumentsPreview: event.argumentsPreview
2815
+ });
2816
+ return "";
2817
+ }
2818
+ if (event.type === "tool-result") {
2819
+ const snapshot = parseControlAgentRunStatusEvent(event);
2820
+ if (snapshot) {
2821
+ let out = "";
2822
+ if (statusFold && statusFold.runId !== snapshot.runId) {
2823
+ out += flushStatusFold();
2824
+ }
2825
+ if (!statusFold) {
2826
+ statusFold = {
2827
+ ...snapshot,
2828
+ pollCount: 1,
2829
+ elapsedMs: event.elapsedMs
2830
+ };
2831
+ } else {
2832
+ statusFold = {
2833
+ runId: snapshot.runId,
2834
+ status: snapshot.status,
2835
+ agentName: snapshot.agentName,
2836
+ errorMessage: snapshot.errorMessage ?? statusFold.errorMessage,
2837
+ logLines: snapshot.logLines ?? statusFold.logLines,
2838
+ logKey: snapshot.logKey || statusFold.logKey,
2839
+ pollCount: statusFold.pollCount + 1,
2840
+ elapsedMs: event.elapsedMs
2841
+ };
2842
+ }
2843
+ pending.delete(event.toolCallId);
2844
+ if (isAgentRunTerminalStatus(snapshot.status)) {
2845
+ out += flushBuffers();
2846
+ }
2847
+ return out;
2848
+ }
2849
+ const flushed2 = flushBuffers();
2850
+ const call2 = pending.get(event.toolCallId);
2851
+ pending.delete(event.toolCallId);
2852
+ return `${flushed2}${formatCompactToolLine(event, call2, colorEnabled)}`;
2853
+ }
2854
+ }
2266
2855
  if (isReadToolName(event.toolName)) {
2267
2856
  if (event.type === "tool-call") {
2268
2857
  pending.set(event.toolCallId, {
@@ -2835,10 +3424,165 @@ function isKnownServerPlatformAgent(options) {
2835
3424
  );
2836
3425
  }
2837
3426
 
3427
+ // packages/core/collapsedPaste.ts
3428
+ var COLLAPSE_PASTE_MIN_LINES = 8;
3429
+ var COLLAPSE_PASTE_MIN_CHARS = 400;
3430
+ var COLLAPSED_PASTE_PLACEHOLDER_RE = /\[paste #(\d+) · (\d+) lines\]/g;
3431
+ var COLLAPSED_PASTE_MODEL_REFERENCE_RE = /\[paste #(\d+)(?: scope:([a-zA-Z0-9_-]+))? · [^\]]+; full content available via readPastedText\(pasteId=(\d+)\)\]/g;
3432
+ function countTextLines(text) {
3433
+ if (text.length === 0) return 0;
3434
+ let lines = 1;
3435
+ for (let i = 0; i < text.length; i += 1) {
3436
+ if (text.charCodeAt(i) === 10) lines += 1;
3437
+ }
3438
+ return lines;
3439
+ }
3440
+ function shouldCollapsePaste(text, threshold = {}) {
3441
+ const minLines = threshold.minLines ?? COLLAPSE_PASTE_MIN_LINES;
3442
+ const minChars = threshold.minChars ?? COLLAPSE_PASTE_MIN_CHARS;
3443
+ if (text.length === 0) return false;
3444
+ if (text.length >= minChars) return true;
3445
+ return countTextLines(text) >= minLines;
3446
+ }
3447
+ function formatPasteByteSize(bytes) {
3448
+ if (!Number.isFinite(bytes) || bytes < 0) return "0 B";
3449
+ if (bytes < 1024) return `${Math.round(bytes)} B`;
3450
+ if (bytes < 1024 * 1024) {
3451
+ const kb = bytes / 1024;
3452
+ return `${kb >= 10 ? kb.toFixed(0) : kb.toFixed(1)} KB`;
3453
+ }
3454
+ const mb = bytes / (1024 * 1024);
3455
+ return `${mb >= 10 ? mb.toFixed(0) : mb.toFixed(1)} MB`;
3456
+ }
3457
+ function estimatePasteBytes(text) {
3458
+ let bytes = 0;
3459
+ for (let i = 0; i < text.length; i += 1) {
3460
+ const code = text.charCodeAt(i);
3461
+ if (code <= 127) bytes += 1;
3462
+ else if (code <= 2047) bytes += 2;
3463
+ else if (code >= 55296 && code <= 56319) {
3464
+ bytes += 4;
3465
+ i += 1;
3466
+ } else bytes += 3;
3467
+ }
3468
+ return bytes;
3469
+ }
3470
+ function formatCollapsedPastePlaceholder(id, text) {
3471
+ const lines = countTextLines(text);
3472
+ return `[paste #${id} \xB7 ${lines} lines]`;
3473
+ }
3474
+ function generatePasteScope() {
3475
+ if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
3476
+ return crypto.randomUUID().slice(0, 8);
3477
+ }
3478
+ return Math.random().toString(36).slice(2, 10);
3479
+ }
3480
+ function formatCollapsedPasteModelReference(id, text, scope) {
3481
+ const lines = countTextLines(text);
3482
+ const size = formatPasteByteSize(estimatePasteBytes(text));
3483
+ const scopeAttr = scope ? ` scope:${scope}` : "";
3484
+ return `[paste #${id}${scopeAttr} \xB7 ${lines} lines \xB7 ${size}; full content available via readPastedText(pasteId=${id})]`;
3485
+ }
3486
+ function createCollapsedPasteStore(scope) {
3487
+ return { scope: scope ?? generatePasteScope(), nextId: 1, items: /* @__PURE__ */ new Map() };
3488
+ }
3489
+ function allocateCollapsedPaste(store, text) {
3490
+ const id = store.nextId;
3491
+ store.nextId += 1;
3492
+ store.items.set(id, text);
3493
+ return { id, placeholder: formatCollapsedPastePlaceholder(id, text) };
3494
+ }
3495
+ function releaseCollapsedPaste(store, id) {
3496
+ store.items.delete(id);
3497
+ }
3498
+ function clearCollapsedPasteStore(store) {
3499
+ store.items.clear();
3500
+ store.nextId = 1;
3501
+ store.scope = generatePasteScope();
3502
+ }
3503
+ function expandCollapsedPastes(buffer, store) {
3504
+ COLLAPSED_PASTE_MODEL_REFERENCE_RE.lastIndex = 0;
3505
+ const expandedReferences = buffer.replace(
3506
+ COLLAPSED_PASTE_MODEL_REFERENCE_RE,
3507
+ (match, _displayIdRaw, scopeRaw, idRaw) => {
3508
+ if (scopeRaw && scopeRaw === store.scope) {
3509
+ const full = store.items.get(Number(idRaw));
3510
+ return full === void 0 ? match : full;
3511
+ }
3512
+ return match;
3513
+ }
3514
+ );
3515
+ if (store.items.size === 0) return expandedReferences;
3516
+ COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
3517
+ return expandedReferences.replace(COLLAPSED_PASTE_PLACEHOLDER_RE, (match, idRaw) => {
3518
+ const id = Number(idRaw);
3519
+ const full = store.items.get(id);
3520
+ return full === void 0 ? match : full;
3521
+ });
3522
+ }
3523
+ function replaceCollapsedPastesWithReferences(buffer, store) {
3524
+ if (store.items.size === 0) return buffer;
3525
+ COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
3526
+ return buffer.replace(COLLAPSED_PASTE_PLACEHOLDER_RE, (match, idRaw) => {
3527
+ const id = Number(idRaw);
3528
+ const full = store.items.get(id);
3529
+ return full === void 0 ? match : formatCollapsedPasteModelReference(id, full, store.scope);
3530
+ });
3531
+ }
3532
+ function releaseCollapsedPasteReferences(buffer, store) {
3533
+ const ids = /* @__PURE__ */ new Set();
3534
+ COLLAPSED_PASTE_MODEL_REFERENCE_RE.lastIndex = 0;
3535
+ let modelMatch;
3536
+ while ((modelMatch = COLLAPSED_PASTE_MODEL_REFERENCE_RE.exec(buffer)) !== null) {
3537
+ const id = Number(modelMatch[3]);
3538
+ const scope = modelMatch[2];
3539
+ if (scope && scope === store.scope) {
3540
+ ids.add(id);
3541
+ }
3542
+ }
3543
+ COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
3544
+ let placeholderMatch;
3545
+ while ((placeholderMatch = COLLAPSED_PASTE_PLACEHOLDER_RE.exec(buffer)) !== null) {
3546
+ ids.add(Number(placeholderMatch[1]));
3547
+ }
3548
+ for (const id of ids) releaseCollapsedPaste(store, id);
3549
+ }
3550
+ function expandRangeToCollapsedPasteChips(buffer, start, end) {
3551
+ let s = Math.max(0, Math.min(start, end));
3552
+ let e = Math.max(s, Math.max(start, end));
3553
+ if (s === e) return { start: s, end: e };
3554
+ COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
3555
+ let match;
3556
+ while ((match = COLLAPSED_PASTE_PLACEHOLDER_RE.exec(buffer)) !== null) {
3557
+ const chipStart = match.index;
3558
+ const chipEnd = chipStart + match[0].length;
3559
+ if (chipStart < e && chipEnd > s) {
3560
+ if (chipStart < s) s = chipStart;
3561
+ if (chipEnd > e) e = chipEnd;
3562
+ }
3563
+ }
3564
+ return { start: s, end: e };
3565
+ }
3566
+ function findCollapsedPasteSpanAt(buffer, pos, opts = {}) {
3567
+ COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
3568
+ let match;
3569
+ while ((match = COLLAPSED_PASTE_PLACEHOLDER_RE.exec(buffer)) !== null) {
3570
+ const start = match.index;
3571
+ const end = start + match[0].length;
3572
+ const inside = pos > start && pos < end;
3573
+ const atEnd = opts.preferLeft && pos === end;
3574
+ const atStart = !opts.preferLeft && pos === start;
3575
+ if (inside || atEnd || atStart) {
3576
+ return { id: Number(match[1]), start, end };
3577
+ }
3578
+ }
3579
+ return null;
3580
+ }
3581
+
2838
3582
  // packages/cli/client/agentRun.ts
2839
3583
  import { ulid } from "ulid";
2840
3584
  async function loadRunLocalAgentTurn() {
2841
- const { runLocalAgentTurn } = await import("./agentRuntimeLocal-UQBMQI2M.js");
3585
+ const { runLocalAgentTurn } = await import("./agentRuntimeLocal-PR67XWQK.js");
2842
3586
  return runLocalAgentTurn;
2843
3587
  }
2844
3588
  async function resolveCurrentMachineId(options) {
@@ -2851,6 +3595,12 @@ function resolveRequestedRuntimeMode(options) {
2851
3595
  return envMode;
2852
3596
  return "auto";
2853
3597
  }
3598
+ function canResolveCollapsedPasteReference(store, content) {
3599
+ const expand = (text) => expandCollapsedPastes(text, store) !== text;
3600
+ if (typeof content === "string") return expand(content);
3601
+ if (!Array.isArray(content)) return false;
3602
+ return content.some((part) => part.type === "text" && expand(part.text));
3603
+ }
2854
3604
  function buildDefaultLocalRuntimeAdapter(options) {
2855
3605
  return createCliLocalRuntimeAdapter({
2856
3606
  env: options.env,
@@ -2858,7 +3608,8 @@ function buildDefaultLocalRuntimeAdapter(options) {
2858
3608
  cwd: options.localRuntimeCwd,
2859
3609
  output: options.output,
2860
3610
  ...options.confirmDestructiveAction ? { confirmDestructiveAction: options.confirmDestructiveAction } : {},
2861
- ...options.requestUserChoice ? { requestUserChoice: options.requestUserChoice } : {}
3611
+ ...options.requestUserChoice ? { requestUserChoice: options.requestUserChoice } : {},
3612
+ ...options.pastedTextStore?.items.size ? { pastedTextStore: options.pastedTextStore } : {}
2862
3613
  });
2863
3614
  }
2864
3615
  function resolveLocalRuntimeAdapter(options) {
@@ -3083,12 +3834,14 @@ async function runHttpAgentTurn(options, authToken) {
3083
3834
  (name) => name.trim()
3084
3835
  );
3085
3836
  const shouldStream = !options.noStream && !options.background;
3837
+ const expandedMessage = options.pastedTextStore?.items.size ? expandCollapsedPastes(options.message, options.pastedTextStore) : options.message;
3838
+ const serverContextBlockScopes = options.contextBlockScopes && options.contextBlockScopes.length > 0 ? options.contextBlockScopes : options.extraContextBlocks && options.extraContextBlocks.length > 0 ? options.extraContextBlocks.map((block) => ({
3839
+ content: block,
3840
+ cacheScope: "turn"
3841
+ })) : void 0;
3086
3842
  const buildRequestBody = (stream) => JSON.stringify({
3087
3843
  agentKey: options.agentKey,
3088
- userInput: buildUserInputContent(
3089
- options.extraContextBlocks?.length ? [...options.extraContextBlocks, "", options.message].join("\n") : options.message,
3090
- options.imageUrls
3091
- ),
3844
+ userInput: buildUserInputContent(expandedMessage, options.imageUrls),
3092
3845
  runtimeContext: {
3093
3846
  surface: "cli",
3094
3847
  host: "terminal",
@@ -3108,6 +3861,7 @@ async function runHttpAgentTurn(options, authToken) {
3108
3861
  ...options.background ? { background: true } : {},
3109
3862
  ...typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {},
3110
3863
  ...options.modelOverride ? { runtimeOptions: { quickChatModelOverride: options.modelOverride } } : {},
3864
+ ...serverContextBlockScopes ? { contextBlockScopes: serverContextBlockScopes } : {},
3111
3865
  stream
3112
3866
  });
3113
3867
  const postAgentRun = (stream) => fetchImpl(`${options.serverUrl}/api/agent/run`, {
@@ -3265,7 +4019,7 @@ async function runLocalAgentTurnForCli(options, settings) {
3265
4019
  } : void 0;
3266
4020
  const currentDialogId = options.continueDialogId ?? ulid();
3267
4021
  const runChildTurn = async (input) => {
3268
- const { runLocalAgentTurn } = await import("./agentRuntimeLocal-UQBMQI2M.js");
4022
+ const { runLocalAgentTurn } = await import("./agentRuntimeLocal-PR67XWQK.js");
3269
4023
  return runLocalAgentTurn(input);
3270
4024
  };
3271
4025
  const createFreshChildBaseAdapter = () => {
@@ -3313,6 +4067,7 @@ async function runLocalAgentTurnForCli(options, settings) {
3313
4067
  spaceId: options.spaceId,
3314
4068
  runtimeContext
3315
4069
  });
4070
+ const expandedMessage = options.pastedTextStore?.items.size ? expandCollapsedPastes(options.message, options.pastedTextStore) : options.message;
3316
4071
  const workingLabel = `${options.agentName} -> working locally`;
3317
4072
  const turnOutput = createCliTurnOutput({
3318
4073
  options,
@@ -3325,6 +4080,19 @@ async function runLocalAgentTurnForCli(options, settings) {
3325
4080
  adapter,
3326
4081
  agentRef: options.agentKey,
3327
4082
  input: buildUserInputContent(options.message, options.imageUrls),
4083
+ ...expandedMessage !== options.message ? {
4084
+ persistedInput: buildUserInputContent(
4085
+ expandedMessage,
4086
+ options.imageUrls
4087
+ ),
4088
+ persistedInputReference: buildUserInputContent(
4089
+ options.message,
4090
+ options.imageUrls
4091
+ )
4092
+ } : {},
4093
+ ...options.pastedTextStore ? {
4094
+ contextReferenceResolver: (reference) => canResolveCollapsedPasteReference(options.pastedTextStore, reference)
4095
+ } : {},
3328
4096
  continueDialogId: currentDialogId,
3329
4097
  spaceId: options.spaceId,
3330
4098
  category: options.category,
@@ -3333,8 +4101,7 @@ async function runLocalAgentTurnForCli(options, settings) {
3333
4101
  background: options.background,
3334
4102
  noStream: options.noStream,
3335
4103
  ...runtimeContext ? { runtimeContext } : {},
3336
- ...options.extraContextBlocks?.length ? { contextBlocks: options.extraContextBlocks } : {},
3337
- ...options.contextBlockScopes?.length ? { contextBlockScopes: options.contextBlockScopes } : {},
4104
+ ...options.contextBlockScopes?.length ? { contextBlockScopes: options.contextBlockScopes } : options.extraContextBlocks?.length ? { contextBlocks: options.extraContextBlocks } : {},
3338
4105
  ...typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {},
3339
4106
  ...options.actionGateHandler ? { onActionGate: options.actionGateHandler } : {},
3340
4107
  onLoopEvent: (event) => {
@@ -3370,10 +4137,12 @@ async function runLocalAgentTurnForCli(options, settings) {
3370
4137
  turnOutput.spinner.stop();
3371
4138
  const savedDialogId = error?.dialogId;
3372
4139
  if (error?.code === LOCAL_TURN_ABORTED_CODE || options.abortSignal?.aborted) {
4140
+ const pendingToolName = error?.pendingToolName;
3373
4141
  return {
3374
4142
  exitCode: 0,
3375
4143
  streamInterrupted: true,
3376
- ...savedDialogId ? { dialogId: savedDialogId } : {}
4144
+ ...savedDialogId ? { dialogId: savedDialogId } : {},
4145
+ ...pendingToolName ? { pendingToolName } : {}
3377
4146
  };
3378
4147
  }
3379
4148
  if (settings.reportFailure) {
@@ -3406,7 +4175,8 @@ async function runAgentTurn(options) {
3406
4175
  exitCode: localResult.exitCode,
3407
4176
  ...localResult.dialogId ? { dialogId: localResult.dialogId } : {},
3408
4177
  ...localResult.turnTokens ? { turnTokens: localResult.turnTokens } : {},
3409
- ...localResult.streamInterrupted ? { streamInterrupted: localResult.streamInterrupted } : {}
4178
+ ...localResult.streamInterrupted ? { streamInterrupted: localResult.streamInterrupted } : {},
4179
+ ...localResult.pendingToolName ? { pendingToolName: localResult.pendingToolName } : {}
3410
4180
  };
3411
4181
  }
3412
4182
  if (isMissingLocalAgentConfigError(localResult.localError, options.agentKey)) {
@@ -3460,196 +4230,6 @@ async function runAgentTurn(options) {
3460
4230
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
3461
4231
  import { join as join2 } from "node:path";
3462
4232
 
3463
- // packages/agent-runtime/quickChatIntentCore.ts
3464
- var INTENT_MODEL = "deepseek-v4-flash";
3465
- var INTENT_PROVIDER = "deepseek";
3466
- var QUICK_CHAT_INTENT_TIMEOUT_MS = 4e3;
3467
- var SHORT_GREETING_MAX_LENGTH = 20;
3468
- var SHORT_GREETING_PATTERN = /^(?:hi|hello|hey|hiya|yo|sup|howdy|嗨|哈喽|哈囉|你好|您好|在吗|在嘛|喂|早上好|中午好|下午好|晚上好|拜拜|再见|谢谢|thanks|thx|ok|好的|收到|了解)[!.。,、~~]?$/iu;
3469
- function isShortGreeting(text) {
3470
- const trimmed = text.trim();
3471
- if (!trimmed) return false;
3472
- if (trimmed.length > SHORT_GREETING_MAX_LENGTH) return false;
3473
- return SHORT_GREETING_PATTERN.test(trimmed);
3474
- }
3475
- var COMPLEXITY_SIMPLE_MAX_LENGTH = 80;
3476
- var COMPLEXITY_MEDIUM_MAX_LENGTH = 500;
3477
- var COMPLEXITY_KEYWORDS = /为什么|如何|分析|对比|比较|设计|架构|实现|原理|推导|评价|区别|关系|影响|优化|重构/;
3478
- var COMPLEXITY_CODE_BLOCK = /```[\s\S]*```/;
3479
- function estimateComplexity(text) {
3480
- const trimmed = text.trim();
3481
- const len = trimmed.length;
3482
- if (len > COMPLEXITY_MEDIUM_MAX_LENGTH) return "complex";
3483
- if (COMPLEXITY_CODE_BLOCK.test(trimmed)) return "complex";
3484
- if (len > COMPLEXITY_SIMPLE_MAX_LENGTH) return "medium";
3485
- if (COMPLEXITY_KEYWORDS.test(trimmed)) return "medium";
3486
- return "simple";
3487
- }
3488
- var TIER_DESCRIPTIONS = {
3489
- flash: "\u5FEB\u901F\u7B80\u5355\uFF1A\u95EE\u5019\u3001\u95F2\u804A\u3001\u5FEB\u901F\u95EE\u7B54\u3001\u7FFB\u8BD1\u3001\u77ED\u6587",
3490
- balanced: "\u5E73\u8861\u63A8\u7406\uFF1A\u5206\u6790\u3001\u4E2D\u7B49\u957F\u5EA6\u5199\u4F5C\u3001\u4EE3\u7801\u3001\u63A8\u7406",
3491
- quality: "\u9AD8\u8D28\u91CF\u6DF1\u5EA6\uFF1A\u590D\u6742\u63A8\u7406\u3001\u957F\u6587\u3001\u67B6\u6784\u8BBE\u8BA1\u3001\u6DF1\u5EA6\u5206\u6790"
3492
- };
3493
- function buildQuickChatIntentSystemPrompt(tierAgents) {
3494
- const agentList = tierAgents.map((t2) => ` - "${t2.agentKey}"\uFF1A${t2.description}`).join("\n");
3495
- return `\u4F60\u662F\u4E00\u4E2A\u610F\u56FE\u8DEF\u7531\u5668\u3002\u6839\u636E\u7528\u6237\u6D88\u606F\uFF0C\u5224\u65AD\u5E94\u8BE5\u4EA4\u7ED9\u54EA\u4E2A agent \u5904\u7406\u3002
3496
-
3497
- \u53EF\u9009 agent \u5217\u8868\uFF08agentKey \u4E0E\u63CF\u8FF0\uFF09\uFF1A
3498
- ${agentList}
3499
-
3500
- \u5224\u65AD\u539F\u5219\uFF08\u9ED8\u8BA4\u504F\u5411\u901A\u7528\u6863\u4F4D\uFF1B\u4E13\u804C agent \u5728\u660E\u786E\u5339\u914D\u65F6\u4F7F\u7528\uFF1B**\u7F16\u7801/\u672C\u5730\u4ED3\u5E93\u4EFB\u52A1\u8D70\u901A\u7528\u6863 + needsWorkspace=true**\uFF09\uFF1A
3501
- - \u9ED8\u8BA4\u60C5\u51B5\u4E0B\uFF0C**\u9664\u975E\u7528\u6237\u660E\u786E\u8868\u8FBE\u8981\u5EFA\u5E94\u7528/\u5EFA Agent/\u63D0\u4EA4\u53CD\u9988/\u591A Agent \u7F16\u6392**\uFF0C\u5426\u5219\u9009\u901A\u7528\u6863\u4F4D\uFF08flash/balanced/quality\uFF09\uFF1A
3502
- - \u7B80\u5355\u95EE\u5019\u3001\u95F2\u804A\u3001\u5FEB\u901F\u95EE\u7B54\u3001\u7FFB\u8BD1\u3001\u77ED\u6587 \u2192 \u9009 flash \u6863
3503
- - \u9700\u8981\u63A8\u7406\u3001\u5206\u6790\u3001\u4E2D\u7B49\u957F\u5EA6\u5199\u4F5C\u3001\u666E\u901A\u4EE3\u7801\u89E3\u91CA/\u67B6\u6784\u95EE\u7B54 \u2192 \u9009 balanced \u6863
3504
- - \u590D\u6742\u63A8\u7406\u3001\u957F\u6587\u3001\u67B6\u6784\u8BBE\u8BA1\u3001\u6DF1\u5EA6\u5206\u6790 \u2192 \u9009 quality \u6863
3505
- - **\u660E\u786E\u7F16\u7801\u4EFB\u52A1\uFF08\u5B9E\u73B0\u529F\u80FD\u3001\u4FEE bug\u3001refactor\u3001\u5199/\u8865\u6D4B\u8BD5\u3001\u8DD1 build/tests/ci\uFF09\u6216\u67E5\u770B\u672C\u673A\u4ED3\u5E93/\u4EE3\u7801\u72B6\u6001\uFF08git/\u5206\u652F/commit/\u672C\u5730\u4E0E\u8FDC\u7A0B\u5DEE\u8DDD/\u672A\u63D0\u4EA4\u6539\u52A8\u7B49\uFF09** \u2192 \u9009 balanced \u6216 quality \u6863\uFF08\u6309\u590D\u6742\u5EA6\uFF1B**\u4E0D\u8981\u9009 flash**\uFF09\uFF0C\u4E14 needsWorkspace=true
3506
- - \u4E13\u804C agent \u8DEF\u7531\u89C4\u5219\uFF08\u6709\u660E\u786E\u5339\u914D\u65F6\u4F7F\u7528\uFF09\uFF1A
3507
- - \u8981\u63D0\u4EA4/\u8BB0\u5F55 bug\u3001\u4F53\u9A8C\u95EE\u9898\u3001\u6570\u636E\u5F02\u5E38\u3001\u4EA7\u54C1\u5EFA\u8BAE\uFF0C\u6216\u53E3\u8BED\u5982\u300C\u60F3\u53CD\u9988\u4E00\u4E9B\u95EE\u9898\u300D\u300C\u53CD\u9988\u4E00\u4E0B\u300D\u2192 \u9009\u610F\u89C1\u53CD\u9988\u4E13\u804C agent
3508
- - \u8981\u65B0\u5EFA\u6216\u5B9A\u5236 AI/Agent/\u667A\u80FD\u4F53\u52A9\u624B\uFF08\u542B\u914D\u7F6E\u5DE5\u5177\u3001\u77E5\u8BC6\u3001\u786E\u8BA4\u521B\u5EFA\uFF09\u2192 \u9009\u521B\u5EFA Agent \u4E13\u804C agent
3509
- - \u8981\u505A/\u6539/\u53D1\u5E03\u7F51\u7AD9\u3001\u7F51\u9875\u3001\u5C0F\u5E94\u7528\u3001\u9884\u7EA6\u9875\u3001\u535A\u5BA2\u3001\u770B\u677F \u2192 \u9009\u5E94\u7528\u6784\u5EFA\u4E13\u804C agent
3510
- - \u8981\u6D3E\u591A\u4E2A agent\u3001\u591A agent \u5E76\u884C\u3001\u62C6\u6210\u4EFB\u52A1\u540E\u53F0\u6267\u884C\u3001\u591A\u4E2A agent review\u3001\u8BA9\u4E0D\u540C agent \u8BA8\u8BBA/\u4F1A\u5546 \u2192 \u9009\u591A Agent \u7F16\u6392\u4E13\u804C agent\uFF08\u663E\u5F0F multi-agent \u4F18\u5148\uFF09
3511
- - **\u62FF\u4E0D\u51C6\u65F6**\uFF1A\u7EAF\u95F2\u804A\u9009 flash\uFF1B**\u82E5\u6CBE\u8FB9\u672C\u5730\u4ED3\u5E93/\u5F53\u524D\u4EE3\u7801\u72B6\u6001\uFF0C\u9009 balanced/quality + needsWorkspace=true**\u3002
3512
-
3513
- \u540C\u65F6\u5224\u65AD\u672C\u8F6E\u662F\u5426\u9700\u8981\u6CE8\u5165\u300C\u5DE5\u4F5C\u533A\u53EA\u8BFB\u5DE5\u5177\u300D\uFF08listFiles/globFiles/searchFiles/readFile/execShell \u7B49\uFF09\uFF1A
3514
- - needsWorkspace=true \u7684\u573A\u666F\uFF1A\u7528\u6237\u8981\u8BFB/\u6539/\u5206\u6790\u6587\u4EF6\u6216\u4EE3\u7801\u3001\u63D0\u5230\u4E86\u6587\u4EF6\u8DEF\u5F84/\u6269\u5C55\u540D\uFF08.md/.csv/.ts \u7B49\uFF09\u3001\u63D0\u5230\u5DE5\u4F5C\u533A/\u4EE3\u7801\u5E93/\u4ED3\u5E93/\u76EE\u5F55/git/\u5206\u652F\u3001\u8981\u770B\u5F53\u524D\u4EE3\u7801\u6216\u4ED3\u5E93\u72B6\u6001\u3001\u672C\u5730\u641C\u7D22/\u67E5\u770B\u4EE3\u7801\u3002
3515
- - needsWorkspace=false \u7684\u573A\u666F\uFF1A\u901A\u7528\u77E5\u8BC6\u95EE\u7B54\uFF08\u5982\u300C\u5E7F\u4E1C\u7ECF\u6D4E\u6570\u636E\u300D\u300C\u5199\u4E00\u9996\u8BD7\u300D\uFF09\u3001\u7EAF\u95F2\u804A\u95EE\u5019\u3001\u7FFB\u8BD1\u3001\u4E0D\u6D89\u53CA\u672C\u5730\u6587\u4EF6/\u4ED3\u5E93\u3002
3516
- - \u6F0F\u5224\uFF08\u7528\u6237\u8981\u6587\u4EF6\u800C\u6CA1\u5E26\u5DE5\u5177\uFF09\u6BD4\u8BEF\u5224\uFF08\u767D\u641C\u51E0\u8F6E\uFF09\u4EE3\u4EF7\u66F4\u9AD8\uFF0C\u5B81\u53EF\u504F\u5BBD\u5224 true\u3002
3517
-
3518
- \u5728\u7ED9\u51FA agentKey \u4E4B\u524D\uFF0C\u5148\u5728\u5FC3\u91CC\u533A\u5206\u5019\u9009\u6863\u4F4D\u7684\u8FB9\u754C\u518D\u7ED9\u7F6E\u4FE1\u5EA6\uFF1Abalanced \u4E0E quality \u7684\u8FB9\u754C\u5728\u4E8E\u590D\u6742\u5EA6/\u7BC7\u5E45/\u662F\u5426\u9700\u8981\u6DF1\u5EA6\u5206\u6790\uFF0C\u62FF\u4E0D\u51C6\u5C31\u7ED9\u4F4E confidence\u3002
3519
-
3520
- \u540C\u65F6\u5224\u65AD\u672C\u8F6E\u6D88\u606F\u662F\u5426\u9700\u8981\u6302\u8F7D\u5BF9\u8C61\u64CD\u4F5C\u6280\u80FD\uFF08skills \u6570\u7EC4\uFF0C\u672A\u547D\u4E2D\u7ED9 []\uFF09\uFF1A
3521
- - \u7528\u6237\u8981\u65B0\u5EFA/\u6574\u7406/\u5F55\u5165/\u6279\u91CF\u5904\u7406\u8868\u683C\u6570\u636E\uFF08\u5EFA\u8868\u3001\u52A0\u884C\u3001\u6539\u5217\u3001\u6309\u6761\u4EF6\u6574\u7406\u6570\u636E\uFF09\u2192 skills \u542B "table"
3522
- - \u7528\u6237\u8981\u5199/\u6DA6\u8272/\u6539\u5199/\u7EED\u5199/\u6392\u7248\u4E00\u7BC7\u6587\u6863\u6216\u6587\u7AE0 \u2192 skills \u542B "doc"
3523
- - \u7528\u6237\u8981\u5199/\u6539/\u5B9E\u73B0/\u4FEE bug/refactor/\u8865\u6D4B\u8BD5/\u5BA1\u67E5\u5E76\u4FEE\u6539\u4EE3\u7801 \u2192 skills \u542B "code"\uFF08\u4EC5\u95EE\u901A\u7528\u77E5\u8BC6\u3001\u7EAF\u95F2\u804A\u3001\u53EA\u67E5\u770B git/\u4ED3\u5E93\u72B6\u6001\u800C\u4E0D\u4FEE\u6539\u4EE3\u7801\u65F6\u4E0D\u6302 "code"\uFF09
3524
- - \u666E\u901A\u95EE\u7B54/\u7EAF\u95F2\u804A/\u5EFA\u5E94\u7528 \u2192 skills \u4E3A []
3525
-
3526
- \u53EA\u8F93\u51FA JSON\uFF0C\u4E0D\u8981\u8F93\u51FA\u5176\u4ED6\u5185\u5BB9\uFF1A
3527
- {"confidence": <0\u52301\u4E4B\u95F4\u7684\u5C0F\u6570\uFF0C\u8868\u793A\u4F60\u5BF9\u8FD9\u4E2A\u5206\u7C7B\u5224\u65AD\u7684\u628A\u63E1\u7A0B\u5EA6>, "agentKey": "<\u4ECE\u5217\u8868\u4E2D\u9009\u62E9\u7684 agentKey>", "needsWorkspace": <true \u6216 false>, "skills": <\u5B57\u7B26\u4E32\u6570\u7EC4\uFF0C\u5143\u7D20\u53EA\u80FD\u662F "table" | "doc" | "code"\uFF0C\u672A\u547D\u4E2D\u7ED9 []>}`;
3528
- }
3529
- function parseQuickChatIntentResult(content, tierAgents) {
3530
- try {
3531
- const parsed = JSON.parse(content.trim());
3532
- if (typeof parsed !== "object" || parsed === null || !("agentKey" in parsed)) return null;
3533
- const key = parsed.agentKey;
3534
- if (typeof key !== "string") return null;
3535
- if (!tierAgents.some((t2) => t2.agentKey === key)) return null;
3536
- const rawNeedsWorkspace = parsed.needsWorkspace;
3537
- const needsWorkspace = rawNeedsWorkspace === true;
3538
- const rawConfidence = parsed.confidence;
3539
- const confidence = typeof rawConfidence === "number" && Number.isFinite(rawConfidence) && rawConfidence >= 0 && rawConfidence <= 1 ? rawConfidence : void 0;
3540
- const rawSkills = parsed.skills;
3541
- let skills;
3542
- if (Array.isArray(rawSkills)) {
3543
- const filtered = [...new Set(rawSkills)].filter(
3544
- (s) => s === "table" || s === "doc" || s === "code"
3545
- );
3546
- if (filtered.length > 0) skills = filtered;
3547
- }
3548
- return { agentKey: key, needsWorkspace, confidence, skills };
3549
- } catch {
3550
- return null;
3551
- }
3552
- }
3553
-
3554
- // packages/cli/client/autoModelRouter.ts
3555
- var CLI_AUTO_TIER_AGENT_KEYS = {
3556
- flash: PUBLIC_DEEPSEEK_V4_FLASH_AGENT_KEY,
3557
- balanced: PUBLIC_DEEPSEEK_V4_PRO_AGENT_KEY,
3558
- quality: PUBLIC_GLM_52_AGENT_KEY
3559
- };
3560
- var CLI_IMAGE_AGENT_KEY = PUBLIC_KIMI_K26_IMAGE_AGENT_KEY;
3561
- var CLI_AUTO_TIER_AGENT_KEY_TABLE = {
3562
- [CLI_AUTO_TIER_AGENT_KEYS.flash]: true,
3563
- [CLI_AUTO_TIER_AGENT_KEYS.balanced]: true,
3564
- [CLI_AUTO_TIER_AGENT_KEYS.quality]: true
3565
- };
3566
- var buildRouteOptions = () => ["flash", "balanced", "quality"].map((tier) => ({
3567
- tier,
3568
- agentKey: CLI_AUTO_TIER_AGENT_KEYS[tier],
3569
- description: TIER_DESCRIPTIONS[tier]
3570
- }));
3571
- var tierForAgentKey = (agentKey) => {
3572
- for (const tier of ["flash", "balanced", "quality"]) {
3573
- if (CLI_AUTO_TIER_AGENT_KEYS[tier] === agentKey) return tier;
3574
- }
3575
- return null;
3576
- };
3577
- function resolveCliAutoFallbackTier(text) {
3578
- switch (estimateComplexity(text)) {
3579
- case "complex":
3580
- return "quality";
3581
- case "medium":
3582
- return "balanced";
3583
- case "simple":
3584
- default:
3585
- return "flash";
3586
- }
3587
- }
3588
- async function classifyCliAutoRoute(text, options) {
3589
- const timeoutMs = options.timeoutMs ?? QUICK_CHAT_INTENT_TIMEOUT_MS;
3590
- const fallbackTier = resolveCliAutoFallbackTier(text);
3591
- const fallback = () => ({
3592
- agentKey: CLI_AUTO_TIER_AGENT_KEYS[fallbackTier],
3593
- tier: fallbackTier,
3594
- classified: false
3595
- });
3596
- if (!text.trim()) return fallback();
3597
- if (isShortGreeting(text)) {
3598
- return {
3599
- agentKey: CLI_AUTO_TIER_AGENT_KEYS.flash,
3600
- tier: "flash",
3601
- classified: true
3602
- };
3603
- }
3604
- if (!options.authToken) return fallback();
3605
- const fetchImpl = options.fetchImpl ?? globalThis.fetch;
3606
- const controller = new AbortController();
3607
- const timeoutHandle = setTimeout(() => controller.abort(), timeoutMs);
3608
- try {
3609
- const routeOptions = buildRouteOptions();
3610
- const messages = [
3611
- { role: "system", content: buildQuickChatIntentSystemPrompt(routeOptions) },
3612
- { role: "user", content: text }
3613
- ];
3614
- const { url, init } = buildPlatformChatCompletionRequest({
3615
- providerConfig: {
3616
- serverUrl: options.serverUrl,
3617
- authToken: options.authToken,
3618
- agentKey: CLI_AUTO_TIER_AGENT_KEYS.flash,
3619
- model: INTENT_MODEL,
3620
- provider: INTENT_PROVIDER,
3621
- endpoint: resolvePlatformChatCompletionsEndpoint(INTENT_PROVIDER) ?? "",
3622
- requestOptions: {}
3623
- },
3624
- messages,
3625
- stream: false
3626
- });
3627
- const response = await fetchImpl(url, {
3628
- ...init,
3629
- signal: controller.signal
3630
- });
3631
- if (!response.ok) return fallback();
3632
- const data = parsePlatformChatCompletionData(await response.text());
3633
- const content = data?.choices?.[0]?.message?.content;
3634
- if (typeof content !== "string" || !content.trim()) return fallback();
3635
- const parsed = parseQuickChatIntentResult(content, routeOptions);
3636
- if (!parsed) return fallback();
3637
- const tier = tierForAgentKey(parsed.agentKey) ?? fallbackTier;
3638
- return {
3639
- agentKey: parsed.agentKey,
3640
- tier,
3641
- classified: true,
3642
- confidence: parsed.confidence,
3643
- needsWorkspace: parsed.needsWorkspace,
3644
- skills: parsed.skills
3645
- };
3646
- } catch {
3647
- return fallback();
3648
- } finally {
3649
- clearTimeout(timeoutHandle);
3650
- }
3651
- }
3652
-
3653
4233
  // packages/cli/agentRunPrompts.ts
3654
4234
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
3655
4235
  import { dirname, extname, isAbsolute, join, relative as relativePath, resolve, sep } from "node:path";
@@ -3993,16 +4573,16 @@ var buildCjkTokens = (text) => {
3993
4573
  }
3994
4574
  return tokens;
3995
4575
  };
3996
- var tokenize = (text) => {
4576
+ var tokenize2 = (text) => {
3997
4577
  const normalized = text.toLowerCase();
3998
4578
  const wordTokens = normalized.split(/[\s,.;:!?()[\]{}"'`,。!?:;、]+/).map((token) => token.trim()).filter((token) => token.length >= 2);
3999
4579
  return [...wordTokens, ...buildCjkTokens(normalized)];
4000
4580
  };
4001
4581
  var keywordScore = (query, item) => {
4002
- const queryTokens = new Set(tokenize(query));
4582
+ const queryTokens = new Set(tokenize2(query));
4003
4583
  if (queryTokens.size === 0) return 0;
4004
4584
  const haystack = /* @__PURE__ */ new Set([
4005
- ...tokenize(item.content),
4585
+ ...tokenize2(item.content),
4006
4586
  ...(item.tags ?? []).map((tag) => tag.toLowerCase()),
4007
4587
  item.patternKey?.toLowerCase() ?? ""
4008
4588
  ]);
@@ -4616,8 +5196,7 @@ ${mdContent}`);
4616
5196
  traceTools: parsed.traceTools,
4617
5197
  ...parsed.eventsMode ? { eventsMode: parsed.eventsMode } : {},
4618
5198
  ...parsed.taskEvidence ? { taskEvidence: parsed.taskEvidence } : {},
4619
- ...extraContextBlocks.length > 0 ? { extraContextBlocks } : {},
4620
- ...contextBlockScopes.length > 0 ? { contextBlockScopes } : {}
5199
+ ...contextBlockScopes.length > 0 ? { contextBlockScopes } : extraContextBlocks.length > 0 ? { extraContextBlocks } : {}
4621
5200
  });
4622
5201
  let result = await raceWithWatchdog(
4623
5202
  runner({
@@ -4748,10 +5327,28 @@ function isBalanceExhaustedError(error) {
4748
5327
  }
4749
5328
 
4750
5329
  export {
5330
+ CLI_AUTO_TIER_AGENT_KEYS,
5331
+ CLI_IMAGE_AGENT_KEY,
5332
+ CLI_AUTO_TIER_AGENT_KEY_TABLE,
5333
+ resolveCliAutoFallbackTier,
5334
+ classifyCliAutoRoute,
5335
+ resolveAgentContextWindow,
4751
5336
  formatTokenCount,
4752
5337
  renderTokenStatus,
4753
5338
  resolveCliColorEnabled,
4754
5339
  dimCliText,
5340
+ ANSI_ESCAPE_REGEX,
5341
+ stripAnsi,
5342
+ applyTerminalOutputToText,
5343
+ displayWidth,
5344
+ visibleWidth,
5345
+ truncateAnsi,
5346
+ fitAnsiLine,
5347
+ countPhysicalLines,
5348
+ takeDisplayWidth,
5349
+ padOrTruncateToWidth,
5350
+ wrapTranscriptLine,
5351
+ wrapTextToLines,
4755
5352
  THEME_PALETTES,
4756
5353
  getActiveThemeName,
4757
5354
  setActiveThemeName,
@@ -4760,22 +5357,24 @@ export {
4760
5357
  getActiveDensity,
4761
5358
  setActiveDensity,
4762
5359
  resolveTuiBrightness,
5360
+ setActiveTerminalBaseHex,
4763
5361
  surfaceBackgroundSequence,
4764
5362
  themeColorSequence,
4765
5363
  themeText,
4766
- highlightMarkdown,
4767
5364
  formatAssistantDisplay,
4768
5365
  normalizeThinkingDisplayMode,
4769
- parseCliLocale,
4770
- getCliLocale,
4771
- setCliLocale,
4772
- initCliLocale,
4773
- t,
4774
5366
  normalizeToolDisplayMode,
5367
+ COLLAPSED_PASTE_PLACEHOLDER_RE,
5368
+ shouldCollapsePaste,
5369
+ createCollapsedPasteStore,
5370
+ allocateCollapsedPaste,
5371
+ releaseCollapsedPaste,
5372
+ clearCollapsedPasteStore,
5373
+ replaceCollapsedPastesWithReferences,
5374
+ releaseCollapsedPasteReferences,
5375
+ expandRangeToCollapsedPasteChips,
5376
+ findCollapsedPasteSpanAt,
4775
5377
  runAgentTurn,
4776
- CLI_IMAGE_AGENT_KEY,
4777
- CLI_AUTO_TIER_AGENT_KEY_TABLE,
4778
- classifyCliAutoRoute,
4779
5378
  resolveWorkflowReference,
4780
5379
  resolveSkillReference,
4781
5380
  buildSkillContextBlocks,