@parall/daemon 1.49.0 → 1.50.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/bundle/manifest.json +11 -11
  2. package/bundle/parall-browser-pod.js +318 -104
  3. package/bundle/parall-claude-agent.js +124 -29
  4. package/bundle/parall-codex-agent.js +124 -29
  5. package/bundle/parall-daemon.js +368 -184
  6. package/dist/browser-pod.d.ts.map +1 -1
  7. package/dist/browser-pod.js +9 -14
  8. package/dist/browser-profile-viewer-control.d.ts +15 -0
  9. package/dist/browser-profile-viewer-control.d.ts.map +1 -0
  10. package/dist/browser-profile-viewer-control.js +27 -0
  11. package/dist/clip-runtime/bb-viewer-command-client.d.ts +19 -0
  12. package/dist/clip-runtime/bb-viewer-command-client.d.ts.map +1 -0
  13. package/dist/clip-runtime/bb-viewer-command-client.js +89 -0
  14. package/dist/clip-runtime/browser-profile-manager.d.ts +3 -1
  15. package/dist/clip-runtime/browser-profile-manager.d.ts.map +1 -1
  16. package/dist/clip-runtime/browser-profile-manager.js +2 -2
  17. package/dist/clip-runtime/browser-viewer-streamer.d.ts +7 -7
  18. package/dist/clip-runtime/browser-viewer-streamer.d.ts.map +1 -1
  19. package/dist/clip-runtime/browser-viewer-streamer.js +39 -47
  20. package/dist/clip-runtime/clip-provider.d.ts +3 -2
  21. package/dist/clip-runtime/clip-provider.d.ts.map +1 -1
  22. package/dist/clip-runtime/clip-provider.js +13 -6
  23. package/dist/clip-runtime/hosted-viewer-command-queue.d.ts +43 -0
  24. package/dist/clip-runtime/hosted-viewer-command-queue.d.ts.map +1 -0
  25. package/dist/clip-runtime/hosted-viewer-command-queue.js +72 -0
  26. package/dist/clip-runtime/index.d.ts +1 -0
  27. package/dist/clip-runtime/index.d.ts.map +1 -1
  28. package/dist/clip-runtime/index.js +1 -0
  29. package/dist/clip-runtime/viewer-command-deadline.d.ts +14 -0
  30. package/dist/clip-runtime/viewer-command-deadline.d.ts.map +1 -0
  31. package/dist/clip-runtime/viewer-command-deadline.js +29 -0
  32. package/dist/clip-runtime/viewer-command-error.d.ts +18 -0
  33. package/dist/clip-runtime/viewer-command-error.d.ts.map +1 -0
  34. package/dist/clip-runtime/viewer-command-error.js +23 -0
  35. package/dist/supervisor.d.ts +0 -8
  36. package/dist/supervisor.d.ts.map +1 -1
  37. package/dist/supervisor.js +3 -32
  38. package/package.json +6 -6
