diff --git a/apps/web/lib/agent-runner.ts b/apps/web/lib/agent-runner.ts index 85294be57a7..005d0c7980d 100644 --- a/apps/web/lib/agent-runner.ts +++ b/apps/web/lib/agent-runner.ts @@ -10,6 +10,7 @@ export type AgentEvent = { stream?: string; data?: Record; seq?: number; + globalSeq?: number; ts?: number; sessionKey?: string; status?: string; @@ -198,6 +199,43 @@ export function spawnAgentProcess( }); } +/** + * Spawn a subscribe-only agent child process that tails a session key's events. + * Uses the same runtime/env wiring as spawnAgentProcess. + */ +export function spawnAgentSubscribeProcess( + sessionKey: string, + afterSeq = 0, +): ReturnType { + const root = resolvePackageRoot(); + + const devScript = join(root, "scripts", "run-node.mjs"); + const prodScript = join(root, "openclaw.mjs"); + const scriptPath = existsSync(devScript) ? devScript : prodScript; + + const args = [ + scriptPath, + "agent", + "--stream-json", + "--subscribe-session-key", + sessionKey, + "--after-seq", + String(Math.max(0, Number.isFinite(afterSeq) ? afterSeq : 0)), + ]; + + const profile = getEffectiveProfile(); + const workspace = resolveWorkspaceRoot(); + return spawn("node", args, { + cwd: root, + env: { + ...process.env, + ...(profile ? { OPENCLAW_PROFILE: profile } : {}), + ...(workspace ? { OPENCLAW_WORKSPACE: workspace } : {}), + }, + stdio: ["ignore", "pipe", "pipe"], + }); +} + /** * Build a flat output object from the agent's tool result so the frontend * can render tool output text, exit codes, etc.