lazy-gravity 0.10.0 → 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 +191 -22
- package/dist/commands/chatCommandHandler.js +11 -41
- package/dist/events/interactionCreateHandler.js +158 -27
- package/dist/events/messageCreateHandler.js +14 -4
- package/dist/handlers/fileChangeButtonAction.js +12 -24
- package/dist/handlers/genericActionButtonAction.js +16 -18
- package/dist/handlers/planningButtonAction.js +105 -17
- package/dist/handlers/planningModalSubmitAction.js +38 -0
- package/dist/handlers/questionSelectAction.js +8 -7
- package/dist/handlers/questionSkipAction.js +7 -6
- package/dist/platform/discord/wrappers.js +76 -0
- package/dist/services/approvalDetector.js +43 -14
- package/dist/services/artifactService.js +61 -21
- package/dist/services/assistantDomExtractor.js +23 -3
- package/dist/services/cdpBridgeManager.js +35 -2
- package/dist/services/cdpConnectionPool.js +7 -2
- package/dist/services/cdpService.js +113 -8
- package/dist/services/chatSessionService.js +15 -8
- package/dist/services/notificationSender.js +12 -2
- package/dist/services/planningDetector.js +1 -1
- package/dist/services/promptDispatcher.js +21 -1
- package/dist/services/questionDetector.js +128 -76
- package/dist/services/responseMonitor.js +17 -1
- package/dist/utils/fileOpenCache.js +2 -6
- package/dist/utils/questionActionUtils.js +22 -0
- package/package.json +1 -1
|
@@ -41,6 +41,7 @@ const cdpPorts_1 = require("../../utils/cdpPorts");
|
|
|
41
41
|
const configLoader_1 = require("../../utils/configLoader");
|
|
42
42
|
const pathUtils_1 = require("../../utils/pathUtils");
|
|
43
43
|
const logger_1 = require("../../utils/logger");
|
|
44
|
+
const artifactService_1 = require("../../services/artifactService");
|
|
44
45
|
const ok = (msg) => console.log(` ${logger_1.COLORS.green}[OK]${logger_1.COLORS.reset} ${msg}`);
|
|
45
46
|
const warn = (msg) => console.log(` ${logger_1.COLORS.yellow}[--]${logger_1.COLORS.reset} ${msg}`);
|
|
46
47
|
const fail = (msg) => console.log(` ${logger_1.COLORS.red}[!!]${logger_1.COLORS.reset} ${msg}`);
|
|
@@ -53,17 +54,22 @@ function checkPort(port) {
|
|
|
53
54
|
res.on('end', () => {
|
|
54
55
|
try {
|
|
55
56
|
const parsed = JSON.parse(data);
|
|
56
|
-
|
|
57
|
+
if (Array.isArray(parsed)) {
|
|
58
|
+
resolve({ alive: true, targets: parsed });
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
resolve({ alive: false });
|
|
62
|
+
}
|
|
57
63
|
}
|
|
58
64
|
catch {
|
|
59
|
-
resolve(false);
|
|
65
|
+
resolve({ alive: false });
|
|
60
66
|
}
|
|
61
67
|
});
|
|
62
68
|
});
|
|
63
|
-
req.on('error', () => resolve(false));
|
|
69
|
+
req.on('error', () => resolve({ alive: false }));
|
|
64
70
|
req.setTimeout(2000, () => {
|
|
65
71
|
req.destroy();
|
|
66
|
-
resolve(false);
|
|
72
|
+
resolve({ alive: false });
|
|
67
73
|
});
|
|
68
74
|
});
|
|
69
75
|
}
|
|
@@ -145,11 +151,15 @@ async function doctorAction() {
|
|
|
145
151
|
// 5. CDP port check
|
|
146
152
|
console.log(`\n ${logger_1.COLORS.dim}Checking CDP ports...${logger_1.COLORS.reset}`);
|
|
147
153
|
let cdpOk = false;
|
|
154
|
+
const portResults = new Map();
|
|
148
155
|
for (const port of cdpPorts_1.CDP_PORTS) {
|
|
149
|
-
const
|
|
150
|
-
if (alive) {
|
|
156
|
+
const result = await checkPort(port);
|
|
157
|
+
if (result.alive) {
|
|
151
158
|
ok(`CDP port ${port} is responding`);
|
|
152
159
|
cdpOk = true;
|
|
160
|
+
if (result.targets) {
|
|
161
|
+
portResults.set(port, result.targets);
|
|
162
|
+
}
|
|
153
163
|
}
|
|
154
164
|
}
|
|
155
165
|
if (!cdpOk) {
|
|
@@ -157,7 +167,35 @@ async function doctorAction() {
|
|
|
157
167
|
hint(`Run: ${(0, pathUtils_1.getAntigravityCdpHint)(9222)}`);
|
|
158
168
|
allOk = false;
|
|
159
169
|
}
|
|
160
|
-
// 6.
|
|
170
|
+
// 6. Path alignment check
|
|
171
|
+
console.log(`\n ${logger_1.COLORS.dim}Checking brain path alignment...${logger_1.COLORS.reset}`);
|
|
172
|
+
const artifactService = new artifactService_1.ArtifactService();
|
|
173
|
+
const resolvedPath = artifactService.getBrainBasePath();
|
|
174
|
+
ok(`Resolved brainBasePath: ${resolvedPath}`);
|
|
175
|
+
for (const port of cdpPorts_1.CDP_PORTS) {
|
|
176
|
+
const targets = portResults.get(port);
|
|
177
|
+
if (targets && Array.isArray(targets)) {
|
|
178
|
+
for (const t of targets) {
|
|
179
|
+
if (t.url?.includes('workbench')) {
|
|
180
|
+
const pathLower = t.url.toLowerCase();
|
|
181
|
+
const isIDE = pathLower.includes('antigravity%20ide') || pathLower.includes('antigravity-ide');
|
|
182
|
+
const resolvedLower = resolvedPath.toLowerCase();
|
|
183
|
+
if (isIDE && !resolvedLower.includes('antigravity-ide')) {
|
|
184
|
+
fail(`Path mismatch: Active IDE target is "Antigravity IDE" but brain basePath is resolved to: ${resolvedPath}`);
|
|
185
|
+
hint('Make sure to use .gemini/antigravity-ide/brain path.');
|
|
186
|
+
allOk = false;
|
|
187
|
+
}
|
|
188
|
+
else if (!isIDE && resolvedLower.includes('antigravity-ide')) {
|
|
189
|
+
warn(`Active IDE target does not appear to be "Antigravity IDE" but brain basePath is: ${resolvedPath}`);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
ok(`Target "${t.title}" aligns correctly with brain basePath`);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// 7. Node.js version check
|
|
161
199
|
const nodeVersion = process.versions.node;
|
|
162
200
|
const major = parseInt(nodeVersion.split('.')[0], 10);
|
|
163
201
|
if (major >= 18) {
|
package/dist/bot/index.js
CHANGED
|
@@ -191,11 +191,15 @@ function createSerialTaskQueueForTest(queueName, traceId) {
|
|
|
191
191
|
async function sendPromptToAntigravity(bridge, message, prompt, cdp, modeService, modelService, inboundImages = [], options) {
|
|
192
192
|
// Completion signal — called exactly once when the entire prompt lifecycle ends
|
|
193
193
|
let completionSignaled = false;
|
|
194
|
+
let onApprovalRef = null;
|
|
194
195
|
const signalCompletion = (exitPath) => {
|
|
195
196
|
if (completionSignaled)
|
|
196
197
|
return;
|
|
197
198
|
completionSignaled = true;
|
|
198
199
|
logger_1.logger.debug(`[sendPrompt:${message.channelId}] signalCompletion via ${exitPath}`);
|
|
200
|
+
if (onApprovalRef) {
|
|
201
|
+
cdp.off('approval_required', onApprovalRef);
|
|
202
|
+
}
|
|
199
203
|
options?.onFullCompletion?.();
|
|
200
204
|
};
|
|
201
205
|
// Resolve output format once at the start (no mid-response switches)
|
|
@@ -587,6 +591,8 @@ async function sendPromptToAntigravity(bridge, message, prompt, cdp, modeService
|
|
|
587
591
|
return;
|
|
588
592
|
}
|
|
589
593
|
const startTime = Date.now();
|
|
594
|
+
let earlyConvIdResolved = false;
|
|
595
|
+
let earlyConvIdInFlight = false;
|
|
590
596
|
await upsertLiveActivityEmbeds(`${PHASE_ICONS.thinking} Process Log`, '', PHASE_COLORS.thinking, (0, i18n_1.t)('⏱️ Elapsed: 0s | Process log'), { source: 'initial' });
|
|
591
597
|
const monitor = new responseMonitor_1.ResponseMonitor({
|
|
592
598
|
cdpService: cdp,
|
|
@@ -613,6 +619,30 @@ async function sendPromptToAntigravity(bridge, message, prompt, cdp, modeService
|
|
|
613
619
|
expectedVersion: activityVersion,
|
|
614
620
|
skipWhenFinalized: true,
|
|
615
621
|
}).catch(() => { });
|
|
622
|
+
// Try to resolve conversation_id early if not already bound
|
|
623
|
+
const { artifactService, chatSessionRepo, chatSessionService } = options || {};
|
|
624
|
+
if (!earlyConvIdResolved && !earlyConvIdInFlight && artifactService && chatSessionRepo && chatSessionService) {
|
|
625
|
+
earlyConvIdInFlight = true;
|
|
626
|
+
chatSessionService.getCurrentSessionInfo(cdp)
|
|
627
|
+
.then((sessionInfo) => {
|
|
628
|
+
if (sessionInfo && sessionInfo.title && sessionInfo.title !== (0, i18n_1.t)('(Untitled)')) {
|
|
629
|
+
const session = chatSessionRepo.findByChannelId(message.channelId);
|
|
630
|
+
const workspaceDirName = (session
|
|
631
|
+
? bridge.pool.extractProjectName(session.workspacePath)
|
|
632
|
+
: cdp.getCurrentWorkspaceName()) ?? undefined;
|
|
633
|
+
const convId = artifactService.findConversationByTitle(sessionInfo.title, workspaceDirName);
|
|
634
|
+
if (convId) {
|
|
635
|
+
chatSessionRepo.setConversationId(message.channelId, convId);
|
|
636
|
+
earlyConvIdResolved = true;
|
|
637
|
+
logger_1.logger.debug(`[EarlyBinding] Saved conversation_id: "${convId}" for channel: ${message.channelId}`);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
})
|
|
641
|
+
.catch(() => { })
|
|
642
|
+
.finally(() => {
|
|
643
|
+
earlyConvIdInFlight = false;
|
|
644
|
+
});
|
|
645
|
+
}
|
|
616
646
|
},
|
|
617
647
|
onProgress: (text) => {
|
|
618
648
|
if (isFinalized)
|
|
@@ -706,6 +736,12 @@ async function sendPromptToAntigravity(bridge, message, prompt, cdp, modeService
|
|
|
706
736
|
const components = [];
|
|
707
737
|
if (!citedFiles)
|
|
708
738
|
citedFiles = [];
|
|
739
|
+
// Only pause when newly created conversation folders and files need to flush to disk
|
|
740
|
+
const existingConvId = options?.chatSessionRepo?.findByChannelId(message.channelId)?.conversationId;
|
|
741
|
+
if (!existingConvId) {
|
|
742
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
743
|
+
}
|
|
744
|
+
let activeConversationId = undefined;
|
|
709
745
|
if (options && message.guild) {
|
|
710
746
|
try {
|
|
711
747
|
const sessionInfo = await options.chatSessionService.getCurrentSessionInfo(cdp);
|
|
@@ -733,6 +769,7 @@ async function sendPromptToAntigravity(bridge, message, prompt, cdp, modeService
|
|
|
733
769
|
const convId = options.artifactService.findConversationByTitle(sessionInfo.title, workspaceDirName);
|
|
734
770
|
if (convId) {
|
|
735
771
|
options.chatSessionRepo.setConversationId(message.channelId, convId);
|
|
772
|
+
activeConversationId = convId;
|
|
736
773
|
}
|
|
737
774
|
}
|
|
738
775
|
}
|
|
@@ -741,6 +778,51 @@ async function sendPromptToAntigravity(bridge, message, prompt, cdp, modeService
|
|
|
741
778
|
logger_1.logger.error('[Rename] Failed to get title from Antigravity and rename:', e);
|
|
742
779
|
}
|
|
743
780
|
}
|
|
781
|
+
const classifiedForFiles = monitor.getLastClassified();
|
|
782
|
+
if (classifiedForFiles?.fileChanges && classifiedForFiles.fileChanges.length > 0) {
|
|
783
|
+
for (const fc of classifiedForFiles.fileChanges) {
|
|
784
|
+
if (!citedFiles.includes(fc.path)) {
|
|
785
|
+
citedFiles.push(fc.path);
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
if (!activeConversationId && options?.chatSessionRepo) {
|
|
790
|
+
activeConversationId = options.chatSessionRepo.findByChannelId(message.channelId)?.conversationId ?? undefined;
|
|
791
|
+
}
|
|
792
|
+
if (activeConversationId && options?.artifactService) {
|
|
793
|
+
const artifacts = options.artifactService.listArtifacts(activeConversationId);
|
|
794
|
+
const planArt = artifacts.find(art => art.artifactType === 'ARTIFACT_TYPE_IMPLEMENTATION_PLAN' ||
|
|
795
|
+
art.filename.toLowerCase() === 'implementation_plan.md');
|
|
796
|
+
let planTime = 0;
|
|
797
|
+
if (planArt) {
|
|
798
|
+
try {
|
|
799
|
+
planTime = fs_1.default.statSync(planArt.absolutePath).mtimeMs;
|
|
800
|
+
}
|
|
801
|
+
catch { /* ignore */ }
|
|
802
|
+
}
|
|
803
|
+
for (const art of artifacts) {
|
|
804
|
+
const nameWithExt = art.filename;
|
|
805
|
+
const nameWithoutExt = art.filename.replace(/\.[^/.]+$/, "");
|
|
806
|
+
const regex = new RegExp(`\\b${nameWithoutExt.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}\\b`, 'i');
|
|
807
|
+
const mentionsArtifact = finalOutputText.includes(nameWithExt) || finalOutputText.includes(`\`${nameWithoutExt}\``) || regex.test(finalOutputText);
|
|
808
|
+
const isTask = art.artifactType === 'ARTIFACT_TYPE_TASK' || nameWithExt.toLowerCase() === 'task.md';
|
|
809
|
+
const isWalkthrough = art.artifactType === 'ARTIFACT_TYPE_WALKTHROUGH' || nameWithExt.toLowerCase() === 'walkthrough.md';
|
|
810
|
+
let isSpecialArtifact = false;
|
|
811
|
+
if (isTask || isWalkthrough) {
|
|
812
|
+
let artTime = 0;
|
|
813
|
+
try {
|
|
814
|
+
artTime = fs_1.default.statSync(art.absolutePath).mtimeMs;
|
|
815
|
+
}
|
|
816
|
+
catch { /* ignore */ }
|
|
817
|
+
if (artTime > planTime) {
|
|
818
|
+
isSpecialArtifact = true;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
if ((mentionsArtifact || isSpecialArtifact) && !citedFiles.includes(nameWithExt)) {
|
|
822
|
+
citedFiles.push(nameWithExt);
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
}
|
|
744
826
|
if (citedFiles && citedFiles.length > 0) {
|
|
745
827
|
// Strip trailing punctuation and deduplicate
|
|
746
828
|
let uniqueFiles = Array.from(new Set(citedFiles.map(f => {
|
|
@@ -756,38 +838,82 @@ async function sendPromptToAntigravity(bridge, message, prompt, cdp, modeService
|
|
|
756
838
|
// Max 5 buttons per row in Discord
|
|
757
839
|
for (let i = 0; i < Math.min(uniqueFiles.length, 5); i++) {
|
|
758
840
|
let fileUrl = uniqueFiles[i];
|
|
841
|
+
let isArtifactMatch = false;
|
|
842
|
+
let artifactDisplayName = fileUrl;
|
|
843
|
+
if (activeConversationId && options?.artifactService) {
|
|
844
|
+
const artifacts = options.artifactService.listArtifacts(activeConversationId);
|
|
845
|
+
const rawName = fileUrl.replace(/^file:\/\/\//, '');
|
|
846
|
+
const matched = artifacts.find(a => a.filename.toLowerCase() === fileUrl.toLowerCase() ||
|
|
847
|
+
a.filename.toLowerCase() === rawName.toLowerCase());
|
|
848
|
+
if (matched) {
|
|
849
|
+
isArtifactMatch = true;
|
|
850
|
+
fileUrl = `file:///${matched.absolutePath.replace(/\\/g, '/')}`;
|
|
851
|
+
artifactDisplayName = matched.filename;
|
|
852
|
+
}
|
|
853
|
+
}
|
|
759
854
|
const wsPath = cdp.getCurrentWorkspacePath();
|
|
760
855
|
if (!wsPath) {
|
|
761
856
|
continue;
|
|
762
857
|
}
|
|
763
|
-
if (!
|
|
764
|
-
fileUrl
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
858
|
+
if (!isArtifactMatch) {
|
|
859
|
+
if (!fileUrl.startsWith('file:///') && !path_1.default.isAbsolute(fileUrl)) {
|
|
860
|
+
fileUrl = `file:///${path_1.default.resolve(wsPath, fileUrl).replace(/\\/g, '/')}`;
|
|
861
|
+
}
|
|
862
|
+
let fsPath = fileUrl.replace(/^file:\/\/\//, '');
|
|
863
|
+
if (path_1.default.sep === '/' && !fsPath.startsWith('/')) {
|
|
864
|
+
fsPath = '/' + fsPath;
|
|
865
|
+
}
|
|
866
|
+
else if (process.platform === 'win32' && fsPath.startsWith('/')) {
|
|
867
|
+
fsPath = fsPath.substring(1);
|
|
868
|
+
}
|
|
869
|
+
const relative = path_1.default.relative(wsPath, fsPath);
|
|
870
|
+
const isArtifact = fsPath.includes('.gemini') && fsPath.includes('antigravity') && fsPath.includes('brain');
|
|
871
|
+
if (!isArtifact && (relative.startsWith('..') || path_1.default.isAbsolute(relative))) {
|
|
872
|
+
continue;
|
|
873
|
+
}
|
|
874
|
+
if (!fs_1.default.existsSync(fsPath)) {
|
|
875
|
+
continue;
|
|
876
|
+
}
|
|
779
877
|
}
|
|
780
878
|
let displayName = fileUrl;
|
|
781
|
-
if (
|
|
879
|
+
if (isArtifactMatch) {
|
|
880
|
+
displayName = artifactDisplayName;
|
|
881
|
+
}
|
|
882
|
+
else if (displayName.startsWith('file:///')) {
|
|
782
883
|
const parts = displayName.split('/');
|
|
783
884
|
displayName = parts[parts.length - 1];
|
|
784
885
|
}
|
|
785
886
|
const hashId = Math.random().toString(36).substring(2, 10);
|
|
786
887
|
fileOpenCache_1.fileOpenCache.set(hashId, fileUrl);
|
|
888
|
+
let customId = `file_open:cache:${hashId}`;
|
|
889
|
+
if (isArtifactMatch && activeConversationId && displayName) {
|
|
890
|
+
const artId = `file_open:art:${activeConversationId}:${displayName}`;
|
|
891
|
+
if (artId.length < 100) {
|
|
892
|
+
customId = artId;
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
else if (wsPath) {
|
|
896
|
+
let fsPath = fileUrl.replace(/^file:\/\/\//, '');
|
|
897
|
+
if (path_1.default.sep === '/' && !fsPath.startsWith('/')) {
|
|
898
|
+
fsPath = '/' + fsPath;
|
|
899
|
+
}
|
|
900
|
+
else if (process.platform === 'win32' && fsPath.startsWith('/')) {
|
|
901
|
+
fsPath = fsPath.substring(1);
|
|
902
|
+
}
|
|
903
|
+
const resolvedFsPath = path_1.default.resolve(fsPath);
|
|
904
|
+
const relative = path_1.default.relative(wsPath, resolvedFsPath);
|
|
905
|
+
if (!relative.startsWith('..') && !path_1.default.isAbsolute(relative)) {
|
|
906
|
+
const relSlash = relative.replace(/\\/g, '/');
|
|
907
|
+
const relId = `file_open:rel:${relSlash}`;
|
|
908
|
+
if (relId.length < 100) {
|
|
909
|
+
customId = relId;
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
787
913
|
row.addComponents(new discord_js_1.ButtonBuilder()
|
|
788
|
-
.setCustomId(
|
|
789
|
-
.setLabel(`Open ${displayName.substring(0, 20)}`)
|
|
790
|
-
.setStyle(discord_js_1.ButtonStyle.Primary));
|
|
914
|
+
.setCustomId(customId)
|
|
915
|
+
.setLabel(isArtifactMatch ? `Review ${displayName.substring(0, 15)}` : `Open ${displayName.substring(0, 20)}`)
|
|
916
|
+
.setStyle(isArtifactMatch ? discord_js_1.ButtonStyle.Success : discord_js_1.ButtonStyle.Primary));
|
|
791
917
|
}
|
|
792
918
|
if (row.components.length > 0) {
|
|
793
919
|
components.push(row);
|
|
@@ -895,6 +1021,32 @@ async function sendPromptToAntigravity(bridge, message, prompt, cdp, modeService
|
|
|
895
1021
|
}
|
|
896
1022
|
},
|
|
897
1023
|
});
|
|
1024
|
+
onApprovalRef = async () => {
|
|
1025
|
+
if (isFinalized)
|
|
1026
|
+
return;
|
|
1027
|
+
const textToUse = lastProgressText || monitor.getLastText() || '';
|
|
1028
|
+
const separated = (0, discordFormatter_1.splitOutputAndLogs)(textToUse);
|
|
1029
|
+
const outputText = separated.output || textToUse;
|
|
1030
|
+
if (outputText && outputText.trim().length > 0) {
|
|
1031
|
+
liveResponseUpdateVersion += 1;
|
|
1032
|
+
const responseVersion = liveResponseUpdateVersion;
|
|
1033
|
+
const elapsed = Math.round((Date.now() - startTime) / 1000);
|
|
1034
|
+
await upsertLiveResponseEmbeds((0, i18n_1.t)('Response'), outputText, PHASE_COLORS.thinking, (0, i18n_1.t)(`⏱️ Time: ${elapsed}s | Awaiting Approval`), {
|
|
1035
|
+
source: 'approval-pause',
|
|
1036
|
+
expectedVersion: responseVersion,
|
|
1037
|
+
skipWhenFinalized: true,
|
|
1038
|
+
}).catch(() => { });
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
cdp.on('approval_required', onApprovalRef);
|
|
1042
|
+
if (options?.onMonitorCreated) {
|
|
1043
|
+
options.onMonitorCreated({
|
|
1044
|
+
stop: async () => {
|
|
1045
|
+
isFinalized = true;
|
|
1046
|
+
await monitor.stop();
|
|
1047
|
+
}
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
898
1050
|
await monitor.start();
|
|
899
1051
|
// 1-second elapsed timer — updates footer independently of process log events
|
|
900
1052
|
const elapsedTimer = setInterval(() => {
|
|
@@ -959,6 +1111,8 @@ const startBot = async (cliLogLevel) => {
|
|
|
959
1111
|
.filter((account) => typeof account.userDataDir === 'string' && account.userDataDir.trim().length > 0)
|
|
960
1112
|
.map((account) => [account.name, account.userDataDir.trim()]));
|
|
961
1113
|
const bridge = (0, cdpBridgeManager_1.initCdpBridge)(config.autoApproveFileEdits, accountPorts, accountUserDataDirs);
|
|
1114
|
+
bridge.chatSessionRepo = chatSessionRepo;
|
|
1115
|
+
bridge.artifactService = artifactService;
|
|
962
1116
|
// Initialize CDP-dependent services (constructor CDP dependency removed)
|
|
963
1117
|
const chatSessionService = new chatSessionService_1.ChatSessionService();
|
|
964
1118
|
const titleGenerator = new titleGeneratorService_1.TitleGeneratorService();
|
|
@@ -1009,7 +1163,20 @@ const startBot = async (cliLogLevel) => {
|
|
|
1009
1163
|
accountPrefRepo,
|
|
1010
1164
|
accounts: config.antigravityAccounts,
|
|
1011
1165
|
});
|
|
1012
|
-
await (0, antigravityLauncher_1.startAntigravity)(accountPorts[accountName] ?? 9222);
|
|
1166
|
+
const status = await (0, antigravityLauncher_1.startAntigravity)(accountPorts[accountName] ?? 9222);
|
|
1167
|
+
if (status === 'started') {
|
|
1168
|
+
const cdp = new cdpService_1.CdpService({ portsToScan: [accountPorts[accountName] ?? 9222] });
|
|
1169
|
+
try {
|
|
1170
|
+
await cdp.connect();
|
|
1171
|
+
await cdp.openChatPanel();
|
|
1172
|
+
}
|
|
1173
|
+
catch (e) {
|
|
1174
|
+
// ignore
|
|
1175
|
+
}
|
|
1176
|
+
finally {
|
|
1177
|
+
await cdp.disconnect().catch(() => { });
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1013
1180
|
});
|
|
1014
1181
|
const chatHandler = new chatCommandHandler_1.ChatCommandHandler(chatSessionService, chatSessionRepo, workspaceBindingRepo, channelManager, workspaceService, bridge.pool, (channelId, userId) => (0, accountUtils_1.resolveScopedAccountName)({
|
|
1015
1182
|
channelId,
|
|
@@ -2043,7 +2210,9 @@ async function handleSlashInteraction(interaction, handler, bridge, wsHandler, c
|
|
|
2043
2210
|
const candidatePath = path_1.default.isAbsolute(rawPath) ? rawPath : path_1.default.join(wsPath, rawPath);
|
|
2044
2211
|
const relative = path_1.default.relative(wsPath, candidatePath);
|
|
2045
2212
|
if (!relative.startsWith('..') && !path_1.default.isAbsolute(relative)) {
|
|
2046
|
-
|
|
2213
|
+
if (fs_1.default.existsSync(candidatePath)) {
|
|
2214
|
+
resolvedPath = candidatePath;
|
|
2215
|
+
}
|
|
2047
2216
|
}
|
|
2048
2217
|
}
|
|
2049
2218
|
}
|
|
@@ -1,40 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
3
|
exports.ChatCommandHandler = void 0;
|
|
37
4
|
const i18n_1 = require("../utils/i18n");
|
|
5
|
+
const logger_1 = require("../utils/logger");
|
|
38
6
|
const discord_js_1 = require("discord.js");
|
|
39
7
|
/**
|
|
40
8
|
* Handler for chat session related commands
|
|
@@ -111,9 +79,7 @@ class ChatCommandHandler {
|
|
|
111
79
|
if (!newChatResult.ok) {
|
|
112
80
|
// Log but don't fail the command, as the channel still needs to be created
|
|
113
81
|
// and the user might just have to click it manually if the IDE state is strange.
|
|
114
|
-
|
|
115
|
-
logger.warn(`[/new] Could not start new chat in IDE automatically: ${newChatResult.error}`);
|
|
116
|
-
});
|
|
82
|
+
logger_1.logger.warn(`[/new] Could not start new chat in IDE automatically: ${newChatResult.error}`);
|
|
117
83
|
}
|
|
118
84
|
const customNameRaw = interaction.options.getString('name');
|
|
119
85
|
let safeCustomName = null;
|
|
@@ -156,9 +122,7 @@ class ChatCommandHandler {
|
|
|
156
122
|
if (workspaceCdp) {
|
|
157
123
|
const renameResult = await this.chatSessionService.renameCurrentChatInUI(workspaceCdp, safeCustomName);
|
|
158
124
|
if (!renameResult.ok) {
|
|
159
|
-
|
|
160
|
-
logger.warn(`[/new] Could not rename chat in IDE automatically: ${renameResult.error}`);
|
|
161
|
-
});
|
|
125
|
+
logger_1.logger.warn(`[/new] Could not rename chat in IDE automatically: ${renameResult.error}`);
|
|
162
126
|
}
|
|
163
127
|
}
|
|
164
128
|
}
|
|
@@ -185,8 +149,14 @@ class ChatCommandHandler {
|
|
|
185
149
|
const embed = new discord_js_1.EmbedBuilder()
|
|
186
150
|
.setTitle((0, i18n_1.t)('💬 Chat Session Info'))
|
|
187
151
|
.setColor(info.hasActiveChat ? 0x00CC88 : 0x888888)
|
|
188
|
-
.addFields({ name: (0, i18n_1.t)('Title'), value: info.title, inline: true }, { name: (0, i18n_1.t)('Status'), value: info.hasActiveChat ? (0, i18n_1.t)('🟢 Active') : (0, i18n_1.t)('⚪ Inactive'), inline: true })
|
|
189
|
-
|
|
152
|
+
.addFields({ name: (0, i18n_1.t)('Title'), value: info.title, inline: true }, { name: (0, i18n_1.t)('Status'), value: info.hasActiveChat ? (0, i18n_1.t)('🟢 Active') : (0, i18n_1.t)('⚪ Inactive'), inline: true });
|
|
153
|
+
const channel = await interaction.client.channels.fetch(interaction.channelId).catch(() => null);
|
|
154
|
+
const categoryId = channel?.parentId;
|
|
155
|
+
const isProjectChannel = categoryId ? !!this.bindingRepo.findByChannelId(categoryId) : false;
|
|
156
|
+
const desc = isProjectChannel
|
|
157
|
+
? (0, i18n_1.t)('※ No active session is bound to this channel.\n\n💡 **Tip**: If you recently deleted a session in the IDE, this channel was automatically unbound. Send a prompt or use `/new` to start a fresh chat.')
|
|
158
|
+
: (0, i18n_1.t)('※ Non-session channel.\nUse `/project` to create a project first.');
|
|
159
|
+
embed.setDescription(desc)
|
|
190
160
|
.setTimestamp();
|
|
191
161
|
await interaction.editReply({ embeds: [embed] });
|
|
192
162
|
return;
|