reasonix 0.47.2 → 0.48.1
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 +14 -26
- package/README.zh-CN.md +5 -26
- package/dist/cli/{acp-GEOAKSTU.js → acp-QJGGHQLA.js} +52 -135
- package/dist/cli/acp-QJGGHQLA.js.map +1 -0
- package/dist/cli/{chat-YTPATMMG.js → chat-ZXF227MP.js} +25 -25
- package/dist/cli/{chunk-DN4B5S6Y.js → chunk-3FULTFRB.js} +2 -2
- package/dist/cli/chunk-43ROGEX2.js +5190 -0
- package/dist/cli/chunk-43ROGEX2.js.map +1 -0
- package/dist/cli/{chunk-DQ6K5ZQ7.js → chunk-4E2BHJU4.js} +4 -4
- package/dist/cli/chunk-4E2BHJU4.js.map +1 -0
- package/dist/cli/{chunk-T5A7EY6B.js → chunk-5AW6NIHU.js} +2 -2
- package/dist/cli/{chunk-DWPAKZTY.js → chunk-5U5LMMFF.js} +2 -2
- package/dist/cli/{chunk-TRSAHHCL.js → chunk-6FRNXWDZ.js} +321 -76
- package/dist/cli/chunk-6FRNXWDZ.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-XMHP7BEE.js → chunk-DABAOQSV.js} +2273 -2517
- package/dist/cli/chunk-DABAOQSV.js.map +1 -0
- package/dist/cli/chunk-EO6RPTJG.js +831 -0
- package/dist/cli/chunk-EO6RPTJG.js.map +1 -0
- package/dist/cli/{chunk-BQ6HC66J.js → chunk-FD7SNDWW.js} +4 -14
- package/dist/cli/chunk-FD7SNDWW.js.map +1 -0
- package/dist/cli/chunk-FPME5QOO.js +17747 -0
- package/dist/cli/chunk-FPME5QOO.js.map +1 -0
- package/dist/cli/{chunk-6QC5RQLE.js → chunk-H2F4LDNH.js} +2 -2
- package/dist/cli/{chunk-QCFLPSPH.js → chunk-IKSYVBBZ.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-JBH5RM7X.js → chunk-JFBGSWQB.js} +395 -85
- package/dist/cli/chunk-JFBGSWQB.js.map +1 -0
- package/dist/cli/{chunk-CCJAP7G3.js → chunk-KH5JIJJD.js} +2 -2
- package/dist/cli/{chunk-TDHXB2ER.js → chunk-NQZ5U37J.js} +2 -2
- package/dist/cli/{chunk-CNG32VAB.js → chunk-O3AGYTG2.js} +2 -2
- package/dist/cli/{chunk-NRQ5UP5T.js → chunk-PIC5HJRD.js} +234 -40
- package/dist/cli/chunk-PIC5HJRD.js.map +1 -0
- package/dist/cli/{chunk-GH7DC2Y5.js → chunk-PJIQIYTV.js} +6 -3
- package/dist/cli/chunk-PJIQIYTV.js.map +1 -0
- package/dist/cli/{chunk-KVZZ5U75.js → chunk-R7U44O3Y.js} +2 -2
- package/dist/cli/{chunk-ZXSCAODE.js → chunk-RCLS63KE.js} +71 -3
- package/dist/cli/chunk-RCLS63KE.js.map +1 -0
- package/dist/cli/{chunk-FY4S7TJZ.js → chunk-SLAFMXAZ.js} +10 -2
- package/dist/cli/chunk-SLAFMXAZ.js.map +1 -0
- package/dist/cli/{chunk-TRWHTFG7.js → chunk-SWUMD2LX.js} +2 -2
- package/dist/cli/{chunk-2XY77LW7.js → chunk-TIJ4ZHD6.js} +56 -24
- package/dist/cli/chunk-TIJ4ZHD6.js.map +1 -0
- package/dist/cli/{chunk-4MFCAZ2W.js → chunk-WKOXKCF3.js} +3 -3
- package/dist/cli/{chunk-HUILPCYX.js → chunk-XMR2VCGT.js} +3 -3
- package/dist/cli/{code-Q4NRVEDG.js → code-OKA5YPOH.js} +31 -32
- package/dist/cli/code-OKA5YPOH.js.map +1 -0
- package/dist/cli/{commands-4CDI4GFM.js → commands-3U6PUVSS.js} +4 -4
- package/dist/cli/{commit-GW7LDQP5.js → commit-HFB7SRBU.js} +3 -3
- package/dist/cli/{desktop-EG6P5SF2.js → desktop-G7UMW3CJ.js} +503 -48
- package/dist/cli/desktop-G7UMW3CJ.js.map +1 -0
- package/dist/cli/{diff-VI2YX4FN.js → diff-PGXW4YZD.js} +8 -8
- package/dist/cli/{doctor-CQTTZP27.js → doctor-WWJFLVCB.js} +9 -9
- package/dist/cli/index.js +53 -41
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/{mcp-J2UCD4RZ.js → mcp-Y3VKIK3T.js} +2 -2
- package/dist/cli/{mcp-browse-GSX34JEK.js → mcp-browse-4IN2QIFR.js} +2 -2
- package/dist/cli/{mcp-inspect-RRFYF4ZV.js → mcp-inspect-BUXFXDHB.js} +2 -2
- package/dist/cli/{prompt-5TQPIVHV.js → prompt-US57R6BA.js} +5 -4
- package/dist/cli/{replay-MJCEMODU.js → replay-EQJMZRB3.js} +8 -8
- package/dist/cli/{run-P4D5VDYE.js → run-KVEI66TR.js} +14 -14
- package/dist/cli/{server-C25JNNZV.js → server-D6C4GHWN.js} +18 -15
- package/dist/cli/server-D6C4GHWN.js.map +1 -0
- package/dist/cli/{sessions-QIONZJQ6.js → sessions-TGVS2RQZ.js} +13 -13
- package/dist/cli/{setup-NLQ6G5G4.js → setup-WLKX6GGG.js} +5 -5
- package/dist/cli/{stats-DFZEXHP4.js → stats-TCD7Q6MB.js} +6 -6
- package/dist/cli/{version-GR3X3MPI.js → version-BCWWS2OU.js} +13 -13
- 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 +46 -12
- package/dist/index.js +684 -129
- package/dist/index.js.map +1 -1
- package/package.json +16 -4
- package/dist/cli/acp-GEOAKSTU.js.map +0 -1
- 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-DQ6K5ZQ7.js.map +0 -1
- package/dist/cli/chunk-FY4S7TJZ.js.map +0 -1
- package/dist/cli/chunk-GH7DC2Y5.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/server-C25JNNZV.js.map +0 -1
- /package/dist/cli/{chat-YTPATMMG.js.map → chat-ZXF227MP.js.map} +0 -0
- /package/dist/cli/{chunk-DN4B5S6Y.js.map → chunk-3FULTFRB.js.map} +0 -0
- /package/dist/cli/{chunk-T5A7EY6B.js.map → chunk-5AW6NIHU.js.map} +0 -0
- /package/dist/cli/{chunk-DWPAKZTY.js.map → chunk-5U5LMMFF.js.map} +0 -0
- /package/dist/cli/{chunk-6QC5RQLE.js.map → chunk-H2F4LDNH.js.map} +0 -0
- /package/dist/cli/{chunk-QCFLPSPH.js.map → chunk-IKSYVBBZ.js.map} +0 -0
- /package/dist/cli/{chunk-CCJAP7G3.js.map → chunk-KH5JIJJD.js.map} +0 -0
- /package/dist/cli/{chunk-TDHXB2ER.js.map → chunk-NQZ5U37J.js.map} +0 -0
- /package/dist/cli/{chunk-CNG32VAB.js.map → chunk-O3AGYTG2.js.map} +0 -0
- /package/dist/cli/{chunk-KVZZ5U75.js.map → chunk-R7U44O3Y.js.map} +0 -0
- /package/dist/cli/{chunk-TRWHTFG7.js.map → chunk-SWUMD2LX.js.map} +0 -0
- /package/dist/cli/{chunk-4MFCAZ2W.js.map → chunk-WKOXKCF3.js.map} +0 -0
- /package/dist/cli/{chunk-HUILPCYX.js.map → chunk-XMR2VCGT.js.map} +0 -0
- /package/dist/cli/{commands-4CDI4GFM.js.map → commands-3U6PUVSS.js.map} +0 -0
- /package/dist/cli/{commit-GW7LDQP5.js.map → commit-HFB7SRBU.js.map} +0 -0
- /package/dist/cli/{diff-VI2YX4FN.js.map → diff-PGXW4YZD.js.map} +0 -0
- /package/dist/cli/{doctor-CQTTZP27.js.map → doctor-WWJFLVCB.js.map} +0 -0
- /package/dist/cli/{mcp-J2UCD4RZ.js.map → mcp-Y3VKIK3T.js.map} +0 -0
- /package/dist/cli/{mcp-browse-GSX34JEK.js.map → mcp-browse-4IN2QIFR.js.map} +0 -0
- /package/dist/cli/{mcp-inspect-RRFYF4ZV.js.map → mcp-inspect-BUXFXDHB.js.map} +0 -0
- /package/dist/cli/{prompt-5TQPIVHV.js.map → prompt-US57R6BA.js.map} +0 -0
- /package/dist/cli/{replay-MJCEMODU.js.map → replay-EQJMZRB3.js.map} +0 -0
- /package/dist/cli/{run-P4D5VDYE.js.map → run-KVEI66TR.js.map} +0 -0
- /package/dist/cli/{sessions-QIONZJQ6.js.map → sessions-TGVS2RQZ.js.map} +0 -0
- /package/dist/cli/{setup-NLQ6G5G4.js.map → setup-WLKX6GGG.js.map} +0 -0
- /package/dist/cli/{stats-DFZEXHP4.js.map → stats-TCD7Q6MB.js.map} +0 -0
- /package/dist/cli/{version-GR3X3MPI.js.map → version-BCWWS2OU.js.map} +0 -0
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire as __cr } from 'node:module'; if (typeof globalThis.require === 'undefined') { globalThis.require = __cr(import.meta.url); }
|
|
3
3
|
import {
|
|
4
|
+
QQChannel,
|
|
4
5
|
createMcpRuntime
|
|
5
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-EO6RPTJG.js";
|
|
6
7
|
import {
|
|
7
8
|
buildCodeToolset
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-43ROGEX2.js";
|
|
9
10
|
import {
|
|
10
11
|
Eventizer,
|
|
11
12
|
autoResolveVerdict
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
13
|
+
} from "./chunk-RCLS63KE.js";
|
|
14
|
+
import "./chunk-4E2BHJU4.js";
|
|
14
15
|
import "./chunk-EQATK2L2.js";
|
|
15
16
|
import {
|
|
16
17
|
CacheFirstLoop,
|
|
@@ -19,14 +20,15 @@ import {
|
|
|
19
20
|
listFilesWithStatsAsync,
|
|
20
21
|
parseAtQuery,
|
|
21
22
|
rankPickerCandidates
|
|
22
|
-
} from "./chunk-
|
|
23
|
-
import "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
} from "./chunk-JFBGSWQB.js";
|
|
24
|
+
import "./chunk-H2F4LDNH.js";
|
|
25
|
+
import "./chunk-XMR2VCGT.js";
|
|
25
26
|
import "./chunk-HIYTRCSW.js";
|
|
26
27
|
import {
|
|
27
28
|
MemoryStore,
|
|
28
29
|
codeSystemPrompt
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-FD7SNDWW.js";
|
|
31
|
+
import "./chunk-FEZK652I.js";
|
|
30
32
|
import {
|
|
31
33
|
canonicalPresetName,
|
|
32
34
|
resolvePreset
|
|
@@ -37,21 +39,22 @@ import {
|
|
|
37
39
|
import {
|
|
38
40
|
DeepSeekClient,
|
|
39
41
|
pickPrimaryBalance
|
|
40
|
-
} from "./chunk-
|
|
42
|
+
} from "./chunk-5U5LMMFF.js";
|
|
41
43
|
import "./chunk-25T6CVUP.js";
|
|
42
44
|
import {
|
|
43
45
|
loadDotenv
|
|
44
46
|
} from "./chunk-2UQP6H6T.js";
|
|
45
|
-
import "./chunk-
|
|
47
|
+
import "./chunk-R7U44O3Y.js";
|
|
46
48
|
import {
|
|
47
|
-
pauseGate
|
|
48
|
-
|
|
49
|
+
pauseGate,
|
|
50
|
+
toApprovalPrompt
|
|
51
|
+
} from "./chunk-6FRNXWDZ.js";
|
|
49
52
|
import {
|
|
50
53
|
SkillStore
|
|
51
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-SLAFMXAZ.js";
|
|
52
55
|
import "./chunk-PLHAZOLZ.js";
|
|
53
|
-
import "./chunk-
|
|
54
|
-
import "./chunk-
|
|
56
|
+
import "./chunk-5AW6NIHU.js";
|
|
57
|
+
import "./chunk-PJIQIYTV.js";
|
|
55
58
|
import "./chunk-S4XVGLRW.js";
|
|
56
59
|
import {
|
|
57
60
|
deleteSession,
|
|
@@ -62,9 +65,9 @@ import {
|
|
|
62
65
|
sessionPath,
|
|
63
66
|
timestampSuffix
|
|
64
67
|
} from "./chunk-RRXUIPWG.js";
|
|
65
|
-
import "./chunk-
|
|
66
|
-
import "./chunk-
|
|
67
|
-
import "./chunk-
|
|
68
|
+
import "./chunk-3FULTFRB.js";
|
|
69
|
+
import "./chunk-IKSYVBBZ.js";
|
|
70
|
+
import "./chunk-PIC5HJRD.js";
|
|
68
71
|
import {
|
|
69
72
|
describeQQAccess,
|
|
70
73
|
isPlausibleKey,
|
|
@@ -92,7 +95,7 @@ import {
|
|
|
92
95
|
saveReasoningEffort,
|
|
93
96
|
saveWorkspaceDir,
|
|
94
97
|
writeConfig
|
|
95
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-FPME5QOO.js";
|
|
96
99
|
import {
|
|
97
100
|
VERSION
|
|
98
101
|
} from "./chunk-XXC2BYTV.js";
|
|
@@ -172,15 +175,12 @@ function toAccess(config) {
|
|
|
172
175
|
function loadDesktopQQState(path) {
|
|
173
176
|
const config = loadQQConfig(path);
|
|
174
177
|
const configured = Boolean(config.appId && config.appSecret);
|
|
175
|
-
const enabled = config.enabled === true;
|
|
176
178
|
return {
|
|
177
179
|
...config,
|
|
178
180
|
sandbox: config.sandbox ?? false,
|
|
179
|
-
enabled,
|
|
181
|
+
enabled: config.enabled === true,
|
|
180
182
|
configured,
|
|
181
|
-
|
|
182
|
-
connected: false,
|
|
183
|
-
enabledForCli: configured && enabled,
|
|
183
|
+
runtimeState: "disconnected",
|
|
184
184
|
appIdPreview: toPreview(config.appId),
|
|
185
185
|
access: toAccess(config)
|
|
186
186
|
};
|
|
@@ -208,9 +208,36 @@ function setDesktopQQEnabled(enabled, path) {
|
|
|
208
208
|
}
|
|
209
209
|
|
|
210
210
|
// src/cli/commands/desktop.ts
|
|
211
|
+
var desktopQqRuntimeSnapshot = {
|
|
212
|
+
runtimeState: "disconnected"
|
|
213
|
+
};
|
|
214
|
+
var STDOUT_BACKPRESSURE_WAIT = new Int32Array(new SharedArrayBuffer(4));
|
|
215
|
+
var SESSION_TITLE_MAX_CHARS = 200;
|
|
216
|
+
function normalizeSessionTitle(raw) {
|
|
217
|
+
return raw.replace(/\s+/g, " ").trim().slice(0, SESSION_TITLE_MAX_CHARS);
|
|
218
|
+
}
|
|
219
|
+
function writeAllSync(fd, buffer, opts = {}) {
|
|
220
|
+
const write = opts.write ?? writeSync;
|
|
221
|
+
const wait = opts.wait ?? (() => Atomics.wait(STDOUT_BACKPRESSURE_WAIT, 0, 0, 5));
|
|
222
|
+
let offset = 0;
|
|
223
|
+
while (offset < buffer.length) {
|
|
224
|
+
let written;
|
|
225
|
+
try {
|
|
226
|
+
written = write(fd, buffer, offset, buffer.length - offset);
|
|
227
|
+
} catch (err) {
|
|
228
|
+
if (err.code === "EAGAIN") {
|
|
229
|
+
wait();
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
throw err;
|
|
233
|
+
}
|
|
234
|
+
if (written <= 0) throw new Error("stdout write returned 0 bytes");
|
|
235
|
+
offset += written;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
211
238
|
function emit(ev, tabId) {
|
|
212
239
|
const payload = tabId ? { ...ev, tabId } : ev;
|
|
213
|
-
|
|
240
|
+
writeAllSync(1, Buffer.from(`${JSON.stringify(payload)}
|
|
214
241
|
`, "utf8"));
|
|
215
242
|
}
|
|
216
243
|
function tailLines(s, n) {
|
|
@@ -287,7 +314,16 @@ function emitSettings(tab) {
|
|
|
287
314
|
);
|
|
288
315
|
}
|
|
289
316
|
function emitQQSettings(tab) {
|
|
290
|
-
|
|
317
|
+
const base = loadDesktopQQState();
|
|
318
|
+
emit(
|
|
319
|
+
{
|
|
320
|
+
type: "$qq_settings",
|
|
321
|
+
...base,
|
|
322
|
+
runtimeState: desktopQqRuntimeSnapshot.runtimeState,
|
|
323
|
+
lastError: desktopQqRuntimeSnapshot.lastError
|
|
324
|
+
},
|
|
325
|
+
tab.id
|
|
326
|
+
);
|
|
291
327
|
}
|
|
292
328
|
async function emitBalance(tab) {
|
|
293
329
|
if (!tab.runtime) return;
|
|
@@ -379,7 +415,8 @@ function emitCtxBreakdown(tab) {
|
|
|
379
415
|
try {
|
|
380
416
|
const sys = countTokensBounded(tab.runtime.loop.prefix.system);
|
|
381
417
|
const tools = countTokensBounded(JSON.stringify(tab.runtime.loop.prefix.toolSpecs));
|
|
382
|
-
|
|
418
|
+
const logTokens = tab.runtime.loop.getCurrentLogTokens();
|
|
419
|
+
emit({ type: "$ctx_breakdown", reservedTokens: sys + tools, logTokens }, tab.id);
|
|
383
420
|
} catch {
|
|
384
421
|
}
|
|
385
422
|
}
|
|
@@ -540,6 +577,319 @@ async function desktopCommand(opts) {
|
|
|
540
577
|
const id = tabContext.getStore();
|
|
541
578
|
return id ? tabs.get(id) : void 0;
|
|
542
579
|
}
|
|
580
|
+
let first;
|
|
581
|
+
const qqRuntime = {
|
|
582
|
+
channel: null,
|
|
583
|
+
runtimeState: "disconnected",
|
|
584
|
+
lastError: void 0,
|
|
585
|
+
pendingGateId: null,
|
|
586
|
+
interaction: { kind: null, payload: null },
|
|
587
|
+
replyThisTurn: false
|
|
588
|
+
};
|
|
589
|
+
function currentQqSettings() {
|
|
590
|
+
const base = loadDesktopQQState();
|
|
591
|
+
return {
|
|
592
|
+
type: "$qq_settings",
|
|
593
|
+
...base,
|
|
594
|
+
runtimeState: qqRuntime.runtimeState,
|
|
595
|
+
lastError: qqRuntime.lastError
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
function activeDesktopTab() {
|
|
599
|
+
return (lastActiveTabId ? tabs.get(lastActiveTabId) : void 0) ?? first;
|
|
600
|
+
}
|
|
601
|
+
function broadcastQQSettings() {
|
|
602
|
+
for (const tab of tabs.values()) emit(currentQqSettings(), tab.id);
|
|
603
|
+
}
|
|
604
|
+
function setQQRuntimeState(runtimeState, lastError) {
|
|
605
|
+
qqRuntime.runtimeState = runtimeState;
|
|
606
|
+
qqRuntime.lastError = lastError;
|
|
607
|
+
desktopQqRuntimeSnapshot.runtimeState = runtimeState;
|
|
608
|
+
desktopQqRuntimeSnapshot.lastError = lastError;
|
|
609
|
+
broadcastQQSettings();
|
|
610
|
+
}
|
|
611
|
+
function sendQQInfo(message) {
|
|
612
|
+
const tab = activeDesktopTab();
|
|
613
|
+
if (tab) {
|
|
614
|
+
emit(
|
|
615
|
+
{
|
|
616
|
+
type: "status",
|
|
617
|
+
id: Date.now(),
|
|
618
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
619
|
+
turn: 0,
|
|
620
|
+
text: message
|
|
621
|
+
},
|
|
622
|
+
tab.id
|
|
623
|
+
);
|
|
624
|
+
}
|
|
625
|
+
void qqRuntime.channel?.sendResponse(message).catch((err) => {
|
|
626
|
+
const active = activeDesktopTab();
|
|
627
|
+
if (active) {
|
|
628
|
+
emit({ type: "$error", message: `qq send failed: ${err.message}` }, active.id);
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
}
|
|
632
|
+
function parseIndexedChoice(text) {
|
|
633
|
+
const rawIndex = text.match(/^(\d+)/)?.[1];
|
|
634
|
+
return rawIndex ? Number.parseInt(rawIndex, 10) - 1 : -1;
|
|
635
|
+
}
|
|
636
|
+
function parseRunPermissionChoice(text) {
|
|
637
|
+
const lower = text.toLowerCase();
|
|
638
|
+
if (lower.includes("1") || lower.includes("run")) return "run_once";
|
|
639
|
+
if (lower.includes("2") || lower.includes("always")) return "always_allow";
|
|
640
|
+
return "deny";
|
|
641
|
+
}
|
|
642
|
+
function parsePlanChoice(text) {
|
|
643
|
+
const lower = text.toLowerCase();
|
|
644
|
+
if (lower.includes("1") || lower.includes("approve")) return "approve";
|
|
645
|
+
if (lower.includes("2") || lower.includes("refine")) return "refine";
|
|
646
|
+
return "cancel";
|
|
647
|
+
}
|
|
648
|
+
function parseCheckpointChoice(text) {
|
|
649
|
+
const lower = text.toLowerCase();
|
|
650
|
+
if (lower.includes("1") || lower.includes("continue")) return "continue";
|
|
651
|
+
if (lower.includes("2") || lower.includes("revise")) return "revise";
|
|
652
|
+
return "stop";
|
|
653
|
+
}
|
|
654
|
+
function parseRevisionChoice(text) {
|
|
655
|
+
const lower = text.toLowerCase();
|
|
656
|
+
if (lower.includes("1") || lower.includes("accept")) return "accept";
|
|
657
|
+
if (lower.includes("2") || lower.includes("reject")) return "reject";
|
|
658
|
+
return "cancel";
|
|
659
|
+
}
|
|
660
|
+
function stripFollowupPrefix(text) {
|
|
661
|
+
return text.replace(
|
|
662
|
+
/^(?:\d+\s*|approve\s*|refine\s*|cancel\s*|continue\s*|revise\s*|stop\s*|accept\s*|reject\s*|run\s*|always\s*|deny\s*)/iu,
|
|
663
|
+
""
|
|
664
|
+
).trim();
|
|
665
|
+
}
|
|
666
|
+
function handleQQPauseReply(text) {
|
|
667
|
+
if (qqRuntime.interaction.kind === null || qqRuntime.pendingGateId === null) return false;
|
|
668
|
+
qqRuntime.replyThisTurn = true;
|
|
669
|
+
const followup = stripFollowupPrefix(text);
|
|
670
|
+
const interaction = qqRuntime.interaction;
|
|
671
|
+
qqRuntime.interaction = { kind: null, payload: null };
|
|
672
|
+
const gateId = qqRuntime.pendingGateId;
|
|
673
|
+
qqRuntime.pendingGateId = null;
|
|
674
|
+
switch (interaction.kind) {
|
|
675
|
+
case "run_command":
|
|
676
|
+
case "run_background":
|
|
677
|
+
case "path_access":
|
|
678
|
+
pauseGate.resolve(gateId, parseRunPermissionChoice(text));
|
|
679
|
+
return true;
|
|
680
|
+
case "plan_proposed": {
|
|
681
|
+
const payload = interaction.payload ?? {};
|
|
682
|
+
const choice = parsePlanChoice(text);
|
|
683
|
+
if (choice === "cancel") {
|
|
684
|
+
pauseGate.cancel(gateId);
|
|
685
|
+
} else {
|
|
686
|
+
pauseGate.resolve(gateId, {
|
|
687
|
+
type: choice === "approve" ? "approve" : "refine",
|
|
688
|
+
feedback: followup,
|
|
689
|
+
override: {
|
|
690
|
+
plan: payload.plan ?? "",
|
|
691
|
+
mode: choice === "approve" ? "approve" : "refine"
|
|
692
|
+
}
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
return true;
|
|
696
|
+
}
|
|
697
|
+
case "plan_checkpoint": {
|
|
698
|
+
const payload = interaction.payload ?? {};
|
|
699
|
+
const choice = parseCheckpointChoice(text);
|
|
700
|
+
if (choice === "revise") {
|
|
701
|
+
pauseGate.resolve(gateId, {
|
|
702
|
+
type: "revise",
|
|
703
|
+
feedback: followup,
|
|
704
|
+
checkpoint: { stepId: payload.stepId ?? "", title: payload.title }
|
|
705
|
+
});
|
|
706
|
+
} else {
|
|
707
|
+
pauseGate.resolve(gateId, { type: choice });
|
|
708
|
+
}
|
|
709
|
+
return true;
|
|
710
|
+
}
|
|
711
|
+
case "plan_revision":
|
|
712
|
+
pauseGate.resolve(gateId, parseRevisionChoice(text));
|
|
713
|
+
return true;
|
|
714
|
+
case "choice": {
|
|
715
|
+
const payload = interaction.payload ?? {};
|
|
716
|
+
const options = payload.options ?? [];
|
|
717
|
+
const pickedIndex = parseIndexedChoice(text);
|
|
718
|
+
if (pickedIndex >= 0 && pickedIndex < options.length) {
|
|
719
|
+
const selected = options[pickedIndex];
|
|
720
|
+
if (selected) pauseGate.resolve(gateId, { type: "pick", optionId: selected.id });
|
|
721
|
+
return true;
|
|
722
|
+
}
|
|
723
|
+
for (const option of options) {
|
|
724
|
+
if (text.toLowerCase().includes(option.title.toLowerCase())) {
|
|
725
|
+
pauseGate.resolve(gateId, { type: "pick", optionId: option.id });
|
|
726
|
+
return true;
|
|
727
|
+
}
|
|
728
|
+
}
|
|
729
|
+
pauseGate.resolve(
|
|
730
|
+
gateId,
|
|
731
|
+
payload.allowCustom ? { type: "text", text } : { type: "cancel" }
|
|
732
|
+
);
|
|
733
|
+
return true;
|
|
734
|
+
}
|
|
735
|
+
default:
|
|
736
|
+
return false;
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
function handleQQPauseRequest(tab, kind, payload) {
|
|
740
|
+
if (!qqRuntime.channel) return;
|
|
741
|
+
qqRuntime.interaction = { kind, payload };
|
|
742
|
+
let qqMessage = "";
|
|
743
|
+
switch (kind) {
|
|
744
|
+
case "run_command":
|
|
745
|
+
case "run_background": {
|
|
746
|
+
const p = payload;
|
|
747
|
+
qqMessage = `Need confirmation
|
|
748
|
+
|
|
749
|
+
Command: \`${p.command}\`
|
|
750
|
+
|
|
751
|
+
Reply with:
|
|
752
|
+
1. Run once
|
|
753
|
+
2. Always allow
|
|
754
|
+
3. Deny`;
|
|
755
|
+
break;
|
|
756
|
+
}
|
|
757
|
+
case "path_access": {
|
|
758
|
+
const p = payload;
|
|
759
|
+
const intentText = p.intent === "read" ? "Read" : "Write";
|
|
760
|
+
qqMessage = `Need file access confirmation
|
|
761
|
+
|
|
762
|
+
Action: ${intentText}
|
|
763
|
+
Path: ${p.path}
|
|
764
|
+
Tool: ${p.toolName}
|
|
765
|
+
|
|
766
|
+
Reply with:
|
|
767
|
+
1. Run once
|
|
768
|
+
2. Always allow
|
|
769
|
+
3. Deny`;
|
|
770
|
+
break;
|
|
771
|
+
}
|
|
772
|
+
case "plan_proposed": {
|
|
773
|
+
const p = payload;
|
|
774
|
+
qqMessage = `Plan confirmation
|
|
775
|
+
|
|
776
|
+
${p.plan}
|
|
777
|
+
|
|
778
|
+
Reply with:
|
|
779
|
+
1. Approve
|
|
780
|
+
2. Refine
|
|
781
|
+
3. Cancel`;
|
|
782
|
+
break;
|
|
783
|
+
}
|
|
784
|
+
case "plan_checkpoint": {
|
|
785
|
+
const p = payload;
|
|
786
|
+
qqMessage = `Step complete (${tab.completedStepIds.size}/${tab.planTotalSteps})
|
|
787
|
+
|
|
788
|
+
${p.title ? `Step: ${p.title}
|
|
789
|
+
` : ""}Result: ${p.result}
|
|
790
|
+
|
|
791
|
+
Reply with:
|
|
792
|
+
1. Continue
|
|
793
|
+
2. Revise
|
|
794
|
+
3. Stop`;
|
|
795
|
+
break;
|
|
796
|
+
}
|
|
797
|
+
case "plan_revision": {
|
|
798
|
+
const p = payload;
|
|
799
|
+
qqMessage = `Plan revision proposed
|
|
800
|
+
|
|
801
|
+
${p.reason}
|
|
802
|
+
|
|
803
|
+
Reply with:
|
|
804
|
+
1. Accept
|
|
805
|
+
2. Reject
|
|
806
|
+
3. Cancel`;
|
|
807
|
+
break;
|
|
808
|
+
}
|
|
809
|
+
case "choice": {
|
|
810
|
+
const p = payload;
|
|
811
|
+
const optionsList = p.options.map((opt, idx) => `${idx + 1}. ${opt.title}`).join("\n");
|
|
812
|
+
qqMessage = `Please choose
|
|
813
|
+
|
|
814
|
+
${p.question}
|
|
815
|
+
|
|
816
|
+
Options:
|
|
817
|
+
${optionsList}${p.allowCustom ? "\n\n(You can also reply with custom text.)" : ""}`;
|
|
818
|
+
break;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if (qqMessage) {
|
|
822
|
+
void qqRuntime.channel.sendResponse(qqMessage).catch((err) => {
|
|
823
|
+
emit({ type: "$error", message: `qq send failed: ${err.message}` }, tab.id);
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
async function startDesktopQQ(shouldPersistEnabled = true) {
|
|
828
|
+
const current = loadQQConfig();
|
|
829
|
+
if (!(current.appId && current.appSecret)) {
|
|
830
|
+
throw new Error("QQ App ID and App Secret are required.");
|
|
831
|
+
}
|
|
832
|
+
if (qqRuntime.channel) {
|
|
833
|
+
qqRuntime.channel.refreshAccessConfig();
|
|
834
|
+
setQQRuntimeState("connected");
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
setQQRuntimeState("connecting");
|
|
838
|
+
const channel = new QQChannel({
|
|
839
|
+
onSubmitMessage: (text) => {
|
|
840
|
+
const tab = activeDesktopTab();
|
|
841
|
+
if (!tab) return;
|
|
842
|
+
const trimmed = text.trim();
|
|
843
|
+
if (!trimmed) return;
|
|
844
|
+
emit(
|
|
845
|
+
{
|
|
846
|
+
type: "user.message",
|
|
847
|
+
id: Date.now(),
|
|
848
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
849
|
+
turn: 0,
|
|
850
|
+
text: trimmed
|
|
851
|
+
},
|
|
852
|
+
tab.id
|
|
853
|
+
);
|
|
854
|
+
if (handleQQPauseReply(trimmed)) return;
|
|
855
|
+
if (tab.aborter) {
|
|
856
|
+
void channel.sendResponse(
|
|
857
|
+
"Session is busy. Wait for the current turn or reply to the pending prompt."
|
|
858
|
+
).catch(() => void 0);
|
|
859
|
+
return;
|
|
860
|
+
}
|
|
861
|
+
qqRuntime.replyThisTurn = true;
|
|
862
|
+
void runTurn(tab, trimmed, true);
|
|
863
|
+
},
|
|
864
|
+
onError: (message) => {
|
|
865
|
+
const tab = activeDesktopTab();
|
|
866
|
+
setQQRuntimeState("failed", message);
|
|
867
|
+
if (tab) emit({ type: "$error", message: `QQ: ${message}` }, tab.id);
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
try {
|
|
871
|
+
await channel.start();
|
|
872
|
+
qqRuntime.channel = channel;
|
|
873
|
+
if (shouldPersistEnabled) setDesktopQQEnabled(true);
|
|
874
|
+
setQQRuntimeState("connected");
|
|
875
|
+
} catch (err) {
|
|
876
|
+
await channel.stop().catch(() => void 0);
|
|
877
|
+
qqRuntime.channel = null;
|
|
878
|
+
if (shouldPersistEnabled) setDesktopQQEnabled(false);
|
|
879
|
+
setQQRuntimeState("failed", err.message);
|
|
880
|
+
throw err;
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
async function stopDesktopQQ(shouldDisable = true) {
|
|
884
|
+
const channel = qqRuntime.channel;
|
|
885
|
+
qqRuntime.channel = null;
|
|
886
|
+
qqRuntime.interaction = { kind: null, payload: null };
|
|
887
|
+
qqRuntime.pendingGateId = null;
|
|
888
|
+
qqRuntime.replyThisTurn = false;
|
|
889
|
+
if (channel) await channel.stop();
|
|
890
|
+
if (shouldDisable) setDesktopQQEnabled(false);
|
|
891
|
+
setQQRuntimeState("disconnected");
|
|
892
|
+
}
|
|
543
893
|
function createTabSkeleton(initialDir) {
|
|
544
894
|
const dir = resolve(initialDir ?? opts.dir ?? loadWorkspaceDir() ?? process.cwd());
|
|
545
895
|
pushRecentWorkspace(dir);
|
|
@@ -667,10 +1017,12 @@ async function desktopCommand(opts) {
|
|
|
667
1017
|
persistOpenTabs();
|
|
668
1018
|
emit({ type: "$tab_closed" }, tab.id);
|
|
669
1019
|
}
|
|
670
|
-
async function runTurn(tab, text) {
|
|
1020
|
+
async function runTurn(tab, text, fromQQ = false) {
|
|
671
1021
|
if (!tab.runtime) return;
|
|
672
1022
|
const rt = tab.runtime;
|
|
673
1023
|
tab.aborter = new AbortController();
|
|
1024
|
+
qqRuntime.replyThisTurn = fromQQ;
|
|
1025
|
+
let lastAssistantText = "";
|
|
674
1026
|
if (tab.currentSession) {
|
|
675
1027
|
const existing = loadSessionMeta(tab.currentSession).summary;
|
|
676
1028
|
if (!existing || !existing.trim()) {
|
|
@@ -686,6 +1038,9 @@ async function desktopCommand(opts) {
|
|
|
686
1038
|
await tabContext.run(tab.id, async () => {
|
|
687
1039
|
try {
|
|
688
1040
|
for await (const ev of rt.loop.step(text)) {
|
|
1041
|
+
if (ev.role === "assistant_final" && ev.content) {
|
|
1042
|
+
lastAssistantText = ev.content;
|
|
1043
|
+
}
|
|
689
1044
|
for (const kev of rt.eventizer.consume(ev, rt.ctx)) emit(kev, tab.id);
|
|
690
1045
|
if (ev.role === "tool" && (ev.toolName === "remember" || ev.toolName === "forget")) {
|
|
691
1046
|
emitMemory(tab);
|
|
@@ -696,6 +1051,12 @@ async function desktopCommand(opts) {
|
|
|
696
1051
|
emit({ type: "$error", message: err.message }, tab.id);
|
|
697
1052
|
} finally {
|
|
698
1053
|
tab.aborter = null;
|
|
1054
|
+
if (fromQQ && lastAssistantText && qqRuntime.channel && qqRuntime.replyThisTurn) {
|
|
1055
|
+
await qqRuntime.channel.sendResponse(lastAssistantText).catch((err) => {
|
|
1056
|
+
emit({ type: "$error", message: `qq send failed: ${err.message}` }, tab.id);
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
qqRuntime.replyThisTurn = false;
|
|
699
1060
|
emit({ type: "$turn_complete" }, tab.id);
|
|
700
1061
|
if (tab.planTotalSteps > 0 && tab.completedStepIds.size >= tab.planTotalSteps) {
|
|
701
1062
|
tab.completedStepIds.clear();
|
|
@@ -828,11 +1189,11 @@ async function desktopCommand(opts) {
|
|
|
828
1189
|
emit({ type: "$plan_cleared" }, tab.id);
|
|
829
1190
|
}
|
|
830
1191
|
}
|
|
831
|
-
let first;
|
|
832
1192
|
let shuttingDown = false;
|
|
833
1193
|
async function gracefulShutdown() {
|
|
834
1194
|
if (shuttingDown) return;
|
|
835
1195
|
shuttingDown = true;
|
|
1196
|
+
await stopDesktopQQ(false).catch(() => void 0);
|
|
836
1197
|
await Promise.allSettled(
|
|
837
1198
|
[...tabs.values()].map((t) => t.toolset?.jobs.shutdown(1500) ?? Promise.resolve())
|
|
838
1199
|
);
|
|
@@ -848,6 +1209,7 @@ async function desktopCommand(opts) {
|
|
|
848
1209
|
const tab = activeRunningTab();
|
|
849
1210
|
const tabId = tab?.id;
|
|
850
1211
|
if (tab) tab.pendingGateIds.add(req.id);
|
|
1212
|
+
qqRuntime.pendingGateId = req.id;
|
|
851
1213
|
const auto = autoResolveVerdict(req, loadEditMode());
|
|
852
1214
|
if (auto !== null) {
|
|
853
1215
|
if (req.kind === "plan_checkpoint") {
|
|
@@ -871,9 +1233,20 @@ async function desktopCommand(opts) {
|
|
|
871
1233
|
if (req.kind === "run_command" || req.kind === "run_background") {
|
|
872
1234
|
const payload = req.payload;
|
|
873
1235
|
emit(
|
|
874
|
-
{
|
|
1236
|
+
{
|
|
1237
|
+
type: "$confirm_required",
|
|
1238
|
+
id: req.id,
|
|
1239
|
+
kind: req.kind,
|
|
1240
|
+
command: payload.command ?? "",
|
|
1241
|
+
prompt: toApprovalPrompt({
|
|
1242
|
+
id: req.id,
|
|
1243
|
+
kind: req.kind,
|
|
1244
|
+
payload
|
|
1245
|
+
})
|
|
1246
|
+
},
|
|
875
1247
|
tabId
|
|
876
1248
|
);
|
|
1249
|
+
if (tab) handleQQPauseRequest(tab, req.kind, payload);
|
|
877
1250
|
return;
|
|
878
1251
|
}
|
|
879
1252
|
if (req.kind === "path_access") {
|
|
@@ -886,10 +1259,16 @@ async function desktopCommand(opts) {
|
|
|
886
1259
|
intent: payload.intent,
|
|
887
1260
|
toolName: payload.toolName,
|
|
888
1261
|
sandboxRoot: payload.sandboxRoot,
|
|
889
|
-
allowPrefix: payload.allowPrefix
|
|
1262
|
+
allowPrefix: payload.allowPrefix,
|
|
1263
|
+
prompt: toApprovalPrompt({
|
|
1264
|
+
id: req.id,
|
|
1265
|
+
kind: req.kind,
|
|
1266
|
+
payload
|
|
1267
|
+
})
|
|
890
1268
|
},
|
|
891
1269
|
tabId
|
|
892
1270
|
);
|
|
1271
|
+
if (tab) handleQQPauseRequest(tab, req.kind, payload);
|
|
893
1272
|
return;
|
|
894
1273
|
}
|
|
895
1274
|
if (req.kind === "choice") {
|
|
@@ -904,6 +1283,7 @@ async function desktopCommand(opts) {
|
|
|
904
1283
|
},
|
|
905
1284
|
tabId
|
|
906
1285
|
);
|
|
1286
|
+
if (tab) handleQQPauseRequest(tab, req.kind, payload);
|
|
907
1287
|
return;
|
|
908
1288
|
}
|
|
909
1289
|
if (req.kind === "plan_proposed") {
|
|
@@ -922,6 +1302,7 @@ async function desktopCommand(opts) {
|
|
|
922
1302
|
},
|
|
923
1303
|
tabId
|
|
924
1304
|
);
|
|
1305
|
+
if (tab) handleQQPauseRequest(tab, req.kind, payload);
|
|
925
1306
|
return;
|
|
926
1307
|
}
|
|
927
1308
|
if (req.kind === "plan_checkpoint") {
|
|
@@ -950,6 +1331,7 @@ async function desktopCommand(opts) {
|
|
|
950
1331
|
},
|
|
951
1332
|
tabId
|
|
952
1333
|
);
|
|
1334
|
+
if (tab) handleQQPauseRequest(tab, req.kind, payload);
|
|
953
1335
|
return;
|
|
954
1336
|
}
|
|
955
1337
|
if (req.kind === "plan_revision") {
|
|
@@ -964,6 +1346,7 @@ async function desktopCommand(opts) {
|
|
|
964
1346
|
},
|
|
965
1347
|
tabId
|
|
966
1348
|
);
|
|
1349
|
+
if (tab) handleQQPauseRequest(tab, req.kind, payload);
|
|
967
1350
|
return;
|
|
968
1351
|
}
|
|
969
1352
|
const exhaustive = req.kind;
|
|
@@ -1035,6 +1418,12 @@ async function desktopCommand(opts) {
|
|
|
1035
1418
|
const activeIdx = savedTabs.findIndex((t) => t.active);
|
|
1036
1419
|
lastActiveTabId = ((activeIdx >= 0 ? restored[activeIdx] : first) ?? first).id;
|
|
1037
1420
|
persistOpenTabs();
|
|
1421
|
+
const qqConfig = loadQQConfig();
|
|
1422
|
+
if (qqConfig.enabled && qqConfig.appId && qqConfig.appSecret) {
|
|
1423
|
+
void startDesktopQQ(false).catch(() => void 0);
|
|
1424
|
+
} else {
|
|
1425
|
+
broadcastQQSettings();
|
|
1426
|
+
}
|
|
1038
1427
|
const rl = createInterface({ input: stdin });
|
|
1039
1428
|
rl.on("line", (line) => {
|
|
1040
1429
|
const trimmed = line.trim();
|
|
@@ -1126,6 +1515,25 @@ async function desktopCommand(opts) {
|
|
|
1126
1515
|
}
|
|
1127
1516
|
return;
|
|
1128
1517
|
}
|
|
1518
|
+
if (msg.cmd === "desktop_resync") {
|
|
1519
|
+
const hasKey = !!loadApiKey();
|
|
1520
|
+
for (const t of tabs.values()) {
|
|
1521
|
+
emit(
|
|
1522
|
+
{ type: "$tab_opened", workspaceDir: t.rootDir, active: t.id === lastActiveTabId },
|
|
1523
|
+
t.id
|
|
1524
|
+
);
|
|
1525
|
+
emitSessions(t);
|
|
1526
|
+
emitSettings(t);
|
|
1527
|
+
emitMcpSpecs(t);
|
|
1528
|
+
emitSkills(t);
|
|
1529
|
+
emitMemory(t);
|
|
1530
|
+
emitQQSettings(t);
|
|
1531
|
+
if (!hasKey) emit({ type: "$needs_setup", reason: "no_api_key" }, t.id);
|
|
1532
|
+
else if (t.toolset) emit({ type: "$ready" }, t.id);
|
|
1533
|
+
void emitBalance(t);
|
|
1534
|
+
}
|
|
1535
|
+
return;
|
|
1536
|
+
}
|
|
1129
1537
|
if (msg.cmd === "jobs_list") {
|
|
1130
1538
|
emitJobs();
|
|
1131
1539
|
return;
|
|
@@ -1247,6 +1655,19 @@ ${found.body}${argsLine}`;
|
|
|
1247
1655
|
emitSessions(tab);
|
|
1248
1656
|
return;
|
|
1249
1657
|
}
|
|
1658
|
+
if (msg.cmd === "session_rename") {
|
|
1659
|
+
try {
|
|
1660
|
+
const trimmed2 = normalizeSessionTitle(msg.title);
|
|
1661
|
+
patchSessionMeta(msg.name, { summary: trimmed2 || void 0 });
|
|
1662
|
+
emitSessions(tab);
|
|
1663
|
+
} catch (err) {
|
|
1664
|
+
emit(
|
|
1665
|
+
{ type: "$error", message: `session_rename failed: ${err.message}` },
|
|
1666
|
+
tab.id
|
|
1667
|
+
);
|
|
1668
|
+
}
|
|
1669
|
+
return;
|
|
1670
|
+
}
|
|
1250
1671
|
if (msg.cmd === "session_load") {
|
|
1251
1672
|
try {
|
|
1252
1673
|
const records = loadSessionMessages(msg.name);
|
|
@@ -1367,18 +1788,38 @@ ${found.body}${argsLine}`;
|
|
|
1367
1788
|
if (msg.cmd === "qq_connect") {
|
|
1368
1789
|
try {
|
|
1369
1790
|
const current = loadQQConfig();
|
|
1370
|
-
setDesktopQQEnabled(true);
|
|
1371
1791
|
emit(
|
|
1372
1792
|
{
|
|
1373
1793
|
type: "status",
|
|
1374
1794
|
id: Date.now(),
|
|
1375
1795
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1376
1796
|
turn: 0,
|
|
1377
|
-
text: `QQ
|
|
1797
|
+
text: `QQ connecting (${current.sandbox ? "sandbox" : "production"})`
|
|
1378
1798
|
},
|
|
1379
1799
|
tab.id
|
|
1380
1800
|
);
|
|
1381
|
-
|
|
1801
|
+
void startDesktopQQ(true).then(
|
|
1802
|
+
() => {
|
|
1803
|
+
emit(
|
|
1804
|
+
{
|
|
1805
|
+
type: "status",
|
|
1806
|
+
id: Date.now(),
|
|
1807
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1808
|
+
turn: 0,
|
|
1809
|
+
text: `QQ connected (${current.sandbox ? "sandbox" : "production"})`
|
|
1810
|
+
},
|
|
1811
|
+
tab.id
|
|
1812
|
+
);
|
|
1813
|
+
emitQQSettings(tab);
|
|
1814
|
+
},
|
|
1815
|
+
(err) => {
|
|
1816
|
+
emit(
|
|
1817
|
+
{ type: "$error", message: `qq_connect failed: ${err.message}` },
|
|
1818
|
+
tab.id
|
|
1819
|
+
);
|
|
1820
|
+
emitQQSettings(tab);
|
|
1821
|
+
}
|
|
1822
|
+
);
|
|
1382
1823
|
} catch (err) {
|
|
1383
1824
|
emit({ type: "$error", message: `qq_connect failed: ${err.message}` }, tab.id);
|
|
1384
1825
|
emitQQSettings(tab);
|
|
@@ -1387,18 +1828,27 @@ ${found.body}${argsLine}`;
|
|
|
1387
1828
|
}
|
|
1388
1829
|
if (msg.cmd === "qq_disconnect") {
|
|
1389
1830
|
try {
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1831
|
+
void stopDesktopQQ(true).then(
|
|
1832
|
+
() => {
|
|
1833
|
+
emit(
|
|
1834
|
+
{
|
|
1835
|
+
type: "status",
|
|
1836
|
+
id: Date.now(),
|
|
1837
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1838
|
+
turn: 0,
|
|
1839
|
+
text: "QQ disabled"
|
|
1840
|
+
},
|
|
1841
|
+
tab.id
|
|
1842
|
+
);
|
|
1843
|
+
emitQQSettings(tab);
|
|
1398
1844
|
},
|
|
1399
|
-
|
|
1845
|
+
(err) => {
|
|
1846
|
+
emit(
|
|
1847
|
+
{ type: "$error", message: `qq_disconnect failed: ${err.message}` },
|
|
1848
|
+
tab.id
|
|
1849
|
+
);
|
|
1850
|
+
}
|
|
1400
1851
|
);
|
|
1401
|
-
emitQQSettings(tab);
|
|
1402
1852
|
} catch (err) {
|
|
1403
1853
|
emit(
|
|
1404
1854
|
{ type: "$error", message: `qq_disconnect failed: ${err.message}` },
|
|
@@ -1481,7 +1931,7 @@ ${found.body}${argsLine}`;
|
|
|
1481
1931
|
}
|
|
1482
1932
|
if (msg.cmd === "compact_history") {
|
|
1483
1933
|
if (!tab.runtime) return;
|
|
1484
|
-
void tab.runtime.loop.compactHistory().catch((err) => {
|
|
1934
|
+
void tab.runtime.loop.compactHistory().then(() => emitCtxBreakdown(tab)).catch((err) => {
|
|
1485
1935
|
emit({ type: "$error", message: `/compact failed: ${err.message}` }, tab.id);
|
|
1486
1936
|
});
|
|
1487
1937
|
return;
|
|
@@ -1503,7 +1953,10 @@ ${found.body}${argsLine}`;
|
|
|
1503
1953
|
const reply = await tab.runtime.loop.client.chat({
|
|
1504
1954
|
model: tab.currentModel,
|
|
1505
1955
|
messages: [
|
|
1506
|
-
{
|
|
1956
|
+
{
|
|
1957
|
+
role: "system",
|
|
1958
|
+
content: "You are answering a side question that is unrelated to the current coding conversation. Answer concisely (1-3 sentences) in plain prose. Do not call tools, do not ask clarifying questions, and do not reference any prior turns."
|
|
1959
|
+
},
|
|
1507
1960
|
{ role: "user", content: question }
|
|
1508
1961
|
]
|
|
1509
1962
|
});
|
|
@@ -1535,6 +1988,8 @@ ${found.body}${argsLine}`;
|
|
|
1535
1988
|
}
|
|
1536
1989
|
export {
|
|
1537
1990
|
desktopCommand,
|
|
1538
|
-
installDesktopCrashGuards
|
|
1991
|
+
installDesktopCrashGuards,
|
|
1992
|
+
normalizeSessionTitle,
|
|
1993
|
+
writeAllSync
|
|
1539
1994
|
};
|
|
1540
|
-
//# sourceMappingURL=desktop-
|
|
1995
|
+
//# sourceMappingURL=desktop-G7UMW3CJ.js.map
|