@@ -1 +1 @@
1
- {"version":3,"file":"browser-pod.d.ts","sourceRoot":"","sources":["../src/browser-pod.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser-pod.d.ts","sourceRoot":"","sources":["../src/browser-pod.ts"],"names":[],"mappings":"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"}
@@ -57,6 +57,7 @@ import { awaitBrowserQuiescence } from './clip-runtime/browser-quiescence.js';
57
57
  import { PUBLIC_PROXY_PROBE_FALLBACK_URL } from './clip-runtime/browser-readiness.js';
58
58
  import { BrowserStateStore } from './clip-runtime/browser-state-store.js';
59
59
  import { ClipProvider } from './clip-runtime/clip-provider.js';
60
+ import { HostedViewerCommandQueue } from './clip-runtime/hosted-viewer-command-queue.js';
60
61
  import { ClipProcessManager } from './clip-runtime/process-manager.js';
61
62
  /**
62
63
  * Platform assignment token prefix (SSOT: server/pkg/platformauth/token.go). A
@@ -701,20 +702,14 @@ export async function preparePodRuntime(config, env, log) {
701
702
  dataDir: path.join(config.stateDir, 'clip-data'),
702
703
  browserProfileManager: browser,
703
704
  });
704
- // Hosted live-viewer handler (design §3.4): clip-service relays viewer commands
705
- // down the ProviderStream and the pod replies over it. Serialize them they
706
- // mutate the single profile's bb-viewer streamer + account state, so a client
707
- // retrying stream.start must not interleave with the in-flight one (the BYOC
708
- // supervisor serializes per profile for the same reason). One pod = one
709
- // profile, so a single chain suffices.
710
- let viewerChain = Promise.resolve();
711
- const onViewerCommand = (cmd) => {
712
- const run = viewerChain
713
- .catch(() => { }) // keep the chain moving past a prior failure
714
- .then(() => browser.handleViewerCommand(cmd.profileId, cmd.sessionId, cmd.command, cmd.input, cmd.turn));
715
- viewerChain = run.catch(() => { });
716
- return run;
717
- };
705
+ // Hosted live-viewer handler (design §3.4): serialize mutations, but start the
706
+ // readiness budget at ProviderStream receipt/queue entry. A plain promise chain
707
+ // used to start bb-viewer's 30s watchdog only AFTER older work drained, so the
708
+ // API's absolute 45s deadline could win first with a generic timeout.
709
+ const viewerCommands = new HostedViewerCommandQueue((cmd, executionDeadlineUnixMs) => browser.handleViewerCommand(cmd.profileId, cmd.sessionId, cmd.command, cmd.input, cmd.turn, {
710
+ deadlineUnixMs: executionDeadlineUnixMs,
711
+ }));
712
+ const onViewerCommand = viewerCommands.enqueue.bind(viewerCommands);
718
713
  // ClipProvider passes authKey straight through as the ProviderStream bearer —
719
714
  // it does not assume mck_ — so the pba_ assignment token authenticates the pod.
720
715
  // providerName is cosmetic for routing (the hub keys the session by the token's
@@ -0,0 +1,15 @@
1
+ import type { GatewayLogger } from '@parall/agent-core';
2
+ import type { MachineBrowserProfileViewerData, ParallClient } from '@parall/sdk';
3
+ import type { BrowserProfilePool } from './clip-runtime/browser-profile-pool.js';
4
+ export interface BrowserProfileViewerControlDeps {
5
+ pool: BrowserProfilePool | null;
6
+ client: Pick<ParallClient, 'postBrowserProfileViewerResponse'>;
7
+ log: Pick<GatewayLogger, 'warn'>;
8
+ }
9
+ /**
10
+ * Handle one viewer control command and reply via REST. Always answers the
11
+ * request/reply bridge exactly once ({result} on success,
12
+ * {error:{code?,message}} on failure) and never throws into the WS event loop.
13
+ */
14
+ export declare function handleBrowserProfileViewerCommand(deps: BrowserProfileViewerControlDeps, data: MachineBrowserProfileViewerData): Promise<void>;
15
+ //# sourceMappingURL=browser-profile-viewer-control.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-profile-viewer-control.d.ts","sourceRoot":"","sources":["../src/browser-profile-viewer-control.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,+BAA+B,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACjF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,wCAAwC,CAAC;AAGjF,MAAM,WAAW,+BAA+B;IAC9C,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE,kCAAkC,CAAC,CAAC;IAC/D,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAsB,iCAAiC,CACrD,IAAI,EAAE,+BAA+B,EACrC,IAAI,EAAE,+BAA+B,GACpC,OAAO,CAAC,IAAI,CAAC,CA8Bf"}
@@ -0,0 +1,27 @@
1
+ import { viewerCommandFailure } from './clip-runtime/viewer-command-error.js';
2
+ /**
3
+ * Handle one viewer control command and reply via REST. Always answers the
4
+ * request/reply bridge exactly once ({result} on success,
5
+ * {error:{code?,message}} on failure) and never throws into the WS event loop.
6
+ */
7
+ export async function handleBrowserProfileViewerCommand(deps, data) {
8
+ if (!deps.pool) {
9
+ await deps.client
10
+ .postBrowserProfileViewerResponse(data.request_id, {
11
+ error: { message: 'Browser profile runtime is disabled on this daemon' },
12
+ })
13
+ .catch((err) => deps.log.warn(`browser profile viewer negative ACK failed: ${String(err)}`));
14
+ return;
15
+ }
16
+ try {
17
+ const result = await deps.pool.handleViewerCommand(data.profile_id, data.session_id, data.command, data.input, data.turn);
18
+ await deps.client.postBrowserProfileViewerResponse(data.request_id, { result });
19
+ }
20
+ catch (err) {
21
+ const failure = viewerCommandFailure(err);
22
+ deps.log.warn(`browser profile viewer command failed (profile=${data.profile_id}, command=${data.command}): ${failure.message}`);
23
+ await deps.client
24
+ .postBrowserProfileViewerResponse(data.request_id, { error: failure })
25
+ .catch((replyErr) => deps.log.warn(`browser profile viewer error ACK failed: ${String(replyErr)}`));
26
+ }
27
+ }
@@ -0,0 +1,19 @@
1
+ /** Protocol 2 answer/switch wait for a bound first frame. Keep their caller
2
+ * budget above bb-viewer's 25s total readiness watchdog so its stable typed
3
+ * failure wins before the daemon aborts the HTTP request. */
4
+ export declare function bbViewerCommandTimeoutMs(method: string): number;
5
+ /** Shrink bb-viewer's command watchdog to the remaining hosted-pod budget. */
6
+ export declare function bbViewerCommandEffectiveTimeoutMs(method: string, deadlineUnixMs?: number, now?: number): number;
7
+ /**
8
+ * POST one command to bb-viewer's loopback `/command` adapter. Hosted callers
9
+ * supply the queue-derived absolute deadline; BYOC callers retain the method
10
+ * defaults. Stable upstream lifecycle codes survive unchanged.
11
+ */
12
+ export declare function sendBBViewerCommand(port: number, method: string, params: Record<string, unknown>, deadlineUnixMs?: number): Promise<Record<string, unknown>>;
13
+ /**
14
+ * Parse one bb-viewer command response without exposing a malformed response
15
+ * body. Exported as the protocol-adapter seam for deterministic regression
16
+ * tests; callers use {@link ViewerCommandError} to preserve stable codes.
17
+ */
18
+ export declare function parseBBViewerCommandResponse(status: number, text: string, method: string): Record<string, unknown>;
19
+ //# sourceMappingURL=bb-viewer-command-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bb-viewer-command-client.d.ts","sourceRoot":"","sources":["../../src/clip-runtime/bb-viewer-command-client.ts"],"names":[],"mappings":"AAMA;;6DAE6D;AAC7D,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAI/D;AAED,8EAA8E;AAC9E,wBAAgB,iCAAiC,CAC/C,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,MAAM,EACvB,GAAG,SAAa,GACf,MAAM,CAQR;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAqBlC;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,GACb,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAmCzB"}
@@ -0,0 +1,89 @@
1
+ import { viewerReadinessDeadlineError } from './viewer-command-deadline.js';
2
+ import { ViewerCommandError } from './viewer-command-error.js';
3
+ const BB_VIEWER_COMMAND_TIMEOUT_MS = 15_000;
4
+ const BB_VIEWER_READINESS_COMMAND_TIMEOUT_MS = 30_000;
5
+ /** Protocol 2 answer/switch wait for a bound first frame. Keep their caller
6
+ * budget above bb-viewer's 25s total readiness watchdog so its stable typed
7
+ * failure wins before the daemon aborts the HTTP request. */
8
+ export function bbViewerCommandTimeoutMs(method) {
9
+ return method === 'answer' || method === 'switch'
10
+ ? BB_VIEWER_READINESS_COMMAND_TIMEOUT_MS
11
+ : BB_VIEWER_COMMAND_TIMEOUT_MS;
12
+ }
13
+ /** Shrink bb-viewer's command watchdog to the remaining hosted-pod budget. */
14
+ export function bbViewerCommandEffectiveTimeoutMs(method, deadlineUnixMs, now = Date.now()) {
15
+ const configured = bbViewerCommandTimeoutMs(method);
16
+ if (deadlineUnixMs === undefined)
17
+ return configured;
18
+ const remaining = deadlineUnixMs - now;
19
+ if (remaining <= 0) {
20
+ throw viewerReadinessDeadlineError(`before bb-viewer ${method}`);
21
+ }
22
+ return Math.max(1, Math.min(configured, remaining));
23
+ }
24
+ /**
25
+ * POST one command to bb-viewer's loopback `/command` adapter. Hosted callers
26
+ * supply the queue-derived absolute deadline; BYOC callers retain the method
27
+ * defaults. Stable upstream lifecycle codes survive unchanged.
28
+ */
29
+ export async function sendBBViewerCommand(port, method, params, deadlineUnixMs) {
30
+ const controller = new AbortController();
31
+ const timeoutMs = bbViewerCommandEffectiveTimeoutMs(method, deadlineUnixMs);
32
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
33
+ try {
34
+ const resp = await fetch(`http://127.0.0.1:${port}/command`, {
35
+ method: 'POST',
36
+ headers: { 'Content-Type': 'application/json' },
37
+ body: JSON.stringify({ method, params }),
38
+ signal: controller.signal,
39
+ });
40
+ const text = await resp.text();
41
+ return parseBBViewerCommandResponse(resp.status, text, method);
42
+ }
43
+ catch (err) {
44
+ if (controller.signal.aborted && (method === 'answer' || method === 'switch')) {
45
+ throw viewerReadinessDeadlineError(`while waiting for bb-viewer ${method}`);
46
+ }
47
+ throw err;
48
+ }
49
+ finally {
50
+ clearTimeout(timer);
51
+ }
52
+ }
53
+ /**
54
+ * Parse one bb-viewer command response without exposing a malformed response
55
+ * body. Exported as the protocol-adapter seam for deterministic regression
56
+ * tests; callers use {@link ViewerCommandError} to preserve stable codes.
57
+ */
58
+ export function parseBBViewerCommandResponse(status, text, method) {
59
+ let parsed;
60
+ try {
61
+ parsed = text ? JSON.parse(text) : {};
62
+ }
63
+ catch {
64
+ throw new ViewerCommandError(`bb-viewer ${method} returned invalid JSON`);
65
+ }
66
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
67
+ throw new ViewerCommandError(`bb-viewer ${method} returned an invalid response`);
68
+ }
69
+ const envelope = parsed;
70
+ if (envelope.error) {
71
+ const code = typeof envelope.error.code === 'string' && envelope.error.code.trim()
72
+ ? envelope.error.code.trim()
73
+ : undefined;
74
+ const message = typeof envelope.error.message === 'string' && envelope.error.message.trim()
75
+ ? envelope.error.message
76
+ : `bb-viewer ${method} failed`;
77
+ throw new ViewerCommandError(message, code);
78
+ }
79
+ if (status < 200 || status >= 300) {
80
+ throw new ViewerCommandError(`bb-viewer ${method} returned ${status}`);
81
+ }
82
+ if (envelope.result === undefined || envelope.result === null) {
83
+ return {};
84
+ }
85
+ if (typeof envelope.result !== 'object' || Array.isArray(envelope.result)) {
86
+ throw new ViewerCommandError(`bb-viewer ${method} returned an invalid result`);
87
+ }
88
+ return envelope.result;
89
+ }
@@ -78,7 +78,9 @@ export declare class BrowserProfileManager {
78
78
  * (browser-viewer-streamer.ts), which owns the per-profile bb-viewer
79
79
  * subprocesses and viewer tab navigation.
80
80
  */
81
- handleViewerCommand(profileId: string, sessionId: string, command: string, input?: Record<string, unknown>, turn?: ViewerTurnConfig): Promise<Record<string, unknown>>;
81
+ handleViewerCommand(profileId: string, sessionId: string, command: string, input?: Record<string, unknown>, turn?: ViewerTurnConfig, execution?: {
82
+ deadlineUnixMs?: number;
83
+ }): Promise<Record<string, unknown>>;
82
84
  /** Read cdpHost/cdpPort from the bb-browser daemon `GET /status`. */
83
85
  private cdpEndpoint;
84
86
  private lastCdpEndpoint;
@@ -1 +1 @@
1
- {"version":3,"file":"browser-profile-manager.d.ts","sourceRoot":"","sources":["../../src/clip-runtime/browser-profile-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser-profile-manager.d.ts","sourceRoot":"","sources":["../../src/clip-runtime/browser-profile-manager.ts"],"names":[],"mappings":"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"}
@@ -271,8 +271,8 @@ export class BrowserProfileManager {
271
271
  * (browser-viewer-streamer.ts), which owns the per-profile bb-viewer
272
272
  * subprocesses and viewer tab navigation.
273
273
  */
274
- async handleViewerCommand(profileId, sessionId, command, input, turn) {
275
- return this.viewer.handleViewerCommand(profileId, sessionId, command, input, turn);
274
+ async handleViewerCommand(profileId, sessionId, command, input, turn, execution) {
275
+ return this.viewer.handleViewerCommand(profileId, sessionId, command, input, turn, execution);
276
276
  }
277
277
  /** Read cdpHost/cdpPort from the bb-browser daemon `GET /status`. */
278
278
  async cdpEndpoint() {
@@ -1,10 +1,15 @@
1
1
  import type { BrowserTargetRegistry } from './browser-target-registry.js';
2
+ export { bbViewerCommandEffectiveTimeoutMs, bbViewerCommandTimeoutMs, parseBBViewerCommandResponse, } from './bb-viewer-command-client.js';
2
3
  /** Optional managed TURN relay config carried on a `stream.start` command. */
3
4
  export interface ViewerTurnConfig {
4
5
  url: string;
5
6
  username?: string;
6
7
  credential?: string;
7
8
  }
9
+ export interface ViewerCommandExecutionBudget {
10
+ /** Absolute pod execution deadline, already capped to leave the reply reserve. */
11
+ deadlineUnixMs?: number;
12
+ }
8
13
  /**
9
14
  * The slice of BrowserProfileManager the viewer streamer depends on: the
10
15
  * account-scoped bb-browser /command path and the daemon lifecycle helpers.
@@ -63,7 +68,7 @@ export declare class BrowserViewerStreamer {
63
68
  * partial result. `data.input` / `data.turn` / `data.session_id` come from
64
69
  * MachineBrowserProfileViewerData.
65
70
  */
66
- handleViewerCommand(profileId: string, sessionId: string, command: string, input?: Record<string, unknown>, turn?: ViewerTurnConfig): Promise<Record<string, unknown>>;
71
+ handleViewerCommand(profileId: string, sessionId: string, command: string, input?: Record<string, unknown>, turn?: ViewerTurnConfig, execution?: ViewerCommandExecutionBudget): Promise<Record<string, unknown>>;
67
72
  /**
68
73
  * kick — server-side per-viewer disconnect (design §3.6 PR7). Terminates ONE
69
74
  * viewer's WebRTC session: stop its bb-viewer streamer (killing the process
@@ -128,6 +133,7 @@ export declare class BrowserViewerStreamer {
128
133
  * (`ws://host:port/devtools/page/<targetId>`) to avoid an extra /status call.
129
134
  */
130
135
  private bringTargetToFront;
136
+ private assertViewerExecutionDeadline;
131
137
  /**
132
138
  * Forward a navigation command (tab_list/tab_new/open/reload/back/forward/
133
139
  * close) to bb-browser scoped to the profile's account. This lets the human
@@ -199,12 +205,6 @@ export declare class BrowserViewerStreamer {
199
205
  * shutdown() abandons the timer — acceptable, the TERM was still sent.
200
206
  */
201
207
  private killChild;
202
- /**
203
- * POST a command to the profile's bb-viewer `/command` endpoint. Parses the
204
- * `{result}` / `{error:{message}}` envelope (bb-viewer api.go) and returns
205
- * the inner result, throwing the error message on failure.
206
- */
207
- private streamerCommand;
208
208
  /**
209
209
  * Kill + remove the profile's bb-viewer streamer, if any. Idempotent. Also
210
210
  * clears any kick marker for the profile: a (re)kill establishes a clean
@@ -1 +1 @@
1
- {"version":3,"file":"browser-viewer-streamer.d.ts","sourceRoot":"","sources":["../../src/clip-runtime/browser-viewer-streamer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browser-viewer-streamer.d.ts","sourceRoot":"","sources":["../../src/clip-runtime/browser-viewer-streamer.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import { spawn } from 'node:child_process';
2
+ import { sendBBViewerCommand } from './bb-viewer-command-client.js';
2
3
  import { findFreePort, formatErrorForLog, sleep } from './subprocess.js';
4
+ import { viewerReadinessDeadlineError } from './viewer-command-deadline.js';
5
+ export { bbViewerCommandEffectiveTimeoutMs, bbViewerCommandTimeoutMs, parseBBViewerCommandResponse, } from './bb-viewer-command-client.js';
3
6
  const BB_VIEWER_HEALTH_TIMEOUT_MS = 10_000;
4
- const BB_VIEWER_COMMAND_TIMEOUT_MS = 15_000;
5
7
  // A streamer whose session never received a stream.answer is abandoned: the
6
8
  // client vanished mid-handshake (hard tab close before its session id arrived)
7
9
  // and can never send a scoped stream.close. Reap it so the bb-viewer process +
@@ -58,7 +60,7 @@ export class BrowserViewerStreamer {
58
60
  * partial result. `data.input` / `data.turn` / `data.session_id` come from
59
61
  * MachineBrowserProfileViewerData.
60
62
  */
61
- async handleViewerCommand(profileId, sessionId, command, input, turn) {
63
+ async handleViewerCommand(profileId, sessionId, command, input, turn, execution) {
62
64
  if (!profileId)
63
65
  throw new Error('browser profile id is required');
64
66
  // Reject a kicked viewer's straggler commands (design §3.6 PR7). After a kick
@@ -75,11 +77,11 @@ export class BrowserViewerStreamer {
75
77
  case 'stream.start':
76
78
  return this.viewerStreamStart(profileId, sessionId, turn);
77
79
  case 'stream.answer':
78
- return this.viewerStreamAnswer(profileId, sessionId, input);
80
+ return this.viewerStreamAnswer(profileId, sessionId, input, execution?.deadlineUnixMs);
79
81
  case 'stream.close':
80
82
  return this.viewerStreamClose(profileId, sessionId, input);
81
83
  case 'stream.switch':
82
- return this.viewerStreamSwitch(profileId, sessionId, input);
84
+ return this.viewerStreamSwitch(profileId, sessionId, input, execution?.deadlineUnixMs);
83
85
  case 'kick':
84
86
  return this.viewerKick(profileId, sessionId, input);
85
87
  case 'close':
@@ -145,7 +147,7 @@ export class BrowserViewerStreamer {
145
147
  await this.bringTargetToFront(cdpUrl);
146
148
  const streamer = await this.spawnStreamer(profileId, sessionId, turn);
147
149
  try {
148
- const result = await this.streamerCommand(streamer, 'connect', { cdpUrl });
150
+ const result = await sendBBViewerCommand(streamer.port, 'connect', { cdpUrl });
149
151
  // Tell the client the EXACT tab being streamed so it targets nav commands
150
152
  // (open/back/forward/reload) at the same tab — no client-side guessing.
151
153
  streamer.streamedTabId = targetIdFromCdpUrl(cdpUrl);
@@ -173,18 +175,24 @@ export class BrowserViewerStreamer {
173
175
  * Rejects if the streamer's sessionId no longer matches (a stale viewer
174
176
  * session from a superseded stream.start).
175
177
  */
176
- async viewerStreamAnswer(profileId, sessionId, input) {
178
+ async viewerStreamAnswer(profileId, sessionId, input, deadlineUnixMs) {
177
179
  const streamer = this.streamers.get(profileId);
178
180
  if (!streamer)
179
181
  throw new Error('no active viewer streamer for profile');
180
182
  if (streamer.sessionId !== sessionId)
181
183
  throw new Error('stale viewer session');
182
- // Mark BEFORE the (up to 15s) bb-viewer await: an answer accepted near the
183
- // reap deadline must not be torn down mid-processing by the timer. A failed
184
- // answer leaves the streamer un-reaped, which is fine the client surfaces
185
- // the error and the next stream.start replaces the streamer anyway.
184
+ this.assertViewerExecutionDeadline(deadlineUnixMs, 'before bb-viewer answer');
185
+ // Mark BEFORE the (up to 30s) bb-viewer readiness await: an answer accepted
186
+ // near the reap deadline must not be torn down mid-processing by the timer.
187
+ // A failed answer leaves the streamer un-reaped, which is fine — the client
188
+ // surfaces the typed error and the next stream.start replaces it anyway.
186
189
  streamer.answered = true;
187
- return this.streamerCommand(streamer, 'answer', input ?? {});
190
+ const result = await sendBBViewerCommand(streamer.port, 'answer', input ?? {}, deadlineUnixMs);
191
+ // The fetch promise can settle in the same event-loop turn as its abort
192
+ // timer. Re-check the absolute boundary before acknowledging readiness so a
193
+ // late microtask can never turn an expired command into a false success.
194
+ this.assertViewerExecutionDeadline(deadlineUnixMs, 'after bb-viewer answer');
195
+ return result;
188
196
  }
189
197
  /**
190
198
  * stream.close — best-effort stop the streamer, then kill + remove it. A
@@ -205,7 +213,7 @@ export class BrowserViewerStreamer {
205
213
  return { ok: true, stale: true };
206
214
  }
207
215
  try {
208
- await this.streamerCommand(streamer, 'stop', {});
216
+ await sendBBViewerCommand(streamer.port, 'stop', {});
209
217
  }
210
218
  catch (err) {
211
219
  this.host.log.warn(`[bb-viewer] stop command failed for ${profileId} (killing anyway): ${formatErrorForLog(err)}`);
@@ -223,7 +231,7 @@ export class BrowserViewerStreamer {
223
231
  * the stream.start response), so a session-less switch is by definition not
224
232
  * the current viewer.
225
233
  */
226
- async viewerStreamSwitch(profileId, sessionId, input) {
234
+ async viewerStreamSwitch(profileId, sessionId, input, deadlineUnixMs) {
227
235
  const streamer = this.streamers.get(profileId);
228
236
  if (!streamer)
229
237
  throw new Error('no active viewer streamer for profile');
@@ -233,10 +241,14 @@ export class BrowserViewerStreamer {
233
241
  if (tab === undefined || tab === null || tab === '') {
234
242
  throw new Error('stream.switch requires input.tab');
235
243
  }
244
+ this.assertViewerExecutionDeadline(deadlineUnixMs, 'before resolving the switch target');
236
245
  const cdpUrl = await this.host.withDaemonRecovery(() => this.resolveAccountPageCdpUrl(profileId, tab), `viewer stream.switch ${profileId}`);
246
+ this.assertViewerExecutionDeadline(deadlineUnixMs, 'after resolving the switch target');
237
247
  // Foreground the new tab so Chrome composites it (see viewerStreamStart).
238
- await this.bringTargetToFront(cdpUrl);
239
- const result = await this.streamerCommand(streamer, 'switch', { cdpUrl });
248
+ await this.bringTargetToFront(cdpUrl, deadlineUnixMs);
249
+ this.assertViewerExecutionDeadline(deadlineUnixMs, 'before bb-viewer switch');
250
+ const result = await sendBBViewerCommand(streamer.port, 'switch', { cdpUrl }, deadlineUnixMs);
251
+ this.assertViewerExecutionDeadline(deadlineUnixMs, 'after bb-viewer switch');
240
252
  streamer.streamedTabId = targetIdFromCdpUrl(cdpUrl);
241
253
  return { ...result, streamed_tab_id: streamer.streamedTabId };
242
254
  }
@@ -267,7 +279,7 @@ export class BrowserViewerStreamer {
267
279
  }
268
280
  const cdpUrl = await this.host.withDaemonRecovery(() => this.resolveAccountPageCdpUrl(profileId), `viewer close re-switch ${profileId}`);
269
281
  await this.bringTargetToFront(cdpUrl);
270
- const sw = await this.streamerCommand(streamer, 'switch', { cdpUrl });
282
+ const sw = await sendBBViewerCommand(streamer.port, 'switch', { cdpUrl });
271
283
  streamer.streamedTabId = targetIdFromCdpUrl(cdpUrl);
272
284
  return { ...result, ...sw, streamed_tab_id: streamer.streamedTabId };
273
285
  }
@@ -279,15 +291,19 @@ export class BrowserViewerStreamer {
279
291
  * must not block the stream. host:port + targetId are parsed from the cdpUrl
280
292
  * (`ws://host:port/devtools/page/<targetId>`) to avoid an extra /status call.
281
293
  */
282
- async bringTargetToFront(cdpUrl) {
294
+ async bringTargetToFront(cdpUrl, deadlineUnixMs) {
283
295
  const m = /^ws:\/\/([^/]+)\/devtools\/page\/(.+)$/.exec(cdpUrl);
284
296
  if (!m)
285
297
  return;
286
298
  const [, hostPort, targetId] = m;
299
+ this.assertViewerExecutionDeadline(deadlineUnixMs, 'before foregrounding the switch target');
300
+ const timeoutMs = deadlineUnixMs === undefined
301
+ ? 5_000
302
+ : Math.max(1, Math.min(5_000, deadlineUnixMs - Date.now()));
287
303
  try {
288
304
  const resp = await fetch(`http://${hostPort}/json/activate/${targetId}`, {
289
305
  method: 'GET',
290
- signal: AbortSignal.timeout(5_000),
306
+ signal: AbortSignal.timeout(timeoutMs),
291
307
  });
292
308
  if (!resp.ok) {
293
309
  this.host.log.warn(`[bb-viewer] activate target ${targetId} returned ${resp.status} (continuing)`);
@@ -297,6 +313,11 @@ export class BrowserViewerStreamer {
297
313
  this.host.log.warn(`[bb-viewer] activate target ${targetId} failed (continuing): ${formatErrorForLog(err)}`);
298
314
  }
299
315
  }
316
+ assertViewerExecutionDeadline(deadlineUnixMs, phase) {
317
+ if (deadlineUnixMs !== undefined && Date.now() >= deadlineUnixMs) {
318
+ throw viewerReadinessDeadlineError(phase);
319
+ }
320
+ }
300
321
  /**
301
322
  * Forward a navigation command (tab_list/tab_new/open/reload/back/forward/
302
323
  * close) to bb-browser scoped to the profile's account. This lets the human
@@ -537,35 +558,6 @@ export class BrowserViewerStreamer {
537
558
  killTimer.unref?.();
538
559
  child.once('exit', () => clearTimeout(killTimer));
539
560
  }
540
- /**
541
- * POST a command to the profile's bb-viewer `/command` endpoint. Parses the
542
- * `{result}` / `{error:{message}}` envelope (bb-viewer api.go) and returns
543
- * the inner result, throwing the error message on failure.
544
- */
545
- async streamerCommand(streamer, method, params) {
546
- const controller = new AbortController();
547
- const timer = setTimeout(() => controller.abort(), BB_VIEWER_COMMAND_TIMEOUT_MS);
548
- try {
549
- const resp = await fetch(`http://127.0.0.1:${streamer.port}/command`, {
550
- method: 'POST',
551
- headers: { 'Content-Type': 'application/json' },
552
- body: JSON.stringify({ method, params }),
553
- signal: controller.signal,
554
- });
555
- const text = await resp.text();
556
- const parsed = (text ? JSON.parse(text) : {});
557
- if (parsed.error) {
558
- throw new Error(parsed.error.message || `bb-viewer ${method} failed`);
559
- }
560
- if (!resp.ok) {
561
- throw new Error(`bb-viewer ${method} returned ${resp.status}: ${text}`);
562
- }
563
- return parsed.result ?? {};
564
- }
565
- finally {
566
- clearTimeout(timer);
567
- }
568
- }
569
561
  /**
570
562
  * Kill + remove the profile's bb-viewer streamer, if any. Idempotent. Also
571
563
  * clears any kick marker for the profile: a (re)kill establishes a clean
@@ -58,6 +58,7 @@ export interface ClipProviderOptions {
58
58
  username?: string;
59
59
  credential?: string;
60
60
  };
61
+ dispatchDeadlineUnixMs?: number;
61
62
  }) => Promise<Record<string, unknown>>;
62
63
  }
63
64
  export declare class ClipProvider {
@@ -125,8 +126,8 @@ export declare class ClipProvider {
125
126
  /**
126
127
  * Handle a hosted-browser live-viewer command relayed by clip-service over the
127
128
  * stream and reply on the same stream (design §3.4). Always answers the
128
- * request/reply bridge exactly once — `{result}` on success, `{error:{message}}`
129
- * on failure — and never throws into the message loop, mirroring the BYOC
129
+ * request/reply bridge exactly once — `{result}` on success,
130
+ * `{error:{code?,message}}` on failure — and never throws into the message loop, mirroring the BYOC
130
131
  * daemon's handleBrowserProfileViewer (which replies over HTTP instead).
131
132
  */
132
133
  private handleViewerCommand;
@@ -1 +1 @@
1
- {"version":3,"file":"clip-provider.d.ts","sourceRoot":"","sources":["../../src/clip-runtime/clip-provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"clip-provider.d.ts","sourceRoot":"","sources":["../../src/clip-runtime/clip-provider.ts"],"names":[],"mappings":"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"}
@@ -14,8 +14,10 @@
14
14
  * flags=0x00 data, flags=0x02 end-of-stream (trailers)
15
15
  */
16
16
  import * as http2 from 'node:http2';
17
- import { ClipCommandError } from './process.js';
18
17
  import { isBrowserDependencyName } from './browser-dependency.js';
18
+ import { ClipCommandError } from './process.js';
19
+ import { isViewerReadinessCommand, parseViewerDispatchDeadlineUnixMs, viewerReadinessDeadlineError, } from './viewer-command-deadline.js';
20
+ import { viewerCommandFailure } from './viewer-command-error.js';
19
21
  // ---------------------------------------------------------------------------
20
22
  // Connect envelope helpers
21
23
  // ---------------------------------------------------------------------------
@@ -463,8 +465,8 @@ export class ClipProvider {
463
465
  /**
464
466
  * Handle a hosted-browser live-viewer command relayed by clip-service over the
465
467
  * stream and reply on the same stream (design §3.4). Always answers the
466
- * request/reply bridge exactly once — `{result}` on success, `{error:{message}}`
467
- * on failure — and never throws into the message loop, mirroring the BYOC
468
+ * request/reply bridge exactly once — `{result}` on success,
469
+ * `{error:{code?,message}}` on failure — and never throws into the message loop, mirroring the BYOC
468
470
  * daemon's handleBrowserProfileViewer (which replies over HTTP instead).
469
471
  */
470
472
  async handleViewerCommand(cmd) {
@@ -478,6 +480,10 @@ export class ClipProvider {
478
480
  return;
479
481
  }
480
482
  try {
483
+ const dispatchDeadlineUnixMs = parseViewerDispatchDeadlineUnixMs(cmd.dispatchDeadlineUnixMs);
484
+ if (isViewerReadinessCommand(cmd.command) && dispatchDeadlineUnixMs === undefined) {
485
+ throw viewerReadinessDeadlineError('because the ProviderStream command has no authenticated deadline');
486
+ }
481
487
  let input;
482
488
  if (cmd.input) {
483
489
  const decoded = Buffer.from(cmd.input, 'base64').toString('utf-8');
@@ -494,13 +500,14 @@ export class ClipProvider {
494
500
  command: cmd.command,
495
501
  input,
496
502
  turn: cmd.turn,
503
+ dispatchDeadlineUnixMs,
497
504
  });
498
505
  await this.sendViewerReply(requestId, { result });
499
506
  }
500
507
  catch (err) {
501
- const message = err instanceof Error ? err.message : String(err);
502
- this.opts.log.warn(`[clip-provider] viewer command failed (profile=${cmd.profileId}, command=${cmd.command}): ${message}`);
503
- await this.sendViewerReply(requestId, { error: { message } }).catch(() => { });
508
+ const failure = viewerCommandFailure(err);
509
+ this.opts.log.warn(`[clip-provider] viewer command failed (profile=${cmd.profileId}, command=${cmd.command}): ${failure.message}`);
510
+ await this.sendViewerReply(requestId, { error: failure }).catch(() => { });
504
511
  }
505
512
  }
506
513
  /** Send a hosted-viewer reply (base64-encoded JSON body) on the stream. */