mirror of
https://github.com/garrytan/gstack.git
synced 2026-07-07 08:37:52 +02:00
feat: auto-load Chrome extension when $B connect launches Chrome
Extension auto-loads via --load-extension flag — no manual chrome://extensions install needed. findExtensionPath() checks repo root, global install, and dev paths. Also adds bin/gstack-extension helper for manual install in regular Chrome, and rewrites BROWSER.md install docs with auto-load as primary path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -70,6 +70,39 @@ export class BrowserManager {
|
||||
|
||||
getConnectionMode(): 'launched' | 'cdp' { return this.connectionMode; }
|
||||
|
||||
/**
|
||||
* Find the gstack Chrome extension directory.
|
||||
* Checks: repo root /extension, global install, dev install.
|
||||
*/
|
||||
private findExtensionPath(): string | null {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const candidates = [
|
||||
// Relative to this source file (dev mode: browse/src/ -> ../../extension)
|
||||
path.resolve(__dirname, '..', '..', 'extension'),
|
||||
// Global gstack install
|
||||
path.join(process.env.HOME || '', '.claude', 'skills', 'gstack', 'extension'),
|
||||
// Git repo root (detected via BROWSE_STATE_FILE location)
|
||||
(() => {
|
||||
const stateFile = process.env.BROWSE_STATE_FILE || '';
|
||||
if (stateFile) {
|
||||
const repoRoot = path.resolve(path.dirname(stateFile), '..');
|
||||
return path.join(repoRoot, '.claude', 'skills', 'gstack', 'extension');
|
||||
}
|
||||
return '';
|
||||
})(),
|
||||
].filter(Boolean);
|
||||
|
||||
for (const candidate of candidates) {
|
||||
try {
|
||||
if (fs.existsSync(path.join(candidate, 'manifest.json'))) {
|
||||
return candidate;
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ref map for external consumers (e.g., /refs endpoint).
|
||||
*/
|
||||
@@ -125,12 +158,20 @@ export class BrowserManager {
|
||||
this.refMap.clear();
|
||||
this.nextTabId = 1;
|
||||
|
||||
// Find the gstack extension directory for auto-loading
|
||||
const extensionPath = this.findExtensionPath();
|
||||
const launchArgs = ['--restore-last-session'];
|
||||
if (extensionPath) {
|
||||
launchArgs.push(`--disable-extensions-except=${extensionPath}`);
|
||||
launchArgs.push(`--load-extension=${extensionPath}`);
|
||||
}
|
||||
|
||||
// Launch real Chrome via Playwright's channel protocol
|
||||
// This uses the system Chrome binary, headed, with real window
|
||||
this.browser = await chromium.launch({
|
||||
channel: 'chrome',
|
||||
headless: false,
|
||||
args: ['--restore-last-session'],
|
||||
args: launchArgs,
|
||||
});
|
||||
this.connectionMode = 'cdp';
|
||||
this.intentionalDisconnect = false;
|
||||
|
||||
Reference in New Issue
Block a user