lazy-gravity 0.9.2 → 0.11.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/dist/bin/commands/doctor.js +45 -7
- package/dist/bot/index.js +401 -41
- package/dist/bot/telegramMessageHandler.js +1 -0
- package/dist/commands/chatCommandHandler.js +43 -3
- package/dist/commands/registerSlashCommands.js +13 -1
- package/dist/events/interactionCreateHandler.js +456 -27
- package/dist/events/messageCreateHandler.js +66 -7
- package/dist/handlers/__tests__/fileChangeButtonAction.test.js +85 -0
- package/dist/handlers/approvalButtonAction.js +2 -1
- package/dist/handlers/errorPopupButtonAction.js +2 -1
- package/dist/handlers/fileChangeButtonAction.js +57 -0
- package/dist/handlers/genericActionButtonAction.js +72 -0
- package/dist/handlers/planningButtonAction.js +126 -23
- package/dist/handlers/planningModalSubmitAction.js +38 -0
- package/dist/handlers/questionSelectAction.js +70 -0
- package/dist/handlers/questionSkipAction.js +68 -0
- package/dist/handlers/runCommandButtonAction.js +2 -1
- package/dist/platform/discord/discordResponseRenderer.js +164 -0
- package/dist/platform/discord/wrappers.js +76 -0
- package/dist/services/approvalDetector.js +110 -35
- package/dist/services/artifactService.js +103 -37
- package/dist/services/assistantDomExtractor.js +194 -3
- package/dist/services/cdpBridgeManager.js +149 -8
- package/dist/services/cdpConnectionPool.js +22 -2
- package/dist/services/cdpService.js +134 -15
- package/dist/services/chatSessionService.js +147 -40
- package/dist/services/errorPopupDetector.js +23 -11
- package/dist/services/notificationSender.js +80 -3
- package/dist/services/planningDetector.js +69 -25
- package/dist/services/promptDispatcher.js +27 -1
- package/dist/services/questionDetector.js +428 -0
- package/dist/services/responseMonitor.js +45 -3
- package/dist/services/runCommandDetector.js +14 -7
- package/dist/ui/artifactsUi.js +4 -3
- package/dist/utils/consecutiveEmptyPollGate.js +21 -0
- package/dist/utils/fileOpenCache.js +29 -0
- package/dist/utils/htmlToDiscordMarkdown.js +5 -2
- package/dist/utils/pathUtils.js +12 -0
- package/dist/utils/projectResolver.js +10 -0
- package/dist/utils/questionActionUtils.js +47 -0
- package/package.json +1 -1
|
@@ -1,16 +1,32 @@
|
|
|
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.createInteractionCreateHandler = createInteractionCreateHandler;
|
|
4
7
|
const discord_js_1 = require("discord.js");
|
|
8
|
+
const child_process_1 = require("child_process");
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const fs_1 = __importDefault(require("fs"));
|
|
11
|
+
const genericActionButtonAction_1 = require("../handlers/genericActionButtonAction");
|
|
5
12
|
const i18n_1 = require("../utils/i18n");
|
|
6
13
|
const logger_1 = require("../utils/logger");
|
|
7
14
|
const discordButtonUtils_1 = require("../utils/discordButtonUtils");
|
|
15
|
+
const pathUtils_1 = require("../utils/pathUtils");
|
|
16
|
+
const fileOpenCache_1 = require("../utils/fileOpenCache");
|
|
8
17
|
const templateUi_1 = require("../ui/templateUi");
|
|
9
18
|
const autoAcceptUi_1 = require("../ui/autoAcceptUi");
|
|
10
19
|
const outputUi_1 = require("../ui/outputUi");
|
|
20
|
+
const notificationSender_1 = require("../services/notificationSender");
|
|
21
|
+
const questionSelectAction_1 = require("../handlers/questionSelectAction");
|
|
22
|
+
const questionSkipAction_1 = require("../handlers/questionSkipAction");
|
|
23
|
+
const wrappers_1 = require("../platform/discord/wrappers");
|
|
24
|
+
const questionActionUtils_1 = require("../utils/questionActionUtils");
|
|
25
|
+
const projectResolver_1 = require("../utils/projectResolver");
|
|
11
26
|
const cleanupCommandHandler_1 = require("../commands/cleanupCommandHandler");
|
|
12
27
|
const projectListUi_1 = require("../ui/projectListUi");
|
|
13
28
|
const modeService_1 = require("../services/modeService");
|
|
29
|
+
const approvalDetector_1 = require("../services/approvalDetector");
|
|
14
30
|
const sessionPickerUi_1 = require("../ui/sessionPickerUi");
|
|
15
31
|
const artifactsUi_1 = require("../ui/artifactsUi");
|
|
16
32
|
const artifactService_1 = require("../services/artifactService");
|
|
@@ -37,16 +53,35 @@ function createInteractionCreateHandler(deps) {
|
|
|
37
53
|
accountPrefRepo: deps.accountPrefRepo,
|
|
38
54
|
accounts: deps.antigravityAccounts,
|
|
39
55
|
});
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
56
|
+
const resolveProjectFromChannel = (interaction) => {
|
|
57
|
+
if (!interaction.channelId)
|
|
58
|
+
return null;
|
|
59
|
+
let workspacePath = deps.wsHandler.getWorkspaceForChannel(interaction.channelId);
|
|
60
|
+
if (!workspacePath) {
|
|
61
|
+
const parentId = getParentChannelId(interaction);
|
|
62
|
+
if (parentId) {
|
|
63
|
+
workspacePath = deps.wsHandler.getWorkspaceForChannel(parentId);
|
|
64
|
+
}
|
|
45
65
|
}
|
|
46
|
-
return deps.bridge.
|
|
47
|
-
|
|
48
|
-
|
|
66
|
+
return workspacePath ? deps.bridge.pool.extractProjectName(workspacePath) : null;
|
|
67
|
+
};
|
|
68
|
+
const getChannelCdp = (interaction) => (() => {
|
|
69
|
+
if (!interaction.channelId)
|
|
70
|
+
return null;
|
|
71
|
+
const projectName = resolveProjectFromChannel(interaction);
|
|
72
|
+
if (projectName) {
|
|
73
|
+
return deps.bridge.pool.getConnected(projectName, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction)));
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
49
76
|
})();
|
|
77
|
+
const buildResumeOptions = () => ({
|
|
78
|
+
chatSessionService: deps.chatSessionService,
|
|
79
|
+
chatSessionRepo: deps.chatSessionRepo,
|
|
80
|
+
channelManager: deps.channelManager,
|
|
81
|
+
titleGenerator: deps.titleGenerator,
|
|
82
|
+
userPrefRepo: deps.userPrefRepo,
|
|
83
|
+
artifactService: deps.artifactService,
|
|
84
|
+
});
|
|
50
85
|
const ensureBoundSessionActive = async (channelId, userId, cdp) => {
|
|
51
86
|
const savedTitle = deps.chatSessionRepo?.findByChannelId(channelId)?.displayName?.trim() || '';
|
|
52
87
|
if (!savedTitle || savedTitle === (0, i18n_1.t)('(Untitled)') || !deps.chatSessionService) {
|
|
@@ -114,6 +149,36 @@ function createInteractionCreateHandler(deps) {
|
|
|
114
149
|
return;
|
|
115
150
|
}
|
|
116
151
|
try {
|
|
152
|
+
const genericAction = (0, genericActionButtonAction_1.parseGenericActionCustomId)(interaction.customId);
|
|
153
|
+
if (genericAction) {
|
|
154
|
+
const { actionName: formattedName, projectName: parsedProject, channelId } = genericAction;
|
|
155
|
+
if (channelId && channelId !== interaction.channelId) {
|
|
156
|
+
await interaction.reply({
|
|
157
|
+
content: (0, i18n_1.t)('This action is linked to a different session channel.'),
|
|
158
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
159
|
+
}).catch(logger_1.logger.error);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const projectName = parsedProject ?? resolveProjectFromChannel(interaction);
|
|
163
|
+
const cdp = projectName
|
|
164
|
+
? deps.bridge.pool.getConnected(projectName, resolveSelectedAccount(channelId || interaction.channelId, interaction.user.id, getParentChannelId(interaction)))
|
|
165
|
+
: await deps.getCurrentCdp(deps.bridge);
|
|
166
|
+
if (!cdp) {
|
|
167
|
+
await interaction.reply({ content: 'Not connected to CDP.', flags: discord_js_1.MessageFlags.Ephemeral });
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
await interaction.deferUpdate();
|
|
171
|
+
const script = (0, approvalDetector_1.buildClickScript)(formattedName);
|
|
172
|
+
const evalResult = await cdp.call('Runtime.evaluate', {
|
|
173
|
+
expression: script,
|
|
174
|
+
returnByValue: true,
|
|
175
|
+
});
|
|
176
|
+
const resultValue = evalResult.result?.value;
|
|
177
|
+
if (!resultValue?.ok) {
|
|
178
|
+
await interaction.followUp({ content: `Failed to execute action: Button "${formattedName}" not found or obscured.`, flags: discord_js_1.MessageFlags.Ephemeral });
|
|
179
|
+
}
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
117
182
|
const approvalAction = deps.parseApprovalCustomId(interaction.customId);
|
|
118
183
|
if (approvalAction) {
|
|
119
184
|
if (approvalAction.channelId && approvalAction.channelId !== interaction.channelId) {
|
|
@@ -123,7 +188,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
123
188
|
}).catch(logger_1.logger.error);
|
|
124
189
|
return;
|
|
125
190
|
}
|
|
126
|
-
const projectName = approvalAction.projectName ??
|
|
191
|
+
const projectName = approvalAction.projectName ?? resolveProjectFromChannel(interaction);
|
|
127
192
|
const detector = projectName
|
|
128
193
|
? deps.bridge.pool.getApprovalDetector(projectName, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction)))
|
|
129
194
|
: undefined;
|
|
@@ -163,6 +228,19 @@ function createInteractionCreateHandler(deps) {
|
|
|
163
228
|
embeds: [updatedEmbed],
|
|
164
229
|
components: (0, discordButtonUtils_1.disableAllButtons)(interaction.message.components),
|
|
165
230
|
});
|
|
231
|
+
if (success && (approvalAction.action === 'approve' || approvalAction.action === 'always_allow') && deps.promptDispatcher && interaction.channelId && interaction.message) {
|
|
232
|
+
const cdp = projectName
|
|
233
|
+
? deps.bridge.pool.getConnected(projectName, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction)))
|
|
234
|
+
: null;
|
|
235
|
+
if (cdp) {
|
|
236
|
+
deps.promptDispatcher.resume({
|
|
237
|
+
message: interaction.message,
|
|
238
|
+
prompt: '',
|
|
239
|
+
cdp,
|
|
240
|
+
options: buildResumeOptions()
|
|
241
|
+
}).catch(e => logger_1.logger.error('[Approval] Failed to resume monitoring:', e));
|
|
242
|
+
}
|
|
243
|
+
}
|
|
166
244
|
}
|
|
167
245
|
else {
|
|
168
246
|
await interaction.reply({ content: 'Approval button not found.', flags: discord_js_1.MessageFlags.Ephemeral });
|
|
@@ -193,7 +271,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
193
271
|
}).catch(logger_1.logger.error);
|
|
194
272
|
return;
|
|
195
273
|
}
|
|
196
|
-
const planWorkspaceDirName = planningAction.projectName ??
|
|
274
|
+
const planWorkspaceDirName = planningAction.projectName ?? resolveProjectFromChannel(interaction);
|
|
197
275
|
const planDetector = planWorkspaceDirName
|
|
198
276
|
? deps.bridge.pool.getPlanningDetector(planWorkspaceDirName, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction)))
|
|
199
277
|
: undefined;
|
|
@@ -257,6 +335,39 @@ function createInteractionCreateHandler(deps) {
|
|
|
257
335
|
}).catch(logger_1.logger.error);
|
|
258
336
|
}
|
|
259
337
|
}
|
|
338
|
+
else if (planningAction.action === 'reject') {
|
|
339
|
+
const clicked = await planDetector.clickRejectButton();
|
|
340
|
+
const originalEmbed = interaction.message.embeds[0];
|
|
341
|
+
const updatedEmbed = originalEmbed
|
|
342
|
+
? discord_js_1.EmbedBuilder.from(originalEmbed)
|
|
343
|
+
: new discord_js_1.EmbedBuilder().setTitle('Planning Mode');
|
|
344
|
+
const historyText = `Reject by <@${interaction.user.id}> (${new Date().toLocaleString('ja-JP')})`;
|
|
345
|
+
updatedEmbed
|
|
346
|
+
.setColor(clicked ? 0xE74C3C : 0x95A5A6)
|
|
347
|
+
.addFields({ name: 'Action History', value: historyText, inline: false })
|
|
348
|
+
.setTimestamp();
|
|
349
|
+
try {
|
|
350
|
+
await interaction.update({
|
|
351
|
+
embeds: [updatedEmbed],
|
|
352
|
+
components: (0, discordButtonUtils_1.disableAllButtons)(interaction.message.components),
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
catch (interactionError) {
|
|
356
|
+
if (interactionError?.code === 10062 || interactionError?.code === 40060) {
|
|
357
|
+
logger_1.logger.warn('[Planning] Interaction expired. Responding directly in the channel.');
|
|
358
|
+
if (interaction.channel && 'send' in interaction.channel) {
|
|
359
|
+
const fallbackMessage = clicked
|
|
360
|
+
? (0, i18n_1.t)('Reject completed.')
|
|
361
|
+
: (0, i18n_1.t)('Reject button not found.');
|
|
362
|
+
await interaction.channel.send(fallbackMessage).catch(logger_1.logger.error);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
throw interactionError;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
260
371
|
else {
|
|
261
372
|
// Proceed action
|
|
262
373
|
const clicked = await planDetector.clickProceedButton();
|
|
@@ -289,6 +400,18 @@ function createInteractionCreateHandler(deps) {
|
|
|
289
400
|
throw interactionError;
|
|
290
401
|
}
|
|
291
402
|
}
|
|
403
|
+
if (clicked && deps.promptDispatcher && interaction.channelId && interaction.message) {
|
|
404
|
+
const cdp = getChannelCdp(interaction);
|
|
405
|
+
if (cdp) {
|
|
406
|
+
// Use 'as any' to bypass the type difference between Interaction's Message and Discord.js Message if needed
|
|
407
|
+
deps.promptDispatcher.resume({
|
|
408
|
+
message: interaction.message,
|
|
409
|
+
prompt: '',
|
|
410
|
+
cdp,
|
|
411
|
+
options: buildResumeOptions()
|
|
412
|
+
}).catch(e => logger_1.logger.error('[Planning] Failed to resume monitoring:', e));
|
|
413
|
+
}
|
|
414
|
+
}
|
|
292
415
|
}
|
|
293
416
|
}
|
|
294
417
|
catch (planError) {
|
|
@@ -310,6 +433,81 @@ function createInteractionCreateHandler(deps) {
|
|
|
310
433
|
}
|
|
311
434
|
return;
|
|
312
435
|
}
|
|
436
|
+
// File Change handling
|
|
437
|
+
const fileChangeAction = deps.parseFileChangeCustomId(interaction.customId);
|
|
438
|
+
if (fileChangeAction) {
|
|
439
|
+
if (fileChangeAction.channelId && fileChangeAction.channelId !== interaction.channelId) {
|
|
440
|
+
await interaction.reply({
|
|
441
|
+
content: (0, i18n_1.t)('This file change action is linked to a different session channel.'),
|
|
442
|
+
flags: discord_js_1.MessageFlags.Ephemeral,
|
|
443
|
+
}).catch(logger_1.logger.error);
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
const projectName = fileChangeAction.projectName ?? resolveProjectFromChannel(interaction);
|
|
447
|
+
const cdp = projectName ? deps.bridge.pool.getConnected(projectName, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction))) : null;
|
|
448
|
+
if (!cdp) {
|
|
449
|
+
await interaction.reply({ content: (0, i18n_1.t)('Workspace CDP connection not found.'), flags: discord_js_1.MessageFlags.Ephemeral }).catch(logger_1.logger.error);
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
let clicked = false;
|
|
453
|
+
try {
|
|
454
|
+
await interaction.deferUpdate();
|
|
455
|
+
const actionLabelEval = fileChangeAction.action === 'accept' ? 'Accept all' : 'Reject all';
|
|
456
|
+
const script = (0, approvalDetector_1.buildClickScript)(actionLabelEval);
|
|
457
|
+
const contextId = cdp.getPrimaryContextId();
|
|
458
|
+
const callParams = {
|
|
459
|
+
expression: script,
|
|
460
|
+
returnByValue: true,
|
|
461
|
+
};
|
|
462
|
+
if (contextId !== null)
|
|
463
|
+
callParams.contextId = contextId;
|
|
464
|
+
const res = await cdp.call('Runtime.evaluate', callParams);
|
|
465
|
+
clicked = res?.result?.value?.ok === true;
|
|
466
|
+
const originalEmbed = interaction.message.embeds[0];
|
|
467
|
+
const updatedEmbed = originalEmbed
|
|
468
|
+
? discord_js_1.EmbedBuilder.from(originalEmbed)
|
|
469
|
+
: new discord_js_1.EmbedBuilder().setTitle('File Changes');
|
|
470
|
+
const actionLabel = fileChangeAction.action === 'accept' ? 'Accept All' : 'Reject All';
|
|
471
|
+
const historyText = `${actionLabel} by <@${interaction.user.id}> (${new Date().toLocaleString('ja-JP')})`;
|
|
472
|
+
updatedEmbed
|
|
473
|
+
.setColor(clicked ? (fileChangeAction.action === 'accept' ? 0x2ECC71 : 0xE74C3C) : 0x95A5A6)
|
|
474
|
+
.addFields({ name: 'Action History', value: historyText, inline: false })
|
|
475
|
+
.setTimestamp();
|
|
476
|
+
await interaction.editReply({
|
|
477
|
+
embeds: [updatedEmbed],
|
|
478
|
+
components: (0, discordButtonUtils_1.disableAllButtons)(interaction.message.components),
|
|
479
|
+
});
|
|
480
|
+
if (clicked && deps.promptDispatcher && interaction.channelId && interaction.message) {
|
|
481
|
+
// Resume monitoring, treating the completion of file changes as a need to poll again
|
|
482
|
+
deps.promptDispatcher.resume({
|
|
483
|
+
message: interaction.message,
|
|
484
|
+
prompt: '',
|
|
485
|
+
cdp,
|
|
486
|
+
options: buildResumeOptions()
|
|
487
|
+
}).catch(e => logger_1.logger.error('[FileChange] Failed to resume monitoring:', e));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch (err) {
|
|
491
|
+
if (err?.code === 10062 || err?.code === 40060) {
|
|
492
|
+
logger_1.logger.warn('[FileChange] Interaction expired. Responding directly in the channel.');
|
|
493
|
+
if (interaction.channel && 'send' in interaction.channel) {
|
|
494
|
+
const actionLabel = fileChangeAction.action === 'accept' ? 'Accept All' : 'Reject All';
|
|
495
|
+
const fallbackMessage = clicked
|
|
496
|
+
? `${actionLabel} completed.`
|
|
497
|
+
: (0, i18n_1.t)('File change button not found or error occurred.');
|
|
498
|
+
await interaction.channel.send(fallbackMessage).catch(logger_1.logger.error);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
else {
|
|
502
|
+
logger_1.logger.error('[FileChange] action error:', err);
|
|
503
|
+
await interaction.followUp({
|
|
504
|
+
content: `❌ Error executing file change action: ${err.message || 'Unknown error'}`,
|
|
505
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
506
|
+
}).catch(() => { });
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
313
511
|
const errorPopupAction = deps.parseErrorPopupCustomId(interaction.customId);
|
|
314
512
|
if (errorPopupAction) {
|
|
315
513
|
if (errorPopupAction.channelId && errorPopupAction.channelId !== interaction.channelId) {
|
|
@@ -319,7 +517,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
319
517
|
}).catch(logger_1.logger.error);
|
|
320
518
|
return;
|
|
321
519
|
}
|
|
322
|
-
const errorWorkspaceDirName = errorPopupAction.projectName ??
|
|
520
|
+
const errorWorkspaceDirName = errorPopupAction.projectName ?? resolveProjectFromChannel(interaction);
|
|
323
521
|
const errorDetector = errorWorkspaceDirName
|
|
324
522
|
? deps.bridge.pool.getErrorPopupDetector(errorWorkspaceDirName, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction)))
|
|
325
523
|
: undefined;
|
|
@@ -469,7 +667,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
469
667
|
}).catch(logger_1.logger.error);
|
|
470
668
|
return;
|
|
471
669
|
}
|
|
472
|
-
const runCmdWorkspace = runCommandAction.projectName ??
|
|
670
|
+
const runCmdWorkspace = runCommandAction.projectName ?? resolveProjectFromChannel(interaction);
|
|
473
671
|
const runCmdDetector = runCmdWorkspace
|
|
474
672
|
? deps.bridge.pool.getRunCommandDetector(runCmdWorkspace, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction)))
|
|
475
673
|
: undefined;
|
|
@@ -540,7 +738,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
540
738
|
}
|
|
541
739
|
if (interaction.customId === 'model_set_default_btn') {
|
|
542
740
|
await interaction.deferUpdate();
|
|
543
|
-
const cdp = getChannelCdp(interaction
|
|
741
|
+
const cdp = getChannelCdp(interaction);
|
|
544
742
|
if (!cdp) {
|
|
545
743
|
await interaction.followUp({ content: 'Not connected to CDP.', flags: discord_js_1.MessageFlags.Ephemeral });
|
|
546
744
|
return;
|
|
@@ -560,7 +758,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
560
758
|
deps.userPrefRepo.setDefaultModel(interaction.user.id, currentModel);
|
|
561
759
|
}
|
|
562
760
|
await deps.sendModelsUI({ editReply: async (data) => await interaction.editReply(data) }, {
|
|
563
|
-
getCurrentCdp: () => getChannelCdp(interaction
|
|
761
|
+
getCurrentCdp: () => getChannelCdp(interaction),
|
|
564
762
|
fetchQuota: async () => deps.bridge.quota.fetchQuota(),
|
|
565
763
|
});
|
|
566
764
|
await interaction.followUp({ content: `Default model set to **${currentModel}**.`, flags: discord_js_1.MessageFlags.Ephemeral });
|
|
@@ -568,7 +766,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
568
766
|
}
|
|
569
767
|
if (interaction.customId === 'model_clear_default_btn') {
|
|
570
768
|
await interaction.deferUpdate();
|
|
571
|
-
const cdp = getChannelCdp(interaction
|
|
769
|
+
const cdp = getChannelCdp(interaction);
|
|
572
770
|
if (cdp) {
|
|
573
771
|
const sessionReady = await ensureBoundSessionActive(interaction.channelId, interaction.user.id, cdp);
|
|
574
772
|
if (!sessionReady.ok) {
|
|
@@ -581,7 +779,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
581
779
|
deps.userPrefRepo.setDefaultModel(interaction.user.id, null);
|
|
582
780
|
}
|
|
583
781
|
await deps.sendModelsUI({ editReply: async (data) => await interaction.editReply(data) }, {
|
|
584
|
-
getCurrentCdp: () => getChannelCdp(interaction
|
|
782
|
+
getCurrentCdp: () => getChannelCdp(interaction),
|
|
585
783
|
fetchQuota: async () => deps.bridge.quota.fetchQuota(),
|
|
586
784
|
});
|
|
587
785
|
await interaction.followUp({ content: 'Default model cleared.', flags: discord_js_1.MessageFlags.Ephemeral });
|
|
@@ -589,7 +787,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
589
787
|
}
|
|
590
788
|
if (interaction.customId === 'model_refresh_btn') {
|
|
591
789
|
await interaction.deferUpdate();
|
|
592
|
-
const cdp = getChannelCdp(interaction
|
|
790
|
+
const cdp = getChannelCdp(interaction);
|
|
593
791
|
if (cdp) {
|
|
594
792
|
const sessionReady = await ensureBoundSessionActive(interaction.channelId, interaction.user.id, cdp);
|
|
595
793
|
if (!sessionReady.ok) {
|
|
@@ -598,7 +796,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
598
796
|
}
|
|
599
797
|
}
|
|
600
798
|
await deps.sendModelsUI({ editReply: async (data) => await interaction.editReply(data) }, {
|
|
601
|
-
getCurrentCdp: () => getChannelCdp(interaction
|
|
799
|
+
getCurrentCdp: () => getChannelCdp(interaction),
|
|
602
800
|
fetchQuota: async () => deps.bridge.quota.fetchQuota(),
|
|
603
801
|
});
|
|
604
802
|
return;
|
|
@@ -606,7 +804,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
606
804
|
if (interaction.customId.startsWith('model_btn_')) {
|
|
607
805
|
await interaction.deferUpdate();
|
|
608
806
|
const modelName = interaction.customId.replace('model_btn_', '');
|
|
609
|
-
const cdp = getChannelCdp(interaction
|
|
807
|
+
const cdp = getChannelCdp(interaction);
|
|
610
808
|
if (!cdp) {
|
|
611
809
|
await interaction.followUp({ content: 'Not connected to CDP.', flags: discord_js_1.MessageFlags.Ephemeral });
|
|
612
810
|
return;
|
|
@@ -622,7 +820,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
622
820
|
}
|
|
623
821
|
else {
|
|
624
822
|
await deps.sendModelsUI({ editReply: async (data) => await interaction.editReply(data) }, {
|
|
625
|
-
getCurrentCdp: () => getChannelCdp(interaction
|
|
823
|
+
getCurrentCdp: () => getChannelCdp(interaction),
|
|
626
824
|
fetchQuota: async () => deps.bridge.quota.fetchQuota(),
|
|
627
825
|
});
|
|
628
826
|
await interaction.followUp({ content: `Model changed to **${res.model}**!`, flags: discord_js_1.MessageFlags.Ephemeral });
|
|
@@ -688,9 +886,173 @@ function createInteractionCreateHandler(deps) {
|
|
|
688
886
|
}, true, passedConvId);
|
|
689
887
|
return;
|
|
690
888
|
}
|
|
889
|
+
if (interaction.customId.startsWith('file_open:')) {
|
|
890
|
+
await interaction.deferUpdate().catch(() => { });
|
|
891
|
+
let fileUrl = undefined;
|
|
892
|
+
const suffix = interaction.customId.substring('file_open:'.length);
|
|
893
|
+
if (suffix.startsWith('rel:')) {
|
|
894
|
+
const relativePath = suffix.substring('rel:'.length);
|
|
895
|
+
const workspacePath = interaction.channelId ? (deps.wsHandler.getWorkspaceForChannel(interaction.channelId) ||
|
|
896
|
+
deps.chatSessionRepo?.findByChannelId(interaction.channelId)?.workspacePath) : undefined;
|
|
897
|
+
if (workspacePath) {
|
|
898
|
+
fileUrl = `file:///${path_1.default.join(workspacePath, relativePath).replace(/\\/g, '/')}`;
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
else if (suffix.startsWith('art:')) {
|
|
902
|
+
const parts = suffix.substring('art:'.length).split(':');
|
|
903
|
+
if (parts.length >= 2) {
|
|
904
|
+
const convId = parts[0];
|
|
905
|
+
const filename = parts.slice(1).join(':');
|
|
906
|
+
if (deps.artifactService) {
|
|
907
|
+
const artifacts = deps.artifactService.listArtifacts(convId);
|
|
908
|
+
const matched = artifacts.find(art => art.filename.toLowerCase() === filename.toLowerCase());
|
|
909
|
+
if (matched) {
|
|
910
|
+
fileUrl = `file:///${matched.absolutePath.replace(/\\/g, '/')}`;
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
if (!fileUrl) {
|
|
914
|
+
const brainDir = path_1.default.join(require('os').homedir(), '.gemini', 'antigravity', 'brain');
|
|
915
|
+
fileUrl = `file:///${path_1.default.join(brainDir, convId, filename).replace(/\\/g, '/')}`;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
else {
|
|
920
|
+
// Fallback to cache (for legacy file_open:<hashId> or explicit cache usage)
|
|
921
|
+
const hashId = suffix.startsWith('cache:') ? suffix.substring('cache:'.length) : suffix;
|
|
922
|
+
fileUrl = fileOpenCache_1.fileOpenCache.get(hashId);
|
|
923
|
+
}
|
|
924
|
+
if (!fileUrl) {
|
|
925
|
+
await interaction.followUp({
|
|
926
|
+
content: (0, i18n_1.t)('File URL not found in cache or expired.'),
|
|
927
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
928
|
+
}).catch(logger_1.logger.error);
|
|
929
|
+
return;
|
|
930
|
+
}
|
|
931
|
+
let resolvedPath = fileUrl;
|
|
932
|
+
if (fileUrl.startsWith('file:///')) {
|
|
933
|
+
let rawPath = fileUrl.replace(/^file:\/\/\//, '');
|
|
934
|
+
if (path_1.default.sep === '/' && !rawPath.startsWith('/')) {
|
|
935
|
+
rawPath = '/' + rawPath;
|
|
936
|
+
}
|
|
937
|
+
else if (process.platform === 'win32' && rawPath.startsWith('/')) {
|
|
938
|
+
rawPath = rawPath.substring(1);
|
|
939
|
+
}
|
|
940
|
+
resolvedPath = path_1.default.resolve(rawPath);
|
|
941
|
+
}
|
|
942
|
+
const isArtifact = resolvedPath.includes('.gemini') && resolvedPath.includes('antigravity') && resolvedPath.includes('brain');
|
|
943
|
+
if (!isArtifact) {
|
|
944
|
+
let workspacePath = undefined;
|
|
945
|
+
if (interaction.channelId) {
|
|
946
|
+
workspacePath = deps.wsHandler.getWorkspaceForChannel(interaction.channelId) ||
|
|
947
|
+
deps.chatSessionRepo?.findByChannelId(interaction.channelId)?.workspacePath;
|
|
948
|
+
}
|
|
949
|
+
if (!workspacePath) {
|
|
950
|
+
await interaction.followUp({
|
|
951
|
+
content: `❌ Error: Cannot open files without an active workspace.`,
|
|
952
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
953
|
+
}).catch(logger_1.logger.error);
|
|
954
|
+
return;
|
|
955
|
+
}
|
|
956
|
+
const resolvedWorkspacePath = path_1.default.resolve(workspacePath);
|
|
957
|
+
const relative = path_1.default.relative(resolvedWorkspacePath, resolvedPath);
|
|
958
|
+
if (relative.startsWith('..') || path_1.default.isAbsolute(relative)) {
|
|
959
|
+
await interaction.followUp({
|
|
960
|
+
content: `❌ Error: Cannot open files outside the workspace root.`,
|
|
961
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
962
|
+
}).catch(logger_1.logger.error);
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
try {
|
|
967
|
+
const comp = interaction.component;
|
|
968
|
+
const buttonLabel = comp?.type === 2 ? comp.label : null;
|
|
969
|
+
const isReviewBtn = suffix.startsWith('art:') ||
|
|
970
|
+
buttonLabel?.toLowerCase().includes('review') ||
|
|
971
|
+
resolvedPath.endsWith('walkthrough.md') ||
|
|
972
|
+
resolvedPath.endsWith('task.md') ||
|
|
973
|
+
resolvedPath.endsWith('implementation_plan.md');
|
|
974
|
+
const fileContent = fs_1.default.readFileSync(resolvedPath, 'utf8');
|
|
975
|
+
const MAX_DESC_LEN = 4096;
|
|
976
|
+
let truncated = fileContent.length > MAX_DESC_LEN
|
|
977
|
+
? fileContent.substring(0, MAX_DESC_LEN - 15) + '\n\n(truncated)'
|
|
978
|
+
: fileContent;
|
|
979
|
+
if (isReviewBtn) {
|
|
980
|
+
truncated += '\n\n💡 *To request changes to this artifact, simply reply in this channel.*';
|
|
981
|
+
}
|
|
982
|
+
const embed = new discord_js_1.EmbedBuilder()
|
|
983
|
+
.setTitle(isReviewBtn ? `Reviewing: ${path_1.default.basename(resolvedPath)}` : `Opened: ${path_1.default.basename(resolvedPath)}`)
|
|
984
|
+
.setDescription(truncated)
|
|
985
|
+
.setColor(isReviewBtn ? 0x2ECC71 : 0x3498DB)
|
|
986
|
+
.setTimestamp();
|
|
987
|
+
if (isReviewBtn) {
|
|
988
|
+
await interaction.followUp({
|
|
989
|
+
embeds: [embed],
|
|
990
|
+
components: []
|
|
991
|
+
}).catch(logger_1.logger.error);
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
(0, child_process_1.execFile)((0, pathUtils_1.getAntigravityCliPath)(), [resolvedPath], async (error) => {
|
|
995
|
+
if (error) {
|
|
996
|
+
logger_1.logger.error(`Failed to open file via CLI: ${error.message}`);
|
|
997
|
+
await interaction.followUp({
|
|
998
|
+
content: `❌ Error opening file via CLI: ${error.message}`,
|
|
999
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
1000
|
+
}).catch(() => { });
|
|
1001
|
+
}
|
|
1002
|
+
else {
|
|
1003
|
+
const closeRow = new discord_js_1.ActionRowBuilder().addComponents(new discord_js_1.ButtonBuilder()
|
|
1004
|
+
.setCustomId('file_close_active')
|
|
1005
|
+
.setLabel('Close Active Tab in IDE')
|
|
1006
|
+
.setStyle(discord_js_1.ButtonStyle.Secondary));
|
|
1007
|
+
await interaction.followUp({
|
|
1008
|
+
content: `✅ Opened file in IDE: **${path_1.default.basename(resolvedPath)}**`,
|
|
1009
|
+
embeds: [embed],
|
|
1010
|
+
components: [closeRow],
|
|
1011
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
1012
|
+
}).catch(() => { });
|
|
1013
|
+
}
|
|
1014
|
+
});
|
|
1015
|
+
}
|
|
1016
|
+
catch (e) {
|
|
1017
|
+
await interaction.followUp({
|
|
1018
|
+
content: `❌ Error opening file: ${e.message}`,
|
|
1019
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
1020
|
+
}).catch(logger_1.logger.error);
|
|
1021
|
+
}
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
if (interaction.customId === 'file_close_active') {
|
|
1025
|
+
await interaction.deferUpdate().catch(() => { });
|
|
1026
|
+
try {
|
|
1027
|
+
const cdp = deps.getCurrentCdp(deps.bridge);
|
|
1028
|
+
if (!cdp) {
|
|
1029
|
+
await interaction.followUp({
|
|
1030
|
+
content: `❌ No active CDP connection found.`,
|
|
1031
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
1032
|
+
}).catch(() => { });
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
if (!cdp.isConnected()) {
|
|
1036
|
+
await cdp.connect();
|
|
1037
|
+
}
|
|
1038
|
+
await cdp.closeActiveEditor();
|
|
1039
|
+
await interaction.followUp({
|
|
1040
|
+
content: `✅ Sent close command to IDE.`,
|
|
1041
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
1042
|
+
}).catch(() => { });
|
|
1043
|
+
}
|
|
1044
|
+
catch (e) {
|
|
1045
|
+
logger_1.logger.error(`Failed to close active editor: ${e.message}`);
|
|
1046
|
+
await interaction.followUp({
|
|
1047
|
+
content: `❌ Error closing editor: ${e.message}`,
|
|
1048
|
+
flags: discord_js_1.MessageFlags.Ephemeral
|
|
1049
|
+
}).catch(() => { });
|
|
1050
|
+
}
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
691
1053
|
}
|
|
692
1054
|
catch (error) {
|
|
693
|
-
logger_1.logger.error(
|
|
1055
|
+
logger_1.logger.error(`[InteractionCreate] Error handling interaction: ${error instanceof Error ? error.message : String(error)}`);
|
|
694
1056
|
try {
|
|
695
1057
|
if (!interaction.replied && !interaction.deferred) {
|
|
696
1058
|
await interaction.reply({ content: 'An error occurred while processing the button action.', flags: discord_js_1.MessageFlags.Ephemeral });
|
|
@@ -723,7 +1085,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
723
1085
|
try {
|
|
724
1086
|
const selectedMode = interaction.values[0];
|
|
725
1087
|
deps.modeService.setMode(selectedMode);
|
|
726
|
-
const cdp = getChannelCdp(interaction
|
|
1088
|
+
const cdp = getChannelCdp(interaction);
|
|
727
1089
|
if (cdp) {
|
|
728
1090
|
const res = await cdp.setUiMode(selectedMode);
|
|
729
1091
|
if (!res.ok) {
|
|
@@ -739,6 +1101,9 @@ function createInteractionCreateHandler(deps) {
|
|
|
739
1101
|
if (interaction.deferred || interaction.replied) {
|
|
740
1102
|
await interaction.followUp({ content: 'An error occurred while changing the mode.', flags: discord_js_1.MessageFlags.Ephemeral }).catch(logger_1.logger.error);
|
|
741
1103
|
}
|
|
1104
|
+
else {
|
|
1105
|
+
await interaction.reply({ content: 'An error occurred while changing the mode.', flags: discord_js_1.MessageFlags.Ephemeral }).catch(logger_1.logger.error);
|
|
1106
|
+
}
|
|
742
1107
|
}
|
|
743
1108
|
catch (e) {
|
|
744
1109
|
logger_1.logger.error('Failed to send error message:', e);
|
|
@@ -866,10 +1231,10 @@ function createInteractionCreateHandler(deps) {
|
|
|
866
1231
|
const artifactService = new artifactService_1.ArtifactService();
|
|
867
1232
|
// Resolve the selected artifact by rescanning and matching the encoded value
|
|
868
1233
|
const channelId = interaction.channelId;
|
|
869
|
-
const
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1234
|
+
const session = deps.chatSessionRepo?.findByChannelId(channelId);
|
|
1235
|
+
const sessionTitle = session?.displayName?.trim() ?? '';
|
|
1236
|
+
const workspaceDirName = (0, pathUtils_1.getWorkspaceDirName)(session);
|
|
1237
|
+
const conversationId = session?.conversationId || (sessionTitle ? artifactService.findConversationByTitle(sessionTitle, workspaceDirName) : null);
|
|
873
1238
|
if (!conversationId) {
|
|
874
1239
|
await interaction.editReply({ content: '📂 No artifacts found.', components: [], allowedMentions: { parse: [] } }).catch(logger_1.logger.error);
|
|
875
1240
|
return;
|
|
@@ -975,6 +1340,70 @@ function createInteractionCreateHandler(deps) {
|
|
|
975
1340
|
}
|
|
976
1341
|
return;
|
|
977
1342
|
}
|
|
1343
|
+
if (interaction.isStringSelectMenu() && interaction.customId.startsWith(notificationSender_1.QUESTION_SELECT_ACTION_PREFIX)) {
|
|
1344
|
+
try {
|
|
1345
|
+
const action = (0, questionSelectAction_1.createQuestionSelectAction)({ bridge: deps.bridge, wsHandler: deps.wsHandler });
|
|
1346
|
+
const wrapped = (0, wrappers_1.wrapDiscordSelect)(interaction);
|
|
1347
|
+
const success = await action.execute(wrapped, interaction.values);
|
|
1348
|
+
if (success && deps.promptDispatcher && interaction.channelId && interaction.message) {
|
|
1349
|
+
const parsed = (0, questionActionUtils_1.parseQuestionCustomId)(interaction.customId, notificationSender_1.QUESTION_SELECT_ACTION_PREFIX);
|
|
1350
|
+
if (parsed) {
|
|
1351
|
+
const projectName = (0, projectResolver_1.resolveProjectName)({ bridge: deps.bridge, wsHandler: deps.wsHandler }, interaction.channelId, parsed.projectName);
|
|
1352
|
+
const cdp = projectName ? deps.bridge.pool.getConnected(projectName, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction))) : null;
|
|
1353
|
+
if (cdp) {
|
|
1354
|
+
deps.promptDispatcher.resume({
|
|
1355
|
+
message: interaction.message,
|
|
1356
|
+
prompt: '',
|
|
1357
|
+
cdp,
|
|
1358
|
+
options: buildResumeOptions()
|
|
1359
|
+
}).catch(e => logger_1.logger.error('[QuestionSelectAction] Failed to resume monitoring:', e));
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
catch (err) {
|
|
1365
|
+
logger_1.logger.error('[QuestionSelectAction] Error executing action:', err);
|
|
1366
|
+
if (!interaction.replied && !interaction.deferred) {
|
|
1367
|
+
await interaction.reply({ content: 'An error occurred.', ephemeral: true }).catch(logger_1.logger.error);
|
|
1368
|
+
}
|
|
1369
|
+
else {
|
|
1370
|
+
await interaction.followUp({ content: 'An error occurred.', ephemeral: true }).catch(logger_1.logger.error);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
return;
|
|
1374
|
+
}
|
|
1375
|
+
if (interaction.isButton() && interaction.customId.startsWith(notificationSender_1.QUESTION_SKIP_ACTION_PREFIX)) {
|
|
1376
|
+
try {
|
|
1377
|
+
const action = (0, questionSkipAction_1.createQuestionSkipAction)({ bridge: deps.bridge, wsHandler: deps.wsHandler });
|
|
1378
|
+
const wrapped = (0, wrappers_1.wrapDiscordButton)(interaction);
|
|
1379
|
+
const success = await action.execute(wrapped, {});
|
|
1380
|
+
if (success && deps.promptDispatcher && interaction.channelId && interaction.message) {
|
|
1381
|
+
const parsed = (0, questionActionUtils_1.parseQuestionCustomId)(interaction.customId, notificationSender_1.QUESTION_SKIP_ACTION_PREFIX);
|
|
1382
|
+
if (parsed) {
|
|
1383
|
+
const projectName = (0, projectResolver_1.resolveProjectName)({ bridge: deps.bridge, wsHandler: deps.wsHandler }, interaction.channelId, parsed.projectName);
|
|
1384
|
+
const cdp = projectName ? deps.bridge.pool.getConnected(projectName, resolveSelectedAccount(interaction.channelId, interaction.user.id, getParentChannelId(interaction))) : null;
|
|
1385
|
+
if (cdp) {
|
|
1386
|
+
deps.promptDispatcher.resume({
|
|
1387
|
+
message: interaction.message,
|
|
1388
|
+
prompt: '',
|
|
1389
|
+
cdp,
|
|
1390
|
+
options: buildResumeOptions()
|
|
1391
|
+
}).catch(e => logger_1.logger.error('[QuestionSkipAction] Failed to resume monitoring:', e));
|
|
1392
|
+
}
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
catch (err) {
|
|
1397
|
+
logger_1.logger.error('[QuestionSkipAction] Error executing action:', err);
|
|
1398
|
+
if (!interaction.replied && !interaction.deferred) {
|
|
1399
|
+
await interaction.reply({ content: 'An error occurred.', ephemeral: true }).catch(logger_1.logger.error);
|
|
1400
|
+
}
|
|
1401
|
+
else {
|
|
1402
|
+
await interaction.followUp({ content: 'An error occurred.', ephemeral: true }).catch(logger_1.logger.error);
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
return;
|
|
1406
|
+
}
|
|
978
1407
|
if (interaction.isStringSelectMenu() && (0, projectListUi_1.isProjectSelectId)(interaction.customId)) {
|
|
979
1408
|
if (!deps.config.allowedUserIds.includes(interaction.user.id)) {
|
|
980
1409
|
await interaction.reply({ content: (0, i18n_1.t)('You do not have permission.'), flags: discord_js_1.MessageFlags.Ephemeral }).catch(logger_1.logger.error);
|
|
@@ -1019,7 +1448,7 @@ function createInteractionCreateHandler(deps) {
|
|
|
1019
1448
|
throw deferError;
|
|
1020
1449
|
}
|
|
1021
1450
|
try {
|
|
1022
|
-
await deps.handleSlashInteraction(commandInteraction, deps.slashCommandHandler, deps.bridge, deps.wsHandler, deps.chatHandler, deps.cleanupHandler, deps.modeService, deps.modelService, deps.bridge.autoAccept, deps.client, deps.accountPrefRepo, deps.channelPrefRepo, deps.antigravityAccounts, deps.chatSessionRepo);
|
|
1451
|
+
await deps.handleSlashInteraction(commandInteraction, deps.slashCommandHandler, deps.bridge, deps.wsHandler, deps.chatHandler, deps.cleanupHandler, deps.modeService, deps.modelService, deps.bridge.autoAccept, deps.client, deps.accountPrefRepo, deps.channelPrefRepo, deps.antigravityAccounts, deps.chatSessionRepo, deps.scheduleService);
|
|
1023
1452
|
}
|
|
1024
1453
|
catch (error) {
|
|
1025
1454
|
logger_1.logger.error(`[SlashCommand] command=${commandInteraction.commandName} channel=${commandInteraction.channelId} ` +
|