nolo-cli 0.8.0-alpha.21 → 0.8.0-alpha.23
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-YXTTYRXS.js} +44 -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-4NO7Y6UI.js} +28 -27
- package/{agentEmailCommands-6FACJBU4.js → agentEmailCommands-NPP5TGZV.js} +60 -58
- package/{agentListCommands-I6KZYCIG.js → agentListCommands-IP5BNB5W.js} +32 -30
- package/{agentMachineCommands-VKLIGMZA.js → agentMachineCommands-24NFTIKY.js} +27 -26
- package/{agentPullCommand-O2MTUAFR.js → agentPullCommand-N6UWRTVL.js} +3 -3
- package/{agentRecordCommands-7TZICYDT.js → agentRecordCommands-7AWSR46F.js} +51 -49
- package/{agentRunCommand-L4OM23KV.js → agentRunCommand-P46WCJ6P.js} +55 -52
- package/{agentRunControl-K4VKNEHF.js → agentRunControl-S3G62M6C.js} +3 -3
- package/{agentRuntimeLocal-ZYEIPTY4.js → agentRuntimeLocal-V5UV7S4R.js} +14 -12
- package/{agentSlice-BX7GXSNO.js → agentSlice-3CVAZZOP.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-VUW5FBDB.js → chunk-4VA3UQRF.js} +9 -9
- package/{chunk-2JCXITPK.js → chunk-5NYGMN4O.js} +15 -15
- package/{chunk-AGFH73SK.js → chunk-6KRA6AWI.js} +1 -1
- package/{chunk-P3PKED2I.js → chunk-6OHYC4BY.js} +9 -12
- package/{chunk-5KLGBAAR.js → chunk-6UUD2WES.js} +1 -1
- package/{chunk-ENOG22KJ.js → chunk-A4MYG3TR.js} +18 -20
- package/{chunk-2FTTDCD4.js → chunk-AMJ7LA5D.js} +1 -1
- package/chunk-AOKWJZ5N.js +4884 -0
- package/{chunk-JRKKFRAV.js → chunk-AWY2AFHN.js} +9 -5
- package/{chunk-RL776AGR.js → chunk-BB2PII22.js} +1 -1
- package/{chunk-I6XMPTMR.js → chunk-BFDWXLFF.js} +2 -2
- package/{chunk-VVX233PH.js → chunk-BT37DVDA.js} +9 -9
- package/chunk-BYXBJQAS.js +0 -0
- package/{chunk-C3RUNRHT.js → chunk-D55DXHXL.js} +1 -1
- package/{chunk-7DAJ4AI4.js → chunk-DSNLHTP3.js} +2 -2
- package/{chunk-SDJDLO5W.js → chunk-EUN3SYY7.js} +5 -5
- package/{chunk-FSO5B7GH.js → chunk-HAC6GPRE.js} +2 -2
- package/{chunk-CKOJQDKR.js → chunk-JEMATI63.js} +1 -1
- package/{chunk-7U44LYTR.js → chunk-JTINRTBT.js} +1 -1
- package/{chunk-YPRZSPF3.js → chunk-KLOCUWKZ.js} +1 -1
- package/{chunk-4O3CARJ4.js → chunk-KTHLAJEY.js} +1 -1
- package/{chunk-URUUZLPA.js → chunk-L3KWEH3V.js} +8 -8
- package/{chunk-O2ZNTTET.js → chunk-LBUTKV7S.js} +21 -12
- package/{chunk-GU3PEVGZ.js → chunk-LFFATN2M.js} +2632 -1578
- package/{chunk-UB6SN4NJ.js → chunk-LJCH34R2.js} +6 -6
- package/{chunk-5EFXE3O7.js → chunk-LTH6AVG7.js} +3 -3
- package/{chunk-7GNGZRLZ.js → chunk-LW6FJFCT.js} +45 -67
- package/{chunk-7KCUSYT2.js → chunk-MIQOUMSN.js} +7 -7
- package/{chunk-FVYY6MCS.js → chunk-O7VS7JLJ.js} +17 -17
- package/{chunk-RCSJFQPB.js → chunk-P7GAHW32.js} +361 -90
- package/{chunk-AL2KDGR2.js → chunk-PTT6KSYQ.js} +134 -84
- package/{chunk-4IJYA27C.js → chunk-PXZAAB4L.js} +4 -4
- package/{chunk-4XENYTF5.js → chunk-Q2WC4KGQ.js} +3 -3
- package/{chunk-4QEWT7KD.js → chunk-RBB43B5W.js} +367 -85
- package/chunk-RBCENBG7.js +36 -0
- package/{chunk-IWX4UW2E.js → chunk-RBCNBU2A.js} +88 -8
- package/{chunk-25LCXTML.js → chunk-RQPZX6KP.js} +2 -2
- package/{chunk-6KHNO3SK.js → chunk-RYMUT5JO.js} +23 -23
- 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-XBUBEFNX.js → chunk-WESWWEVA.js} +1 -1
- package/{chunk-2ECQG4YX.js → chunk-ZAUDEKML.js} +253 -159
- package/{chunk-N54XAP77.js → chunk-ZJS64PZJ.js} +1 -1
- package/{createAgentAutomationAction-RJF3N2QY.js → createAgentAutomationAction-DYQOGAVE.js} +25 -24
- package/{createDialogAction-DRSPS6CE.js → createDialogAction-ETB3KQQE.js} +25 -24
- package/{createPageAction-6B2WMNO3.js → createPageAction-UF2RHA63.js} +25 -24
- package/{dbSlice-Q3TM2FJV.js → dbSlice-R5EJKZBW.js} +7 -7
- package/{deleteFile-OW53A6BX.js → deleteFile-WPWVZE4B.js} +5 -5
- package/{dialogCommands-4IX4XIZE.js → dialogCommands-LYYC7XHF.js} +23 -22
- package/{dialogSlice-3M7KX2TX.js → dialogSlice-IFBZ4IT2.js} +24 -23
- package/{docCreateCommands-SIL3NPGT.js → docCreateCommands-I66OI374.js} +22 -21
- package/{docDeleteCommands-7IOMLUS4.js → docDeleteCommands-OVRBCHMF.js} +23 -22
- package/{docReadCommands-FNFXUA5L.js → docReadCommands-YLWUMEH7.js} +22 -21
- package/{docStore-SV7E34D4.js → docStore-65WO7U36.js} +24 -23
- package/{docUpdateCommands-X2HNDVUC.js → docUpdateCommands-NSICS4IN.js} +22 -21
- package/fetchMessages-KTNM7QAR.js +1 -1
- package/{getPricing-3E6UNPKL.js → getPricing-7PUT44ZS.js} +7 -3
- package/{handleSendMessageAction-JYETO5RZ.js → handleSendMessageAction-T76HEDOP.js} +29 -28
- package/index.js +74 -74
- package/{localDialogRead-2VRI24F4.js → localDialogRead-YSKFFRTT.js} +1 -1
- package/{machineCommands-RIO3RP5Q.js → machineCommands-4HQY6UVZ.js} +57 -55
- package/{machineWsRunDispatch-W7UYLGB5.js → machineWsRunDispatch-7YW2M4FS.js} +49 -47
- package/{memoryCommands-O4MIPIWQ.js → memoryCommands-HG4WKTU7.js} +2 -2
- package/{models-4OPOOLFS.js → models-MFXNI3TF.js} +2 -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-FLQWOAUR.js} +759 -604
- package/{removeDialogAgentAction-CXKR4NJI.js → removeDialogAgentAction-KOLQ2R5W.js} +13 -12
- package/{runAgentClientLoop-HZFAPJHS.js → runAgentClientLoop-IUV2TR3X.js} +43 -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-BDDAT4VU.js} +29 -28
- package/{spaceSlice-TSVROA5U.js → spaceSlice-HH633ZA4.js} +23 -22
- package/{streamAgentChatTurn-3C5RQZJF.js → streamAgentChatTurn-UBZOVFKV.js} +95 -72
- package/{tableCommands-O7O2LBEG.js → tableCommands-M3DJUETS.js} +10 -10
- package/{toolApiClient-QI3YBNWB.js → toolApiClient-C7P7YSE4.js} +2 -2
- package/{tools-EQDEKR6N.js → tools-OQZ34KCU.js} +31 -30
- package/{tuiSummaryLlmCaller-RV3THLZF.js → tuiSummaryLlmCaller-42AEL3LL.js} +8 -6
- package/{updateCommands-VOSPKXFF.js → updateCommands-TC5SX42Y.js} +3 -3
- package/{updateDialogTitleAction-3XV7VWSZ.js → updateDialogTitleAction-A3OOMSDO.js} +27 -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,147 @@ import {
|
|
|
3
3
|
normalizeDialogRecord,
|
|
4
4
|
readDialogSnapshot,
|
|
5
5
|
sortDialogs
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-O7VS7JLJ.js";
|
|
7
7
|
import {
|
|
8
|
+
ANSI_ESCAPE_REGEX,
|
|
8
9
|
CLI_AUTO_TIER_AGENT_KEY_TABLE,
|
|
9
10
|
CLI_IMAGE_AGENT_KEY,
|
|
11
|
+
COLLAPSED_PASTE_PLACEHOLDER_RE,
|
|
10
12
|
THEME_PALETTES,
|
|
13
|
+
allocateCollapsedPaste,
|
|
14
|
+
applyTerminalOutputToText,
|
|
11
15
|
buildSkillContextBlocks,
|
|
12
16
|
classifyCliAutoRoute,
|
|
17
|
+
clearCollapsedPasteStore,
|
|
18
|
+
countPhysicalLines,
|
|
19
|
+
createCollapsedPasteStore,
|
|
13
20
|
dimCliText,
|
|
21
|
+
displayWidth,
|
|
22
|
+
expandRangeToCollapsedPasteChips,
|
|
23
|
+
findCollapsedPasteSpanAt,
|
|
24
|
+
fitAnsiLine,
|
|
14
25
|
formatAssistantDisplay,
|
|
15
26
|
formatTokenCount,
|
|
16
27
|
getActiveBrightness,
|
|
17
28
|
getActiveDensity,
|
|
18
29
|
getActiveThemeName,
|
|
19
|
-
getCliLocale,
|
|
20
|
-
highlightMarkdown,
|
|
21
30
|
initCliLocale,
|
|
31
|
+
isBalanceExhaustedError,
|
|
22
32
|
isQuotaExhaustedError,
|
|
23
33
|
normalizeThinkingDisplayMode,
|
|
24
34
|
normalizeToolDisplayMode,
|
|
35
|
+
padOrTruncateToWidth,
|
|
25
36
|
parseCliLocale,
|
|
37
|
+
releaseCollapsedPaste,
|
|
38
|
+
releaseCollapsedPasteReferences,
|
|
26
39
|
renderTokenStatus,
|
|
40
|
+
replaceCollapsedPastesWithReferences,
|
|
41
|
+
resolveAgentContextWindow,
|
|
27
42
|
resolveCliColorEnabled,
|
|
28
43
|
resolveSkillReference,
|
|
29
44
|
resolveTuiBrightness,
|
|
30
45
|
runAgentTurn,
|
|
31
46
|
setActiveBrightness,
|
|
32
47
|
setActiveDensity,
|
|
48
|
+
setActiveTerminalBaseHex,
|
|
33
49
|
setActiveThemeName,
|
|
34
50
|
setCliLocale,
|
|
51
|
+
shouldCollapsePaste,
|
|
52
|
+
stripAnsi,
|
|
35
53
|
surfaceBackgroundSequence,
|
|
36
54
|
t,
|
|
55
|
+
takeDisplayWidth,
|
|
37
56
|
themeColorSequence,
|
|
38
|
-
themeText
|
|
39
|
-
|
|
57
|
+
themeText,
|
|
58
|
+
truncateAnsi,
|
|
59
|
+
visibleWidth,
|
|
60
|
+
wrapTextToLines,
|
|
61
|
+
wrapTranscriptLine
|
|
62
|
+
} from "./chunk-LFFATN2M.js";
|
|
40
63
|
import "./chunk-6HYVJV7B.js";
|
|
41
|
-
import "./chunk-2FTTDCD4.js";
|
|
42
64
|
import {
|
|
43
65
|
listFavoriteAgentIdsAcrossServers,
|
|
44
66
|
listLocalCachedAgents,
|
|
45
67
|
listRemoteAgents,
|
|
46
68
|
listRemoteAgentsAcrossServers
|
|
47
|
-
} from "./chunk-
|
|
48
|
-
import "./chunk-
|
|
69
|
+
} from "./chunk-DSNLHTP3.js";
|
|
70
|
+
import "./chunk-ID4G2MAR.js";
|
|
49
71
|
import {
|
|
50
72
|
listUserRecordsFromServers
|
|
51
|
-
} from "./chunk-
|
|
52
|
-
import "./chunk-
|
|
53
|
-
import
|
|
54
|
-
|
|
73
|
+
} from "./chunk-BB2PII22.js";
|
|
74
|
+
import "./chunk-3QAF2LTL.js";
|
|
75
|
+
import {
|
|
76
|
+
createCliLocalRuntimeAdapter
|
|
77
|
+
} from "./chunk-P7GAHW32.js";
|
|
78
|
+
import "./chunk-5MMZUWSG.js";
|
|
79
|
+
import "./chunk-CMKUBIGW.js";
|
|
80
|
+
import "./chunk-JBTJAPUF.js";
|
|
55
81
|
import {
|
|
56
82
|
getReadableCliDb
|
|
57
83
|
} from "./chunk-W4NVOSFF.js";
|
|
58
84
|
import {
|
|
59
85
|
queryUserRecords,
|
|
60
86
|
readDbRecord
|
|
61
|
-
} from "./chunk-
|
|
62
|
-
import "./chunk-
|
|
87
|
+
} from "./chunk-EUN3SYY7.js";
|
|
88
|
+
import "./chunk-ZJS64PZJ.js";
|
|
63
89
|
import {
|
|
64
90
|
resolveCliAgentKeyInput
|
|
65
91
|
} from "./chunk-VHBWHNVT.js";
|
|
66
92
|
import "./chunk-LTRXGFMS.js";
|
|
67
|
-
import "./chunk-
|
|
68
|
-
import "./chunk-CMKUBIGW.js";
|
|
69
|
-
import "./chunk-JBTJAPUF.js";
|
|
93
|
+
import "./chunk-KTHLAJEY.js";
|
|
70
94
|
import "./chunk-ATNTHIZI.js";
|
|
71
95
|
import "./chunk-JEXVIMYZ.js";
|
|
72
|
-
import
|
|
73
|
-
|
|
74
|
-
|
|
96
|
+
import {
|
|
97
|
+
prepareTools
|
|
98
|
+
} from "./chunk-HAC6GPRE.js";
|
|
99
|
+
import "./chunk-D55DXHXL.js";
|
|
100
|
+
import {
|
|
101
|
+
expandEnabledPacks
|
|
102
|
+
} from "./chunk-PTT6KSYQ.js";
|
|
75
103
|
import "./chunk-GAKEBQD6.js";
|
|
76
104
|
import "./chunk-KQHGZWSV.js";
|
|
77
|
-
import "./chunk-
|
|
105
|
+
import "./chunk-2CVZSC5L.js";
|
|
78
106
|
import "./chunk-3LY4F7SV.js";
|
|
79
107
|
import "./chunk-VP4WJWKW.js";
|
|
80
108
|
import "./chunk-63W5N6P3.js";
|
|
81
109
|
import "./chunk-VF4K2QE6.js";
|
|
82
|
-
import "./chunk-
|
|
83
|
-
import "./chunk-
|
|
110
|
+
import "./chunk-LJCH34R2.js";
|
|
111
|
+
import "./chunk-A4MYG3TR.js";
|
|
84
112
|
import "./chunk-VC6OZXO5.js";
|
|
85
113
|
import "./chunk-OWOHNGCN.js";
|
|
86
|
-
import "./chunk-25LCXTML.js";
|
|
87
|
-
import "./chunk-HNW7IJSK.js";
|
|
88
|
-
import "./chunk-XENYHRUE.js";
|
|
89
114
|
import {
|
|
90
115
|
DEFAULT_CONTEXT_WINDOW,
|
|
116
|
+
estimateTokenCount,
|
|
91
117
|
extractReferenceKeysFromMessage,
|
|
92
118
|
getModelContextWindow,
|
|
93
119
|
planCompression,
|
|
94
120
|
serializeMessageContent
|
|
95
|
-
} from "./chunk-
|
|
121
|
+
} from "./chunk-ZAUDEKML.js";
|
|
96
122
|
import {
|
|
97
123
|
buildBuiltinSummaryContent
|
|
98
|
-
} from "./chunk-
|
|
124
|
+
} from "./chunk-V2J635L5.js";
|
|
99
125
|
import "./chunk-MRC4Q34M.js";
|
|
100
126
|
import "./chunk-MTU75CZ2.js";
|
|
101
127
|
import "./chunk-CWMSB67P.js";
|
|
102
|
-
import "./chunk-
|
|
103
|
-
import "./chunk-
|
|
128
|
+
import "./chunk-4VA3UQRF.js";
|
|
129
|
+
import "./chunk-LTH6AVG7.js";
|
|
104
130
|
import "./chunk-Z4NR32XR.js";
|
|
105
131
|
import "./chunk-M76ECQRD.js";
|
|
132
|
+
import "./chunk-RQPZX6KP.js";
|
|
133
|
+
import "./chunk-UBSKX3LP.js";
|
|
134
|
+
import "./chunk-Y5GCAMGP.js";
|
|
106
135
|
import "./chunk-SOTZ6RDN.js";
|
|
107
|
-
import "./chunk-
|
|
136
|
+
import "./chunk-BFDWXLFF.js";
|
|
108
137
|
import "./chunk-UAD2WT54.js";
|
|
109
|
-
import "./chunk-
|
|
138
|
+
import "./chunk-L3KWEH3V.js";
|
|
139
|
+
import "./chunk-AZPCASRE.js";
|
|
140
|
+
import "./chunk-RBCENBG7.js";
|
|
141
|
+
import "./chunk-HNW7IJSK.js";
|
|
142
|
+
import "./chunk-XENYHRUE.js";
|
|
143
|
+
import "./chunk-JTINRTBT.js";
|
|
110
144
|
import {
|
|
111
145
|
runSelfUpdate
|
|
112
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-JEMATI63.js";
|
|
113
147
|
import {
|
|
114
148
|
saveProfileAgentSelection,
|
|
115
149
|
saveProfileLocale
|
|
@@ -118,15 +152,6 @@ import {
|
|
|
118
152
|
readPipeText,
|
|
119
153
|
spawnProcess
|
|
120
154
|
} 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
155
|
import {
|
|
131
156
|
buildSkillDiscoveryContextBlock
|
|
132
157
|
} from "./chunk-AFON4QUU.js";
|
|
@@ -134,71 +159,158 @@ import "./chunk-C4FTUXVF.js";
|
|
|
134
159
|
import "./chunk-KKY4B2Q2.js";
|
|
135
160
|
import "./chunk-WZSRQNQG.js";
|
|
136
161
|
import {
|
|
162
|
+
buildLocalWorkspaceOpenAiTools,
|
|
163
|
+
buildLocalWorkspaceToolset,
|
|
137
164
|
getProcessRegistry
|
|
138
|
-
} from "./chunk-
|
|
139
|
-
import "./chunk-
|
|
165
|
+
} from "./chunk-LBUTKV7S.js";
|
|
166
|
+
import "./chunk-6UUD2WES.js";
|
|
140
167
|
import "./chunk-ZNFJWEN4.js";
|
|
141
|
-
import "./chunk-
|
|
168
|
+
import "./chunk-YOCHZD7D.js";
|
|
142
169
|
import {
|
|
143
170
|
readCommandActionGatePayload,
|
|
144
171
|
resolveAgentImageInputSupport
|
|
145
|
-
} from "./chunk-
|
|
172
|
+
} from "./chunk-RBB43B5W.js";
|
|
146
173
|
import "./chunk-OPZYGHUC.js";
|
|
147
|
-
import
|
|
148
|
-
|
|
149
|
-
|
|
174
|
+
import {
|
|
175
|
+
buildCurrentTimeBlock,
|
|
176
|
+
buildIdentityBlock,
|
|
177
|
+
buildRuntimeGuidanceBlocks
|
|
178
|
+
} from "./chunk-6KRA6AWI.js";
|
|
179
|
+
import "./chunk-AWY2AFHN.js";
|
|
180
|
+
import {
|
|
181
|
+
canonicalizeToolNames
|
|
182
|
+
} from "./chunk-6OHYC4BY.js";
|
|
150
183
|
import {
|
|
151
184
|
clipCompactText
|
|
152
185
|
} from "./chunk-5MMAK75Q.js";
|
|
153
|
-
import "./chunk-
|
|
186
|
+
import "./chunk-AOKWJZ5N.js";
|
|
154
187
|
import "./chunk-5CS33IBL.js";
|
|
155
188
|
import "./chunk-JZPBVBIY.js";
|
|
156
|
-
import "./chunk-
|
|
157
|
-
import "./chunk-
|
|
189
|
+
import "./chunk-BYXBJQAS.js";
|
|
190
|
+
import "./chunk-KX6YBIHG.js";
|
|
191
|
+
import "./chunk-RBCNBU2A.js";
|
|
192
|
+
import "./chunk-O4BU24WZ.js";
|
|
193
|
+
import "./chunk-I42VC5KR.js";
|
|
194
|
+
import "./chunk-WWC7I6TA.js";
|
|
195
|
+
import "./chunk-JK7VW2FN.js";
|
|
158
196
|
import {
|
|
159
197
|
extractCustomId
|
|
160
198
|
} from "./chunk-DFFIZ25G.js";
|
|
161
199
|
import "./chunk-3ASDTTEI.js";
|
|
200
|
+
import {
|
|
201
|
+
asTrimmedLowercaseString
|
|
202
|
+
} from "./chunk-QSJ3HFEF.js";
|
|
162
203
|
import {
|
|
163
204
|
compactWhitespace
|
|
164
205
|
} from "./chunk-DWLEOOGR.js";
|
|
206
|
+
import "./chunk-AMJ7LA5D.js";
|
|
207
|
+
import {
|
|
208
|
+
parseUserIdFromAuthToken,
|
|
209
|
+
resolveAuthToken,
|
|
210
|
+
resolveServerCandidates,
|
|
211
|
+
resolveServerUrl
|
|
212
|
+
} from "./chunk-AVMJVOQY.js";
|
|
213
|
+
import {
|
|
214
|
+
DEFAULT_NOLO_SERVER_URL
|
|
215
|
+
} from "./chunk-OLZBQWZU.js";
|
|
165
216
|
import {
|
|
166
217
|
toErrorMessage
|
|
167
218
|
} from "./chunk-HNMXYYJR.js";
|
|
168
219
|
import "./chunk-H33743XH.js";
|
|
169
220
|
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";
|
|
221
|
+
import "./chunk-VBKJTOAW.js";
|
|
222
|
+
import "./chunk-DVRHHFEA.js";
|
|
184
223
|
import "./chunk-OOSFSFMA.js";
|
|
185
224
|
import "./chunk-GBRG75BQ.js";
|
|
186
|
-
import "./chunk-4SN6J65J.js";
|
|
187
|
-
import "./chunk-LCBAMY2M.js";
|
|
188
225
|
import "./chunk-3EUW3WEO.js";
|
|
189
226
|
import "./chunk-U6VC4MU4.js";
|
|
227
|
+
import "./chunk-KUG52IAP.js";
|
|
228
|
+
import "./chunk-LCBAMY2M.js";
|
|
229
|
+
import "./chunk-4SN6J65J.js";
|
|
190
230
|
import "./chunk-CF7PE763.js";
|
|
191
231
|
import {
|
|
192
232
|
asOptionalTrimmedString
|
|
193
233
|
} from "./chunk-G3SUCT4W.js";
|
|
194
|
-
import "./chunk-KUG52IAP.js";
|
|
195
234
|
import "./chunk-4VNS5WPM.js";
|
|
196
235
|
|
|
197
236
|
// packages/cli/tui/readlineWorkspace.ts
|
|
198
237
|
import { createInterface } from "node:readline";
|
|
199
238
|
import { stdin as defaultInput, stdout as defaultOutput } from "node:process";
|
|
200
|
-
import { existsSync as
|
|
239
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
240
|
+
import { join as join2 } from "node:path";
|
|
241
|
+
|
|
242
|
+
// packages/cli/client/estimateCliContext.ts
|
|
243
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
201
244
|
import { join } from "node:path";
|
|
245
|
+
var DEFAULT_CLI_PACKS = ["code", "agent-orchestration"];
|
|
246
|
+
var DEFAULT_CLI_PLATFORM_TOOLS = [
|
|
247
|
+
"ui_ask_choice",
|
|
248
|
+
"exa_search",
|
|
249
|
+
"fetchWebpage"
|
|
250
|
+
];
|
|
251
|
+
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";
|
|
252
|
+
function readAgentsMd(cwd) {
|
|
253
|
+
for (const name of ["AGENTS.md", "agents.md"]) {
|
|
254
|
+
const path = join(cwd, name);
|
|
255
|
+
if (!existsSync(path)) continue;
|
|
256
|
+
try {
|
|
257
|
+
return readFileSync(path, "utf8");
|
|
258
|
+
} catch {
|
|
259
|
+
return "";
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return "";
|
|
263
|
+
}
|
|
264
|
+
function estimateToolSchemas(toolNames) {
|
|
265
|
+
const toolset = buildLocalWorkspaceToolset({
|
|
266
|
+
declaredToolNames: toolNames,
|
|
267
|
+
exposeShellTools: true
|
|
268
|
+
});
|
|
269
|
+
const workspaceTools = buildLocalWorkspaceOpenAiTools({
|
|
270
|
+
toolNames: toolset.toolNames,
|
|
271
|
+
exposeShellTools: true
|
|
272
|
+
});
|
|
273
|
+
const platformNames = DEFAULT_CLI_PLATFORM_TOOLS.filter(
|
|
274
|
+
(name) => toolNames.includes(name)
|
|
275
|
+
);
|
|
276
|
+
const platformTools = platformNames.length > 0 ? prepareTools([...platformNames]) : [];
|
|
277
|
+
return estimateTokenCount(JSON.stringify([...workspaceTools, ...platformTools]));
|
|
278
|
+
}
|
|
279
|
+
function estimateDefaultCliContextTokens(opts = {}) {
|
|
280
|
+
const cwd = opts.cwd?.trim() || process.cwd();
|
|
281
|
+
const model = opts.model?.trim() || "deepseek-v4-flash";
|
|
282
|
+
const agentName = opts.agentName?.trim() || "DeepSeek V4 Flash";
|
|
283
|
+
const agentKey = opts.agentKey?.trim() || "agent-pub-deepseek-v4-flash";
|
|
284
|
+
const prompt = opts.agentPrompt?.trim() || DEFAULT_FLASH_PROMPT;
|
|
285
|
+
const packTools = canonicalizeToolNames(
|
|
286
|
+
expandEnabledPacks([...DEFAULT_CLI_PACKS], [])
|
|
287
|
+
);
|
|
288
|
+
const toolNames = canonicalizeToolNames([
|
|
289
|
+
...packTools,
|
|
290
|
+
...DEFAULT_CLI_PLATFORM_TOOLS
|
|
291
|
+
]);
|
|
292
|
+
const guidance = buildRuntimeGuidanceBlocks(toolNames);
|
|
293
|
+
const systemParts = [
|
|
294
|
+
prompt,
|
|
295
|
+
buildIdentityBlock({
|
|
296
|
+
agentName,
|
|
297
|
+
agentId: agentKey,
|
|
298
|
+
model
|
|
299
|
+
}),
|
|
300
|
+
guidance.startupProtocol,
|
|
301
|
+
guidance.contextLayerContract,
|
|
302
|
+
guidance.emailRegistrationWorkflow,
|
|
303
|
+
guidance.webResearchToolPolicy,
|
|
304
|
+
buildCurrentTimeBlock(/* @__PURE__ */ new Date()),
|
|
305
|
+
readAgentsMd(cwd),
|
|
306
|
+
buildSkillDiscoveryContextBlock(cwd) ?? ""
|
|
307
|
+
];
|
|
308
|
+
const systemTokens = estimateTokenCount(
|
|
309
|
+
systemParts.filter((part) => part?.trim()).join("\n\n")
|
|
310
|
+
);
|
|
311
|
+
const toolTokens = estimateToolSchemas(toolNames);
|
|
312
|
+
return Math.max(0, systemTokens + toolTokens);
|
|
313
|
+
}
|
|
202
314
|
|
|
203
315
|
// packages/cli/client/compactDialog.ts
|
|
204
316
|
import { ulid } from "ulid";
|
|
@@ -479,6 +591,12 @@ function renderDialogRow(args, colorEnabled = resolveCliColorEnabled()) {
|
|
|
479
591
|
function renderDialogOverflow(text, colorEnabled = resolveCliColorEnabled()) {
|
|
480
592
|
return themeText(` ${text}`, "chrome", colorEnabled);
|
|
481
593
|
}
|
|
594
|
+
function renderOverflowAbove(count, colorEnabled = resolveCliColorEnabled()) {
|
|
595
|
+
return renderDialogOverflow(t("dialogMoreAbove", String(count)), colorEnabled);
|
|
596
|
+
}
|
|
597
|
+
function renderOverflowBelow(count, colorEnabled = resolveCliColorEnabled()) {
|
|
598
|
+
return renderDialogOverflow(t("dialogMoreBelow", String(count)), colorEnabled);
|
|
599
|
+
}
|
|
482
600
|
function renderDialogCommand(text, colorEnabled = resolveCliColorEnabled()) {
|
|
483
601
|
return themeText(` ${text}`, "danger", colorEnabled);
|
|
484
602
|
}
|
|
@@ -577,7 +695,7 @@ function renderSelectDialog(args) {
|
|
|
577
695
|
];
|
|
578
696
|
const lines = [...titleLines, ""];
|
|
579
697
|
if (window.start > 0) {
|
|
580
|
-
lines.push(
|
|
698
|
+
lines.push(renderOverflowAbove(window.start));
|
|
581
699
|
}
|
|
582
700
|
for (let index = window.start; index < window.end; index += 1) {
|
|
583
701
|
const item = args.items[index];
|
|
@@ -590,7 +708,7 @@ function renderSelectDialog(args) {
|
|
|
590
708
|
);
|
|
591
709
|
}
|
|
592
710
|
if (window.end < total) {
|
|
593
|
-
lines.push("",
|
|
711
|
+
lines.push("", renderOverflowBelow(total - window.end));
|
|
594
712
|
}
|
|
595
713
|
return lines.join("\n");
|
|
596
714
|
}
|
|
@@ -819,7 +937,7 @@ async function runSelectDialog(args) {
|
|
|
819
937
|
// packages/cli/tui/confirmDialog.ts
|
|
820
938
|
var FALLBACK_TERMINAL_WIDTH = 80;
|
|
821
939
|
var WIDE_CHAR = /[ᄀ-ᅟ⺀-〾ぁ-㏿㐀-䶿一-鿿ꀀ-가-힣豈-︰--⦆¢-₩]/;
|
|
822
|
-
function
|
|
940
|
+
function displayWidth2(text) {
|
|
823
941
|
let width = 0;
|
|
824
942
|
for (const char of text) width += WIDE_CHAR.test(char) ? 2 : 1;
|
|
825
943
|
return width;
|
|
@@ -827,9 +945,9 @@ function displayWidth(text) {
|
|
|
827
945
|
function truncateCommand(command, maxWidth) {
|
|
828
946
|
const indent = 2;
|
|
829
947
|
const budget = Math.max(10, maxWidth - indent);
|
|
830
|
-
if (
|
|
948
|
+
if (displayWidth2(command) <= budget) return command;
|
|
831
949
|
const marker = ` ${t("dialogConfirmCommandTruncated")}`;
|
|
832
|
-
const keep = Math.max(1, budget -
|
|
950
|
+
const keep = Math.max(1, budget - displayWidth2(marker));
|
|
833
951
|
let kept = "";
|
|
834
952
|
let width = 0;
|
|
835
953
|
for (const char of command) {
|
|
@@ -1111,19 +1229,23 @@ function renderTabBar(questions, activeIndex, colorEnabled) {
|
|
|
1111
1229
|
}
|
|
1112
1230
|
return colorEnabled ? themeText(` ${label} `, "muted", colorEnabled) : ` ${label} `;
|
|
1113
1231
|
});
|
|
1114
|
-
const submitLabel = "
|
|
1232
|
+
const submitLabel = t("askChoiceSubmit");
|
|
1115
1233
|
return tabs.join(" ") + " " + (colorEnabled ? themeText(submitLabel, "chrome", colorEnabled) : submitLabel);
|
|
1116
1234
|
}
|
|
1117
|
-
function renderFooter(colorEnabled) {
|
|
1118
|
-
const hints =
|
|
1235
|
+
function renderFooter(multiSelect, colorEnabled) {
|
|
1236
|
+
const hints = multiSelect ? t("askChoiceFooterMulti") : t("askChoiceFooterSingle");
|
|
1119
1237
|
return colorEnabled ? themeText(` ${hints}`, "chrome", colorEnabled) : ` ${hints}`;
|
|
1120
1238
|
}
|
|
1239
|
+
function otherRowPrefix(index) {
|
|
1240
|
+
return ` [${index + 1}] ${t("askChoiceOtherLabel")}: `;
|
|
1241
|
+
}
|
|
1121
1242
|
function renderAskChoiceFrame(state) {
|
|
1122
1243
|
const colorEnabled = resolveCliColorEnabled();
|
|
1123
1244
|
const q = state.questions[state.activeIndex];
|
|
1124
1245
|
const qs = state.questionStates[state.activeIndex];
|
|
1125
1246
|
const lines = [];
|
|
1126
|
-
|
|
1247
|
+
let otherCursor = null;
|
|
1248
|
+
lines.push(renderDialogTitle(t("askChoiceTitle")));
|
|
1127
1249
|
lines.push("");
|
|
1128
1250
|
if (state.questions.length > 1) {
|
|
1129
1251
|
lines.push(renderTabBar(state.questions, state.activeIndex, colorEnabled));
|
|
@@ -1134,11 +1256,11 @@ function renderAskChoiceFrame(state) {
|
|
|
1134
1256
|
);
|
|
1135
1257
|
if (q.multiSelect) {
|
|
1136
1258
|
lines.push(
|
|
1137
|
-
colorEnabled ? themeText(
|
|
1259
|
+
colorEnabled ? themeText(` ${t("askChoiceHintMulti")}`, "muted", colorEnabled) : ` ${t("askChoiceHintMulti")}`
|
|
1138
1260
|
);
|
|
1139
1261
|
} else {
|
|
1140
1262
|
lines.push(
|
|
1141
|
-
colorEnabled ? themeText(
|
|
1263
|
+
colorEnabled ? themeText(` ${t("askChoiceHintSingle")}`, "muted", colorEnabled) : ` ${t("askChoiceHintSingle")}`
|
|
1142
1264
|
);
|
|
1143
1265
|
}
|
|
1144
1266
|
lines.push("");
|
|
@@ -1148,9 +1270,7 @@ function renderAskChoiceFrame(state) {
|
|
|
1148
1270
|
total: totalRows
|
|
1149
1271
|
});
|
|
1150
1272
|
if (window.start > 0) {
|
|
1151
|
-
lines.push(
|
|
1152
|
-
colorEnabled ? themeText(` \u2191 ${window.start} more`, "chrome", colorEnabled) : ` \u2191 ${window.start} more`
|
|
1153
|
-
);
|
|
1273
|
+
lines.push(renderOverflowAbove(window.start));
|
|
1154
1274
|
}
|
|
1155
1275
|
for (let i = window.start; i < window.end; i++) {
|
|
1156
1276
|
if (i < q.choices.length) {
|
|
@@ -1168,25 +1288,29 @@ function renderAskChoiceFrame(state) {
|
|
|
1168
1288
|
} else {
|
|
1169
1289
|
const focused = qs.cursorIndex === i;
|
|
1170
1290
|
const marker = focused ? DIALOG_CURSOR : " ";
|
|
1171
|
-
const
|
|
1172
|
-
const
|
|
1291
|
+
const plainPrefix = `${marker}${otherRowPrefix(i)}`;
|
|
1292
|
+
const plainRow = `${plainPrefix}${qs.otherText}`;
|
|
1173
1293
|
if (focused && colorEnabled) {
|
|
1174
1294
|
lines.push(
|
|
1175
|
-
`\x1B[1m${themeColorSequence("accent")}${
|
|
1295
|
+
`\x1B[1m${themeColorSequence("accent")}${plainRow}\x1B[0m`
|
|
1176
1296
|
);
|
|
1177
1297
|
} else {
|
|
1178
|
-
lines.push(
|
|
1298
|
+
lines.push(plainRow);
|
|
1299
|
+
}
|
|
1300
|
+
if (qs.otherFocused) {
|
|
1301
|
+
otherCursor = {
|
|
1302
|
+
lineIndex: lines.length - 1,
|
|
1303
|
+
col: displayWidth(plainPrefix + qs.otherText)
|
|
1304
|
+
};
|
|
1179
1305
|
}
|
|
1180
1306
|
}
|
|
1181
1307
|
}
|
|
1182
1308
|
if (window.end < totalRows) {
|
|
1183
|
-
lines.push(
|
|
1184
|
-
colorEnabled ? themeText(` \u2193 ${totalRows - window.end} more`, "chrome", colorEnabled) : ` \u2193 ${totalRows - window.end} more`
|
|
1185
|
-
);
|
|
1309
|
+
lines.push(renderOverflowBelow(totalRows - window.end));
|
|
1186
1310
|
}
|
|
1187
1311
|
lines.push("");
|
|
1188
|
-
lines.push(renderFooter(colorEnabled));
|
|
1189
|
-
return lines.join("\n");
|
|
1312
|
+
lines.push(renderFooter(q.multiSelect, colorEnabled));
|
|
1313
|
+
return { text: lines.join("\n"), otherCursor };
|
|
1190
1314
|
}
|
|
1191
1315
|
async function runAskChoiceDialog(args) {
|
|
1192
1316
|
const { request } = args;
|
|
@@ -1199,9 +1323,6 @@ async function runAskChoiceDialog(args) {
|
|
|
1199
1323
|
if (normalized.questions.length === 0) {
|
|
1200
1324
|
return { kind: "cancelled" };
|
|
1201
1325
|
}
|
|
1202
|
-
const q0 = normalized.questions[0];
|
|
1203
|
-
if (normalized.questions.length === 1 && !q0.multiSelect && !q0.allowOther) {
|
|
1204
|
-
}
|
|
1205
1326
|
let state = createInitialAskChoiceState(normalized.questions);
|
|
1206
1327
|
const output = args.output ?? process.stdout;
|
|
1207
1328
|
const input = args.input ?? process.stdin;
|
|
@@ -1215,9 +1336,15 @@ async function runAskChoiceDialog(args) {
|
|
|
1215
1336
|
typeof args.bottomRow === "function" ? args.bottomRow() : args.bottomRow ?? 0
|
|
1216
1337
|
);
|
|
1217
1338
|
let lastBottomRow = 0;
|
|
1339
|
+
let unanchoredCursorLift = 0;
|
|
1340
|
+
const restoreUnanchoredCursor = () => {
|
|
1341
|
+
if (unanchoredCursorLift <= 0) return;
|
|
1342
|
+
output.write(`\x1B[${unanchoredCursorLift}B`);
|
|
1343
|
+
unanchoredCursorLift = 0;
|
|
1344
|
+
};
|
|
1218
1345
|
const paint = () => {
|
|
1219
1346
|
const frame = renderAskChoiceFrame(state);
|
|
1220
|
-
const lines = frame.split("\n");
|
|
1347
|
+
const lines = frame.text.split("\n");
|
|
1221
1348
|
const lineCount = lines.length;
|
|
1222
1349
|
const canPosition = outputIsTty(output) && typeof output.write === "function";
|
|
1223
1350
|
if (bottomAnchored && canPosition) {
|
|
@@ -1234,22 +1361,37 @@ async function runAskChoiceDialog(args) {
|
|
|
1234
1361
|
}
|
|
1235
1362
|
lastBottomRow = anchorRow;
|
|
1236
1363
|
renderedLineCount = lineCount;
|
|
1364
|
+
unanchoredCursorLift = 0;
|
|
1365
|
+
if (frame.otherCursor) {
|
|
1366
|
+
const cursorRow = anchorRow - (lineCount - 1 - frame.otherCursor.lineIndex);
|
|
1367
|
+
if (cursorRow >= 1) {
|
|
1368
|
+
output.write(`\x1B[${cursorRow};${frame.otherCursor.col + 1}H`);
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1237
1371
|
return;
|
|
1238
1372
|
}
|
|
1239
1373
|
if (canPosition) {
|
|
1374
|
+
restoreUnanchoredCursor();
|
|
1240
1375
|
for (let i = 0; i < renderedLineCount; i++) {
|
|
1241
1376
|
output.write("\x1B[1A\x1B[2K");
|
|
1242
1377
|
}
|
|
1243
|
-
output.write(`${frame}
|
|
1378
|
+
output.write(`${frame.text}
|
|
1244
1379
|
`);
|
|
1245
1380
|
renderedLineCount = lineCount;
|
|
1381
|
+
if (frame.otherCursor) {
|
|
1382
|
+
const linesFromBottom = lineCount - frame.otherCursor.lineIndex;
|
|
1383
|
+
output.write(`\x1B[${linesFromBottom}A`);
|
|
1384
|
+
output.write(`\x1B[${frame.otherCursor.col + 1}G`);
|
|
1385
|
+
unanchoredCursorLift = linesFromBottom;
|
|
1386
|
+
}
|
|
1246
1387
|
return;
|
|
1247
1388
|
}
|
|
1248
1389
|
if (typeof output.write === "function") {
|
|
1249
|
-
output.write(`${frame}
|
|
1390
|
+
output.write(`${frame.text}
|
|
1250
1391
|
`);
|
|
1251
1392
|
}
|
|
1252
1393
|
renderedLineCount = lineCount;
|
|
1394
|
+
unanchoredCursorLift = 0;
|
|
1253
1395
|
};
|
|
1254
1396
|
const resizeTarget = output;
|
|
1255
1397
|
const onOutputResize = () => paint();
|
|
@@ -1277,6 +1419,9 @@ async function runAskChoiceDialog(args) {
|
|
|
1277
1419
|
continue;
|
|
1278
1420
|
}
|
|
1279
1421
|
let action = null;
|
|
1422
|
+
const qs = state.questionStates[state.activeIndex];
|
|
1423
|
+
const q = state.questions[state.activeIndex];
|
|
1424
|
+
const isOtherRow = qs.cursorIndex >= q.choices.length;
|
|
1280
1425
|
if (isCancel(sequence)) {
|
|
1281
1426
|
action = { type: "CANCEL" };
|
|
1282
1427
|
} else if (sequence === CSI_TAB) {
|
|
@@ -1288,11 +1433,17 @@ async function runAskChoiceDialog(args) {
|
|
|
1288
1433
|
} else if (isArrowDown(sequence)) {
|
|
1289
1434
|
action = { type: "MOVE_CURSOR", delta: 1 };
|
|
1290
1435
|
} else if (sequence === CSI_SPACE) {
|
|
1291
|
-
|
|
1436
|
+
if (qs.otherFocused) {
|
|
1437
|
+
action = {
|
|
1438
|
+
type: "SET_OTHER_TEXT",
|
|
1439
|
+
text: qs.otherText + " "
|
|
1440
|
+
};
|
|
1441
|
+
} else if (q.multiSelect) {
|
|
1442
|
+
action = { type: "TOGGLE_AT_CURSOR" };
|
|
1443
|
+
} else if (isOtherRow) {
|
|
1444
|
+
action = { type: "FOCUS_OTHER" };
|
|
1445
|
+
}
|
|
1292
1446
|
} 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
1447
|
if (qs.otherFocused) {
|
|
1297
1448
|
action = { type: "BLUR_OTHER" };
|
|
1298
1449
|
} else if (isOtherRow && !qs.otherFocused) {
|
|
@@ -1303,27 +1454,29 @@ async function runAskChoiceDialog(args) {
|
|
|
1303
1454
|
action = { type: "SELECT_AT_CURSOR" };
|
|
1304
1455
|
}
|
|
1305
1456
|
} else if (sequence === CSI_BACKSPACE || sequence === CSI_BACKSPACE_ALT) {
|
|
1306
|
-
const qs = state.questionStates[state.activeIndex];
|
|
1307
1457
|
if (qs.otherFocused && qs.otherText.length > 0) {
|
|
1458
|
+
const chars = Array.from(qs.otherText);
|
|
1308
1459
|
action = {
|
|
1309
1460
|
type: "SET_OTHER_TEXT",
|
|
1310
|
-
text:
|
|
1461
|
+
text: chars.slice(0, -1).join("")
|
|
1311
1462
|
};
|
|
1312
1463
|
}
|
|
1313
1464
|
} else if (sequence.length >= 1 && sequence.charCodeAt(0) >= 32 && !sequence.startsWith("\x1B")) {
|
|
1314
|
-
|
|
1315
|
-
if (qs.otherFocused) {
|
|
1465
|
+
if (qs.otherFocused || isOtherRow && q.allowOther) {
|
|
1316
1466
|
const cleaned = sequence.replace(/[\x00-\x1f\x7f]/g, "");
|
|
1317
1467
|
if (cleaned) {
|
|
1468
|
+
if (!qs.otherFocused) {
|
|
1469
|
+
state = askChoiceReducer(state, { type: "FOCUS_OTHER" });
|
|
1470
|
+
}
|
|
1471
|
+
const currentText = state.questionStates[state.activeIndex].otherText;
|
|
1318
1472
|
action = {
|
|
1319
1473
|
type: "SET_OTHER_TEXT",
|
|
1320
|
-
text:
|
|
1474
|
+
text: currentText + cleaned
|
|
1321
1475
|
};
|
|
1322
1476
|
}
|
|
1323
1477
|
}
|
|
1324
1478
|
}
|
|
1325
1479
|
if (action) {
|
|
1326
|
-
const prev = state;
|
|
1327
1480
|
state = askChoiceReducer(state, action);
|
|
1328
1481
|
if (state.phase !== "active") break;
|
|
1329
1482
|
if (action.type === "BLUR_OTHER" && state.activeIndex >= state.questions.length - 1 && canSubmit(state)) {
|
|
@@ -1347,6 +1500,7 @@ async function runAskChoiceDialog(args) {
|
|
|
1347
1500
|
renderedLineCount
|
|
1348
1501
|
);
|
|
1349
1502
|
} else {
|
|
1503
|
+
restoreUnanchoredCursor();
|
|
1350
1504
|
for (let i = 0; i < renderedLineCount; i++) {
|
|
1351
1505
|
output.write("\x1B[1A\x1B[2K");
|
|
1352
1506
|
}
|
|
@@ -1360,13 +1514,13 @@ async function runAskChoiceDialog(args) {
|
|
|
1360
1514
|
}
|
|
1361
1515
|
if (result.answers.length === 1) {
|
|
1362
1516
|
const a = result.answers[0];
|
|
1517
|
+
const q = normalized.questions[0];
|
|
1518
|
+
const labels = a.selectedIds.map((id) => q.choices.find((c) => c.id === id)?.label ?? "").filter(Boolean);
|
|
1519
|
+
if (a.otherText) labels.push(a.otherText);
|
|
1363
1520
|
return {
|
|
1364
1521
|
kind: "selected",
|
|
1365
1522
|
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 || ""
|
|
1523
|
+
label: labels.join(", ") || a.otherText || ""
|
|
1370
1524
|
};
|
|
1371
1525
|
}
|
|
1372
1526
|
return {
|
|
@@ -1424,8 +1578,13 @@ function createActivityIndicator(deps) {
|
|
|
1424
1578
|
let lastActivityAt = 0;
|
|
1425
1579
|
let frameIndex = 0;
|
|
1426
1580
|
let timer = null;
|
|
1581
|
+
let stopping = false;
|
|
1427
1582
|
const elapsedSecFrom = (startedAt) => startedAt > 0 ? Math.max(0, Math.floor((now() - startedAt) / 1e3)) : 0;
|
|
1428
1583
|
const tick = () => {
|
|
1584
|
+
if (stopping) {
|
|
1585
|
+
deps.onRepaint();
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1429
1588
|
frameIndex += 1;
|
|
1430
1589
|
if (explicitLabel === null && !fallbackActive && deps.isTurnActive() && lastActivityAt > 0 && now() - lastActivityAt >= fallbackDelayMs) {
|
|
1431
1590
|
fallbackActive = true;
|
|
@@ -1454,9 +1613,21 @@ function createActivityIndicator(deps) {
|
|
|
1454
1613
|
ensureTimer();
|
|
1455
1614
|
deps.onRepaint();
|
|
1456
1615
|
};
|
|
1616
|
+
const markStopping = () => {
|
|
1617
|
+
stopping = true;
|
|
1618
|
+
deps.onRepaint();
|
|
1619
|
+
};
|
|
1620
|
+
const isStopping = () => stopping;
|
|
1457
1621
|
const getView = () => {
|
|
1458
1622
|
if (!deps.isTurnActive()) return null;
|
|
1459
1623
|
const frame = ACTIVITY_FRAMES[frameIndex % ACTIVITY_FRAMES.length];
|
|
1624
|
+
if (stopping) {
|
|
1625
|
+
return {
|
|
1626
|
+
frame,
|
|
1627
|
+
label: deps.stoppingLabel(),
|
|
1628
|
+
elapsedSec: 0
|
|
1629
|
+
};
|
|
1630
|
+
}
|
|
1460
1631
|
if (explicitLabel !== null) {
|
|
1461
1632
|
return {
|
|
1462
1633
|
frame,
|
|
@@ -1483,8 +1654,9 @@ function createActivityIndicator(deps) {
|
|
|
1483
1654
|
fallbackActive = false;
|
|
1484
1655
|
fallbackStartedAt = 0;
|
|
1485
1656
|
lastActivityAt = 0;
|
|
1657
|
+
stopping = false;
|
|
1486
1658
|
};
|
|
1487
|
-
return { report, getView, stop };
|
|
1659
|
+
return { report, getView, markStopping, isStopping, stop };
|
|
1488
1660
|
}
|
|
1489
1661
|
|
|
1490
1662
|
// packages/ai/agent/utils/sortUtils.ts
|
|
@@ -1724,13 +1896,15 @@ function findAgentCatalogEntry(entries, rawTarget) {
|
|
|
1724
1896
|
if (!target) return null;
|
|
1725
1897
|
if (/^\d+$/.test(target)) {
|
|
1726
1898
|
const entry = entries[Number(target) - 1];
|
|
1727
|
-
return entry ? { name: entry.name, key: entry.key } : null;
|
|
1899
|
+
return entry ? { name: entry.name, key: entry.key, model: entry.model } : null;
|
|
1728
1900
|
}
|
|
1729
1901
|
const lower = target.toLowerCase();
|
|
1730
1902
|
const byName = entries.find(
|
|
1731
1903
|
(entry) => entry.name.toLowerCase() === lower || entry.key.toLowerCase() === lower || entry.key.toLowerCase().endsWith(`-${lower}`)
|
|
1732
1904
|
);
|
|
1733
|
-
if (byName)
|
|
1905
|
+
if (byName) {
|
|
1906
|
+
return { name: byName.name, key: byName.key, model: byName.model };
|
|
1907
|
+
}
|
|
1734
1908
|
if (target.startsWith("agent-") || target.startsWith("agent-pub-")) {
|
|
1735
1909
|
return { name: target, key: target };
|
|
1736
1910
|
}
|
|
@@ -1789,6 +1963,7 @@ async function runAgentPicker(args) {
|
|
|
1789
1963
|
kind: "selected",
|
|
1790
1964
|
name: selected.name,
|
|
1791
1965
|
key: selected.key,
|
|
1966
|
+
model: selected.model,
|
|
1792
1967
|
entries
|
|
1793
1968
|
};
|
|
1794
1969
|
}
|
|
@@ -1798,7 +1973,8 @@ function resolveAgentSwitchTarget(rawTarget, catalogEntries = []) {
|
|
|
1798
1973
|
const aliasEntry = catalogEntries.find((entry) => entry.key === resolvedKey);
|
|
1799
1974
|
return {
|
|
1800
1975
|
name: aliasEntry?.name ?? asTrimmedLowercaseString(rawTarget),
|
|
1801
|
-
key: resolvedKey
|
|
1976
|
+
key: resolvedKey,
|
|
1977
|
+
...aliasEntry?.model ? { model: aliasEntry.model } : {}
|
|
1802
1978
|
};
|
|
1803
1979
|
}
|
|
1804
1980
|
return findAgentCatalogEntry(catalogEntries, rawTarget);
|
|
@@ -1811,10 +1987,10 @@ function formatDialogTimestamp(value, now = Date.now()) {
|
|
|
1811
1987
|
const time = typeof value === "number" ? value : Date.parse(value);
|
|
1812
1988
|
if (!Number.isFinite(time) || time <= 0) return "";
|
|
1813
1989
|
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
|
|
1990
|
+
if (deltaSeconds < 60) return t("timeJustNow");
|
|
1991
|
+
if (deltaSeconds < 3600) return t("timeMinutesAgo", String(Math.floor(deltaSeconds / 60)));
|
|
1992
|
+
if (deltaSeconds < 86400) return t("timeHoursAgo", String(Math.floor(deltaSeconds / 3600)));
|
|
1993
|
+
if (deltaSeconds < 30 * 86400) return t("timeDaysAgo", String(Math.floor(deltaSeconds / 86400)));
|
|
1818
1994
|
const date = new Date(time);
|
|
1819
1995
|
const pad = (part) => String(part).padStart(2, "0");
|
|
1820
1996
|
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
|
@@ -1831,7 +2007,7 @@ function toDialogPickerItems(dialogs) {
|
|
|
1831
2007
|
}
|
|
1832
2008
|
function renderDialogList(dialogs) {
|
|
1833
2009
|
if (dialogs.length === 0) return t("noDialogsYet");
|
|
1834
|
-
const lines = ["
|
|
2010
|
+
const lines = [t("recentDialogs")];
|
|
1835
2011
|
for (const [index, dialog] of dialogs.entries()) {
|
|
1836
2012
|
const stamp = formatDialogTimestamp(dialog.updatedAt ?? dialog.createdAt);
|
|
1837
2013
|
lines.push(
|
|
@@ -1839,7 +2015,7 @@ function renderDialogList(dialogs) {
|
|
|
1839
2015
|
` id=${dialog.id}`
|
|
1840
2016
|
);
|
|
1841
2017
|
}
|
|
1842
|
-
lines.push("", "
|
|
2018
|
+
lines.push("", t("dialogListTip"));
|
|
1843
2019
|
return lines.join("\n");
|
|
1844
2020
|
}
|
|
1845
2021
|
async function fetchRecentDialogs(args) {
|
|
@@ -1920,7 +2096,7 @@ async function runDialogPicker(args) {
|
|
|
1920
2096
|
}
|
|
1921
2097
|
|
|
1922
2098
|
// packages/cli/tui/pasteImage.ts
|
|
1923
|
-
import { existsSync } from "node:fs";
|
|
2099
|
+
import { existsSync as existsSync2 } from "node:fs";
|
|
1924
2100
|
import { readFile, stat } from "node:fs/promises";
|
|
1925
2101
|
import { homedir } from "node:os";
|
|
1926
2102
|
import { isAbsolute, resolve } from "node:path";
|
|
@@ -1975,7 +2151,7 @@ function detectImagePaths(line, cwd) {
|
|
|
1975
2151
|
if (!token.raw) continue;
|
|
1976
2152
|
const resolved = resolveImageSource(token.decoded, cwd);
|
|
1977
2153
|
if (!isImagePath(resolved)) continue;
|
|
1978
|
-
if (!
|
|
2154
|
+
if (!existsSync2(resolved)) continue;
|
|
1979
2155
|
out.push({ raw: token.raw, resolvedPath: resolved });
|
|
1980
2156
|
}
|
|
1981
2157
|
return out;
|
|
@@ -2191,271 +2367,6 @@ function detectGitStatus(cwd) {
|
|
|
2191
2367
|
}
|
|
2192
2368
|
}
|
|
2193
2369
|
|
|
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
2370
|
// packages/cli/tui/sessionRender.ts
|
|
2460
2371
|
function formatCwd(cwd) {
|
|
2461
2372
|
const parts = cwd.split(/[/\\]/);
|
|
@@ -2470,12 +2381,12 @@ function formatElapsedSeconds(totalSeconds) {
|
|
|
2470
2381
|
const mins = minutes % 60;
|
|
2471
2382
|
return `${hours}h ${mins}m`;
|
|
2472
2383
|
}
|
|
2473
|
-
function renderComposerTokenChip(tokens, fallbackContextWindow) {
|
|
2384
|
+
function renderComposerTokenChip(tokens, fallbackContextWindow, estimatedContextTokens) {
|
|
2474
2385
|
const cw = tokens?.contextWindow ?? fallbackContextWindow;
|
|
2475
2386
|
if (!cw) {
|
|
2476
2387
|
return "context: \u2014";
|
|
2477
2388
|
}
|
|
2478
|
-
const used = tokens ? tokens.input + tokens.output : 0;
|
|
2389
|
+
const used = tokens ? tokens.input + tokens.output : Math.max(0, estimatedContextTokens ?? 0);
|
|
2479
2390
|
const pct = Math.min(100, used / cw * 100);
|
|
2480
2391
|
const pctText = pct > 0 && pct < 10 ? pct.toFixed(1) : Math.round(pct).toString();
|
|
2481
2392
|
return `context: ${pctText}% (${formatTokenCount(used)}/${formatTokenCount(cw)})`;
|
|
@@ -2497,7 +2408,15 @@ function renderStatusLine(state) {
|
|
|
2497
2408
|
const untrackedText = untracked > 0 ? ` ${themeText(`?${untracked}`, "muted", colorEnabled)}` : "";
|
|
2498
2409
|
parts.push(`${branchText}${modifiedText}${untrackedText}`);
|
|
2499
2410
|
}
|
|
2500
|
-
const tokenSegment = themeText(
|
|
2411
|
+
const tokenSegment = themeText(
|
|
2412
|
+
renderComposerTokenChip(
|
|
2413
|
+
state.turnTokens,
|
|
2414
|
+
state.contextWindow,
|
|
2415
|
+
state.estimatedContextTokens
|
|
2416
|
+
),
|
|
2417
|
+
"muted",
|
|
2418
|
+
colorEnabled
|
|
2419
|
+
);
|
|
2501
2420
|
parts.push(tokenSegment);
|
|
2502
2421
|
const runningCount = getProcessRegistry().list().filter((p) => p.status === "running").length;
|
|
2503
2422
|
if (runningCount > 0) {
|
|
@@ -2579,7 +2498,7 @@ function renderWelcome(state, frame = 0, maxFrames = 0, columns) {
|
|
|
2579
2498
|
const isDark = brightness === "dark";
|
|
2580
2499
|
let sceneArt = colorEnabled ? buildColoredScene(isDark, frame, maxFrames) : buildPlainScene(isDark, frame, maxFrames);
|
|
2581
2500
|
if (typeof columns === "number" && columns > 0) {
|
|
2582
|
-
const widestSceneCol = sceneArt.split("\n").reduce((max, line) => Math.max(max,
|
|
2501
|
+
const widestSceneCol = sceneArt.split("\n").reduce((max, line) => Math.max(max, displayWidth(stripAnsi(line))), 0);
|
|
2583
2502
|
if (columns < widestSceneCol) sceneArt = "";
|
|
2584
2503
|
}
|
|
2585
2504
|
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 +2548,19 @@ function renderContextPanel(state, colorEnabled = resolveCliColorEnabled()) {
|
|
|
2629
2548
|
];
|
|
2630
2549
|
let maxW = 0;
|
|
2631
2550
|
for (const l of labels) {
|
|
2632
|
-
const w =
|
|
2551
|
+
const w = displayWidth(l);
|
|
2633
2552
|
if (w > maxW) maxW = w;
|
|
2634
2553
|
}
|
|
2635
2554
|
const targetWidth = maxW >= 9 ? maxW + 1 : 9;
|
|
2636
2555
|
const padLabel = (raw) => {
|
|
2637
|
-
const w =
|
|
2556
|
+
const w = displayWidth(raw);
|
|
2638
2557
|
const padding = " ".repeat(Math.max(0, targetWidth - w));
|
|
2639
2558
|
return raw + padding;
|
|
2640
2559
|
};
|
|
2641
2560
|
const field = (rawLabel, value) => `${themeText(padLabel(rawLabel), "muted", colorEnabled)}${value}`;
|
|
2642
2561
|
const next = (command, description) => ` ${themeText(command, "accent", colorEnabled)}${themeText(description, "muted", colorEnabled)}`;
|
|
2643
2562
|
const titleText = t("contextTitle");
|
|
2644
|
-
const heading = colorEnabled ? [renderDialogTitle(titleText, true)] : [titleText, "\u2500".repeat(
|
|
2563
|
+
const heading = colorEnabled ? [renderDialogTitle(titleText, true)] : [titleText, "\u2500".repeat(displayWidth(titleText))];
|
|
2645
2564
|
return [
|
|
2646
2565
|
...heading,
|
|
2647
2566
|
field(labels[0], `${state.agentName} (${state.agentKey})`),
|
|
@@ -2684,86 +2603,6 @@ function renderKnownAgents(colorEnabled = resolveCliColorEnabled()) {
|
|
|
2684
2603
|
].join("\n");
|
|
2685
2604
|
}
|
|
2686
2605
|
|
|
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
2606
|
// packages/cli/tui/sessionInput.ts
|
|
2768
2607
|
var PASTE_TOKEN_PREFIX = "\0PASTE\0";
|
|
2769
2608
|
function applyTuiInputKey(buffer, sequence, key = {}, cursorPos, options) {
|
|
@@ -3051,6 +2890,7 @@ function createInitialTuiState(env = process.env) {
|
|
|
3051
2890
|
) || void 0;
|
|
3052
2891
|
const dialogEnvValue = asOptionalTrimmedString(env.NOLO_DIALOG);
|
|
3053
2892
|
const explicitDialogKey = asOptionalTrimmedString(env.NOLO_DIALOG_KEY) ?? (dialogEnvValue?.startsWith("dialog-") ? dialogEnvValue : void 0);
|
|
2893
|
+
const autoRouteDefault = env.NOLO_AUTO_ROUTE !== "0";
|
|
3054
2894
|
return {
|
|
3055
2895
|
agentKey,
|
|
3056
2896
|
agentName,
|
|
@@ -3076,16 +2916,39 @@ function createInitialTuiState(env = process.env) {
|
|
|
3076
2916
|
"hide"
|
|
3077
2917
|
),
|
|
3078
2918
|
toolDisplay: normalizeToolDisplayMode(env.NOLO_CLI_TOOLS ?? env.NOLO_TOOLS, "compact"),
|
|
3079
|
-
contextWindow:
|
|
2919
|
+
contextWindow: resolveAgentContextWindow({
|
|
2920
|
+
agentKey,
|
|
2921
|
+
agentName,
|
|
2922
|
+
autoRouteDefault
|
|
2923
|
+
}),
|
|
2924
|
+
estimatedContextTokens: estimateDefaultCliContextTokens({
|
|
2925
|
+
cwd,
|
|
2926
|
+
agentKey,
|
|
2927
|
+
agentName: autoRouteDefault ? "DeepSeek V4 Flash" : agentName,
|
|
2928
|
+
model: autoRouteDefault ? "deepseek-v4-flash" : void 0
|
|
2929
|
+
})
|
|
3080
2930
|
};
|
|
3081
2931
|
}
|
|
3082
|
-
function applyAgentSwitch(state, target) {
|
|
2932
|
+
function applyAgentSwitch(state, target, opts) {
|
|
2933
|
+
const autoRouteDefault = opts?.autoRouteDefault ?? process.env.NOLO_AUTO_ROUTE !== "0";
|
|
2934
|
+
const contextWindow = resolveAgentContextWindow({
|
|
2935
|
+
agentKey: target.key,
|
|
2936
|
+
agentName: target.name,
|
|
2937
|
+
model: target.model,
|
|
2938
|
+
autoRouteDefault
|
|
2939
|
+
});
|
|
3083
2940
|
return {
|
|
3084
2941
|
nextState: {
|
|
3085
2942
|
...state,
|
|
3086
2943
|
agentName: target.name,
|
|
3087
2944
|
agentKey: target.key,
|
|
3088
|
-
contextWindow
|
|
2945
|
+
contextWindow,
|
|
2946
|
+
estimatedContextTokens: estimateDefaultCliContextTokens({
|
|
2947
|
+
cwd: state.cwd,
|
|
2948
|
+
agentKey: target.key,
|
|
2949
|
+
agentName: target.name,
|
|
2950
|
+
model: target.model
|
|
2951
|
+
})
|
|
3089
2952
|
},
|
|
3090
2953
|
output: `Switched to ${target.name}. ${state.dialogId ? `Dialog kept: ${state.dialogId}` : "Dialog kept: new"}`
|
|
3091
2954
|
};
|
|
@@ -3147,32 +3010,32 @@ function handleTuiInput(input, state) {
|
|
|
3147
3010
|
return {
|
|
3148
3011
|
nextState: state,
|
|
3149
3012
|
output: [
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
3013
|
+
t("themeCurrent", getActiveThemeName(), brightness),
|
|
3014
|
+
t("themeUsage"),
|
|
3015
|
+
t("themeAvailable", available)
|
|
3153
3016
|
].join("\n")
|
|
3154
3017
|
};
|
|
3155
3018
|
}
|
|
3156
3019
|
if (sub === "light" || sub === "dark") {
|
|
3157
3020
|
setActiveBrightness(sub);
|
|
3158
|
-
return { nextState: state, output:
|
|
3021
|
+
return { nextState: state, output: t("themeBrightnessSwitched", sub) };
|
|
3159
3022
|
}
|
|
3160
3023
|
if (sub === "auto") {
|
|
3161
3024
|
setActiveBrightness(null);
|
|
3162
3025
|
return {
|
|
3163
3026
|
nextState: state,
|
|
3164
|
-
output:
|
|
3027
|
+
output: t("themeBrightnessAuto", resolveTuiBrightness())
|
|
3165
3028
|
};
|
|
3166
3029
|
}
|
|
3167
3030
|
if (setActiveThemeName(sub)) {
|
|
3168
3031
|
return {
|
|
3169
3032
|
nextState: state,
|
|
3170
|
-
output:
|
|
3033
|
+
output: t("themeSwitched", sub)
|
|
3171
3034
|
};
|
|
3172
3035
|
} else {
|
|
3173
3036
|
return {
|
|
3174
3037
|
nextState: state,
|
|
3175
|
-
output:
|
|
3038
|
+
output: t("themeUnknown", sub, available)
|
|
3176
3039
|
};
|
|
3177
3040
|
}
|
|
3178
3041
|
}
|
|
@@ -3182,20 +3045,19 @@ function handleTuiInput(input, state) {
|
|
|
3182
3045
|
if (!sub) {
|
|
3183
3046
|
return {
|
|
3184
3047
|
nextState: state,
|
|
3185
|
-
output:
|
|
3186
|
-
Usage: /density <cozy|spacious>`
|
|
3048
|
+
output: t("densityCurrent", getActiveDensity())
|
|
3187
3049
|
};
|
|
3188
3050
|
}
|
|
3189
3051
|
if (sub === "cozy" || sub === "spacious") {
|
|
3190
3052
|
setActiveDensity(sub);
|
|
3191
3053
|
return {
|
|
3192
3054
|
nextState: state,
|
|
3193
|
-
output:
|
|
3055
|
+
output: t("densitySwitched", sub)
|
|
3194
3056
|
};
|
|
3195
3057
|
} else {
|
|
3196
3058
|
return {
|
|
3197
3059
|
nextState: state,
|
|
3198
|
-
output:
|
|
3060
|
+
output: t("densityUnknown", sub)
|
|
3199
3061
|
};
|
|
3200
3062
|
}
|
|
3201
3063
|
}
|
|
@@ -3206,52 +3068,52 @@ Usage: /density <cozy|spacious>`
|
|
|
3206
3068
|
if (argText !== "auto" && argText !== "local" && argText !== "server") {
|
|
3207
3069
|
return {
|
|
3208
3070
|
nextState: state,
|
|
3209
|
-
output: "
|
|
3071
|
+
output: t("runtimeUsage")
|
|
3210
3072
|
};
|
|
3211
3073
|
}
|
|
3212
3074
|
return {
|
|
3213
3075
|
nextState: { ...state, runtimeMode: argText },
|
|
3214
|
-
output:
|
|
3076
|
+
output: t("runtimeSet", argText)
|
|
3215
3077
|
};
|
|
3216
3078
|
}
|
|
3217
3079
|
case "/tools": {
|
|
3218
3080
|
if (!argText) {
|
|
3219
3081
|
return {
|
|
3220
3082
|
nextState: state,
|
|
3221
|
-
output:
|
|
3083
|
+
output: t("toolsCurrent", state.toolDisplay)
|
|
3222
3084
|
};
|
|
3223
3085
|
}
|
|
3224
3086
|
const normalizedArg = asTrimmedLowercaseString(argText);
|
|
3225
3087
|
if (!["hide", "compact", "verbose", "on", "off"].includes(normalizedArg)) {
|
|
3226
3088
|
return {
|
|
3227
3089
|
nextState: state,
|
|
3228
|
-
output: "
|
|
3090
|
+
output: t("toolsUsage")
|
|
3229
3091
|
};
|
|
3230
3092
|
}
|
|
3231
3093
|
const nextMode = normalizeToolDisplayMode(normalizedArg, state.toolDisplay);
|
|
3232
3094
|
return {
|
|
3233
3095
|
nextState: { ...state, toolDisplay: nextMode },
|
|
3234
|
-
output:
|
|
3096
|
+
output: t("toolsSet", nextMode)
|
|
3235
3097
|
};
|
|
3236
3098
|
}
|
|
3237
3099
|
case "/thinking": {
|
|
3238
3100
|
if (!argText) {
|
|
3239
3101
|
return {
|
|
3240
3102
|
nextState: state,
|
|
3241
|
-
output:
|
|
3103
|
+
output: t("thinkingCurrent", state.thinkingDisplay)
|
|
3242
3104
|
};
|
|
3243
3105
|
}
|
|
3244
3106
|
const normalizedArg = asTrimmedLowercaseString(argText);
|
|
3245
3107
|
if (!["hide", "marker", "show", "on", "off"].includes(normalizedArg)) {
|
|
3246
3108
|
return {
|
|
3247
3109
|
nextState: state,
|
|
3248
|
-
output: "
|
|
3110
|
+
output: t("thinkingUsage")
|
|
3249
3111
|
};
|
|
3250
3112
|
}
|
|
3251
3113
|
const nextMode = normalizeThinkingDisplayMode(normalizedArg, state.thinkingDisplay);
|
|
3252
3114
|
return {
|
|
3253
3115
|
nextState: { ...state, thinkingDisplay: nextMode },
|
|
3254
|
-
output:
|
|
3116
|
+
output: t("thinkingSet", nextMode)
|
|
3255
3117
|
};
|
|
3256
3118
|
}
|
|
3257
3119
|
case "/tasks":
|
|
@@ -3263,14 +3125,14 @@ Usage: /density <cozy|spacious>`
|
|
|
3263
3125
|
const stopped = all.filter((p) => p.status !== "running");
|
|
3264
3126
|
const lines = [];
|
|
3265
3127
|
if (running.length > 0) {
|
|
3266
|
-
lines.push(
|
|
3128
|
+
lines.push(t("tasksRunning", String(running.length)));
|
|
3267
3129
|
for (const p of running) {
|
|
3268
3130
|
const elapsed = formatElapsedSeconds(Math.floor((Date.now() - p.startedAt) / 1e3));
|
|
3269
3131
|
lines.push(` pid ${p.pid} ${p.label} running ${elapsed}`);
|
|
3270
3132
|
}
|
|
3271
3133
|
}
|
|
3272
3134
|
if (stopped.length > 0) {
|
|
3273
|
-
lines.push(
|
|
3135
|
+
lines.push(t("tasksStopped", String(stopped.length)));
|
|
3274
3136
|
for (const p of stopped) {
|
|
3275
3137
|
const elapsed = formatElapsedSeconds(Math.floor((Date.now() - p.startedAt) / 1e3));
|
|
3276
3138
|
const exitInfo = p.exitCode !== void 0 ? ` exit ${p.exitCode}` : "";
|
|
@@ -3278,38 +3140,38 @@ Usage: /density <cozy|spacious>`
|
|
|
3278
3140
|
}
|
|
3279
3141
|
}
|
|
3280
3142
|
if (all.length === 0) {
|
|
3281
|
-
lines.push("
|
|
3143
|
+
lines.push(t("tasksNone"));
|
|
3282
3144
|
}
|
|
3283
3145
|
return { nextState: state, output: lines.join("\n") };
|
|
3284
3146
|
}
|
|
3285
3147
|
case "/stop": {
|
|
3286
3148
|
const registry = getProcessRegistry();
|
|
3287
3149
|
if (!argText) {
|
|
3288
|
-
return { nextState: state, output: "
|
|
3150
|
+
return { nextState: state, output: t("stopUsage") };
|
|
3289
3151
|
}
|
|
3290
3152
|
if (argText === "all") {
|
|
3291
3153
|
const before = registry.list().filter((p) => p.status === "running").length;
|
|
3292
3154
|
registry.stopAll();
|
|
3293
|
-
return { nextState: state, output:
|
|
3155
|
+
return { nextState: state, output: t("stopAllDone", String(before)) };
|
|
3294
3156
|
}
|
|
3295
3157
|
if (/^\d+$/.test(argText)) {
|
|
3296
3158
|
const pid = parseInt(argText, 10);
|
|
3297
3159
|
const proc = registry.get(pid);
|
|
3298
3160
|
if (!proc || proc.status !== "running") {
|
|
3299
|
-
return { nextState: state, output:
|
|
3161
|
+
return { nextState: state, output: t("stopNoPid", String(pid)) };
|
|
3300
3162
|
}
|
|
3301
3163
|
registry.kill(pid);
|
|
3302
|
-
return { nextState: state, output:
|
|
3164
|
+
return { nextState: state, output: t("stopPidDone", String(pid), proc.label) };
|
|
3303
3165
|
}
|
|
3304
3166
|
const matches = registry.list().filter((p) => p.status === "running" && p.label === argText);
|
|
3305
3167
|
if (matches.length === 0) {
|
|
3306
|
-
return { nextState: state, output:
|
|
3168
|
+
return { nextState: state, output: t("stopNoLabel", argText) };
|
|
3307
3169
|
}
|
|
3308
3170
|
for (const p of matches) {
|
|
3309
3171
|
registry.kill(p.pid);
|
|
3310
3172
|
}
|
|
3311
3173
|
const stoppedNames = matches.map((p) => `pid ${p.pid} (${p.label})`).join(", ");
|
|
3312
|
-
return { nextState: state, output:
|
|
3174
|
+
return { nextState: state, output: t("stopLabelsDone", stoppedNames) };
|
|
3313
3175
|
}
|
|
3314
3176
|
case "/exit":
|
|
3315
3177
|
case "/quit":
|
|
@@ -3333,15 +3195,13 @@ Usage: /density <cozy|spacious>`
|
|
|
3333
3195
|
if (argText) {
|
|
3334
3196
|
return {
|
|
3335
3197
|
nextState: state,
|
|
3336
|
-
output:
|
|
3337
|
-
|
|
3338
|
-
${renderTuiHelp()}`
|
|
3198
|
+
output: t("unknownCommand", trimmed) + renderTuiHelp()
|
|
3339
3199
|
};
|
|
3340
3200
|
}
|
|
3341
3201
|
if (!state.dialogId) {
|
|
3342
3202
|
return {
|
|
3343
3203
|
nextState: state,
|
|
3344
|
-
output: "
|
|
3204
|
+
output: t("compactNothing")
|
|
3345
3205
|
};
|
|
3346
3206
|
}
|
|
3347
3207
|
return {
|
|
@@ -3368,15 +3228,14 @@ ${renderTuiHelp()}`
|
|
|
3368
3228
|
if (argText === "current" || argText === "show") {
|
|
3369
3229
|
return {
|
|
3370
3230
|
nextState: state,
|
|
3371
|
-
output:
|
|
3231
|
+
output: t("agentCurrent", state.agentName, state.agentKey)
|
|
3372
3232
|
};
|
|
3373
3233
|
}
|
|
3374
3234
|
const resolvedTarget = resolveAgentSwitchTarget(argText, resolveCatalogPlatformAgents());
|
|
3375
3235
|
if (!resolvedTarget) {
|
|
3376
3236
|
return {
|
|
3377
3237
|
nextState: state,
|
|
3378
|
-
output:
|
|
3379
|
-
Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
3238
|
+
output: t("agentUnknown", argText)
|
|
3380
3239
|
};
|
|
3381
3240
|
}
|
|
3382
3241
|
return applyAgentSwitch(state, resolvedTarget);
|
|
@@ -3430,6 +3289,16 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3430
3289
|
action: { type: "set-mouse", enabled: argText === "on" }
|
|
3431
3290
|
};
|
|
3432
3291
|
}
|
|
3292
|
+
case "/altscreen": {
|
|
3293
|
+
if (argText !== "on" && argText !== "off") {
|
|
3294
|
+
return { nextState: state, output: t("altscreenUsage") };
|
|
3295
|
+
}
|
|
3296
|
+
return {
|
|
3297
|
+
nextState: state,
|
|
3298
|
+
output: argText === "on" ? t("altscreenOn") : t("altscreenOff"),
|
|
3299
|
+
action: { type: "set-altscreen", enabled: argText === "on" }
|
|
3300
|
+
};
|
|
3301
|
+
}
|
|
3433
3302
|
case "/resume": {
|
|
3434
3303
|
if (!argText) {
|
|
3435
3304
|
return {
|
|
@@ -3459,7 +3328,7 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3459
3328
|
if (rest[0] === "attach") {
|
|
3460
3329
|
const docName = rest.slice(1).join(" ").trim();
|
|
3461
3330
|
if (!docName) {
|
|
3462
|
-
return { nextState: state, output: "
|
|
3331
|
+
return { nextState: state, output: t("docAttachUsage") };
|
|
3463
3332
|
}
|
|
3464
3333
|
const attachedDocs = state.attachedDocs.includes(docName) ? state.attachedDocs : [...state.attachedDocs, docName];
|
|
3465
3334
|
return {
|
|
@@ -3469,7 +3338,7 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3469
3338
|
}
|
|
3470
3339
|
return {
|
|
3471
3340
|
nextState: state,
|
|
3472
|
-
output: state.attachedDocs.length > 0 ?
|
|
3341
|
+
output: state.attachedDocs.length > 0 ? t("docList", state.attachedDocs.join(", ")) : t("docNone")
|
|
3473
3342
|
};
|
|
3474
3343
|
}
|
|
3475
3344
|
case "/skill": {
|
|
@@ -3477,7 +3346,7 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3477
3346
|
if (sub === "attach") {
|
|
3478
3347
|
const skillRef = rest.slice(1).join(" ").trim();
|
|
3479
3348
|
if (!skillRef) {
|
|
3480
|
-
return { nextState: state, output: "
|
|
3349
|
+
return { nextState: state, output: t("skillAttachUsage") };
|
|
3481
3350
|
}
|
|
3482
3351
|
const attachedSkills = state.attachedSkills.includes(skillRef) ? state.attachedSkills : [...state.attachedSkills, skillRef];
|
|
3483
3352
|
return {
|
|
@@ -3488,38 +3357,37 @@ Use /switch, /switch list, /switch minimax-m3, or a full agent key.`
|
|
|
3488
3357
|
if (sub === "detach") {
|
|
3489
3358
|
const skillRef = rest.slice(1).join(" ").trim();
|
|
3490
3359
|
if (!skillRef) {
|
|
3491
|
-
return { nextState: state, output: "
|
|
3360
|
+
return { nextState: state, output: t("skillDetachUsage") };
|
|
3492
3361
|
}
|
|
3493
3362
|
const attachedSkills = state.attachedSkills.filter((s) => s !== skillRef);
|
|
3494
3363
|
return {
|
|
3495
3364
|
nextState: { ...state, attachedSkills },
|
|
3496
|
-
output: state.attachedSkills.includes(skillRef) ?
|
|
3365
|
+
output: state.attachedSkills.includes(skillRef) ? t("skillDetached", skillRef) : t("skillNotAttached", skillRef)
|
|
3497
3366
|
};
|
|
3498
3367
|
}
|
|
3499
3368
|
if (sub === "clear") {
|
|
3500
3369
|
if (state.attachedSkills.length === 0) {
|
|
3501
|
-
return { nextState: state, output: "
|
|
3370
|
+
return { nextState: state, output: t("skillNone") };
|
|
3502
3371
|
}
|
|
3503
3372
|
return {
|
|
3504
3373
|
nextState: { ...state, attachedSkills: [] },
|
|
3505
|
-
output:
|
|
3374
|
+
output: t("skillCleared", String(state.attachedSkills.length))
|
|
3506
3375
|
};
|
|
3507
3376
|
}
|
|
3508
3377
|
return {
|
|
3509
3378
|
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."
|
|
3379
|
+
output: state.attachedSkills.length > 0 ? t("skillList", state.attachedSkills.join(", ")) : t("skillNoneHint")
|
|
3512
3380
|
};
|
|
3513
3381
|
}
|
|
3514
3382
|
case "/customize":
|
|
3515
3383
|
return {
|
|
3516
3384
|
nextState: state,
|
|
3517
|
-
output: "
|
|
3385
|
+
output: t("customizeHint")
|
|
3518
3386
|
};
|
|
3519
3387
|
case "/login":
|
|
3520
3388
|
return {
|
|
3521
3389
|
nextState: state,
|
|
3522
|
-
output: "
|
|
3390
|
+
output: t("loginHint")
|
|
3523
3391
|
};
|
|
3524
3392
|
case "/profile":
|
|
3525
3393
|
return {
|
|
@@ -3535,16 +3403,12 @@ Usage: /skill attach <ref> | /skill detach <ref> | /skill clear` : "No skills at
|
|
|
3535
3403
|
case "/version":
|
|
3536
3404
|
return {
|
|
3537
3405
|
nextState: state,
|
|
3538
|
-
output:
|
|
3539
|
-
Update this install with: nolo update
|
|
3540
|
-
If repo-local output differs, publish/install the latest npm package first.`
|
|
3406
|
+
output: t("versionInfo", state.cliVersion || t("versionUnknown"))
|
|
3541
3407
|
};
|
|
3542
3408
|
default:
|
|
3543
3409
|
return {
|
|
3544
3410
|
nextState: state,
|
|
3545
|
-
output:
|
|
3546
|
-
|
|
3547
|
-
${renderTuiHelp()}`
|
|
3411
|
+
output: t("unknownCommand", command) + renderTuiHelp()
|
|
3548
3412
|
};
|
|
3549
3413
|
}
|
|
3550
3414
|
}
|
|
@@ -3562,19 +3426,23 @@ function brightnessFromRgb(r, g, b) {
|
|
|
3562
3426
|
const luma = (0.299 * r + 0.587 * g + 0.114 * b) / 255;
|
|
3563
3427
|
return luma >= 0.5 ? "light" : "dark";
|
|
3564
3428
|
}
|
|
3565
|
-
function
|
|
3429
|
+
function parseOsc11Background(reply) {
|
|
3566
3430
|
const match = reply.match(OSC11_REPLY_RE);
|
|
3567
3431
|
if (!match) return null;
|
|
3568
|
-
|
|
3432
|
+
const channels = [
|
|
3569
3433
|
componentToByte(match[1]),
|
|
3570
3434
|
componentToByte(match[2]),
|
|
3571
3435
|
componentToByte(match[3])
|
|
3572
|
-
|
|
3436
|
+
];
|
|
3437
|
+
return {
|
|
3438
|
+
brightness: brightnessFromRgb(channels[0], channels[1], channels[2]),
|
|
3439
|
+
hex: channels.map((v) => v.toString(16).padStart(2, "0").toUpperCase()).join("")
|
|
3440
|
+
};
|
|
3573
3441
|
}
|
|
3574
3442
|
function isTerminalDevice(stream) {
|
|
3575
3443
|
return stream instanceof ReadStream;
|
|
3576
3444
|
}
|
|
3577
|
-
async function
|
|
3445
|
+
async function detectTerminalBackground(args = {}) {
|
|
3578
3446
|
const stdin = args.stdin ?? process.stdin;
|
|
3579
3447
|
const stdout = args.stdout ?? process.stdout;
|
|
3580
3448
|
const timeoutMs = args.timeoutMs ?? 100;
|
|
@@ -3601,7 +3469,7 @@ async function detectTerminalBrightness(args = {}) {
|
|
|
3601
3469
|
};
|
|
3602
3470
|
const onData = (chunk) => {
|
|
3603
3471
|
buffer += chunk.toString("latin1");
|
|
3604
|
-
const parsed =
|
|
3472
|
+
const parsed = parseOsc11Background(buffer);
|
|
3605
3473
|
if (parsed) finish(parsed);
|
|
3606
3474
|
else if (buffer.length > 256) finish(null);
|
|
3607
3475
|
};
|
|
@@ -3945,7 +3813,7 @@ function buildHistoryLines(history, contentWidth) {
|
|
|
3945
3813
|
const reset = "\x1B[39m";
|
|
3946
3814
|
return `${accent}\u276F${reset} ${content}`;
|
|
3947
3815
|
}
|
|
3948
|
-
const highlighted =
|
|
3816
|
+
const highlighted = colorEnabled ? formatAssistantDisplay(content) : stripAnsi(formatAssistantDisplay(content));
|
|
3949
3817
|
const rawLines = highlighted.split("\n");
|
|
3950
3818
|
const styledLines = rawLines.map((line, idx) => {
|
|
3951
3819
|
if (idx === 0 && !line.startsWith("[nolo]")) {
|
|
@@ -4072,6 +3940,30 @@ function applyScrollAction(history, action, output, inputLines) {
|
|
|
4072
3940
|
}
|
|
4073
3941
|
|
|
4074
3942
|
// packages/cli/tui/tuiRawInput.ts
|
|
3943
|
+
function normalizePasteNewlines(text) {
|
|
3944
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3945
|
+
}
|
|
3946
|
+
var altScreenOn = /* @__PURE__ */ new WeakMap();
|
|
3947
|
+
function outputIsTty2(output) {
|
|
3948
|
+
return Boolean(output.isTTY);
|
|
3949
|
+
}
|
|
3950
|
+
function enterAltScreen(output) {
|
|
3951
|
+
if (!outputIsTty2(output)) return false;
|
|
3952
|
+
if (altScreenOn.get(output)) return false;
|
|
3953
|
+
altScreenOn.set(output, true);
|
|
3954
|
+
output.write("\x1B[?1049h");
|
|
3955
|
+
return true;
|
|
3956
|
+
}
|
|
3957
|
+
function leaveAltScreen(output) {
|
|
3958
|
+
if (!outputIsTty2(output)) return false;
|
|
3959
|
+
if (!altScreenOn.get(output)) return false;
|
|
3960
|
+
altScreenOn.set(output, false);
|
|
3961
|
+
output.write("\x1B[?1049l");
|
|
3962
|
+
return true;
|
|
3963
|
+
}
|
|
3964
|
+
function isAltScreenOn(output) {
|
|
3965
|
+
return Boolean(altScreenOn.get(output));
|
|
3966
|
+
}
|
|
4075
3967
|
function styleCollapsedPastePlaceholders(text, colorEnabled) {
|
|
4076
3968
|
if (!colorEnabled || !text.includes("[paste #")) return text;
|
|
4077
3969
|
COLLAPSED_PASTE_PLACEHOLDER_RE.lastIndex = 0;
|
|
@@ -4102,6 +3994,8 @@ function createNoopFixedInput() {
|
|
|
4102
3994
|
getInputLines: () => 1,
|
|
4103
3995
|
isPaused: () => false,
|
|
4104
3996
|
setMouseEnabled() {
|
|
3997
|
+
},
|
|
3998
|
+
setAltScreenEnabled() {
|
|
4105
3999
|
}
|
|
4106
4000
|
};
|
|
4107
4001
|
}
|
|
@@ -4145,7 +4039,7 @@ function createFixedInput(output, config) {
|
|
|
4145
4039
|
sections.push(fitAnsiLine(line.replace(/\r?\n/g, " "), cols));
|
|
4146
4040
|
}
|
|
4147
4041
|
const promptRaw = t("promptLabel");
|
|
4148
|
-
const promptWidth =
|
|
4042
|
+
const promptWidth = displayWidth(promptRaw);
|
|
4149
4043
|
const prompt = colorEnabled ? `${themeColorSequence("accent")}${promptRaw}\x1B[39m` : promptRaw;
|
|
4150
4044
|
const contentWidth = Math.max(1, cols - promptWidth);
|
|
4151
4045
|
const logicalLines = buffer.length === 0 ? [""] : buffer.split("\n");
|
|
@@ -4181,7 +4075,7 @@ function createFixedInput(output, config) {
|
|
|
4181
4075
|
if (targetPos <= charOffset + rowLen || j === rows.length - 1 && i === logicalLines.length - 1) {
|
|
4182
4076
|
const subOffset = Math.max(0, Math.min(rowLen, targetPos - charOffset));
|
|
4183
4077
|
const subStr = rowText.slice(0, subOffset);
|
|
4184
|
-
cursorCol = promptWidth +
|
|
4078
|
+
cursorCol = promptWidth + displayWidth(subStr);
|
|
4185
4079
|
cursorRow = inputRows;
|
|
4186
4080
|
cursorFound = true;
|
|
4187
4081
|
}
|
|
@@ -4198,10 +4092,15 @@ function createFixedInput(output, config) {
|
|
|
4198
4092
|
};
|
|
4199
4093
|
const repaintAt = (buffer, cursorPos) => {
|
|
4200
4094
|
const { text, lines, cursorCol, cursorRow } = renderInputArea(buffer, cursorPos);
|
|
4095
|
+
let linesChanged = false;
|
|
4201
4096
|
if (lines !== inputLines) {
|
|
4202
4097
|
inputLines = lines;
|
|
4098
|
+
linesChanged = true;
|
|
4203
4099
|
}
|
|
4204
4100
|
setScrollRegion(inputLines);
|
|
4101
|
+
if (linesChanged) {
|
|
4102
|
+
config.onInputLinesChange?.(inputLines);
|
|
4103
|
+
}
|
|
4205
4104
|
const startRow = getRows() - inputLines + 1;
|
|
4206
4105
|
write(`\x1B[${startRow};1H`);
|
|
4207
4106
|
write("\x1B[J");
|
|
@@ -4249,8 +4148,7 @@ function createFixedInput(output, config) {
|
|
|
4249
4148
|
disable() {
|
|
4250
4149
|
disableMouse();
|
|
4251
4150
|
resetScrollRegion();
|
|
4252
|
-
|
|
4253
|
-
write(`\x1B[${rows};1H\x1B[2K\x1B[${Math.max(1, rows - 1)};1H`);
|
|
4151
|
+
leaveAltScreen(output);
|
|
4254
4152
|
},
|
|
4255
4153
|
getInputLines: () => inputLines,
|
|
4256
4154
|
isPaused: () => paused,
|
|
@@ -4261,6 +4159,13 @@ function createFixedInput(output, config) {
|
|
|
4261
4159
|
} else {
|
|
4262
4160
|
write("\x1B[?1000l\x1B[?1006l");
|
|
4263
4161
|
}
|
|
4162
|
+
},
|
|
4163
|
+
setAltScreenEnabled(enabled) {
|
|
4164
|
+
if (enabled) {
|
|
4165
|
+
enterAltScreen(output);
|
|
4166
|
+
} else {
|
|
4167
|
+
leaveAltScreen(output);
|
|
4168
|
+
}
|
|
4264
4169
|
}
|
|
4265
4170
|
};
|
|
4266
4171
|
}
|
|
@@ -4310,9 +4215,27 @@ function isIncompleteTail(input, start) {
|
|
|
4310
4215
|
}
|
|
4311
4216
|
return false;
|
|
4312
4217
|
}
|
|
4313
|
-
var PASTE_START = "\x1B[
|
|
4314
|
-
var PASTE_END = "\x1B[
|
|
4315
|
-
function
|
|
4218
|
+
var PASTE_START = "\x1B[200~";
|
|
4219
|
+
var PASTE_END = "\x1B[201~";
|
|
4220
|
+
function findBracketedPasteEnd(input, contentStart) {
|
|
4221
|
+
return input.indexOf(PASTE_END, contentStart);
|
|
4222
|
+
}
|
|
4223
|
+
function emitPlainRunAsTokens(run) {
|
|
4224
|
+
if (run.length === 0) return [];
|
|
4225
|
+
if (shouldCollapsePaste(normalizePasteNewlines(run))) {
|
|
4226
|
+
return [`${PASTE_TOKEN_PREFIX}${run}`];
|
|
4227
|
+
}
|
|
4228
|
+
const tokens = [];
|
|
4229
|
+
for (let index = 0; index < run.length; ) {
|
|
4230
|
+
const codePoint = run.codePointAt(index);
|
|
4231
|
+
if (codePoint === void 0) break;
|
|
4232
|
+
const value = String.fromCodePoint(codePoint);
|
|
4233
|
+
tokens.push(value);
|
|
4234
|
+
index += value.length;
|
|
4235
|
+
}
|
|
4236
|
+
return tokens;
|
|
4237
|
+
}
|
|
4238
|
+
function splitRawInputWithTail(input, options) {
|
|
4316
4239
|
const tokens = [];
|
|
4317
4240
|
for (let index = 0; index < input.length; ) {
|
|
4318
4241
|
if (isIncompleteTail(input, index)) {
|
|
@@ -4320,15 +4243,17 @@ function splitRawInputWithTail(input) {
|
|
|
4320
4243
|
}
|
|
4321
4244
|
if (input.startsWith(PASTE_START, index)) {
|
|
4322
4245
|
const contentStart = index + PASTE_START.length;
|
|
4323
|
-
const endPos = input
|
|
4246
|
+
const endPos = findBracketedPasteEnd(input, contentStart);
|
|
4324
4247
|
if (endPos !== -1) {
|
|
4325
4248
|
const payload = input.slice(contentStart, endPos);
|
|
4326
4249
|
tokens.push(`${PASTE_TOKEN_PREFIX}${payload}`);
|
|
4327
4250
|
index = endPos + PASTE_END.length;
|
|
4328
|
-
} else {
|
|
4251
|
+
} else if (options?.forceCompleteOpenPaste) {
|
|
4329
4252
|
const payload = input.slice(contentStart);
|
|
4330
4253
|
tokens.push(`${PASTE_TOKEN_PREFIX}${payload}`);
|
|
4331
4254
|
index = input.length;
|
|
4255
|
+
} else {
|
|
4256
|
+
return { tokens, tail: input.slice(index) };
|
|
4332
4257
|
}
|
|
4333
4258
|
continue;
|
|
4334
4259
|
}
|
|
@@ -4353,63 +4278,121 @@ function splitRawInputWithTail(input) {
|
|
|
4353
4278
|
index += csi.length;
|
|
4354
4279
|
continue;
|
|
4355
4280
|
}
|
|
4356
|
-
const
|
|
4357
|
-
|
|
4358
|
-
const
|
|
4359
|
-
|
|
4360
|
-
|
|
4281
|
+
const nextEsc = input.indexOf("\x1B", index);
|
|
4282
|
+
const runEnd = nextEsc === -1 ? input.length : nextEsc;
|
|
4283
|
+
const run = input.slice(index, runEnd);
|
|
4284
|
+
if (run.length === 0) {
|
|
4285
|
+
const codePoint = input.codePointAt(index);
|
|
4286
|
+
if (codePoint === void 0) break;
|
|
4287
|
+
const value = String.fromCodePoint(codePoint);
|
|
4288
|
+
tokens.push(value);
|
|
4289
|
+
index += value.length;
|
|
4290
|
+
continue;
|
|
4291
|
+
}
|
|
4292
|
+
tokens.push(...emitPlainRunAsTokens(run));
|
|
4293
|
+
index = runEnd;
|
|
4361
4294
|
}
|
|
4362
4295
|
return { tokens, tail: "" };
|
|
4363
4296
|
}
|
|
4364
4297
|
function splitRawInput(input) {
|
|
4365
|
-
const { tokens, tail } = splitRawInputWithTail(input
|
|
4298
|
+
const { tokens, tail } = splitRawInputWithTail(input, {
|
|
4299
|
+
forceCompleteOpenPaste: true
|
|
4300
|
+
});
|
|
4366
4301
|
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];
|
|
4302
|
+
return [...tokens, ...emitPlainRunAsTokens(tail)];
|
|
4376
4303
|
}
|
|
4377
4304
|
function createRawInputDecoder(onToken, options) {
|
|
4378
4305
|
const decoder = new TextDecoder("utf-8", { fatal: false, ignoreBOM: true });
|
|
4379
4306
|
let pendingBuffer = "";
|
|
4380
4307
|
let timer = null;
|
|
4381
4308
|
const timeoutMs = options?.escTimeoutMs ?? 15;
|
|
4309
|
+
const unmarkedPasteDebounceMs = options?.unmarkedPasteDebounceMs ?? 40;
|
|
4382
4310
|
const clearTimer = () => {
|
|
4383
4311
|
if (timer !== null) {
|
|
4384
4312
|
clearTimeout(timer);
|
|
4385
4313
|
timer = null;
|
|
4386
4314
|
}
|
|
4387
4315
|
};
|
|
4388
|
-
const
|
|
4316
|
+
const emitCodePoints = (text) => {
|
|
4317
|
+
for (let index = 0; index < text.length; ) {
|
|
4318
|
+
const codePoint = text.codePointAt(index);
|
|
4319
|
+
if (codePoint === void 0) break;
|
|
4320
|
+
const value = String.fromCodePoint(codePoint);
|
|
4321
|
+
onToken(value);
|
|
4322
|
+
index += value.length;
|
|
4323
|
+
}
|
|
4324
|
+
};
|
|
4325
|
+
const flushPlainPending = () => {
|
|
4389
4326
|
clearTimer();
|
|
4390
|
-
if (pendingBuffer.length
|
|
4391
|
-
|
|
4392
|
-
|
|
4393
|
-
|
|
4394
|
-
|
|
4395
|
-
|
|
4327
|
+
if (pendingBuffer.length === 0) return;
|
|
4328
|
+
const text = pendingBuffer;
|
|
4329
|
+
pendingBuffer = "";
|
|
4330
|
+
for (const token of emitPlainRunAsTokens(text)) {
|
|
4331
|
+
onToken(token);
|
|
4332
|
+
}
|
|
4333
|
+
};
|
|
4334
|
+
const flushEscPending = (forceCompleteOpenPaste) => {
|
|
4335
|
+
clearTimer();
|
|
4336
|
+
if (pendingBuffer.length === 0) return;
|
|
4337
|
+
const textToFlush = pendingBuffer;
|
|
4338
|
+
pendingBuffer = "";
|
|
4339
|
+
const { tokens, tail } = splitRawInputWithTail(textToFlush, {
|
|
4340
|
+
forceCompleteOpenPaste
|
|
4341
|
+
});
|
|
4342
|
+
for (const token of tokens) {
|
|
4343
|
+
onToken(token);
|
|
4344
|
+
}
|
|
4345
|
+
if (!tail) return;
|
|
4346
|
+
if (forceCompleteOpenPaste) {
|
|
4347
|
+
emitCodePoints(tail);
|
|
4348
|
+
return;
|
|
4396
4349
|
}
|
|
4350
|
+
pendingBuffer = tail;
|
|
4397
4351
|
};
|
|
4398
4352
|
const decodeFn = (chunk) => {
|
|
4399
4353
|
clearTimer();
|
|
4400
4354
|
const bytes = typeof chunk === "string" ? Buffer.from(chunk, "utf8") : chunk;
|
|
4401
4355
|
const text = decoder.decode(bytes, { stream: true });
|
|
4402
4356
|
pendingBuffer += text;
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4357
|
+
if (pendingBuffer.startsWith(PASTE_START)) {
|
|
4358
|
+
const endPos = findBracketedPasteEnd(
|
|
4359
|
+
pendingBuffer,
|
|
4360
|
+
PASTE_START.length
|
|
4361
|
+
);
|
|
4362
|
+
if (endPos === -1) return;
|
|
4363
|
+
const { tokens, tail } = splitRawInputWithTail(pendingBuffer);
|
|
4364
|
+
pendingBuffer = tail;
|
|
4365
|
+
for (const token of tokens) onToken(token);
|
|
4366
|
+
if (pendingBuffer.startsWith(PASTE_START)) return;
|
|
4367
|
+
}
|
|
4368
|
+
if (pendingBuffer.includes("\x1B")) {
|
|
4369
|
+
const { tokens, tail } = splitRawInputWithTail(pendingBuffer);
|
|
4370
|
+
pendingBuffer = tail;
|
|
4371
|
+
for (const token of tokens) onToken(token);
|
|
4372
|
+
if (pendingBuffer.startsWith(PASTE_START)) return;
|
|
4373
|
+
if (pendingBuffer.length > 0) {
|
|
4374
|
+
timer = setTimeout(() => flushEscPending(true), timeoutMs);
|
|
4375
|
+
}
|
|
4376
|
+
return;
|
|
4377
|
+
}
|
|
4378
|
+
if (shouldCollapsePaste(normalizePasteNewlines(pendingBuffer))) {
|
|
4379
|
+
timer = setTimeout(flushPlainPending, unmarkedPasteDebounceMs);
|
|
4380
|
+
return;
|
|
4407
4381
|
}
|
|
4408
|
-
if (pendingBuffer.
|
|
4409
|
-
|
|
4382
|
+
if (!pendingBuffer.includes("\n") && !pendingBuffer.includes("\r")) {
|
|
4383
|
+
emitCodePoints(pendingBuffer);
|
|
4384
|
+
pendingBuffer = "";
|
|
4385
|
+
return;
|
|
4410
4386
|
}
|
|
4387
|
+
timer = setTimeout(flushPlainPending, unmarkedPasteDebounceMs);
|
|
4388
|
+
};
|
|
4389
|
+
decodeFn.flush = () => {
|
|
4390
|
+
if (pendingBuffer.startsWith(PASTE_START) || pendingBuffer.includes("\x1B")) {
|
|
4391
|
+
flushEscPending(true);
|
|
4392
|
+
return;
|
|
4393
|
+
}
|
|
4394
|
+
flushPlainPending();
|
|
4411
4395
|
};
|
|
4412
|
-
decodeFn.flush = flush;
|
|
4413
4396
|
decodeFn.destroy = () => {
|
|
4414
4397
|
clearTimer();
|
|
4415
4398
|
pendingBuffer = "";
|
|
@@ -4419,12 +4402,66 @@ function createRawInputDecoder(onToken, options) {
|
|
|
4419
4402
|
|
|
4420
4403
|
// packages/cli/tui/readlineWorkspace.ts
|
|
4421
4404
|
var AGENTS_MD_MAX_BYTES = 8192;
|
|
4405
|
+
var altScreenRestoreOutput = null;
|
|
4406
|
+
var altScreenHandlersInstalled = false;
|
|
4407
|
+
var preExistingSignalListeners = {};
|
|
4408
|
+
var SIGNAL_EXIT_CODE = {
|
|
4409
|
+
SIGINT: 130,
|
|
4410
|
+
SIGTERM: 143,
|
|
4411
|
+
SIGHUP: 129
|
|
4412
|
+
};
|
|
4413
|
+
var restoreAltScreen = () => {
|
|
4414
|
+
try {
|
|
4415
|
+
if (altScreenRestoreOutput) leaveAltScreen(altScreenRestoreOutput);
|
|
4416
|
+
} catch {
|
|
4417
|
+
}
|
|
4418
|
+
};
|
|
4419
|
+
function installAltScreenRestoreHandlers(output) {
|
|
4420
|
+
altScreenRestoreOutput = output;
|
|
4421
|
+
if (altScreenHandlersInstalled) return;
|
|
4422
|
+
altScreenHandlersInstalled = true;
|
|
4423
|
+
process.on("exit", restoreAltScreen);
|
|
4424
|
+
for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) {
|
|
4425
|
+
const existing = process.listeners(sig);
|
|
4426
|
+
preExistingSignalListeners[sig] = [...existing];
|
|
4427
|
+
const handler = () => {
|
|
4428
|
+
restoreAltScreen();
|
|
4429
|
+
const others = process.listeners(sig).filter((fn) => fn !== handler);
|
|
4430
|
+
if (others.length === 0) {
|
|
4431
|
+
process.exit(SIGNAL_EXIT_CODE[sig] ?? 128 + 1);
|
|
4432
|
+
return;
|
|
4433
|
+
}
|
|
4434
|
+
};
|
|
4435
|
+
process.prependListener(sig, handler);
|
|
4436
|
+
}
|
|
4437
|
+
process.on("uncaughtException", (err) => {
|
|
4438
|
+
restoreAltScreen();
|
|
4439
|
+
try {
|
|
4440
|
+
process.stderr.write(
|
|
4441
|
+
`uncaughtException: ${err?.stack ?? String(err)}
|
|
4442
|
+
`
|
|
4443
|
+
);
|
|
4444
|
+
} catch {
|
|
4445
|
+
}
|
|
4446
|
+
process.exit(1);
|
|
4447
|
+
});
|
|
4448
|
+
process.on("unhandledRejection", (reason) => {
|
|
4449
|
+
restoreAltScreen();
|
|
4450
|
+
try {
|
|
4451
|
+
const text = reason instanceof Error ? reason.stack ?? String(reason) : String(reason);
|
|
4452
|
+
process.stderr.write(`unhandledRejection: ${text}
|
|
4453
|
+
`);
|
|
4454
|
+
} catch {
|
|
4455
|
+
}
|
|
4456
|
+
process.exit(1);
|
|
4457
|
+
});
|
|
4458
|
+
}
|
|
4422
4459
|
function readAgentsMdBlock(cwd) {
|
|
4423
4460
|
for (const name of ["AGENTS.md", "CLAUDE.md"]) {
|
|
4424
|
-
const filePath =
|
|
4425
|
-
if (
|
|
4461
|
+
const filePath = join2(cwd, name);
|
|
4462
|
+
if (existsSync3(filePath)) {
|
|
4426
4463
|
try {
|
|
4427
|
-
let content =
|
|
4464
|
+
let content = readFileSync2(filePath, "utf8").trim();
|
|
4428
4465
|
if (!content) continue;
|
|
4429
4466
|
if (Buffer.byteLength(content, "utf8") > AGENTS_MD_MAX_BYTES) {
|
|
4430
4467
|
content = Buffer.from(content, "utf8").subarray(0, AGENTS_MD_MAX_BYTES).toString("utf8") + "\n\n<!-- AGENTS.md truncated -->";
|
|
@@ -4539,6 +4576,18 @@ async function runAgentChat(scriptDir, state, message, env, output, agentRunner
|
|
|
4539
4576
|
if (skillDiscoveryBlock) {
|
|
4540
4577
|
extraContextBlocks.push(skillDiscoveryBlock);
|
|
4541
4578
|
}
|
|
4579
|
+
const agentsMdMarker = "--- \u9879\u76EE\u6307\u4EE4\uFF08";
|
|
4580
|
+
const contextBlockScopes = [];
|
|
4581
|
+
for (const block of extraContextBlocks) {
|
|
4582
|
+
if (block.startsWith(agentsMdMarker)) {
|
|
4583
|
+
contextBlockScopes.push({ content: block, cacheScope: "session" });
|
|
4584
|
+
}
|
|
4585
|
+
}
|
|
4586
|
+
for (const block of extraContextBlocks) {
|
|
4587
|
+
if (!block.startsWith(agentsMdMarker)) {
|
|
4588
|
+
contextBlockScopes.push({ content: block, cacheScope: "turn" });
|
|
4589
|
+
}
|
|
4590
|
+
}
|
|
4542
4591
|
const result = await agentRunner({
|
|
4543
4592
|
agentName: effectiveAgentName,
|
|
4544
4593
|
agentKey: effectiveAgentKey,
|
|
@@ -4559,9 +4608,17 @@ async function runAgentChat(scriptDir, state, message, env, output, agentRunner
|
|
|
4559
4608
|
...options.confirmDestructiveAction ? { confirmDestructiveAction: options.confirmDestructiveAction } : {},
|
|
4560
4609
|
...options.requestUserChoice ? { requestUserChoice: options.requestUserChoice } : {},
|
|
4561
4610
|
...options.abortSignal ? { abortSignal: options.abortSignal } : {},
|
|
4611
|
+
...options.pastedTextStore?.items.size ? {
|
|
4612
|
+
pastedTextStore: options.pastedTextStore,
|
|
4613
|
+
localRuntimeAdapterFactory: (factoryEnv, factoryOptions) => createCliLocalRuntimeAdapter({
|
|
4614
|
+
env: factoryEnv,
|
|
4615
|
+
cwd: factoryOptions?.cwd ?? state.cwd,
|
|
4616
|
+
pastedTextStore: options.pastedTextStore
|
|
4617
|
+
})
|
|
4618
|
+
} : {},
|
|
4562
4619
|
...options.activityReporter ? { activityReporter: options.activityReporter } : {},
|
|
4563
4620
|
...skillAllowedTools !== void 0 ? { allowedToolNames: skillAllowedTools } : {},
|
|
4564
|
-
...
|
|
4621
|
+
...contextBlockScopes.length > 0 ? { contextBlockScopes } : {}
|
|
4565
4622
|
});
|
|
4566
4623
|
if (!continueId && result.dialogId && effectiveAgentKey !== state.agentKey) {
|
|
4567
4624
|
autoRouteByDialog.set(result.dialogId, {
|
|
@@ -4569,7 +4626,14 @@ async function runAgentChat(scriptDir, state, message, env, output, agentRunner
|
|
|
4569
4626
|
agentName: effectiveAgentName
|
|
4570
4627
|
});
|
|
4571
4628
|
}
|
|
4572
|
-
return
|
|
4629
|
+
return {
|
|
4630
|
+
...result,
|
|
4631
|
+
contextWindow: resolveAgentContextWindow({
|
|
4632
|
+
agentKey: effectiveAgentKey,
|
|
4633
|
+
agentName: effectiveAgentName,
|
|
4634
|
+
autoRouteDefault: env.NOLO_AUTO_ROUTE !== "0"
|
|
4635
|
+
})
|
|
4636
|
+
};
|
|
4573
4637
|
}
|
|
4574
4638
|
function waitForActionGate(rl, input, output, gate, spawnRunner) {
|
|
4575
4639
|
const commandPayload = gate.kind === "handoff" ? readCommandActionGatePayload(gate.payload) : null;
|
|
@@ -4755,13 +4819,18 @@ async function startTuiWorkspace(options) {
|
|
|
4755
4819
|
const spawnRunner = options.spawnRunner ?? spawnProcess;
|
|
4756
4820
|
const selfUpdater = options.selfUpdater ?? ((target) => runSelfUpdate({ output: target }));
|
|
4757
4821
|
if (output.isTTY) {
|
|
4758
|
-
output
|
|
4822
|
+
enterAltScreen(output);
|
|
4823
|
+
installAltScreenRestoreHandlers(output);
|
|
4824
|
+
output.write("\x1B[2J\x1B[H");
|
|
4759
4825
|
}
|
|
4760
|
-
const detected = await
|
|
4826
|
+
const detected = await detectTerminalBackground({
|
|
4761
4827
|
stdin: input,
|
|
4762
4828
|
stdout: output
|
|
4763
4829
|
});
|
|
4764
|
-
if (detected)
|
|
4830
|
+
if (detected) {
|
|
4831
|
+
setActiveBrightness(detected.brightness);
|
|
4832
|
+
setActiveTerminalBaseHex(detected.hex);
|
|
4833
|
+
}
|
|
4765
4834
|
const bannerColumns = output.columns;
|
|
4766
4835
|
output.write(renderWelcome(state, 0, 0, bannerColumns));
|
|
4767
4836
|
let fixedInput = createNoopFixedInput();
|
|
@@ -4769,9 +4838,14 @@ async function startTuiWorkspace(options) {
|
|
|
4769
4838
|
let cursorPos = 0;
|
|
4770
4839
|
const pasteStore = createCollapsedPasteStore();
|
|
4771
4840
|
let activeTurnAbort = null;
|
|
4841
|
+
let forcedStop = false;
|
|
4842
|
+
let forcedStopEpoch = 0;
|
|
4843
|
+
let turnEpoch = 0;
|
|
4844
|
+
let activeTurnEpoch = 0;
|
|
4772
4845
|
const activityIndicator = createActivityIndicator({
|
|
4773
4846
|
isTurnActive: () => activeTurnAbort !== null,
|
|
4774
4847
|
fallbackLabel: () => `${state.agentName} -> working`,
|
|
4848
|
+
stoppingLabel: () => t("turnStopping"),
|
|
4775
4849
|
onRepaint: () => {
|
|
4776
4850
|
if (fixedInput.active && !fixedInput.isPaused()) {
|
|
4777
4851
|
output.write("\x1B[?2026h\x1B[?25l");
|
|
@@ -4831,9 +4905,16 @@ async function startTuiWorkspace(options) {
|
|
|
4831
4905
|
paintSyncedFrame();
|
|
4832
4906
|
}, 0);
|
|
4833
4907
|
};
|
|
4908
|
+
let syncingLayout = false;
|
|
4834
4909
|
const renderHistoryToOutput = () => {
|
|
4835
4910
|
if (fixedInput.isPaused()) return;
|
|
4836
|
-
|
|
4911
|
+
if (syncingLayout) return;
|
|
4912
|
+
syncingLayout = true;
|
|
4913
|
+
try {
|
|
4914
|
+
renderHistory(output, history, fixedInput.getInputLines());
|
|
4915
|
+
} finally {
|
|
4916
|
+
syncingLayout = false;
|
|
4917
|
+
}
|
|
4837
4918
|
};
|
|
4838
4919
|
const readLatestAssistantReply = () => {
|
|
4839
4920
|
const lastReply = [...history.turns].reverse().find((turn) => turn.role === "assistant")?.content;
|
|
@@ -4872,6 +4953,9 @@ ${t("copyViewHint")}
|
|
|
4872
4953
|
};
|
|
4873
4954
|
let modalOwnsKeyboard = false;
|
|
4874
4955
|
const runOneAgentTurn = async (message, imageUrls, actionGateHandler, confirmDestructiveAction) => {
|
|
4956
|
+
forcedStop = false;
|
|
4957
|
+
turnEpoch += 1;
|
|
4958
|
+
const myEpoch = turnEpoch;
|
|
4875
4959
|
history.followBottom = true;
|
|
4876
4960
|
startTurn(history, "user");
|
|
4877
4961
|
appendToCurrentTurn(history, message);
|
|
@@ -4901,6 +4985,7 @@ ${t("copyViewHint")}
|
|
|
4901
4985
|
} : void 0;
|
|
4902
4986
|
try {
|
|
4903
4987
|
activeTurnAbort = new AbortController();
|
|
4988
|
+
activeTurnEpoch = myEpoch;
|
|
4904
4989
|
const runResult = await runAgentChat(
|
|
4905
4990
|
options.scriptDir,
|
|
4906
4991
|
state,
|
|
@@ -4914,10 +4999,27 @@ ${t("copyViewHint")}
|
|
|
4914
4999
|
...confirmDestructiveAction ? { confirmDestructiveAction } : {},
|
|
4915
5000
|
...requestUserChoice ? { requestUserChoice } : {},
|
|
4916
5001
|
abortSignal: activeTurnAbort.signal,
|
|
5002
|
+
pastedTextStore: pasteStore,
|
|
4917
5003
|
explicitAgentSwitch,
|
|
4918
5004
|
activityReporter
|
|
4919
5005
|
}
|
|
4920
5006
|
);
|
|
5007
|
+
const wasForceStopped = forcedStopEpoch === myEpoch;
|
|
5008
|
+
if (wasForceStopped) {
|
|
5009
|
+
if (runResult.dialogId || runResult.turnTokens) {
|
|
5010
|
+
const nextDialogKey = runResult.dialogId ? runResult.dialogId === state.dialogId && state.dialogKey ? state.dialogKey : state.dialogOwnerId ? `dialog-${state.dialogOwnerId}-${runResult.dialogId}` : void 0 : state.dialogKey;
|
|
5011
|
+
state = {
|
|
5012
|
+
...state,
|
|
5013
|
+
...runResult.dialogId ? {
|
|
5014
|
+
dialogId: runResult.dialogId,
|
|
5015
|
+
dialogKey: nextDialogKey,
|
|
5016
|
+
dialogLabel: runResult.dialogId
|
|
5017
|
+
} : {},
|
|
5018
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {}
|
|
5019
|
+
};
|
|
5020
|
+
}
|
|
5021
|
+
return { ok: false, aborted: true };
|
|
5022
|
+
}
|
|
4921
5023
|
const wasAborted = activeTurnAbort.signal.aborted;
|
|
4922
5024
|
activeTurnAbort = null;
|
|
4923
5025
|
explicitAgentSwitch = false;
|
|
@@ -4928,9 +5030,13 @@ ${t("copyViewHint")}
|
|
|
4928
5030
|
if (fixedInput.active) fixedInput.repaint(buffer);
|
|
4929
5031
|
}
|
|
4930
5032
|
if (wasAborted) {
|
|
4931
|
-
|
|
5033
|
+
if (runResult.pendingToolName) {
|
|
5034
|
+
emitCommandOutput(t("turnStoppedToolPending", runResult.pendingToolName));
|
|
5035
|
+
} else {
|
|
5036
|
+
emitCommandOutput(t("turnStopped"));
|
|
5037
|
+
}
|
|
4932
5038
|
}
|
|
4933
|
-
if (runResult.dialogId || runResult.turnTokens) {
|
|
5039
|
+
if (runResult.dialogId || runResult.turnTokens || runResult.contextWindow) {
|
|
4934
5040
|
const nextDialogKey = runResult.dialogId ? runResult.dialogId === state.dialogId && state.dialogKey ? state.dialogKey : state.dialogOwnerId ? `dialog-${state.dialogOwnerId}-${runResult.dialogId}` : void 0 : state.dialogKey;
|
|
4935
5041
|
state = {
|
|
4936
5042
|
...state,
|
|
@@ -4939,11 +5045,20 @@ ${t("copyViewHint")}
|
|
|
4939
5045
|
dialogKey: nextDialogKey,
|
|
4940
5046
|
dialogLabel: runResult.dialogId
|
|
4941
5047
|
} : {},
|
|
4942
|
-
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {}
|
|
5048
|
+
...runResult.turnTokens ? { turnTokens: runResult.turnTokens } : {},
|
|
5049
|
+
...runResult.contextWindow ? { contextWindow: runResult.contextWindow } : {}
|
|
4943
5050
|
};
|
|
4944
5051
|
}
|
|
4945
|
-
if (!wasAborted && runResult.exitCode !== 0
|
|
4946
|
-
|
|
5052
|
+
if (!wasAborted && runResult.exitCode !== 0) {
|
|
5053
|
+
if (isBalanceExhaustedError(runResult.localError) && runResult.dialogId) {
|
|
5054
|
+
emitCommandOutput(t("balanceExhaustedHint"));
|
|
5055
|
+
} else if (isQuotaExhaustedError(runResult.localError)) {
|
|
5056
|
+
emitCommandOutput(t("quotaExhaustedHint"));
|
|
5057
|
+
} else if (runResult.dialogId) {
|
|
5058
|
+
emitCommandOutput(t("dialogPreservedHint"));
|
|
5059
|
+
} else {
|
|
5060
|
+
emitCommandOutput(t("dialogNotSavedHint"));
|
|
5061
|
+
}
|
|
4947
5062
|
}
|
|
4948
5063
|
return { ok: !wasAborted, aborted: wasAborted };
|
|
4949
5064
|
} finally {
|
|
@@ -4998,6 +5113,7 @@ ${t("copyViewHint")}
|
|
|
4998
5113
|
}
|
|
4999
5114
|
if (result.action?.type === "exit") return true;
|
|
5000
5115
|
if (result.action?.type === "clear") {
|
|
5116
|
+
clearCollapsedPasteStore(pasteStore);
|
|
5001
5117
|
history.turns.length = 0;
|
|
5002
5118
|
history.currentRole = null;
|
|
5003
5119
|
history.currentContent = "";
|
|
@@ -5068,7 +5184,18 @@ ${t("copyViewHint")}
|
|
|
5068
5184
|
...state,
|
|
5069
5185
|
agentName: pickResult.name,
|
|
5070
5186
|
agentKey: pickResult.key,
|
|
5071
|
-
contextWindow:
|
|
5187
|
+
contextWindow: resolveAgentContextWindow({
|
|
5188
|
+
agentKey: pickResult.key,
|
|
5189
|
+
agentName: pickResult.name,
|
|
5190
|
+
model: pickResult.model,
|
|
5191
|
+
autoRouteDefault: (options.env ?? process.env).NOLO_AUTO_ROUTE !== "0"
|
|
5192
|
+
}),
|
|
5193
|
+
estimatedContextTokens: estimateDefaultCliContextTokens({
|
|
5194
|
+
cwd: state.cwd,
|
|
5195
|
+
agentKey: pickResult.key,
|
|
5196
|
+
agentName: pickResult.name,
|
|
5197
|
+
model: pickResult.model
|
|
5198
|
+
})
|
|
5072
5199
|
};
|
|
5073
5200
|
if (state.dialogId) autoRouteByDialog.delete(state.dialogId);
|
|
5074
5201
|
explicitAgentSwitch = true;
|
|
@@ -5100,6 +5227,16 @@ ${t("copyViewHint")}
|
|
|
5100
5227
|
if (result.action?.type === "set-mouse") {
|
|
5101
5228
|
fixedInput.setMouseEnabled(result.action.enabled);
|
|
5102
5229
|
}
|
|
5230
|
+
if (result.action?.type === "set-altscreen") {
|
|
5231
|
+
if (result.action.enabled) {
|
|
5232
|
+
enterAltScreen(output);
|
|
5233
|
+
installAltScreenRestoreHandlers(output);
|
|
5234
|
+
} else {
|
|
5235
|
+
leaveAltScreen(output);
|
|
5236
|
+
}
|
|
5237
|
+
renderHistoryToOutput();
|
|
5238
|
+
fixedInput.repaint(buffer);
|
|
5239
|
+
}
|
|
5103
5240
|
if (result.action?.type === "copy-view") {
|
|
5104
5241
|
const opened = await openCopyView();
|
|
5105
5242
|
if (!opened) emitCommandOutput(t("copyNothing"));
|
|
@@ -5143,14 +5280,7 @@ ${t("copyViewHint")}
|
|
|
5143
5280
|
dialog: pickResult.dialog,
|
|
5144
5281
|
env: options.env ?? process.env
|
|
5145
5282
|
});
|
|
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
|
-
);
|
|
5283
|
+
const restored = loadedTurns.slice(-MAX_TUI_HISTORY_TURNS);
|
|
5154
5284
|
history.turns.length = 0;
|
|
5155
5285
|
history.turns.push(...restored);
|
|
5156
5286
|
history.currentRole = null;
|
|
@@ -5164,6 +5294,7 @@ ${t("copyViewHint")}
|
|
|
5164
5294
|
dialogLabel: pickResult.dialog.id,
|
|
5165
5295
|
turnTokens: void 0
|
|
5166
5296
|
};
|
|
5297
|
+
clearCollapsedPasteStore(pasteStore);
|
|
5167
5298
|
emitCommandOutput(
|
|
5168
5299
|
`${t("resumedDialogPrefix")}: ${pickResult.dialog.title} (${pickResult.dialog.id})`
|
|
5169
5300
|
);
|
|
@@ -5323,6 +5454,9 @@ ${err.message}` : ""}`
|
|
|
5323
5454
|
const oneLine = text.replace(/\r?\n/g, " \u23CE ");
|
|
5324
5455
|
return dimCliText(` \u2937 ${i + 1}. ${oneLine}`, colorEnabled);
|
|
5325
5456
|
});
|
|
5457
|
+
},
|
|
5458
|
+
onInputLinesChange: () => {
|
|
5459
|
+
renderHistoryToOutput();
|
|
5326
5460
|
}
|
|
5327
5461
|
});
|
|
5328
5462
|
fixedInput.init();
|
|
@@ -5345,6 +5479,7 @@ ${err.message}` : ""}`
|
|
|
5345
5479
|
const finish = () => {
|
|
5346
5480
|
if (done) return;
|
|
5347
5481
|
done = true;
|
|
5482
|
+
clearCollapsedPasteStore(pasteStore);
|
|
5348
5483
|
resizeTarget.off?.("resize", onResize);
|
|
5349
5484
|
input.off("data", onData);
|
|
5350
5485
|
onData.destroy();
|
|
@@ -5372,10 +5507,25 @@ ${err.message}` : ""}`
|
|
|
5372
5507
|
return;
|
|
5373
5508
|
}
|
|
5374
5509
|
if (busyLock && sequence === "\x1B" && activeTurnAbort) {
|
|
5510
|
+
if (activityIndicator.isStopping()) {
|
|
5511
|
+
forcedStop = true;
|
|
5512
|
+
forcedStopEpoch = activeTurnEpoch;
|
|
5513
|
+
activityIndicator.stop();
|
|
5514
|
+
activeTurnAbort.abort();
|
|
5515
|
+
activeTurnAbort = null;
|
|
5516
|
+
activeTurnEpoch = 0;
|
|
5517
|
+
busy = false;
|
|
5518
|
+
emitCommandOutput(t("forceStopped"));
|
|
5519
|
+
flushPendingRender();
|
|
5520
|
+
renderHistoryToOutput();
|
|
5521
|
+
if (fixedInput.active) fixedInput.repaint(buffer);
|
|
5522
|
+
return;
|
|
5523
|
+
}
|
|
5375
5524
|
const stopBinding = chatQueueBinding;
|
|
5376
5525
|
if (stopBinding && stopBinding.queueLength() > 0) {
|
|
5377
5526
|
stopBinding.preemptForStop();
|
|
5378
5527
|
}
|
|
5528
|
+
activityIndicator.markStopping();
|
|
5379
5529
|
activeTurnAbort.abort();
|
|
5380
5530
|
return;
|
|
5381
5531
|
}
|
|
@@ -5402,7 +5552,10 @@ ${err.message}` : ""}`
|
|
|
5402
5552
|
return;
|
|
5403
5553
|
}
|
|
5404
5554
|
if (result.submit !== void 0) {
|
|
5405
|
-
const submittedText =
|
|
5555
|
+
const submittedText = replaceCollapsedPastesWithReferences(
|
|
5556
|
+
result.submit,
|
|
5557
|
+
pasteStore
|
|
5558
|
+
);
|
|
5406
5559
|
if (busyLock) {
|
|
5407
5560
|
const trimmedText = submittedText.trim();
|
|
5408
5561
|
const busySlashCommand = trimmedText.split(/\s+/)[0]?.toLowerCase();
|
|
@@ -5427,7 +5580,7 @@ ${hint}` : hint;
|
|
|
5427
5580
|
`);
|
|
5428
5581
|
}
|
|
5429
5582
|
}
|
|
5430
|
-
|
|
5583
|
+
releaseCollapsedPasteReferences(submittedText, pasteStore);
|
|
5431
5584
|
buffer = "";
|
|
5432
5585
|
cursorPos2 = 0;
|
|
5433
5586
|
if (fixedInput.active) fixedInput.repaint(buffer, cursorPos2);
|
|
@@ -5466,7 +5619,6 @@ ${hint}` : hint;
|
|
|
5466
5619
|
isRunning: true
|
|
5467
5620
|
});
|
|
5468
5621
|
if (decision.kind === "queue-text") {
|
|
5469
|
-
clearCollapsedPasteStore(pasteStore);
|
|
5470
5622
|
binding.enqueue(decision.text);
|
|
5471
5623
|
buffer = "";
|
|
5472
5624
|
cursorPos2 = 0;
|
|
@@ -5541,7 +5693,6 @@ ${err.message}` : ""}`
|
|
|
5541
5693
|
return;
|
|
5542
5694
|
}
|
|
5543
5695
|
}
|
|
5544
|
-
clearCollapsedPasteStore(pasteStore);
|
|
5545
5696
|
busy = true;
|
|
5546
5697
|
buffer = "";
|
|
5547
5698
|
cursorPos2 = 0;
|
|
@@ -5664,9 +5815,13 @@ export {
|
|
|
5664
5815
|
createNoopFixedInput,
|
|
5665
5816
|
createRawInputDecoder,
|
|
5666
5817
|
createTurnHistory,
|
|
5667
|
-
|
|
5818
|
+
displayWidth,
|
|
5819
|
+
enterAltScreen,
|
|
5668
5820
|
finalizeCurrentTurn,
|
|
5669
5821
|
fitAnsiLine,
|
|
5822
|
+
installAltScreenRestoreHandlers,
|
|
5823
|
+
isAltScreenOn,
|
|
5824
|
+
leaveAltScreen,
|
|
5670
5825
|
padOrTruncateToWidth,
|
|
5671
5826
|
parseScrollAction,
|
|
5672
5827
|
renderHistory,
|