@yu_robotics/remote-cli 1.6.111 → 1.6.113
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/dist/client/MessageHandler.d.ts +4 -0
- package/dist/client/MessageHandler.d.ts.map +1 -1
- package/dist/client/MessageHandler.js +113 -9
- package/dist/client/MessageHandler.js.map +1 -1
- package/dist/client/WebSocketClient.d.ts +5 -0
- package/dist/client/WebSocketClient.d.ts.map +1 -1
- package/dist/client/WebSocketClient.js +37 -3
- package/dist/client/WebSocketClient.js.map +1 -1
- package/dist/commands/files.d.ts +5 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +30 -0
- package/dist/commands/files.js.map +1 -0
- package/dist/commands/start.d.ts.map +1 -1
- package/dist/commands/start.js +4 -1
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.d.ts.map +1 -1
- package/dist/commands/status.js +4 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/files/DeviceIdentity.d.ts +10 -0
- package/dist/files/DeviceIdentity.d.ts.map +1 -0
- package/dist/files/DeviceIdentity.js +82 -0
- package/dist/files/DeviceIdentity.js.map +1 -0
- package/dist/files/DocumentExtractor.d.ts +4 -0
- package/dist/files/DocumentExtractor.d.ts.map +1 -0
- package/dist/files/DocumentExtractor.js +59 -0
- package/dist/files/DocumentExtractor.js.map +1 -0
- package/dist/files/DocumentWorker.d.ts +3 -0
- package/dist/files/DocumentWorker.d.ts.map +1 -0
- package/dist/files/DocumentWorker.js +359 -0
- package/dist/files/DocumentWorker.js.map +1 -0
- package/dist/files/FileIO.d.ts +21 -0
- package/dist/files/FileIO.d.ts.map +1 -0
- package/dist/files/FileIO.js +134 -0
- package/dist/files/FileIO.js.map +1 -0
- package/dist/files/FileInbox.d.ts +60 -0
- package/dist/files/FileInbox.d.ts.map +1 -0
- package/dist/files/FileInbox.js +426 -0
- package/dist/files/FileInbox.js.map +1 -0
- package/dist/index.js +16 -0
- package/dist/index.js.map +1 -1
- package/dist/types/config.d.ts +3 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/index.d.ts +5 -3
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -1
|
@@ -37,11 +37,13 @@ export declare class MessageHandler {
|
|
|
37
37
|
private readonly abortOperations;
|
|
38
38
|
private automaticUpdateInProgress;
|
|
39
39
|
private approvalCardsSupported;
|
|
40
|
+
private streamingContextSupported;
|
|
40
41
|
private delegationProgressSupported;
|
|
41
42
|
private delegationProgressTextSupported;
|
|
42
43
|
private readonly pendingApprovalCards;
|
|
43
44
|
private readonly delegation;
|
|
44
45
|
private readonly delegationBridges;
|
|
46
|
+
private fileInbox?;
|
|
45
47
|
constructor(wsClient: WebSocketClient, threadPool: ThreadExecutorPool, threadManager: ThreadManager, directoryGuard: DirectoryGuard, config: ConfigManager);
|
|
46
48
|
reconcilePendingDelegatedWorkers(): Promise<void>;
|
|
47
49
|
/**
|
|
@@ -165,6 +167,8 @@ export declare class MessageHandler {
|
|
|
165
167
|
private showApprovalFallback;
|
|
166
168
|
private resolveApprovalCard;
|
|
167
169
|
private handleApprovalResponse;
|
|
170
|
+
/** Publish routing metadata before backend startup or the first output token. */
|
|
171
|
+
private sendStreamContext;
|
|
168
172
|
private sendStreamChunk;
|
|
169
173
|
private sendToolUse;
|
|
170
174
|
private sendToolResult;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../src/client/MessageHandler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"MessageHandler.d.ts","sourceRoot":"","sources":["../../src/client/MessageHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.MessageHandler = void 0;
|
|
7
|
+
const FileInbox_1 = require("../files/FileInbox");
|
|
8
|
+
const DeviceIdentity_1 = require("../files/DeviceIdentity");
|
|
9
|
+
const crypto_1 = require("crypto");
|
|
10
|
+
const DocumentExtractor_1 = require("../files/DocumentExtractor");
|
|
11
|
+
const path_1 = __importDefault(require("path"));
|
|
4
12
|
const hooks_1 = require("../hooks");
|
|
5
13
|
const FileReadDetector_1 = require("../utils/FileReadDetector");
|
|
6
14
|
const LocalImageDetector_1 = require("../utils/LocalImageDetector");
|
|
@@ -10,7 +18,7 @@ const child_process_1 = require("child_process");
|
|
|
10
18
|
const promises_1 = require("fs/promises");
|
|
11
19
|
const fs_1 = require("fs");
|
|
12
20
|
const os_1 = require("os");
|
|
13
|
-
const
|
|
21
|
+
const path_2 = require("path");
|
|
14
22
|
const config_1 = require("../types/config");
|
|
15
23
|
const uuid_1 = require("uuid");
|
|
16
24
|
const ZCodeCommand_1 = require("../executor/zcode/ZCodeCommand");
|
|
@@ -94,17 +102,20 @@ class MessageHandler {
|
|
|
94
102
|
abortOperations = new Map();
|
|
95
103
|
automaticUpdateInProgress = false;
|
|
96
104
|
approvalCardsSupported = false;
|
|
105
|
+
streamingContextSupported = false;
|
|
97
106
|
delegationProgressSupported = false;
|
|
98
107
|
delegationProgressTextSupported = false;
|
|
99
108
|
pendingApprovalCards = new Map();
|
|
100
109
|
delegation;
|
|
101
110
|
delegationBridges = new Map();
|
|
111
|
+
fileInbox;
|
|
102
112
|
constructor(wsClient, threadPool, threadManager, directoryGuard, config) {
|
|
103
113
|
this.wsClient = wsClient;
|
|
104
114
|
this.threadPool = threadPool;
|
|
105
115
|
this.threadManager = threadManager;
|
|
106
116
|
this.directoryGuard = directoryGuard;
|
|
107
117
|
this.config = config;
|
|
118
|
+
this.wsClient.onClose?.(() => this.fileInbox?.disconnect());
|
|
108
119
|
this.delegation = new DelegationManager_1.DelegationManager(directoryGuard);
|
|
109
120
|
this.notificationAdapter = new hooks_1.FeishuNotificationAdapter(wsClient);
|
|
110
121
|
this.notificationAdapter.setThreadNameResolver((threadId) => this.threadManager.getThread(threadId)?.name);
|
|
@@ -140,7 +151,20 @@ class MessageHandler {
|
|
|
140
151
|
await this.handleStatusQuery(message.messageId);
|
|
141
152
|
return;
|
|
142
153
|
case 'command':
|
|
143
|
-
await this.handleCommandMessage(message);
|
|
154
|
+
await this.handleCommandMessage(message, this.fileInbox?.mark());
|
|
155
|
+
return;
|
|
156
|
+
case 'file_pending':
|
|
157
|
+
if (this.fileInbox)
|
|
158
|
+
await this.fileInbox.accept(message);
|
|
159
|
+
else
|
|
160
|
+
this.wsClient.send({ type: 'file_status', fileId: message.fileId, status: 'failed',
|
|
161
|
+
detail: 'Local file staging is unavailable. Check secure enrollment, files.retentionDays and storage permissions.' });
|
|
162
|
+
return;
|
|
163
|
+
case 'file_available':
|
|
164
|
+
this.fileInbox?.available(message);
|
|
165
|
+
return;
|
|
166
|
+
case 'file_failed':
|
|
167
|
+
await this.fileInbox?.failed(message.fileId, message.detail);
|
|
144
168
|
return;
|
|
145
169
|
case 'heartbeat':
|
|
146
170
|
return;
|
|
@@ -148,7 +172,24 @@ class MessageHandler {
|
|
|
148
172
|
const data = message.data;
|
|
149
173
|
if (data?.success !== true)
|
|
150
174
|
return;
|
|
175
|
+
if (data.capabilities?.fileTransferV1 === true && !this.fileInbox) {
|
|
176
|
+
try {
|
|
177
|
+
const fileServer = this.config.get('serverUrl');
|
|
178
|
+
const fileNamespace = (0, crypto_1.createHash)('sha256').update((0, DeviceIdentity_1.fileOrigin)(fileServer)).digest('hex');
|
|
179
|
+
this.fileInbox = new FileInbox_1.FileInbox(path_1.default.join(this.config.getConfigDir(), 'attachments', fileNamespace), fileServer, {
|
|
180
|
+
thread: id => id ? this.threadManager.getThread(id) : this.threadManager.getDefaultThread(),
|
|
181
|
+
send: value => this.wsClient.send(value), extract: DocumentExtractor_1.extractDocument,
|
|
182
|
+
}, this.config.get('files.retentionDays'));
|
|
183
|
+
await this.fileInbox.initialize();
|
|
184
|
+
}
|
|
185
|
+
catch {
|
|
186
|
+
await this.fileInbox?.destroy();
|
|
187
|
+
this.fileInbox = undefined;
|
|
188
|
+
console.error('[Files] Local staging is unavailable. File requests will fail without running a model.');
|
|
189
|
+
}
|
|
190
|
+
}
|
|
151
191
|
this.approvalCardsSupported = data.capabilities?.approvalCards === true;
|
|
192
|
+
this.streamingContextSupported = data.capabilities?.streamingContext === true;
|
|
152
193
|
this.delegationProgressSupported = data.capabilities?.delegationProgress === true;
|
|
153
194
|
this.delegationProgressTextSupported = this.delegationProgressSupported
|
|
154
195
|
&& data.capabilities?.delegationProgressText === true;
|
|
@@ -196,7 +237,7 @@ class MessageHandler {
|
|
|
196
237
|
/**
|
|
197
238
|
* Handle command message — route to the correct thread executor.
|
|
198
239
|
*/
|
|
199
|
-
async handleCommandMessage(message) {
|
|
240
|
+
async handleCommandMessage(message, fileOrder) {
|
|
200
241
|
const { messageId, content, attachments, workingDirectory, openId, isSlashCommand, threadId } = message;
|
|
201
242
|
this.currentOpenId = openId;
|
|
202
243
|
this.messageOpenIds.set(message.messageId, openId);
|
|
@@ -221,6 +262,7 @@ class MessageHandler {
|
|
|
221
262
|
return;
|
|
222
263
|
}
|
|
223
264
|
const executor = this.threadPool.getExecutor(resolvedThreadId);
|
|
265
|
+
this.sendStreamContext(messageId, resolvedThreadId, executor);
|
|
224
266
|
// Handle /abort for this specific thread (bypasses busy check)
|
|
225
267
|
if (content?.trim() === '/abort') {
|
|
226
268
|
await this.handleAbortCommand(messageId, resolvedThreadId, executor);
|
|
@@ -291,12 +333,26 @@ class MessageHandler {
|
|
|
291
333
|
return;
|
|
292
334
|
}
|
|
293
335
|
}
|
|
336
|
+
const ordinaryMessage = !isSlashCommand && !content?.trim().startsWith('/');
|
|
337
|
+
if (ordinaryMessage) {
|
|
338
|
+
try {
|
|
339
|
+
if (message.fileIds?.length && !this.fileInbox)
|
|
340
|
+
throw new Error('File support was not negotiated. Upgrade and enroll this CLI first.');
|
|
341
|
+
if (this.fileInbox) {
|
|
342
|
+
await this.fileInbox.initialize();
|
|
343
|
+
this.fileInbox.claim(messageId, resolvedThreadId, openId, message.fileIds, fileOrder);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
catch (error) {
|
|
347
|
+
this.sendResponse(messageId, resolvedThreadId, { success: false, error: error instanceof Error ? error.message : 'Attachment is unavailable.' });
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
294
351
|
const threadBusy = this.threadPool.isThreadBusy(resolvedThreadId);
|
|
295
352
|
const queuedCount = this.threadQueues.get(resolvedThreadId)?.length ?? 0;
|
|
296
353
|
if (!threadBusy && !this.hasThreadQueueState(resolvedThreadId))
|
|
297
354
|
this.pausedQueues.delete(resolvedThreadId);
|
|
298
355
|
const queuePaused = this.pausedQueues.has(resolvedThreadId);
|
|
299
|
-
const ordinaryMessage = !isSlashCommand && !content?.trim().startsWith('/');
|
|
300
356
|
// An idle executor can still have a paused queue. New work must not overtake it.
|
|
301
357
|
if (threadBusy || (ordinaryMessage && (queuedCount > 0 || queuePaused))) {
|
|
302
358
|
// Allow pending replace even when busy
|
|
@@ -405,6 +461,7 @@ class MessageHandler {
|
|
|
405
461
|
* Handle /abort command for a specific thread executor
|
|
406
462
|
*/
|
|
407
463
|
async handleAbortCommand(messageId, threadId, executor) {
|
|
464
|
+
this.fileInbox?.cancelThread(threadId);
|
|
408
465
|
const existingAbort = this.abortOperations.get(threadId);
|
|
409
466
|
if (existingAbort) {
|
|
410
467
|
await existingAbort;
|
|
@@ -490,6 +547,12 @@ class MessageHandler {
|
|
|
490
547
|
*/
|
|
491
548
|
async handleBuiltInCommand(messageId, threadId, content, executor) {
|
|
492
549
|
const trimmed = content.trim();
|
|
550
|
+
if (trimmed === '/files' || trimmed === '/files clear') {
|
|
551
|
+
this.sendResponse(messageId, threadId, { success: true, output: this.fileInbox
|
|
552
|
+
? await this.fileInbox.list(threadId, this.getMessageOpenId(messageId), trimmed === '/files clear')
|
|
553
|
+
: 'File reception is unavailable. Upgrade both peers, configure Router TLS, run remote-cli files enable locally, approve its binding code, and reconnect.' });
|
|
554
|
+
return true;
|
|
555
|
+
}
|
|
493
556
|
if (trimmed === '/delegation' || trimmed.startsWith('/delegation ')) {
|
|
494
557
|
const argumentsList = trimmed.slice('/delegation'.length).trim().split(/\s+/).filter(Boolean);
|
|
495
558
|
const action = argumentsList[0];
|
|
@@ -917,23 +980,30 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
917
980
|
});
|
|
918
981
|
setTimeout(() => {
|
|
919
982
|
const pending = this.pendingQueueConfirmations.get(id);
|
|
920
|
-
if (pending && pending.info.expiresAt <= Date.now())
|
|
983
|
+
if (pending && pending.info.expiresAt <= Date.now()) {
|
|
984
|
+
this.fileInbox?.release(pending.command.messageId);
|
|
921
985
|
this.pendingQueueConfirmations.delete(id);
|
|
986
|
+
}
|
|
922
987
|
}, QUEUE_CONFIRMATION_TTL_MS).unref?.();
|
|
923
988
|
return info;
|
|
924
989
|
}
|
|
925
990
|
removeExpiredQueueConfirmations() {
|
|
926
991
|
const now = Date.now();
|
|
927
992
|
for (const [id, pending] of this.pendingQueueConfirmations) {
|
|
928
|
-
if (pending.info.expiresAt <= now)
|
|
993
|
+
if (pending.info.expiresAt <= now) {
|
|
994
|
+
this.fileInbox?.release(pending.command.messageId);
|
|
929
995
|
this.pendingQueueConfirmations.delete(id);
|
|
996
|
+
}
|
|
930
997
|
}
|
|
931
998
|
}
|
|
932
999
|
clearThreadQueue(threadId) {
|
|
933
1000
|
let cleared = this.threadQueues.get(threadId)?.length ?? 0;
|
|
1001
|
+
for (const command of this.threadQueues.get(threadId) ?? [])
|
|
1002
|
+
this.fileInbox?.release(command.messageId);
|
|
934
1003
|
this.threadQueues.delete(threadId);
|
|
935
1004
|
for (const [id, pending] of this.pendingQueueConfirmations) {
|
|
936
1005
|
if (pending.info.threadId === threadId) {
|
|
1006
|
+
this.fileInbox?.release(pending.command.messageId);
|
|
937
1007
|
this.pendingQueueConfirmations.delete(id);
|
|
938
1008
|
cleared += 1;
|
|
939
1009
|
}
|
|
@@ -960,6 +1030,8 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
960
1030
|
if (!pending || pending.info.threadId !== threadId || pending.info.expiresAt <= Date.now()
|
|
961
1031
|
|| pending.info.backend !== this.threadPool.getBackendKey(threadId) || pending.info.cwd !== currentCwd
|
|
962
1032
|
|| (pending.command.openId && pending.command.openId !== this.getMessageOpenId(messageId))) {
|
|
1033
|
+
if (pending)
|
|
1034
|
+
this.fileInbox?.release(pending.command.messageId);
|
|
963
1035
|
this.pendingQueueConfirmations.delete(id);
|
|
964
1036
|
this.sendResponse(messageId, threadId, { success: false, error: 'Queue confirmation is no longer valid. The message was not queued.' });
|
|
965
1037
|
return;
|
|
@@ -967,9 +1039,11 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
967
1039
|
this.pendingQueueConfirmations.delete(id);
|
|
968
1040
|
const queue = this.threadQueues.get(threadId) ?? [];
|
|
969
1041
|
if (queue.length >= MAX_THREAD_QUEUE_LENGTH) {
|
|
1042
|
+
this.fileInbox?.release(pending.command.messageId);
|
|
970
1043
|
this.sendResponse(messageId, threadId, { success: false, error: `This thread queue is full (${MAX_THREAD_QUEUE_LENGTH} messages).` });
|
|
971
1044
|
return;
|
|
972
1045
|
}
|
|
1046
|
+
this.fileInbox?.moveClaim(pending.command.messageId, parts[3] || pending.command.messageId);
|
|
973
1047
|
queue.push({ ...pending.command, messageId: parts[3] || pending.command.messageId });
|
|
974
1048
|
this.threadQueues.set(threadId, queue);
|
|
975
1049
|
console.log(`[MessageHandler] Queued message ${parts[3] || pending.command.messageId} in thread ${threadId}: position=${queue.length}, paused=${this.pausedQueues.has(threadId)}`);
|
|
@@ -983,6 +1057,7 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
983
1057
|
if (action === 'cancel' && id) {
|
|
984
1058
|
const pending = this.pendingQueueConfirmations.get(id);
|
|
985
1059
|
if (pending?.info.threadId === threadId) {
|
|
1060
|
+
this.fileInbox?.release(pending.command.messageId);
|
|
986
1061
|
this.pendingQueueConfirmations.delete(id);
|
|
987
1062
|
this.sendResponse(messageId, threadId, { success: true, output: '❌ Message was not queued.' });
|
|
988
1063
|
}
|
|
@@ -1276,6 +1351,7 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
1276
1351
|
await this.delegation.store.deleteThread(target.id);
|
|
1277
1352
|
await this.threadPool.destroyThread(target.id);
|
|
1278
1353
|
await this.threadManager.deleteThread(target.id);
|
|
1354
|
+
await this.fileInbox?.deleteThread(target.id);
|
|
1279
1355
|
this.sendResponse(messageId, callerThreadId, {
|
|
1280
1356
|
success: true,
|
|
1281
1357
|
output: `✅ Thread "${name}" deleted.`,
|
|
@@ -1543,8 +1619,8 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
1543
1619
|
]);
|
|
1544
1620
|
async listLocalSkills(cwd, backend) {
|
|
1545
1621
|
const roots = backend === 'codex'
|
|
1546
|
-
? [(0,
|
|
1547
|
-
: [(0,
|
|
1622
|
+
? [(0, path_2.join)(cwd, '.agents', 'skills'), (0, path_2.join)((0, os_1.homedir)(), '.codex', 'skills'), (0, path_2.join)((0, os_1.homedir)(), '.codex', 'skills', '.system')]
|
|
1623
|
+
: [(0, path_2.join)(cwd, '.claude', 'skills'), (0, path_2.join)((0, os_1.homedir)(), '.claude', 'skills')];
|
|
1548
1624
|
const skills = [];
|
|
1549
1625
|
const seen = new Set();
|
|
1550
1626
|
for (const root of roots) {
|
|
@@ -1558,7 +1634,7 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
1558
1634
|
for (const entry of entries) {
|
|
1559
1635
|
if (!entry.isDirectory() || seen.has(entry.name))
|
|
1560
1636
|
continue;
|
|
1561
|
-
const skillPath = (0,
|
|
1637
|
+
const skillPath = (0, path_2.join)(root, entry.name, 'SKILL.md');
|
|
1562
1638
|
try {
|
|
1563
1639
|
const content = await (0, promises_1.readFile)(skillPath, 'utf8');
|
|
1564
1640
|
const description = content.match(/^description:\s*(.+)$/mi)?.[1]?.trim();
|
|
@@ -1705,6 +1781,7 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
1705
1781
|
* Execute AI command on a specific executor
|
|
1706
1782
|
*/
|
|
1707
1783
|
async executeCommand(messageId, threadId, content, executor, attachments, fromQueue = false) {
|
|
1784
|
+
this.sendStreamContext(messageId, threadId, executor);
|
|
1708
1785
|
let delegationScope;
|
|
1709
1786
|
let delegationBridge;
|
|
1710
1787
|
const complete = async (success, error) => {
|
|
@@ -1736,6 +1813,12 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
1736
1813
|
return success;
|
|
1737
1814
|
};
|
|
1738
1815
|
try {
|
|
1816
|
+
if (this.fileInbox?.hasClaim(messageId)) {
|
|
1817
|
+
this.sendStreamChunk(messageId, threadId, '📎 Waiting for attached files to be ready...\n');
|
|
1818
|
+
content += await this.fileInbox.prepare(messageId);
|
|
1819
|
+
if (this.isDestroyed || this.abortOperations.has(threadId))
|
|
1820
|
+
throw new Error('Attachment task cancelled.');
|
|
1821
|
+
}
|
|
1739
1822
|
const openId = this.getMessageOpenId(messageId);
|
|
1740
1823
|
const thread = this.threadManager.getThread(threadId);
|
|
1741
1824
|
if (thread?.delegation && executor.configureDelegation) {
|
|
@@ -2057,6 +2140,24 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
2057
2140
|
error: 'Approval could not be applied. Check the task output or choose another action.', timestamp: Date.now() });
|
|
2058
2141
|
}
|
|
2059
2142
|
}
|
|
2143
|
+
/** Publish routing metadata before backend startup or the first output token. */
|
|
2144
|
+
sendStreamContext(messageId, threadId, executor) {
|
|
2145
|
+
if (!this.streamingContextSupported)
|
|
2146
|
+
return;
|
|
2147
|
+
const thread = this.threadManager.getThread(threadId);
|
|
2148
|
+
const openId = this.getMessageOpenId(messageId);
|
|
2149
|
+
if (!thread || !openId)
|
|
2150
|
+
return;
|
|
2151
|
+
try {
|
|
2152
|
+
this.wsClient.send({
|
|
2153
|
+
type: 'stream_context', messageId, openId, threadId,
|
|
2154
|
+
threadName: thread.name, cwd: executor.getCurrentWorkingDirectory(), timestamp: Date.now(),
|
|
2155
|
+
});
|
|
2156
|
+
}
|
|
2157
|
+
catch (error) {
|
|
2158
|
+
console.error('Failed to send stream context:', error);
|
|
2159
|
+
}
|
|
2160
|
+
}
|
|
2060
2161
|
sendStreamChunk(messageId, threadId, chunk) {
|
|
2061
2162
|
try {
|
|
2062
2163
|
this.wsClient.send({
|
|
@@ -2186,6 +2287,8 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
2186
2287
|
}
|
|
2187
2288
|
}
|
|
2188
2289
|
sendResponse(messageId, threadId, result) {
|
|
2290
|
+
if (!result.queueConfirmation)
|
|
2291
|
+
this.fileInbox?.release(messageId, !result.success);
|
|
2189
2292
|
try {
|
|
2190
2293
|
// Resolve CWD from thread executor if possible
|
|
2191
2294
|
let cwd;
|
|
@@ -2348,6 +2451,7 @@ You can also use natural language commands to control Claude Code CLI.`,
|
|
|
2348
2451
|
*/
|
|
2349
2452
|
async destroy() {
|
|
2350
2453
|
this.isDestroyed = true;
|
|
2454
|
+
await this.fileInbox?.destroy();
|
|
2351
2455
|
this.notificationAdapter.unregister();
|
|
2352
2456
|
try {
|
|
2353
2457
|
await this.delegation.destroy();
|