feat: session connect command + auto-registration + bridge/register protocol

This commit is contained in:
2026-03-07 14:15:53 +09:00
parent 887850d0c9
commit 98bb037c81
3 changed files with 136 additions and 1 deletions

View File

@@ -72,7 +72,7 @@ export function activate(context: vscode.ExtensionContext) {
bridgePath = configPath || path.join(os.homedir(), '.gemini', 'antigravity', 'bridge');
// Ensure bridge directories exist
const dirs = ['pending', 'response', 'commands'];
const dirs = ['pending', 'response', 'commands', 'register'];
for (const dir of dirs) {
const dirPath = path.join(bridgePath, dir);
if (!fs.existsSync(dirPath)) {
@@ -92,10 +92,14 @@ export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('gravityBridge.start', startBridge),
vscode.commands.registerCommand('gravityBridge.stop', stopBridge),
vscode.commands.registerCommand('gravityBridge.connect', connectSession),
vscode.commands.registerCommand('gravityBridge.approve', () => handleManualAction(true)),
vscode.commands.registerCommand('gravityBridge.reject', () => handleManualAction(false)),
);
// Auto-watch brain/ for new conversations → auto-register
watchBrainForNewSessions();
// Auto-start
startBridge();
}
@@ -356,6 +360,107 @@ export function writePendingApproval(
return requestId;
}
/**
* Register a conversation → project mapping in bridge/register/.
* The bot reads these files to route brain events to the correct channel.
*/
function registerConversation(conversationId: string) {
const registerDir = path.join(bridgePath, 'register');
if (!fs.existsSync(registerDir)) {
fs.mkdirSync(registerDir, { recursive: true });
}
const filePath = path.join(registerDir, `${conversationId}.json`);
const data = {
conversation_id: conversationId,
project_name: projectName,
timestamp: Date.now() / 1000,
};
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');
console.log(`Gravity Bridge [${projectName}]: registered ${conversationId.substring(0, 8)}`);
}
/**
* Manual connect: scan brain/ for recent conversations and let user pick.
*/
async function connectSession() {
const brainPath = path.join(os.homedir(), '.gemini', 'antigravity', 'brain');
if (!fs.existsSync(brainPath)) {
vscode.window.showErrorMessage('Brain 디렉토리를 찾을 수 없습니다.');
return;
}
// Get conversation dirs sorted by modification time (newest first)
const dirs = fs.readdirSync(brainPath)
.filter(d => {
const fullPath = path.join(brainPath, d);
return fs.statSync(fullPath).isDirectory() && d.includes('-');
})
.map(d => ({
name: d,
mtime: fs.statSync(path.join(brainPath, d)).mtimeMs,
}))
.sort((a, b) => b.mtime - a.mtime)
.slice(0, 10); // Show top 10
if (dirs.length === 0) {
vscode.window.showInformationMessage('활성 세션이 없습니다.');
return;
}
const items = dirs.map(d => ({
label: d.name.substring(0, 8),
description: d.name,
detail: `수정: ${new Date(d.mtime).toLocaleString()}`,
convId: d.name,
}));
const selected = await vscode.window.showQuickPick(items, {
placeHolder: `프로젝트 "${projectName}"에 연결할 세션을 선택하세요`,
});
if (selected) {
registerConversation(selected.convId);
vscode.window.showInformationMessage(
`${selected.label}${projectName} 연결됨`
);
}
}
/**
* Auto-watch brain/ for new conversation directories → auto-register.
*/
function watchBrainForNewSessions() {
const brainPath = path.join(os.homedir(), '.gemini', 'antigravity', 'brain');
if (!fs.existsSync(brainPath)) { return; }
// Track known dirs
const knownDirs = new Set(
fs.readdirSync(brainPath).filter(d =>
fs.statSync(path.join(brainPath, d)).isDirectory()
)
);
try {
fs.watch(brainPath, { persistent: false }, (eventType, filename) => {
if (!filename || !filename.includes('-')) { return; }
const fullPath = path.join(brainPath, filename);
// Check if it's a new directory
if (!knownDirs.has(filename) && fs.existsSync(fullPath) &&
fs.statSync(fullPath).isDirectory()) {
knownDirs.add(filename);
registerConversation(filename);
console.log(`Gravity Bridge [${projectName}]: auto-registered new session ${filename.substring(0, 8)}`);
}
});
console.log(`Gravity Bridge [${projectName}]: watching brain/ for new sessions`);
} catch (err) {
console.error('Gravity Bridge: failed to watch brain dir', err);
}
}
export function deactivate() {
stopBridge();
}