mirror of https://github.com/garrytan/gstack.git
feat: ungate sidebar agent + raise timeout to 5 minutes (v0.12.0)
Sidebar chat is now always available in headed mode — no --chat flag needed. Agent tasks get 5 minutes instead of 2, enabling multi-page workflows like navigating directories and filling forms across pages. Changes: - cli.ts: remove --chat flag, always set BROWSE_SIDEBAR_CHAT=1, always spawn agent - server.ts: remove chatEnabled gate (403 response), raise AGENT_TIMEOUT_MS to 300s - sidebar-agent.ts: raise child process timeout from 120s to 300s Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b2e1ee9e7b
commit
376b572c5a
|
|
@ -520,18 +520,15 @@ Refs: After 'snapshot', use @e1, @e2... as selectors:
|
||||||
// Delete stale state file
|
// Delete stale state file
|
||||||
try { fs.unlinkSync(config.stateFile); } catch {}
|
try { fs.unlinkSync(config.stateFile); } catch {}
|
||||||
|
|
||||||
const chatMode = commandArgs.includes('--chat');
|
console.log('Launching headed Chromium with extension + sidebar agent...');
|
||||||
console.log(chatMode
|
|
||||||
? 'Launching headed Chromium with extension + standalone chat (experimental)...'
|
|
||||||
: 'Launching headed Chromium with extension...');
|
|
||||||
try {
|
try {
|
||||||
// Start server in headed mode with extension auto-loaded
|
// Start server in headed mode with extension auto-loaded
|
||||||
// Use a well-known port so the Chrome extension auto-connects
|
// Use a well-known port so the Chrome extension auto-connects
|
||||||
const serverEnv: Record<string, string> = {
|
const serverEnv: Record<string, string> = {
|
||||||
BROWSE_HEADED: '1',
|
BROWSE_HEADED: '1',
|
||||||
BROWSE_PORT: '34567',
|
BROWSE_PORT: '34567',
|
||||||
|
BROWSE_SIDEBAR_CHAT: '1',
|
||||||
};
|
};
|
||||||
if (chatMode) serverEnv.BROWSE_SIDEBAR_CHAT = '1';
|
|
||||||
const newState = await startServer(serverEnv);
|
const newState = await startServer(serverEnv);
|
||||||
|
|
||||||
// Print connected status
|
// Print connected status
|
||||||
|
|
@ -547,31 +544,28 @@ Refs: After 'snapshot', use @e1, @e2... as selectors:
|
||||||
const status = await resp.text();
|
const status = await resp.text();
|
||||||
console.log(`Connected to real Chrome\n${status}`);
|
console.log(`Connected to real Chrome\n${status}`);
|
||||||
|
|
||||||
// Auto-start sidebar agent only when --chat is enabled
|
// Auto-start sidebar agent
|
||||||
if (chatMode) {
|
const agentScript = path.resolve(__dirname, 'sidebar-agent.ts');
|
||||||
const agentScript = path.resolve(__dirname, 'sidebar-agent.ts');
|
try {
|
||||||
const agentLogFile = path.join(process.env.HOME || '/tmp', '.gstack', 'sidebar-agent.log');
|
// Clear old agent queue
|
||||||
try {
|
const agentQueue = path.join(process.env.HOME || '/tmp', '.gstack', 'sidebar-agent-queue.jsonl');
|
||||||
// Clear old agent queue
|
try { fs.writeFileSync(agentQueue, ''); } catch {}
|
||||||
const agentQueue = path.join(process.env.HOME || '/tmp', '.gstack', 'sidebar-agent-queue.jsonl');
|
|
||||||
try { fs.writeFileSync(agentQueue, ''); } catch {}
|
|
||||||
|
|
||||||
const agentProc = Bun.spawn(['bun', 'run', agentScript], {
|
const agentProc = Bun.spawn(['bun', 'run', agentScript], {
|
||||||
cwd: config.projectDir,
|
cwd: config.projectDir,
|
||||||
env: {
|
env: {
|
||||||
...process.env,
|
...process.env,
|
||||||
BROWSE_BIN: path.resolve(__dirname, '..', 'dist', 'browse'),
|
BROWSE_BIN: path.resolve(__dirname, '..', 'dist', 'browse'),
|
||||||
BROWSE_STATE_FILE: config.stateFile,
|
BROWSE_STATE_FILE: config.stateFile,
|
||||||
BROWSE_SERVER_PORT: String(newState.port),
|
BROWSE_SERVER_PORT: String(newState.port),
|
||||||
},
|
},
|
||||||
stdio: ['ignore', 'ignore', 'ignore'],
|
stdio: ['ignore', 'ignore', 'ignore'],
|
||||||
});
|
});
|
||||||
agentProc.unref();
|
agentProc.unref();
|
||||||
console.log(`[browse] Sidebar agent started (PID: ${agentProc.pid})`);
|
console.log(`[browse] Sidebar agent started (PID: ${agentProc.pid})`);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error(`[browse] Sidebar agent failed to start: ${err.message}`);
|
console.error(`[browse] Sidebar agent failed to start: ${err.message}`);
|
||||||
console.error(`[browse] Run manually: bun run ${agentScript}`);
|
console.error(`[browse] Run manually: bun run ${agentScript}`);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.error(`[browse] Connect failed: ${err.message}`);
|
console.error(`[browse] Connect failed: ${err.message}`);
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ ensureStateDir(config);
|
||||||
const AUTH_TOKEN = crypto.randomUUID();
|
const AUTH_TOKEN = crypto.randomUUID();
|
||||||
const BROWSE_PORT = parseInt(process.env.BROWSE_PORT || '0', 10);
|
const BROWSE_PORT = parseInt(process.env.BROWSE_PORT || '0', 10);
|
||||||
const IDLE_TIMEOUT_MS = parseInt(process.env.BROWSE_IDLE_TIMEOUT || '1800000', 10); // 30 min
|
const IDLE_TIMEOUT_MS = parseInt(process.env.BROWSE_IDLE_TIMEOUT || '1800000', 10); // 30 min
|
||||||
const chatEnabled = process.env.BROWSE_SIDEBAR_CHAT === '1';
|
// Sidebar chat is always enabled in headed mode (ungated in v0.12.0)
|
||||||
|
|
||||||
function validateAuth(req: Request): boolean {
|
function validateAuth(req: Request): boolean {
|
||||||
const header = req.headers.get('authorization');
|
const header = req.headers.get('authorization');
|
||||||
|
|
@ -116,7 +116,7 @@ interface SidebarSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
const SESSIONS_DIR = path.join(process.env.HOME || '/tmp', '.gstack', 'sidebar-sessions');
|
const SESSIONS_DIR = path.join(process.env.HOME || '/tmp', '.gstack', 'sidebar-sessions');
|
||||||
const AGENT_TIMEOUT_MS = 120_000;
|
const AGENT_TIMEOUT_MS = 300_000; // 5 minutes — multi-page tasks need time
|
||||||
const MAX_QUEUE = 5;
|
const MAX_QUEUE = 5;
|
||||||
|
|
||||||
let sidebarSession: SidebarSession | null = null;
|
let sidebarSession: SidebarSession | null = null;
|
||||||
|
|
@ -811,7 +811,7 @@ async function start() {
|
||||||
tabs: browserManager.getTabCount(),
|
tabs: browserManager.getTabCount(),
|
||||||
currentUrl: browserManager.getCurrentUrl(),
|
currentUrl: browserManager.getCurrentUrl(),
|
||||||
token: AUTH_TOKEN, // Extension uses this for Bearer auth
|
token: AUTH_TOKEN, // Extension uses this for Bearer auth
|
||||||
chatEnabled,
|
chatEnabled: true,
|
||||||
agent: {
|
agent: {
|
||||||
status: agentStatus,
|
status: agentStatus,
|
||||||
runningFor: agentStartTime ? Date.now() - agentStartTime : null,
|
runningFor: agentStartTime ? Date.now() - agentStartTime : null,
|
||||||
|
|
@ -910,13 +910,7 @@ async function start() {
|
||||||
|
|
||||||
// ─── Sidebar endpoints (auth required — token from /health) ────
|
// ─── Sidebar endpoints (auth required — token from /health) ────
|
||||||
|
|
||||||
// Gate all sidebar/chat routes behind --chat flag
|
// Sidebar routes are always available in headed mode (ungated in v0.12.0)
|
||||||
if (!chatEnabled && url.pathname.startsWith('/sidebar')) {
|
|
||||||
return new Response(JSON.stringify({ error: 'Chat not enabled. Use: $B connect --chat' }), {
|
|
||||||
status: 403,
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sidebar chat history — read from in-memory buffer
|
// Sidebar chat history — read from in-memory buffer
|
||||||
if (url.pathname === '/sidebar-chat') {
|
if (url.pathname === '/sidebar-chat') {
|
||||||
|
|
|
||||||
|
|
@ -205,14 +205,14 @@ async function askClaude(queueEntry: any): Promise<void> {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Timeout after 120 seconds
|
// Timeout after 300 seconds (5 min — multi-page tasks need time)
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
try { proc.kill(); } catch {}
|
try { proc.kill(); } catch {}
|
||||||
sendEvent({ type: 'agent_error', error: 'Timed out after 120s' }).then(() => {
|
sendEvent({ type: 'agent_error', error: 'Timed out after 300s' }).then(() => {
|
||||||
isProcessing = false;
|
isProcessing = false;
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
}, 120000);
|
}, 300000);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue