fix(ext): !stop CancelCascadeInvocation RPC — AG 빨간■ 동일 메커니즘 적용 #task-411

This commit is contained in:
Variet Worker
2026-03-18 07:16:17 +09:00
parent 759dab55b6
commit d8eac80b2f
6 changed files with 685 additions and 656 deletions

View File

@@ -435,7 +435,7 @@ async function activate(context) {
onCommand: (data) => {
logToFile(`[WS-CMD] ${data.text?.substring(0, 50)}`);
(0, command_handler_1.handleWSCommand)({
bridgePath, projectName, sdk, autoApproveEnabled, logToFile,
bridgePath, projectName, sdk, ls: sdk?.ls, autoApproveEnabled, logToFile,
onAutoApproveChanged: (enabled) => { autoApproveEnabled = enabled; },
recentDiscordSentTexts,
}, data);
@@ -558,7 +558,7 @@ async function activate(context) {
}
// Watch commands directory
(0, command_handler_1.watchCommandsDir)({
bridgePath, projectName, sdk, autoApproveEnabled, logToFile,
bridgePath, projectName, sdk, ls: sdk?.ls, autoApproveEnabled, logToFile,
onAutoApproveChanged: (enabled) => { autoApproveEnabled = enabled; },
recentDiscordSentTexts,
});

File diff suppressed because one or more lines are too long

View File

@@ -17,6 +17,8 @@ export interface CommandHandlerContext {
bridgePath: string;
projectName: string;
sdk: any;
/** LSBridge instance for direct LS RPC calls (cancelCascade, etc.) */
ls: any;
autoApproveEnabled: boolean;
logToFile: (msg: string) => void;
/** Called when auto-approve is toggled; extension.ts updates its own state */
@@ -93,9 +95,7 @@ export function handleWSCommand(ctx: CommandHandlerContext, data: { text?: strin
if (text === '!stop') {
ctx.logToFile('[WS-CMD] !stop — cancelling AG task');
if (ctx.sdk) {
try { ctx.sdk.cascade.cancelCurrentTask(); } catch { }
}
_cancelCurrentCascade(ctx);
return;
}
@@ -122,6 +122,42 @@ export function handleWSCommand(ctx: CommandHandlerContext, data: { text?: strin
// ─── Private ───
/**
* Cancel the currently active cascade via CancelCascadeInvocation RPC.
* This is the same mechanism AG's native red ■ stop button uses.
*/
async function _cancelCurrentCascade(ctx: CommandHandlerContext) {
// 1. Get the active cascade ID from SDK titles manager
const cascadeId = ctx.sdk?.titles?.getActiveCascadeId?.();
if (!cascadeId) {
ctx.logToFile('[STOP] No active cascade to cancel (getActiveCascadeId returned null)');
return;
}
ctx.logToFile(`[STOP] Cancelling cascade: ${cascadeId.substring(0, 12)}...`);
// 2. Use LSBridge.cancelCascade() → CancelCascadeInvocation RPC
if (ctx.ls) {
try {
await ctx.ls.cancelCascade(cascadeId);
ctx.logToFile(`[STOP] ✅ CancelCascadeInvocation sent for ${cascadeId.substring(0, 12)}`);
return;
} catch (e: any) {
ctx.logToFile(`[STOP] LSBridge cancelCascade failed: ${e.message}`);
}
}
// 3. Fallback: try rawRPC directly via sdk.ls
if (ctx.sdk?.ls?.rawRPC) {
try {
await ctx.sdk.ls.rawRPC('CancelCascadeInvocation', { cascadeId });
ctx.logToFile(`[STOP] ✅ rawRPC CancelCascadeInvocation sent for ${cascadeId.substring(0, 12)}`);
} catch (e: any) {
ctx.logToFile(`[STOP] rawRPC fallback also failed: ${e.message}`);
}
}
}
function _processCommandFile(filePath: string, ctx: CommandHandlerContext) {
try {
const content = fs.readFileSync(filePath, 'utf-8');
@@ -158,15 +194,8 @@ function _processCommandFile(filePath: string, ctx: CommandHandlerContext) {
console.log(`Gravity Bridge: approve_terminal error: ${e.message}`)
);
} else if (text === '!stop') {
// Cancel current operation — use SDK (rejectAgentStep is NOT a registered VS Code command)
if (ctx.sdk) {
try {
ctx.sdk.cascade.cancelCurrentTask();
console.log('Gravity Bridge: ✅ stop sent via SDK');
} catch (e: any) {
console.log(`Gravity Bridge: stop error: ${e.message}`);
}
}
// Cancel current operation — use CancelCascadeInvocation RPC (same as AG's red ■ button)
_cancelCurrentCascade(ctx);
} else if (text.startsWith('!auto')) {
// Auto-approve mode toggle
let enabled: boolean;

File diff suppressed because it is too large Load Diff