fix(extension): v0.3.7 — file_permission 3-button 주입 + active_project.lock 제거

- writePendingApproval()에서 step_type=file_permission일 때 자동 3-button 주입
- active_project.lock 메커니즘 제거 (멀티 프로젝트 동시 사용 지원)
- step_probe auto-resolve에 project_name 필터 추가
- known-issues 2건 추가
This commit is contained in:
2026-03-10 18:48:08 +09:00
parent 11a4730873
commit c9524fc8a8
6 changed files with 54 additions and 103 deletions

View File

@@ -1598,6 +1598,8 @@ function setupMonitor() {
const pfPath = path.join(bridgePath, 'pending', pf);
const pd = JSON.parse(fs.readFileSync(pfPath, 'utf-8'));
if (pd.status !== 'pending') continue;
// Skip other projects' pendings
if (pd.project_name && pd.project_name !== projectName) continue;
// Match by step_index OR by recency (< 60s, any source)
const ageMs = nowMs - (pd.timestamp * 1000);
const isMatch = pd.step_index === lastPendingStepIndex
@@ -2325,7 +2327,18 @@ function writePendingApproval(data: { conversation_id: string; command: string;
}
const id = nowMs.toString();
const payload = {
// Auto-inject 3-button array for file_permission steps
// (step_probe sets step_type but not buttons; DOM observer /pending handler
// only injects buttons when command contains 'allow' which misses step_probe paths)
let buttons = data.buttons;
if (!buttons && data.step_type === 'file_permission') {
buttons = [
{ text: 'Allow Once', index: 0 },
{ text: 'Allow This Conversation', index: 1 },
{ text: 'Deny', index: 2 },
];
}
const payload: Record<string, any> = {
request_id: id,
conversation_id: data.conversation_id,
command: data.command,
@@ -2337,6 +2350,7 @@ function writePendingApproval(data: { conversation_id: string; command: string;
...(data.step_type ? { step_type: data.step_type } : {}),
...(data.step_index !== undefined ? { step_index: data.step_index } : {}),
...(data.source ? { source: data.source } : {}),
...(buttons ? { buttons } : {}),
};
fs.writeFileSync(path.join(pendingDir, `${id}.json`), JSON.stringify(payload, null, 2), 'utf-8');
console.log(`Gravity Bridge: pending approval written → ${id}.json`);
@@ -2664,51 +2678,9 @@ export async function activate(context: vscode.ExtensionContext) {
ensureBridgeDir();
console.log(`Gravity Bridge: bridge path: ${bridgePath}`);
// ── Single Active Project Lock ──
const lockFile = path.join(bridgePath, 'active_project.lock');
let bridgeDisabled = false;
try {
if (fs.existsSync(lockFile)) {
const lockData = JSON.parse(fs.readFileSync(lockFile, 'utf-8'));
// Check if lock holder is still alive
let lockAlive = false;
if (lockData.pid) {
try { process.kill(lockData.pid, 0); lockAlive = true; } catch { lockAlive = false; }
}
if (lockAlive && lockData.project !== projectName) {
vscode.window.showWarningMessage(
`⚠️ Discord Bridge: "${lockData.project}"가 이미 활성 중 (PID ${lockData.pid}). 이 프로젝트(${projectName})는 Discord에 연결되지 않습니다.`,
'무시하고 연결'
).then(choice => {
if (choice === '무시하고 연결') {
// Overwrite lock
fs.writeFileSync(lockFile, JSON.stringify({
project: projectName, pid: process.pid,
since: new Date().toISOString(), hostname: os.hostname()
}), 'utf-8');
logToFile(`[LOCK] Force-acquired lock (was: ${lockData.project})`);
}
});
bridgeDisabled = true;
logToFile(`[LOCK] Another project active: ${lockData.project} (PID ${lockData.pid}) — bridge disabled`);
} else {
// Stale lock or same project — overwrite
fs.writeFileSync(lockFile, JSON.stringify({
project: projectName, pid: process.pid,
since: new Date().toISOString(), hostname: os.hostname()
}), 'utf-8');
logToFile(`[LOCK] Acquired lock (stale/same project)`);
}
} else {
fs.writeFileSync(lockFile, JSON.stringify({
project: projectName, pid: process.pid,
since: new Date().toISOString(), hostname: os.hostname()
}), 'utf-8');
logToFile(`[LOCK] Created lock for ${projectName}`);
}
} catch (lockErr: any) {
logToFile(`[LOCK] Error: ${lockErr.message}`);
}
// ── Multi-project: no lock file, each project uses project_name-based filtering ──
// (active_project.lock removed — was blocking concurrent multi-project usage)
logToFile(`[INIT] project="${projectName}" pid=${process.pid} — multi-project mode (no lock)`);
// Status bar
statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100);
@@ -2831,14 +2803,13 @@ export async function activate(context: vscode.ExtensionContext) {
}
export function deactivate() {
// Release active project lock
// Clean up stale lock file if it exists (legacy cleanup)
try {
const lockFile = path.join(bridgePath, 'active_project.lock');
if (fs.existsSync(lockFile)) {
const lockData = JSON.parse(fs.readFileSync(lockFile, 'utf-8'));
if (lockData.pid === process.pid) {
fs.unlinkSync(lockFile);
logToFile(`[LOCK] Released lock for ${projectName}`);
}
}
} catch { }