reasonix 0.47.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -26
- package/README.zh-CN.md +5 -26
- package/dist/cli/{acp-GEOAKSTU.js → acp-4ROCGYNH.js} +17 -17
- package/dist/cli/{chat-YTPATMMG.js → chat-GZNB5625.js} +24 -24
- package/dist/cli/{chunk-BQ6HC66J.js → chunk-2QSTA2QV.js} +3 -13
- package/dist/cli/chunk-2QSTA2QV.js.map +1 -0
- package/dist/cli/{chunk-DQ6K5ZQ7.js → chunk-3WGTGXO4.js} +2 -2
- package/dist/cli/{chunk-6QC5RQLE.js → chunk-5OHHAQ4W.js} +2 -2
- package/dist/cli/{chunk-XMHP7BEE.js → chunk-6MZTZO7A.js} +514 -791
- package/dist/cli/chunk-6MZTZO7A.js.map +1 -0
- package/dist/cli/chunk-7M4YYMKW.js +5198 -0
- package/dist/cli/chunk-7M4YYMKW.js.map +1 -0
- package/dist/cli/{chunk-KYQVQ5X4.js → chunk-B5CZL2SE.js} +9 -4
- package/dist/cli/chunk-B5CZL2SE.js.map +1 -0
- package/dist/cli/chunk-CDVSFSAK.js +17732 -0
- package/dist/cli/chunk-CDVSFSAK.js.map +1 -0
- package/dist/cli/{chunk-TRWHTFG7.js → chunk-DOWEOA6E.js} +2 -2
- package/dist/cli/chunk-EMMENC4O.js +831 -0
- package/dist/cli/chunk-EMMENC4O.js.map +1 -0
- package/dist/cli/{chunk-TDHXB2ER.js → chunk-H4CCXMDD.js} +2 -2
- package/dist/cli/{chunk-T5A7EY6B.js → chunk-HR5NBKEM.js} +2 -2
- package/dist/cli/{chunk-CNG32VAB.js → chunk-I4M5QJNL.js} +2 -2
- package/dist/cli/{chunk-5QCB62C4.js → chunk-J2TQAWOM.js} +135 -18
- package/dist/cli/{chunk-5QCB62C4.js.map → chunk-J2TQAWOM.js.map} +1 -1
- package/dist/cli/{chunk-DN4B5S6Y.js → chunk-JMDE6IO3.js} +2 -2
- package/dist/cli/{chunk-4MFCAZ2W.js → chunk-MOJYKO2A.js} +3 -3
- package/dist/cli/{chunk-HUILPCYX.js → chunk-MRZG4GBF.js} +3 -3
- package/dist/cli/{chunk-GH7DC2Y5.js → chunk-NMQSUNLB.js} +2 -2
- package/dist/cli/{chunk-ZXSCAODE.js → chunk-OB4BUJBL.js} +67 -2
- package/dist/cli/chunk-OB4BUJBL.js.map +1 -0
- package/dist/cli/{chunk-QCFLPSPH.js → chunk-OG5JANQ4.js} +2 -2
- package/dist/cli/{chunk-JBH5RM7X.js → chunk-OPYALNTT.js} +326 -55
- package/dist/cli/chunk-OPYALNTT.js.map +1 -0
- package/dist/cli/{chunk-CCJAP7G3.js → chunk-RUDBUHO4.js} +2 -2
- package/dist/cli/{chunk-2XY77LW7.js → chunk-S2RMQULY.js} +56 -24
- package/dist/cli/chunk-S2RMQULY.js.map +1 -0
- package/dist/cli/{chunk-DWPAKZTY.js → chunk-TE5UIIFL.js} +2 -2
- package/dist/cli/{chunk-KVZZ5U75.js → chunk-V4Y732RQ.js} +2 -2
- package/dist/cli/{chunk-TRSAHHCL.js → chunk-WZGNXR6E.js} +3 -3
- package/dist/cli/chunk-WZGNXR6E.js.map +1 -0
- package/dist/cli/{chunk-NRQ5UP5T.js → chunk-YW63N3ZR.js} +116 -28
- package/dist/cli/chunk-YW63N3ZR.js.map +1 -0
- package/dist/cli/{code-Q4NRVEDG.js → code-PMPJWXEO.js} +30 -31
- package/dist/cli/code-PMPJWXEO.js.map +1 -0
- package/dist/cli/{commands-4CDI4GFM.js → commands-QS6TG4G3.js} +4 -4
- package/dist/cli/{commit-GW7LDQP5.js → commit-XPRSKUBF.js} +3 -3
- package/dist/cli/{desktop-EG6P5SF2.js → desktop-562OPWIU.js} +461 -43
- package/dist/cli/desktop-562OPWIU.js.map +1 -0
- package/dist/cli/{diff-VI2YX4FN.js → diff-I6W4AUWJ.js} +8 -8
- package/dist/cli/{doctor-CQTTZP27.js → doctor-6XVZKT4U.js} +9 -9
- package/dist/cli/index.js +52 -40
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-J2UCD4RZ.js → mcp-7W7ANO2Y.js} +2 -2
- package/dist/cli/{mcp-browse-GSX34JEK.js → mcp-browse-LA4I4YIZ.js} +2 -2
- package/dist/cli/{mcp-inspect-RRFYF4ZV.js → mcp-inspect-LWXXU7BY.js} +2 -2
- package/dist/cli/{prompt-5TQPIVHV.js → prompt-RKZD4X6Y.js} +3 -3
- package/dist/cli/{replay-MJCEMODU.js → replay-2X7MVXOI.js} +8 -8
- package/dist/cli/{run-P4D5VDYE.js → run-TPKXIJ27.js} +13 -13
- package/dist/cli/{server-C25JNNZV.js → server-NHQ3QXOZ.js} +15 -14
- package/dist/cli/{server-C25JNNZV.js.map → server-NHQ3QXOZ.js.map} +1 -1
- package/dist/cli/{sessions-QIONZJQ6.js → sessions-2A4DGSHA.js} +12 -12
- package/dist/cli/{setup-NLQ6G5G4.js → setup-GOLP7J4C.js} +5 -5
- package/dist/cli/{stats-DFZEXHP4.js → stats-CGDAFDKI.js} +6 -6
- package/dist/cli/{version-GR3X3MPI.js → version-FIL4ZFOS.js} +12 -12
- package/dist/grammars/tree-sitter-go.wasm +0 -0
- package/dist/grammars/tree-sitter-java.wasm +0 -0
- package/dist/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/grammars/tree-sitter-python.wasm +0 -0
- package/dist/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/grammars/web-tree-sitter.wasm +0 -0
- package/dist/index.d.ts +38 -10
- package/dist/index.js +488 -87
- package/dist/index.js.map +1 -1
- package/package.json +13 -4
- package/dist/cli/chunk-2XY77LW7.js.map +0 -1
- package/dist/cli/chunk-6CRPCJAU.js +0 -3141
- package/dist/cli/chunk-6CRPCJAU.js.map +0 -1
- package/dist/cli/chunk-BQ6HC66J.js.map +0 -1
- package/dist/cli/chunk-JBH5RM7X.js.map +0 -1
- package/dist/cli/chunk-KYQVQ5X4.js.map +0 -1
- package/dist/cli/chunk-NRQ5UP5T.js.map +0 -1
- package/dist/cli/chunk-TRSAHHCL.js.map +0 -1
- package/dist/cli/chunk-XD6P7AFH.js +0 -375
- package/dist/cli/chunk-XD6P7AFH.js.map +0 -1
- package/dist/cli/chunk-XMHP7BEE.js.map +0 -1
- package/dist/cli/chunk-YFP3MYMY.js +0 -323
- package/dist/cli/chunk-YFP3MYMY.js.map +0 -1
- package/dist/cli/chunk-ZXSCAODE.js.map +0 -1
- package/dist/cli/code-Q4NRVEDG.js.map +0 -1
- package/dist/cli/desktop-EG6P5SF2.js.map +0 -1
- /package/dist/cli/{acp-GEOAKSTU.js.map → acp-4ROCGYNH.js.map} +0 -0
- /package/dist/cli/{chat-YTPATMMG.js.map → chat-GZNB5625.js.map} +0 -0
- /package/dist/cli/{chunk-DQ6K5ZQ7.js.map → chunk-3WGTGXO4.js.map} +0 -0
- /package/dist/cli/{chunk-6QC5RQLE.js.map → chunk-5OHHAQ4W.js.map} +0 -0
- /package/dist/cli/{chunk-TRWHTFG7.js.map → chunk-DOWEOA6E.js.map} +0 -0
- /package/dist/cli/{chunk-TDHXB2ER.js.map → chunk-H4CCXMDD.js.map} +0 -0
- /package/dist/cli/{chunk-T5A7EY6B.js.map → chunk-HR5NBKEM.js.map} +0 -0
- /package/dist/cli/{chunk-CNG32VAB.js.map → chunk-I4M5QJNL.js.map} +0 -0
- /package/dist/cli/{chunk-DN4B5S6Y.js.map → chunk-JMDE6IO3.js.map} +0 -0
- /package/dist/cli/{chunk-4MFCAZ2W.js.map → chunk-MOJYKO2A.js.map} +0 -0
- /package/dist/cli/{chunk-HUILPCYX.js.map → chunk-MRZG4GBF.js.map} +0 -0
- /package/dist/cli/{chunk-GH7DC2Y5.js.map → chunk-NMQSUNLB.js.map} +0 -0
- /package/dist/cli/{chunk-QCFLPSPH.js.map → chunk-OG5JANQ4.js.map} +0 -0
- /package/dist/cli/{chunk-CCJAP7G3.js.map → chunk-RUDBUHO4.js.map} +0 -0
- /package/dist/cli/{chunk-DWPAKZTY.js.map → chunk-TE5UIIFL.js.map} +0 -0
- /package/dist/cli/{chunk-KVZZ5U75.js.map → chunk-V4Y732RQ.js.map} +0 -0
- /package/dist/cli/{commands-4CDI4GFM.js.map → commands-QS6TG4G3.js.map} +0 -0
- /package/dist/cli/{commit-GW7LDQP5.js.map → commit-XPRSKUBF.js.map} +0 -0
- /package/dist/cli/{diff-VI2YX4FN.js.map → diff-I6W4AUWJ.js.map} +0 -0
- /package/dist/cli/{doctor-CQTTZP27.js.map → doctor-6XVZKT4U.js.map} +0 -0
- /package/dist/cli/{mcp-J2UCD4RZ.js.map → mcp-7W7ANO2Y.js.map} +0 -0
- /package/dist/cli/{mcp-browse-GSX34JEK.js.map → mcp-browse-LA4I4YIZ.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-RRFYF4ZV.js.map → mcp-inspect-LWXXU7BY.js.map} +0 -0
- /package/dist/cli/{prompt-5TQPIVHV.js.map → prompt-RKZD4X6Y.js.map} +0 -0
- /package/dist/cli/{replay-MJCEMODU.js.map → replay-2X7MVXOI.js.map} +0 -0
- /package/dist/cli/{run-P4D5VDYE.js.map → run-TPKXIJ27.js.map} +0 -0
- /package/dist/cli/{sessions-QIONZJQ6.js.map → sessions-2A4DGSHA.js.map} +0 -0
- /package/dist/cli/{setup-NLQ6G5G4.js.map → setup-GOLP7J4C.js.map} +0 -0
- /package/dist/cli/{stats-DFZEXHP4.js.map → stats-CGDAFDKI.js.map} +0 -0
- /package/dist/cli/{version-GR3X3MPI.js.map → version-FIL4ZFOS.js.map} +0 -0
|
@@ -8,18 +8,23 @@ import {
|
|
|
8
8
|
loadOverlay
|
|
9
9
|
} from "./chunk-JMBMLOBP.js";
|
|
10
10
|
import {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
QQChannel,
|
|
12
|
+
createMcpRuntime,
|
|
13
|
+
formatQQAccessSummary,
|
|
14
|
+
formatQQModeLabel,
|
|
15
|
+
formatQQSetupPrompt,
|
|
16
|
+
formatQQSetupWaiting
|
|
17
|
+
} from "./chunk-EMMENC4O.js";
|
|
13
18
|
import {
|
|
14
19
|
Eventizer,
|
|
15
20
|
autoResolveVerdict,
|
|
16
21
|
registerSkillTools,
|
|
17
22
|
shouldAutoResolveCheckpoint
|
|
18
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-OB4BUJBL.js";
|
|
19
24
|
import {
|
|
20
25
|
formatMcpLifecycleEvent,
|
|
21
26
|
formatMcpSlowToast
|
|
22
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-3WGTGXO4.js";
|
|
23
28
|
import {
|
|
24
29
|
buildTransportFromSpec
|
|
25
30
|
} from "./chunk-EQATK2L2.js";
|
|
@@ -31,6 +36,7 @@ import {
|
|
|
31
36
|
import {
|
|
32
37
|
CacheFirstLoop,
|
|
33
38
|
ImmutablePrefix,
|
|
39
|
+
SHARED_SUBAGENT_SINK,
|
|
34
40
|
ToolRegistry,
|
|
35
41
|
applyEditBlocks,
|
|
36
42
|
detectAtPicker,
|
|
@@ -53,27 +59,24 @@ import {
|
|
|
53
59
|
toWholeFileEditBlock,
|
|
54
60
|
walkFilesStream,
|
|
55
61
|
webFetch
|
|
56
|
-
} from "./chunk-
|
|
62
|
+
} from "./chunk-OPYALNTT.js";
|
|
57
63
|
import {
|
|
58
64
|
openTranscriptFile,
|
|
59
65
|
recordFromLoopEvent,
|
|
60
66
|
writeRecord
|
|
61
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-MRZG4GBF.js";
|
|
62
68
|
import {
|
|
63
69
|
McpClient
|
|
64
70
|
} from "./chunk-HIYTRCSW.js";
|
|
65
71
|
import {
|
|
66
72
|
MemoryStore,
|
|
67
73
|
effectivePriority
|
|
68
|
-
} from "./chunk-
|
|
69
|
-
import {
|
|
70
|
-
wrapper_default
|
|
71
|
-
} from "./chunk-FEZK652I.js";
|
|
74
|
+
} from "./chunk-2QSTA2QV.js";
|
|
72
75
|
import {
|
|
73
76
|
KeystrokeProvider,
|
|
74
77
|
SingleSelect,
|
|
75
78
|
useKeystroke
|
|
76
|
-
} from "./chunk-
|
|
79
|
+
} from "./chunk-DOWEOA6E.js";
|
|
77
80
|
import {
|
|
78
81
|
COLOR,
|
|
79
82
|
GLYPH,
|
|
@@ -81,7 +84,7 @@ import {
|
|
|
81
84
|
ThemeProvider,
|
|
82
85
|
useColor,
|
|
83
86
|
useThemeTokens
|
|
84
|
-
} from "./chunk-
|
|
87
|
+
} from "./chunk-RUDBUHO4.js";
|
|
85
88
|
import {
|
|
86
89
|
Box_default,
|
|
87
90
|
Text,
|
|
@@ -101,20 +104,20 @@ import {
|
|
|
101
104
|
} from "./chunk-LGEKVMMV.js";
|
|
102
105
|
import {
|
|
103
106
|
runDoctorChecks
|
|
104
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-S2RMQULY.js";
|
|
105
108
|
import {
|
|
106
109
|
countTokensBounded
|
|
107
110
|
} from "./chunk-6OWJV3YW.js";
|
|
108
111
|
import {
|
|
109
112
|
DeepSeekClient,
|
|
110
113
|
pickPrimaryBalance
|
|
111
|
-
} from "./chunk-
|
|
114
|
+
} from "./chunk-TE5UIIFL.js";
|
|
112
115
|
import {
|
|
113
116
|
loadDotenv
|
|
114
117
|
} from "./chunk-2UQP6H6T.js";
|
|
115
118
|
import {
|
|
116
119
|
renderDashboard
|
|
117
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-MOJYKO2A.js";
|
|
118
121
|
import {
|
|
119
122
|
MANUAL_UPDATE_COMMANDS,
|
|
120
123
|
planUpdate
|
|
@@ -140,7 +143,7 @@ import {
|
|
|
140
143
|
restoreCheckpoint,
|
|
141
144
|
savePlanState,
|
|
142
145
|
suggestSlashCommands
|
|
143
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-B5CZL2SE.js";
|
|
144
147
|
import {
|
|
145
148
|
eventLogPath,
|
|
146
149
|
openEventSink
|
|
@@ -158,7 +161,7 @@ import {
|
|
|
158
161
|
pauseGate,
|
|
159
162
|
runCommand,
|
|
160
163
|
tildeify
|
|
161
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-WZGNXR6E.js";
|
|
162
165
|
import {
|
|
163
166
|
PROJECT_MEMORY_FILE,
|
|
164
167
|
SkillStore,
|
|
@@ -173,7 +176,7 @@ import {
|
|
|
173
176
|
loadHooks,
|
|
174
177
|
projectSettingsPath,
|
|
175
178
|
runHooks
|
|
176
|
-
} from "./chunk-
|
|
179
|
+
} from "./chunk-NMQSUNLB.js";
|
|
177
180
|
import {
|
|
178
181
|
deleteSession,
|
|
179
182
|
detectGitBranch,
|
|
@@ -196,12 +199,12 @@ import {
|
|
|
196
199
|
appendUsage,
|
|
197
200
|
defaultUsageLogPath,
|
|
198
201
|
readUsageLog
|
|
199
|
-
} from "./chunk-
|
|
202
|
+
} from "./chunk-JMDE6IO3.js";
|
|
200
203
|
import {
|
|
201
204
|
DEEPSEEK_CONTEXT_TOKENS,
|
|
202
205
|
DEFAULT_CONTEXT_TOKENS,
|
|
203
206
|
pricingFor
|
|
204
|
-
} from "./chunk-
|
|
207
|
+
} from "./chunk-OG5JANQ4.js";
|
|
205
208
|
import {
|
|
206
209
|
getLanguage,
|
|
207
210
|
getSupportedLanguages,
|
|
@@ -210,7 +213,7 @@ import {
|
|
|
210
213
|
setLanguage,
|
|
211
214
|
t,
|
|
212
215
|
tObj
|
|
213
|
-
} from "./chunk-
|
|
216
|
+
} from "./chunk-YW63N3ZR.js";
|
|
214
217
|
import {
|
|
215
218
|
CARD,
|
|
216
219
|
FG,
|
|
@@ -221,9 +224,7 @@ import {
|
|
|
221
224
|
addSkillPath,
|
|
222
225
|
balanceColor,
|
|
223
226
|
clearProjectShellAllowed,
|
|
224
|
-
decideQQAccess,
|
|
225
227
|
defaultConfigPath,
|
|
226
|
-
describeQQAccess,
|
|
227
228
|
editModeHintShown,
|
|
228
229
|
formatBalance,
|
|
229
230
|
formatCost,
|
|
@@ -234,6 +235,9 @@ import {
|
|
|
234
235
|
loadBaseUrl,
|
|
235
236
|
loadEditMode,
|
|
236
237
|
loadEngineeringLifecycleMode,
|
|
238
|
+
loadExaApiKey,
|
|
239
|
+
loadMetasoApiKey,
|
|
240
|
+
loadPerplexityApiKey,
|
|
237
241
|
loadProjectShellAllowed,
|
|
238
242
|
loadQQConfig,
|
|
239
243
|
loadRateLimit,
|
|
@@ -241,19 +245,17 @@ import {
|
|
|
241
245
|
loadRecentWorkspaces,
|
|
242
246
|
loadResolvedSkillPaths,
|
|
243
247
|
loadSkillPaths,
|
|
248
|
+
loadTavilyApiKey,
|
|
244
249
|
loadTheme,
|
|
245
250
|
loadWorkspaceDir,
|
|
246
251
|
markEditModeHintShown,
|
|
247
252
|
markMouseClipboardHintShown,
|
|
248
253
|
mouseClipboardHintShown,
|
|
249
254
|
normalizeMcpConfig,
|
|
250
|
-
normalizeQQAllowlist,
|
|
251
|
-
normalizeQQOpenId,
|
|
252
255
|
parseMcpSpec,
|
|
253
256
|
pushRecentWorkspace,
|
|
254
257
|
readConfig,
|
|
255
258
|
redactKey,
|
|
256
|
-
redactQQOpenId,
|
|
257
259
|
removeProjectShellAllowed,
|
|
258
260
|
removeSkillPath,
|
|
259
261
|
resolveThemePreference,
|
|
@@ -266,7 +268,7 @@ import {
|
|
|
266
268
|
webSearchEndpoint,
|
|
267
269
|
webSearchEngine,
|
|
268
270
|
writeConfig
|
|
269
|
-
} from "./chunk-
|
|
271
|
+
} from "./chunk-CDVSFSAK.js";
|
|
270
272
|
import {
|
|
271
273
|
VERSION,
|
|
272
274
|
compareVersions,
|
|
@@ -535,7 +537,7 @@ var require_core = __commonJS({
|
|
|
535
537
|
return match && match.index === 0;
|
|
536
538
|
}
|
|
537
539
|
var BACKREF_RE = /\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;
|
|
538
|
-
function
|
|
540
|
+
function join7(regexps, separator = "|") {
|
|
539
541
|
let numCaptures = 0;
|
|
540
542
|
return regexps.map((regex) => {
|
|
541
543
|
numCaptures += 1;
|
|
@@ -839,7 +841,7 @@ var require_core = __commonJS({
|
|
|
839
841
|
this.exec = () => null;
|
|
840
842
|
}
|
|
841
843
|
const terminators = this.regexes.map((el) => el[1]);
|
|
842
|
-
this.matcherRe = langRe(
|
|
844
|
+
this.matcherRe = langRe(join7(terminators), true);
|
|
843
845
|
this.lastIndex = 0;
|
|
844
846
|
}
|
|
845
847
|
/** @param {string} s */
|
|
@@ -35859,8 +35861,8 @@ var require_tokenizer = __commonJS({
|
|
|
35859
35861
|
this.consumedAfterSnapshot--;
|
|
35860
35862
|
this.preprocessor.retreat();
|
|
35861
35863
|
}
|
|
35862
|
-
_reconsumeInState(
|
|
35863
|
-
this.state =
|
|
35864
|
+
_reconsumeInState(state2) {
|
|
35865
|
+
this.state = state2;
|
|
35864
35866
|
this._unconsume();
|
|
35865
35867
|
}
|
|
35866
35868
|
_consumeSequenceIfMatch(pattern, startCp, caseSensitive) {
|
|
@@ -38482,10 +38484,10 @@ var require_tokenizer_mixin = __commonJS({
|
|
|
38482
38484
|
}
|
|
38483
38485
|
};
|
|
38484
38486
|
Object.keys(Tokenizer.MODE).forEach((modeName) => {
|
|
38485
|
-
const
|
|
38486
|
-
methods[
|
|
38487
|
+
const state2 = Tokenizer.MODE[modeName];
|
|
38488
|
+
methods[state2] = function(cp) {
|
|
38487
38489
|
mxn.ctLoc = mxn._getCurrentLocation();
|
|
38488
|
-
orig[
|
|
38490
|
+
orig[state2].call(this, cp);
|
|
38489
38491
|
};
|
|
38490
38492
|
});
|
|
38491
38493
|
return methods;
|
|
@@ -44320,497 +44322,6 @@ var require_dist = __commonJS({
|
|
|
44320
44322
|
// src/cli/commands/chat.tsx
|
|
44321
44323
|
var import_react95 = __toESM(require_react(), 1);
|
|
44322
44324
|
|
|
44323
|
-
// src/qq/channel.ts
|
|
44324
|
-
import { mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
44325
|
-
import { homedir } from "os";
|
|
44326
|
-
import { dirname, join } from "path";
|
|
44327
|
-
|
|
44328
|
-
// src/qq/bot.ts
|
|
44329
|
-
import { EventEmitter } from "events";
|
|
44330
|
-
var TOKEN_URL = "https://bots.qq.com/app/getAppAccessToken";
|
|
44331
|
-
var BASE_URL = "https://api.sgroup.qq.com";
|
|
44332
|
-
var SANDBOX_URL = "https://sandbox.api.sgroup.qq.com";
|
|
44333
|
-
var INTENT_C2C_GROUP = 1 << 25;
|
|
44334
|
-
var MIN_HEARTBEAT_INTERVAL_MS = 5e3;
|
|
44335
|
-
var MAX_HEARTBEAT_INTERVAL_MS = 6e4;
|
|
44336
|
-
var ALLOWED_GATEWAY_HOSTS = ["api.sgroup.qq.com", "sandbox.api.sgroup.qq.com", "qq.com"];
|
|
44337
|
-
var QQBot = class extends EventEmitter {
|
|
44338
|
-
config;
|
|
44339
|
-
token = "";
|
|
44340
|
-
tokenExpiresAt = 0;
|
|
44341
|
-
ws = null;
|
|
44342
|
-
heartbeatTimer = null;
|
|
44343
|
-
seq = 0;
|
|
44344
|
-
sessionId = "";
|
|
44345
|
-
closed = false;
|
|
44346
|
-
readyReceived = false;
|
|
44347
|
-
constructor(config) {
|
|
44348
|
-
super();
|
|
44349
|
-
this.config = config;
|
|
44350
|
-
}
|
|
44351
|
-
get baseUrl() {
|
|
44352
|
-
return this.config.sandbox ? SANDBOX_URL : BASE_URL;
|
|
44353
|
-
}
|
|
44354
|
-
sanitizeHeartbeatInterval(interval) {
|
|
44355
|
-
if (typeof interval !== "number" || !Number.isFinite(interval)) {
|
|
44356
|
-
return null;
|
|
44357
|
-
}
|
|
44358
|
-
if (interval < MIN_HEARTBEAT_INTERVAL_MS) {
|
|
44359
|
-
return MIN_HEARTBEAT_INTERVAL_MS;
|
|
44360
|
-
}
|
|
44361
|
-
if (interval > MAX_HEARTBEAT_INTERVAL_MS) {
|
|
44362
|
-
return MAX_HEARTBEAT_INTERVAL_MS;
|
|
44363
|
-
}
|
|
44364
|
-
return Math.trunc(interval);
|
|
44365
|
-
}
|
|
44366
|
-
validateGatewayUrl(rawUrl) {
|
|
44367
|
-
const url = new URL(rawUrl);
|
|
44368
|
-
const trustedHost = ALLOWED_GATEWAY_HOSTS.some(
|
|
44369
|
-
(host) => url.hostname === host || url.hostname.endsWith(`.${host}`)
|
|
44370
|
-
);
|
|
44371
|
-
if (url.protocol !== "wss:" || !trustedHost || url.username || url.password || url.search || url.hash) {
|
|
44372
|
-
throw new Error(`Unexpected QQ gateway URL: ${rawUrl}`);
|
|
44373
|
-
}
|
|
44374
|
-
return url.toString();
|
|
44375
|
-
}
|
|
44376
|
-
async ensureToken() {
|
|
44377
|
-
if (this.token && Date.now() < this.tokenExpiresAt - 6e4) {
|
|
44378
|
-
return this.token;
|
|
44379
|
-
}
|
|
44380
|
-
const res = await fetch(TOKEN_URL, {
|
|
44381
|
-
method: "POST",
|
|
44382
|
-
headers: { "Content-Type": "application/json" },
|
|
44383
|
-
body: JSON.stringify({
|
|
44384
|
-
appId: this.config.appid,
|
|
44385
|
-
clientSecret: this.config.secret
|
|
44386
|
-
})
|
|
44387
|
-
});
|
|
44388
|
-
if (!res.ok) {
|
|
44389
|
-
const text = await res.text();
|
|
44390
|
-
throw new Error(`Failed to get access token (${res.status}): ${text}`);
|
|
44391
|
-
}
|
|
44392
|
-
const data = await res.json();
|
|
44393
|
-
this.token = data.access_token;
|
|
44394
|
-
this.tokenExpiresAt = Date.now() + data.expires_in * 1e3;
|
|
44395
|
-
return this.token;
|
|
44396
|
-
}
|
|
44397
|
-
async getGateway() {
|
|
44398
|
-
const token = await this.ensureToken();
|
|
44399
|
-
const res = await fetch(`${this.baseUrl}/gateway`, {
|
|
44400
|
-
headers: { Authorization: `QQBot ${token}` }
|
|
44401
|
-
});
|
|
44402
|
-
if (!res.ok) {
|
|
44403
|
-
const text = await res.text();
|
|
44404
|
-
throw new Error(`Failed to get gateway (${res.status}): ${text}`);
|
|
44405
|
-
}
|
|
44406
|
-
const data = await res.json();
|
|
44407
|
-
return this.validateGatewayUrl(data.url);
|
|
44408
|
-
}
|
|
44409
|
-
sendOp(op, data) {
|
|
44410
|
-
if (!this.ws) return;
|
|
44411
|
-
this.ws.send(JSON.stringify({ op, d: data ?? {} }));
|
|
44412
|
-
}
|
|
44413
|
-
async handlePayload(payload) {
|
|
44414
|
-
switch (payload.op) {
|
|
44415
|
-
case 10: {
|
|
44416
|
-
const d = payload.d;
|
|
44417
|
-
this.sendOp(2, {
|
|
44418
|
-
token: `QQBot ${await this.ensureToken()}`,
|
|
44419
|
-
intents: INTENT_C2C_GROUP,
|
|
44420
|
-
shard: [0, 1]
|
|
44421
|
-
});
|
|
44422
|
-
const heartbeatInterval = this.sanitizeHeartbeatInterval(d?.heartbeat_interval);
|
|
44423
|
-
if (heartbeatInterval) {
|
|
44424
|
-
this.heartbeatTimer = setInterval(() => {
|
|
44425
|
-
this.sendOp(1, this.seq || null);
|
|
44426
|
-
}, heartbeatInterval);
|
|
44427
|
-
}
|
|
44428
|
-
break;
|
|
44429
|
-
}
|
|
44430
|
-
case 0: {
|
|
44431
|
-
if (payload.s) this.seq = payload.s;
|
|
44432
|
-
if (payload.t === "READY") {
|
|
44433
|
-
const d = payload.d;
|
|
44434
|
-
this.sessionId = d.session_id;
|
|
44435
|
-
this.readyReceived = true;
|
|
44436
|
-
this.emit("online");
|
|
44437
|
-
} else if (payload.t === "C2C_MESSAGE_CREATE") {
|
|
44438
|
-
this.emit("message.private", payload.d);
|
|
44439
|
-
} else if (payload.t === "GROUP_AT_MESSAGE_CREATE") {
|
|
44440
|
-
this.emit("message.group", payload.d);
|
|
44441
|
-
}
|
|
44442
|
-
break;
|
|
44443
|
-
}
|
|
44444
|
-
case 7: {
|
|
44445
|
-
this.reconnect();
|
|
44446
|
-
break;
|
|
44447
|
-
}
|
|
44448
|
-
case 9: {
|
|
44449
|
-
this.sessionId = "";
|
|
44450
|
-
this.sendOp(2, {
|
|
44451
|
-
token: `QQBot ${await this.ensureToken()}`,
|
|
44452
|
-
intents: INTENT_C2C_GROUP,
|
|
44453
|
-
shard: [0, 1]
|
|
44454
|
-
});
|
|
44455
|
-
break;
|
|
44456
|
-
}
|
|
44457
|
-
}
|
|
44458
|
-
}
|
|
44459
|
-
async reconnect() {
|
|
44460
|
-
this.cleanup();
|
|
44461
|
-
await this.connect();
|
|
44462
|
-
}
|
|
44463
|
-
cleanup() {
|
|
44464
|
-
if (this.heartbeatTimer) {
|
|
44465
|
-
clearInterval(this.heartbeatTimer);
|
|
44466
|
-
this.heartbeatTimer = null;
|
|
44467
|
-
}
|
|
44468
|
-
if (this.ws) {
|
|
44469
|
-
this.ws.removeAllListeners();
|
|
44470
|
-
this.ws.close();
|
|
44471
|
-
this.ws = null;
|
|
44472
|
-
}
|
|
44473
|
-
}
|
|
44474
|
-
async connect() {
|
|
44475
|
-
const gatewayUrl = await this.getGateway();
|
|
44476
|
-
const token = await this.ensureToken();
|
|
44477
|
-
this.ws = new wrapper_default(gatewayUrl, {
|
|
44478
|
-
headers: {
|
|
44479
|
-
Authorization: `QQBot ${token}`,
|
|
44480
|
-
"X-Union-Appid": this.config.appid
|
|
44481
|
-
}
|
|
44482
|
-
});
|
|
44483
|
-
this.ws.on("open", () => {
|
|
44484
|
-
if (this.sessionId) {
|
|
44485
|
-
this.sendOp(6, {
|
|
44486
|
-
token: `QQBot ${this.token}`,
|
|
44487
|
-
session_id: this.sessionId,
|
|
44488
|
-
seq: this.seq
|
|
44489
|
-
});
|
|
44490
|
-
}
|
|
44491
|
-
});
|
|
44492
|
-
this.ws.on("message", (raw) => {
|
|
44493
|
-
try {
|
|
44494
|
-
const payload = JSON.parse(raw.toString());
|
|
44495
|
-
this.handlePayload(payload).catch(() => {
|
|
44496
|
-
});
|
|
44497
|
-
} catch {
|
|
44498
|
-
}
|
|
44499
|
-
});
|
|
44500
|
-
this.ws.on("close", () => {
|
|
44501
|
-
if (!this.closed) {
|
|
44502
|
-
if (this.readyReceived) {
|
|
44503
|
-
console.error("QQ WebSocket reconnecting...");
|
|
44504
|
-
this.cleanup();
|
|
44505
|
-
setTimeout(() => this.reconnect(), 3e3);
|
|
44506
|
-
} else {
|
|
44507
|
-
const msg = "QQ WebSocket closed before authentication completed \u2014 check your appId and appSecret";
|
|
44508
|
-
this.emit("bot_error", msg);
|
|
44509
|
-
this.closed = true;
|
|
44510
|
-
}
|
|
44511
|
-
}
|
|
44512
|
-
});
|
|
44513
|
-
this.ws.on("error", (err) => {
|
|
44514
|
-
const msg = `QQ WebSocket error: ${err.message}`;
|
|
44515
|
-
console.error(msg);
|
|
44516
|
-
this.emit("bot_error", msg);
|
|
44517
|
-
});
|
|
44518
|
-
}
|
|
44519
|
-
async start() {
|
|
44520
|
-
this.closed = false;
|
|
44521
|
-
this.readyReceived = false;
|
|
44522
|
-
await this.connect();
|
|
44523
|
-
}
|
|
44524
|
-
async stop() {
|
|
44525
|
-
this.closed = true;
|
|
44526
|
-
this.cleanup();
|
|
44527
|
-
}
|
|
44528
|
-
async sendPrivateMessage(openid, content, msgId, msgSeq) {
|
|
44529
|
-
const token = await this.ensureToken();
|
|
44530
|
-
const body = {
|
|
44531
|
-
content,
|
|
44532
|
-
msg_type: 0
|
|
44533
|
-
};
|
|
44534
|
-
if (msgId) body.msg_id = msgId;
|
|
44535
|
-
if (typeof msgSeq === "number" && Number.isFinite(msgSeq)) body.msg_seq = Math.trunc(msgSeq);
|
|
44536
|
-
const res = await fetch(`${this.baseUrl}/v2/users/${encodeURIComponent(openid)}/messages`, {
|
|
44537
|
-
method: "POST",
|
|
44538
|
-
headers: {
|
|
44539
|
-
Authorization: `QQBot ${token}`,
|
|
44540
|
-
"Content-Type": "application/json",
|
|
44541
|
-
"X-Union-Appid": this.config.appid
|
|
44542
|
-
},
|
|
44543
|
-
body: JSON.stringify(body)
|
|
44544
|
-
});
|
|
44545
|
-
if (!res.ok) {
|
|
44546
|
-
const text = await res.text();
|
|
44547
|
-
const msg = `QQ sendPrivateMessage failed (${res.status}): ${text}`;
|
|
44548
|
-
throw new Error(msg);
|
|
44549
|
-
}
|
|
44550
|
-
}
|
|
44551
|
-
};
|
|
44552
|
-
|
|
44553
|
-
// src/qq/strings.ts
|
|
44554
|
-
function formatQQModeLabel(codeMode) {
|
|
44555
|
-
return t(codeMode ? "handlers.qq.modeCode" : "handlers.qq.modeChat");
|
|
44556
|
-
}
|
|
44557
|
-
function formatQQAccessSummary(config) {
|
|
44558
|
-
const ownerOpenId = normalizeQQOpenId(config.ownerOpenId);
|
|
44559
|
-
const allowlist = normalizeQQAllowlist(config.allowlist) ?? [];
|
|
44560
|
-
const runtimeBoundOpenId = normalizeQQOpenId(config.runtimeBoundOpenId);
|
|
44561
|
-
if (ownerOpenId) {
|
|
44562
|
-
if (allowlist.length > 0) {
|
|
44563
|
-
return t("handlers.qq.accessOwnerWithAllowlist", {
|
|
44564
|
-
owner: redactQQOpenId(ownerOpenId),
|
|
44565
|
-
count: allowlist.length
|
|
44566
|
-
});
|
|
44567
|
-
}
|
|
44568
|
-
return t("handlers.qq.accessOwner", {
|
|
44569
|
-
owner: redactQQOpenId(ownerOpenId)
|
|
44570
|
-
});
|
|
44571
|
-
}
|
|
44572
|
-
if (allowlist.length > 0) {
|
|
44573
|
-
return t("handlers.qq.accessAllowlist", { count: allowlist.length });
|
|
44574
|
-
}
|
|
44575
|
-
if (runtimeBoundOpenId) {
|
|
44576
|
-
return t("handlers.qq.accessRuntime", {
|
|
44577
|
-
owner: redactQQOpenId(runtimeBoundOpenId)
|
|
44578
|
-
});
|
|
44579
|
-
}
|
|
44580
|
-
return t("handlers.qq.accessOpen");
|
|
44581
|
-
}
|
|
44582
|
-
function formatQQSetupPrompt(step) {
|
|
44583
|
-
return t(step === "appId" ? "handlers.qq.promptAppId" : "handlers.qq.promptAppSecret");
|
|
44584
|
-
}
|
|
44585
|
-
function formatQQSetupWaiting(step) {
|
|
44586
|
-
return t(
|
|
44587
|
-
step === "appId" ? "handlers.qq.setupWaitingAppId" : "handlers.qq.setupWaitingAppSecret"
|
|
44588
|
-
);
|
|
44589
|
-
}
|
|
44590
|
-
|
|
44591
|
-
// src/qq/channel.ts
|
|
44592
|
-
var QQ_LOCK_FILE = join(homedir(), ".reasonix", "qq-channel.pid");
|
|
44593
|
-
var QQ_MAX_CHUNK_BYTES = 1500;
|
|
44594
|
-
var NATURAL_SPLIT_MIN_FRACTION = 0.6;
|
|
44595
|
-
function fitUtf8Slice(text, maxBytes) {
|
|
44596
|
-
let end = 0;
|
|
44597
|
-
let bytes = 0;
|
|
44598
|
-
for (const char of text) {
|
|
44599
|
-
const nextBytes = Buffer.byteLength(char, "utf8");
|
|
44600
|
-
if (bytes > 0 && bytes + nextBytes > maxBytes) break;
|
|
44601
|
-
end += char.length;
|
|
44602
|
-
bytes += nextBytes;
|
|
44603
|
-
}
|
|
44604
|
-
return end > 0 ? text.slice(0, end) : text.slice(0, 1);
|
|
44605
|
-
}
|
|
44606
|
-
function pickNaturalSplit(candidate) {
|
|
44607
|
-
const minSplit = Math.floor(candidate.length * NATURAL_SPLIT_MIN_FRACTION);
|
|
44608
|
-
const splitters = ["\n\n", "\n", " "];
|
|
44609
|
-
for (const splitter of splitters) {
|
|
44610
|
-
const at = candidate.lastIndexOf(splitter);
|
|
44611
|
-
if (at >= minSplit) return at + splitter.length;
|
|
44612
|
-
}
|
|
44613
|
-
return candidate.length;
|
|
44614
|
-
}
|
|
44615
|
-
function splitQQMessage(text, maxBytes = QQ_MAX_CHUNK_BYTES) {
|
|
44616
|
-
const chunks = [];
|
|
44617
|
-
let remaining = text;
|
|
44618
|
-
while (remaining.length > 0) {
|
|
44619
|
-
if (Buffer.byteLength(remaining, "utf8") <= maxBytes) {
|
|
44620
|
-
chunks.push(remaining);
|
|
44621
|
-
break;
|
|
44622
|
-
}
|
|
44623
|
-
const candidate = fitUtf8Slice(remaining, maxBytes);
|
|
44624
|
-
const splitAt = pickNaturalSplit(candidate);
|
|
44625
|
-
chunks.push(candidate.slice(0, splitAt));
|
|
44626
|
-
remaining = remaining.slice(splitAt).trimStart();
|
|
44627
|
-
}
|
|
44628
|
-
return chunks;
|
|
44629
|
-
}
|
|
44630
|
-
var QQChannel = class {
|
|
44631
|
-
constructor(callbacks) {
|
|
44632
|
-
this.callbacks = callbacks;
|
|
44633
|
-
}
|
|
44634
|
-
callbacks;
|
|
44635
|
-
bot = null;
|
|
44636
|
-
qqUserId = null;
|
|
44637
|
-
qqMessageId = null;
|
|
44638
|
-
ownerOpenId;
|
|
44639
|
-
allowlist;
|
|
44640
|
-
runtimeBoundOpenId = null;
|
|
44641
|
-
processedMsgIds = /* @__PURE__ */ new Set();
|
|
44642
|
-
processedMsgIdQueue = [];
|
|
44643
|
-
lockAcquired = false;
|
|
44644
|
-
nextOutboundMsgSeq = 1;
|
|
44645
|
-
rememberMessage(id) {
|
|
44646
|
-
if (this.processedMsgIds.has(id)) return false;
|
|
44647
|
-
this.processedMsgIds.add(id);
|
|
44648
|
-
this.processedMsgIdQueue.push(id);
|
|
44649
|
-
if (this.processedMsgIdQueue.length > 200) {
|
|
44650
|
-
const oldest = this.processedMsgIdQueue.shift();
|
|
44651
|
-
if (oldest) this.processedMsgIds.delete(oldest);
|
|
44652
|
-
}
|
|
44653
|
-
return true;
|
|
44654
|
-
}
|
|
44655
|
-
acquireLock() {
|
|
44656
|
-
try {
|
|
44657
|
-
const existing = Number(readFileSync(QQ_LOCK_FILE, "utf8").trim());
|
|
44658
|
-
if (Number.isInteger(existing) && existing > 0 && existing !== process.pid) {
|
|
44659
|
-
try {
|
|
44660
|
-
process.kill(existing, 0);
|
|
44661
|
-
throw new Error(t("handlers.qq.lockAlreadyRunning", { pid: existing }));
|
|
44662
|
-
} catch (err) {
|
|
44663
|
-
const e = err;
|
|
44664
|
-
if (e.code !== "ESRCH") throw err;
|
|
44665
|
-
}
|
|
44666
|
-
}
|
|
44667
|
-
} catch (err) {
|
|
44668
|
-
const e = err;
|
|
44669
|
-
if (e.code !== "ENOENT") throw err;
|
|
44670
|
-
}
|
|
44671
|
-
mkdirSync(dirname(QQ_LOCK_FILE), { recursive: true });
|
|
44672
|
-
writeFileSync(QQ_LOCK_FILE, String(process.pid), "utf8");
|
|
44673
|
-
this.lockAcquired = true;
|
|
44674
|
-
}
|
|
44675
|
-
releaseLock() {
|
|
44676
|
-
if (!this.lockAcquired) return;
|
|
44677
|
-
try {
|
|
44678
|
-
const existing = Number(readFileSync(QQ_LOCK_FILE, "utf8").trim());
|
|
44679
|
-
if (existing === process.pid) unlinkSync(QQ_LOCK_FILE);
|
|
44680
|
-
} catch {
|
|
44681
|
-
}
|
|
44682
|
-
this.lockAcquired = false;
|
|
44683
|
-
}
|
|
44684
|
-
applyAccessConfig(config) {
|
|
44685
|
-
this.ownerOpenId = config.ownerOpenId;
|
|
44686
|
-
this.allowlist = config.allowlist;
|
|
44687
|
-
if (this.ownerOpenId || (this.allowlist?.length ?? 0) > 0) {
|
|
44688
|
-
this.runtimeBoundOpenId = null;
|
|
44689
|
-
}
|
|
44690
|
-
}
|
|
44691
|
-
handlePrivateMessage(msg) {
|
|
44692
|
-
const text = msg.content?.trim();
|
|
44693
|
-
if (!text) return;
|
|
44694
|
-
if (!this.rememberMessage(msg.id)) return;
|
|
44695
|
-
const openid = msg.author.user_openid;
|
|
44696
|
-
const verdict = decideQQAccess(
|
|
44697
|
-
{
|
|
44698
|
-
ownerOpenId: this.ownerOpenId,
|
|
44699
|
-
allowlist: this.allowlist,
|
|
44700
|
-
runtimeBoundOpenId: this.runtimeBoundOpenId
|
|
44701
|
-
},
|
|
44702
|
-
openid
|
|
44703
|
-
);
|
|
44704
|
-
if (!verdict.accept) {
|
|
44705
|
-
this.callbacks.onError?.(
|
|
44706
|
-
t("handlers.qq.unauthorizedMessage", {
|
|
44707
|
-
openid: redactQQOpenId(openid),
|
|
44708
|
-
access: formatQQAccessSummary({
|
|
44709
|
-
ownerOpenId: this.ownerOpenId,
|
|
44710
|
-
allowlist: this.allowlist,
|
|
44711
|
-
runtimeBoundOpenId: this.runtimeBoundOpenId
|
|
44712
|
-
})
|
|
44713
|
-
})
|
|
44714
|
-
);
|
|
44715
|
-
return;
|
|
44716
|
-
}
|
|
44717
|
-
if (verdict.bindRuntime) {
|
|
44718
|
-
this.runtimeBoundOpenId = openid;
|
|
44719
|
-
this.callbacks.onError?.(
|
|
44720
|
-
t("handlers.qq.runtimeBound", {
|
|
44721
|
-
openid: redactQQOpenId(openid)
|
|
44722
|
-
})
|
|
44723
|
-
);
|
|
44724
|
-
}
|
|
44725
|
-
this.qqUserId = openid;
|
|
44726
|
-
this.qqMessageId = msg.id;
|
|
44727
|
-
this.callbacks.onSubmitMessage(`[QQ] ${text}`);
|
|
44728
|
-
}
|
|
44729
|
-
refreshAccessConfig() {
|
|
44730
|
-
this.applyAccessConfig(loadQQConfig());
|
|
44731
|
-
}
|
|
44732
|
-
describeAccess() {
|
|
44733
|
-
return describeQQAccess({
|
|
44734
|
-
ownerOpenId: this.ownerOpenId,
|
|
44735
|
-
allowlist: this.allowlist,
|
|
44736
|
-
runtimeBoundOpenId: this.runtimeBoundOpenId
|
|
44737
|
-
});
|
|
44738
|
-
}
|
|
44739
|
-
getRuntimeBoundOpenId() {
|
|
44740
|
-
return this.runtimeBoundOpenId;
|
|
44741
|
-
}
|
|
44742
|
-
async start() {
|
|
44743
|
-
loadDotenv();
|
|
44744
|
-
this.acquireLock();
|
|
44745
|
-
const config = loadQQConfig();
|
|
44746
|
-
if (!config.appId) {
|
|
44747
|
-
this.releaseLock();
|
|
44748
|
-
throw new Error(t("handlers.qq.missingAppId"));
|
|
44749
|
-
}
|
|
44750
|
-
if (!config.appSecret) {
|
|
44751
|
-
this.releaseLock();
|
|
44752
|
-
throw new Error(t("handlers.qq.missingAppSecret"));
|
|
44753
|
-
}
|
|
44754
|
-
this.applyAccessConfig(config);
|
|
44755
|
-
const bot = new QQBot({
|
|
44756
|
-
appid: config.appId,
|
|
44757
|
-
secret: config.appSecret,
|
|
44758
|
-
sandbox: config.sandbox ?? false
|
|
44759
|
-
});
|
|
44760
|
-
bot.on("online", () => {
|
|
44761
|
-
process.stderr.write("QQ bot is online!\n");
|
|
44762
|
-
});
|
|
44763
|
-
bot.on("bot_error", (msg) => {
|
|
44764
|
-
this.callbacks.onError?.(msg);
|
|
44765
|
-
});
|
|
44766
|
-
bot.on("message.private", (msg) => {
|
|
44767
|
-
this.handlePrivateMessage(msg);
|
|
44768
|
-
});
|
|
44769
|
-
this.bot = bot;
|
|
44770
|
-
try {
|
|
44771
|
-
await bot.start();
|
|
44772
|
-
const readyOrError = await Promise.race([
|
|
44773
|
-
new Promise((resolve4) => bot.once("online", () => resolve4("ready"))),
|
|
44774
|
-
new Promise((resolve4) => bot.once("bot_error", () => resolve4("error"))),
|
|
44775
|
-
new Promise((resolve4) => setTimeout(() => resolve4("timeout"), 15e3))
|
|
44776
|
-
]);
|
|
44777
|
-
if (readyOrError === "error") {
|
|
44778
|
-
throw new Error(t("handlers.qq.authFailed"));
|
|
44779
|
-
}
|
|
44780
|
-
if (readyOrError === "timeout") {
|
|
44781
|
-
throw new Error(t("handlers.qq.readyTimeout"));
|
|
44782
|
-
}
|
|
44783
|
-
} catch (err) {
|
|
44784
|
-
this.releaseLock();
|
|
44785
|
-
throw err;
|
|
44786
|
-
}
|
|
44787
|
-
}
|
|
44788
|
-
async sendResponse(text) {
|
|
44789
|
-
if (!this.bot || !this.qqUserId) return;
|
|
44790
|
-
const chunks = splitQQMessage(text);
|
|
44791
|
-
for (let index = 0; index < chunks.length; index++) {
|
|
44792
|
-
const chunk = chunks[index];
|
|
44793
|
-
if (!chunk) continue;
|
|
44794
|
-
try {
|
|
44795
|
-
await this.bot.sendPrivateMessage(
|
|
44796
|
-
this.qqUserId,
|
|
44797
|
-
chunk,
|
|
44798
|
-
this.qqMessageId ?? void 0,
|
|
44799
|
-
this.nextOutboundMsgSeq++
|
|
44800
|
-
);
|
|
44801
|
-
} catch (err) {
|
|
44802
|
-
const msg = `QQ sendResponse chunk ${index + 1}/${chunks.length} failed: ${err.message}`;
|
|
44803
|
-
this.callbacks.onError?.(msg);
|
|
44804
|
-
break;
|
|
44805
|
-
}
|
|
44806
|
-
}
|
|
44807
|
-
}
|
|
44808
|
-
async stop() {
|
|
44809
|
-
await this.bot?.stop();
|
|
44810
|
-
this.releaseLock();
|
|
44811
|
-
}
|
|
44812
|
-
};
|
|
44813
|
-
|
|
44814
44325
|
// src/cli/ui/App.tsx
|
|
44815
44326
|
import { statSync as statSync2 } from "fs";
|
|
44816
44327
|
import { relative as relative2, resolve as resolve3 } from "path";
|
|
@@ -44927,6 +44438,27 @@ var EngineeringLifecycleRuntime = class {
|
|
|
44927
44438
|
this._completedStepIds.clear();
|
|
44928
44439
|
this._mutatedSinceLastStep = false;
|
|
44929
44440
|
}
|
|
44441
|
+
recordPlanRevised(remainingSteps) {
|
|
44442
|
+
if (this._mode === "off") return;
|
|
44443
|
+
const donePrefix = this._planSteps.filter((step) => this._completedStepIds.has(step.id));
|
|
44444
|
+
const merged = [...donePrefix];
|
|
44445
|
+
for (const step of remainingSteps) {
|
|
44446
|
+
if (this._completedStepIds.has(step.id)) continue;
|
|
44447
|
+
merged.push(step);
|
|
44448
|
+
}
|
|
44449
|
+
this._planSteps = merged;
|
|
44450
|
+
if (this._planSteps.length > 0 && this._completedStepIds.size >= this._planSteps.length) {
|
|
44451
|
+
this._state = "complete";
|
|
44452
|
+
} else {
|
|
44453
|
+
this._state = "executing";
|
|
44454
|
+
}
|
|
44455
|
+
}
|
|
44456
|
+
recordCheckpointReached() {
|
|
44457
|
+
if (this._mode === "off") return;
|
|
44458
|
+
if (this._state === "approved" || this._state === "executing") {
|
|
44459
|
+
this._state = "checkpoint";
|
|
44460
|
+
}
|
|
44461
|
+
}
|
|
44930
44462
|
recordStepCompleted(stepId) {
|
|
44931
44463
|
if (!stepId) return;
|
|
44932
44464
|
this._completedStepIds.add(stepId);
|
|
@@ -44964,9 +44496,10 @@ var EngineeringLifecycleRuntime = class {
|
|
|
44964
44496
|
if (!isHighRiskLifecycleToolCall(name, args)) return null;
|
|
44965
44497
|
if (this._state !== "approved" && this._state !== "executing") {
|
|
44966
44498
|
return JSON.stringify({
|
|
44967
|
-
error: `${name}: blocked by Engineering Lifecycle \u2014
|
|
44499
|
+
error: `${name}: blocked by Engineering Lifecycle \u2014 submit an approved plan before high-risk mutation.`,
|
|
44968
44500
|
rejectedReason: "engineering-lifecycle",
|
|
44969
|
-
state: this._state
|
|
44501
|
+
state: this._state,
|
|
44502
|
+
nextAction: "submit_plan"
|
|
44970
44503
|
});
|
|
44971
44504
|
}
|
|
44972
44505
|
this._state = "executing";
|
|
@@ -44988,9 +44521,10 @@ var EngineeringLifecycleRuntime = class {
|
|
|
44988
44521
|
const evidenceRequired = this._mutatedSinceLastStep || step?.risk === "med" || step?.risk === "high" || (step?.verification?.length ?? 0) > 0;
|
|
44989
44522
|
if (evidenceRequired && evidence.length === 0) {
|
|
44990
44523
|
return JSON.stringify({
|
|
44991
|
-
error: "mark_step_complete: evidence required
|
|
44524
|
+
error: "mark_step_complete: evidence required \u2014 add verification, diff, checkpoint, or manual evidence.",
|
|
44992
44525
|
rejectedReason: "engineering-lifecycle-evidence",
|
|
44993
|
-
stepId
|
|
44526
|
+
stepId,
|
|
44527
|
+
nextAction: "add_evidence"
|
|
44994
44528
|
});
|
|
44995
44529
|
}
|
|
44996
44530
|
return null;
|
|
@@ -45096,21 +44630,21 @@ function looksLikePathCheckout(arg) {
|
|
|
45096
44630
|
}
|
|
45097
44631
|
|
|
45098
44632
|
// src/code/pending-edits.ts
|
|
45099
|
-
import { existsSync, mkdirSync
|
|
45100
|
-
import { dirname
|
|
44633
|
+
import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "fs";
|
|
44634
|
+
import { dirname, join } from "path";
|
|
45101
44635
|
function pendingEditsPath(sessionName) {
|
|
45102
|
-
return
|
|
44636
|
+
return join(sessionsDir(), `${sanitizeName(sessionName)}.pending.json`);
|
|
45103
44637
|
}
|
|
45104
44638
|
function savePendingEdits(sessionName, blocks) {
|
|
45105
44639
|
if (!sessionName) return;
|
|
45106
44640
|
const path = pendingEditsPath(sessionName);
|
|
45107
44641
|
try {
|
|
45108
44642
|
if (blocks.length === 0) {
|
|
45109
|
-
if (existsSync(path))
|
|
44643
|
+
if (existsSync(path)) unlinkSync(path);
|
|
45110
44644
|
return;
|
|
45111
44645
|
}
|
|
45112
|
-
|
|
45113
|
-
|
|
44646
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
44647
|
+
writeFileSync(path, JSON.stringify(blocks, null, 2), "utf8");
|
|
45114
44648
|
} catch {
|
|
45115
44649
|
}
|
|
45116
44650
|
}
|
|
@@ -45120,7 +44654,7 @@ function loadPendingEdits(sessionName) {
|
|
|
45120
44654
|
if (!existsSync(path)) return null;
|
|
45121
44655
|
let raw;
|
|
45122
44656
|
try {
|
|
45123
|
-
raw =
|
|
44657
|
+
raw = readFileSync(path, "utf8");
|
|
45124
44658
|
} catch {
|
|
45125
44659
|
return null;
|
|
45126
44660
|
}
|
|
@@ -45142,7 +44676,7 @@ function clearPendingEdits(sessionName) {
|
|
|
45142
44676
|
if (!sessionName) return;
|
|
45143
44677
|
const path = pendingEditsPath(sessionName);
|
|
45144
44678
|
try {
|
|
45145
|
-
if (existsSync(path))
|
|
44679
|
+
if (existsSync(path)) unlinkSync(path);
|
|
45146
44680
|
} catch {
|
|
45147
44681
|
}
|
|
45148
44682
|
}
|
|
@@ -46005,19 +45539,19 @@ function truncateForPrompt(text, max) {
|
|
|
46005
45539
|
}
|
|
46006
45540
|
|
|
46007
45541
|
// src/slash-usage.ts
|
|
46008
|
-
import { existsSync as existsSync3, mkdirSync as
|
|
46009
|
-
import { homedir
|
|
46010
|
-
import { dirname as
|
|
45542
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync, writeFileSync as writeFileSync2 } from "fs";
|
|
45543
|
+
import { homedir } from "os";
|
|
45544
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
46011
45545
|
function slashUsagePath() {
|
|
46012
45546
|
const override = process.env.REASONIX_SLASH_USAGE_PATH;
|
|
46013
45547
|
if (override) return override;
|
|
46014
|
-
return
|
|
45548
|
+
return join2(homedir(), ".reasonix", "slash-usage.json");
|
|
46015
45549
|
}
|
|
46016
45550
|
function loadSlashUsage() {
|
|
46017
45551
|
const path = slashUsagePath();
|
|
46018
45552
|
if (!existsSync3(path)) return {};
|
|
46019
45553
|
try {
|
|
46020
|
-
const raw =
|
|
45554
|
+
const raw = readFileSync2(path, "utf8");
|
|
46021
45555
|
const parsed = JSON.parse(raw);
|
|
46022
45556
|
if (!parsed || typeof parsed !== "object") return {};
|
|
46023
45557
|
const out = {};
|
|
@@ -46034,8 +45568,8 @@ function persist(counts) {
|
|
|
46034
45568
|
const tmp = `${path}.tmp`;
|
|
46035
45569
|
const payload = { version: 1, counts };
|
|
46036
45570
|
try {
|
|
46037
|
-
|
|
46038
|
-
|
|
45571
|
+
mkdirSync2(dirname2(path), { recursive: true });
|
|
45572
|
+
writeFileSync2(tmp, JSON.stringify(payload), "utf8");
|
|
46039
45573
|
renameSync(tmp, path);
|
|
46040
45574
|
} catch {
|
|
46041
45575
|
}
|
|
@@ -46122,9 +45656,9 @@ function isDirectory(path) {
|
|
|
46122
45656
|
|
|
46123
45657
|
// src/cli/edit/external-editor.ts
|
|
46124
45658
|
import { spawn } from "child_process";
|
|
46125
|
-
import { mkdtempSync, readFileSync as
|
|
45659
|
+
import { mkdtempSync, readFileSync as readFileSync3, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
46126
45660
|
import { tmpdir } from "os";
|
|
46127
|
-
import { join as
|
|
45661
|
+
import { join as join3 } from "path";
|
|
46128
45662
|
function detectEditor(env = process.env) {
|
|
46129
45663
|
for (const key of ["GIT_EDITOR", "VISUAL", "EDITOR"]) {
|
|
46130
45664
|
const raw = env[key];
|
|
@@ -46141,12 +45675,12 @@ async function openInExternalEditor(initial2) {
|
|
|
46141
45675
|
detail: t("composer.editorMissing")
|
|
46142
45676
|
};
|
|
46143
45677
|
}
|
|
46144
|
-
const dir = mkdtempSync(
|
|
46145
|
-
const path =
|
|
45678
|
+
const dir = mkdtempSync(join3(tmpdir(), "reasonix-compose-"));
|
|
45679
|
+
const path = join3(dir, "REASONIX_INPUT.md");
|
|
46146
45680
|
try {
|
|
46147
|
-
|
|
45681
|
+
writeFileSync3(path, initial2, "utf8");
|
|
46148
45682
|
await spawnEditor(editor, path);
|
|
46149
|
-
const raw =
|
|
45683
|
+
const raw = readFileSync3(path, "utf8");
|
|
46150
45684
|
return { kind: "ok", content: normalizeEditorBuffer(raw) };
|
|
46151
45685
|
} catch (err) {
|
|
46152
45686
|
return {
|
|
@@ -46416,22 +45950,22 @@ function allocateRows(claims, totalRows) {
|
|
|
46416
45950
|
}
|
|
46417
45951
|
return out;
|
|
46418
45952
|
}
|
|
46419
|
-
function reducer(
|
|
45953
|
+
function reducer(state2, action) {
|
|
46420
45954
|
switch (action.type) {
|
|
46421
45955
|
case "claim": {
|
|
46422
|
-
const next = new Map(
|
|
45956
|
+
const next = new Map(state2.claims);
|
|
46423
45957
|
next.set(action.zone, action.spec);
|
|
46424
|
-
return { ...
|
|
45958
|
+
return { ...state2, claims: next };
|
|
46425
45959
|
}
|
|
46426
45960
|
case "release": {
|
|
46427
|
-
if (!
|
|
46428
|
-
const next = new Map(
|
|
45961
|
+
if (!state2.claims.has(action.zone)) return state2;
|
|
45962
|
+
const next = new Map(state2.claims);
|
|
46429
45963
|
next.delete(action.zone);
|
|
46430
|
-
return { ...
|
|
45964
|
+
return { ...state2, claims: next };
|
|
46431
45965
|
}
|
|
46432
45966
|
case "resize":
|
|
46433
|
-
if (action.rows ===
|
|
46434
|
-
return { ...
|
|
45967
|
+
if (action.rows === state2.totalRows) return state2;
|
|
45968
|
+
return { ...state2, totalRows: action.rows };
|
|
46435
45969
|
}
|
|
46436
45970
|
}
|
|
46437
45971
|
var BudgetContext = (0, import_react6.createContext)(null);
|
|
@@ -46440,7 +45974,7 @@ function ViewportBudgetProvider({
|
|
|
46440
45974
|
initialRows
|
|
46441
45975
|
}) {
|
|
46442
45976
|
const { stdout } = use_stdout_default();
|
|
46443
|
-
const [
|
|
45977
|
+
const [state2, dispatch] = (0, import_react6.useReducer)(reducer, void 0, () => ({
|
|
46444
45978
|
claims: /* @__PURE__ */ new Map(),
|
|
46445
45979
|
totalRows: initialRows ?? stdout?.rows ?? 40
|
|
46446
45980
|
}));
|
|
@@ -46456,19 +45990,19 @@ function ViewportBudgetProvider({
|
|
|
46456
45990
|
}, [stdout, initialRows]);
|
|
46457
45991
|
const allocations = (0, import_react6.useMemo)(() => {
|
|
46458
45992
|
const list2 = [];
|
|
46459
|
-
for (const [zone, spec] of
|
|
45993
|
+
for (const [zone, spec] of state2.claims) {
|
|
46460
45994
|
list2.push({ zone, priority: ZONE_PRIORITY[zone], ...spec });
|
|
46461
45995
|
}
|
|
46462
|
-
return allocateRows(list2,
|
|
46463
|
-
}, [
|
|
45996
|
+
return allocateRows(list2, state2.totalRows);
|
|
45997
|
+
}, [state2.claims, state2.totalRows]);
|
|
46464
45998
|
const value = (0, import_react6.useMemo)(
|
|
46465
45999
|
() => ({
|
|
46466
|
-
totalRows:
|
|
46000
|
+
totalRows: state2.totalRows,
|
|
46467
46001
|
allocations,
|
|
46468
|
-
claims:
|
|
46002
|
+
claims: state2.claims,
|
|
46469
46003
|
dispatch
|
|
46470
46004
|
}),
|
|
46471
|
-
[
|
|
46005
|
+
[state2.totalRows, allocations, state2.claims]
|
|
46472
46006
|
);
|
|
46473
46007
|
return /* @__PURE__ */ import_react6.default.createElement(BudgetContext.Provider, { value }, children);
|
|
46474
46008
|
}
|
|
@@ -46539,19 +46073,19 @@ var import_react23 = __toESM(require_react(), 1);
|
|
|
46539
46073
|
var import_react8 = __toESM(require_react(), 1);
|
|
46540
46074
|
var ROW_WINDOW = 8;
|
|
46541
46075
|
function AtMentionSuggestions({
|
|
46542
|
-
state,
|
|
46076
|
+
state: state2,
|
|
46543
46077
|
selectedIndex
|
|
46544
46078
|
}) {
|
|
46545
46079
|
const color = useColor();
|
|
46546
|
-
if (!
|
|
46547
|
-
const isBrowse =
|
|
46548
|
-
const entries =
|
|
46080
|
+
if (!state2) return null;
|
|
46081
|
+
const isBrowse = state2.kind === "browse";
|
|
46082
|
+
const entries = state2.entries;
|
|
46549
46083
|
const total = entries.length;
|
|
46550
46084
|
const windowStart = total <= ROW_WINDOW ? 0 : Math.max(0, Math.min(selectedIndex - Math.floor(ROW_WINDOW / 2), total - ROW_WINDOW));
|
|
46551
46085
|
const shown = entries.slice(windowStart, windowStart + ROW_WINDOW);
|
|
46552
46086
|
const hiddenAbove = windowStart;
|
|
46553
46087
|
const hiddenBelow = total - windowStart - shown.length;
|
|
46554
|
-
return /* @__PURE__ */ import_react8.default.createElement(Box_default, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ import_react8.default.createElement(HeaderRow, { state, hiddenAbove }), total === 0 ? /* @__PURE__ */ import_react8.default.createElement(EmptyRow, { state, color }) : null, shown.map((entry, i) => /* @__PURE__ */ import_react8.default.createElement(
|
|
46088
|
+
return /* @__PURE__ */ import_react8.default.createElement(Box_default, { flexDirection: "column", paddingX: 1, marginTop: 1 }, /* @__PURE__ */ import_react8.default.createElement(HeaderRow, { state: state2, hiddenAbove }), total === 0 ? /* @__PURE__ */ import_react8.default.createElement(EmptyRow, { state: state2, color }) : null, shown.map((entry, i) => /* @__PURE__ */ import_react8.default.createElement(
|
|
46555
46089
|
EntryRow,
|
|
46556
46090
|
{
|
|
46557
46091
|
key: `${entry.insertPath}:${entry.isDir ? "d" : "f"}`,
|
|
@@ -46561,29 +46095,29 @@ function AtMentionSuggestions({
|
|
|
46561
46095
|
)), hiddenBelow > 0 ? /* @__PURE__ */ import_react8.default.createElement(Text, { dimColor: true }, ` \u2193 ${hiddenBelow} below`) : null, /* @__PURE__ */ import_react8.default.createElement(FooterRow, { isBrowse, hasFolder: shown.some((e) => e.isDir) }));
|
|
46562
46096
|
}
|
|
46563
46097
|
function HeaderRow({
|
|
46564
|
-
state,
|
|
46098
|
+
state: state2,
|
|
46565
46099
|
hiddenAbove
|
|
46566
46100
|
}) {
|
|
46567
46101
|
const color = useColor();
|
|
46568
|
-
const total =
|
|
46102
|
+
const total = state2.entries.length;
|
|
46569
46103
|
const lead = /* @__PURE__ */ import_react8.default.createElement(Text, { color: color.primary, bold: true }, "@ ");
|
|
46570
|
-
if (
|
|
46571
|
-
const where =
|
|
46572
|
-
const counter =
|
|
46104
|
+
if (state2.kind === "browse") {
|
|
46105
|
+
const where = state2.baseDir === "" ? "/" : `${state2.baseDir}/`;
|
|
46106
|
+
const counter = state2.loading ? t("atMentions.loading") : t(total === 1 ? "atMentions.entrySingular" : "atMentions.entryPlural", { count: total });
|
|
46573
46107
|
return /* @__PURE__ */ import_react8.default.createElement(Box_default, null, lead, /* @__PURE__ */ import_react8.default.createElement(Text, { dimColor: true }, `${where} ${counter}`), hiddenAbove > 0 ? /* @__PURE__ */ import_react8.default.createElement(Text, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null);
|
|
46574
46108
|
}
|
|
46575
|
-
const status2 =
|
|
46109
|
+
const status2 = state2.searching ? `${t("atMentions.searching")} ${state2.scanned} ${t("atMentions.scanned")} \xB7 ${total} ${total === 1 ? t("atMentions.match") : t("atMentions.matches")}` : `${total} ${total === 1 ? t("atMentions.match") : t("atMentions.matches")} ${t("atMentions.forFilter", { filter: state2.filter })}`;
|
|
46576
46110
|
return /* @__PURE__ */ import_react8.default.createElement(Box_default, null, lead, /* @__PURE__ */ import_react8.default.createElement(Text, { dimColor: true }, status2), hiddenAbove > 0 ? /* @__PURE__ */ import_react8.default.createElement(Text, { dimColor: true }, ` \u2191 ${hiddenAbove} above`) : null);
|
|
46577
46111
|
}
|
|
46578
|
-
function EmptyRow({ state, color }) {
|
|
46579
|
-
if (
|
|
46580
|
-
if (
|
|
46112
|
+
function EmptyRow({ state: state2, color }) {
|
|
46113
|
+
if (state2.kind === "browse") {
|
|
46114
|
+
if (state2.loading) return null;
|
|
46581
46115
|
return /* @__PURE__ */ import_react8.default.createElement(Box_default, null, /* @__PURE__ */ import_react8.default.createElement(Text, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ import_react8.default.createElement(Text, null, " "), /* @__PURE__ */ import_react8.default.createElement(Text, { color: color.warn }, t("atMentions.emptyDir")));
|
|
46582
46116
|
}
|
|
46583
|
-
if (
|
|
46117
|
+
if (state2.searching) {
|
|
46584
46118
|
return /* @__PURE__ */ import_react8.default.createElement(Box_default, null, /* @__PURE__ */ import_react8.default.createElement(Text, { dimColor: true }, t("atMentions.scanning")));
|
|
46585
46119
|
}
|
|
46586
|
-
return /* @__PURE__ */ import_react8.default.createElement(Box_default, null, /* @__PURE__ */ import_react8.default.createElement(Text, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ import_react8.default.createElement(Text, null, " "), /* @__PURE__ */ import_react8.default.createElement(Text, { color: color.warn }, t("atMentions.noMatch", { filter:
|
|
46120
|
+
return /* @__PURE__ */ import_react8.default.createElement(Box_default, null, /* @__PURE__ */ import_react8.default.createElement(Text, { color: color.warn, bold: true }, GLYPH.warn), /* @__PURE__ */ import_react8.default.createElement(Text, null, " "), /* @__PURE__ */ import_react8.default.createElement(Text, { color: color.warn }, t("atMentions.noMatch", { filter: state2.filter })));
|
|
46587
46121
|
}
|
|
46588
46122
|
function EntryRow({ entry, isSelected }) {
|
|
46589
46123
|
const color = useColor();
|
|
@@ -47913,6 +47447,7 @@ function SubagentRow({ activity }) {
|
|
|
47913
47447
|
const last = activity.lastInner;
|
|
47914
47448
|
const subtitle = activity.skillName ?? truncate(activity.task, 48);
|
|
47915
47449
|
const modelBadge = activity.model ? modelBadgeFor(activity.model) : null;
|
|
47450
|
+
const streamLine = formatStreamLine(activity);
|
|
47916
47451
|
return /* @__PURE__ */ import_react18.default.createElement(Card, { tone: CARD.subagent.color }, /* @__PURE__ */ import_react18.default.createElement(
|
|
47917
47452
|
CardHeader,
|
|
47918
47453
|
{
|
|
@@ -47923,7 +47458,28 @@ function SubagentRow({ activity }) {
|
|
|
47923
47458
|
meta: [`iter ${activity.iter}`, `${seconds}s`],
|
|
47924
47459
|
right: /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, modelBadge ? /* @__PURE__ */ import_react18.default.createElement(Pill, { label: modelBadge.label, ...PILL_MODEL[modelBadge.kind], bold: false }) : null, /* @__PURE__ */ import_react18.default.createElement(Spinner, { kind: "braille", color: CARD.subagent.color }))
|
|
47925
47460
|
}
|
|
47926
|
-
), /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, "task ", /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.sub }, activity.task)), /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, "last ", last ? /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(Text, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.body }, last.label), last.meta ? /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, t("editMode.queuedDots"))), /* @__PURE__ */ import_react18.default.createElement(Text, { color: TONE.brand }, "\u25B6 ", phase));
|
|
47461
|
+
), /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, "task ", /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.sub }, activity.task)), /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, "last ", last ? /* @__PURE__ */ import_react18.default.createElement(import_react18.default.Fragment, null, /* @__PURE__ */ import_react18.default.createElement(Text, { color: last.color }, `${last.glyph} `), /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.body }, last.label), last.meta ? /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, ` ${last.meta}`) : null) : /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, t("editMode.queuedDots"))), streamLine ? /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, "flow ", /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.sub }, streamLine)) : null, /* @__PURE__ */ import_react18.default.createElement(Text, { color: TONE.brand }, "\u25B6 ", phase));
|
|
47462
|
+
}
|
|
47463
|
+
function formatBytes(n) {
|
|
47464
|
+
if (n < 1024) return `${n} B`;
|
|
47465
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
47466
|
+
return `${(n / (1024 * 1024)).toFixed(2)} MB`;
|
|
47467
|
+
}
|
|
47468
|
+
function formatSubagentBytes(a) {
|
|
47469
|
+
if (a.outputChars + a.reasoningChars + a.toolReadChars === 0) return null;
|
|
47470
|
+
const parts = [];
|
|
47471
|
+
if (a.toolReadChars > 0) parts.push(`\u2193 ${formatBytes(a.toolReadChars)} read`);
|
|
47472
|
+
if (a.outputChars > 0) parts.push(`\u2191 ${formatBytes(a.outputChars)} out`);
|
|
47473
|
+
if (a.reasoningChars > 0) parts.push(`\u25C6 ${formatBytes(a.reasoningChars)} think`);
|
|
47474
|
+
return parts.join(" \xB7 ");
|
|
47475
|
+
}
|
|
47476
|
+
function formatStreamLine(a) {
|
|
47477
|
+
if (a.outputChars + a.reasoningChars + a.toolReadChars === 0) return null;
|
|
47478
|
+
const parts = [];
|
|
47479
|
+
if (a.toolReadChars > 0) parts.push(`\u2193 read ${formatBytes(a.toolReadChars)}`);
|
|
47480
|
+
if (a.outputChars > 0) parts.push(`\u2191 out ${formatBytes(a.outputChars)}`);
|
|
47481
|
+
if (a.reasoningChars > 0) parts.push(`\u25C6 think ${formatBytes(a.reasoningChars)}`);
|
|
47482
|
+
return parts.join(" \xB7 ");
|
|
47927
47483
|
}
|
|
47928
47484
|
function SubagentLiveStack({
|
|
47929
47485
|
activities,
|
|
@@ -47966,14 +47522,25 @@ function CompactSubagentLine({
|
|
|
47966
47522
|
function truncate(text, max) {
|
|
47967
47523
|
return text.length > max ? `${text.slice(0, max)}\u2026` : text;
|
|
47968
47524
|
}
|
|
47525
|
+
var SUBAGENT_WRAPPER_TOOLS = /* @__PURE__ */ new Set([
|
|
47526
|
+
"explore",
|
|
47527
|
+
"research",
|
|
47528
|
+
"review",
|
|
47529
|
+
"security_review",
|
|
47530
|
+
"run_skill"
|
|
47531
|
+
]);
|
|
47969
47532
|
function OngoingToolRow({
|
|
47970
47533
|
tool,
|
|
47971
|
-
progress
|
|
47534
|
+
progress,
|
|
47535
|
+
subagentActivities = []
|
|
47972
47536
|
}) {
|
|
47973
47537
|
const tick = useTick();
|
|
47974
47538
|
const elapsed = useElapsedSeconds();
|
|
47975
47539
|
const summary = summarizeToolArgs(tool.name, tool.args);
|
|
47976
|
-
|
|
47540
|
+
const argsBytes = tool.args ? tool.args.length : 0;
|
|
47541
|
+
const subagentBytes = SUBAGENT_WRAPPER_TOOLS.has(tool.name) ? subagentActivities[subagentActivities.length - 1] : void 0;
|
|
47542
|
+
const subagentBytesLine = subagentBytes ? formatSubagentBytes(subagentBytes) : null;
|
|
47543
|
+
return /* @__PURE__ */ import_react18.default.createElement(Box_default, { marginY: 1, flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ import_react18.default.createElement(Box_default, null, /* @__PURE__ */ import_react18.default.createElement(Text, { color: CARD.tool.color, bold: true }, SPINNER_FRAMES[tick % SPINNER_FRAMES.length]), /* @__PURE__ */ import_react18.default.createElement(Text, null, " "), /* @__PURE__ */ import_react18.default.createElement(Text, { color: CARD.tool.color, bold: true }, `\u25A3 ${tool.name}`), /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, ` running \xB7 ${elapsed}s`, argsBytes > 0 ? ` \xB7 args ${formatBytes(argsBytes)}` : "")), subagentBytesLine ? /* @__PURE__ */ import_react18.default.createElement(Box_default, { paddingLeft: 3 }, /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, subagentBytesLine)) : null, progress ? /* @__PURE__ */ import_react18.default.createElement(Box_default, { paddingLeft: 3 }, /* @__PURE__ */ import_react18.default.createElement(Text, { color: TONE.brand }, renderProgressLine(progress))) : null, summary ? /* @__PURE__ */ import_react18.default.createElement(Box_default, { paddingLeft: 3 }, /* @__PURE__ */ import_react18.default.createElement(Text, { color: FG.faint }, summary)) : null);
|
|
47977
47544
|
}
|
|
47978
47545
|
function renderProgressLine(p) {
|
|
47979
47546
|
const msg = p.message ? ` ${p.message}` : "";
|
|
@@ -48047,23 +47614,23 @@ function Countdown({
|
|
|
48047
47614
|
var import_react20 = __toESM(require_react(), 1);
|
|
48048
47615
|
|
|
48049
47616
|
// src/cli/ui/state/reducer.ts
|
|
48050
|
-
function reduce(
|
|
47617
|
+
function reduce(state2, event) {
|
|
48051
47618
|
switch (event.type) {
|
|
48052
47619
|
case "user.submit":
|
|
48053
|
-
return appendCard(
|
|
47620
|
+
return appendCard(state2, makeUserCard(event.text));
|
|
48054
47621
|
case "turn.start":
|
|
48055
|
-
return { ...
|
|
47622
|
+
return { ...state2, turnInProgress: true };
|
|
48056
47623
|
case "turn.thinking":
|
|
48057
47624
|
return appendCard(
|
|
48058
|
-
|
|
48059
|
-
makeLiveCard("thinking", `thinking \xB7 ${
|
|
47625
|
+
state2,
|
|
47626
|
+
makeLiveCard("thinking", `thinking \xB7 ${state2.session.model}`, "brand")
|
|
48060
47627
|
);
|
|
48061
47628
|
case "reasoning.start":
|
|
48062
|
-
return appendCard(
|
|
47629
|
+
return appendCard(state2, makeReasoningCard(event.id, event.model ?? state2.session.model));
|
|
48063
47630
|
case "reasoning.chunk":
|
|
48064
|
-
return mutateCard(
|
|
47631
|
+
return mutateCard(state2, event.id, "reasoning", (c) => ({ ...c, text: c.text + event.text }));
|
|
48065
47632
|
case "reasoning.end":
|
|
48066
|
-
return mutateCard(
|
|
47633
|
+
return mutateCard(state2, event.id, "reasoning", (c) => ({
|
|
48067
47634
|
...c,
|
|
48068
47635
|
paragraphs: event.paragraphs,
|
|
48069
47636
|
tokens: event.tokens,
|
|
@@ -48072,24 +47639,24 @@ function reduce(state, event) {
|
|
|
48072
47639
|
...event.aborted ? { aborted: true } : {}
|
|
48073
47640
|
}));
|
|
48074
47641
|
case "streaming.start":
|
|
48075
|
-
return appendCard(
|
|
47642
|
+
return appendCard(state2, makeStreamingCard(event.id, event.model ?? state2.session.model));
|
|
48076
47643
|
case "streaming.chunk":
|
|
48077
|
-
return mutateCard(
|
|
47644
|
+
return mutateCard(state2, event.id, "streaming", (c) => ({ ...c, text: c.text + event.text }));
|
|
48078
47645
|
case "streaming.end":
|
|
48079
|
-
return mutateCard(
|
|
47646
|
+
return mutateCard(state2, event.id, "streaming", (c) => ({
|
|
48080
47647
|
...c,
|
|
48081
47648
|
done: true,
|
|
48082
47649
|
endedAt: Date.now(),
|
|
48083
47650
|
...event.aborted ? { aborted: true } : {}
|
|
48084
47651
|
}));
|
|
48085
47652
|
case "tool.start":
|
|
48086
|
-
return appendCard(
|
|
47653
|
+
return appendCard(state2, makeToolCard(event.id, event.name, event.args));
|
|
48087
47654
|
case "tool.chunk":
|
|
48088
|
-
return mutateCard(
|
|
47655
|
+
return mutateCard(state2, event.id, "tool", (c) => ({ ...c, output: c.output + event.text }));
|
|
48089
47656
|
case "tool.end": {
|
|
48090
47657
|
const finalOutput = event.output ?? "";
|
|
48091
47658
|
const rejected = isPlanModeRejection(finalOutput);
|
|
48092
|
-
return mutateCard(
|
|
47659
|
+
return mutateCard(state2, event.id, "tool", (c) => ({
|
|
48093
47660
|
...c,
|
|
48094
47661
|
done: true,
|
|
48095
47662
|
output: event.output ?? c.output,
|
|
@@ -48100,97 +47667,97 @@ function reduce(state, event) {
|
|
|
48100
47667
|
}));
|
|
48101
47668
|
}
|
|
48102
47669
|
case "tool.retry":
|
|
48103
|
-
return mutateCard(
|
|
47670
|
+
return mutateCard(state2, event.id, "tool", (c) => ({
|
|
48104
47671
|
...c,
|
|
48105
47672
|
retry: { attempt: event.attempt, max: event.max }
|
|
48106
47673
|
}));
|
|
48107
47674
|
case "turn.abort":
|
|
48108
47675
|
return {
|
|
48109
|
-
...
|
|
47676
|
+
...state2,
|
|
48110
47677
|
turnInProgress: false,
|
|
48111
|
-
composer: { ...
|
|
47678
|
+
composer: { ...state2.composer, abortedHint: true }
|
|
48112
47679
|
};
|
|
48113
47680
|
case "turn.end": {
|
|
48114
|
-
const sessionCost =
|
|
48115
|
-
const sessionInputTokens =
|
|
48116
|
-
const sessionOutputTokens =
|
|
47681
|
+
const sessionCost = state2.status.sessionCost + event.usage.cost;
|
|
47682
|
+
const sessionInputTokens = state2.status.sessionInputTokens + event.usage.prompt;
|
|
47683
|
+
const sessionOutputTokens = state2.status.sessionOutputTokens + event.usage.output;
|
|
48117
47684
|
return {
|
|
48118
|
-
...
|
|
47685
|
+
...state2,
|
|
48119
47686
|
turnInProgress: false,
|
|
48120
47687
|
status: {
|
|
48121
|
-
...
|
|
47688
|
+
...state2.status,
|
|
48122
47689
|
cost: event.usage.cost,
|
|
48123
47690
|
sessionCost,
|
|
48124
47691
|
cacheHit: event.sessionCacheHit ?? event.usage.cacheHit,
|
|
48125
47692
|
promptTokens: event.usage.prompt,
|
|
48126
|
-
promptCap: event.promptCap ??
|
|
47693
|
+
promptCap: event.promptCap ?? state2.status.promptCap,
|
|
48127
47694
|
sessionInputTokens,
|
|
48128
47695
|
sessionOutputTokens,
|
|
48129
|
-
lastTurnMs: event.elapsedMs ??
|
|
47696
|
+
lastTurnMs: event.elapsedMs ?? state2.status.lastTurnMs
|
|
48130
47697
|
}
|
|
48131
47698
|
};
|
|
48132
47699
|
}
|
|
48133
47700
|
case "mode.change":
|
|
48134
|
-
return { ...
|
|
47701
|
+
return { ...state2, status: { ...state2.status, mode: event.mode } };
|
|
48135
47702
|
case "network.change":
|
|
48136
47703
|
return {
|
|
48137
|
-
...
|
|
48138
|
-
status: { ...
|
|
47704
|
+
...state2,
|
|
47705
|
+
status: { ...state2.status, network: event.state, networkDetail: event.detail }
|
|
48139
47706
|
};
|
|
48140
47707
|
case "language.change":
|
|
48141
|
-
return { ...
|
|
47708
|
+
return { ...state2, lang: event.lang };
|
|
48142
47709
|
case "session.update":
|
|
48143
|
-
return { ...
|
|
47710
|
+
return { ...state2, status: { ...state2.status, ...event.patch } };
|
|
48144
47711
|
case "session.model.change":
|
|
48145
|
-
return
|
|
47712
|
+
return state2.session.model === event.model ? state2 : { ...state2, session: { ...state2.session, model: event.model } };
|
|
48146
47713
|
case "session.preset.change":
|
|
48147
|
-
return
|
|
47714
|
+
return state2.status.preset === event.preset ? state2 : { ...state2, status: { ...state2.status, preset: event.preset } };
|
|
48148
47715
|
case "mcp.loading": {
|
|
48149
|
-
const current =
|
|
47716
|
+
const current = state2.status.mcpLoading;
|
|
48150
47717
|
if (event.total <= 0) {
|
|
48151
|
-
if (!current) return
|
|
48152
|
-
const { mcpLoading: _drop, ...rest } =
|
|
48153
|
-
return { ...
|
|
47718
|
+
if (!current) return state2;
|
|
47719
|
+
const { mcpLoading: _drop, ...rest } = state2.status;
|
|
47720
|
+
return { ...state2, status: rest };
|
|
48154
47721
|
}
|
|
48155
|
-
if (current && current.ready === event.ready && current.total === event.total) return
|
|
47722
|
+
if (current && current.ready === event.ready && current.total === event.total) return state2;
|
|
48156
47723
|
return {
|
|
48157
|
-
...
|
|
48158
|
-
status: { ...
|
|
47724
|
+
...state2,
|
|
47725
|
+
status: { ...state2.status, mcpLoading: { ready: event.ready, total: event.total } }
|
|
48159
47726
|
};
|
|
48160
47727
|
}
|
|
48161
47728
|
case "focus.move":
|
|
48162
47729
|
return {
|
|
48163
|
-
...
|
|
48164
|
-
focusedCardId: moveFocus(
|
|
47730
|
+
...state2,
|
|
47731
|
+
focusedCardId: moveFocus(state2.cards, state2.focusedCardId, event.direction)
|
|
48165
47732
|
};
|
|
48166
47733
|
case "focus.set":
|
|
48167
|
-
return { ...
|
|
47734
|
+
return { ...state2, focusedCardId: event.cardId };
|
|
48168
47735
|
case "card.toggle":
|
|
48169
|
-
return
|
|
47736
|
+
return state2;
|
|
48170
47737
|
case "composer.input":
|
|
48171
47738
|
return {
|
|
48172
|
-
...
|
|
47739
|
+
...state2,
|
|
48173
47740
|
composer: {
|
|
48174
|
-
...
|
|
47741
|
+
...state2.composer,
|
|
48175
47742
|
value: event.value,
|
|
48176
47743
|
cursor: event.value.length,
|
|
48177
47744
|
abortedHint: false
|
|
48178
47745
|
}
|
|
48179
47746
|
};
|
|
48180
47747
|
case "composer.cursor":
|
|
48181
|
-
return { ...
|
|
47748
|
+
return { ...state2, composer: { ...state2.composer, cursor: event.index } };
|
|
48182
47749
|
case "composer.history":
|
|
48183
|
-
return
|
|
47750
|
+
return state2;
|
|
48184
47751
|
case "picker.open":
|
|
48185
|
-
return { ...
|
|
47752
|
+
return { ...state2, composer: { ...state2.composer, picker: event.kind } };
|
|
48186
47753
|
case "picker.close":
|
|
48187
|
-
return { ...
|
|
47754
|
+
return { ...state2, composer: { ...state2.composer, picker: null } };
|
|
48188
47755
|
case "toast.show":
|
|
48189
|
-
return { ...
|
|
47756
|
+
return { ...state2, toasts: [...state2.toasts, makeToast(event)] };
|
|
48190
47757
|
case "toast.hide":
|
|
48191
|
-
return { ...
|
|
47758
|
+
return { ...state2, toasts: state2.toasts.filter((t2) => t2.id !== event.id) };
|
|
48192
47759
|
case "live.show":
|
|
48193
|
-
return appendCard(
|
|
47760
|
+
return appendCard(state2, {
|
|
48194
47761
|
kind: "live",
|
|
48195
47762
|
id: event.id,
|
|
48196
47763
|
ts: event.ts,
|
|
@@ -48200,7 +47767,7 @@ function reduce(state, event) {
|
|
|
48200
47767
|
meta: event.meta
|
|
48201
47768
|
});
|
|
48202
47769
|
case "tip.show":
|
|
48203
|
-
return appendCard(
|
|
47770
|
+
return appendCard(state2, {
|
|
48204
47771
|
kind: "tip",
|
|
48205
47772
|
id: event.id,
|
|
48206
47773
|
ts: event.ts,
|
|
@@ -48211,12 +47778,12 @@ function reduce(state, event) {
|
|
|
48211
47778
|
});
|
|
48212
47779
|
case "session.reset":
|
|
48213
47780
|
return {
|
|
48214
|
-
...
|
|
47781
|
+
...state2,
|
|
48215
47782
|
cards: [],
|
|
48216
47783
|
focusedCardId: null,
|
|
48217
47784
|
toasts: [],
|
|
48218
47785
|
status: {
|
|
48219
|
-
...
|
|
47786
|
+
...state2.status,
|
|
48220
47787
|
cost: 0,
|
|
48221
47788
|
sessionCost: 0,
|
|
48222
47789
|
cacheHit: 0,
|
|
@@ -48225,17 +47792,17 @@ function reduce(state, event) {
|
|
|
48225
47792
|
}
|
|
48226
47793
|
};
|
|
48227
47794
|
case "session.fork": {
|
|
48228
|
-
const idx =
|
|
48229
|
-
if (idx < 0) return
|
|
48230
|
-
return { ...
|
|
47795
|
+
const idx = state2.cards.findIndex((c) => c.id === event.cardId);
|
|
47796
|
+
if (idx < 0) return state2;
|
|
47797
|
+
return { ...state2, cards: state2.cards.slice(0, idx), focusedCardId: null };
|
|
48231
47798
|
}
|
|
48232
47799
|
case "session.workspace.change":
|
|
48233
|
-
return
|
|
48234
|
-
...
|
|
48235
|
-
session: { ...
|
|
47800
|
+
return state2.session.id === event.id && state2.session.workspace === event.workspace ? state2 : {
|
|
47801
|
+
...state2,
|
|
47802
|
+
session: { ...state2.session, id: event.id, workspace: event.workspace }
|
|
48236
47803
|
};
|
|
48237
47804
|
case "plan.show":
|
|
48238
|
-
return appendCard(
|
|
47805
|
+
return appendCard(state2, {
|
|
48239
47806
|
kind: "plan",
|
|
48240
47807
|
id: event.id,
|
|
48241
47808
|
ts: Date.now(),
|
|
@@ -48245,20 +47812,20 @@ function reduce(state, event) {
|
|
|
48245
47812
|
});
|
|
48246
47813
|
case "plan.drop": {
|
|
48247
47814
|
let dropped = false;
|
|
48248
|
-
const cards =
|
|
47815
|
+
const cards = state2.cards.map((c, i) => {
|
|
48249
47816
|
if (dropped) return c;
|
|
48250
47817
|
if (c.kind !== "plan" || c.variant !== "active") return c;
|
|
48251
|
-
if (
|
|
47818
|
+
if (state2.cards.slice(i + 1).some((cc) => cc.kind === "plan" && cc.variant === "active")) {
|
|
48252
47819
|
return c;
|
|
48253
47820
|
}
|
|
48254
47821
|
dropped = true;
|
|
48255
47822
|
return { ...c, variant: "replay" };
|
|
48256
47823
|
});
|
|
48257
|
-
return dropped ? { ...
|
|
47824
|
+
return dropped ? { ...state2, cards } : state2;
|
|
48258
47825
|
}
|
|
48259
47826
|
case "plan.step.complete": {
|
|
48260
47827
|
let changed = false;
|
|
48261
|
-
const cards =
|
|
47828
|
+
const cards = state2.cards.map((c) => {
|
|
48262
47829
|
if (c.kind !== "plan") return c;
|
|
48263
47830
|
let stepChanged = false;
|
|
48264
47831
|
const next = c.steps.map((s) => {
|
|
@@ -48270,10 +47837,10 @@ function reduce(state, event) {
|
|
|
48270
47837
|
changed = true;
|
|
48271
47838
|
return { ...c, steps: next };
|
|
48272
47839
|
});
|
|
48273
|
-
return changed ? { ...
|
|
47840
|
+
return changed ? { ...state2, cards } : state2;
|
|
48274
47841
|
}
|
|
48275
47842
|
case "ctx.show":
|
|
48276
|
-
return appendCard(
|
|
47843
|
+
return appendCard(state2, {
|
|
48277
47844
|
kind: "ctx",
|
|
48278
47845
|
id: event.id,
|
|
48279
47846
|
ts: Date.now(),
|
|
@@ -48288,14 +47855,14 @@ function reduce(state, event) {
|
|
|
48288
47855
|
topTools: event.topTools
|
|
48289
47856
|
});
|
|
48290
47857
|
case "doctor.show":
|
|
48291
|
-
return appendCard(
|
|
47858
|
+
return appendCard(state2, {
|
|
48292
47859
|
kind: "doctor",
|
|
48293
47860
|
id: event.id,
|
|
48294
47861
|
ts: Date.now(),
|
|
48295
47862
|
checks: event.checks
|
|
48296
47863
|
});
|
|
48297
47864
|
case "usage.show":
|
|
48298
|
-
return appendCard(
|
|
47865
|
+
return appendCard(state2, {
|
|
48299
47866
|
kind: "usage",
|
|
48300
47867
|
id: event.id,
|
|
48301
47868
|
ts: Date.now(),
|
|
@@ -48313,34 +47880,65 @@ function reduce(state, event) {
|
|
|
48313
47880
|
var RECENT_CARDS_WINDOW = 200;
|
|
48314
47881
|
var MIN_ELIDE_OUTPUT_LENGTH = 4096;
|
|
48315
47882
|
var ELIDED_TOOL_OUTPUT_PREFIX = "[elided \u2014 older than the last ";
|
|
48316
|
-
function
|
|
47883
|
+
function elidedStub(originalChars) {
|
|
47884
|
+
return `${ELIDED_TOOL_OUTPUT_PREFIX}${RECENT_CARDS_WINDOW} cards; ${originalChars.toLocaleString()} chars dropped to save memory. Full output is on disk in the session log.]`;
|
|
47885
|
+
}
|
|
47886
|
+
function stubHeavyContent(c) {
|
|
47887
|
+
switch (c.kind) {
|
|
47888
|
+
case "tool": {
|
|
47889
|
+
const out = c.output;
|
|
47890
|
+
if (typeof out !== "string") return c;
|
|
47891
|
+
if (out.length <= MIN_ELIDE_OUTPUT_LENGTH) return c;
|
|
47892
|
+
if (out.startsWith(ELIDED_TOOL_OUTPUT_PREFIX)) return c;
|
|
47893
|
+
return { ...c, output: elidedStub(out.length) };
|
|
47894
|
+
}
|
|
47895
|
+
case "reasoning": {
|
|
47896
|
+
const r = c;
|
|
47897
|
+
if (r.streaming) return c;
|
|
47898
|
+
if (r.text.length <= MIN_ELIDE_OUTPUT_LENGTH) return c;
|
|
47899
|
+
if (r.text.startsWith(ELIDED_TOOL_OUTPUT_PREFIX)) return c;
|
|
47900
|
+
return { ...r, text: elidedStub(r.text.length) };
|
|
47901
|
+
}
|
|
47902
|
+
case "streaming": {
|
|
47903
|
+
const s = c;
|
|
47904
|
+
if (!s.done) return c;
|
|
47905
|
+
if (s.text.length <= MIN_ELIDE_OUTPUT_LENGTH) return c;
|
|
47906
|
+
if (s.text.startsWith(ELIDED_TOOL_OUTPUT_PREFIX)) return c;
|
|
47907
|
+
return { ...s, text: elidedStub(s.text.length) };
|
|
47908
|
+
}
|
|
47909
|
+
case "diff": {
|
|
47910
|
+
if (c.hunks.length === 0) return c;
|
|
47911
|
+
let totalChars = 0;
|
|
47912
|
+
for (const h of c.hunks) for (const l of h.lines) totalChars += l.text.length;
|
|
47913
|
+
if (totalChars <= MIN_ELIDE_OUTPUT_LENGTH) return c;
|
|
47914
|
+
return { ...c, hunks: [] };
|
|
47915
|
+
}
|
|
47916
|
+
default:
|
|
47917
|
+
return c;
|
|
47918
|
+
}
|
|
47919
|
+
}
|
|
47920
|
+
function elideOldCardContent(cards) {
|
|
48317
47921
|
if (cards.length < RECENT_CARDS_WINDOW) return cards;
|
|
48318
47922
|
const cutoff = cards.length + 1 - RECENT_CARDS_WINDOW;
|
|
48319
47923
|
let next = null;
|
|
48320
47924
|
for (let i = 0; i < cutoff; i++) {
|
|
48321
47925
|
const c = cards[i];
|
|
48322
|
-
|
|
48323
|
-
|
|
48324
|
-
if (typeof out !== "string") continue;
|
|
48325
|
-
if (out.length <= MIN_ELIDE_OUTPUT_LENGTH) continue;
|
|
48326
|
-
if (out.startsWith(ELIDED_TOOL_OUTPUT_PREFIX)) continue;
|
|
47926
|
+
const stubbed = stubHeavyContent(c);
|
|
47927
|
+
if (stubbed === c) continue;
|
|
48327
47928
|
if (next === null) next = cards.slice();
|
|
48328
|
-
next[i] =
|
|
48329
|
-
...c,
|
|
48330
|
-
output: `${ELIDED_TOOL_OUTPUT_PREFIX}${RECENT_CARDS_WINDOW} cards; ${out.length.toLocaleString()} chars dropped to save memory. Full output is on disk in the session log.]`
|
|
48331
|
-
};
|
|
47929
|
+
next[i] = stubbed;
|
|
48332
47930
|
}
|
|
48333
47931
|
return next ?? cards;
|
|
48334
47932
|
}
|
|
48335
|
-
function appendCard(
|
|
48336
|
-
return { ...
|
|
47933
|
+
function appendCard(state2, card) {
|
|
47934
|
+
return { ...state2, cards: [...elideOldCardContent(state2.cards), card] };
|
|
48337
47935
|
}
|
|
48338
|
-
function mutateCard(
|
|
48339
|
-
const idx =
|
|
48340
|
-
if (idx < 0) return
|
|
48341
|
-
const next =
|
|
48342
|
-
next[idx] = patch(
|
|
48343
|
-
return { ...
|
|
47936
|
+
function mutateCard(state2, id, kind, patch) {
|
|
47937
|
+
const idx = state2.cards.findIndex((c) => c.id === id && c.kind === kind);
|
|
47938
|
+
if (idx < 0) return state2;
|
|
47939
|
+
const next = state2.cards.slice();
|
|
47940
|
+
next[idx] = patch(state2.cards[idx]);
|
|
47941
|
+
return { ...state2, cards: next };
|
|
48344
47942
|
}
|
|
48345
47943
|
function moveFocus(cards, current, dir) {
|
|
48346
47944
|
const last = cards.length - 1;
|
|
@@ -48450,15 +48048,15 @@ function initialState(session, cards = []) {
|
|
|
48450
48048
|
|
|
48451
48049
|
// src/cli/ui/state/store.ts
|
|
48452
48050
|
function createStore(session, initialCards) {
|
|
48453
|
-
let
|
|
48051
|
+
let state2 = initialState(session, initialCards);
|
|
48454
48052
|
const stateListeners = /* @__PURE__ */ new Set();
|
|
48455
48053
|
const eventListeners = /* @__PURE__ */ new Set();
|
|
48456
48054
|
return {
|
|
48457
48055
|
getState() {
|
|
48458
|
-
return
|
|
48056
|
+
return state2;
|
|
48459
48057
|
},
|
|
48460
48058
|
dispatch(event) {
|
|
48461
|
-
|
|
48059
|
+
state2 = reduce(state2, event);
|
|
48462
48060
|
for (const listener of stateListeners) listener();
|
|
48463
48061
|
for (const listener of eventListeners) listener(event);
|
|
48464
48062
|
},
|
|
@@ -48651,8 +48249,8 @@ function modeGlyph(mode2) {
|
|
|
48651
48249
|
return { glyph: "\xB1", color: TONE.ok };
|
|
48652
48250
|
}
|
|
48653
48251
|
}
|
|
48654
|
-
function networkDot(
|
|
48655
|
-
switch (
|
|
48252
|
+
function networkDot(state2) {
|
|
48253
|
+
switch (state2) {
|
|
48656
48254
|
case "online":
|
|
48657
48255
|
return { glyph: "\u25CF", color: TONE.ok };
|
|
48658
48256
|
case "slow":
|
|
@@ -48729,6 +48327,7 @@ var import_react22 = __toESM(require_react(), 1);
|
|
|
48729
48327
|
// src/cli/ui/state/chat-scroll-store.ts
|
|
48730
48328
|
var SCROLL_ARROW_ROWS = 3;
|
|
48731
48329
|
var SCROLL_PAGE_ROWS = 5;
|
|
48330
|
+
var SCROLL_WHEEL_ROWS = 1;
|
|
48732
48331
|
var COALESCE_MS = 16;
|
|
48733
48332
|
var EMPTY_HEIGHTS = /* @__PURE__ */ new Map();
|
|
48734
48333
|
var initial = {
|
|
@@ -48739,29 +48338,29 @@ var initial = {
|
|
|
48739
48338
|
cardHeights: EMPTY_HEIGHTS
|
|
48740
48339
|
};
|
|
48741
48340
|
function createChatScrollStore() {
|
|
48742
|
-
let
|
|
48341
|
+
let state2 = initial;
|
|
48743
48342
|
const listeners = /* @__PURE__ */ new Set();
|
|
48744
48343
|
let pendingDelta = 0;
|
|
48745
48344
|
let flushTimer = null;
|
|
48746
48345
|
let pendingMaxShrink = null;
|
|
48747
48346
|
let shrinkTimer = null;
|
|
48748
48347
|
function set(next) {
|
|
48749
|
-
const merged = { ...
|
|
48750
|
-
if (merged.scrollRows ===
|
|
48348
|
+
const merged = { ...state2, ...next };
|
|
48349
|
+
if (merged.scrollRows === state2.scrollRows && merged.pinned === state2.pinned && merged.maxScroll === state2.maxScroll && merged.scrollVersion === state2.scrollVersion && merged.cardHeights === state2.cardHeights) {
|
|
48751
48350
|
return;
|
|
48752
48351
|
}
|
|
48753
|
-
|
|
48352
|
+
state2 = merged;
|
|
48754
48353
|
for (const l of listeners) l();
|
|
48755
48354
|
}
|
|
48756
48355
|
function applyDelta() {
|
|
48757
48356
|
const d = pendingDelta;
|
|
48758
48357
|
pendingDelta = 0;
|
|
48759
48358
|
if (d === 0) return;
|
|
48760
|
-
const next = Math.max(0, Math.min(
|
|
48359
|
+
const next = Math.max(0, Math.min(state2.maxScroll, state2.scrollRows + d));
|
|
48761
48360
|
set({
|
|
48762
48361
|
scrollRows: next,
|
|
48763
|
-
pinned: d < 0 ? false : next >=
|
|
48764
|
-
scrollVersion:
|
|
48362
|
+
pinned: d < 0 ? false : next >= state2.maxScroll ? true : state2.pinned,
|
|
48363
|
+
scrollVersion: state2.scrollVersion + 1
|
|
48765
48364
|
});
|
|
48766
48365
|
}
|
|
48767
48366
|
function schedule(delta) {
|
|
@@ -48784,12 +48383,12 @@ function createChatScrollStore() {
|
|
|
48784
48383
|
const target = pendingMaxShrink;
|
|
48785
48384
|
pendingMaxShrink = null;
|
|
48786
48385
|
if (target === null) return;
|
|
48787
|
-
const nextScrollRows =
|
|
48386
|
+
const nextScrollRows = state2.pinned ? target : Math.min(state2.scrollRows, target);
|
|
48788
48387
|
set({ maxScroll: target, scrollRows: nextScrollRows });
|
|
48789
48388
|
}
|
|
48790
48389
|
return {
|
|
48791
48390
|
getState() {
|
|
48792
|
-
return
|
|
48391
|
+
return state2;
|
|
48793
48392
|
},
|
|
48794
48393
|
subscribe(listener) {
|
|
48795
48394
|
listeners.add(listener);
|
|
@@ -48801,6 +48400,8 @@ function createChatScrollStore() {
|
|
|
48801
48400
|
scrollDown: () => schedule(SCROLL_ARROW_ROWS),
|
|
48802
48401
|
scrollPageUp: () => schedule(-SCROLL_PAGE_ROWS),
|
|
48803
48402
|
scrollPageDown: () => schedule(SCROLL_PAGE_ROWS),
|
|
48403
|
+
scrollWheelUp: () => schedule(-SCROLL_WHEEL_ROWS),
|
|
48404
|
+
scrollWheelDown: () => schedule(SCROLL_WHEEL_ROWS),
|
|
48804
48405
|
jumpToBottom() {
|
|
48805
48406
|
pendingDelta = 0;
|
|
48806
48407
|
if (flushTimer !== null) {
|
|
@@ -48816,8 +48417,8 @@ function createChatScrollStore() {
|
|
|
48816
48417
|
},
|
|
48817
48418
|
setMaxScroll(rows) {
|
|
48818
48419
|
const m = rows < 0 ? 0 : rows;
|
|
48819
|
-
const currentMax = pendingMaxShrink ??
|
|
48820
|
-
if (
|
|
48420
|
+
const currentMax = pendingMaxShrink ?? state2.maxScroll;
|
|
48421
|
+
if (state2.pinned && m < currentMax) {
|
|
48821
48422
|
pendingMaxShrink = m;
|
|
48822
48423
|
if (shrinkTimer === null) {
|
|
48823
48424
|
shrinkTimer = setTimeout(() => {
|
|
@@ -48828,23 +48429,23 @@ function createChatScrollStore() {
|
|
|
48828
48429
|
return;
|
|
48829
48430
|
}
|
|
48830
48431
|
if (pendingMaxShrink !== null) flushShrink();
|
|
48831
|
-
const nextScrollRows =
|
|
48432
|
+
const nextScrollRows = state2.pinned ? m : Math.min(state2.scrollRows, m);
|
|
48832
48433
|
set({ maxScroll: m, scrollRows: nextScrollRows });
|
|
48833
48434
|
},
|
|
48834
48435
|
setCardHeight(id, rows) {
|
|
48835
|
-
if (
|
|
48836
|
-
const next = new Map(
|
|
48436
|
+
if (state2.cardHeights.get(id) === rows) return;
|
|
48437
|
+
const next = new Map(state2.cardHeights);
|
|
48837
48438
|
next.set(id, rows);
|
|
48838
48439
|
set({ cardHeights: next });
|
|
48839
48440
|
},
|
|
48840
48441
|
pruneCardHeights(liveIds) {
|
|
48841
48442
|
let drop = 0;
|
|
48842
|
-
for (const id of
|
|
48443
|
+
for (const id of state2.cardHeights.keys()) {
|
|
48843
48444
|
if (!liveIds.has(id)) drop++;
|
|
48844
48445
|
}
|
|
48845
48446
|
if (drop === 0) return;
|
|
48846
48447
|
const next = /* @__PURE__ */ new Map();
|
|
48847
|
-
for (const [id, h] of
|
|
48448
|
+
for (const [id, h] of state2.cardHeights) {
|
|
48848
48449
|
if (liveIds.has(id)) next.set(id, h);
|
|
48849
48450
|
}
|
|
48850
48451
|
set({ cardHeights: next });
|
|
@@ -49530,7 +49131,14 @@ var LiveActivityArea = import_react31.default.memo(
|
|
|
49530
49131
|
undoBanner,
|
|
49531
49132
|
hideUndo
|
|
49532
49133
|
}) => {
|
|
49533
|
-
return /* @__PURE__ */ import_react31.default.createElement(Box_default, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, noTakeoverOverlay && ongoingTool ? /* @__PURE__ */ import_react31.default.createElement(
|
|
49134
|
+
return /* @__PURE__ */ import_react31.default.createElement(Box_default, { flexDirection: "column", flexShrink: 0, flexWrap: "nowrap" }, noTakeoverOverlay && ongoingTool ? /* @__PURE__ */ import_react31.default.createElement(
|
|
49135
|
+
OngoingToolRow,
|
|
49136
|
+
{
|
|
49137
|
+
tool: ongoingTool,
|
|
49138
|
+
progress: toolProgress,
|
|
49139
|
+
subagentActivities
|
|
49140
|
+
}
|
|
49141
|
+
) : null, noTakeoverOverlay && subagentActivities.length > 0 ? /* @__PURE__ */ import_react31.default.createElement(SubagentLiveStack, { activities: subagentActivities, max: 3 }) : null, noTakeoverOverlay && !ongoingTool && statusLine ? /* @__PURE__ */ import_react31.default.createElement(ThinkingRow, { text: statusLine }) : null, undoBanner && !hideUndo ? /* @__PURE__ */ import_react31.default.createElement(UndoBanner, { banner: undoBanner }) : null, noTakeoverOverlay && busy && !isStreaming && !ongoingTool && !statusLine ? /* @__PURE__ */ import_react31.default.createElement(ThinkingRow, { text: activityLabel }) : null, noTakeoverOverlay ? /* @__PURE__ */ import_react31.default.createElement(PlanLiveRow, null) : null, /* @__PURE__ */ import_react31.default.createElement(ToastRail, null));
|
|
49534
49142
|
}
|
|
49535
49143
|
);
|
|
49536
49144
|
LiveActivityArea.displayName = "LiveActivityArea";
|
|
@@ -49865,7 +49473,7 @@ function isInstalled(installedSpecs, entry) {
|
|
|
49865
49473
|
}
|
|
49866
49474
|
}
|
|
49867
49475
|
function McpMarketplace({ onClose, postInfo, reloadMcp, pickerPorts }) {
|
|
49868
|
-
const [
|
|
49476
|
+
const [state2, setState] = (0, import_react33.useState)({
|
|
49869
49477
|
handle: null,
|
|
49870
49478
|
loading: true,
|
|
49871
49479
|
query: "",
|
|
@@ -49899,28 +49507,28 @@ function McpMarketplace({ onClose, postInfo, reloadMcp, pickerPorts }) {
|
|
|
49899
49507
|
};
|
|
49900
49508
|
}, []);
|
|
49901
49509
|
const filtered = (0, import_react33.useMemo)(() => {
|
|
49902
|
-
if (!
|
|
49903
|
-
return rankAndFilter(
|
|
49904
|
-
}, [
|
|
49905
|
-
const selected = filtered[
|
|
49510
|
+
if (!state2.handle) return [];
|
|
49511
|
+
return rankAndFilter(state2.handle.cache.entries, state2.query);
|
|
49512
|
+
}, [state2.handle, state2.query]);
|
|
49513
|
+
const selected = filtered[state2.selected];
|
|
49906
49514
|
const fetchMore = (0, import_react33.useCallback)(async () => {
|
|
49907
|
-
if (!
|
|
49908
|
-
if (
|
|
49515
|
+
if (!state2.handle || state2.loading) return;
|
|
49516
|
+
if (state2.handle.cache.pagination.nextCursor === null) {
|
|
49909
49517
|
setState((s) => ({ ...s, status: t("mcpMarketplace.allLoaded") }));
|
|
49910
49518
|
return;
|
|
49911
49519
|
}
|
|
49912
49520
|
setState((s) => ({ ...s, loading: true, status: t("mcpMarketplace.loadingMore") }));
|
|
49913
49521
|
try {
|
|
49914
|
-
const r = await loadMorePages(
|
|
49522
|
+
const r = await loadMorePages(state2.handle, { pages: 5 });
|
|
49915
49523
|
setState((s) => ({
|
|
49916
49524
|
...s,
|
|
49917
49525
|
loading: false,
|
|
49918
|
-
status: `+${r.newEntries} \xB7 ${
|
|
49526
|
+
status: `+${r.newEntries} \xB7 ${state2.handle?.cache.entries.length ?? 0} total${r.exhausted ? " \xB7 exhausted" : ""}`
|
|
49919
49527
|
}));
|
|
49920
49528
|
} catch (err) {
|
|
49921
49529
|
setState((s) => ({ ...s, loading: false, status: `error: ${err.message}` }));
|
|
49922
49530
|
}
|
|
49923
|
-
}, [
|
|
49531
|
+
}, [state2.handle, state2.loading]);
|
|
49924
49532
|
const doUninstall = (0, import_react33.useCallback)(
|
|
49925
49533
|
async (entry, installed) => {
|
|
49926
49534
|
const cfg = readConfig();
|
|
@@ -50005,21 +49613,21 @@ function McpMarketplace({ onClose, postInfo, reloadMcp, pickerPorts }) {
|
|
|
50005
49613
|
);
|
|
50006
49614
|
const installOrToggle = (0, import_react33.useCallback)(
|
|
50007
49615
|
async (entry) => {
|
|
50008
|
-
const installed = isInstalled(
|
|
49616
|
+
const installed = isInstalled(state2.installedSpecs, entry);
|
|
50009
49617
|
if (installed) await doUninstall(entry, installed);
|
|
50010
49618
|
else await doInstall(entry);
|
|
50011
49619
|
},
|
|
50012
|
-
[
|
|
49620
|
+
[state2.installedSpecs, doInstall, doUninstall]
|
|
50013
49621
|
);
|
|
50014
49622
|
const pickerSnapshot = (0, import_react33.useMemo)(
|
|
50015
49623
|
() => buildMarketplacePickerSnapshot({
|
|
50016
49624
|
filtered,
|
|
50017
|
-
installedSpecs:
|
|
50018
|
-
query:
|
|
50019
|
-
status:
|
|
50020
|
-
hasMore:
|
|
49625
|
+
installedSpecs: state2.installedSpecs,
|
|
49626
|
+
query: state2.query,
|
|
49627
|
+
status: state2.status,
|
|
49628
|
+
hasMore: state2.handle?.cache.pagination.nextCursor != null
|
|
50021
49629
|
}),
|
|
50022
|
-
[filtered,
|
|
49630
|
+
[filtered, state2.installedSpecs, state2.handle, state2.query, state2.status]
|
|
50023
49631
|
);
|
|
50024
49632
|
usePickerBroadcast(
|
|
50025
49633
|
!!pickerPorts,
|
|
@@ -50035,9 +49643,9 @@ function McpMarketplace({ onClose, postInfo, reloadMcp, pickerPorts }) {
|
|
|
50035
49643
|
return;
|
|
50036
49644
|
}
|
|
50037
49645
|
if (res.action === "install") {
|
|
50038
|
-
const entry =
|
|
49646
|
+
const entry = state2.handle?.cache.entries.find((e) => e.name === res.id);
|
|
50039
49647
|
if (!entry) return;
|
|
50040
|
-
if (isInstalled(
|
|
49648
|
+
if (isInstalled(state2.installedSpecs, entry)) {
|
|
50041
49649
|
setState((s) => ({ ...s, status: `already installed: ${entry.name}` }));
|
|
50042
49650
|
return;
|
|
50043
49651
|
}
|
|
@@ -50045,9 +49653,9 @@ function McpMarketplace({ onClose, postInfo, reloadMcp, pickerPorts }) {
|
|
|
50045
49653
|
return;
|
|
50046
49654
|
}
|
|
50047
49655
|
if (res.action === "uninstall") {
|
|
50048
|
-
const entry =
|
|
49656
|
+
const entry = state2.handle?.cache.entries.find((e) => e.name === res.id);
|
|
50049
49657
|
if (!entry) return;
|
|
50050
|
-
const installed = isInstalled(
|
|
49658
|
+
const installed = isInstalled(state2.installedSpecs, entry);
|
|
50051
49659
|
if (!installed) {
|
|
50052
49660
|
setState((s) => ({ ...s, status: `not installed: ${entry.name}` }));
|
|
50053
49661
|
return;
|
|
@@ -50094,20 +49702,20 @@ function McpMarketplace({ onClose, postInfo, reloadMcp, pickerPorts }) {
|
|
|
50094
49702
|
const overlay = (0, import_react33.useMemo)(() => loadOverlay("zh-CN"), []);
|
|
50095
49703
|
const start = Math.max(
|
|
50096
49704
|
0,
|
|
50097
|
-
Math.min(
|
|
49705
|
+
Math.min(state2.selected - Math.floor(VISIBLE_ROWS / 2), filtered.length - VISIBLE_ROWS)
|
|
50098
49706
|
);
|
|
50099
49707
|
const window2 = filtered.slice(Math.max(0, start), Math.max(0, start) + VISIBLE_ROWS);
|
|
50100
|
-
return /* @__PURE__ */ import_react33.default.createElement(Box_default, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ import_react33.default.createElement(Box_default, null, /* @__PURE__ */ import_react33.default.createElement(Text, { bold: true, color: COLOR.brand }, "\u25C8 MCP marketplace"), /* @__PURE__ */ import_react33.default.createElement(Text, { dimColor: true }, ` \xB7 ${
|
|
49708
|
+
return /* @__PURE__ */ import_react33.default.createElement(Box_default, { flexDirection: "column", paddingX: 1 }, /* @__PURE__ */ import_react33.default.createElement(Box_default, null, /* @__PURE__ */ import_react33.default.createElement(Text, { bold: true, color: COLOR.brand }, "\u25C8 MCP marketplace"), /* @__PURE__ */ import_react33.default.createElement(Text, { dimColor: true }, ` \xB7 ${state2.status}`)), /* @__PURE__ */ import_react33.default.createElement(Box_default, { marginTop: 1 }, /* @__PURE__ */ import_react33.default.createElement(Text, null, t("mcpMarketplace.filter")), /* @__PURE__ */ import_react33.default.createElement(Text, null, state2.query || t("mcpMarketplace.filterPlaceholder")), /* @__PURE__ */ import_react33.default.createElement(
|
|
50101
49709
|
Text,
|
|
50102
49710
|
{
|
|
50103
49711
|
dimColor: true
|
|
50104
49712
|
},
|
|
50105
49713
|
` ${t(filtered.length === 1 ? "mcpMarketplace.matchSingular" : "mcpMarketplace.matchPlural", { n: filtered.length })}`
|
|
50106
|
-
)), /* @__PURE__ */ import_react33.default.createElement(Box_default, { marginTop: 1, flexDirection: "column" }, window2.length === 0 ? /* @__PURE__ */ import_react33.default.createElement(Text, { dimColor: true },
|
|
49714
|
+
)), /* @__PURE__ */ import_react33.default.createElement(Box_default, { marginTop: 1, flexDirection: "column" }, window2.length === 0 ? /* @__PURE__ */ import_react33.default.createElement(Text, { dimColor: true }, state2.loading ? t("mcpMarketplace.loading") : t("mcpMarketplace.noEntries")) : window2.map((e, i) => {
|
|
50107
49715
|
const idx = (start || 0) + i;
|
|
50108
|
-
const active2 = idx ===
|
|
49716
|
+
const active2 = idx === state2.selected;
|
|
50109
49717
|
const tag2 = e.source === "official" ? "[off]" : e.source === "smithery" ? "[smt]" : "[loc]";
|
|
50110
|
-
const installedSpec = isInstalled(
|
|
49718
|
+
const installedSpec = isInstalled(state2.installedSpecs, e);
|
|
50111
49719
|
const installedBadge = installedSpec ? " \u2713" : "";
|
|
50112
49720
|
const pop = e.popularity !== void 0 ? ` \xB7 ${e.popularity.toLocaleString()}` : "";
|
|
50113
49721
|
return /* @__PURE__ */ import_react33.default.createElement(Box_default, { key: e.name }, /* @__PURE__ */ import_react33.default.createElement(Text, { color: active2 ? COLOR.brand : void 0 }, active2 ? "\u25B8 " : " "), /* @__PURE__ */ import_react33.default.createElement(Text, { bold: active2 }, e.name.padEnd(38).slice(0, 38)), /* @__PURE__ */ import_react33.default.createElement(Text, { dimColor: true }, ` ${tag2}${pop}${installedBadge}`));
|
|
@@ -53053,17 +52661,17 @@ function PlanConfirmInner({ plan: plan2, steps, summary, onChoose }) {
|
|
|
53053
52661
|
return;
|
|
53054
52662
|
}
|
|
53055
52663
|
if (!isDetailScrollKey(ev)) return;
|
|
53056
|
-
if (ev.pageUp
|
|
52664
|
+
if (ev.pageUp) {
|
|
53057
52665
|
setDetailOffset((n) => Math.max(0, n - detailViewRows));
|
|
53058
|
-
} else if (ev.pageDown
|
|
52666
|
+
} else if (ev.pageDown) {
|
|
53059
52667
|
setDetailOffset((n) => Math.min(maxDetailOffset, n + detailViewRows));
|
|
53060
52668
|
} else if (ev.home) {
|
|
53061
52669
|
setDetailOffset(0);
|
|
53062
52670
|
} else if (ev.end) {
|
|
53063
52671
|
setDetailOffset(maxDetailOffset);
|
|
53064
|
-
} else if (ev.upArrow) {
|
|
52672
|
+
} else if (ev.upArrow || ev.mouseScrollUp) {
|
|
53065
52673
|
setDetailOffset((n) => Math.max(0, n - 1));
|
|
53066
|
-
} else if (ev.downArrow) {
|
|
52674
|
+
} else if (ev.downArrow || ev.mouseScrollDown) {
|
|
53067
52675
|
setDetailOffset((n) => Math.min(maxDetailOffset, n + 1));
|
|
53068
52676
|
}
|
|
53069
52677
|
});
|
|
@@ -53601,7 +53209,7 @@ function relativeTime2(date) {
|
|
|
53601
53209
|
}
|
|
53602
53210
|
|
|
53603
53211
|
// src/cli/ui/ShellConfirm.tsx
|
|
53604
|
-
import { homedir as
|
|
53212
|
+
import { homedir as homedir2 } from "os";
|
|
53605
53213
|
var import_react45 = __toESM(require_react(), 1);
|
|
53606
53214
|
var CHROME_ROWS = 18;
|
|
53607
53215
|
var MIN_COMMAND_LINES = 3;
|
|
@@ -53611,7 +53219,7 @@ function clampCommand(command, max) {
|
|
|
53611
53219
|
return { preview: lines.slice(0, max).join("\n"), hidden: lines.length - max };
|
|
53612
53220
|
}
|
|
53613
53221
|
function tildeify2(path) {
|
|
53614
|
-
const home =
|
|
53222
|
+
const home = homedir2();
|
|
53615
53223
|
if (!home) return path;
|
|
53616
53224
|
const normalized = home.replace(/[\\/]+$/, "");
|
|
53617
53225
|
if (path === normalized) return "~";
|
|
@@ -53944,13 +53552,13 @@ function wrapToCells(s, maxCells) {
|
|
|
53944
53552
|
}
|
|
53945
53553
|
|
|
53946
53554
|
// src/cli/ui/clipboard.ts
|
|
53947
|
-
import { mkdtempSync as mkdtempSync2, writeFileSync as
|
|
53555
|
+
import { mkdtempSync as mkdtempSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
53948
53556
|
import { tmpdir as tmpdir2 } from "os";
|
|
53949
|
-
import { join as
|
|
53557
|
+
import { join as join4 } from "path";
|
|
53950
53558
|
var OSC_52_LIMIT = 75e3;
|
|
53951
53559
|
function writeClipboard(text) {
|
|
53952
|
-
const dir = mkdtempSync2(
|
|
53953
|
-
const filePath =
|
|
53560
|
+
const dir = mkdtempSync2(join4(tmpdir2(), "reasonix-clip-"));
|
|
53561
|
+
const filePath = join4(dir, "clip.txt");
|
|
53954
53562
|
let osc52 = false;
|
|
53955
53563
|
if (text.length <= OSC_52_LIMIT) {
|
|
53956
53564
|
const b64 = Buffer.from(text, "utf8").toString("base64");
|
|
@@ -53959,7 +53567,7 @@ function writeClipboard(text) {
|
|
|
53959
53567
|
}
|
|
53960
53568
|
let writtenPath = null;
|
|
53961
53569
|
try {
|
|
53962
|
-
|
|
53570
|
+
writeFileSync4(filePath, text, "utf8");
|
|
53963
53571
|
writtenPath = filePath;
|
|
53964
53572
|
} catch {
|
|
53965
53573
|
}
|
|
@@ -54234,9 +53842,9 @@ function loopEventToDashboard(ev, ctx) {
|
|
|
54234
53842
|
}
|
|
54235
53843
|
|
|
54236
53844
|
// src/cli/ui/hash-memory.ts
|
|
54237
|
-
import { closeSync, fstatSync, mkdirSync as
|
|
54238
|
-
import { homedir as
|
|
54239
|
-
import { dirname as
|
|
53845
|
+
import { closeSync, fstatSync, mkdirSync as mkdirSync3, openSync, readSync, writeSync } from "fs";
|
|
53846
|
+
import { homedir as homedir3 } from "os";
|
|
53847
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
54240
53848
|
var PROJECT_HEADER = `# Reasonix project memory
|
|
54241
53849
|
|
|
54242
53850
|
Notes the user pinned via the \`#\` prompt prefix. The whole file is
|
|
@@ -54272,8 +53880,8 @@ function appendProjectMemory(rootDir, note) {
|
|
|
54272
53880
|
}
|
|
54273
53881
|
var GLOBAL_MEMORY_DIR = ".reasonix";
|
|
54274
53882
|
var GLOBAL_MEMORY_FILE = "REASONIX.md";
|
|
54275
|
-
function globalMemoryPath(homeDir =
|
|
54276
|
-
return
|
|
53883
|
+
function globalMemoryPath(homeDir = homedir3()) {
|
|
53884
|
+
return join5(homeDir, GLOBAL_MEMORY_DIR, GLOBAL_MEMORY_FILE);
|
|
54277
53885
|
}
|
|
54278
53886
|
function appendGlobalMemory(note, homeDir) {
|
|
54279
53887
|
return appendBulletToFile(globalMemoryPath(homeDir), note, GLOBAL_HEADER);
|
|
@@ -54283,7 +53891,7 @@ function appendBulletToFile(path, note, newFileHeader) {
|
|
|
54283
53891
|
if (!trimmed) throw new Error("note body cannot be empty");
|
|
54284
53892
|
const bullet2 = `- ${trimmed}
|
|
54285
53893
|
`;
|
|
54286
|
-
|
|
53894
|
+
mkdirSync3(dirname3(path), { recursive: true });
|
|
54287
53895
|
const fd = openSync(path, "a+");
|
|
54288
53896
|
try {
|
|
54289
53897
|
const stat = fstatSync(fd);
|
|
@@ -54454,16 +54062,22 @@ function handleToolEvent(ev, ctx) {
|
|
|
54454
54062
|
const parsed = JSON.parse(ev.content);
|
|
54455
54063
|
const stepId = parsed.stepId;
|
|
54456
54064
|
if (parsed.kind === "step_completed" && typeof stepId === "string") {
|
|
54065
|
+
const fullCompletion = ctx.pendingStepCompletionsRef?.current.get(stepId);
|
|
54066
|
+
ctx.pendingStepCompletionsRef?.current.delete(stepId);
|
|
54067
|
+
const completion = fullCompletion ?? parsed;
|
|
54457
54068
|
ctx.completedStepIdsRef.current.add(stepId);
|
|
54458
|
-
ctx.stepCompletionsRef?.current.set(stepId,
|
|
54069
|
+
ctx.stepCompletionsRef?.current.set(stepId, completion);
|
|
54459
54070
|
ctx.persistPlanState();
|
|
54460
54071
|
ctx.log.completePlanStep(stepId);
|
|
54461
54072
|
ctx.onPlanStepCompleted?.(stepId);
|
|
54462
54073
|
const total = ctx.planStepsRef.current?.length ?? 0;
|
|
54463
54074
|
const completed = ctx.completedStepIdsRef.current.size;
|
|
54464
54075
|
const stepFromPlan = ctx.planStepsRef.current?.find((s) => s.id === stepId);
|
|
54465
|
-
const title2 = parsed.title ?? stepFromPlan?.title;
|
|
54076
|
+
const title2 = completion.title ?? parsed.title ?? stepFromPlan?.title;
|
|
54466
54077
|
if (title2) ctx.log.pushStepProgress(completed, total, title2);
|
|
54078
|
+
const compactEvidenceSummary = typeof parsed.evidenceSummary === "string" && parsed.evidenceSummary.trim() ? `evidence: ${parsed.evidenceSummary.trim()}` : null;
|
|
54079
|
+
const evidenceSummary = formatStepEvidenceSummary(completion.evidence) ?? compactEvidenceSummary;
|
|
54080
|
+
if (evidenceSummary) ctx.log.pushInfo(evidenceSummary, "ghost");
|
|
54467
54081
|
if (ctx.session && total > 0 && completed >= total) {
|
|
54468
54082
|
const archive = archivePlanState(ctx.session);
|
|
54469
54083
|
if (archive) {
|
|
@@ -54475,6 +54089,20 @@ function handleToolEvent(ev, ctx) {
|
|
|
54475
54089
|
}
|
|
54476
54090
|
}
|
|
54477
54091
|
}
|
|
54092
|
+
function formatStepEvidenceSummary(evidence) {
|
|
54093
|
+
if (!evidence || evidence.length === 0) return null;
|
|
54094
|
+
const parts = evidence.map(formatStepEvidenceItem).filter((part) => part.length > 0);
|
|
54095
|
+
if (parts.length === 0) return null;
|
|
54096
|
+
return `evidence: ${parts.join("; ")}`;
|
|
54097
|
+
}
|
|
54098
|
+
function formatStepEvidenceItem(evidence) {
|
|
54099
|
+
const extras = [];
|
|
54100
|
+
if (evidence.command) extras.push(evidence.command);
|
|
54101
|
+
if (evidence.paths && evidence.paths.length > 0)
|
|
54102
|
+
extras.push(evidence.paths.slice(0, 3).join(", "));
|
|
54103
|
+
const suffix = extras.length > 0 ? ` (${extras.join("; ")})` : "";
|
|
54104
|
+
return `${evidence.kind} - ${evidence.summary}${suffix}`;
|
|
54105
|
+
}
|
|
54478
54106
|
|
|
54479
54107
|
// src/cli/ui/hooks/useActivityPhase.ts
|
|
54480
54108
|
function deriveActivityLabel(cards) {
|
|
@@ -56235,7 +55863,7 @@ function headerColorFor(s) {
|
|
|
56235
55863
|
function metaTrail(card) {
|
|
56236
55864
|
const parts = [];
|
|
56237
55865
|
const inputBytes = largestStringInputBytes(card.args);
|
|
56238
|
-
if (inputBytes !== null) parts.push(t("cardLabels.bytesIn", { bytes:
|
|
55866
|
+
if (inputBytes !== null) parts.push(t("cardLabels.bytesIn", { bytes: formatBytes2(inputBytes) }));
|
|
56239
55867
|
if (card.elapsedMs > 0)
|
|
56240
55868
|
parts.push(t("cardLabels.elapsedSec", { secs: (card.elapsedMs / 1e3).toFixed(2) }));
|
|
56241
55869
|
if (card.done && !card.rejected && !card.aborted && card.exitCode !== void 0 && card.exitCode !== 0) {
|
|
@@ -56270,7 +55898,7 @@ function largestStringInputBytes(args) {
|
|
|
56270
55898
|
}
|
|
56271
55899
|
return max >= INPUT_SIZE_THRESHOLD ? max : null;
|
|
56272
55900
|
}
|
|
56273
|
-
function
|
|
55901
|
+
function formatBytes2(n) {
|
|
56274
55902
|
if (n < 1024) return `${n} B`;
|
|
56275
55903
|
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
56276
55904
|
return `${(n / (1024 * 1024)).toFixed(1)} MB`;
|
|
@@ -56586,9 +56214,9 @@ function formatResourceList(servers) {
|
|
|
56586
56214
|
lines.push("");
|
|
56587
56215
|
}
|
|
56588
56216
|
if (total === 0) {
|
|
56589
|
-
return "
|
|
56217
|
+
return t("mcpBrowse.noResources");
|
|
56590
56218
|
}
|
|
56591
|
-
lines.push("
|
|
56219
|
+
lines.push(t("mcpBrowse.readOne"));
|
|
56592
56220
|
return lines.join("\n");
|
|
56593
56221
|
}
|
|
56594
56222
|
function formatPromptList(servers) {
|
|
@@ -56609,11 +56237,9 @@ function formatPromptList(servers) {
|
|
|
56609
56237
|
lines.push("");
|
|
56610
56238
|
}
|
|
56611
56239
|
if (total === 0) {
|
|
56612
|
-
return "
|
|
56240
|
+
return t("mcpBrowse.noPrompts");
|
|
56613
56241
|
}
|
|
56614
|
-
lines.push(
|
|
56615
|
-
"Fetch one: `/prompt <name>` \u2014 args are not supported yet; prompts with required args will surface an error from the server."
|
|
56616
|
-
);
|
|
56242
|
+
lines.push(t("mcpBrowse.fetchOne"));
|
|
56617
56243
|
return lines.join("\n");
|
|
56618
56244
|
}
|
|
56619
56245
|
function findServerForResource(servers, uri) {
|
|
@@ -56769,7 +56395,7 @@ function formatLongPaste(input, opts = {}) {
|
|
|
56769
56395
|
if (originalChars <= charCap && originalLines <= lineCap) {
|
|
56770
56396
|
return { displayText: input, collapsed: false, originalChars, originalLines };
|
|
56771
56397
|
}
|
|
56772
|
-
const header = `\u25B8 pasted ${
|
|
56398
|
+
const header = `\u25B8 pasted ${formatBytes3(originalChars)} (${originalLines} lines) \u2014 first ${Math.min(headN, originalLines)} shown, full text sent to model`;
|
|
56773
56399
|
const head = lines.slice(0, headN).join("\n");
|
|
56774
56400
|
const remaining = originalLines - headN;
|
|
56775
56401
|
const footer = remaining > 0 ? `\u2026 (${remaining} more line${remaining === 1 ? "" : "s"})` : "";
|
|
@@ -56779,7 +56405,7 @@ ${footer}` : `${header}
|
|
|
56779
56405
|
${head}`;
|
|
56780
56406
|
return { displayText, collapsed: true, originalChars, originalLines };
|
|
56781
56407
|
}
|
|
56782
|
-
function
|
|
56408
|
+
function formatBytes3(n) {
|
|
56783
56409
|
if (n < 1024) return `${n} B`;
|
|
56784
56410
|
const kb = n / 1024;
|
|
56785
56411
|
if (kb < 1024) return `${kb.toFixed(kb >= 10 ? 0 : 1)} KB`;
|
|
@@ -56915,6 +56541,9 @@ var handlers = {
|
|
|
56915
56541
|
};
|
|
56916
56542
|
|
|
56917
56543
|
// src/cli/ui/slash/handlers/basic.ts
|
|
56544
|
+
var ABOUT_WEBSITE = "https://esengine.github.io/DeepSeek-Reasonix/";
|
|
56545
|
+
var ABOUT_REPO = "https://github.com/esengine/DeepSeek-Reasonix";
|
|
56546
|
+
var ABOUT_LICENSE = "MIT";
|
|
56918
56547
|
var exit = () => ({ exit: true });
|
|
56919
56548
|
var resetLog = (_args, loop2) => {
|
|
56920
56549
|
const { dropped, archived, systemRebuilt } = loop2.clearLog();
|
|
@@ -57042,6 +56671,16 @@ var keys = (_args, _loop, ctx) => {
|
|
|
57042
56671
|
return {};
|
|
57043
56672
|
};
|
|
57044
56673
|
var copy = () => ({ openCopyMode: true });
|
|
56674
|
+
var about = () => {
|
|
56675
|
+
const lines = [
|
|
56676
|
+
t("handlers.basic.aboutHeader", { version: VERSION }),
|
|
56677
|
+
"",
|
|
56678
|
+
` ${t("handlers.basic.aboutWebsiteLabel")} ${ABOUT_WEBSITE}`,
|
|
56679
|
+
` ${t("handlers.basic.aboutRepoLabel")} ${ABOUT_REPO}`,
|
|
56680
|
+
` ${t("handlers.basic.aboutLicenseLabel")} ${ABOUT_LICENSE}`
|
|
56681
|
+
];
|
|
56682
|
+
return { info: lines.join("\n") };
|
|
56683
|
+
};
|
|
57045
56684
|
var handlers2 = {
|
|
57046
56685
|
exit,
|
|
57047
56686
|
new: resetLog,
|
|
@@ -57049,7 +56688,8 @@ var handlers2 = {
|
|
|
57049
56688
|
retry,
|
|
57050
56689
|
loop,
|
|
57051
56690
|
keys,
|
|
57052
|
-
copy
|
|
56691
|
+
copy,
|
|
56692
|
+
about
|
|
57053
56693
|
};
|
|
57054
56694
|
|
|
57055
56695
|
// src/cli/ui/slash/handlers/dashboard.ts
|
|
@@ -57219,7 +56859,7 @@ var plan = (args, _loop, ctx) => {
|
|
|
57219
56859
|
if (raw === "on" || raw === "true" || raw === "1" || raw === "strict") target = true;
|
|
57220
56860
|
else if (raw === "off" || raw === "false" || raw === "0") target = false;
|
|
57221
56861
|
else target = !currentOn;
|
|
57222
|
-
ctx.setPlanMode(target);
|
|
56862
|
+
ctx.setPlanMode(target, "slash");
|
|
57223
56863
|
if (target) {
|
|
57224
56864
|
return { info: t("handlers.edits.planOn") };
|
|
57225
56865
|
}
|
|
@@ -58799,7 +58439,7 @@ var handlers17 = {
|
|
|
58799
58439
|
var handlers18 = {
|
|
58800
58440
|
"search-engine": (args, _loop, ctx) => {
|
|
58801
58441
|
const engine = args[0];
|
|
58802
|
-
if (!engine || engine !== "mojeek" && engine !== "searxng" && engine !== "metaso" && engine !== "tavily") {
|
|
58442
|
+
if (!engine || engine !== "mojeek" && engine !== "searxng" && engine !== "metaso" && engine !== "tavily" && engine !== "perplexity" && engine !== "exa") {
|
|
58803
58443
|
return {
|
|
58804
58444
|
info: [
|
|
58805
58445
|
t("handlers.webSearchEngine.currentEngine", { engine: webSearchEngine() }),
|
|
@@ -58811,6 +58451,8 @@ var handlers18 = {
|
|
|
58811
58451
|
t("handlers.webSearchEngine.usageSearxngUrl"),
|
|
58812
58452
|
t("handlers.webSearchEngine.usageMetaso"),
|
|
58813
58453
|
t("handlers.webSearchEngine.usageTavily"),
|
|
58454
|
+
t("handlers.webSearchEngine.usagePerplexity"),
|
|
58455
|
+
t("handlers.webSearchEngine.usageExa"),
|
|
58814
58456
|
"",
|
|
58815
58457
|
t("handlers.webSearchEngine.alias"),
|
|
58816
58458
|
"",
|
|
@@ -58820,14 +58462,33 @@ var handlers18 = {
|
|
|
58820
58462
|
};
|
|
58821
58463
|
}
|
|
58822
58464
|
const cfg = readConfig();
|
|
58465
|
+
const apiKeyEngines = /* @__PURE__ */ new Set(["tavily", "perplexity", "exa", "metaso"]);
|
|
58466
|
+
if (apiKeyEngines.has(engine)) {
|
|
58467
|
+
const loadKey = engine === "tavily" ? loadTavilyApiKey : engine === "perplexity" ? loadPerplexityApiKey : engine === "exa" ? loadExaApiKey : loadMetasoApiKey;
|
|
58468
|
+
if (args[1]) {
|
|
58469
|
+
cfg.webSearchEngine = engine;
|
|
58470
|
+
cfg[`${engine}ApiKey`] = args[1];
|
|
58471
|
+
writeConfig(cfg);
|
|
58472
|
+
return {
|
|
58473
|
+
info: `${t("handlers.webSearchEngine.confirmed", { engine, detail: "" })} ${t("handlers.webSearchEngine.keySaved")}`
|
|
58474
|
+
};
|
|
58475
|
+
}
|
|
58476
|
+
const existingKey = loadKey();
|
|
58477
|
+
if (existingKey) {
|
|
58478
|
+
cfg.webSearchEngine = engine;
|
|
58479
|
+
writeConfig(cfg);
|
|
58480
|
+
return { info: t("handlers.webSearchEngine.confirmed", { engine, detail: "" }) };
|
|
58481
|
+
}
|
|
58482
|
+
const envVar = `${engine.toUpperCase()}_API_KEY`;
|
|
58483
|
+
return { info: t("handlers.webSearchEngine.keyNeeded", { engine, envVar }) };
|
|
58484
|
+
}
|
|
58823
58485
|
cfg.webSearchEngine = engine;
|
|
58824
58486
|
if (engine === "searxng" && args[1]) {
|
|
58825
58487
|
const raw = args[1];
|
|
58826
58488
|
cfg.webSearchEndpoint = raw.includes("://") ? raw : `http://${raw}`;
|
|
58827
58489
|
}
|
|
58828
58490
|
writeConfig(cfg);
|
|
58829
|
-
const note = engine === "searxng" ? t("handlers.webSearchEngine.switchedSearxngNote", { endpoint: webSearchEndpoint() }) : engine === "metaso" ? t("handlers.webSearchEngine.switchedMetasoNote") : engine === "tavily" ? t("handlers.webSearchEngine.switchedTavilyNote") : "";
|
|
58830
|
-
ctx.postInfo?.(t("handlers.webSearchEngine.switched", { engine, note }));
|
|
58491
|
+
const note = engine === "searxng" ? t("handlers.webSearchEngine.switchedSearxngNote", { endpoint: webSearchEndpoint() }) : engine === "metaso" ? t("handlers.webSearchEngine.switchedMetasoNote") : engine === "tavily" ? t("handlers.webSearchEngine.switchedTavilyNote") : engine === "perplexity" ? t("handlers.webSearchEngine.switchedPerplexityNote") : engine === "exa" ? t("handlers.webSearchEngine.switchedExaNote") : "";
|
|
58831
58492
|
const detail = engine === "searxng" ? t("handlers.webSearchEngine.confirmedDetail", { endpoint: webSearchEndpoint() }) : "";
|
|
58832
58493
|
return { info: t("handlers.webSearchEngine.confirmed", { engine, detail }) };
|
|
58833
58494
|
},
|
|
@@ -59662,35 +59323,31 @@ function useEditHistory(codeMode) {
|
|
|
59662
59323
|
[codeMode]
|
|
59663
59324
|
);
|
|
59664
59325
|
const codeHistory = (0, import_react89.useCallback)(() => {
|
|
59665
|
-
if (!codeMode) return "
|
|
59326
|
+
if (!codeMode) return t("app.editHistoryNoCodeMode");
|
|
59666
59327
|
const entries = editHistory.current;
|
|
59667
|
-
if (entries.length === 0) return "
|
|
59668
|
-
const lines = ["
|
|
59328
|
+
if (entries.length === 0) return t("app.editHistoryNoEdits");
|
|
59329
|
+
const lines = [t("app.editHistoryTitle")];
|
|
59669
59330
|
for (const e of entries) {
|
|
59670
59331
|
const when = new Date(e.at).toISOString().replace("T", " ").slice(11, 19);
|
|
59671
59332
|
const files = new Set(e.blocks.map((b) => b.path));
|
|
59672
59333
|
const fileList = [...files].join(", ");
|
|
59673
59334
|
const fileSummary = fileList.length > 60 ? `${fileList.slice(0, 60)}\u2026` : fileList;
|
|
59674
59335
|
const status2 = entryStatus(e);
|
|
59675
|
-
const statusText = status2 === "applied" ? "
|
|
59336
|
+
const statusText = status2 === "applied" ? t("app.editHistoryStatusApplied") : status2 === "PARTIAL" ? t("app.editHistoryStatusPartial") : t("app.editHistoryStatusUndone");
|
|
59676
59337
|
lines.push(
|
|
59677
59338
|
` #${String(e.id).padStart(3)} ${when} ${statusText} ${e.source.padEnd(12)} ${files.size} file \xB7 ${e.blocks.length} block ${fileSummary}`
|
|
59678
59339
|
);
|
|
59679
59340
|
}
|
|
59680
59341
|
lines.push("");
|
|
59681
|
-
lines.push(
|
|
59682
|
-
|
|
59683
|
-
);
|
|
59684
|
-
lines.push(
|
|
59685
|
-
"/undo \u2192 newest non-undone \xB7 /undo <id> [path] \u2192 target a specific batch or file"
|
|
59686
|
-
);
|
|
59342
|
+
lines.push(t("app.editHistoryHelpShow"));
|
|
59343
|
+
lines.push(t("app.editHistoryHelpUndo"));
|
|
59687
59344
|
return lines.join("\n");
|
|
59688
59345
|
}, [codeMode]);
|
|
59689
59346
|
const codeShowEdit = (0, import_react89.useCallback)(
|
|
59690
59347
|
(args = []) => {
|
|
59691
|
-
if (!codeMode) return "
|
|
59348
|
+
if (!codeMode) return t("app.editHistoryNoCodeMode");
|
|
59692
59349
|
const entries = editHistory.current;
|
|
59693
|
-
if (entries.length === 0) return "
|
|
59350
|
+
if (entries.length === 0) return t("app.editHistoryNoEdits2");
|
|
59694
59351
|
const idArg = args[0];
|
|
59695
59352
|
const pathArg = args[1];
|
|
59696
59353
|
let entry;
|
|
@@ -59699,23 +59356,27 @@ function useEditHistory(codeMode) {
|
|
|
59699
59356
|
} else {
|
|
59700
59357
|
const id = Number.parseInt(idArg, 10);
|
|
59701
59358
|
if (!Number.isFinite(id)) {
|
|
59702
|
-
return "
|
|
59359
|
+
return t("app.editHistoryNoShowId");
|
|
59703
59360
|
}
|
|
59704
59361
|
entry = entries.find((e) => e.id === id);
|
|
59705
|
-
if (!entry) return
|
|
59362
|
+
if (!entry) return t("app.editHistoryIdNotFound", { id });
|
|
59706
59363
|
}
|
|
59707
|
-
if (!entry) return "
|
|
59364
|
+
if (!entry) return t("app.editHistoryLookupFailed");
|
|
59708
59365
|
if (pathArg) {
|
|
59709
59366
|
const fileBlocks = entry.blocks.filter((b) => b.path === pathArg);
|
|
59710
59367
|
if (fileBlocks.length === 0) {
|
|
59711
59368
|
const files2 = [...new Set(entry.blocks.map((b) => b.path))];
|
|
59712
|
-
return
|
|
59369
|
+
return t("app.editHistoryBatchNoFile", {
|
|
59370
|
+
id: entry.id,
|
|
59371
|
+
path: pathArg,
|
|
59372
|
+
files: files2.join(", ")
|
|
59373
|
+
});
|
|
59713
59374
|
}
|
|
59714
59375
|
const when2 = new Date(entry.at).toISOString().replace("T", " ").slice(11, 19);
|
|
59715
|
-
const
|
|
59716
|
-
const header2 = `\u25B8 edit #${entry.id} \xB7 ${when2} \xB7 ${pathArg} \xB7 ${
|
|
59376
|
+
const state2 = entry.undoneFiles.has(pathArg) ? "UNDONE" : "applied";
|
|
59377
|
+
const header2 = `\u25B8 edit #${entry.id} \xB7 ${when2} \xB7 ${pathArg} \xB7 ${state2} \xB7 ${fileBlocks.length} block(s)`;
|
|
59717
59378
|
const diff = formatAllBlockDiffs(fileBlocks, { maxLines: 60, contextLines: 2 });
|
|
59718
|
-
const footer = entry.undoneFiles.has(pathArg) ? "
|
|
59379
|
+
const footer = entry.undoneFiles.has(pathArg) ? t("app.editHistoryAlreadyReverted") : t("app.editHistoryRevertFile", { id: entry.id, path: pathArg });
|
|
59719
59380
|
return [header2, ...diff, "", footer].join("\n");
|
|
59720
59381
|
}
|
|
59721
59382
|
const when = new Date(entry.at).toISOString().replace("T", " ").slice(11, 19);
|
|
@@ -59731,8 +59392,8 @@ function useEditHistory(codeMode) {
|
|
|
59731
59392
|
removed += countLines2(b.search);
|
|
59732
59393
|
added += countLines2(b.replace);
|
|
59733
59394
|
}
|
|
59734
|
-
const
|
|
59735
|
-
return ` ${
|
|
59395
|
+
const state2 = entry.undoneFiles.has(path) ? "UNDONE" : "applied";
|
|
59396
|
+
return ` ${state2.padEnd(7)} -${String(removed).padStart(3)}/+${String(added).padStart(3)} ${path} (${fileBlocks.length} block${fileBlocks.length === 1 ? "" : "s"})`;
|
|
59736
59397
|
});
|
|
59737
59398
|
return [
|
|
59738
59399
|
header,
|
|
@@ -59870,6 +59531,18 @@ function reduceSubagentInnerEvent(prev, ev) {
|
|
|
59870
59531
|
return { ...a, phase };
|
|
59871
59532
|
});
|
|
59872
59533
|
}
|
|
59534
|
+
if (ev.kind === "stream-progress") {
|
|
59535
|
+
return mapMatchingRun(prev, ev.runId, (a) => {
|
|
59536
|
+
const outputChars = ev.outputChars ?? a.outputChars;
|
|
59537
|
+
const reasoningChars = ev.reasoningChars ?? a.reasoningChars;
|
|
59538
|
+
const toolReadChars = ev.toolReadChars ?? a.toolReadChars;
|
|
59539
|
+
const elapsedMs = ev.elapsedMs ?? a.elapsedMs;
|
|
59540
|
+
if (outputChars === a.outputChars && reasoningChars === a.reasoningChars && toolReadChars === a.toolReadChars && elapsedMs === a.elapsedMs) {
|
|
59541
|
+
return a;
|
|
59542
|
+
}
|
|
59543
|
+
return { ...a, outputChars, reasoningChars, toolReadChars, elapsedMs };
|
|
59544
|
+
});
|
|
59545
|
+
}
|
|
59873
59546
|
return prev;
|
|
59874
59547
|
}
|
|
59875
59548
|
function mapMatchingRun(prev, runId, fn) {
|
|
@@ -59923,7 +59596,7 @@ function useSubagent({
|
|
|
59923
59596
|
getWalletCurrency
|
|
59924
59597
|
}) {
|
|
59925
59598
|
const [activities, setActivities] = (0, import_react91.useState)([]);
|
|
59926
|
-
const sinkRef = (0, import_react91.useRef)(
|
|
59599
|
+
const sinkRef = (0, import_react91.useRef)(SHARED_SUBAGENT_SINK);
|
|
59927
59600
|
const getWalletCurrencyRef = (0, import_react91.useRef)(getWalletCurrency);
|
|
59928
59601
|
(0, import_react91.useEffect)(() => {
|
|
59929
59602
|
getWalletCurrencyRef.current = getWalletCurrency;
|
|
@@ -59942,7 +59615,10 @@ function useSubagent({
|
|
|
59942
59615
|
skillName: ev.skillName,
|
|
59943
59616
|
model: ev.model,
|
|
59944
59617
|
phase: "exploring",
|
|
59945
|
-
lastInner: null
|
|
59618
|
+
lastInner: null,
|
|
59619
|
+
outputChars: 0,
|
|
59620
|
+
reasoningChars: 0,
|
|
59621
|
+
toolReadChars: 0
|
|
59946
59622
|
};
|
|
59947
59623
|
return [...prev, next];
|
|
59948
59624
|
});
|
|
@@ -60274,6 +59950,7 @@ function AppInner({
|
|
|
60274
59950
|
const planStepsRef = (0, import_react92.useRef)(null);
|
|
60275
59951
|
const completedStepIdsRef = (0, import_react92.useRef)(/* @__PURE__ */ new Set());
|
|
60276
59952
|
const stepCompletionsRef = (0, import_react92.useRef)(/* @__PURE__ */ new Map());
|
|
59953
|
+
const pendingStepCompletionsRef = (0, import_react92.useRef)(/* @__PURE__ */ new Map());
|
|
60277
59954
|
const planBodyRef = (0, import_react92.useRef)(null);
|
|
60278
59955
|
const planSummaryRef = (0, import_react92.useRef)(null);
|
|
60279
59956
|
const toolStartedAtRef = (0, import_react92.useRef)(null);
|
|
@@ -60827,6 +60504,7 @@ run \`reasonix setup\` to remove this entry, or fix the underlying issue (missin
|
|
|
60827
60504
|
planStepsRef.current = restoredPlan.steps;
|
|
60828
60505
|
completedStepIdsRef.current = new Set(restoredPlan.completedStepIds);
|
|
60829
60506
|
stepCompletionsRef.current = new Map(Object.entries(restoredPlan.stepCompletions ?? {}));
|
|
60507
|
+
pendingStepCompletionsRef.current = /* @__PURE__ */ new Map();
|
|
60830
60508
|
planBodyRef.current = restoredPlan.body ?? null;
|
|
60831
60509
|
planSummaryRef.current = restoredPlan.summary ?? null;
|
|
60832
60510
|
engineeringLifecycleRef.current?.recordPlanApproved(restoredPlan.steps);
|
|
@@ -60871,8 +60549,10 @@ run \`reasonix setup\` to remove this entry, or fix the underlying issue (missin
|
|
|
60871
60549
|
});
|
|
60872
60550
|
});
|
|
60873
60551
|
useKeystroke((ev) => {
|
|
60874
|
-
if (ev.pageUp
|
|
60875
|
-
else if (ev.pageDown
|
|
60552
|
+
if (ev.pageUp) chatScroll.scrollPageUp();
|
|
60553
|
+
else if (ev.pageDown) chatScroll.scrollPageDown();
|
|
60554
|
+
else if (ev.mouseScrollUp) chatScroll.scrollWheelUp();
|
|
60555
|
+
else if (ev.mouseScrollDown) chatScroll.scrollWheelDown();
|
|
60876
60556
|
else if (ev.end) chatScroll.jumpToBottom();
|
|
60877
60557
|
else if (!composerPinned && ev.upArrow) chatScroll.scrollUp();
|
|
60878
60558
|
else if (!composerPinned && ev.downArrow) chatScroll.scrollDown();
|
|
@@ -61096,14 +60776,16 @@ run \`reasonix setup\` to remove this entry, or fix the underlying issue (missin
|
|
|
61096
60776
|
const prefixHash = loop2.prefix.fingerprint;
|
|
61097
60777
|
const writeTranscript = useTranscriptWriter(transcriptRef, model2, prefixHash);
|
|
61098
60778
|
const togglePlanMode = (0, import_react92.useCallback)(
|
|
61099
|
-
(on) => {
|
|
60779
|
+
(on, source) => {
|
|
61100
60780
|
setPlanMode(on);
|
|
61101
60781
|
tools?.setPlanMode(on);
|
|
61102
60782
|
if (on) {
|
|
61103
60783
|
engineeringLifecycleRef.current?.setMode("strict");
|
|
60784
|
+
} else if (source === "slash") {
|
|
60785
|
+
engineeringLifecycleRef.current?.setMode("off");
|
|
61104
60786
|
} else {
|
|
61105
|
-
const
|
|
61106
|
-
if (
|
|
60787
|
+
const state2 = engineeringLifecycleRef.current?.snapshot().state;
|
|
60788
|
+
if (state2 === void 0 || state2 === "idle" || state2 === "complete" || state2 === "cancelled") {
|
|
61107
60789
|
engineeringLifecycleRef.current?.setMode(engineeringLifecycleBaseModeRef.current);
|
|
61108
60790
|
}
|
|
61109
60791
|
}
|
|
@@ -61133,7 +60815,7 @@ run \`reasonix setup\` to remove this entry, or fix the underlying issue (missin
|
|
|
61133
60815
|
if (dashboardRef.current) return dashboardRef.current.url;
|
|
61134
60816
|
if (dashboardStartingRef.current) return dashboardStartingRef.current;
|
|
61135
60817
|
const startup = (async () => {
|
|
61136
|
-
const { startDashboardServer } = await import("./server-
|
|
60818
|
+
const { startDashboardServer } = await import("./server-NHQ3QXOZ.js");
|
|
61137
60819
|
const handle = await startDashboardServer(
|
|
61138
60820
|
{
|
|
61139
60821
|
mode: "attached",
|
|
@@ -61155,8 +60837,8 @@ run \`reasonix setup\` to remove this entry, or fix the underlying issue (missin
|
|
|
61155
60837
|
saveEditMode(m);
|
|
61156
60838
|
return m;
|
|
61157
60839
|
},
|
|
61158
|
-
setPlanMode: (on) => {
|
|
61159
|
-
if (codeMode) togglePlanMode(on);
|
|
60840
|
+
setPlanMode: (on, source) => {
|
|
60841
|
+
if (codeMode) togglePlanMode(on, source);
|
|
61160
60842
|
},
|
|
61161
60843
|
applyPresetLive: (name) => {
|
|
61162
60844
|
const settings = resolvePreset(name);
|
|
@@ -62079,6 +61761,7 @@ ${answer}`, "brand");
|
|
|
62079
61761
|
planStepsRef,
|
|
62080
61762
|
completedStepIdsRef,
|
|
62081
61763
|
stepCompletionsRef,
|
|
61764
|
+
pendingStepCompletionsRef,
|
|
62082
61765
|
planBodyRef,
|
|
62083
61766
|
planSummaryRef,
|
|
62084
61767
|
persistPlanState,
|
|
@@ -62352,6 +62035,7 @@ ${answer}`, "brand");
|
|
|
62352
62035
|
if (approvedSteps && approvedSteps.length > 0) {
|
|
62353
62036
|
completedStepIdsRef.current = /* @__PURE__ */ new Set();
|
|
62354
62037
|
stepCompletionsRef.current = /* @__PURE__ */ new Map();
|
|
62038
|
+
pendingStepCompletionsRef.current = /* @__PURE__ */ new Map();
|
|
62355
62039
|
log.showPlan({
|
|
62356
62040
|
title: planSummaryRef.current ?? "plan",
|
|
62357
62041
|
steps: approvedSteps.map((s) => ({
|
|
@@ -62368,6 +62052,7 @@ ${answer}`, "brand");
|
|
|
62368
62052
|
planStepsRef.current = null;
|
|
62369
62053
|
completedStepIdsRef.current = /* @__PURE__ */ new Set();
|
|
62370
62054
|
stepCompletionsRef.current = /* @__PURE__ */ new Map();
|
|
62055
|
+
pendingStepCompletionsRef.current = /* @__PURE__ */ new Map();
|
|
62371
62056
|
planBodyRef.current = null;
|
|
62372
62057
|
planSummaryRef.current = null;
|
|
62373
62058
|
persistPlanState();
|
|
@@ -62475,17 +62160,22 @@ ${answer}`, "brand");
|
|
|
62475
62160
|
planSummaryRef.current = p.summary ?? null;
|
|
62476
62161
|
planBodyRef.current = p.plan;
|
|
62477
62162
|
stepCompletionsRef.current = /* @__PURE__ */ new Map();
|
|
62163
|
+
pendingStepCompletionsRef.current = /* @__PURE__ */ new Map();
|
|
62478
62164
|
engineeringLifecycleRef.current?.recordPlanProposed(p.steps);
|
|
62479
62165
|
break;
|
|
62480
62166
|
}
|
|
62481
62167
|
case "plan_checkpoint": {
|
|
62482
62168
|
const p = payload;
|
|
62169
|
+
if (p.completion?.kind === "step_completed") {
|
|
62170
|
+
pendingStepCompletionsRef.current.set(p.stepId, p.completion);
|
|
62171
|
+
}
|
|
62483
62172
|
const total = planStepsRef.current?.length ?? 0;
|
|
62484
62173
|
const completed = completedCountIncludingStep(
|
|
62485
62174
|
completedStepIdsRef.current,
|
|
62486
62175
|
p.stepId,
|
|
62487
62176
|
total
|
|
62488
62177
|
);
|
|
62178
|
+
engineeringLifecycleRef.current?.recordCheckpointReached();
|
|
62489
62179
|
if (shouldAutoResolveCheckpoint(editModeRef.current)) {
|
|
62490
62180
|
handleAutoCheckpointContinueRef.current(p.stepId, p.title);
|
|
62491
62181
|
pauseGate.resolve(request.id, { type: "continue" });
|
|
@@ -62546,6 +62236,9 @@ ${answer}`, "brand");
|
|
|
62546
62236
|
setStagedCheckpointRevise(snap);
|
|
62547
62237
|
return;
|
|
62548
62238
|
}
|
|
62239
|
+
if (choice === "stop") {
|
|
62240
|
+
engineeringLifecycleRef.current?.cancel();
|
|
62241
|
+
}
|
|
62549
62242
|
if (codeMode && choice === "continue") {
|
|
62550
62243
|
const paths = touchedPaths();
|
|
62551
62244
|
if (paths.length > 0) {
|
|
@@ -62693,10 +62386,7 @@ ${answer}`, "brand");
|
|
|
62693
62386
|
merged.push(s);
|
|
62694
62387
|
}
|
|
62695
62388
|
planStepsRef.current = merged;
|
|
62696
|
-
engineeringLifecycleRef.current?.
|
|
62697
|
-
for (const s of merged) {
|
|
62698
|
-
if (completed.has(s.id)) engineeringLifecycleRef.current?.recordStepCompleted(s.id);
|
|
62699
|
-
}
|
|
62389
|
+
engineeringLifecycleRef.current?.recordPlanRevised(snap.remainingSteps);
|
|
62700
62390
|
persistPlanState();
|
|
62701
62391
|
agentStore.dispatch({ type: "plan.drop" });
|
|
62702
62392
|
log.showPlan({
|
|
@@ -63274,6 +62964,39 @@ function disableMouseMode() {
|
|
|
63274
62964
|
active = false;
|
|
63275
62965
|
}
|
|
63276
62966
|
|
|
62967
|
+
// src/cli/ui/resize-broadcaster.ts
|
|
62968
|
+
var state = null;
|
|
62969
|
+
function installResizeBroadcaster(stream = process.stdout) {
|
|
62970
|
+
if (state) return;
|
|
62971
|
+
if (typeof stream.on !== "function" || typeof stream.off !== "function") return;
|
|
62972
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
62973
|
+
const realOn = stream.on.bind(stream);
|
|
62974
|
+
const realOff = stream.off.bind(stream);
|
|
62975
|
+
const broadcast = (...args) => {
|
|
62976
|
+
for (const l of subscribers) l(...args);
|
|
62977
|
+
};
|
|
62978
|
+
realOn("resize", broadcast);
|
|
62979
|
+
const shimOn = (event, listener) => {
|
|
62980
|
+
if (event === "resize") {
|
|
62981
|
+
subscribers.add(listener);
|
|
62982
|
+
return stream;
|
|
62983
|
+
}
|
|
62984
|
+
return realOn(event, listener);
|
|
62985
|
+
};
|
|
62986
|
+
const shimOff = (event, listener) => {
|
|
62987
|
+
if (event === "resize") {
|
|
62988
|
+
subscribers.delete(listener);
|
|
62989
|
+
return stream;
|
|
62990
|
+
}
|
|
62991
|
+
return realOff(event, listener);
|
|
62992
|
+
};
|
|
62993
|
+
stream.on = shimOn;
|
|
62994
|
+
stream.addListener = shimOn;
|
|
62995
|
+
stream.off = shimOff;
|
|
62996
|
+
stream.removeListener = shimOff;
|
|
62997
|
+
state = { stream, subscribers };
|
|
62998
|
+
}
|
|
62999
|
+
|
|
63277
63000
|
// src/cli/commands/chat.tsx
|
|
63278
63001
|
function Root({
|
|
63279
63002
|
initialKey,
|
|
@@ -63447,8 +63170,8 @@ async function chatCommand(opts) {
|
|
|
63447
63170
|
`);
|
|
63448
63171
|
}
|
|
63449
63172
|
}
|
|
63450
|
-
|
|
63451
|
-
if (cfg.mouseTracking !== false) {
|
|
63173
|
+
installResizeBroadcaster();
|
|
63174
|
+
if (!opts.noMouse && cfg.mouseTracking !== false) {
|
|
63452
63175
|
enableMouseMode();
|
|
63453
63176
|
process.once("exit", disableMouseMode);
|
|
63454
63177
|
process.once("SIGINT", () => {
|
|
@@ -63494,4 +63217,4 @@ async function chatCommand(opts) {
|
|
|
63494
63217
|
export {
|
|
63495
63218
|
chatCommand
|
|
63496
63219
|
};
|
|
63497
|
-
//# sourceMappingURL=chunk-
|
|
63220
|
+
//# sourceMappingURL=chunk-6MZTZO7A.js.map
|