@wenrwa/marketplace-cli 0.4.4 → 0.4.6
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.
- package/dist/__tests__/bridge-activity-parser.test.d.ts +1 -0
- package/dist/__tests__/bridge-activity-parser.test.js +0 -0
- package/dist/__tests__/bridge-activity-tap.test.d.ts +1 -0
- package/dist/__tests__/bridge-activity-tap.test.js +178 -0
- package/dist/__tests__/bridge-api-client.test.d.ts +1 -0
- package/dist/__tests__/bridge-api-client.test.js +69 -0
- package/dist/__tests__/bridge-browser-driver.test.d.ts +1 -0
- package/dist/__tests__/bridge-browser-driver.test.js +379 -0
- package/dist/__tests__/bridge-browser-frames.test.d.ts +1 -0
- package/dist/__tests__/bridge-browser-frames.test.js +166 -0
- package/dist/__tests__/bridge-browser-idle.test.d.ts +1 -0
- package/dist/__tests__/bridge-browser-idle.test.js +259 -0
- package/dist/__tests__/bridge-browser-relay.test.d.ts +1 -0
- package/dist/__tests__/bridge-browser-relay.test.js +670 -0
- package/dist/__tests__/bridge-bundle-installer.test.d.ts +1 -0
- package/dist/__tests__/bridge-bundle-installer.test.js +126 -0
- package/dist/__tests__/bridge-cdp-client.test.d.ts +1 -0
- package/dist/__tests__/bridge-cdp-client.test.js +133 -0
- package/dist/__tests__/bridge-chromium-launcher.test.d.ts +1 -0
- package/dist/__tests__/bridge-chromium-launcher.test.js +202 -0
- package/dist/__tests__/bridge-command-browser-options.test.d.ts +1 -0
- package/dist/__tests__/bridge-command-browser-options.test.js +37 -0
- package/dist/__tests__/bridge-config-mcp.test.js +4 -0
- package/dist/__tests__/bridge-context-manifest-frame.test.d.ts +1 -0
- package/dist/__tests__/bridge-context-manifest-frame.test.js +125 -0
- package/dist/__tests__/bridge-context-writer.test.d.ts +1 -0
- package/dist/__tests__/bridge-context-writer.test.js +161 -0
- package/dist/__tests__/bridge-device-registration.test.d.ts +1 -0
- package/dist/__tests__/bridge-device-registration.test.js +33 -0
- package/dist/__tests__/bridge-folder-picker-runner.test.d.ts +1 -0
- package/dist/__tests__/bridge-folder-picker-runner.test.js +37 -0
- package/dist/__tests__/bridge-folder-picker.test.d.ts +1 -0
- package/dist/__tests__/bridge-folder-picker.test.js +66 -0
- package/dist/__tests__/bridge-folder-registry.test.d.ts +1 -0
- package/dist/__tests__/bridge-folder-registry.test.js +107 -0
- package/dist/__tests__/bridge-frame-pacer.test.d.ts +1 -0
- package/dist/__tests__/bridge-frame-pacer.test.js +102 -0
- package/dist/__tests__/bridge-install-bundle-frame.test.d.ts +1 -0
- package/dist/__tests__/bridge-install-bundle-frame.test.js +107 -0
- package/dist/__tests__/bridge-local-add-core.test.d.ts +1 -0
- package/dist/__tests__/bridge-local-add-core.test.js +48 -0
- package/dist/__tests__/bridge-local-path-validation-fs.test.d.ts +1 -0
- package/dist/__tests__/bridge-local-path-validation-fs.test.js +88 -0
- package/dist/__tests__/bridge-local-path-validation.test.d.ts +1 -0
- package/dist/__tests__/bridge-local-path-validation.test.js +45 -0
- package/dist/__tests__/bridge-login-status.test.d.ts +1 -0
- package/dist/__tests__/bridge-login-status.test.js +60 -0
- package/dist/__tests__/bridge-relay-client.test.d.ts +1 -0
- package/dist/__tests__/bridge-relay-client.test.js +283 -0
- package/dist/__tests__/bridge-relay-mode.test.d.ts +1 -0
- package/dist/__tests__/bridge-relay-mode.test.js +33 -0
- package/dist/__tests__/bridge-relay-pucc14.test.d.ts +1 -0
- package/dist/__tests__/bridge-relay-pucc14.test.js +230 -0
- package/dist/__tests__/bridge-server-local-endpoints.test.d.ts +1 -0
- package/dist/__tests__/bridge-server-local-endpoints.test.js +197 -0
- package/dist/__tests__/bridge-server.test.js +22 -0
- package/dist/__tests__/bridge-workspace-multirepo.test.d.ts +1 -0
- package/dist/__tests__/bridge-workspace-multirepo.test.js +317 -0
- package/dist/__tests__/devices.test.d.ts +1 -0
- package/dist/__tests__/devices.test.js +66 -0
- package/dist/__tests__/local.test.d.ts +1 -0
- package/dist/__tests__/local.test.js +147 -0
- package/dist/bridge/activityParser.d.ts +53 -0
- package/dist/bridge/activityParser.js +202 -0
- package/dist/bridge/apiClient.d.ts +56 -0
- package/dist/bridge/apiClient.js +50 -0
- package/dist/bridge/browserDriver.d.ts +98 -0
- package/dist/bridge/browserDriver.js +265 -0
- package/dist/bridge/browserFrames.d.ts +182 -0
- package/dist/bridge/browserFrames.js +179 -0
- package/dist/bridge/browserIdle.d.ts +75 -0
- package/dist/bridge/browserIdle.js +120 -0
- package/dist/bridge/bundleInstaller.d.ts +31 -0
- package/dist/bridge/bundleInstaller.js +127 -0
- package/dist/bridge/cdpClient.d.ts +47 -0
- package/dist/bridge/cdpClient.js +102 -0
- package/dist/bridge/chromiumLauncher.d.ts +45 -0
- package/dist/bridge/chromiumLauncher.js +113 -0
- package/dist/bridge/config.d.ts +3 -0
- package/dist/bridge/contextWriter.d.ts +31 -0
- package/dist/bridge/contextWriter.js +139 -0
- package/dist/bridge/deviceRegistration.d.ts +28 -0
- package/dist/bridge/deviceRegistration.js +19 -0
- package/dist/bridge/folderPicker.d.ts +34 -0
- package/dist/bridge/folderPicker.js +36 -0
- package/dist/bridge/folderPickerRunner.d.ts +3 -0
- package/dist/bridge/folderPickerRunner.js +25 -0
- package/dist/bridge/folderRegistry.d.ts +19 -0
- package/dist/bridge/folderRegistry.js +100 -0
- package/dist/bridge/framePacer.d.ts +61 -0
- package/dist/bridge/framePacer.js +79 -0
- package/dist/bridge/localAdd.d.ts +28 -0
- package/dist/bridge/localAdd.js +67 -0
- package/dist/bridge/localPathValidation.d.ts +20 -0
- package/dist/bridge/localPathValidation.js +58 -0
- package/dist/bridge/localPathValidationFs.d.ts +2 -0
- package/dist/bridge/localPathValidationFs.js +98 -0
- package/dist/bridge/loginStatus.d.ts +38 -0
- package/dist/bridge/loginStatus.js +56 -0
- package/dist/bridge/realPty.js +6 -2
- package/dist/bridge/relayClient.d.ts +166 -0
- package/dist/bridge/relayClient.js +517 -0
- package/dist/bridge/repoCheckout.d.ts +31 -0
- package/dist/bridge/repoCheckout.js +18 -0
- package/dist/bridge/server.d.ts +33 -0
- package/dist/bridge/server.js +98 -10
- package/dist/bridge/sessionManager.d.ts +18 -0
- package/dist/bridge/sessionManager.js +15 -1
- package/dist/commands/bridge.d.ts +21 -0
- package/dist/commands/bridge.js +194 -1
- package/dist/commands/devices.d.ts +9 -0
- package/dist/commands/devices.js +53 -0
- package/dist/commands/local.d.ts +9 -0
- package/dist/commands/local.js +141 -0
- package/dist/index.js +7 -1
- package/package.json +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* pucc-14 — in-box Claude Code login-validity check (ADR-0028 boundary).
|
|
3
|
+
*
|
|
4
|
+
* The shared container keeps the user's ONE Claude Code login on the volume at
|
|
5
|
+
* CLAUDE_CONFIG_DIR (/data/.claude). The platform needs to know whether that
|
|
6
|
+
* login is currently usable so `GET /me/claude-container` can render
|
|
7
|
+
* connected / needs_relogin — but the credential itself is the USER's and the
|
|
8
|
+
* platform must NEVER read, store, move, or transmit its value (ADR-0031
|
|
9
|
+
* decision 4 / ADR-0028). So the bridge reduces the whole thing to a single
|
|
10
|
+
* BOOLEAN: does a non-expired login exist? It reads ONLY the expiry timestamp
|
|
11
|
+
* out of the credentials file — never the accessToken / refreshToken — and
|
|
12
|
+
* returns true/false. Nothing else ever leaves this function.
|
|
13
|
+
*/
|
|
14
|
+
/** Claude Code writes its OAuth login here under CLAUDE_CONFIG_DIR. */
|
|
15
|
+
export declare const CLAUDE_CREDENTIALS_FILE = ".credentials.json";
|
|
16
|
+
export interface LoginCheckDeps {
|
|
17
|
+
/** CLAUDE_CONFIG_DIR — /data/.claude in the container. */
|
|
18
|
+
claudeDir: string;
|
|
19
|
+
exists: (path: string) => boolean;
|
|
20
|
+
/** Reads + parses the credentials JSON. The caller extracts ONLY the expiry
|
|
21
|
+
* from the result and discards everything else, so the token value is never
|
|
22
|
+
* handled by this module beyond the fs read it cannot avoid. */
|
|
23
|
+
readJson: (path: string) => unknown;
|
|
24
|
+
/** Injectable clock for tests. */
|
|
25
|
+
now?: () => number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Returns true iff a valid, non-expired `claude` login exists on the volume.
|
|
29
|
+
*
|
|
30
|
+
* Existence + expiry ONLY — the token value is never extracted, returned, or
|
|
31
|
+
* logged. Semantics:
|
|
32
|
+
* - credentials file absent → false (never logged in)
|
|
33
|
+
* - unparseable / not an object → false (corrupt → treat as no login)
|
|
34
|
+
* - has a numeric expiry in the past → false (expired / needs re-login)
|
|
35
|
+
* - has a numeric expiry in the future → true
|
|
36
|
+
* - exists but no expiry field → true (existence is the login signal)
|
|
37
|
+
*/
|
|
38
|
+
export declare function checkClaudeLoginValid(deps: LoginCheckDeps): boolean;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* pucc-14 — in-box Claude Code login-validity check (ADR-0028 boundary).
|
|
4
|
+
*
|
|
5
|
+
* The shared container keeps the user's ONE Claude Code login on the volume at
|
|
6
|
+
* CLAUDE_CONFIG_DIR (/data/.claude). The platform needs to know whether that
|
|
7
|
+
* login is currently usable so `GET /me/claude-container` can render
|
|
8
|
+
* connected / needs_relogin — but the credential itself is the USER's and the
|
|
9
|
+
* platform must NEVER read, store, move, or transmit its value (ADR-0031
|
|
10
|
+
* decision 4 / ADR-0028). So the bridge reduces the whole thing to a single
|
|
11
|
+
* BOOLEAN: does a non-expired login exist? It reads ONLY the expiry timestamp
|
|
12
|
+
* out of the credentials file — never the accessToken / refreshToken — and
|
|
13
|
+
* returns true/false. Nothing else ever leaves this function.
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.CLAUDE_CREDENTIALS_FILE = void 0;
|
|
17
|
+
exports.checkClaudeLoginValid = checkClaudeLoginValid;
|
|
18
|
+
/** Claude Code writes its OAuth login here under CLAUDE_CONFIG_DIR. */
|
|
19
|
+
exports.CLAUDE_CREDENTIALS_FILE = '.credentials.json';
|
|
20
|
+
function joinPath(dir, file) {
|
|
21
|
+
return dir.endsWith('/') ? `${dir}${file}` : `${dir}/${file}`;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Returns true iff a valid, non-expired `claude` login exists on the volume.
|
|
25
|
+
*
|
|
26
|
+
* Existence + expiry ONLY — the token value is never extracted, returned, or
|
|
27
|
+
* logged. Semantics:
|
|
28
|
+
* - credentials file absent → false (never logged in)
|
|
29
|
+
* - unparseable / not an object → false (corrupt → treat as no login)
|
|
30
|
+
* - has a numeric expiry in the past → false (expired / needs re-login)
|
|
31
|
+
* - has a numeric expiry in the future → true
|
|
32
|
+
* - exists but no expiry field → true (existence is the login signal)
|
|
33
|
+
*/
|
|
34
|
+
function checkClaudeLoginValid(deps) {
|
|
35
|
+
const credPath = joinPath(deps.claudeDir, exports.CLAUDE_CREDENTIALS_FILE);
|
|
36
|
+
if (!deps.exists(credPath))
|
|
37
|
+
return false;
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = deps.readJson(credPath);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
if (!parsed || typeof parsed !== 'object')
|
|
46
|
+
return false;
|
|
47
|
+
// Claude Code nests the login under `claudeAiOauth`; tolerate a flat shape too.
|
|
48
|
+
const record = parsed;
|
|
49
|
+
const oauth = record.claudeAiOauth ?? record;
|
|
50
|
+
// Read ONLY the expiry. We deliberately never touch accessToken/refreshToken.
|
|
51
|
+
const expiresAt = oauth && typeof oauth.expiresAt === 'number' ? oauth.expiresAt : undefined;
|
|
52
|
+
if (expiresAt === undefined)
|
|
53
|
+
return true; // file present, no expiry → treat as valid
|
|
54
|
+
const now = (deps.now ?? Date.now)();
|
|
55
|
+
return expiresAt > now;
|
|
56
|
+
}
|
package/dist/bridge/realPty.js
CHANGED
|
@@ -68,13 +68,17 @@ function realPtyFactory() {
|
|
|
68
68
|
const pty = require('node-pty');
|
|
69
69
|
const shell = process.env.SHELL || (os.platform() === 'win32' ? 'powershell.exe' : '/bin/bash');
|
|
70
70
|
return {
|
|
71
|
-
spawn: ({ cols, rows, cwd }) => {
|
|
71
|
+
spawn: ({ cols, rows, cwd, env }) => {
|
|
72
72
|
const proc = pty.spawn(shell, [], {
|
|
73
73
|
name: 'xterm-256color',
|
|
74
74
|
cols,
|
|
75
75
|
rows,
|
|
76
76
|
cwd: cwd || os.homedir(),
|
|
77
|
-
|
|
77
|
+
// pucc-03: per-session env (WENRWA_WORKSPACE_ID / HT_AUTONOMOUS) is
|
|
78
|
+
// merged OVER the inherited process env, so one shared container can
|
|
79
|
+
// give each terminal its own workspace context without a machine-wide
|
|
80
|
+
// value. CLAUDE_CONFIG_DIR is inherited unchanged (shared ~/.claude).
|
|
81
|
+
env: { ...process.env, ...(env ?? {}) },
|
|
78
82
|
});
|
|
79
83
|
return {
|
|
80
84
|
write: (data) => proc.write(data),
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { SessionManager } from './sessionManager';
|
|
2
|
+
import { BrowserDriver } from './browserDriver';
|
|
3
|
+
import { BrowserIdleTracker } from './browserIdle';
|
|
4
|
+
/** pucc-04 workspace-scoped git credential, resolved + injected by the relay. */
|
|
5
|
+
export interface InjectedGitCredential {
|
|
6
|
+
token: string;
|
|
7
|
+
repoFullName: string;
|
|
8
|
+
expiresAt?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* pucc-14 — assemble the per-session PTY env for a workspace-scoped `open`.
|
|
12
|
+
*
|
|
13
|
+
* Pure + exported so the env contract is unit-tested without a socket. Merges
|
|
14
|
+
* the relay-injected `env` (which already carries WENRWA_WORKSPACE_ID +
|
|
15
|
+
* WENRWA_CONNECT_TOKEN) and layers on:
|
|
16
|
+
* - WENRWA_WORKSPACE_ID — fallback if the relay didn't pre-set it in `env`.
|
|
17
|
+
* - WENRWA_CONNECT_TOKEN — the workspace-bound Connect Token (MCP world-wiring).
|
|
18
|
+
* - HT_AUTONOMOUS — per-session: `claude` vs `claude --dangerously-skip-permissions`.
|
|
19
|
+
* - WENRWA_GIT_TOKEN / WENRWA_GIT_REPO — the workspace git credential, read by
|
|
20
|
+
* git-credential-wenrwa for clone-on-demand + in-terminal git (per-workspace,
|
|
21
|
+
* no backend round-trip). The token rides the PTY env only; it is never
|
|
22
|
+
* logged here.
|
|
23
|
+
*/
|
|
24
|
+
export declare function assembleSessionEnv(frame: {
|
|
25
|
+
workspaceId?: string;
|
|
26
|
+
autonomous?: boolean;
|
|
27
|
+
connectToken?: string;
|
|
28
|
+
gitCredential?: InjectedGitCredential;
|
|
29
|
+
env?: Record<string, string>;
|
|
30
|
+
}): Record<string, string>;
|
|
31
|
+
/** Minimal surface relayClient needs from a socket — lets tests inject fakes if ever needed. */
|
|
32
|
+
export interface WebSocketLike {
|
|
33
|
+
readyState: number;
|
|
34
|
+
send(data: string): void;
|
|
35
|
+
close(code?: number, reason?: string): void;
|
|
36
|
+
on(event: 'open' | 'message' | 'close' | 'error', cb: (...args: any[]) => void): void;
|
|
37
|
+
}
|
|
38
|
+
export interface BackoffOpts {
|
|
39
|
+
/** First retry delay in ms (before jitter). Default 250. */
|
|
40
|
+
initialMs?: number;
|
|
41
|
+
/** Cap on the backoff ceiling. Default 10_000. */
|
|
42
|
+
maxMs?: number;
|
|
43
|
+
/** Multiplier per attempt. Default 2. */
|
|
44
|
+
factor?: number;
|
|
45
|
+
/** Returns a value in [0, 1); overridable for deterministic tests. Default Math.random. */
|
|
46
|
+
jitter?: () => number;
|
|
47
|
+
}
|
|
48
|
+
export interface RelayClientOpts {
|
|
49
|
+
relayUrl: string;
|
|
50
|
+
relayToken: string;
|
|
51
|
+
sessions: SessionManager;
|
|
52
|
+
/**
|
|
53
|
+
* pucc-03 (ADR-0031 model B): resolve a workspace to the local checkout the
|
|
54
|
+
* terminal should open in, cloning on demand the first time (see
|
|
55
|
+
* ensureWorkspaceRepo). Returns the cwd, or null to fall back to the shell's
|
|
56
|
+
* default home dir. Absent → workspace-scoped opens still set
|
|
57
|
+
* WENRWA_WORKSPACE_ID but land in the default cwd.
|
|
58
|
+
*/
|
|
59
|
+
resolveWorkspaceCwd?: (opts: {
|
|
60
|
+
workspaceId: string;
|
|
61
|
+
repoUrl?: string;
|
|
62
|
+
}) => Promise<string | null>;
|
|
63
|
+
/**
|
|
64
|
+
* pucc-int-04 (ADR-0032): install a forged crew `.claude` bundle (Forge
|
|
65
|
+
* format=map FileMap) into `/data/repos/<workspaceId>`. Path-safe + idempotent
|
|
66
|
+
* (see bundleInstaller.installBundle). Absent → an `install-bundle` frame is
|
|
67
|
+
* answered with an error (legacy / local bridge has no workspace checkouts).
|
|
68
|
+
* This does NOT run any crew engine — it only writes files.
|
|
69
|
+
*/
|
|
70
|
+
installBundle?: (bundle: {
|
|
71
|
+
workspaceId: string;
|
|
72
|
+
files: Record<string, string>;
|
|
73
|
+
}) => {
|
|
74
|
+
written: string[];
|
|
75
|
+
skipped: Array<{
|
|
76
|
+
path: string;
|
|
77
|
+
reason: string;
|
|
78
|
+
}>;
|
|
79
|
+
} | void;
|
|
80
|
+
/**
|
|
81
|
+
* pucc-int-01 (ADR-0032 / ADR-0028): write the arena-pushed context manifest
|
|
82
|
+
* into a fenced managed region of `/data/repos/<workspaceId>/CLAUDE.md`
|
|
83
|
+
* (path-safe + idempotent — see contextWriter.writeContext); empty `content`
|
|
84
|
+
* removes the region. Absent → a `context-manifest` frame is answered with an
|
|
85
|
+
* error (legacy / local bridge has no workspace checkouts). This opens NO PTY
|
|
86
|
+
* and does NOT feed Claude Code via keystrokes — the context arrives as a FILE.
|
|
87
|
+
*/
|
|
88
|
+
writeContext?: (manifest: {
|
|
89
|
+
workspaceId: string;
|
|
90
|
+
content: string;
|
|
91
|
+
}) => {
|
|
92
|
+
action: string;
|
|
93
|
+
claudeMdPath: string | null;
|
|
94
|
+
} | void;
|
|
95
|
+
/** Injectable for tests: defaults to `new WebSocket(url)` from `ws`. */
|
|
96
|
+
wsFactory?: (url: string) => WebSocketLike;
|
|
97
|
+
backoff?: BackoffOpts;
|
|
98
|
+
/** Injectable timer so backoff tests never wait on a real clock. */
|
|
99
|
+
setTimeoutFn?: (cb: () => void, ms: number) => unknown;
|
|
100
|
+
clearTimeoutFn?: (handle: unknown) => void;
|
|
101
|
+
/**
|
|
102
|
+
* pucc-14 login_valid report: returns whether a valid, non-expired `claude`
|
|
103
|
+
* login exists on the volume — a BOOLEAN only, never the token (see
|
|
104
|
+
* loginStatus.checkClaudeLoginValid). Absent → no login-status frame is ever
|
|
105
|
+
* emitted (legacy / local bridge). Present → the bridge emits `login-status`
|
|
106
|
+
* on connect and whenever the boolean changes.
|
|
107
|
+
*/
|
|
108
|
+
checkLoginValid?: () => boolean;
|
|
109
|
+
/** Poll interval for re-checking login validity (default 30_000ms). */
|
|
110
|
+
loginPollMs?: number;
|
|
111
|
+
/**
|
|
112
|
+
* pucc-int-03 (ADR-0032): observe PTY output for Claude Code tool-use and
|
|
113
|
+
* emit a display-only `activity` frame ({ filePaths, thinking }) the relay
|
|
114
|
+
* broadcasts as `terminal:event` on the workspace room — driving the arena's
|
|
115
|
+
* drones/holograms from the agent's real work. This is a READ-ONLY tap that
|
|
116
|
+
* runs ALONGSIDE the browser forwarding: it never alters the `data` frames the
|
|
117
|
+
* pane receives (ADR-0028), and a parse miss/crash yields no frame — it can
|
|
118
|
+
* never break the terminal. Default ON. Set false for a plain (non-Claude)
|
|
119
|
+
* shell where activity has no meaning.
|
|
120
|
+
*/
|
|
121
|
+
emitActivity?: boolean;
|
|
122
|
+
/** Min ms between activity frames per session (coalesces bursts). Default 1000. */
|
|
123
|
+
activityThrottleMs?: number;
|
|
124
|
+
/** Injectable clock for the activity throttle (tests). Default Date.now. */
|
|
125
|
+
nowFn?: () => number;
|
|
126
|
+
/** Injectable interval timer so the login poll is deterministic in tests. */
|
|
127
|
+
setIntervalFn?: (cb: () => void, ms: number) => unknown;
|
|
128
|
+
clearIntervalFn?: (handle: unknown) => void;
|
|
129
|
+
/**
|
|
130
|
+
* cbs-02: create the (single, session-keyed) browser driver for a
|
|
131
|
+
* `browser-open` frame's sessionId. Absent → `browser-open` is answered
|
|
132
|
+
* with an error (legacy / local bridge, or a bridge build without
|
|
133
|
+
* Chromium). This never opens or touches a PTY session — see the
|
|
134
|
+
* `browser-open`/`browser-input` cases below.
|
|
135
|
+
*/
|
|
136
|
+
createBrowserDriver?: (args: {
|
|
137
|
+
sessionId: string;
|
|
138
|
+
}) => BrowserDriver;
|
|
139
|
+
/**
|
|
140
|
+
* cbs-06: create the per-session idle tracker (browserIdle.ts) alongside a
|
|
141
|
+
* freshly-created browser driver — mirrors createBrowserDriver's injection
|
|
142
|
+
* shape exactly. Absent → no idle auto-close is attempted (legacy / local
|
|
143
|
+
* bridge, or a caller that doesn't want it; browser-open/input/sleep still
|
|
144
|
+
* all work normally). `onIdle` fires once both liveness signals
|
|
145
|
+
* (browser-input, browser-frame-ack) have been stale past the tracker's
|
|
146
|
+
* own threshold; handled exactly like an incoming `browser-sleep` except
|
|
147
|
+
* the emitted browser-state's reason is 'idle-timeout' instead of 'sleep'.
|
|
148
|
+
*/
|
|
149
|
+
createBrowserIdleTracker?: (args: {
|
|
150
|
+
sessionId: string;
|
|
151
|
+
onIdle: () => void;
|
|
152
|
+
}) => BrowserIdleTracker;
|
|
153
|
+
/** Test/observability hooks. */
|
|
154
|
+
onConnect?: () => void;
|
|
155
|
+
onDisconnect?: (info: {
|
|
156
|
+
code?: number;
|
|
157
|
+
reason?: string;
|
|
158
|
+
}) => void;
|
|
159
|
+
onReconnectScheduled?: (delayMs: number) => void;
|
|
160
|
+
}
|
|
161
|
+
export interface RelayClientHandle {
|
|
162
|
+
/** Stop reconnecting and close the current socket. Sessions are untouched — they live in SessionManager. */
|
|
163
|
+
close(): void;
|
|
164
|
+
isConnected(): boolean;
|
|
165
|
+
}
|
|
166
|
+
export declare function startRelayClient(opts: RelayClientOpts): RelayClientHandle;
|