nolo-cli 0.8.0-alpha.21 → 0.8.0-alpha.24
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.
- package/{_executeModel-42U3VOVZ.js → _executeModel-2ZAPHFOX.js} +46 -43
- package/{action-TLI3V62L.js → action-QM2ONPYZ.js} +9 -9
- package/{addContentAction-57RSIIMR.js → addContentAction-UXY3GM53.js} +8 -8
- package/{addDialogAgentAction-G3VWEA6E.js → addDialogAgentAction-MUBYOG65.js} +10 -10
- package/{agentDeleteCommand-5DD2IM3J.js → agentDeleteCommand-5TFSII4Z.js} +28 -27
- package/{agentEmailCommands-6FACJBU4.js → agentEmailCommands-XMXWGUMZ.js} +62 -58
- package/{agentListCommands-I6KZYCIG.js → agentListCommands-OWEFQEY4.js} +119 -33
- package/{agentMachineCommands-VKLIGMZA.js → agentMachineCommands-DGHYBBFC.js} +27 -26
- package/{agentPullCommand-O2MTUAFR.js → agentPullCommand-N6UWRTVL.js} +3 -3
- package/{agentRecordCommands-7TZICYDT.js → agentRecordCommands-I433EE5F.js} +53 -49
- package/{agentRunCommand-L4OM23KV.js → agentRunCommand-UQSX3IGW.js} +57 -52
- package/{agentRunControl-K4VKNEHF.js → agentRunControl-S3G62M6C.js} +3 -3
- package/{agentRuntimeLocal-ZYEIPTY4.js → agentRuntimeLocal-73SVOC5U.js} +14 -12
- package/{agentSlice-BX7GXSNO.js → agentSlice-JQCS4LR3.js} +9 -9
- package/{authCommand-EB5JSOX5.js → authCommand-B6P2XYLN.js} +11 -11
- package/{authCommands-XPEHTKSM.js → authCommands-4YKA4GTU.js} +7 -7
- package/{chunk-AS4PVWA4.js → chunk-2CVZSC5L.js} +1 -1
- package/{chunk-JRKKFRAV.js → chunk-3HPUUWOR.js} +58 -8
- package/{chunk-5KLGBAAR.js → chunk-3KGTFX3T.js} +2 -13
- package/{chunk-IWX4UW2E.js → chunk-524BDL33.js} +89 -8
- package/chunk-6QFNUK2G.js +144 -0
- package/{chunk-4QEWT7KD.js → chunk-AISLHYDB.js} +367 -85
- package/{chunk-2FTTDCD4.js → chunk-AMJ7LA5D.js} +1 -1
- package/{chunk-I6XMPTMR.js → chunk-BFDWXLFF.js} +2 -2
- package/{chunk-RL776AGR.js → chunk-BKGNXJAM.js} +1 -1
- package/{chunk-RCSJFQPB.js → chunk-BQECZ3Q4.js} +361 -90
- package/{chunk-VVX233PH.js → chunk-BT37DVDA.js} +9 -9
- package/{chunk-ENOG22KJ.js → chunk-BT57QC5K.js} +18 -20
- package/chunk-BYXBJQAS.js +0 -0
- package/{chunk-O2ZNTTET.js → chunk-C4DZRHFJ.js} +24 -15
- package/{chunk-4XENYTF5.js → chunk-DS3VC4EA.js} +3 -3
- package/{chunk-N54XAP77.js → chunk-FVVST32H.js} +1 -1
- package/{chunk-P3PKED2I.js → chunk-FZ2G3I4B.js} +11 -13
- package/{chunk-AGFH73SK.js → chunk-G7KM6BBZ.js} +1 -1
- package/{chunk-2ECQG4YX.js → chunk-GROGNZOA.js} +264 -161
- package/chunk-IOQIOZNI.js +42 -0
- package/{chunk-AL2KDGR2.js → chunk-IPA2WQGY.js} +201 -98
- package/{chunk-7DAJ4AI4.js → chunk-IYMGQ3TN.js} +9 -2
- package/{chunk-CKOJQDKR.js → chunk-JEMATI63.js} +1 -1
- package/{chunk-7U44LYTR.js → chunk-JTINRTBT.js} +1 -1
- package/{chunk-4O3CARJ4.js → chunk-KTHLAJEY.js} +1 -1
- package/{chunk-URUUZLPA.js → chunk-L3KWEH3V.js} +8 -8
- package/{chunk-XBUBEFNX.js → chunk-L76QNLGU.js} +1 -1
- package/{chunk-UB6SN4NJ.js → chunk-LE6JAIXE.js} +6 -6
- package/{chunk-2JCXITPK.js → chunk-LRKEOCWY.js} +15 -15
- package/{chunk-5EFXE3O7.js → chunk-LTH6AVG7.js} +3 -3
- package/{chunk-YPRZSPF3.js → chunk-OCDEWRE2.js} +1 -1
- package/{chunk-6KHNO3SK.js → chunk-P2SPC3FT.js} +27 -23
- package/{chunk-4IJYA27C.js → chunk-PXZAAB4L.js} +4 -4
- package/{chunk-VUW5FBDB.js → chunk-Q7S2ORXX.js} +9 -9
- package/{chunk-C3RUNRHT.js → chunk-QWM7YWVT.js} +1 -1
- package/{chunk-25LCXTML.js → chunk-RQPZX6KP.js} +2 -2
- package/chunk-S3UTETIC.js +4885 -0
- package/{chunk-SDJDLO5W.js → chunk-SBVUZC2E.js} +5 -5
- package/{chunk-VX3SXJ3N.js → chunk-UBSKX3LP.js} +6 -6
- package/{chunk-4ZDM73SD.js → chunk-V2J635L5.js} +1 -1
- package/{chunk-DSZUWUYB.js → chunk-VBKJTOAW.js} +1 -1
- package/{chunk-FVYY6MCS.js → chunk-VUEXKW6U.js} +17 -17
- package/{chunk-7KCUSYT2.js → chunk-WKQGZJVI.js} +7 -7
- package/{chunk-GU3PEVGZ.js → chunk-WM7P5OWZ.js} +2639 -1579
- package/{chunk-7GNGZRLZ.js → chunk-WTBWWBSF.js} +150 -78
- package/{chunk-FSO5B7GH.js → chunk-WVS3GX3B.js} +2 -2
- package/chunk-Z3NEXVYE.js +33 -0
- package/{createAgentAutomationAction-RJF3N2QY.js → createAgentAutomationAction-GXZNLJZK.js} +26 -24
- package/{createDialogAction-DRSPS6CE.js → createDialogAction-KLW42ZGF.js} +26 -24
- package/{createPageAction-6B2WMNO3.js → createPageAction-IBJHE6MH.js} +26 -24
- package/{dbSlice-Q3TM2FJV.js → dbSlice-R5EJKZBW.js} +7 -7
- package/{deleteFile-OW53A6BX.js → deleteFile-WPWVZE4B.js} +5 -5
- package/{dialogCommands-4IX4XIZE.js → dialogCommands-7O5PUZRU.js} +23 -22
- package/{dialogSlice-3M7KX2TX.js → dialogSlice-GGV7PF53.js} +25 -23
- package/{docCreateCommands-SIL3NPGT.js → docCreateCommands-7ZO2NQQF.js} +22 -21
- package/{docDeleteCommands-7IOMLUS4.js → docDeleteCommands-YKIXZYBR.js} +23 -22
- package/{docReadCommands-FNFXUA5L.js → docReadCommands-5UDONBUL.js} +22 -21
- package/{docStore-SV7E34D4.js → docStore-VDWTATFH.js} +25 -23
- package/{docUpdateCommands-X2HNDVUC.js → docUpdateCommands-EPZIIQMY.js} +22 -21
- package/fetchMessages-KTNM7QAR.js +1 -1
- package/{getPricing-3E6UNPKL.js → getPricing-6TOZXPAU.js} +7 -3
- package/{handleSendMessageAction-JYETO5RZ.js → handleSendMessageAction-MMATC5V5.js} +30 -28
- package/index.js +74 -74
- package/{localDialogRead-2VRI24F4.js → localDialogRead-YSKFFRTT.js} +1 -1
- package/{machineCommands-RIO3RP5Q.js → machineCommands-PTHPKSIZ.js} +59 -55
- package/{machineWsRunDispatch-W7UYLGB5.js → machineWsRunDispatch-M5L2NVWJ.js} +51 -47
- package/{memoryCommands-O4MIPIWQ.js → memoryCommands-HG4WKTU7.js} +2 -2
- package/{models-4OPOOLFS.js → models-H524GH3U.js} +3 -2
- package/package.json +1 -1
- package/{read-GW7ZEI23.js → read-5ZMY7FKP.js} +5 -5
- package/{readDocTool-HUFU6OCT.js → readDocTool-2NXDK32S.js} +1 -1
- package/{readlineWorkspace-27JR7WPW.js → readlineWorkspace-4NXMEOHP.js} +835 -622
- package/{removeDialogAgentAction-CXKR4NJI.js → removeDialogAgentAction-KOLQ2R5W.js} +13 -12
- package/{runAgentClientLoop-HZFAPJHS.js → runAgentClientLoop-FGUYNGSA.js} +45 -42
- package/{runtimeDoctorCommands-LRHLPDRC.js → runtimeDoctorCommands-UWR5UDSM.js} +5 -5
- package/{setDialogExtraReferencesAction-6RKUSXHX.js → setDialogExtraReferencesAction-OMTEO7X6.js} +10 -10
- package/{setPrimaryDialogAgentAction-T3UTBEFG.js → setPrimaryDialogAgentAction-DOCIS6V4.js} +13 -12
- package/{settingSlice-IVKXJXMG.js → settingSlice-UWZJYDOA.js} +8 -8
- package/{spaceCommands-E7VOF4LO.js → spaceCommands-S3EB6TOS.js} +29 -28
- package/{spaceSlice-TSVROA5U.js → spaceSlice-RG2GSV7K.js} +24 -22
- package/{streamAgentChatTurn-3C5RQZJF.js → streamAgentChatTurn-X576C23M.js} +209 -86
- package/{tableCommands-O7O2LBEG.js → tableCommands-M3DJUETS.js} +10 -10
- package/{toolApiClient-QI3YBNWB.js → toolApiClient-C7P7YSE4.js} +2 -2
- package/{tools-EQDEKR6N.js → tools-HURZ2N4O.js} +33 -30
- package/{tuiSummaryLlmCaller-RV3THLZF.js → tuiSummaryLlmCaller-DG2LBTBX.js} +8 -6
- package/{updateCommands-VOSPKXFF.js → updateCommands-TC5SX42Y.js} +3 -3
- package/{updateDialogTitleAction-3XV7VWSZ.js → updateDialogTitleAction-62LVIAUZ.js} +28 -26
- package/chunk-BBYVOSU2.js +0 -792
- package/chunk-DCOA4QSN.js +0 -105
- package/{chunk-DZ3XJVET.js → chunk-3QAF2LTL.js} +3 -3
- package/{chunk-EHLHSX7R.js → chunk-5MMZUWSG.js} +3 -3
- package/{chunk-ISNCLGUZ.js → chunk-AVMJVOQY.js} +3 -3
- package/{chunk-UTLZINAP.js → chunk-DVRHHFEA.js} +10 -10
- package/{chunk-4CQLVGRV.js → chunk-ID4G2MAR.js} +3 -3
- package/{chunk-5MIDPSSK.js → chunk-JK7VW2FN.js} +3 -3
- package/{chunk-TILFE6LV.js → chunk-YOCHZD7D.js} +3 -3
- package/{db-HCJ5PRB5.js → db-6QED3ZVO.js} +3 -3
- package/{understanding-3CUQQ6SV.js → understanding-ZOESBLF3.js} +3 -3
|
@@ -3,113 +3,151 @@ import {
|
|
|
3
3
|
normalizeDialogRecord,
|
|
4
4
|
readDialogSnapshot,
|
|
5
5
|
sortDialogs
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-VUEXKW6U.js";
|
|
7
7
|
import {
|
|
8
|
+
ANSI_ESCAPE_REGEX,
|
|
9
|
+
CLI_AUTO_TIER_AGENT_KEYS,
|
|
8
10
|
CLI_AUTO_TIER_AGENT_KEY_TABLE,
|
|
9
11
|
CLI_IMAGE_AGENT_KEY,
|
|
12
|
+
COLLAPSED_PASTE_PLACEHOLDER_RE,
|
|
10
13
|
THEME_PALETTES,
|
|
14
|
+
allocateCollapsedPaste,
|
|
15
|
+
applyTerminalOutputToText,
|
|
11
16
|
buildSkillContextBlocks,
|
|
12
17
|
classifyCliAutoRoute,
|
|
18
|
+
clearCollapsedPasteStore,
|
|
19
|
+
countPhysicalLines,
|
|
20
|
+
createCollapsedPasteStore,
|
|
13
21
|
dimCliText,
|
|
22
|
+
displayWidth,
|
|
23
|
+
expandRangeToCollapsedPasteChips,
|
|
24
|
+
findCollapsedPasteSpanAt,
|
|
25
|
+
fitAnsiLine,
|
|
14
26
|
formatAssistantDisplay,
|
|
15
27
|
formatTokenCount,
|
|
16
28
|
getActiveBrightness,
|
|
17
29
|
getActiveDensity,
|
|
18
30
|
getActiveThemeName,
|
|
19
|
-
getCliLocale,
|
|
20
|
-
highlightMarkdown,
|
|
21
31
|
initCliLocale,
|
|
32
|
+
isBalanceExhaustedError,
|
|
22
33
|
isQuotaExhaustedError,
|
|
23
34
|
normalizeThinkingDisplayMode,
|
|
24
35
|
normalizeToolDisplayMode,
|
|
36
|
+
padOrTruncateToWidth,
|
|
25
37
|
parseCliLocale,
|
|
38
|
+
releaseCollapsedPaste,
|
|
39
|
+
releaseCollapsedPasteReferences,
|
|
26
40
|
renderTokenStatus,
|
|
41
|
+
replaceCollapsedPastesWithReferences,
|
|
42
|
+
resolveAgentContextWindow,
|
|
43
|
+
resolveCliAutoFallbackTier,
|
|
27
44
|
resolveCliColorEnabled,
|
|
28
45
|
resolveSkillReference,
|
|
29
46
|
resolveTuiBrightness,
|
|
30
47
|
runAgentTurn,
|
|
31
48
|
setActiveBrightness,
|
|
32
49
|
setActiveDensity,
|
|
50
|
+
setActiveTerminalBaseHex,
|
|
33
51
|
setActiveThemeName,
|
|
34
52
|
setCliLocale,
|
|
53
|
+
shouldCollapsePaste,
|
|
54
|
+
stripAnsi,
|
|
35
55
|
surfaceBackgroundSequence,
|
|
36
56
|
t,
|
|
57
|
+
takeDisplayWidth,
|
|
37
58
|
themeColorSequence,
|
|
38
|
-
themeText
|
|
39
|
-
|
|
59
|
+
themeText,
|
|
60
|
+
truncateAnsi,
|
|
61
|
+
visibleWidth,
|
|
62
|
+
wrapTextToLines,
|
|
63
|
+
wrapTranscriptLine
|
|
64
|
+
} from "./chunk-WM7P5OWZ.js";
|
|
40
65
|
import "./chunk-6HYVJV7B.js";
|
|
41
|
-
import "./chunk-2FTTDCD4.js";
|
|
42
66
|
import {
|
|
43
67
|
listFavoriteAgentIdsAcrossServers,
|
|
44
68
|
listLocalCachedAgents,
|
|
45
69
|
listRemoteAgents,
|
|
46
70
|
listRemoteAgentsAcrossServers
|
|
47
|
-
} from "./chunk-
|
|
48
|
-
import "./chunk-
|
|
71
|
+
} from "./chunk-IYMGQ3TN.js";
|
|
72
|
+
import "./chunk-ID4G2MAR.js";
|
|
49
73
|
import {
|
|
50
74
|
listUserRecordsFromServers
|
|
51
|
-
} from "./chunk-
|
|
52
|
-
import "./chunk-
|
|
53
|
-
import
|
|
54
|
-
|
|
75
|
+
} from "./chunk-BKGNXJAM.js";
|
|
76
|
+
import "./chunk-3QAF2LTL.js";
|
|
77
|
+
import {
|
|
78
|
+
createCliLocalRuntimeAdapter
|
|
79
|
+
} from "./chunk-BQECZ3Q4.js";
|
|
80
|
+
import "./chunk-5MMZUWSG.js";
|
|
81
|
+
import "./chunk-CMKUBIGW.js";
|
|
82
|
+
import "./chunk-JBTJAPUF.js";
|
|
55
83
|
import {
|
|
56
84
|
getReadableCliDb
|
|
57
85
|
} from "./chunk-W4NVOSFF.js";
|
|
58
86
|
import {
|
|
59
87
|
queryUserRecords,
|
|
60
88
|
readDbRecord
|
|
61
|
-
} from "./chunk-
|
|
62
|
-
import "./chunk-
|
|
89
|
+
} from "./chunk-SBVUZC2E.js";
|
|
90
|
+
import "./chunk-FVVST32H.js";
|
|
63
91
|
import {
|
|
64
92
|
resolveCliAgentKeyInput
|
|
65
93
|
} from "./chunk-VHBWHNVT.js";
|
|
66
94
|
import "./chunk-LTRXGFMS.js";
|
|
67
|
-
import "./chunk-
|
|
68
|
-
import "./chunk-CMKUBIGW.js";
|
|
69
|
-
import "./chunk-JBTJAPUF.js";
|
|
95
|
+
import "./chunk-KTHLAJEY.js";
|
|
70
96
|
import "./chunk-ATNTHIZI.js";
|
|
71
97
|
import "./chunk-JEXVIMYZ.js";
|
|
72
|
-
import
|
|
73
|
-
|
|
74
|
-
|
|
98
|
+
import {
|
|
99
|
+
prepareTools
|
|
100
|
+
} from "./chunk-WVS3GX3B.js";
|
|
101
|
+
import "./chunk-QWM7YWVT.js";
|
|
102
|
+
import {
|
|
103
|
+
expandEnabledPacks
|
|
104
|
+
} from "./chunk-IPA2WQGY.js";
|
|
75
105
|
import "./chunk-GAKEBQD6.js";
|
|
106
|
+
import "./chunk-6QFNUK2G.js";
|
|
76
107
|
import "./chunk-KQHGZWSV.js";
|
|
77
|
-
import "./chunk-
|
|
108
|
+
import "./chunk-2CVZSC5L.js";
|
|
78
109
|
import "./chunk-3LY4F7SV.js";
|
|
79
110
|
import "./chunk-VP4WJWKW.js";
|
|
80
111
|
import "./chunk-63W5N6P3.js";
|
|
81
112
|
import "./chunk-VF4K2QE6.js";
|
|
82
|
-
import "./chunk-
|
|
83
|
-
import "./chunk-
|
|
113
|
+
import "./chunk-LE6JAIXE.js";
|
|
114
|
+
import "./chunk-BT57QC5K.js";
|
|
84
115
|
import "./chunk-VC6OZXO5.js";
|
|
85
116
|
import "./chunk-OWOHNGCN.js";
|
|
86
|
-
import "./chunk-25LCXTML.js";
|
|
87
|
-
import "./chunk-HNW7IJSK.js";
|
|
88
|
-
import "./chunk-XENYHRUE.js";
|
|
89
117
|
import {
|
|
90
118
|
DEFAULT_CONTEXT_WINDOW,
|
|
119
|
+
estimateTokenCount,
|
|
91
120
|
extractReferenceKeysFromMessage,
|
|
92
121
|
getModelContextWindow,
|
|
93
122
|
planCompression,
|
|
94
123
|
serializeMessageContent
|
|
95
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-GROGNZOA.js";
|
|
96
125
|
import {
|
|
97
126
|
buildBuiltinSummaryContent
|
|
98
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-V2J635L5.js";
|
|
99
128
|
import "./chunk-MRC4Q34M.js";
|
|
100
129
|
import "./chunk-MTU75CZ2.js";
|
|
101
130
|
import "./chunk-CWMSB67P.js";
|
|
102
|
-
import "./chunk-
|
|
103
|
-
import "./chunk-
|
|
131
|
+
import "./chunk-Q7S2ORXX.js";
|
|
132
|
+
import "./chunk-LTH6AVG7.js";
|
|
104
133
|
import "./chunk-Z4NR32XR.js";
|
|
105
134
|
import "./chunk-M76ECQRD.js";
|
|
135
|
+
import "./chunk-RQPZX6KP.js";
|
|
136
|
+
import "./chunk-UBSKX3LP.js";
|
|
137
|
+
import "./chunk-Y5GCAMGP.js";
|
|
106
138
|
import "./chunk-SOTZ6RDN.js";
|
|
107
|
-
import "./chunk-
|
|
139
|
+
import "./chunk-BFDWXLFF.js";
|
|
108
140
|
import "./chunk-UAD2WT54.js";
|
|
109
|
-
import "./chunk-
|
|
141
|
+
import "./chunk-L3KWEH3V.js";
|
|
142
|
+
import "./chunk-AZPCASRE.js";
|
|
143
|
+
import "./chunk-IOQIOZNI.js";
|
|
144
|
+
import "./chunk-Z3NEXVYE.js";
|
|
145
|
+
import "./chunk-HNW7IJSK.js";
|
|
146
|
+
import "./chunk-XENYHRUE.js";
|
|
147
|
+
import "./chunk-JTINRTBT.js";
|
|
110
148
|
import {
|
|
111
149
|
runSelfUpdate
|
|
112
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-JEMATI63.js";
|
|
113
151
|
import {
|
|
114
152
|
saveProfileAgentSelection,
|
|
115
153
|
saveProfileLocale
|
|
@@ -118,15 +156,6 @@ import {
|
|
|
118
156
|
readPipeText,
|
|
119
157
|
spawnProcess
|
|
120
158
|
} from "./chunk-IDZTNRP2.js";
|
|
121
|
-
import {
|
|
122
|
-
parseUserIdFromAuthToken,
|
|
123
|
-
resolveAuthToken,
|
|
124
|
-
resolveServerCandidates,
|
|
125
|
-
resolveServerUrl
|
|
126
|
-
} from "./chunk-ISNCLGUZ.js";
|
|
127
|
-
import {
|
|
128
|
-
DEFAULT_NOLO_SERVER_URL
|
|
129
|
-
} from "./chunk-OLZBQWZU.js";
|
|
130
159
|
import {
|
|
131
160
|
buildSkillDiscoveryContextBlock
|
|
132
161
|
} from "./chunk-AFON4QUU.js";
|
|
@@ -134,71 +163,158 @@ import "./chunk-C4FTUXVF.js";
|
|
|
134
163
|
import "./chunk-KKY4B2Q2.js";
|
|
135
164
|
import "./chunk-WZSRQNQG.js";
|
|
136
165
|
import {
|
|
166
|
+
buildLocalWorkspaceOpenAiTools,
|
|
167
|
+
buildLocalWorkspaceToolset,
|
|
137
168
|
getProcessRegistry
|
|
138
|
-
} from "./chunk-
|
|
139
|
-
import "./chunk-
|
|
169
|
+
} from "./chunk-C4DZRHFJ.js";
|
|
170
|
+
import "./chunk-3KGTFX3T.js";
|
|
140
171
|
import "./chunk-ZNFJWEN4.js";
|
|
141
|
-
import "./chunk-
|
|
172
|
+
import "./chunk-YOCHZD7D.js";
|
|
142
173
|
import {
|
|
143
174
|
readCommandActionGatePayload,
|
|
144
175
|
resolveAgentImageInputSupport
|
|
145
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-AISLHYDB.js";
|
|
146
177
|
import "./chunk-OPZYGHUC.js";
|
|
147
|
-
import
|
|
148
|
-
|
|
149
|
-
|
|
178
|
+
import {
|
|
179
|
+
buildCurrentTimeBlock,
|
|
180
|
+
buildIdentityBlock,
|
|
181
|
+
buildRuntimeGuidanceBlocks
|
|
182
|
+
} from "./chunk-G7KM6BBZ.js";
|
|
183
|
+
import "./chunk-3HPUUWOR.js";
|
|
184
|
+
import {
|
|
185
|
+
canonicalizeToolNames
|
|
186
|
+
} from "./chunk-FZ2G3I4B.js";
|
|
150
187
|
import {
|
|
151
188
|
clipCompactText
|
|
152
189
|
} from "./chunk-5MMAK75Q.js";
|
|
153
|
-
import "./chunk-
|
|
190
|
+
import "./chunk-S3UTETIC.js";
|
|
154
191
|
import "./chunk-5CS33IBL.js";
|
|
155
192
|
import "./chunk-JZPBVBIY.js";
|
|
156
|
-
import "./chunk-
|
|
157
|
-
import "./chunk-
|
|
193
|
+
import "./chunk-BYXBJQAS.js";
|
|
194
|
+
import "./chunk-KX6YBIHG.js";
|
|
195
|
+
import "./chunk-524BDL33.js";
|
|
196
|
+
import "./chunk-O4BU24WZ.js";
|
|
197
|
+
import "./chunk-I42VC5KR.js";
|
|
198
|
+
import "./chunk-WWC7I6TA.js";
|
|
199
|
+
import "./chunk-JK7VW2FN.js";
|
|
158
200
|
import {
|
|
159
201
|
extractCustomId
|
|
160
202
|
} from "./chunk-DFFIZ25G.js";
|
|
161
203
|
import "./chunk-3ASDTTEI.js";
|
|
204
|
+
import {
|
|
205
|
+
asTrimmedLowercaseString
|
|
206
|
+
} from "./chunk-QSJ3HFEF.js";
|
|
162
207
|
import {
|
|
163
208
|
compactWhitespace
|
|
164
209
|
} from "./chunk-DWLEOOGR.js";
|
|
210
|
+
import "./chunk-AMJ7LA5D.js";
|
|
211
|
+
import {
|
|
212
|
+
parseUserIdFromAuthToken,
|
|
213
|
+
resolveAuthToken,
|
|
214
|
+
resolveServerCandidates,
|
|
215
|
+
resolveServerUrl
|
|
216
|
+
} from "./chunk-AVMJVOQY.js";
|
|
217
|
+
import {
|
|
218
|
+
DEFAULT_NOLO_SERVER_URL
|
|
219
|
+
} from "./chunk-OLZBQWZU.js";
|
|
165
220
|
import {
|
|
166
221
|
toErrorMessage
|
|
167
222
|
} from "./chunk-HNMXYYJR.js";
|
|
168
223
|
import "./chunk-H33743XH.js";
|
|
169
224
|
import "./chunk-LM6IYQ3F.js";
|
|
170
|
-
import "./chunk-
|
|
171
|
-
import "./chunk-
|
|
172
|
-
import "./chunk-URUUZLPA.js";
|
|
173
|
-
import "./chunk-AZPCASRE.js";
|
|
174
|
-
import "./chunk-7U44LYTR.js";
|
|
175
|
-
import "./chunk-KX6YBIHG.js";
|
|
176
|
-
import "./chunk-O4BU24WZ.js";
|
|
177
|
-
import "./chunk-I42VC5KR.js";
|
|
178
|
-
import "./chunk-WWC7I6TA.js";
|
|
179
|
-
import {
|
|
180
|
-
asTrimmedLowercaseString
|
|
181
|
-
} from "./chunk-QSJ3HFEF.js";
|
|
182
|
-
import "./chunk-DSZUWUYB.js";
|
|
183
|
-
import "./chunk-UTLZINAP.js";
|
|
225
|
+
import "./chunk-VBKJTOAW.js";
|
|
226
|
+
import "./chunk-DVRHHFEA.js";
|
|
184
227
|
import "./chunk-OOSFSFMA.js";
|
|
185
228
|
import "./chunk-GBRG75BQ.js";
|
|
186
|
-
import "./chunk-4SN6J65J.js";
|
|
187
|
-
import "./chunk-LCBAMY2M.js";
|
|
188
229
|
import "./chunk-3EUW3WEO.js";
|
|
189
230
|
import "./chunk-U6VC4MU4.js";
|
|
231
|
+
import "./chunk-KUG52IAP.js";
|
|
232
|
+
import "./chunk-LCBAMY2M.js";
|
|
233
|
+
import "./chunk-4SN6J65J.js";
|
|
190
234
|
import "./chunk-CF7PE763.js";
|
|
191
235
|
import {
|
|
192
236
|
asOptionalTrimmedString
|
|
193
237
|
} from "./chunk-G3SUCT4W.js";
|
|
194
|
-
import "./chunk-KUG52IAP.js";
|
|
195
238
|
import "./chunk-4VNS5WPM.js";
|
|
196
239
|
|
|
197
240
|
// packages/cli/tui/readlineWorkspace.ts
|
|
198
241
|
import { createInterface } from "node:readline";
|
|
199
242
|
import { stdin as defaultInput, stdout as defaultOutput } from "node:process";
|
|
200
|
-
import { existsSync as
|
|
243
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
244
|
+
import { join as join2 } from "node:path";
|
|
245
|
+
|
|
246
|
+
// packages/cli/client/estimateCliContext.ts
|
|
247
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
201
248
|
import { join } from "node:path";
|
|
249
|
+
var DEFAULT_CLI_PACKS = ["code", "agent-orchestration"];
|
|
250
|
+
var DEFAULT_CLI_PLATFORM_TOOLS = [
|
|
251
|
+
"ui_ask_choice",
|
|
252
|
+
"exa_search",
|
|
253
|
+
"fetchWebpage"
|
|
254
|
+
];
|
|
255
|
+
var DEFAULT_FLASH_PROMPT = "\u4F60\u662F\u5171\u4EAB\u7A7A\u95F4\u91CC\u7684\u9AD8\u6027\u4EF7\u6BD4\u901A\u7528 AI \u52A9\u624B\u3002\u4F18\u5148\u5FEB\u901F\u3001\u76F4\u63A5\u3001\u7A33\u5B9A\u5730\u5B8C\u6210\u4EFB\u52A1\uFF1B\u9700\u8981\u63A8\u7406\u65F6\u4FDD\u6301\u6B65\u9AA4\u6E05\u6670\u3002";
|
|
256
|
+
function readAgentsMd(cwd) {
|
|
257
|
+
for (const name of ["AGENTS.md", "agents.md"]) {
|
|
258
|
+
const path = join(cwd, name);
|
|
259
|
+
if (!existsSync(path)) continue;
|
|
260
|
+
try {
|
|
261
|
+
return readFileSync(path, "utf8");
|
|
262
|
+
} catch {
|
|
263
|
+
return "";
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return "";
|
|
267
|
+
}
|
|
268
|
+
function estimateToolSchemas(toolNames) {
|
|
269
|
+
const toolset = buildLocalWorkspaceToolset({
|
|
270
|
+
declaredToolNames: toolNames,
|
|
271
|
+
exposeShellTools: true
|
|
272
|
+
});
|
|
273
|
+
const workspaceTools = buildLocalWorkspaceOpenAiTools({
|
|
274
|
+
toolNames: toolset.toolNames,
|
|
275
|
+
exposeShellTools: true
|
|
276
|
+
});
|
|
277
|
+
const platformNames = DEFAULT_CLI_PLATFORM_TOOLS.filter(
|
|
278
|
+
(name) => toolNames.includes(name)
|
|
279
|
+
);
|
|
280
|
+
const platformTools = platformNames.length > 0 ? prepareTools([...platformNames]) : [];
|
|
281
|
+
return estimateTokenCount(JSON.stringify([...workspaceTools, ...platformTools]));
|
|
282
|
+
}
|
|
283
|
+
function estimateDefaultCliContextTokens(opts = {}) {
|
|
284
|
+
const cwd = opts.cwd?.trim() || process.cwd();
|
|
285
|
+
const model = opts.model?.trim() || "deepseek-v4-flash";
|
|
286
|
+
const agentName = opts.agentName?.trim() || "DeepSeek V4 Flash";
|
|
287
|
+
const agentKey = opts.agentKey?.trim() || "agent-pub-deepseek-v4-flash";
|
|
288
|
+
const prompt = opts.agentPrompt?.trim() || DEFAULT_FLASH_PROMPT;
|
|
289
|
+
const packTools = canonicalizeToolNames(
|
|
290
|
+
expandEnabledPacks([...DEFAULT_CLI_PACKS], [])
|
|
291
|
+
);
|
|
292
|
+
const toolNames = canonicalizeToolNames([
|
|
293
|
+
...packTools,
|
|
294
|
+
...DEFAULT_CLI_PLATFORM_TOOLS
|
|
295
|
+
]);
|
|
296
|
+
const guidance = buildRuntimeGuidanceBlocks(toolNames);
|
|
297
|
+
const systemParts = [
|
|
298
|
+
prompt,
|
|
299
|
+
buildIdentityBlock({
|
|
300
|
+
agentName,
|
|
301
|
+
agentId: agentKey,
|
|
302
|
+
model
|
|
303
|
+
}),
|
|
304
|
+
guidance.startupProtocol,
|
|
305
|
+
guidance.contextLayerContract,
|
|
306
|
+
guidance.emailRegistrationWorkflow,
|
|
307
|
+
guidance.webResearchToolPolicy,
|
|
308
|
+
buildCurrentTimeBlock(/* @__PURE__ */ new Date()),
|
|
309
|
+
readAgentsMd(cwd),
|
|
310
|
+
buildSkillDiscoveryContextBlock(cwd) ?? ""
|
|
311
|
+
];
|
|
312
|
+
const systemTokens = estimateTokenCount(
|
|
313
|
+
systemParts.filter((part) => part?.trim()).join("\n\n")
|
|
314
|
+
);
|
|
315
|
+
const toolTokens = estimateToolSchemas(toolNames);
|
|
316
|
+
return Math.max(0, systemTokens + toolTokens);
|
|
317
|
+
}
|
|
202
318
|
|
|
203
319
|
// packages/cli/client/compactDialog.ts
|
|
204
320
|
import { ulid } from "ulid";
|
|
@@ -479,6 +595,12 @@ function renderDialogRow(args, colorEnabled = resolveCliColorEnabled()) {
|
|
|
479
595
|
function renderDialogOverflow(text, colorEnabled = resolveCliColorEnabled()) {
|
|
480
596
|
return themeText(` ${text}`, "chrome", colorEnabled);
|
|
481
597
|
}
|
|
598
|
+
function renderOverflowAbove(count, colorEnabled = resolveCliColorEnabled()) {
|
|
599
|
+
return renderDialogOverflow(t("dialogMoreAbove", String(count)), colorEnabled);
|
|
600
|
+
}
|
|
601
|
+
function renderOverflowBelow(count, colorEnabled = resolveCliColorEnabled()) {
|
|
602
|
+
return renderDialogOverflow(t("dialogMoreBelow", String(count)), colorEnabled);
|
|
603
|
+
}
|
|
482
604
|
function renderDialogCommand(text, colorEnabled = resolveCliColorEnabled()) {
|
|
483
605
|
return themeText(` ${text}`, "danger", colorEnabled);
|
|
484
606
|
}
|
|
@@ -577,7 +699,7 @@ function renderSelectDialog(args) {
|
|
|
577
699
|
];
|
|
578
700
|
const lines = [...titleLines, ""];
|
|
579
701
|
if (window.start > 0) {
|
|
580
|
-
lines.push(
|
|
702
|
+
lines.push(renderOverflowAbove(window.start));
|
|
581
703
|
}
|
|
582
704
|
for (let index = window.start; index < window.end; index += 1) {
|
|
583
705
|
const item = args.items[index];
|
|
@@ -590,7 +712,7 @@ function renderSelectDialog(args) {
|
|
|
590
712
|
);
|
|
591
713
|
}
|
|
592
714
|
if (window.end < total) {
|
|
593
|
-
lines.push("",
|
|
715
|
+
lines.push("", renderOverflowBelow(total - window.end));
|
|
594
716
|
}
|
|
595
717
|
return lines.join("\n");
|
|
596
718
|
}
|
|
@@ -819,7 +941,7 @@ async function runSelectDialog(args) {
|
|
|
819
941
|
// packages/cli/tui/confirmDialog.ts
|
|
820
942
|
var FALLBACK_TERMINAL_WIDTH = 80;
|
|
821
943
|
var WIDE_CHAR = /[ᄀ-ᅟ⺀-〾ぁ-㏿㐀-䶿一-鿿ꀀ-가-힣豈-︰--⦆¢-₩]/;
|
|
822
|
-
function
|
|
944
|
+
function displayWidth2(text) {
|
|
823
945
|
let width = 0;
|
|
824
946
|
for (const char of text) width += WIDE_CHAR.test(char) ? 2 : 1;
|
|
825
947
|
return width;
|
|
@@ -827,9 +949,9 @@ function displayWidth(text) {
|
|
|
827
949
|
function truncateCommand(command, maxWidth) {
|
|
828
950
|
const indent = 2;
|
|
829
951
|
const budget = Math.max(10, maxWidth - indent);
|
|
830
|
-
if (
|
|
952
|
+
if (displayWidth2(command) <= budget) return command;
|
|
831
953
|
const marker = ` ${t("dialogConfirmCommandTruncated")}`;
|
|
832
|
-
const keep = Math.max(1, budget -
|
|
954
|
+
const keep = Math.max(1, budget - displayWidth2(marker));
|
|
833
955
|
let kept = "";
|
|
834
956
|
let width = 0;
|
|
835
957
|
for (const char of command) {
|
|
@@ -1111,19 +1233,23 @@ function renderTabBar(questions, activeIndex, colorEnabled) {
|
|
|
1111
1233
|
}
|
|
1112
1234
|
return colorEnabled ? themeText(` ${label} `, "muted", colorEnabled) : ` ${label} `;
|
|
1113
1235
|
});
|
|
1114
|
-
const submitLabel = "
|
|
1236
|
+
const submitLabel = t("askChoiceSubmit");
|
|
1115
1237
|
return tabs.join(" ") + " " + (colorEnabled ? themeText(submitLabel, "chrome", colorEnabled) : submitLabel);
|
|
1116
1238
|
}
|
|
1117
|
-
function renderFooter(colorEnabled) {
|
|
1118
|
-
const hints =
|
|
1239
|
+
function renderFooter(multiSelect, colorEnabled) {
|
|
1240
|
+
const hints = multiSelect ? t("askChoiceFooterMulti") : t("askChoiceFooterSingle");
|
|
1119
1241
|
return colorEnabled ? themeText(` ${hints}`, "chrome", colorEnabled) : ` ${hints}`;
|
|
1120
1242
|
}
|
|
1243
|
+
function otherRowPrefix(index) {
|
|
1244
|
+
return ` [${index + 1}] ${t("askChoiceOtherLabel")}: `;
|
|
1245
|
+
}
|
|
1121
1246
|
function renderAskChoiceFrame(state) {
|
|
1122
1247
|
const colorEnabled = resolveCliColorEnabled();
|
|
1123
1248
|
const q = state.questions[state.activeIndex];
|
|
1124
1249
|
const qs = state.questionStates[state.activeIndex];
|
|
1125
1250
|
const lines = [];
|
|
1126
|
-
|
|
1251
|
+
let otherCursor = null;
|
|
1252
|
+
lines.push(renderDialogTitle(t("askChoiceTitle")));
|
|
1127
1253
|
lines.push("");
|
|
1128
1254
|
if (state.questions.length > 1) {
|
|
1129
1255
|
lines.push(renderTabBar(state.questions, state.activeIndex, colorEnabled));
|
|
@@ -1134,11 +1260,11 @@ function renderAskChoiceFrame(state) {
|
|
|
1134
1260
|
);
|
|
1135
1261
|
if (q.multiSelect) {
|
|
1136
1262
|
lines.push(
|
|
1137
|
-
colorEnabled ? themeText(
|
|
1263
|
+
colorEnabled ? themeText(` ${t("askChoiceHintMulti")}`, "muted", colorEnabled) : ` ${t("askChoiceHintMulti")}`
|
|
1138
1264
|
);
|
|
1139
1265
|
} else {
|
|
1140
1266
|
lines.push(
|
|
1141
|
-
colorEnabled ? themeText(
|
|
1267
|
+
colorEnabled ? themeText(` ${t("askChoiceHintSingle")}`, "muted", colorEnabled) : ` ${t("askChoiceHintSingle")}`
|
|
1142
1268
|
);
|
|
1143
1269
|
}
|
|
1144
1270
|
lines.push("");
|
|
@@ -1148,9 +1274,7 @@ function renderAskChoiceFrame(state) {
|
|
|
1148
1274
|
total: totalRows
|
|
1149
1275
|
});
|
|
1150
1276
|
if (window.start > 0) {
|
|
1151
|
-
lines.push(
|
|
1152
|
-
colorEnabled ? themeText(` \u2191 ${window.start} more`, "chrome", colorEnabled) : ` \u2191 ${window.start} more`
|
|
1153
|
-
);
|
|
1277
|
+
lines.push(renderOverflowAbove(window.start));
|
|
1154
1278
|
}
|
|
1155
1279
|
for (let i = window.start; i < window.end; i++) {
|
|
1156
1280
|
if (i < q.choices.length) {
|
|
@@ -1168,25 +1292,29 @@ function renderAskChoiceFrame(state) {
|
|
|
1168
1292
|
} else {
|
|
1169
1293
|
const focused = qs.cursorIndex === i;
|
|
1170
1294
|
const marker = focused ? DIALOG_CURSOR : " ";
|
|
1171
|
-
const
|
|
1172
|
-
const
|
|
1295
|
+
const plainPrefix = `${marker}${otherRowPrefix(i)}`;
|
|
1296
|
+
const plainRow = `${plainPrefix}${qs.otherText}`;
|
|
1173
1297
|
if (focused && colorEnabled) {
|
|
1174
1298
|
lines.push(
|
|
1175
|
-
`\x1B[1m${themeColorSequence("accent")}${
|
|
1299
|
+
`\x1B[1m${themeColorSequence("accent")}${plainRow}\x1B[0m`
|
|
1176
1300
|
);
|
|
1177
1301
|
} else {
|
|
1178
|
-
lines.push(
|
|
1302
|
+
lines.push(plainRow);
|
|
1303
|
+
}
|
|
1304
|
+
if (qs.otherFocused) {
|
|
1305
|
+
otherCursor = {
|
|
1306
|
+
lineIndex: lines.length - 1,
|
|
1307
|
+
col: displayWidth(plainPrefix + qs.otherText)
|
|
1308
|
+
};
|
|
1179
1309
|
}
|
|
1180
1310
|
}
|
|
1181
1311
|
}
|
|
1182
1312
|
if (window.end < totalRows) {
|
|
1183
|
-
lines.push(
|
|
1184
|
-
colorEnabled ? themeText(` \u2193 ${totalRows - window.end} more`, "chrome", colorEnabled) : ` \u2193 ${totalRows - window.end} more`
|
|
1185
|
-
);
|
|
1313
|
+
lines.push(renderOverflowBelow(totalRows - window.end));
|
|
1186
1314
|
}
|
|
1187
1315
|
lines.push("");
|
|
1188
|
-
lines.push(renderFooter(colorEnabled));
|
|
1189
|
-
return lines.join("\n");
|
|
1316
|
+
lines.push(renderFooter(q.multiSelect, colorEnabled));
|
|
1317
|
+
return { text: lines.join("\n"), otherCursor };
|
|
1190
1318
|
}
|
|
1191
1319
|
async function runAskChoiceDialog(args) {
|
|
1192
1320
|
const { request } = args;
|
|
@@ -1199,9 +1327,6 @@ async function runAskChoiceDialog(args) {
|
|
|
1199
1327
|
if (normalized.questions.length === 0) {
|
|
1200
1328
|
return { kind: "cancelled" };
|
|
1201
1329
|
}
|
|
1202
|
-
const q0 = normalized.questions[0];
|
|
1203
|
-
if (normalized.questions.length === 1 && !q0.multiSelect && !q0.allowOther) {
|
|
1204
|
-
}
|
|
1205
1330
|
let state = createInitialAskChoiceState(normalized.questions);
|
|
1206
1331
|
const output = args.output ?? process.stdout;
|
|
1207
1332
|
const input = args.input ?? process.stdin;
|
|
@@ -1215,9 +1340,15 @@ async function runAskChoiceDialog(args) {
|
|
|
1215
1340
|
typeof args.bottomRow === "function" ? args.bottomRow() : args.bottomRow ?? 0
|
|
1216
1341
|
);
|
|
1217
1342
|
let lastBottomRow = 0;
|
|
1343
|
+
let unanchoredCursorLift = 0;
|
|
1344
|
+
const restoreUnanchoredCursor = () => {
|
|
1345
|
+
if (unanchoredCursorLift <= 0) return;
|
|
1346
|
+
output.write(`\x1B[${unanchoredCursorLift}B`);
|
|
1347
|
+
unanchoredCursorLift = 0;
|
|
1348
|
+
};
|
|
1218
1349
|
const paint = () => {
|
|
1219
1350
|
const frame = renderAskChoiceFrame(state);
|
|
1220
|
-
const lines = frame.split("\n");
|
|
1351
|
+
const lines = frame.text.split("\n");
|
|
1221
1352
|
const lineCount = lines.length;
|
|
1222
1353
|
const canPosition = outputIsTty(output) && typeof output.write === "function";
|
|
1223
1354
|
if (bottomAnchored && canPosition) {
|
|
@@ -1234,22 +1365,37 @@ async function runAskChoiceDialog(args) {
|
|
|
1234
1365
|
}
|
|
1235
1366
|
lastBottomRow = anchorRow;
|
|
1236
1367
|
renderedLineCount = lineCount;
|
|
1368
|
+
unanchoredCursorLift = 0;
|
|
1369
|
+
if (frame.otherCursor) {
|
|
1370
|
+
const cursorRow = anchorRow - (lineCount - 1 - frame.otherCursor.lineIndex);
|
|
1371
|
+
if (cursorRow >= 1) {
|
|
1372
|
+
output.write(`\x1B[${cursorRow};${frame.otherCursor.col + 1}H`);
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1237
1375
|
return;
|
|
1238
1376
|
}
|
|
1239
1377
|
if (canPosition) {
|
|
1378
|
+
restoreUnanchoredCursor();
|
|
1240
1379
|
for (let i = 0; i < renderedLineCount; i++) {
|
|
1241
1380
|
output.write("\x1B[1A\x1B[2K");
|
|
1242
1381
|
}
|
|
1243
|
-
output.write(`${frame}
|
|
1382
|
+
output.write(`${frame.text}
|
|
1244
1383
|
`);
|
|
1245
1384
|
renderedLineCount = lineCount;
|
|
1385
|
+
if (frame.otherCursor) {
|
|
1386
|
+
const linesFromBottom = lineCount - frame.otherCursor.lineIndex;
|
|
1387
|
+
output.write(`\x1B[${linesFromBottom}A`);
|
|
1388
|
+
output.write(`\x1B[${frame.otherCursor.col + 1}G`);
|
|
1389
|
+
unanchoredCursorLift = linesFromBottom;
|
|
1390
|
+
}
|
|
1246
1391
|
return;
|
|
1247
1392
|
}
|
|
1248
1393
|
if (typeof output.write === "function") {
|
|
1249
|
-
output.write(`${frame}
|
|
1394
|
+
output.write(`${frame.text}
|
|
1250
1395
|
`);
|
|
1251
1396
|
}
|
|
1252
1397
|
renderedLineCount = lineCount;
|
|
1398
|
+
unanchoredCursorLift = 0;
|
|
1253
1399
|
};
|
|
1254
1400
|
const resizeTarget = output;
|
|
1255
1401
|
const onOutputResize = () => paint();
|
|
@@ -1277,6 +1423,9 @@ async function runAskChoiceDialog(args) {
|
|
|
1277
1423
|
continue;
|
|
1278
1424
|
}
|
|
1279
1425
|
let action = null;
|
|
1426
|
+
const qs = state.questionStates[state.activeIndex];
|
|
1427
|
+
const q = state.questions[state.activeIndex];
|
|
1428
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
1280
1429
|
if (isCancel(sequence)) {
|
|
1281
1430
|
action = { type: "CANCEL" };
|
|
1282
1431
|
} else if (sequence === CSI_TAB) {
|
|
@@ -1288,11 +1437,17 @@ async function runAskChoiceDialog(args) {
|
|
|
1288
1437
|
} else if (isArrowDown(sequence)) {
|
|
1289
1438
|
action = { type: "MOVE_CURSOR", delta: 1 };
|
|
1290
1439
|
} else if (sequence === CSI_SPACE) {
|
|
1291
|
-
|
|
1440
|
+
if (qs.otherFocused) {
|
|
1441
|
+
action = {
|
|
1442
|
+
type: "SET_OTHER_TEXT",
|
|
1443
|
+
text: qs.otherText + " "
|
|
1444
|
+
};
|
|
1445
|
+
} else if (q.multiSelect) {
|
|
1446
|
+
action = { type: "TOGGLE_AT_CURSOR" };
|
|
1447
|
+
} else if (isOtherRow) {
|
|
1448
|
+
action = { type: "FOCUS_OTHER" };
|
|
1449
|
+
}
|
|
1292
1450
|
} else if (isSubmit(sequence)) {
|
|
1293
|
-
const qs = state.questionStates[state.activeIndex];
|
|
1294
|
-
const q = state.questions[state.activeIndex];
|
|
1295
|
-
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
1296
1451
|
if (qs.otherFocused) {
|
|
1297
1452
|
action = { type: "BLUR_OTHER" };
|
|
1298
1453
|
} else if (isOtherRow && !qs.otherFocused) {
|
|
@@ -1303,27 +1458,29 @@ async function runAskChoiceDialog(args) {
|
|
|
1303
1458
|
action = { type: "SELECT_AT_CURSOR" };
|
|
1304
1459
|
}
|
|
1305
1460
|
} else if (sequence === CSI_BACKSPACE || sequence === CSI_BACKSPACE_ALT) {
|
|
1306
|
-
const qs = state.questionStates[state.activeIndex];
|
|
1307
1461
|
if (qs.otherFocused && qs.otherText.length > 0) {
|
|
1462
|
+
const chars = Array.from(qs.otherText);
|
|
1308
1463
|
action = {
|
|
1309
1464
|
type: "SET_OTHER_TEXT",
|
|
1310
|
-
text:
|
|
1465
|
+
text: chars.slice(0, -1).join("")
|
|
1311
1466
|
};
|
|
1312
1467
|
}
|
|
1313
1468
|
} else if (sequence.length >= 1 && sequence.charCodeAt(0) >= 32 && !sequence.startsWith("\x1B")) {
|
|
1314
|
-
|
|
1315
|
-
if (qs.otherFocused) {
|
|
1469
|
+
if (qs.otherFocused || isOtherRow && q.allowOther) {
|
|
1316
1470
|
const cleaned = sequence.replace(/[\x00-\x1f\x7f]/g, "");
|
|
1317
1471
|
if (cleaned) {
|
|
1472
|
+
if (!qs.otherFocused) {
|
|
1473
|
+
state = askChoiceReducer(state, { type: "FOCUS_OTHER" });
|
|
1474
|
+
}
|
|
1475
|
+
const currentText = state.questionStates[state.activeIndex].otherText;
|
|
1318
1476
|
action = {
|
|
1319
1477
|
type: "SET_OTHER_TEXT",
|
|
1320
|
-
text:
|
|
1478
|
+
text: currentText + cleaned
|
|
1321
1479
|
};
|
|
1322
1480
|
}
|
|
1323
1481
|
}
|
|
1324
1482
|
}
|
|
1325
1483
|
if (action) {
|
|
1326
|
-
const prev = state;
|
|
1327
1484
|
state = askChoiceReducer(state, action);
|
|
1328
1485
|
if (state.phase !== "active") break;
|
|
1329
1486
|
if (action.type === "BLUR_OTHER" && state.activeIndex >= state.questions.length - 1 && canSubmit(state)) {
|
|
@@ -1347,6 +1504,7 @@ async function runAskChoiceDialog(args) {
|
|
|
1347
1504
|
renderedLineCount
|
|
1348
1505
|
);
|
|
1349
1506
|
} else {
|
|
1507
|
+
restoreUnanchoredCursor();
|
|
1350
1508
|
for (let i = 0; i < renderedLineCount; i++) {
|
|
1351
1509
|
output.write("\x1B[1A\x1B[2K");
|
|
1352
1510
|
}
|
|
@@ -1360,13 +1518,13 @@ async function runAskChoiceDialog(args) {
|
|
|
1360
1518
|
}
|
|
1361
1519
|
if (result.answers.length === 1) {
|
|
1362
1520
|
const a = result.answers[0];
|
|
1521
|
+
const q = normalized.questions[0];
|
|
1522
|
+
const labels = a.selectedIds.map((id) => q.choices.find((c) => c.id === id)?.label ?? "").filter(Boolean);
|
|
1523
|
+
if (a.otherText) labels.push(a.otherText);
|
|
1363
1524
|
return {
|
|
1364
1525
|
kind: "selected",
|
|
1365
1526
|
userMessage: a.userMessage,
|
|
1366
|
-
label:
|
|
1367
|
-
const q = normalized.questions[0];
|
|
1368
|
-
return q.choices.find((c) => c.id === id)?.label ?? "";
|
|
1369
|
-
}).join(", ") || a.otherText || ""
|
|
1527
|
+
label: labels.join(", ") || a.otherText || ""
|
|
1370
1528
|
};
|
|
1371
1529
|
}
|
|
1372
1530
|
return {
|
|
@@ -1424,8 +1582,13 @@ function createActivityIndicator(deps) {
|
|
|
1424
1582
|
let lastActivityAt = 0;
|
|
1425
1583
|
let frameIndex = 0;
|
|
1426
1584
|
let timer = null;
|
|
1585
|
+
let stopping = false;
|
|
1427
1586
|
const elapsedSecFrom = (startedAt) => startedAt > 0 ? Math.max(0, Math.floor((now() - startedAt) / 1e3)) : 0;
|
|
1428
1587
|
const tick = () => {
|
|
1588
|
+
if (stopping) {
|
|
1589
|
+
deps.onRepaint();
|
|
1590
|
+
return;
|
|
1591
|
+
}
|
|
1429
1592
|
frameIndex += 1;
|
|
1430
1593
|
if (explicitLabel === null && !fallbackActive && deps.isTurnActive() && lastActivityAt > 0 && now() - lastActivityAt >= fallbackDelayMs) {
|
|
1431
1594
|
fallbackActive = true;
|
|
@@ -1454,9 +1617,21 @@ function createActivityIndicator(deps) {
|
|
|
1454
1617
|
ensureTimer();
|
|
1455
1618
|
deps.onRepaint();
|
|
1456
1619
|
};
|
|
1620
|
+
const markStopping = () => {
|
|
1621
|
+
stopping = true;
|
|
1622
|
+
deps.onRepaint();
|
|
1623
|
+
};
|
|
1624
|
+
const isStopping = () => stopping;
|
|
1457
1625
|
const getView = () => {
|
|
1458
1626
|
if (!deps.isTurnActive()) return null;
|
|
1459
1627
|
const frame = ACTIVITY_FRAMES[frameIndex % ACTIVITY_FRAMES.length];
|
|
1628
|
+
if (stopping) {
|
|
1629
|
+
return {
|
|
1630
|
+
frame,
|
|
1631
|
+
label: deps.stoppingLabel(),
|
|
1632
|
+
elapsedSec: 0
|
|
1633
|
+
};
|
|
1634
|
+
}
|
|
1460
1635
|
if (explicitLabel !== null) {
|
|
1461
1636
|
return {
|
|
1462
1637
|
frame,
|
|
@@ -1483,8 +1658,9 @@ function createActivityIndicator(deps) {
|
|
|
1483
1658
|
fallbackActive = false;
|
|
1484
1659
|
fallbackStartedAt = 0;
|
|
1485
1660
|
lastActivityAt = 0;
|
|
1661
|
+
stopping = false;
|
|
1486
1662
|
};
|
|
1487
|
-
return { report, getView, stop };
|
|
1663
|
+
return { report, getView, markStopping, isStopping, stop };
|
|
1488
1664
|
}
|
|
1489
1665
|
|
|
1490
1666
|
// packages/ai/agent/utils/sortUtils.ts
|
|
@@ -1724,13 +1900,25 @@ function findAgentCatalogEntry(entries, rawTarget) {
|
|
|
1724
1900
|
if (!target) return null;
|
|
1725
1901
|
if (/^\d+$/.test(target)) {
|
|
1726
1902
|
const entry = entries[Number(target) - 1];
|
|
1727
|
-
return entry ? {
|
|
1903
|
+
return entry ? {
|
|
1904
|
+
name: entry.name,
|
|
1905
|
+
key: entry.key,
|
|
1906
|
+
model: entry.model,
|
|
1907
|
+
...entry.apiSource ? { apiSource: entry.apiSource } : entry.kind === "platform" ? { apiSource: "platform" } : {}
|
|
1908
|
+
} : null;
|
|
1728
1909
|
}
|
|
1729
1910
|
const lower = target.toLowerCase();
|
|
1730
1911
|
const byName = entries.find(
|
|
1731
1912
|
(entry) => entry.name.toLowerCase() === lower || entry.key.toLowerCase() === lower || entry.key.toLowerCase().endsWith(`-${lower}`)
|
|
1732
1913
|
);
|
|
1733
|
-
if (byName)
|
|
1914
|
+
if (byName) {
|
|
1915
|
+
return {
|
|
1916
|
+
name: byName.name,
|
|
1917
|
+
key: byName.key,
|
|
1918
|
+
model: byName.model,
|
|
1919
|
+
...byName.apiSource ? { apiSource: byName.apiSource } : byName.kind === "platform" ? { apiSource: "platform" } : {}
|
|
1920
|
+
};
|
|
1921
|
+
}
|
|
1734
1922
|
if (target.startsWith("agent-") || target.startsWith("agent-pub-")) {
|
|
1735
1923
|
return { name: target, key: target };
|
|
1736
1924
|
}
|
|
@@ -1789,6 +1977,8 @@ async function runAgentPicker(args) {
|
|
|
1789
1977
|
kind: "selected",
|
|
1790
1978
|
name: selected.name,
|
|
1791
1979
|
key: selected.key,
|
|
1980
|
+
model: selected.model,
|
|
1981
|
+
apiSource: selected.apiSource ?? (selected.kind === "platform" ? "platform" : void 0),
|
|
1792
1982
|
entries
|
|
1793
1983
|
};
|
|
1794
1984
|
}
|
|
@@ -1798,7 +1988,11 @@ function resolveAgentSwitchTarget(rawTarget, catalogEntries = []) {
|
|
|
1798
1988
|
const aliasEntry = catalogEntries.find((entry) => entry.key === resolvedKey);
|
|
1799
1989
|
return {
|
|
1800
1990
|
name: aliasEntry?.name ?? asTrimmedLowercaseString(rawTarget),
|
|
1801
|
-
key: resolvedKey
|
|
1991
|
+
key: resolvedKey,
|
|
1992
|
+
...aliasEntry?.model ? { model: aliasEntry.model } : {},
|
|
1993
|
+
...aliasEntry ? {
|
|
1994
|
+
...aliasEntry.apiSource ? { apiSource: aliasEntry.apiSource } : aliasEntry.kind === "platform" ? { apiSource: "platform" } : {}
|
|
1995
|
+
} : {}
|
|
1802
1996
|
};
|
|
1803
1997
|
}
|
|
1804
1998
|
return findAgentCatalogEntry(catalogEntries, rawTarget);
|
|
@@ -1811,10 +2005,10 @@ function formatDialogTimestamp(value, now = Date.now()) {
|
|
|
1811
2005
|
const time = typeof value === "number" ? value : Date.parse(value);
|
|
1812
2006
|
if (!Number.isFinite(time) || time <= 0) return "";
|
|
1813
2007
|
const deltaSeconds = Math.max(0, Math.floor((now - time) / 1e3));
|
|
1814
|
-
if (deltaSeconds < 60) return "
|
|
1815
|
-
if (deltaSeconds < 3600) return
|
|
1816
|
-
if (deltaSeconds < 86400) return
|
|
1817
|
-
if (deltaSeconds < 30 * 86400) return
|
|
2008
|
+
if (deltaSeconds < 60) return t("timeJustNow");
|
|
2009
|
+
if (deltaSeconds < 3600) return t("timeMinutesAgo", String(Math.floor(deltaSeconds / 60)));
|
|
2010
|
+
if (deltaSeconds < 86400) return t("timeHoursAgo", String(Math.floor(deltaSeconds / 3600)));
|
|
2011
|
+
if (deltaSeconds < 30 * 86400) return t("timeDaysAgo", String(Math.floor(deltaSeconds / 86400)));
|
|
1818
2012
|
const date = new Date(time);
|
|
1819
2013
|
const pad = (part) => String(part).padStart(2, "0");
|
|
1820
2014
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
@@ -1831,7 +2025,7 @@ function toDialogPickerItems(dialogs) {
|
|
|
1831
2025
|
}
|
|
1832
2026
|
function renderDialogList(dialogs) {
|
|
1833
2027
|
if (dialogs.length === 0) return t("noDialogsYet");
|
|
1834
|
-
const lines = ["
|
|
2028
|
+
const lines = [t("recentDialogs")];
|
|
1835
2029
|
for (const [index, dialog] of dialogs.entries()) {
|
|
1836
2030
|
const stamp = formatDialogTimestamp(dialog.updatedAt ?? dialog.createdAt);
|
|
1837
2031
|
lines.push(
|
|
@@ -1839,7 +2033,7 @@ function renderDialogList(dialogs) {
|
|
|
1839
2033
|
` id=${dialog.id}`
|
|
1840
2034
|
);
|
|
1841
2035
|
}
|
|
1842
|
-
lines.push("", "
|
|
2036
|
+
lines.push("", t("dialogListTip"));
|
|
1843
2037
|
return lines.join("\n");
|
|
1844
2038
|
}
|
|
1845
2039
|
async function fetchRecentDialogs(args) {
|
|
@@ -1920,7 +2114,7 @@ async function runDialogPicker(args) {
|
|
|
1920
2114
|
}
|
|
1921
2115
|
|
|
1922
2116
|
// packages/cli/tui/pasteImage.ts
|
|
1923
|
-
import { existsSync } from "node:fs";
|
|
2117
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
1924
2118
|
import { readFile, stat } from "node:fs/promises";
|
|
1925
2119
|
import { homedir } from "node:os";
|
|
1926
2120
|
import { isAbsolute, resolve } from "node:path";
|
|
@@ -1975,7 +2169,7 @@ function detectImagePaths(line, cwd) {
|
|
|
1975
2169
|
if (!token.raw) continue;
|
|
1976
2170
|
const resolved = resolveImageSource(token.decoded, cwd);
|
|
1977
2171
|
if (!isImagePath(resolved)) continue;
|
|
1978
|
-
if (!
|
|
2172
|
+
if (!existsSync2(resolved)) continue;
|
|
1979
2173
|
out.push({ raw: token.raw, resolvedPath: resolved });
|
|
1980
2174
|
}
|
|
1981
2175
|
return out;
|
|
@@ -2191,271 +2385,6 @@ function detectGitStatus(cwd) {
|
|
|
2191
2385
|
}
|
|
2192
2386
|
}
|
|
2193
2387
|
|
|
2194
|
-
// packages/cli/tui/tuiAnsi.ts
|
|
2195
|
-
var ANSI_ESCAPE_REGEX = /\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/g;
|
|
2196
|
-
var OSC_HYPERLINK_REGEX = /\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)\x1b\]8;;(?:\x07|\x1b\\)|\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/g;
|
|
2197
|
-
function stripAnsi(text) {
|
|
2198
|
-
return text.replace(OSC_HYPERLINK_REGEX, "").replace(ANSI_ESCAPE_REGEX, "");
|
|
2199
|
-
}
|
|
2200
|
-
var SGR_SEQUENCE_REGEX = /^\x1b\[[0-9;]*m/;
|
|
2201
|
-
var TRAILING_SGR_REGEX = /(?:\x1b\[[0-9;]*m)+$/;
|
|
2202
|
-
function applyTerminalOutputToText(existing, chunk) {
|
|
2203
|
-
if (!chunk) return existing;
|
|
2204
|
-
let text = existing;
|
|
2205
|
-
let index = 0;
|
|
2206
|
-
while (index < chunk.length) {
|
|
2207
|
-
if (chunk[index] === "\x1B") {
|
|
2208
|
-
const sgr = SGR_SEQUENCE_REGEX.exec(chunk.slice(index));
|
|
2209
|
-
if (sgr) {
|
|
2210
|
-
text += sgr[0];
|
|
2211
|
-
index += sgr[0].length;
|
|
2212
|
-
continue;
|
|
2213
|
-
}
|
|
2214
|
-
const osc = chunk.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
2215
|
-
if (osc) {
|
|
2216
|
-
index += osc[0].length;
|
|
2217
|
-
continue;
|
|
2218
|
-
}
|
|
2219
|
-
const csi = chunk.slice(index).match(/^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]/);
|
|
2220
|
-
if (csi) {
|
|
2221
|
-
index += csi[0].length;
|
|
2222
|
-
continue;
|
|
2223
|
-
}
|
|
2224
|
-
index += 1;
|
|
2225
|
-
continue;
|
|
2226
|
-
}
|
|
2227
|
-
const ch = chunk[index];
|
|
2228
|
-
if (ch === "\r") {
|
|
2229
|
-
const lastNl = text.lastIndexOf("\n");
|
|
2230
|
-
text = lastNl === -1 ? "" : text.slice(0, lastNl + 1);
|
|
2231
|
-
index += 1;
|
|
2232
|
-
continue;
|
|
2233
|
-
}
|
|
2234
|
-
if (ch === "\n") {
|
|
2235
|
-
text += "\n";
|
|
2236
|
-
index += 1;
|
|
2237
|
-
continue;
|
|
2238
|
-
}
|
|
2239
|
-
if (ch === "\b") {
|
|
2240
|
-
const trailing = TRAILING_SGR_REGEX.exec(text);
|
|
2241
|
-
const sgrTail = trailing ? trailing[0] : "";
|
|
2242
|
-
const head = sgrTail ? text.slice(0, -sgrTail.length) : text;
|
|
2243
|
-
if (head.length > 0 && head[head.length - 1] !== "\n") {
|
|
2244
|
-
text = head.slice(0, -1) + sgrTail;
|
|
2245
|
-
}
|
|
2246
|
-
index += 1;
|
|
2247
|
-
continue;
|
|
2248
|
-
}
|
|
2249
|
-
const code = ch.charCodeAt(0);
|
|
2250
|
-
if (code < 32 && ch !== " " || code === 127) {
|
|
2251
|
-
index += 1;
|
|
2252
|
-
continue;
|
|
2253
|
-
}
|
|
2254
|
-
text += ch;
|
|
2255
|
-
index += 1;
|
|
2256
|
-
}
|
|
2257
|
-
return text;
|
|
2258
|
-
}
|
|
2259
|
-
function displayWidth2(str) {
|
|
2260
|
-
let width = 0;
|
|
2261
|
-
for (const char of str) {
|
|
2262
|
-
const code = char.codePointAt(0) ?? 0;
|
|
2263
|
-
if (code < 32 || code === 127) continue;
|
|
2264
|
-
if (code >= 4352 && code <= 4447 || // 0x2768-0x2775 (ornamental brackets, incl. the ❯ prompt at U+276F)
|
|
2265
|
-
// render narrow in terminals; counting them wide drifts the cursor.
|
|
2266
|
-
code >= 9728 && code <= 10175 && !(code >= 10088 && code <= 10101) || // 0x2B00-0x2BFF (Misc Symbols and Arrows, incl. ⬢ U+2B22 used as the
|
|
2267
|
-
// status-line agent icon) render double-wide in common monospace fonts;
|
|
2268
|
-
// counting ⬢ as width 1 drifts the whole status line right of the icon.
|
|
2269
|
-
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 ‘ ’).
|
|
2270
|
-
// In CJK locale + CJK fonts these render double-wide like 全角 punctuation;
|
|
2271
|
-
// in English fonts they stay width 1. Follow the active locale so Chinese
|
|
2272
|
-
// replies align correctly without breaking English terminal output.
|
|
2273
|
-
getCliLocale() === "zh" && (code === 8220 || code === 8221 || code === 8216 || code === 8217)) {
|
|
2274
|
-
width += 2;
|
|
2275
|
-
} else {
|
|
2276
|
-
width += 1;
|
|
2277
|
-
}
|
|
2278
|
-
}
|
|
2279
|
-
return width;
|
|
2280
|
-
}
|
|
2281
|
-
function visibleWidth(str) {
|
|
2282
|
-
return displayWidth2(stripAnsi(str));
|
|
2283
|
-
}
|
|
2284
|
-
function truncateAnsi(text, maxWidth) {
|
|
2285
|
-
if (maxWidth <= 0) return "";
|
|
2286
|
-
if (visibleWidth(text) <= maxWidth) return text;
|
|
2287
|
-
let width = 0;
|
|
2288
|
-
let out = "";
|
|
2289
|
-
let i = 0;
|
|
2290
|
-
let sawAnsi = false;
|
|
2291
|
-
while (i < text.length) {
|
|
2292
|
-
if (text[i] === "\x1B" && text[i + 1] === "[") {
|
|
2293
|
-
sawAnsi = true;
|
|
2294
|
-
let j = i + 2;
|
|
2295
|
-
while (j < text.length) {
|
|
2296
|
-
const code = text.charCodeAt(j);
|
|
2297
|
-
j += 1;
|
|
2298
|
-
if (code >= 64 && code <= 126) break;
|
|
2299
|
-
}
|
|
2300
|
-
out += text.slice(i, j);
|
|
2301
|
-
i = j;
|
|
2302
|
-
continue;
|
|
2303
|
-
}
|
|
2304
|
-
const codePoint = text.codePointAt(i) ?? 0;
|
|
2305
|
-
const char = String.fromCodePoint(codePoint);
|
|
2306
|
-
const charWidth = displayWidth2(char);
|
|
2307
|
-
if (width + charWidth > maxWidth) break;
|
|
2308
|
-
out += char;
|
|
2309
|
-
width += charWidth;
|
|
2310
|
-
i += char.length;
|
|
2311
|
-
}
|
|
2312
|
-
return sawAnsi ? `${out}\x1B[0m` : out;
|
|
2313
|
-
}
|
|
2314
|
-
function fitAnsiLine(text, width, ellipsis = "\u2026") {
|
|
2315
|
-
if (width <= 0) return "";
|
|
2316
|
-
if (visibleWidth(text) <= width) return text;
|
|
2317
|
-
const ellipsisWidth = displayWidth2(ellipsis);
|
|
2318
|
-
if (width < ellipsisWidth) return truncateAnsi(text, width);
|
|
2319
|
-
if (width === ellipsisWidth) return truncateAnsi(ellipsis, width) || truncateAnsi(text, width);
|
|
2320
|
-
return `${truncateAnsi(text, width - ellipsisWidth)}${ellipsis}`;
|
|
2321
|
-
}
|
|
2322
|
-
function countPhysicalLines(text, columns) {
|
|
2323
|
-
const lines = text.split("\n");
|
|
2324
|
-
let total = 0;
|
|
2325
|
-
for (const line of lines) {
|
|
2326
|
-
const width = displayWidth2(line);
|
|
2327
|
-
total += Math.max(1, Math.ceil(width / columns));
|
|
2328
|
-
}
|
|
2329
|
-
return Math.max(total, 1);
|
|
2330
|
-
}
|
|
2331
|
-
function takeDisplayWidth(text, width) {
|
|
2332
|
-
let used = 0;
|
|
2333
|
-
let index = 0;
|
|
2334
|
-
for (const char of text) {
|
|
2335
|
-
const charWidth = displayWidth2(char);
|
|
2336
|
-
if (used + charWidth > width && used > 0) break;
|
|
2337
|
-
used += charWidth;
|
|
2338
|
-
index += char.length;
|
|
2339
|
-
}
|
|
2340
|
-
return { prefix: text.slice(0, index), rest: text.slice(index) };
|
|
2341
|
-
}
|
|
2342
|
-
function padOrTruncateToWidth(text, width) {
|
|
2343
|
-
const textWidth = visibleWidth(text);
|
|
2344
|
-
if (textWidth > width) {
|
|
2345
|
-
return truncateAnsi(text, width);
|
|
2346
|
-
}
|
|
2347
|
-
return `${text}${" ".repeat(width - textWidth)}`;
|
|
2348
|
-
}
|
|
2349
|
-
var SGR_RESET_REGEX = /^\x1b\[0?m$/;
|
|
2350
|
-
function tokenizeAnsiLine(line) {
|
|
2351
|
-
const tokens = [];
|
|
2352
|
-
let index = 0;
|
|
2353
|
-
while (index < line.length) {
|
|
2354
|
-
if (line[index] === "\x1B") {
|
|
2355
|
-
const osc = line.slice(index).match(/^\x1b\]8;;[^\x07\x1b]*(?:\x07|\x1b\\)/);
|
|
2356
|
-
if (osc) {
|
|
2357
|
-
tokens.push({ kind: "sgr", value: osc[0], width: 0 });
|
|
2358
|
-
index += osc[0].length;
|
|
2359
|
-
continue;
|
|
2360
|
-
}
|
|
2361
|
-
const sgr = SGR_SEQUENCE_REGEX.exec(line.slice(index));
|
|
2362
|
-
if (sgr) {
|
|
2363
|
-
tokens.push({ kind: "sgr", value: sgr[0], width: 0 });
|
|
2364
|
-
index += sgr[0].length;
|
|
2365
|
-
continue;
|
|
2366
|
-
}
|
|
2367
|
-
}
|
|
2368
|
-
const codePoint = line.codePointAt(index) ?? 0;
|
|
2369
|
-
const value = String.fromCodePoint(codePoint);
|
|
2370
|
-
tokens.push({ kind: "char", value, width: displayWidth2(value) });
|
|
2371
|
-
index += value.length;
|
|
2372
|
-
}
|
|
2373
|
-
return tokens;
|
|
2374
|
-
}
|
|
2375
|
-
function wrapTranscriptLine(line, columns) {
|
|
2376
|
-
if (line === "") return [""];
|
|
2377
|
-
const tokens = tokenizeAnsiLine(line);
|
|
2378
|
-
const result = [];
|
|
2379
|
-
let activeStyles = [];
|
|
2380
|
-
const applyStyleToken = (value) => {
|
|
2381
|
-
if (SGR_RESET_REGEX.test(value)) {
|
|
2382
|
-
activeStyles = [];
|
|
2383
|
-
} else {
|
|
2384
|
-
activeStyles.push(value);
|
|
2385
|
-
}
|
|
2386
|
-
};
|
|
2387
|
-
let start = 0;
|
|
2388
|
-
while (start < tokens.length) {
|
|
2389
|
-
if (tokens.slice(start).every((token) => token.kind === "sgr")) {
|
|
2390
|
-
if (result.length > 0) break;
|
|
2391
|
-
}
|
|
2392
|
-
const openingStyles = [...activeStyles];
|
|
2393
|
-
let width = 0;
|
|
2394
|
-
let end = start;
|
|
2395
|
-
let lastBreak = -1;
|
|
2396
|
-
while (end < tokens.length) {
|
|
2397
|
-
const token = tokens[end];
|
|
2398
|
-
if (token.kind === "sgr") {
|
|
2399
|
-
end += 1;
|
|
2400
|
-
continue;
|
|
2401
|
-
}
|
|
2402
|
-
if (width + token.width > columns && width > 0) break;
|
|
2403
|
-
width += token.width;
|
|
2404
|
-
end += 1;
|
|
2405
|
-
if (token.value === " " || token.value === " ") {
|
|
2406
|
-
lastBreak = end;
|
|
2407
|
-
}
|
|
2408
|
-
}
|
|
2409
|
-
let segmentEnd = end;
|
|
2410
|
-
if (end < tokens.length && lastBreak > start) {
|
|
2411
|
-
const overflowToken = tokens[end];
|
|
2412
|
-
if (overflowToken.kind === "char" && overflowToken.value !== " " && overflowToken.width === 1) {
|
|
2413
|
-
segmentEnd = lastBreak;
|
|
2414
|
-
}
|
|
2415
|
-
}
|
|
2416
|
-
if (segmentEnd === start) segmentEnd = start + 1;
|
|
2417
|
-
let segment = "";
|
|
2418
|
-
let sawStyle = openingStyles.length > 0;
|
|
2419
|
-
for (let i = start; i < segmentEnd; i += 1) {
|
|
2420
|
-
const token = tokens[i];
|
|
2421
|
-
segment += token.value;
|
|
2422
|
-
if (token.kind === "sgr") {
|
|
2423
|
-
sawStyle = true;
|
|
2424
|
-
applyStyleToken(token.value);
|
|
2425
|
-
}
|
|
2426
|
-
}
|
|
2427
|
-
const prefix = openingStyles.join("");
|
|
2428
|
-
const needsReset = (sawStyle || activeStyles.length > 0) && !segment.endsWith("\x1B[0m");
|
|
2429
|
-
result.push(`${prefix}${segment}${needsReset ? "\x1B[0m" : ""}`);
|
|
2430
|
-
start = segmentEnd;
|
|
2431
|
-
while (start < tokens.length) {
|
|
2432
|
-
const token = tokens[start];
|
|
2433
|
-
if (token.kind === "char" && token.value === " ") {
|
|
2434
|
-
start += 1;
|
|
2435
|
-
continue;
|
|
2436
|
-
}
|
|
2437
|
-
break;
|
|
2438
|
-
}
|
|
2439
|
-
}
|
|
2440
|
-
return result.length > 0 ? result : [""];
|
|
2441
|
-
}
|
|
2442
|
-
function wrapTextToLines(text, columns) {
|
|
2443
|
-
const result = [];
|
|
2444
|
-
for (const logicalLine of text.split("\n")) {
|
|
2445
|
-
if (logicalLine === "") {
|
|
2446
|
-
result.push("");
|
|
2447
|
-
continue;
|
|
2448
|
-
}
|
|
2449
|
-
let remaining = logicalLine;
|
|
2450
|
-
while (remaining.length > 0) {
|
|
2451
|
-
const { prefix, rest } = takeDisplayWidth(remaining, columns);
|
|
2452
|
-
result.push(prefix);
|
|
2453
|
-
remaining = rest;
|
|
2454
|
-
}
|
|
2455
|
-
}
|
|
2456
|
-
return result;
|
|
2457
|
-
}
|
|
2458
|
-
|
|
2459
2388
|
// packages/cli/tui/sessionRender.ts
|
|
2460
2389
|
function formatCwd(cwd) {
|
|
2461
2390
|
const parts = cwd.split(/[/\\]/);
|
|
@@ -2470,12 +2399,12 @@ function formatElapsedSeconds(totalSeconds) {
|
|
|
2470
2399
|
const mins = minutes % 60;
|
|
2471
2400
|
return `${hours}h ${mins}m`;
|
|
2472
2401
|
}
|
|
2473
|
-
function renderComposerTokenChip(tokens, fallbackContextWindow) {
|
|
2402
|
+
function renderComposerTokenChip(tokens, fallbackContextWindow, estimatedContextTokens) {
|
|
2474
2403
|
const cw = tokens?.contextWindow ?? fallbackContextWindow;
|
|
2475
2404
|
if (!cw) {
|
|
2476
2405
|
return "context: \u2014";
|
|
2477
2406
|
}
|
|
2478
|
-
const used = tokens ? tokens.input + tokens.output : 0;
|
|
2407
|
+
const used = tokens ? tokens.input + tokens.output : Math.max(0, estimatedContextTokens ?? 0);
|
|
2479
2408
|
const pct = Math.min(100, used / cw * 100);
|
|
2480
2409
|
const pctText = pct > 0 && pct < 10 ? pct.toFixed(1) : Math.round(pct).toString();
|
|
2481
2410
|
return `context: ${pctText}% (${formatTokenCount(used)}/${formatTokenCount(cw)})`;
|
|
@@ -2497,7 +2426,17 @@ function renderStatusLine(state) {
|
|
|
2497
2426
|
const untrackedText = untracked > 0 ? ` ${themeText(`?${untracked}`, "muted", colorEnabled)}` : "";
|
|
2498
2427
|
parts.push(`${branchText}${modifiedText}${untrackedText}`);
|
|
2499
2428
|
}
|
|
2500
|
-
const
|
|
2429
|
+
const credits = state.apiSource === "platform" ? state.turnTokens?.credits : void 0;
|
|
2430
|
+
const creditsSuffix = credits !== void 0 && credits > 0 ? ` \xB7 \u26A1 ${credits.toFixed(2)} \u79EF\u5206` : "";
|
|
2431
|
+
const tokenSegment = themeText(
|
|
2432
|
+
renderComposerTokenChip(
|
|
2433
|
+
state.turnTokens,
|
|
2434
|
+
state.contextWindow,
|
|
2435
|
+
state.estimatedContextTokens
|
|
2436
|
+
) + creditsSuffix,
|
|
2437
|
+
"muted",
|
|
2438
|
+
colorEnabled
|
|
2439
|
+
);
|
|
2501
2440
|
parts.push(tokenSegment);
|
|
2502
2441
|
const runningCount = getProcessRegistry().list().filter((p) => p.status === "running").length;
|
|
2503
2442
|
if (runningCount > 0) {
|
|
@@ -2579,7 +2518,7 @@ function renderWelcome(state, frame = 0, maxFrames = 0, columns) {
|
|
|
2579
2518
|
const isDark = brightness === "dark";
|
|
2580
2519
|
let sceneArt = colorEnabled ? buildColoredScene(isDark, frame, maxFrames) : buildPlainScene(isDark, frame, maxFrames);
|
|
2581
2520
|
if (typeof columns === "number" && columns > 0) {
|
|
2582
|
-
const widestSceneCol = sceneArt.split("\n").reduce((max, line) => Math.max(max,
|
|
2521
|
+
const widestSceneCol = sceneArt.split("\n").reduce((max, line) => Math.max(max, displayWidth(stripAnsi(line))), 0);
|
|
2583
2522
|
if (columns < widestSceneCol) sceneArt = "";
|
|
2584
2523
|
}
|
|
2585
2524
|
const versionLine = colorEnabled ? `\x1B[1m${themeColorSequence("accent")}nolo\x1B[0m ${state.cliVersion ?? ""} | server ${state.serverUrl}`.replace(" |", " |") : `nolo ${state.cliVersion ?? ""} | server ${state.serverUrl}`.replace(" |", " |");
|
|
@@ -2629,19 +2568,19 @@ function renderContextPanel(state, colorEnabled = resolveCliColorEnabled()) {
|
|
|
2629
2568
|
];
|
|
2630
2569
|
let maxW = 0;
|
|
2631
2570
|
for (const l of labels) {
|
|
2632
|
-
const w =
|
|
2571
|
+
const w = displayWidth(l);
|
|
2633
2572
|
if (w > maxW) maxW = w;
|
|
2634
2573
|
}
|
|
2635
2574
|
const targetWidth = maxW >= 9 ? maxW + 1 : 9;
|
|
2636
2575
|
const padLabel = (raw) => {
|
|
2637
|
-
const w =
|
|
2576
|
+
const w = displayWidth(raw);
|
|
2638
2577
|
const padding = " ".repeat(Math.max(0, targetWidth - w));
|
|
2639
2578
|
return raw + padding;
|
|
2640
2579
|
};
|
|
2641
2580
|
const field = (rawLabel, value) => `${themeText(padLabel(rawLabel), "muted", colorEnabled)}${value}`;
|
|
2642
2581
|
const next = (command, description) => ` ${themeText(command, "accent", colorEnabled)}${themeText(description, "muted", colorEnabled)}`;
|
|
2643
2582
|
const titleText = t("contextTitle");
|
|
2644
|
-
const heading = colorEnabled ? [renderDialogTitle(titleText, true)] : [titleText, "\u2500".repeat(
|
|
2583
|
+
const heading = colorEnabled ? [renderDialogTitle(titleText, true)] : [titleText, "\u2500".repeat(displayWidth(titleText))];
|
|
2645
2584
|
return [
|
|
2646
2585
|
...heading,
|
|
2647
2586
|
field(labels[0], `${state.agentName} (${state.agentKey})`),
|
|
@@ -2684,86 +2623,6 @@ function renderKnownAgents(colorEnabled = resolveCliColorEnabled()) {
|
|
|
2684
2623
|
].join("\n");
|
|
2685
2624
|
}
|
|
2686
2625
|
|
|
2687
|
-
// packages/core/collapsedPaste.ts
|
|
2688
|
-
var COLLAPSE_PASTE_MIN_LINES = 8;
|
|
2689
|
-
var COLLAPSE_PASTE_MIN_CHARS = 400;
|
|
2690
|
-
var COLLAPSED_PASTE_PLACEHOLDER_RE = /\[paste #(\d+) · (\d+) lines\]/g;
|
|
2691
|
-
function countTextLines(text) {
|
|
2692
|
-
if (text.length === 0) return 0;
|
|
2693
|
-
let lines = 1;
|
|
2694
|
-
for (let i = 0; i < text.length; i += 1) {
|
|
2695
|
-
if (text.charCodeAt(i) === 10) lines += 1;
|
|
2696
|
-
}
|
|
2697
|
-
return lines;
|
|
2698
|
-
}
|
|
2699
|
-
function shouldCollapsePaste(text, threshold = {}) {
|
|
2700
|
-
const minLines = threshold.minLines ?? COLLAPSE_PASTE_MIN_LINES;
|
|
2701
|
-
const minChars = threshold.minChars ?? COLLAPSE_PASTE_MIN_CHARS;
|
|
2702
|
-
if (text.length === 0) return false;
|
|
2703
|
-
if (text.length >= minChars) return true;
|
|
2704
|
-
return countTextLines(text) >= minLines;
|
|
2705
|
-
}
|
|
2706
|
-
function formatCollapsedPastePlaceholder(id, text) {
|
|
2707
|
-
const lines = countTextLines(text);
|
|
2708
|
-
return `[paste #${id} \xB7 ${lines} lines]`;
|
|
2709
|
-
}
|
|
2710
|
-
function createCollapsedPasteStore() {
|
|
2711
|
-
return { nextId: 1, items: /* @__PURE__ */ new Map() };
|
|
2712
|
-
}
|
|
2713
|
-
function allocateCollapsedPaste(store, text) {
|
|
2714
|
-
const id = store.nextId;
|
|
2715
|
-
store.nextId += 1;
|
|
2716
|
-
store.items.set(id, text);
|
|
2717
|
-
return { id, placeholder: formatCollapsedPastePlaceholder(id, text) };
|
|
2718
|
-
}
|
|
2719
|
-
function releaseCollapsedPaste(store, id) {
|
|
2720
|
-
store.items.delete(id);
|
|
2721
|
-
}
|
|
2722
|
-
function clearCollapsedPasteStore(store) {
|
|
2723
|
-
store.items.clear();
|
|
2724
|
-
store.nextId = 1;
|
|
2725
|
-
}
|
|
2726
|
-
function expandCollapsedPastes(buffer, store) {
|
|
2727
|
-
if (store.items.size === 0) return buffer;
|
|
2728
|
-
COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
|
|
2729
|
-
return buffer.replace(COLLAPSED_PASTE_PLACEHOLDER_RE, (match, idRaw) => {
|
|
2730
|
-
const id = Number(idRaw);
|
|
2731
|
-
const full = store.items.get(id);
|
|
2732
|
-
return full === void 0 ? match : full;
|
|
2733
|
-
});
|
|
2734
|
-
}
|
|
2735
|
-
function expandRangeToCollapsedPasteChips(buffer, start, end) {
|
|
2736
|
-
let s = Math.max(0, Math.min(start, end));
|
|
2737
|
-
let e = Math.max(s, Math.max(start, end));
|
|
2738
|
-
if (s === e) return { start: s, end: e };
|
|
2739
|
-
COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
|
|
2740
|
-
let match;
|
|
2741
|
-
while ((match = COLLAPSED_PASTE_PLACEHOLDER_RE.exec(buffer)) !== null) {
|
|
2742
|
-
const chipStart = match.index;
|
|
2743
|
-
const chipEnd = chipStart + match[0].length;
|
|
2744
|
-
if (chipStart < e && chipEnd > s) {
|
|
2745
|
-
if (chipStart < s) s = chipStart;
|
|
2746
|
-
if (chipEnd > e) e = chipEnd;
|
|
2747
|
-
}
|
|
2748
|
-
}
|
|
2749
|
-
return { start: s, end: e };
|
|
2750
|
-
}
|
|
2751
|
-
function findCollapsedPasteSpanAt(buffer, pos, opts = {}) {
|
|
2752
|
-
COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
|
|
2753
|
-
let match;
|
|
2754
|
-
while ((match = COLLAPSED_PASTE_PLACEHOLDER_RE.exec(buffer)) !== null) {
|
|
2755
|
-
const start = match.index;
|
|
2756
|
-
const end = start + match[0].length;
|
|
2757
|
-
const inside = pos > start && pos < end;
|
|
2758
|
-
const atEnd = opts.preferLeft && pos === end;
|
|
2759
|
-
const atStart = !opts.preferLeft && pos === start;
|
|
2760
|
-
if (inside || atEnd || atStart) {
|
|
2761
|
-
return { id: Number(match[1]), start, end };
|
|
2762
|
-
}
|
|
2763
|
-
}
|
|
2764
|
-
return null;
|
|
2765
|
-
}
|
|
2766
|
-
|
|
2767
2626
|
// packages/cli/tui/sessionInput.ts
|
|
2768
2627
|
var PASTE_TOKEN_PREFIX = "\0PASTE\0";
|
|
2769
2628
|
function applyTuiInputKey(buffer, sequence, key = {}, cursorPos, options) {
|
|
@@ -3051,6 +2910,7 @@ function createInitialTuiState(env = process.env) {
|
|
|
3051
2910
|
) || void 0;
|
|
3052
2911
|
const dialogEnvValue = asOptionalTrimmedString(env.NOLO_DIALOG);
|
|
3053
2912
|
const explicitDialogKey = asOptionalTrimmedString(env.NOLO_DIALOG_KEY) ?? (dialogEnvValue?.startsWith("dialog-") ? dialogEnvValue : void 0);
|
|
2913
|
+
const autoRouteDefault = env.NOLO_AUTO_ROUTE !== "0";
|
|
3054
2914
|
return {
|
|
3055
2915
|
agentKey,
|
|
3056
2916
|
agentName,
|
|
@@ -3076,16 +2936,41 @@ function createInitialTuiState(env = process.env) {
|
|
|
3076
2936
|
"hide"
|
|
3077
2937
|
),
|
|
3078
2938
|
toolDisplay: normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "compact"),
|
|
3079
|
-
contextWindow:
|
|
2939
|
+
contextWindow: resolveAgentContextWindow({
|
|
2940
|
+
agentKey,
|
|
2941
|
+
agentName,
|
|
2942
|
+
autoRouteDefault
|
|
2943
|
+
}),
|
|
2944
|
+
estimatedContextTokens: estimateDefaultCliContextTokens({
|
|
2945
|
+
cwd,
|
|
2946
|
+
agentKey,
|
|
2947
|
+
agentName: autoRouteDefault ? "DeepSeek V4 Flash" : agentName,
|
|
2948
|
+
model: autoRouteDefault ? "deepseek-v4-flash" : void 0
|
|
2949
|
+
}),
|
|
2950
|
+
apiSource: PLATFORM_AGENTS.some((entry) => entry.key === agentKey) ? "platform" : void 0
|
|
3080
2951
|
};
|
|
3081
2952
|
}
|
|
3082
|
-
function applyAgentSwitch(state, target) {
|
|
2953
|
+
function applyAgentSwitch(state, target, opts) {
|
|
2954
|
+
const autoRouteDefault = opts?.autoRouteDefault ?? process.env.NOLO_AUTO_ROUTE !== "0";
|
|
2955
|
+
const contextWindow = resolveAgentContextWindow({
|
|
2956
|
+
agentKey: target.key,
|
|
2957
|
+
agentName: target.name,
|
|
2958
|
+
model: target.model,
|
|
2959
|
+
autoRouteDefault
|
|
2960
|
+
});
|
|
3083
2961
|
return {
|
|
3084
2962
|
nextState: {
|
|
3085
2963
|
...state,
|
|
3086
2964
|
agentName: target.name,
|
|
3087
2965
|
agentKey: target.key,
|
|
3088
|
-
contextWindow
|
|
2966
|
+
contextWindow,
|
|
2967
|
+
estimatedContextTokens: estimateDefaultCliContextTokens({
|
|
2968
|
+
cwd: state.cwd,
|
|
2969
|
+
agentKey: target.key,
|
|
2970
|
+
agentName: target.name,
|
|
2971
|
+
model: target.model
|
|
2972
|
+
}),
|
|
2973
|
+
apiSource: target.apiSource
|
|
3089
2974
|
},
|
|
3090
2975
|
output: `Switched to ${target.name}. ${state.dialogId ? `Dialog kept: ${state.dialogId}` : "Dialog kept: new"}`
|
|
3091
2976
|
};
|
|
@@ -3147,32 +3032,32 @@ function handleTuiInput(input, state) {
|
|
|
3147
3032
|
return {
|
|
3148
3033
|
nextState: state,
|
|
3149
3034
|
output: [
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3035
|
+
t("themeCurrent", getActiveThemeName(), brightness),
|
|
3036
|
+
t("themeUsage"),
|
|
3037
|
+
t("themeAvailable", available)
|
|
3153
3038
|
].join("\n")
|
|
3154
3039
|
};
|
|
3155
3040
|
}
|
|
3156
3041
|
if (sub === "light" || sub === "dark") {
|
|
3157
3042
|
setActiveBrightness(sub);
|
|
3158
|
-
return { nextState: state, output:
|
|
3043
|
+
return { nextState: state, output: t("themeBrightnessSwitched", sub) };
|
|
3159
3044
|
}
|
|
3160
3045
|
if (sub === "auto") {
|
|
3161
3046
|
setActiveBrightness(null);
|
|
3162
3047
|
return {
|
|
3163
3048
|
nextState: state,
|
|
3164
|
-
output:
|
|
3049
|
+
output: t("themeBrightnessAuto", resolveTuiBrightness())
|
|
3165
3050
|
};
|
|
3166
3051
|
}
|
|
3167
3052
|
if (setActiveThemeName(sub)) {
|
|
3168
3053
|
return {
|
|
3169
3054
|
nextState: state,
|
|
3170
|
-
output:
|
|
3055
|
+
output: t("themeSwitched", sub)
|
|
3171
3056
|
};
|
|
3172
3057
|
} else {
|
|
3173
3058
|
return {
|
|
3174
3059
|
nextState: state,
|
|
3175
|
-
output:
|
|
3060
|
+
output: t("themeUnknown", sub, available)
|
|
3176
3061
|
};
|
|
3177
3062
|
}
|
|
3178
3063
|
}
|
|
@@ -3182,20 +3067,19 @@ function handleTuiInput(input, state) {
|
|
|
3182
3067
|
if (!sub) {
|
|
3183
3068
|
return {
|
|
3184
3069
|
nextState: state,
|
|
3185
|
-
output:
|
|
3186
|
-
Usage: /density <cozy|spacious>`
|
|
3070
|
+
output: t("densityCurrent", getActiveDensity())
|
|
3187
3071
|
};
|
|
3188
3072
|
}
|
|
3189
3073
|
if (sub === "cozy" || sub === "spacious") {
|
|
3190
3074
|
setActiveDensity(sub);
|
|
3191
3075
|
return {
|
|
3192
3076
|
nextState: state,
|
|
3193
|
-
output:
|
|
3077
|
+
output: t("densitySwitched", sub)
|
|
3194
3078
|
};
|
|
3195
3079
|
} else {
|
|
3196
3080
|
return {
|
|
3197
3081
|
nextState: state,
|
|
3198
|
-
output:
|
|
3082
|
+
output: t("densityUnknown", sub)
|
|
3199
3083
|
};
|
|
3200
3084
|
}
|
|
3201
3085
|
}
|
|
@@ -3206,52 +3090,52 @@ Usage: /density <cozy|spacious>`
|
|
|
3206
3090
|
if (argText !== "auto" && argText !== "local" && argText !== "server") {
|
|
3207
3091
|
return {
|
|
3208
3092
|
nextState: state,
|
|
3209
|
-
output: "
|
|
3093
|
+
output: t("runtimeUsage")
|
|
3210
3094
|
};
|
|
3211
3095
|
}
|
|
3212
3096
|
return {
|
|
3213
3097
|
nextState: { ...state, runtimeMode: argText },
|
|
3214
|
-
output:
|
|
3098
|
+
output: t("runtimeSet", argText)
|
|
3215
3099
|
};
|
|
3216
3100
|
}
|
|
3217
3101
|
case "/tools": {
|
|
3218
3102
|
if (!argText) {
|
|
3219
3103
|
return {
|
|
3220
3104
|
nextState: state,
|
|
3221
|
-
output:
|
|
3105
|
+
output: t("toolsCurrent", state.toolDisplay)
|
|
3222
3106
|
};
|
|
3223
3107
|
}
|
|
3224
3108
|
const normalizedArg = asTrimmedLowercaseString(argText);
|
|
3225
3109
|
if (!["hide", "compact", "verbose", "on", "off"].includes(normalizedArg)) {
|
|
3226
3110
|
return {
|
|
3227
3111
|
nextState: state,
|
|
3228
|
-
output: "
|
|
3112
|
+
output: t("toolsUsage")
|
|
3229
3113
|
};
|
|
3230
3114
|
}
|
|
3231
3115
|
const nextMode = normalizeToolDisplayMode(normalizedArg, state.toolDisplay);
|
|
3232
3116
|
return {
|
|
3233
3117
|
nextState: { ...state, toolDisplay: nextMode },
|
|
3234
|
-
output:
|
|
3118
|
+
output: t("toolsSet", nextMode)
|
|
3235
3119
|
};
|
|
3236
3120
|
}
|
|
3237
3121
|
case "/thinking": {
|
|
3238
3122
|
if (!argText) {
|
|
3239
3123
|
return {
|
|
3240
3124
|
nextState: state,
|
|
3241
|
-
output:
|
|
3125
|
+
output: t("thinkingCurrent", state.thinkingDisplay)
|
|
3242
3126
|
};
|
|
3243
3127
|
}
|
|
3244
3128
|
const normalizedArg = asTrimmedLowercaseString(argText);
|
|
3245
3129
|
if (!["hide", "marker", "show", "on", "off"].includes(normalizedArg)) {
|
|
3246
3130
|
return {
|
|
3247
3131
|
nextState: state,
|
|
3248
|
-
output: "
|
|
3132
|
+
output: t("thinkingUsage")
|
|
3249
3133
|
};
|
|
3250
3134
|
}
|
|
3251
3135
|
const nextMode = normalizeThinkingDisplayMode(normalizedArg, state.thinkingDisplay);
|
|
3252
3136
|
return {
|
|
3253
3137
|
nextState: { ...state, thinkingDisplay: nextMode },
|
|
3254
|
-
output:
|
|
3138
|
+
output: t("thinkingSet", nextMode)
|
|
3255
3139
|
};
|
|
3256
3140
|
}
|
|
3257
3141
|
case "/tasks":
|
|
@@ -3263,14 +3147,14 @@ Usage: /density <cozy|spacious>`
|
|
|
3263
3147
|
const stopped = all.filter((p) => p.status !== "running");
|
|
3264
3148
|
const lines = [];
|
|
3265
3149
|
if (running.length > 0) {
|
|
3266
|
-
lines.push(
|
|
3150
|
+
lines.push(t("tasksRunning", String(running.length)));
|
|
3267
3151
|
for (const p of running) {
|
|
3268
3152
|
const elapsed = formatElapsedSeconds(Math.floor((Date.now() - p.startedAt) / 1e3));
|
|
3269
3153
|
lines.push(` pid ${p.pid} ${p.label} running ${elapsed}`);
|
|
3270
3154
|
}
|
|
3271
3155
|
}
|
|
3272
3156
|
if (stopped.length > 0) {
|
|
3273
|
-
lines.push(
|
|
3157
|
+
lines.push(t("tasksStopped", String(stopped.length)));
|
|
3274
3158
|
for (const p of stopped) {
|
|
3275
3159
|
const elapsed = formatElapsedSeconds(Math.floor((Date.now() - p.startedAt) / 1e3));
|
|
3276
3160
|
const exitInfo = p.exitCode !== void 0 ? ` exit ${p.exitCode}` : "";
|
|
@@ -3278,38 +3162,38 @@ Usage: /density <cozy|spacious>`
|
|
|
3278
3162
|
}
|
|
3279
3163
|
}
|
|
3280
3164
|
if (all.length === 0) {
|
|
3281
|
-
lines.push("
|
|
3165
|
+
lines.push(t("tasksNone"));
|
|
3282
3166
|
}
|
|
3283
3167
|
return { nextState: state, output: lines.join("\n") };
|
|
3284
3168
|
}
|
|
3285
3169
|
case "/stop": {
|
|
3286
3170
|
const registry = getProcessRegistry();
|
|
3287
3171
|
if (!argText) {
|
|
3288
|
-
return { nextState: state, output: "
|
|
3172
|
+
return { nextState: state, output: t("stopUsage") };
|
|
3289
3173
|
}
|
|
3290
3174
|
if (argText === "all") {
|
|
3291
3175
|
const before = registry.list().filter((p) => p.status === "running").length;
|
|
3292
3176
|
registry.stopAll();
|
|
3293
|
-
return { nextState: state, output:
|
|
3177
|
+
return { nextState: state, output: t("stopAllDone", String(before)) };
|
|
3294
3178
|
}
|
|
3295
3179
|
if (/^\d+$/.test(argText)) {
|
|
3296
3180
|
const pid = parseInt(argText, 10);
|
|
3297
3181
|
const proc = registry.get(pid);
|
|
3298
3182
|
if (!proc || proc.status !== "running") {
|
|
3299
|
-
return { nextState: state, output:
|
|
3183
|
+
return { nextState: state, output: t("stopNoPid", String(pid)) };
|
|
3300
3184
|
}
|
|
3301
3185
|
registry.kill(pid);
|
|
3302
|
-
return { nextState: state, output:
|
|
3186
|
+
return { nextState: state, output: t("stopPidDone", String(pid), proc.label) };
|
|
3303
3187
|
}
|
|
3304
3188
|
const matches = registry.list().filter((p) => p.status === "running" && p.label === argText);
|
|
3305
3189
|
if (matches.length === 0) {
|
|
3306
|
-
return { nextState: state, output:
|
|
3190
|
+
return { nextState: state, output: t("stopNoLabel", argText) };
|
|
3307
3191
|
}
|
|
3308
3192
|
for (const p of matches) {
|
|
3309
3193
|
registry.kill(p.pid);
|
|
3310
3194
|
}
|
|
3311
3195
|
const stoppedNames = matches.map((p) => `pid ${p.pid} (${p.label})`).join(", ");
|
|
3312
|
-
return { nextState: state, output:
|
|
3196
|
+
return { nextState: state, output: t("stopLabelsDone", stoppedNames) };
|
|
3313
3197
|
}
|
|
3314
3198
|
case "/exit":
|
|
3315
3199
|
case "/quit":
|
|
@@ -3333,15 +3217,13 @@ Usage: /density <cozy|spacious>`
|
|
|
3333
3217
|
if (argText) {
|
|
3334
3218
|
return {
|
|
3335
3219
|
nextState: state,
|
|
3336
|
-
output:
|
|
3337
|
-
|
|
3338
|
-
${renderTuiHelp()}`
|
|
3220
|
+
output: t("unknownCommand", trimmed) + renderTuiHelp()
|
|
3339
3221
|
};
|
|
3340
3222
|
}
|
|
3341
3223
|
if (!state.dialogId) {
|
|
3342
3224
|
return {
|
|
3343
3225
|
nextState: state,
|
|
3344
|
-
output: "
|
|
3226
|
+
output: t("compactNothing")
|
|
3345
3227
|
};
|
|
3346
3228
|
}
|
|
3347
3229
|
return {
|
|
@@ -3368,15 +3250,14 @@ ${renderTuiHelp()}`
|
|
|
3368
3250
|
if (argText === "current" || argText === "show") {
|
|
3369
3251
|
return {
|
|
3370
3252
|
nextState: state,
|
|
3371
|
-
output:
|
|
3253
|
+
output: t("agentCurrent", state.agentName, state.agentKey)
|
|
3372
3254
|
};
|
|
3373
3255
|
}
|
|
3374
3256
|
const resolvedTarget = resolveAgentSwitchTarget(argText, resolveCatalogPlatformAgents());
|
|
3375
3257
|
if (!resolvedTarget) {
|
|
3376
3258
|
return {
|
|
3377
3259
|
nextState: state,
|
|
3378
|
-
output:
|
|
3379
|
-
Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
3260
|
+
output: t("agentUnknown", argText)
|
|
3380
3261
|
};
|
|
3381
3262
|
}
|
|
3382
3263
|
return applyAgentSwitch(state, resolvedTarget);
|
|
@@ -3430,6 +3311,16 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3430
3311
|
action: { type: "set-mouse", enabled: argText === "on" }
|
|
3431
3312
|
};
|
|
3432
3313
|
}
|
|
3314
|
+
case "/altscreen": {
|
|
3315
|
+
if (argText !== "on" && argText !== "off") {
|
|
3316
|
+
return { nextState: state, output: t("altscreenUsage") };
|
|
3317
|
+
}
|
|
3318
|
+
return {
|
|
3319
|
+
nextState: state,
|
|
3320
|
+
output: argText === "on" ? t("altscreenOn") : t("altscreenOff"),
|
|
3321
|
+
action: { type: "set-altscreen", enabled: argText === "on" }
|
|
3322
|
+
};
|
|
3323
|
+
}
|
|
3433
3324
|
case "/resume": {
|
|
3434
3325
|
if (!argText) {
|
|
3435
3326
|
return {
|
|
@@ -3459,7 +3350,7 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3459
3350
|
if (rest[0] === "attach") {
|
|
3460
3351
|
const docName = rest.slice(1).join(" ").trim();
|
|
3461
3352
|
if (!docName) {
|
|
3462
|
-
return { nextState: state, output: "
|
|
3353
|
+
return { nextState: state, output: t("docAttachUsage") };
|
|
3463
3354
|
}
|
|
3464
3355
|
const attachedDocs = state.attachedDocs.includes(docName) ? state.attachedDocs : [...state.attachedDocs, docName];
|
|
3465
3356
|
return {
|
|
@@ -3469,7 +3360,7 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3469
3360
|
}
|
|
3470
3361
|
return {
|
|
3471
3362
|
nextState: state,
|
|
3472
|
-
output: state.attachedDocs.length > 0 ?
|
|
3363
|
+
output: state.attachedDocs.length > 0 ? t("docList", state.attachedDocs.join(", ")) : t("docNone")
|
|
3473
3364
|
};
|
|
3474
3365
|
}
|
|
3475
3366
|
case "/skill": {
|
|
@@ -3477,7 +3368,7 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3477
3368
|
if (sub === "attach") {
|
|
3478
3369
|
const skillRef = rest.slice(1).join(" ").trim();
|
|
3479
3370
|
if (!skillRef) {
|
|
3480
|
-
return { nextState: state, output: "
|
|
3371
|
+
return { nextState: state, output: t("skillAttachUsage") };
|
|
3481
3372
|
}
|
|
3482
3373
|
const attachedSkills = state.attachedSkills.includes(skillRef) ? state.attachedSkills : [...state.attachedSkills, skillRef];
|
|
3483
3374
|
return {
|
|
@@ -3488,38 +3379,37 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3488
3379
|
if (sub === "detach") {
|
|
3489
3380
|
const skillRef = rest.slice(1).join(" ").trim();
|
|
3490
3381
|
if (!skillRef) {
|
|
3491
|
-
return { nextState: state, output: "
|
|
3382
|
+
return { nextState: state, output: t("skillDetachUsage") };
|
|
3492
3383
|
}
|
|
3493
3384
|
const attachedSkills = state.attachedSkills.filter((s) => s !== skillRef);
|
|
3494
3385
|
return {
|
|
3495
3386
|
nextState: { ...state, attachedSkills },
|
|
3496
|
-
output: state.attachedSkills.includes(skillRef) ?
|
|
3387
|
+
output: state.attachedSkills.includes(skillRef) ? t("skillDetached", skillRef) : t("skillNotAttached", skillRef)
|
|
3497
3388
|
};
|
|
3498
3389
|
}
|
|
3499
3390
|
if (sub === "clear") {
|
|
3500
3391
|
if (state.attachedSkills.length === 0) {
|
|
3501
|
-
return { nextState: state, output: "
|
|
3392
|
+
return { nextState: state, output: t("skillNone") };
|
|
3502
3393
|
}
|
|
3503
3394
|
return {
|
|
3504
3395
|
nextState: { ...state, attachedSkills: [] },
|
|
3505
|
-
output:
|
|
3396
|
+
output: t("skillCleared", String(state.attachedSkills.length))
|
|
3506
3397
|
};
|
|
3507
3398
|
}
|
|
3508
3399
|
return {
|
|
3509
3400
|
nextState: state,
|
|
3510
|
-
output: state.attachedSkills.length > 0 ?
|
|
3511
|
-
Usage: /skill attach <ref> | /skill detach <ref> | /skill clear` : "No skills attached. Use /skill attach <skill-ref> to attach a skill.\nSkill refs can be a dbKey (page-xxx), a skill name (searched in .agents/skills/ then docs/skills/), or a direct path."
|
|
3401
|
+
output: state.attachedSkills.length > 0 ? t("skillList", state.attachedSkills.join(", ")) : t("skillNoneHint")
|
|
3512
3402
|
};
|
|
3513
3403
|
}
|
|
3514
3404
|
case "/customize":
|
|
3515
3405
|
return {
|
|
3516
3406
|
nextState: state,
|
|
3517
|
-
output: "
|
|
3407
|
+
output: t("customizeHint")
|
|
3518
3408
|
};
|
|
3519
3409
|
case "/login":
|
|
3520
3410
|
return {
|
|
3521
3411
|
nextState: state,
|
|
3522
|
-
output: "
|
|
3412
|
+
output: t("loginHint")
|
|
3523
3413
|
};
|
|
3524
3414
|
case "/profile":
|
|
3525
3415
|
return {
|
|
@@ -3535,16 +3425,12 @@ Usage: /skill attach <ref> | /skill detach <ref> | /skill clear` : "No skills at
|
|
|
3535
3425
|
case "/version":
|
|
3536
3426
|
return {
|
|
3537
3427
|
nextState: state,
|
|
3538
|
-
output:
|
|
3539
|
-
Update this install with: nolo update
|
|
3540
|
-
If repo-local output differs, publish/install the latest npm package first.`
|
|
3428
|
+
output: t("versionInfo", state.cliVersion || t("versionUnknown"))
|
|
3541
3429
|
};
|
|
3542
3430
|
default:
|
|
3543
3431
|
return {
|
|
3544
3432
|
nextState: state,
|
|
3545
|
-
output:
|
|
3546
|
-
|
|
3547
|
-
${renderTuiHelp()}`
|
|
3433
|
+
output: t("unknownCommand", command) + renderTuiHelp()
|
|
3548
3434
|
};
|
|
3549
3435
|
}
|
|
3550
3436
|
}
|
|
@@ -3562,19 +3448,23 @@ function brightnessFromRgb(r, g, b) {
|
|
|
3562
3448
|
const luma = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
3563
3449
|
return luma >= 0.5 ? "light" : "dark";
|
|
3564
3450
|
}
|
|
3565
|
-
function
|
|
3451
|
+
function parseOsc11Background(reply) {
|
|
3566
3452
|
const match = reply.match(OSC11_REPLY_RE);
|
|
3567
3453
|
if (!match) return null;
|
|
3568
|
-
|
|
3454
|
+
const channels = [
|
|
3569
3455
|
componentToByte(match[1]),
|
|
3570
3456
|
componentToByte(match[2]),
|
|
3571
3457
|
componentToByte(match[3])
|
|
3572
|
-
|
|
3458
|
+
];
|
|
3459
|
+
return {
|
|
3460
|
+
brightness: brightnessFromRgb(channels[0], channels[1], channels[2]),
|
|
3461
|
+
hex: channels.map((v) => v.toString(16).padStart(2, "0").toUpperCase()).join("")
|
|
3462
|
+
};
|
|
3573
3463
|
}
|
|
3574
3464
|
function isTerminalDevice(stream) {
|
|
3575
3465
|
return stream instanceof ReadStream;
|
|
3576
3466
|
}
|
|
3577
|
-
async function
|
|
3467
|
+
async function detectTerminalBackground(args = {}) {
|
|
3578
3468
|
const stdin = args.stdin ?? process.stdin;
|
|
3579
3469
|
const stdout = args.stdout ?? process.stdout;
|
|
3580
3470
|
const timeoutMs = args.timeoutMs ?? 100;
|
|
@@ -3601,7 +3491,7 @@ async function detectTerminalBrightness(args = {}) {
|
|
|
3601
3491
|
};
|
|
3602
3492
|
const onData = (chunk) => {
|
|
3603
3493
|
buffer += chunk.toString("latin1");
|
|
3604
|
-
const parsed =
|
|
3494
|
+
const parsed = parseOsc11Background(buffer);
|
|
3605
3495
|
if (parsed) finish(parsed);
|
|
3606
3496
|
else if (buffer.length > 256) finish(null);
|
|
3607
3497
|
};
|
|
@@ -3945,7 +3835,7 @@ function buildHistoryLines(history, contentWidth) {
|
|
|
3945
3835
|
const reset = "\x1B[39m";
|
|
3946
3836
|
return `${accent}\u276F${reset} ${content}`;
|
|
3947
3837
|
}
|
|
3948
|
-
const highlighted =
|
|
3838
|
+
const highlighted = colorEnabled ? formatAssistantDisplay(content) : stripAnsi(formatAssistantDisplay(content));
|
|
3949
3839
|
const rawLines = highlighted.split("\n");
|
|
3950
3840
|
const styledLines = rawLines.map((line, idx) => {
|
|
3951
3841
|
if (idx === 0 && !line.startsWith("[nolo]")) {
|
|
@@ -4072,6 +3962,30 @@ function applyScrollAction(history, action, output, inputLines) {
|
|
|
4072
3962
|
}
|
|
4073
3963
|
|
|
4074
3964
|
// packages/cli/tui/tuiRawInput.ts
|
|
3965
|
+
function normalizePasteNewlines(text) {
|
|
3966
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3967
|
+
}
|
|
3968
|
+
var altScreenOn = /* @__PURE__ */ new WeakMap();
|
|
3969
|
+
function outputIsTty2(output) {
|
|
3970
|
+
return Boolean(output.isTTY);
|
|
3971
|
+
}
|
|
3972
|
+
function enterAltScreen(output) {
|
|
3973
|
+
if (!outputIsTty2(output)) return false;
|
|
3974
|
+
if (altScreenOn.get(output)) return false;
|
|
3975
|
+
altScreenOn.set(output, true);
|
|
3976
|
+
output.write("\x1B[?1049h");
|
|
3977
|
+
return true;
|
|
3978
|
+
}
|
|
3979
|
+
function leaveAltScreen(output) {
|
|
3980
|
+
if (!outputIsTty2(output)) return false;
|
|
3981
|
+
if (!altScreenOn.get(output)) return false;
|
|
3982
|
+
altScreenOn.set(output, false);
|
|
3983
|
+
output.write("\x1B[?1049l");
|
|
3984
|
+
return true;
|
|
3985
|
+
}
|
|
3986
|
+
function isAltScreenOn(output) {
|
|
3987
|
+
return Boolean(altScreenOn.get(output));
|
|
3988
|
+
}
|
|
4075
3989
|
function styleCollapsedPastePlaceholders(text, colorEnabled) {
|
|
4076
3990
|
if (!colorEnabled || !text.includes("[paste #")) return text;
|
|
4077
3991
|
COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
|
|
@@ -4102,6 +4016,8 @@ function createNoopFixedInput() {
|
|
|
4102
4016
|
getInputLines: () => 1,
|
|
4103
4017
|
isPaused: () => false,
|
|
4104
4018
|
setMouseEnabled() {
|
|
4019
|
+
},
|
|
4020
|
+
setAltScreenEnabled() {
|
|
4105
4021
|
}
|
|
4106
4022
|
};
|
|
4107
4023
|
}
|
|
@@ -4145,7 +4061,7 @@ function createFixedInput(output, config) {
|
|
|
4145
4061
|
sections.push(fitAnsiLine(line.replace(/\r?\n/g, " "), cols));
|
|
4146
4062
|
}
|
|
4147
4063
|
const promptRaw = t("promptLabel");
|
|
4148
|
-
const promptWidth =
|
|
4064
|
+
const promptWidth = displayWidth(promptRaw);
|
|
4149
4065
|
const prompt = colorEnabled ? `${themeColorSequence("accent")}${promptRaw}\x1B[39m` : promptRaw;
|
|
4150
4066
|
const contentWidth = Math.max(1, cols - promptWidth);
|
|
4151
4067
|
const logicalLines = buffer.length === 0 ? [""] : buffer.split("\n");
|
|
@@ -4181,7 +4097,7 @@ function createFixedInput(output, config) {
|
|
|
4181
4097
|
if (targetPos <= charOffset + rowLen || j === rows.length - 1 && i === logicalLines.length - 1) {
|
|
4182
4098
|
const subOffset = Math.max(0, Math.min(rowLen, targetPos - charOffset));
|
|
4183
4099
|
const subStr = rowText.slice(0, subOffset);
|
|
4184
|
-
cursorCol = promptWidth +
|
|
4100
|
+
cursorCol = promptWidth + displayWidth(subStr);
|
|
4185
4101
|
cursorRow = inputRows;
|
|
4186
4102
|
cursorFound = true;
|
|
4187
4103
|
}
|
|
@@ -4198,10 +4114,15 @@ function createFixedInput(output, config) {
|
|
|
4198
4114
|
};
|
|
4199
4115
|
const repaintAt = (buffer, cursorPos) => {
|
|
4200
4116
|
const { text, lines, cursorCol, cursorRow } = renderInputArea(buffer, cursorPos);
|
|
4117
|
+
let linesChanged = false;
|
|
4201
4118
|
if (lines !== inputLines) {
|
|
4202
4119
|
inputLines = lines;
|
|
4120
|
+
linesChanged = true;
|
|
4203
4121
|
}
|
|
4204
4122
|
setScrollRegion(inputLines);
|
|
4123
|
+
if (linesChanged) {
|
|
4124
|
+
config.onInputLinesChange?.(inputLines);
|
|
4125
|
+
}
|
|
4205
4126
|
const startRow = getRows() - inputLines + 1;
|
|
4206
4127
|
write(`\x1B[${startRow};1H`);
|
|
4207
4128
|
write("\x1B[J");
|
|
@@ -4249,8 +4170,7 @@ function createFixedInput(output, config) {
|
|
|
4249
4170
|
disable() {
|
|
4250
4171
|
disableMouse();
|
|
4251
4172
|
resetScrollRegion();
|
|
4252
|
-
|
|
4253
|
-
write(`\x1B[${rows};1H\x1B[2K\x1B[${Math.max(1, rows - 1)};1H`);
|
|
4173
|
+
leaveAltScreen(output);
|
|
4254
4174
|
},
|
|
4255
4175
|
getInputLines: () => inputLines,
|
|
4256
4176
|
isPaused: () => paused,
|
|
@@ -4261,6 +4181,13 @@ function createFixedInput(output, config) {
|
|
|
4261
4181
|
} else {
|
|
4262
4182
|
write("\x1B[?1000l\x1B[?1006l");
|
|
4263
4183
|
}
|
|
4184
|
+
},
|
|
4185
|
+
setAltScreenEnabled(enabled) {
|
|
4186
|
+
if (enabled) {
|
|
4187
|
+
enterAltScreen(output);
|
|
4188
|
+
} else {
|
|
4189
|
+
leaveAltScreen(output);
|
|
4190
|
+
}
|
|
4264
4191
|
}
|
|
4265
4192
|
};
|
|
4266
4193
|
}
|
|
@@ -4310,9 +4237,27 @@ function isIncompleteTail(input, start) {
|
|
|
4310
4237
|
}
|
|
4311
4238
|
return false;
|
|
4312
4239
|
}
|
|
4313
|
-
var PASTE_START = "\x1B[
|
|
4314
|
-
var PASTE_END = "\x1B[
|
|
4315
|
-
function
|
|
4240
|
+
var PASTE_START = "\x1B[200~";
|
|
4241
|
+
var PASTE_END = "\x1B[201~";
|
|
4242
|
+
function findBracketedPasteEnd(input, contentStart) {
|
|
4243
|
+
return input.indexOf(PASTE_END, contentStart);
|
|
4244
|
+
}
|
|
4245
|
+
function emitPlainRunAsTokens(run) {
|
|
4246
|
+
if (run.length === 0) return [];
|
|
4247
|
+
if (shouldCollapsePaste(normalizePasteNewlines(run))) {
|
|
4248
|
+
return [`${PASTE_TOKEN_PREFIX}${run}`];
|
|
4249
|
+
}
|
|
4250
|
+
const tokens = [];
|
|
4251
|
+
for (let index = 0; index < run.length; ) {
|
|
4252
|
+
const codePoint = run.codePointAt(index);
|
|
4253
|
+
if (codePoint === void 0) break;
|
|
4254
|
+
const value = String.fromCodePoint(codePoint);
|
|
4255
|
+
tokens.push(value);
|
|
4256
|
+
index += value.length;
|
|
4257
|
+
}
|
|
4258
|
+
return tokens;
|
|
4259
|
+
}
|
|
4260
|
+
function splitRawInputWithTail(input, options) {
|
|
4316
4261
|
const tokens = [];
|
|
4317
4262
|
for (let index = 0; index < input.length; ) {
|
|
4318
4263
|
if (isIncompleteTail(input, index)) {
|
|
@@ -4320,15 +4265,17 @@ function splitRawInputWithTail(input) {
|
|
|
4320
4265
|
}
|
|
4321
4266
|
if (input.startsWith(PASTE_START, index)) {
|
|
4322
4267
|
const contentStart = index + PASTE_START.length;
|
|
4323
|
-
const endPos = input
|
|
4268
|
+
const endPos = findBracketedPasteEnd(input, contentStart);
|
|
4324
4269
|
if (endPos !== -1) {
|
|
4325
4270
|
const payload = input.slice(contentStart, endPos);
|
|
4326
4271
|
tokens.push(`${PASTE_TOKEN_PREFIX}${payload}`);
|
|
4327
4272
|
index = endPos + PASTE_END.length;
|
|
4328
|
-
} else {
|
|
4273
|
+
} else if (options?.forceCompleteOpenPaste) {
|
|
4329
4274
|
const payload = input.slice(contentStart);
|
|
4330
4275
|
tokens.push(`${PASTE_TOKEN_PREFIX}${payload}`);
|
|
4331
4276
|
index = input.length;
|
|
4277
|
+
} else {
|
|
4278
|
+
return { tokens, tail: input.slice(index) };
|
|
4332
4279
|
}
|
|
4333
4280
|
continue;
|
|
4334
4281
|
}
|
|
@@ -4353,63 +4300,121 @@ function splitRawInputWithTail(input) {
|
|
|
4353
4300
|
index += csi.length;
|
|
4354
4301
|
continue;
|
|
4355
4302
|
}
|
|
4356
|
-
const
|
|
4357
|
-
|
|
4358
|
-
const
|
|
4359
|
-
|
|
4360
|
-
|
|
4303
|
+
const nextEsc = input.indexOf("\x1B", index);
|
|
4304
|
+
const runEnd = nextEsc === -1 ? input.length : nextEsc;
|
|
4305
|
+
const run = input.slice(index, runEnd);
|
|
4306
|
+
if (run.length === 0) {
|
|
4307
|
+
const codePoint = input.codePointAt(index);
|
|
4308
|
+
if (codePoint === void 0) break;
|
|
4309
|
+
const value = String.fromCodePoint(codePoint);
|
|
4310
|
+
tokens.push(value);
|
|
4311
|
+
index += value.length;
|
|
4312
|
+
continue;
|
|
4313
|
+
}
|
|
4314
|
+
tokens.push(...emitPlainRunAsTokens(run));
|
|
4315
|
+
index = runEnd;
|
|
4361
4316
|
}
|
|
4362
4317
|
return { tokens, tail: "" };
|
|
4363
4318
|
}
|
|
4364
4319
|
function splitRawInput(input) {
|
|
4365
|
-
const { tokens, tail } = splitRawInputWithTail(input
|
|
4320
|
+
const { tokens, tail } = splitRawInputWithTail(input, {
|
|
4321
|
+
forceCompleteOpenPaste: true
|
|
4322
|
+
});
|
|
4366
4323
|
if (!tail) return tokens;
|
|
4367
|
-
|
|
4368
|
-
for (let index = 0; index < tail.length; ) {
|
|
4369
|
-
const codePoint = tail.codePointAt(index);
|
|
4370
|
-
if (codePoint === void 0) break;
|
|
4371
|
-
const value = String.fromCodePoint(codePoint);
|
|
4372
|
-
tailTokens.push(value);
|
|
4373
|
-
index += value.length;
|
|
4374
|
-
}
|
|
4375
|
-
return [...tokens, ...tailTokens];
|
|
4324
|
+
return [...tokens, ...emitPlainRunAsTokens(tail)];
|
|
4376
4325
|
}
|
|
4377
4326
|
function createRawInputDecoder(onToken, options) {
|
|
4378
4327
|
const decoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
|
|
4379
4328
|
let pendingBuffer = "";
|
|
4380
4329
|
let timer = null;
|
|
4381
4330
|
const timeoutMs = options?.escTimeoutMs ?? 15;
|
|
4331
|
+
const unmarkedPasteDebounceMs = options?.unmarkedPasteDebounceMs ?? 40;
|
|
4382
4332
|
const clearTimer = () => {
|
|
4383
4333
|
if (timer !== null) {
|
|
4384
4334
|
clearTimeout(timer);
|
|
4385
4335
|
timer = null;
|
|
4386
4336
|
}
|
|
4387
4337
|
};
|
|
4388
|
-
const
|
|
4338
|
+
const emitCodePoints = (text) => {
|
|
4339
|
+
for (let index = 0; index < text.length; ) {
|
|
4340
|
+
const codePoint = text.codePointAt(index);
|
|
4341
|
+
if (codePoint === void 0) break;
|
|
4342
|
+
const value = String.fromCodePoint(codePoint);
|
|
4343
|
+
onToken(value);
|
|
4344
|
+
index += value.length;
|
|
4345
|
+
}
|
|
4346
|
+
};
|
|
4347
|
+
const flushPlainPending = () => {
|
|
4389
4348
|
clearTimer();
|
|
4390
|
-
if (pendingBuffer.length
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
}
|
|
4349
|
+
if (pendingBuffer.length === 0) return;
|
|
4350
|
+
const text = pendingBuffer;
|
|
4351
|
+
pendingBuffer = "";
|
|
4352
|
+
for (const token of emitPlainRunAsTokens(text)) {
|
|
4353
|
+
onToken(token);
|
|
4396
4354
|
}
|
|
4397
4355
|
};
|
|
4356
|
+
const flushEscPending = (forceCompleteOpenPaste) => {
|
|
4357
|
+
clearTimer();
|
|
4358
|
+
if (pendingBuffer.length === 0) return;
|
|
4359
|
+
const textToFlush = pendingBuffer;
|
|
4360
|
+
pendingBuffer = "";
|
|
4361
|
+
const { tokens, tail } = splitRawInputWithTail(textToFlush, {
|
|
4362
|
+
forceCompleteOpenPaste
|
|
4363
|
+
});
|
|
4364
|
+
for (const token of tokens) {
|
|
4365
|
+
onToken(token);
|
|
4366
|
+
}
|
|
4367
|
+
if (!tail) return;
|
|
4368
|
+
if (forceCompleteOpenPaste) {
|
|
4369
|
+
emitCodePoints(tail);
|
|
4370
|
+
return;
|
|
4371
|
+
}
|
|
4372
|
+
pendingBuffer = tail;
|
|
4373
|
+
};
|
|
4398
4374
|
const decodeFn = (chunk) => {
|
|
4399
4375
|
clearTimer();
|
|
4400
4376
|
const bytes = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
4401
4377
|
const text = decoder.decode(bytes, { stream: true });
|
|
4402
4378
|
pendingBuffer += text;
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4379
|
+
if (pendingBuffer.startsWith(PASTE_START)) {
|
|
4380
|
+
const endPos = findBracketedPasteEnd(
|
|
4381
|
+
pendingBuffer,
|
|
4382
|
+
PASTE_START.length
|
|
4383
|
+
);
|
|
4384
|
+
if (endPos === -1) return;
|
|
4385
|
+
const { tokens, tail } = splitRawInputWithTail(pendingBuffer);
|
|
4386
|
+
pendingBuffer = tail;
|
|
4387
|
+
for (const token of tokens) onToken(token);
|
|
4388
|
+
if (pendingBuffer.startsWith(PASTE_START)) return;
|
|
4389
|
+
}
|
|
4390
|
+
if (pendingBuffer.includes("\x1B")) {
|
|
4391
|
+
const { tokens, tail } = splitRawInputWithTail(pendingBuffer);
|
|
4392
|
+
pendingBuffer = tail;
|
|
4393
|
+
for (const token of tokens) onToken(token);
|
|
4394
|
+
if (pendingBuffer.startsWith(PASTE_START)) return;
|
|
4395
|
+
if (pendingBuffer.length > 0) {
|
|
4396
|
+
timer = setTimeout(() => flushEscPending(true), timeoutMs);
|
|
4397
|
+
}
|
|
4398
|
+
return;
|
|
4399
|
+
}
|
|
4400
|
+
if (shouldCollapsePaste(normalizePasteNewlines(pendingBuffer))) {
|
|
4401
|
+
timer = setTimeout(flushPlainPending, unmarkedPasteDebounceMs);
|
|
4402
|
+
return;
|
|
4403
|
+
}
|
|
4404
|
+
if (!pendingBuffer.includes("\n") && !pendingBuffer.includes("\r")) {
|
|
4405
|
+
emitCodePoints(pendingBuffer);
|
|
4406
|
+
pendingBuffer = "";
|
|
4407
|
+
return;
|
|
4407
4408
|
}
|
|
4408
|
-
|
|
4409
|
-
|
|
4409
|
+
timer = setTimeout(flushPlainPending, unmarkedPasteDebounceMs);
|
|
4410
|
+
};
|
|
4411
|
+
decodeFn.flush = () => {
|
|
4412
|
+
if (pendingBuffer.startsWith(PASTE_START) || pendingBuffer.includes("\x1B")) {
|
|
4413
|
+
flushEscPending(true);
|
|
4414
|
+
return;
|
|
4410
4415
|
}
|
|
4416
|
+
flushPlainPending();
|
|
4411
4417
|
};
|
|
4412
|
-
decodeFn.flush = flush;
|
|
4413
4418
|
decodeFn.destroy = () => {
|
|
4414
4419
|
clearTimer();
|
|
4415
4420
|
pendingBuffer = "";
|
|
@@ -4419,12 +4424,66 @@ function createRawInputDecoder(onToken, options) {
|
|
|
4419
4424
|
|
|
4420
4425
|
// packages/cli/tui/readlineWorkspace.ts
|
|
4421
4426
|
var AGENTS_MD_MAX_BYTES = 8192;
|
|
4427
|
+
var altScreenRestoreOutput = null;
|
|
4428
|
+
var altScreenHandlersInstalled = false;
|
|
4429
|
+
var preExistingSignalListeners = {};
|
|
4430
|
+
var SIGNAL_EXIT_CODE = {
|
|
4431
|
+
SIGINT: 130,
|
|
4432
|
+
SIGTERM: 143,
|
|
4433
|
+
SIGHUP: 129
|
|
4434
|
+
};
|
|
4435
|
+
var restoreAltScreen = () => {
|
|
4436
|
+
try {
|
|
4437
|
+
if (altScreenRestoreOutput) leaveAltScreen(altScreenRestoreOutput);
|
|
4438
|
+
} catch {
|
|
4439
|
+
}
|
|
4440
|
+
};
|
|
4441
|
+
function installAltScreenRestoreHandlers(output) {
|
|
4442
|
+
altScreenRestoreOutput = output;
|
|
4443
|
+
if (altScreenHandlersInstalled) return;
|
|
4444
|
+
altScreenHandlersInstalled = true;
|
|
4445
|
+
process.on("exit", restoreAltScreen);
|
|
4446
|
+
for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
4447
|
+
const existing = process.listeners(sig);
|
|
4448
|
+
preExistingSignalListeners[sig] = [...existing];
|
|
4449
|
+
const handler = () => {
|
|
4450
|
+
restoreAltScreen();
|
|
4451
|
+
const others = process.listeners(sig).filter((fn) => fn !== handler);
|
|
4452
|
+
if (others.length === 0) {
|
|
4453
|
+
process.exit(SIGNAL_EXIT_CODE[sig] ?? 128 + 1);
|
|
4454
|
+
return;
|
|
4455
|
+
}
|
|
4456
|
+
};
|
|
4457
|
+
process.prependListener(sig, handler);
|
|
4458
|
+
}
|
|
4459
|
+
process.on("uncaughtException", (err) => {
|
|
4460
|
+
restoreAltScreen();
|
|
4461
|
+
try {
|
|
4462
|
+
process.stderr.write(
|
|
4463
|
+
`uncaughtException: ${err?.stack ?? String(err)}
|
|
4464
|
+
`
|
|
4465
|
+
);
|
|
4466
|
+
} catch {
|
|
4467
|
+
}
|
|
4468
|
+
process.exit(1);
|
|
4469
|
+
});
|
|
4470
|
+
process.on("unhandledRejection", (reason) => {
|
|
4471
|
+
restoreAltScreen();
|
|
4472
|
+
try {
|
|
4473
|
+
const text = reason instanceof Error ? reason.stack ?? String(reason) : String(reason);
|
|
4474
|
+
process.stderr.write(`unhandledRejection: ${text}
|
|
4475
|
+
`);
|
|
4476
|
+
} catch {
|
|
4477
|
+
}
|
|
4478
|
+
process.exit(1);
|
|
4479
|
+
});
|
|
4480
|
+
}
|
|
4422
4481
|
function readAgentsMdBlock(cwd) {
|
|
4423
4482
|
for (const name of ["AGENTS.md", "CLAUDE.md"]) {
|
|
4424
|
-
const filePath =
|
|
4425
|
-
if (
|
|
4483
|
+
const filePath = join2(cwd, name);
|
|
4484
|
+
if (existsSync3(filePath)) {
|
|
4426
4485
|
try {
|
|
4427
|
-
let content =
|
|
4486
|
+
let content = readFileSync2(filePath, "utf8").trim();
|
|
4428
4487
|
if (!content) continue;
|
|
4429
4488
|
if (Buffer.byteLength(content, "utf8") > AGENTS_MD_MAX_BYTES) {
|
|
4430
4489
|
content = Buffer.from(content, "utf8").subarray(0, AGENTS_MD_MAX_BYTES).toString("utf8") + "\n\n<!-- AGENTS.md truncated -->";
|
|
@@ -4448,10 +4507,14 @@ async function runAgentChat(scriptDir, state, message, env, output, agentRunner
|
|
|
4448
4507
|
effectiveAgentName = cachedRoute.agentName;
|
|
4449
4508
|
} else if (!continueId && env.NOLO_AUTO_ROUTE !== "0" && state.agentKey === DEFAULT_TUI_AGENT_KEY) {
|
|
4450
4509
|
const authToken = env.AUTH_TOKEN ?? env.AUTH ?? env.BENCHMARK_AUTH_TOKEN ?? "";
|
|
4451
|
-
const route = await classifyCliAutoRoute(message, {
|
|
4510
|
+
const route = authToken ? await classifyCliAutoRoute(message, {
|
|
4452
4511
|
serverUrl: state.serverUrl,
|
|
4453
4512
|
authToken
|
|
4454
|
-
})
|
|
4513
|
+
}) : {
|
|
4514
|
+
agentKey: CLI_AUTO_TIER_AGENT_KEYS[resolveCliAutoFallbackTier(message)],
|
|
4515
|
+
tier: resolveCliAutoFallbackTier(message),
|
|
4516
|
+
classified: false
|
|
4517
|
+
};
|
|
4455
4518
|
effectiveAgentKey = route.agentKey;
|
|
4456
4519
|
effectiveAgentName = `auto\u2192${route.tier}`;
|
|
4457
4520
|
if (effectiveAgentKey !== state.agentKey) {
|
|
@@ -4539,6 +4602,18 @@ async function runAgentChat(scriptDir, state, message, env, output, agentRunner
|
|
|
4539
4602
|
if (skillDiscoveryBlock) {
|
|
4540
4603
|
extraContextBlocks.push(skillDiscoveryBlock);
|
|
4541
4604
|
}
|
|
4605
|
+
const agentsMdMarker = "--- \u9879\u76EE\u6307\u4EE4\uFF08";
|
|
4606
|
+
const contextBlockScopes = [];
|
|
4607
|
+
for (const block of extraContextBlocks) {
|
|
4608
|
+
if (block.startsWith(agentsMdMarker)) {
|
|
4609
|
+
contextBlockScopes.push({ content: block, cacheScope: "session" });
|
|
4610
|
+
}
|
|
4611
|
+
}
|
|
4612
|
+
for (const block of extraContextBlocks) {
|
|
4613
|
+
if (!block.startsWith(agentsMdMarker)) {
|
|
4614
|
+
contextBlockScopes.push({ content: block, cacheScope: "turn" });
|
|
4615
|
+
}
|
|
4616
|
+
}
|
|
4542
4617
|
const result = await agentRunner({
|
|
4543
4618
|
agentName: effectiveAgentName,
|
|
4544
4619
|
agentKey: effectiveAgentKey,
|
|
@@ -4559,9 +4634,17 @@ async function runAgentChat(scriptDir, state, message, env, output, agentRunner
|
|
|
4559
4634
|
...options.confirmDestructiveAction ? { confirmDestructiveAction: options.confirmDestructiveAction } : {},
|
|
4560
4635
|
...options.requestUserChoice ? { requestUserChoice: options.requestUserChoice } : {},
|
|
4561
4636
|
...options.abortSignal ? { abortSignal: options.abortSignal } : {},
|
|
4637
|
+
...options.pastedTextStore?.items.size ? {
|
|
4638
|
+
pastedTextStore: options.pastedTextStore,
|
|
4639
|
+
localRuntimeAdapterFactory: (factoryEnv, factoryOptions) => createCliLocalRuntimeAdapter({
|
|
4640
|
+
env: factoryEnv,
|
|
4641
|
+
cwd: factoryOptions?.cwd ?? state.cwd,
|
|
4642
|
+
pastedTextStore: options.pastedTextStore
|
|
4643
|
+
})
|
|
4644
|
+
} : {},
|
|
4562
4645
|
...options.activityReporter ? { activityReporter: options.activityReporter } : {},
|
|
4563
4646
|
...skillAllowedTools !== void 0 ? { allowedToolNames: skillAllowedTools } : {},
|
|
4564
|
-
...
|
|
4647
|
+
...contextBlockScopes.length > 0 ? { contextBlockScopes } : {}
|
|
4565
4648
|
});
|
|
4566
4649
|
if (!continueId && result.dialogId && effectiveAgentKey !== state.agentKey) {
|
|
4567
4650
|
autoRouteByDialog.set(result.dialogId, {
|
|
@@ -4569,7 +4652,14 @@ async function runAgentChat(scriptDir, state, message, env, output, agentRunner
|
|
|
4569
4652
|
agentName: effectiveAgentName
|
|
4570
4653
|
});
|
|
4571
4654
|
}
|
|
4572
|
-
return
|
|
4655
|
+
return {
|
|
4656
|
+
...result,
|
|
4657
|
+
contextWindow: resolveAgentContextWindow({
|
|
4658
|
+
agentKey: effectiveAgentKey,
|
|
4659
|
+
agentName: effectiveAgentName,
|
|
4660
|
+
autoRouteDefault: env.NOLO_AUTO_ROUTE !== "0"
|
|
4661
|
+
})
|
|
4662
|
+
};
|
|
4573
4663
|
}
|
|
4574
4664
|
function waitForActionGate(rl, input, output, gate, spawnRunner) {
|
|
4575
4665
|
const commandPayload = gate.kind === "handoff" ? readCommandActionGatePayload(gate.payload) : null;
|
|
@@ -4681,7 +4771,12 @@ function waitForRawActionGate(input, output, gate, spawnRunner, hooks) {
|
|
|
4681
4771
|
output.write("[nolo] Press Enter to run it now. Follow any prompts below, or Ctrl+C to cancel.\n");
|
|
4682
4772
|
return new Promise((resolve2) => {
|
|
4683
4773
|
const rawInput = input;
|
|
4774
|
+
let settled = false;
|
|
4775
|
+
let commandRunning = false;
|
|
4684
4776
|
const finish = (result) => {
|
|
4777
|
+
if (settled) return;
|
|
4778
|
+
settled = true;
|
|
4779
|
+
hooks?.registerToken?.(null);
|
|
4685
4780
|
input.off("data", onData);
|
|
4686
4781
|
resolve2(result);
|
|
4687
4782
|
};
|
|
@@ -4699,13 +4794,9 @@ function waitForRawActionGate(input, output, gate, spawnRunner, hooks) {
|
|
|
4699
4794
|
actionGateResult: { gateId: gate.id, status: "failed", output: message }
|
|
4700
4795
|
}
|
|
4701
4796
|
});
|
|
4702
|
-
const
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
cancel("interrupted");
|
|
4706
|
-
return;
|
|
4707
|
-
}
|
|
4708
|
-
if (!text.includes("\r") && !text.includes("\n")) return;
|
|
4797
|
+
const runCommand = async () => {
|
|
4798
|
+
if (settled || commandRunning) return;
|
|
4799
|
+
commandRunning = true;
|
|
4709
4800
|
if (!commandPayload) {
|
|
4710
4801
|
fail("unsupported gate payload");
|
|
4711
4802
|
return;
|
|
@@ -4743,7 +4834,25 @@ function waitForRawActionGate(input, output, gate, spawnRunner, hooks) {
|
|
|
4743
4834
|
}
|
|
4744
4835
|
});
|
|
4745
4836
|
};
|
|
4746
|
-
|
|
4837
|
+
const handleToken = (text) => {
|
|
4838
|
+
if (settled || commandRunning) return;
|
|
4839
|
+
if (text.includes("")) {
|
|
4840
|
+
cancel("interrupted");
|
|
4841
|
+
return;
|
|
4842
|
+
}
|
|
4843
|
+
if (text.includes("\r") || text.includes("\n")) {
|
|
4844
|
+
void runCommand();
|
|
4845
|
+
}
|
|
4846
|
+
};
|
|
4847
|
+
const onData = (chunk) => {
|
|
4848
|
+
const text = String(chunk);
|
|
4849
|
+
handleToken(text);
|
|
4850
|
+
};
|
|
4851
|
+
if (hooks?.registerToken) {
|
|
4852
|
+
hooks.registerToken(handleToken);
|
|
4853
|
+
} else {
|
|
4854
|
+
input.on("data", onData);
|
|
4855
|
+
}
|
|
4747
4856
|
});
|
|
4748
4857
|
}
|
|
4749
4858
|
async function startTuiWorkspace(options) {
|
|
@@ -4755,13 +4864,18 @@ async function startTuiWorkspace(options) {
|
|
|
4755
4864
|
const spawnRunner = options.spawnRunner ?? spawnProcess;
|
|
4756
4865
|
const selfUpdater = options.selfUpdater ?? ((target) => runSelfUpdate({ output: target }));
|
|
4757
4866
|
if (output.isTTY) {
|
|
4758
|
-
output
|
|
4867
|
+
enterAltScreen(output);
|
|
4868
|
+
installAltScreenRestoreHandlers(output);
|
|
4869
|
+
output.write("\x1B[2J\x1B[H");
|
|
4759
4870
|
}
|
|
4760
|
-
const detected = await
|
|
4871
|
+
const detected = await detectTerminalBackground({
|
|
4761
4872
|
stdin: input,
|
|
4762
4873
|
stdout: output
|
|
4763
4874
|
});
|
|
4764
|
-
if (detected)
|
|
4875
|
+
if (detected) {
|
|
4876
|
+
setActiveBrightness(detected.brightness);
|
|
4877
|
+
setActiveTerminalBaseHex(detected.hex);
|
|
4878
|
+
}
|
|
4765
4879
|
const bannerColumns = output.columns;
|
|
4766
4880
|
output.write(renderWelcome(state, 0, 0, bannerColumns));
|
|
4767
4881
|
let fixedInput = createNoopFixedInput();
|
|
@@ -4769,9 +4883,14 @@ async function startTuiWorkspace(options) {
|
|
|
4769
4883
|
let cursorPos = 0;
|
|
4770
4884
|
const pasteStore = createCollapsedPasteStore();
|
|
4771
4885
|
let activeTurnAbort = null;
|
|
4886
|
+
let forcedStop = false;
|
|
4887
|
+
let forcedStopEpoch = 0;
|
|
4888
|
+
let turnEpoch = 0;
|
|
4889
|
+
let activeTurnEpoch = 0;
|
|
4772
4890
|
const activityIndicator = createActivityIndicator({
|
|
4773
4891
|
isTurnActive: () => activeTurnAbort !== null,
|
|
4774
4892
|
fallbackLabel: () => `${state.agentName} -> working`,
|
|
4893
|
+
stoppingLabel: () => t("turnStopping"),
|
|
4775
4894
|
onRepaint: () => {
|
|
4776
4895
|
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
4777
4896
|
output.write("\x1B[?2026h\x1B[?25l");
|
|
@@ -4831,9 +4950,16 @@ async function startTuiWorkspace(options) {
|
|
|
4831
4950
|
paintSyncedFrame();
|
|
4832
4951
|
}, 0);
|
|
4833
4952
|
};
|
|
4953
|
+
let syncingLayout = false;
|
|
4834
4954
|
const renderHistoryToOutput = () => {
|
|
4835
4955
|
if (fixedInput.isPaused()) return;
|
|
4836
|
-
|
|
4956
|
+
if (syncingLayout) return;
|
|
4957
|
+
syncingLayout = true;
|
|
4958
|
+
try {
|
|
4959
|
+
renderHistory(output, history, fixedInput.getInputLines());
|
|
4960
|
+
} finally {
|
|
4961
|
+
syncingLayout = false;
|
|
4962
|
+
}
|
|
4837
4963
|
};
|
|
4838
4964
|
const readLatestAssistantReply = () => {
|
|
4839
4965
|
const lastReply = [...history.turns].reverse().find((turn) => turn.role === "assistant")?.content;
|
|
@@ -4871,7 +4997,11 @@ ${t("copyViewHint")}
|
|
|
4871
4997
|
return true;
|
|
4872
4998
|
};
|
|
4873
4999
|
let modalOwnsKeyboard = false;
|
|
5000
|
+
let rawActionGateTokenHandler = null;
|
|
4874
5001
|
const runOneAgentTurn = async (message, imageUrls, actionGateHandler, confirmDestructiveAction) => {
|
|
5002
|
+
forcedStop = false;
|
|
5003
|
+
turnEpoch += 1;
|
|
5004
|
+
const myEpoch = turnEpoch;
|
|
4875
5005
|
history.followBottom = true;
|
|
4876
5006
|
startTurn(history, "user");
|
|
4877
5007
|
appendToCurrentTurn(history, message);
|
|
@@ -4901,6 +5031,7 @@ ${t("copyViewHint")}
|
|
|
4901
5031
|
} : void 0;
|
|
4902
5032
|
try {
|
|
4903
5033
|
activeTurnAbort = new AbortController();
|
|
5034
|
+
activeTurnEpoch = myEpoch;
|
|
4904
5035
|
const runResult = await runAgentChat(
|
|
4905
5036
|
options.scriptDir,
|
|
4906
5037
|
state,
|
|
@@ -4914,10 +5045,27 @@ ${t("copyViewHint")}
|
|
|
4914
5045
|
...confirmDestructiveAction ? { confirmDestructiveAction } : {},
|
|
4915
5046
|
...requestUserChoice ? { requestUserChoice } : {},
|
|
4916
5047
|
abortSignal: activeTurnAbort.signal,
|
|
5048
|
+
pastedTextStore: pasteStore,
|
|
4917
5049
|
explicitAgentSwitch,
|
|
4918
5050
|
activityReporter
|
|
4919
5051
|
}
|
|
4920
5052
|
);
|
|
5053
|
+
const wasForceStopped = forcedStopEpoch === myEpoch;
|
|
5054
|
+
if (wasForceStopped) {
|
|
5055
|
+
if (runResult.dialogId || runResult.turnTokens) {
|
|
5056
|
+
const nextDialogKey = runResult.dialogId ? runResult.dialogId === state.dialogId && state.dialogKey ? state.dialogKey : state.dialogOwnerId ? `dialog-${state.dialogOwnerId}-${runResult.dialogId}` : void 0 : state.dialogKey;
|
|
5057
|
+
state = {
|
|
5058
|
+
...state,
|
|
5059
|
+
...runResult.dialogId ? {
|
|
5060
|
+
dialogId: runResult.dialogId,
|
|
5061
|
+
dialogKey: nextDialogKey,
|
|
5062
|
+
dialogLabel: runResult.dialogId
|
|
5063
|
+
} : {},
|
|
5064
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {}
|
|
5065
|
+
};
|
|
5066
|
+
}
|
|
5067
|
+
return { ok: false, aborted: true };
|
|
5068
|
+
}
|
|
4921
5069
|
const wasAborted = activeTurnAbort.signal.aborted;
|
|
4922
5070
|
activeTurnAbort = null;
|
|
4923
5071
|
explicitAgentSwitch = false;
|
|
@@ -4928,9 +5076,13 @@ ${t("copyViewHint")}
|
|
|
4928
5076
|
if (fixedInput.active) fixedInput.repaint(buffer);
|
|
4929
5077
|
}
|
|
4930
5078
|
if (wasAborted) {
|
|
4931
|
-
|
|
5079
|
+
if (runResult.pendingToolName) {
|
|
5080
|
+
emitCommandOutput(t("turnStoppedToolPending", runResult.pendingToolName));
|
|
5081
|
+
} else {
|
|
5082
|
+
emitCommandOutput(t("turnStopped"));
|
|
5083
|
+
}
|
|
4932
5084
|
}
|
|
4933
|
-
if (runResult.dialogId || runResult.turnTokens) {
|
|
5085
|
+
if (runResult.dialogId || runResult.turnTokens || runResult.contextWindow) {
|
|
4934
5086
|
const nextDialogKey = runResult.dialogId ? runResult.dialogId === state.dialogId && state.dialogKey ? state.dialogKey : state.dialogOwnerId ? `dialog-${state.dialogOwnerId}-${runResult.dialogId}` : void 0 : state.dialogKey;
|
|
4935
5087
|
state = {
|
|
4936
5088
|
...state,
|
|
@@ -4939,11 +5091,20 @@ ${t("copyViewHint")}
|
|
|
4939
5091
|
dialogKey: nextDialogKey,
|
|
4940
5092
|
dialogLabel: runResult.dialogId
|
|
4941
5093
|
} : {},
|
|
4942
|
-
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {}
|
|
5094
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {},
|
|
5095
|
+
...runResult.contextWindow ? { contextWindow: runResult.contextWindow } : {}
|
|
4943
5096
|
};
|
|
4944
5097
|
}
|
|
4945
|
-
if (!wasAborted && runResult.exitCode !== 0
|
|
4946
|
-
|
|
5098
|
+
if (!wasAborted && runResult.exitCode !== 0) {
|
|
5099
|
+
if (isBalanceExhaustedError(runResult.localError) && runResult.dialogId) {
|
|
5100
|
+
emitCommandOutput(t("balanceExhaustedHint"));
|
|
5101
|
+
} else if (isQuotaExhaustedError(runResult.localError)) {
|
|
5102
|
+
emitCommandOutput(t("quotaExhaustedHint"));
|
|
5103
|
+
} else if (runResult.dialogId) {
|
|
5104
|
+
emitCommandOutput(t("dialogPreservedHint"));
|
|
5105
|
+
} else {
|
|
5106
|
+
emitCommandOutput(t("dialogNotSavedHint"));
|
|
5107
|
+
}
|
|
4947
5108
|
}
|
|
4948
5109
|
return { ok: !wasAborted, aborted: wasAborted };
|
|
4949
5110
|
} finally {
|
|
@@ -4998,6 +5159,7 @@ ${t("copyViewHint")}
|
|
|
4998
5159
|
}
|
|
4999
5160
|
if (result.action?.type === "exit") return true;
|
|
5000
5161
|
if (result.action?.type === "clear") {
|
|
5162
|
+
clearCollapsedPasteStore(pasteStore);
|
|
5001
5163
|
history.turns.length = 0;
|
|
5002
5164
|
history.currentRole = null;
|
|
5003
5165
|
history.currentContent = "";
|
|
@@ -5068,7 +5230,19 @@ ${t("copyViewHint")}
|
|
|
5068
5230
|
...state,
|
|
5069
5231
|
agentName: pickResult.name,
|
|
5070
5232
|
agentKey: pickResult.key,
|
|
5071
|
-
contextWindow:
|
|
5233
|
+
contextWindow: resolveAgentContextWindow({
|
|
5234
|
+
agentKey: pickResult.key,
|
|
5235
|
+
agentName: pickResult.name,
|
|
5236
|
+
model: pickResult.model,
|
|
5237
|
+
autoRouteDefault: (options.env ?? process.env).NOLO_AUTO_ROUTE !== "0"
|
|
5238
|
+
}),
|
|
5239
|
+
estimatedContextTokens: estimateDefaultCliContextTokens({
|
|
5240
|
+
cwd: state.cwd,
|
|
5241
|
+
agentKey: pickResult.key,
|
|
5242
|
+
agentName: pickResult.name,
|
|
5243
|
+
model: pickResult.model
|
|
5244
|
+
}),
|
|
5245
|
+
...pickResult.apiSource ? { apiSource: pickResult.apiSource } : {}
|
|
5072
5246
|
};
|
|
5073
5247
|
if (state.dialogId) autoRouteByDialog.delete(state.dialogId);
|
|
5074
5248
|
explicitAgentSwitch = true;
|
|
@@ -5100,6 +5274,16 @@ ${t("copyViewHint")}
|
|
|
5100
5274
|
if (result.action?.type === "set-mouse") {
|
|
5101
5275
|
fixedInput.setMouseEnabled(result.action.enabled);
|
|
5102
5276
|
}
|
|
5277
|
+
if (result.action?.type === "set-altscreen") {
|
|
5278
|
+
if (result.action.enabled) {
|
|
5279
|
+
enterAltScreen(output);
|
|
5280
|
+
installAltScreenRestoreHandlers(output);
|
|
5281
|
+
} else {
|
|
5282
|
+
leaveAltScreen(output);
|
|
5283
|
+
}
|
|
5284
|
+
renderHistoryToOutput();
|
|
5285
|
+
fixedInput.repaint(buffer);
|
|
5286
|
+
}
|
|
5103
5287
|
if (result.action?.type === "copy-view") {
|
|
5104
5288
|
const opened = await openCopyView();
|
|
5105
5289
|
if (!opened) emitCommandOutput(t("copyNothing"));
|
|
@@ -5143,14 +5327,7 @@ ${t("copyViewHint")}
|
|
|
5143
5327
|
dialog: pickResult.dialog,
|
|
5144
5328
|
env: options.env ?? process.env
|
|
5145
5329
|
});
|
|
5146
|
-
const restored = loadedTurns.slice(-MAX_TUI_HISTORY_TURNS)
|
|
5147
|
-
(turn) => turn.role === "assistant" ? {
|
|
5148
|
-
...turn,
|
|
5149
|
-
content: formatAssistantDisplay(
|
|
5150
|
-
turn.content
|
|
5151
|
-
)
|
|
5152
|
-
} : turn
|
|
5153
|
-
);
|
|
5330
|
+
const restored = loadedTurns.slice(-MAX_TUI_HISTORY_TURNS);
|
|
5154
5331
|
history.turns.length = 0;
|
|
5155
5332
|
history.turns.push(...restored);
|
|
5156
5333
|
history.currentRole = null;
|
|
@@ -5164,6 +5341,7 @@ ${t("copyViewHint")}
|
|
|
5164
5341
|
dialogLabel: pickResult.dialog.id,
|
|
5165
5342
|
turnTokens: void 0
|
|
5166
5343
|
};
|
|
5344
|
+
clearCollapsedPasteStore(pasteStore);
|
|
5167
5345
|
emitCommandOutput(
|
|
5168
5346
|
`${t("resumedDialogPrefix")}: ${pickResult.dialog.title} (${pickResult.dialog.id})`
|
|
5169
5347
|
);
|
|
@@ -5323,6 +5501,9 @@ ${err.message}` : ""}`
|
|
|
5323
5501
|
const oneLine = text.replace(/\r?\n/g, " \u23CE ");
|
|
5324
5502
|
return dimCliText(` \u2937 ${i + 1}. ${oneLine}`, colorEnabled);
|
|
5325
5503
|
});
|
|
5504
|
+
},
|
|
5505
|
+
onInputLinesChange: () => {
|
|
5506
|
+
renderHistoryToOutput();
|
|
5326
5507
|
}
|
|
5327
5508
|
});
|
|
5328
5509
|
fixedInput.init();
|
|
@@ -5345,6 +5526,7 @@ ${err.message}` : ""}`
|
|
|
5345
5526
|
const finish = () => {
|
|
5346
5527
|
if (done) return;
|
|
5347
5528
|
done = true;
|
|
5529
|
+
clearCollapsedPasteStore(pasteStore);
|
|
5348
5530
|
resizeTarget.off?.("resize", onResize);
|
|
5349
5531
|
input.off("data", onData);
|
|
5350
5532
|
onData.destroy();
|
|
@@ -5362,7 +5544,10 @@ ${err.message}` : ""}`
|
|
|
5362
5544
|
}
|
|
5363
5545
|
return;
|
|
5364
5546
|
}
|
|
5365
|
-
if (modalOwnsKeyboard)
|
|
5547
|
+
if (modalOwnsKeyboard) {
|
|
5548
|
+
rawActionGateTokenHandler?.(sequence);
|
|
5549
|
+
return;
|
|
5550
|
+
}
|
|
5366
5551
|
const busyLock = busy;
|
|
5367
5552
|
const scrollAction = parseScrollAction(sequence);
|
|
5368
5553
|
if (scrollAction) {
|
|
@@ -5372,10 +5557,25 @@ ${err.message}` : ""}`
|
|
|
5372
5557
|
return;
|
|
5373
5558
|
}
|
|
5374
5559
|
if (busyLock && sequence === "\x1B" && activeTurnAbort) {
|
|
5560
|
+
if (activityIndicator.isStopping()) {
|
|
5561
|
+
forcedStop = true;
|
|
5562
|
+
forcedStopEpoch = activeTurnEpoch;
|
|
5563
|
+
activityIndicator.stop();
|
|
5564
|
+
activeTurnAbort.abort();
|
|
5565
|
+
activeTurnAbort = null;
|
|
5566
|
+
activeTurnEpoch = 0;
|
|
5567
|
+
busy = false;
|
|
5568
|
+
emitCommandOutput(t("forceStopped"));
|
|
5569
|
+
flushPendingRender();
|
|
5570
|
+
renderHistoryToOutput();
|
|
5571
|
+
if (fixedInput.active) fixedInput.repaint(buffer);
|
|
5572
|
+
return;
|
|
5573
|
+
}
|
|
5375
5574
|
const stopBinding = chatQueueBinding;
|
|
5376
5575
|
if (stopBinding && stopBinding.queueLength() > 0) {
|
|
5377
5576
|
stopBinding.preemptForStop();
|
|
5378
5577
|
}
|
|
5578
|
+
activityIndicator.markStopping();
|
|
5379
5579
|
activeTurnAbort.abort();
|
|
5380
5580
|
return;
|
|
5381
5581
|
}
|
|
@@ -5383,10 +5583,7 @@ ${err.message}` : ""}`
|
|
|
5383
5583
|
pasteStore
|
|
5384
5584
|
});
|
|
5385
5585
|
if (result.copyView) {
|
|
5386
|
-
if (busyLock) return;
|
|
5387
|
-
busy = true;
|
|
5388
5586
|
const opened = await openCopyView();
|
|
5389
|
-
busy = false;
|
|
5390
5587
|
if (!opened) {
|
|
5391
5588
|
history.followBottom = true;
|
|
5392
5589
|
startTurn(history, "assistant");
|
|
@@ -5402,7 +5599,12 @@ ${err.message}` : ""}`
|
|
|
5402
5599
|
return;
|
|
5403
5600
|
}
|
|
5404
5601
|
if (result.submit !== void 0) {
|
|
5405
|
-
const submittedText =
|
|
5602
|
+
const submittedText = replaceCollapsedPastesWithReferences(
|
|
5603
|
+
result.submit,
|
|
5604
|
+
pasteStore
|
|
5605
|
+
);
|
|
5606
|
+
const submittedTrimmed = submittedText.trim();
|
|
5607
|
+
const startsChatTurn = submittedTrimmed.length > 0 && !submittedTrimmed.startsWith("/") && !submittedTrimmed.startsWith("!");
|
|
5406
5608
|
if (busyLock) {
|
|
5407
5609
|
const trimmedText = submittedText.trim();
|
|
5408
5610
|
const busySlashCommand = trimmedText.split(/\s+/)[0]?.toLowerCase();
|
|
@@ -5427,7 +5629,7 @@ ${hint}` : hint;
|
|
|
5427
5629
|
`);
|
|
5428
5630
|
}
|
|
5429
5631
|
}
|
|
5430
|
-
|
|
5632
|
+
releaseCollapsedPasteReferences(submittedText, pasteStore);
|
|
5431
5633
|
buffer = "";
|
|
5432
5634
|
cursorPos2 = 0;
|
|
5433
5635
|
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos2);
|
|
@@ -5439,7 +5641,10 @@ ${hint}` : hint;
|
|
|
5439
5641
|
try {
|
|
5440
5642
|
return await waitForRawActionGate(input, output, gate, spawnRunner, {
|
|
5441
5643
|
beforeSubprocess: () => fixedInput.pause(),
|
|
5442
|
-
afterSubprocess: () => fixedInput.resumeFromSubprocess()
|
|
5644
|
+
afterSubprocess: () => fixedInput.resumeFromSubprocess(),
|
|
5645
|
+
registerToken: (handler) => {
|
|
5646
|
+
rawActionGateTokenHandler = handler;
|
|
5647
|
+
}
|
|
5443
5648
|
});
|
|
5444
5649
|
} finally {
|
|
5445
5650
|
modalOwnsKeyboard = false;
|
|
@@ -5466,7 +5671,6 @@ ${hint}` : hint;
|
|
|
5466
5671
|
isRunning: true
|
|
5467
5672
|
});
|
|
5468
5673
|
if (decision.kind === "queue-text") {
|
|
5469
|
-
clearCollapsedPasteStore(pasteStore);
|
|
5470
5674
|
binding.enqueue(decision.text);
|
|
5471
5675
|
buffer = "";
|
|
5472
5676
|
cursorPos2 = 0;
|
|
@@ -5487,7 +5691,10 @@ ${hint}` : hint;
|
|
|
5487
5691
|
try {
|
|
5488
5692
|
return await waitForRawActionGate(input, output, gate, spawnRunner, {
|
|
5489
5693
|
beforeSubprocess: () => fixedInput.pause(),
|
|
5490
|
-
afterSubprocess: () => fixedInput.resumeFromSubprocess()
|
|
5694
|
+
afterSubprocess: () => fixedInput.resumeFromSubprocess(),
|
|
5695
|
+
registerToken: (handler) => {
|
|
5696
|
+
rawActionGateTokenHandler = handler;
|
|
5697
|
+
}
|
|
5491
5698
|
});
|
|
5492
5699
|
} finally {
|
|
5493
5700
|
modalOwnsKeyboard = false;
|
|
@@ -5541,8 +5748,7 @@ ${err.message}` : ""}`
|
|
|
5541
5748
|
return;
|
|
5542
5749
|
}
|
|
5543
5750
|
}
|
|
5544
|
-
|
|
5545
|
-
busy = true;
|
|
5751
|
+
busy = startsChatTurn;
|
|
5546
5752
|
buffer = "";
|
|
5547
5753
|
cursorPos2 = 0;
|
|
5548
5754
|
fixedInput.enterOutputMode(submittedText);
|
|
@@ -5555,7 +5761,10 @@ ${err.message}` : ""}`
|
|
|
5555
5761
|
try {
|
|
5556
5762
|
return await waitForRawActionGate(input, output, gate, spawnRunner, {
|
|
5557
5763
|
beforeSubprocess: () => fixedInput.pause(),
|
|
5558
|
-
afterSubprocess: () => fixedInput.resumeFromSubprocess()
|
|
5764
|
+
afterSubprocess: () => fixedInput.resumeFromSubprocess(),
|
|
5765
|
+
registerToken: (handler) => {
|
|
5766
|
+
rawActionGateTokenHandler = handler;
|
|
5767
|
+
}
|
|
5559
5768
|
});
|
|
5560
5769
|
} finally {
|
|
5561
5770
|
modalOwnsKeyboard = false;
|
|
@@ -5664,9 +5873,13 @@ export {
|
|
|
5664
5873
|
createNoopFixedInput,
|
|
5665
5874
|
createRawInputDecoder,
|
|
5666
5875
|
createTurnHistory,
|
|
5667
|
-
|
|
5876
|
+
displayWidth,
|
|
5877
|
+
enterAltScreen,
|
|
5668
5878
|
finalizeCurrentTurn,
|
|
5669
5879
|
fitAnsiLine,
|
|
5880
|
+
installAltScreenRestoreHandlers,
|
|
5881
|
+
isAltScreenOn,
|
|
5882
|
+
leaveAltScreen,
|
|
5670
5883
|
padOrTruncateToWidth,
|
|
5671
5884
|
parseScrollAction,
|
|
5672
5885
|
renderHistory,
|