fix(bot,extension): prevent dual delivery of commands and responses via WS+file
This commit is contained in:
15
bot.py
15
bot.py
@@ -102,7 +102,8 @@ class ApprovalView(discord.ui.View):
|
||||
await self.hub.send_response_to_pending_owner(self.request.request_id, {
|
||||
"type": "response", "data": response_data,
|
||||
})
|
||||
# File bridge (fallback — local Extensions)
|
||||
else:
|
||||
# File bridge (fallback — only when Hub is unavailable)
|
||||
self.bridge.write_response(UserResponse(**response_data))
|
||||
embed = interaction.message.embeds[0] if interaction.message.embeds else None
|
||||
if embed:
|
||||
@@ -133,6 +134,7 @@ class ApprovalView(discord.ui.View):
|
||||
await self.hub.send_response_to_pending_owner(self.request.request_id, {
|
||||
"type": "response", "data": response_data,
|
||||
})
|
||||
else:
|
||||
self.bridge.write_response(UserResponse(**response_data))
|
||||
embed = interaction.message.embeds[0] if interaction.message.embeds else None
|
||||
if embed:
|
||||
@@ -158,6 +160,7 @@ class ApprovalView(discord.ui.View):
|
||||
await self.hub.send_response_to_pending_owner(self.request.request_id, {
|
||||
"type": "response", "data": response_data,
|
||||
})
|
||||
else:
|
||||
self.bridge.write_response(UserResponse(**response_data))
|
||||
embed = interaction.message.embeds[0] if interaction.message.embeds else None
|
||||
if embed:
|
||||
@@ -213,7 +216,10 @@ class GravityBot(commands.Bot):
|
||||
|
||||
def _write_command(self, project: str, text: str, *,
|
||||
target_instance: int | None = None, **kwargs):
|
||||
"""Write command to bridge AND push to gateway/hub.
|
||||
"""Write command to Extension via Hub WS (primary) or file bridge (fallback).
|
||||
|
||||
When Hub is connected, ONLY use WS to prevent duplicate delivery.
|
||||
File bridge + Gateway are legacy fallbacks for when Hub is unavailable.
|
||||
|
||||
Args:
|
||||
target_instance: If set, send only to this instance number (via Hub).
|
||||
@@ -224,7 +230,7 @@ class GravityBot(commands.Bot):
|
||||
"project_name": kwargs.get('project_name', project),
|
||||
}
|
||||
|
||||
# Hub route (preferred if available)
|
||||
# Hub route (primary — skip file bridge to prevent double delivery)
|
||||
if self.hub:
|
||||
import time as _time
|
||||
cmd_data["id"] = str(int(_time.time() * 1000))
|
||||
@@ -237,8 +243,9 @@ class GravityBot(commands.Bot):
|
||||
asyncio.create_task(
|
||||
self.hub.broadcast_to_project(project, msg)
|
||||
)
|
||||
return # ← WS sent, skip file bridge
|
||||
|
||||
# Legacy routes (file bridge + gateway HTTP)
|
||||
# Legacy fallback (file bridge + gateway HTTP) — only when Hub is unavailable
|
||||
self.bridge.write_command(project, text, **kwargs)
|
||||
if self.gateway:
|
||||
import time as _time
|
||||
|
||||
@@ -405,8 +405,11 @@ export async function activate(context: vscode.ExtensionContext) {
|
||||
.catch(err => logToFile(`[WS-RESPONSE] Approval error: ${err.message}`));
|
||||
},
|
||||
onCommand: (data: WSCommandData) => {
|
||||
logToFile(`[WS-CMD] ${data.text?.substring(0, 50)}`);
|
||||
// Process command directly (same logic as processCommandFile)
|
||||
logToFile(`[WS-CMD] ${data.text?.substring(0, 50)}`);
|
||||
handleWSCommand({
|
||||
bridgePath, projectName, sdk, autoApproveEnabled, logToFile,
|
||||
onAutoApproveChanged: (enabled: boolean) => { autoApproveEnabled = enabled; },
|
||||
recentDiscordSentTexts,
|
||||
}, data);
|
||||
},
|
||||
onInstanceUpdate: (count, instances) => {
|
||||
@@ -609,41 +612,3 @@ export function deactivate() {
|
||||
if (sdk) {
|
||||
try { sdk.dispose(); } catch { }
|
||||
}
|
||||
}
|
||||
|
||||
// ─── WS Command Handler ───
|
||||
|
||||
function _handleWSCommand(data: WSCommandData) {
|
||||
const text = data.text || '';
|
||||
if (!text) return;
|
||||
|
||||
// Project filtering (WS already routes by project, but double-check)
|
||||
if (data.project_name && data.project_name !== projectName) {
|
||||
logToFile(`[WS-CMD] Ignoring command for ${data.project_name} (we are ${projectName})`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (text === '!stop') {
|
||||
logToFile('[WS-CMD] !stop — cancelling AG task');
|
||||
if (sdk) {
|
||||
try { sdk.cascade.cancelCurrentTask(); } catch { }
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (text.startsWith('!auto')) {
|
||||
const parts = text.split(' ');
|
||||
autoApproveEnabled = parts[1] !== 'off';
|
||||
logToFile(`[WS-CMD] auto_approve=${autoApproveEnabled}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// General text → send as user message to AG
|
||||
logToFile(`[WS-CMD] Sending text to AG: ${text.substring(0, 80)}`);
|
||||
if (sdk) {
|
||||
try {
|
||||
sdk.cascade.sendPrompt(text);
|
||||
} catch (e: any) {
|
||||
logToFile(`[WS-CMD] SDK sendPrompt error: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user