local-browser-bridge 0.1.0
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/README.md +724 -0
- package/dist/package.json +61 -0
- package/dist/src/browser/chrome.d.ts +19 -0
- package/dist/src/browser/chrome.js +778 -0
- package/dist/src/browser/index.d.ts +3 -0
- package/dist/src/browser/index.js +25 -0
- package/dist/src/browser/safari.d.ts +41 -0
- package/dist/src/browser/safari.js +827 -0
- package/dist/src/browser-attach-ux-helper.d.ts +39 -0
- package/dist/src/browser-attach-ux-helper.js +157 -0
- package/dist/src/capabilities.d.ts +3 -0
- package/dist/src/capabilities.js +182 -0
- package/dist/src/chrome-relay-error-helper.d.ts +19 -0
- package/dist/src/chrome-relay-error-helper.js +78 -0
- package/dist/src/chrome-relay-helper-cli.d.ts +2 -0
- package/dist/src/chrome-relay-helper-cli.js +97 -0
- package/dist/src/chrome-relay-helper.d.ts +29 -0
- package/dist/src/chrome-relay-helper.js +151 -0
- package/dist/src/chrome-relay-state.d.ts +23 -0
- package/dist/src/chrome-relay-state.js +108 -0
- package/dist/src/claude-code.d.ts +20 -0
- package/dist/src/claude-code.js +66 -0
- package/dist/src/cli-reference-adapter.d.ts +13 -0
- package/dist/src/cli-reference-adapter.js +48 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.js +200 -0
- package/dist/src/codex.d.ts +17 -0
- package/dist/src/codex.js +25 -0
- package/dist/src/connection-ux.d.ts +61 -0
- package/dist/src/connection-ux.js +256 -0
- package/dist/src/errors.d.ts +12 -0
- package/dist/src/errors.js +58 -0
- package/dist/src/http-reference-adapter.d.ts +34 -0
- package/dist/src/http-reference-adapter.js +61 -0
- package/dist/src/http.d.ts +3 -0
- package/dist/src/http.js +161 -0
- package/dist/src/index.d.ts +17 -0
- package/dist/src/index.js +43 -0
- package/dist/src/mcp-stdio.d.ts +2 -0
- package/dist/src/mcp-stdio.js +10 -0
- package/dist/src/mcp.d.ts +25 -0
- package/dist/src/mcp.js +483 -0
- package/dist/src/reference-adapter.d.ts +32 -0
- package/dist/src/reference-adapter.js +42 -0
- package/dist/src/service/attach-service.d.ts +28 -0
- package/dist/src/service/attach-service.js +272 -0
- package/dist/src/session-metadata.d.ts +4 -0
- package/dist/src/session-metadata.js +88 -0
- package/dist/src/store/session-store.d.ts +14 -0
- package/dist/src/store/session-store.js +52 -0
- package/dist/src/target.d.ts +9 -0
- package/dist/src/target.js +61 -0
- package/dist/src/types.d.ts +397 -0
- package/dist/src/types.js +2 -0
- package/dist/tests/attach-service.test.d.ts +1 -0
- package/dist/tests/attach-service.test.js +1367 -0
- package/dist/tests/browser-attach-ux-helper.test.d.ts +1 -0
- package/dist/tests/browser-attach-ux-helper.test.js +139 -0
- package/dist/tests/chrome-relay-error-helper.test.d.ts +1 -0
- package/dist/tests/chrome-relay-error-helper.test.js +67 -0
- package/dist/tests/chrome-relay-helper.test.d.ts +1 -0
- package/dist/tests/chrome-relay-helper.test.js +142 -0
- package/dist/tests/chrome-relay-state-schema.test.d.ts +1 -0
- package/dist/tests/chrome-relay-state-schema.test.js +96 -0
- package/dist/tests/claude-code-wrapper.test.d.ts +1 -0
- package/dist/tests/claude-code-wrapper.test.js +170 -0
- package/dist/tests/codex.test.d.ts +1 -0
- package/dist/tests/codex.test.js +210 -0
- package/dist/tests/demo-client-smoke.test.d.ts +1 -0
- package/dist/tests/demo-client-smoke.test.js +405 -0
- package/dist/tests/docs-fixtures.test.d.ts +1 -0
- package/dist/tests/docs-fixtures.test.js +255 -0
- package/dist/tests/doctor-connect-wrapper.test.d.ts +1 -0
- package/dist/tests/doctor-connect-wrapper.test.js +62 -0
- package/dist/tests/fixtures/doctor-connect-cli-stub.d.ts +1 -0
- package/dist/tests/fixtures/doctor-connect-cli-stub.js +93 -0
- package/dist/tests/fixtures/public-root-cli-stub.d.ts +210 -0
- package/dist/tests/fixtures/public-root-cli-stub.js +143 -0
- package/dist/tests/fixtures/public-root-consumer.js +67 -0
- package/dist/tests/mcp.test.d.ts +1 -0
- package/dist/tests/mcp.test.js +345 -0
- package/dist/tests/public-consumer-helpers.test.d.ts +1 -0
- package/dist/tests/public-consumer-helpers.test.js +33 -0
- package/dist/tests/public-package-git-consumption.test.d.ts +1 -0
- package/dist/tests/public-package-git-consumption.test.js +56 -0
- package/dist/tests/public-root-consumer-smoke.test.d.ts +1 -0
- package/dist/tests/public-root-consumer-smoke.test.js +214 -0
- package/dist/tests/reference-adapter.test.d.ts +1 -0
- package/dist/tests/reference-adapter.test.js +220 -0
- package/dist/tests/transport-reference-adapters.test.d.ts +1 -0
- package/dist/tests/transport-reference-adapters.test.js +214 -0
- package/package.json +61 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const promises_1 = require("node:fs/promises");
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const node_test_1 = __importDefault(require("node:test"));
|
|
9
|
+
const node_path_1 = require("node:path");
|
|
10
|
+
async function readJson(path) {
|
|
11
|
+
return JSON.parse(await (0, promises_1.readFile)(path, "utf8"));
|
|
12
|
+
}
|
|
13
|
+
(0, node_test_1.default)("documentation fixtures preserve the stable contract examples", async () => {
|
|
14
|
+
const root = process.cwd();
|
|
15
|
+
const capabilities = await readJson((0, node_path_1.resolve)(root, "examples", "capabilities.example.json"));
|
|
16
|
+
strict_1.default.equal(capabilities.capabilities.schemaVersion, 1);
|
|
17
|
+
strict_1.default.equal(capabilities.capabilities.product.summary, "Reusable, agent-agnostic local browser bridge with honest capability signaling. Safari is actionable; Chrome/Chromium is read-only in v1.");
|
|
18
|
+
const safari = capabilities.capabilities.browsers.find((browser) => browser.browser === "safari");
|
|
19
|
+
const chrome = capabilities.capabilities.browsers.find((browser) => browser.browser === "chrome");
|
|
20
|
+
strict_1.default.ok(safari);
|
|
21
|
+
strict_1.default.ok(chrome);
|
|
22
|
+
strict_1.default.equal(safari.kind, "safari-actionable");
|
|
23
|
+
strict_1.default.equal(safari.attachModes?.[0]?.mode, "direct");
|
|
24
|
+
strict_1.default.equal(safari.attachModes?.[0]?.source, "user-browser");
|
|
25
|
+
strict_1.default.equal(safari.attachModes?.[0]?.scope, "browser");
|
|
26
|
+
strict_1.default.equal(safari.operations.resumeSession, true);
|
|
27
|
+
strict_1.default.equal(safari.operations.activate, true);
|
|
28
|
+
strict_1.default.equal(safari.operations.navigate, true);
|
|
29
|
+
strict_1.default.equal(safari.operations.screenshot, true);
|
|
30
|
+
strict_1.default.equal(chrome.kind, "chrome-readonly");
|
|
31
|
+
strict_1.default.match(chrome.bridge.implementation, /read-only in v1/i);
|
|
32
|
+
strict_1.default.equal(chrome.attachModes?.[0]?.mode, "direct");
|
|
33
|
+
strict_1.default.equal(chrome.attachModes?.[1]?.mode, "relay");
|
|
34
|
+
strict_1.default.equal(chrome.attachModes?.[1]?.scope, "tab");
|
|
35
|
+
strict_1.default.equal(chrome.operations.resumeSession, true);
|
|
36
|
+
strict_1.default.equal(chrome.operations.activate, false);
|
|
37
|
+
strict_1.default.equal(chrome.operations.navigate, false);
|
|
38
|
+
strict_1.default.equal(chrome.operations.screenshot, false);
|
|
39
|
+
const safariSession = await readJson((0, node_path_1.resolve)(root, "examples", "session.safari-actionable.example.json"));
|
|
40
|
+
strict_1.default.equal(safariSession.session.schemaVersion, 1);
|
|
41
|
+
strict_1.default.equal(safariSession.session.kind, "safari-actionable");
|
|
42
|
+
strict_1.default.equal(safariSession.session.attach.mode, "direct");
|
|
43
|
+
strict_1.default.equal(safariSession.session.attach.scope, "browser");
|
|
44
|
+
strict_1.default.equal(safariSession.session.semantics.inspect, "browser-tabs");
|
|
45
|
+
strict_1.default.equal(safariSession.session.semantics.resume, "saved-browser-target");
|
|
46
|
+
strict_1.default.equal(safariSession.session.semantics.tabReference.windowIndex, "browser-position");
|
|
47
|
+
strict_1.default.equal(safariSession.session.status.state, "actionable");
|
|
48
|
+
strict_1.default.equal(safariSession.session.status.canAct, true);
|
|
49
|
+
strict_1.default.equal(safariSession.session.capabilities.resume, true);
|
|
50
|
+
strict_1.default.equal(safariSession.session.capabilities.activate, true);
|
|
51
|
+
strict_1.default.equal(safariSession.session.capabilities.navigate, true);
|
|
52
|
+
strict_1.default.equal(safariSession.session.capabilities.screenshot, true);
|
|
53
|
+
const chromeSession = await readJson((0, node_path_1.resolve)(root, "examples", "session.chrome-readonly.example.json"));
|
|
54
|
+
strict_1.default.equal(chromeSession.session.schemaVersion, 1);
|
|
55
|
+
strict_1.default.equal(chromeSession.session.kind, "chrome-readonly");
|
|
56
|
+
strict_1.default.equal(chromeSession.session.attach.mode, "direct");
|
|
57
|
+
strict_1.default.equal(chromeSession.session.attach.source, "user-browser");
|
|
58
|
+
strict_1.default.equal(chromeSession.session.semantics.inspect, "browser-tabs");
|
|
59
|
+
strict_1.default.equal(chromeSession.session.semantics.resume, "saved-browser-target");
|
|
60
|
+
strict_1.default.equal(chromeSession.session.semantics.tabReference.tabIndex, "browser-position");
|
|
61
|
+
strict_1.default.equal(chromeSession.session.status.state, "read-only");
|
|
62
|
+
strict_1.default.equal(chromeSession.session.status.canAct, false);
|
|
63
|
+
strict_1.default.equal(chromeSession.session.capabilities.resume, true);
|
|
64
|
+
strict_1.default.equal(chromeSession.session.capabilities.activate, false);
|
|
65
|
+
strict_1.default.equal(chromeSession.session.capabilities.navigate, false);
|
|
66
|
+
strict_1.default.equal(chromeSession.session.capabilities.screenshot, false);
|
|
67
|
+
const chromeRelaySession = await readJson((0, node_path_1.resolve)(root, "examples", "session.chrome-relay-readonly.example.json"));
|
|
68
|
+
strict_1.default.equal(chromeRelaySession.session.schemaVersion, 1);
|
|
69
|
+
strict_1.default.equal(chromeRelaySession.session.kind, "chrome-readonly");
|
|
70
|
+
strict_1.default.equal(chromeRelaySession.session.attach.mode, "relay");
|
|
71
|
+
strict_1.default.equal(chromeRelaySession.session.attach.source, "extension-relay");
|
|
72
|
+
strict_1.default.equal(chromeRelaySession.session.attach.scope, "tab");
|
|
73
|
+
strict_1.default.equal(chromeRelaySession.session.attach.resumeRequiresUserGesture, true);
|
|
74
|
+
strict_1.default.equal(chromeRelaySession.session.semantics.inspect, "shared-tab-only");
|
|
75
|
+
strict_1.default.equal(chromeRelaySession.session.semantics.resume, "current-shared-tab");
|
|
76
|
+
strict_1.default.equal(chromeRelaySession.session.semantics.tabReference.windowIndex, "synthetic-shared-tab-position");
|
|
77
|
+
strict_1.default.match(chromeRelaySession.session.semantics.notes?.[0] ?? "", /last tab explicitly shared/i);
|
|
78
|
+
strict_1.default.equal(chromeRelaySession.session.status.state, "read-only");
|
|
79
|
+
strict_1.default.equal(chromeRelaySession.session.status.canAct, false);
|
|
80
|
+
strict_1.default.equal(chromeRelaySession.session.capabilities.resume, true);
|
|
81
|
+
strict_1.default.equal(chromeRelaySession.session.capabilities.activate, false);
|
|
82
|
+
strict_1.default.equal(chromeRelaySession.session.capabilities.navigate, false);
|
|
83
|
+
strict_1.default.equal(chromeRelaySession.session.capabilities.screenshot, false);
|
|
84
|
+
const chromeRelayError = await readJson((0, node_path_1.resolve)(root, "examples", "error.chrome-relay-share-required.example.json"));
|
|
85
|
+
strict_1.default.equal(chromeRelayError.error.code, "relay_share_required");
|
|
86
|
+
strict_1.default.equal(chromeRelayError.error.statusCode, 503);
|
|
87
|
+
strict_1.default.equal(chromeRelayError.error.details.context.browser, "chrome");
|
|
88
|
+
strict_1.default.equal(chromeRelayError.error.details.context.attachMode, "relay");
|
|
89
|
+
strict_1.default.equal(chromeRelayError.error.details.context.operation, "attach");
|
|
90
|
+
strict_1.default.equal(chromeRelayError.error.details.relay.branch, "share-tab");
|
|
91
|
+
strict_1.default.equal(chromeRelayError.error.details.relay.retryable, true);
|
|
92
|
+
strict_1.default.equal(chromeRelayError.error.details.relay.userActionRequired, true);
|
|
93
|
+
strict_1.default.equal(chromeRelayError.error.details.relay.phase, "diagnostics");
|
|
94
|
+
strict_1.default.equal(chromeRelayError.error.details.relay.sharedTabScope, "current-shared-tab");
|
|
95
|
+
});
|
|
96
|
+
(0, node_test_1.default)("consumer sample stays aligned with the stable contract guidance", async () => {
|
|
97
|
+
const root = process.cwd();
|
|
98
|
+
const sample = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "examples", "clients", "http-node.ts"), "utf8");
|
|
99
|
+
const httpConsumer = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "examples", "clients", "http-consumer.ts"), "utf8");
|
|
100
|
+
const cliConsumer = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "examples", "clients", "cli-consumer.ts"), "utf8");
|
|
101
|
+
const doctorConnectWrapper = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "examples", "clients", "doctor-connect-wrapper.ts"), "utf8");
|
|
102
|
+
const claudeCodeInstalledPackageMcpConfig = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "examples", "mcp", "claude-code.installed-package.mcp.json"), "utf8");
|
|
103
|
+
const genericRepoCheckoutMcpConfig = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "examples", "mcp", "generic-stdio.repo-checkout.json"), "utf8");
|
|
104
|
+
const consumerGuide = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "docs", "consuming-the-bridge.md"), "utf8");
|
|
105
|
+
const adapterPatterns = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "docs", "adapter-patterns.md"), "utf8");
|
|
106
|
+
const readme = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "README.md"), "utf8");
|
|
107
|
+
strict_1.default.match(sample, /schemaVersion !== 1/);
|
|
108
|
+
strict_1.default.match(sample, /chrome-direct/);
|
|
109
|
+
strict_1.default.match(sample, /chrome-relay/);
|
|
110
|
+
strict_1.default.match(sample, /\/v1\/diagnostics\?browser=/);
|
|
111
|
+
strict_1.default.match(sample, /Safari \(actionable\)/);
|
|
112
|
+
strict_1.default.match(sample, /Chrome \(direct, read-only\)/);
|
|
113
|
+
strict_1.default.match(sample, /Chrome \(shared tab, read-only\)/);
|
|
114
|
+
strict_1.default.match(sample, /Chrome direct attach needs a local DevTools endpoint/);
|
|
115
|
+
strict_1.default.match(sample, /Chrome relay only works for a tab you explicitly share/);
|
|
116
|
+
strict_1.default.match(sample, /does not silently fall back between Chrome direct and relay/);
|
|
117
|
+
strict_1.default.match(sample, /Derive relay behavior from attach\.mode=relay plus the returned semantics fields\./);
|
|
118
|
+
strict_1.default.match(sample, /Tab reference semantics: windowIndex=/);
|
|
119
|
+
strict_1.default.match(sample, /Relay failure branch:/);
|
|
120
|
+
strict_1.default.match(sample, /Relay user prompt:/);
|
|
121
|
+
strict_1.default.match(sample, /sharedTabScope\?: "current-shared-tab"/);
|
|
122
|
+
strict_1.default.match(sample, /LOCAL_BROWSER_BRIDGE_SESSION_ID/);
|
|
123
|
+
strict_1.default.match(sample, /Hide activate\/navigate\/screenshot\./);
|
|
124
|
+
strict_1.default.match(sample, /require\("\.\.\/\.\.\/dist\/src"\) as typeof import\("\.\.\/\.\.\/src"\)/);
|
|
125
|
+
strict_1.default.match(httpConsumer, /createHttpBridgeAdapter/);
|
|
126
|
+
strict_1.default.match(httpConsumer, /connectViaBridge/);
|
|
127
|
+
strict_1.default.match(httpConsumer, /interpretBrowserAttachUxFromError/);
|
|
128
|
+
strict_1.default.match(httpConsumer, /chrome-direct/);
|
|
129
|
+
strict_1.default.match(httpConsumer, /chrome-relay/);
|
|
130
|
+
strict_1.default.match(httpConsumer, /LOCAL_BROWSER_BRIDGE_SESSION_ID/);
|
|
131
|
+
strict_1.default.match(httpConsumer, /transport: http/);
|
|
132
|
+
strict_1.default.match(cliConsumer, /createCliBridgeAdapter/);
|
|
133
|
+
strict_1.default.match(cliConsumer, /connectViaBridge/);
|
|
134
|
+
strict_1.default.match(cliConsumer, /interpretBrowserAttachUxFromError/);
|
|
135
|
+
strict_1.default.match(cliConsumer, /chrome-direct/);
|
|
136
|
+
strict_1.default.match(cliConsumer, /chrome-relay/);
|
|
137
|
+
strict_1.default.match(cliConsumer, /LOCAL_BROWSER_BRIDGE_SESSION_ID/);
|
|
138
|
+
strict_1.default.match(cliConsumer, /transport: cli/);
|
|
139
|
+
strict_1.default.match(doctorConnectWrapper, /runBridgeJson<DoctorPayload>\(\["doctor"/);
|
|
140
|
+
strict_1.default.match(doctorConnectWrapper, /runBridgeJson<ConnectPayload>\(\["connect"/);
|
|
141
|
+
strict_1.default.match(doctorConnectWrapper, /LOCAL_BROWSER_BRIDGE_SESSION_ID/);
|
|
142
|
+
strict_1.default.match(doctorConnectWrapper, /LOCAL_BROWSER_BRIDGE_BIN/);
|
|
143
|
+
strict_1.default.match(doctorConnectWrapper, /wrapper: "doctor-connect"/);
|
|
144
|
+
strict_1.default.match(doctorConnectWrapper, /outcome: "success"/);
|
|
145
|
+
strict_1.default.match(doctorConnectWrapper, /category: "session-connected"/);
|
|
146
|
+
strict_1.default.match(doctorConnectWrapper, /payload\.reason/);
|
|
147
|
+
strict_1.default.match(doctorConnectWrapper, /"chrome-relay"/);
|
|
148
|
+
strict_1.default.match(doctorConnectWrapper, /"safari"/);
|
|
149
|
+
strict_1.default.match(doctorConnectWrapper, /sharedTabScoped/);
|
|
150
|
+
strict_1.default.match(doctorConnectWrapper, /suggestedActions/);
|
|
151
|
+
strict_1.default.match(claudeCodeInstalledPackageMcpConfig, /node_modules\/\.bin\/local-browser-bridge-mcp/);
|
|
152
|
+
strict_1.default.doesNotMatch(claudeCodeInstalledPackageMcpConfig, /dist\/src\/mcp-stdio\.js/);
|
|
153
|
+
strict_1.default.match(genericRepoCheckoutMcpConfig, /"command": "node"/);
|
|
154
|
+
strict_1.default.match(genericRepoCheckoutMcpConfig, /dist\/src\/mcp-stdio\.js/);
|
|
155
|
+
strict_1.default.doesNotMatch(genericRepoCheckoutMcpConfig, /node_modules\/\.bin\/local-browser-bridge-mcp/);
|
|
156
|
+
strict_1.default.match(consumerGuide, /src\/index\.ts/);
|
|
157
|
+
strict_1.default.match(consumerGuide, /import \{ interpretChromeRelayFailure \} from "\.\.\/src"/);
|
|
158
|
+
strict_1.default.match(consumerGuide, /interpretBrowserAttachUxFromSession[\s\S]*from "\.\.\/src"/);
|
|
159
|
+
strict_1.default.match(consumerGuide, /Chrome relay parity example/);
|
|
160
|
+
strict_1.default.match(consumerGuide, /Adapter Patterns/);
|
|
161
|
+
strict_1.default.match(consumerGuide, /\.\/adapter-patterns\.md/);
|
|
162
|
+
strict_1.default.match(consumerGuide, /schema\/chrome-relay-error\.schema\.json/);
|
|
163
|
+
strict_1.default.match(consumerGuide, /examples\/error\.chrome-relay-share-required\.example\.json/);
|
|
164
|
+
strict_1.default.match(consumerGuide, /attach --browser chrome --attach-mode relay/);
|
|
165
|
+
strict_1.default.match(consumerGuide, /"attach":\{"mode":"relay"\}/);
|
|
166
|
+
strict_1.default.match(consumerGuide, /session\.attach/);
|
|
167
|
+
strict_1.default.match(consumerGuide, /session\.semantics/);
|
|
168
|
+
strict_1.default.match(consumerGuide, /error\.details\.relay\.branch/);
|
|
169
|
+
strict_1.default.match(consumerGuide, /error\.details\.relay\.sharedTabScope = "current-shared-tab"/);
|
|
170
|
+
strict_1.default.match(consumerGuide, /interpretChromeRelayFailure/);
|
|
171
|
+
strict_1.default.match(consumerGuide, /retryable/);
|
|
172
|
+
strict_1.default.match(consumerGuide, /examples\/clients\/http-consumer\.ts/);
|
|
173
|
+
strict_1.default.match(consumerGuide, /examples\/clients\/cli-consumer\.ts/);
|
|
174
|
+
strict_1.default.match(consumerGuide, /examples\/clients\/doctor-connect-wrapper\.ts/);
|
|
175
|
+
strict_1.default.match(consumerGuide, /examples\/clients\/codex-consumer\.ts/);
|
|
176
|
+
strict_1.default.match(consumerGuide, /examples\/clients\/claude-code-tool\.ts/);
|
|
177
|
+
strict_1.default.match(consumerGuide, /createHttpBridgeAdapter/);
|
|
178
|
+
strict_1.default.match(consumerGuide, /createCliBridgeAdapter/);
|
|
179
|
+
strict_1.default.match(consumerGuide, /connectViaBridge/);
|
|
180
|
+
strict_1.default.match(consumerGuide, /normalizeCodexRoute/);
|
|
181
|
+
strict_1.default.match(consumerGuide, /connectCodexViaCli/);
|
|
182
|
+
strict_1.default.match(consumerGuide, /connectCodexViaHttp/);
|
|
183
|
+
strict_1.default.match(consumerGuide, /normalizeClaudeCodeRoute/);
|
|
184
|
+
strict_1.default.match(consumerGuide, /prepareClaudeCodeRoute/);
|
|
185
|
+
strict_1.default.match(consumerGuide, /node --experimental-strip-types examples\/clients\/doctor-connect-wrapper\.ts safari/);
|
|
186
|
+
strict_1.default.match(consumerGuide, /outcome`, `status`, `category`, and optional `reason`/);
|
|
187
|
+
strict_1.default.match(consumerGuide, /"outcome": "blocked"/);
|
|
188
|
+
strict_1.default.match(consumerGuide, /"category": "session-connected"/);
|
|
189
|
+
strict_1.default.match(consumerGuide, /Chrome relay only works for a tab you explicitly share/);
|
|
190
|
+
strict_1.default.match(consumerGuide, /suggestedActions/);
|
|
191
|
+
strict_1.default.doesNotMatch(consumerGuide, /OpenClaw\/browser-style consumer demo/);
|
|
192
|
+
strict_1.default.match(adapterPatterns, /OpenClaw/);
|
|
193
|
+
strict_1.default.match(adapterPatterns, /AWOS/);
|
|
194
|
+
strict_1.default.match(adapterPatterns, /Codex/);
|
|
195
|
+
strict_1.default.match(adapterPatterns, /Claude Code/);
|
|
196
|
+
strict_1.default.match(adapterPatterns, /transport-neutral/i);
|
|
197
|
+
strict_1.default.match(adapterPatterns, /agent-agnostic/i);
|
|
198
|
+
strict_1.default.match(adapterPatterns, /CLI for one-shot invocation/);
|
|
199
|
+
strict_1.default.match(adapterPatterns, /local HTTP for long-running connectors/);
|
|
200
|
+
strict_1.default.match(adapterPatterns, /Shared consumer surface/);
|
|
201
|
+
strict_1.default.match(adapterPatterns, /from "local-browser-bridge"/);
|
|
202
|
+
strict_1.default.match(adapterPatterns, /Minimal adapter skeleton:/);
|
|
203
|
+
strict_1.default.match(adapterPatterns, /connectBrowserRoute/);
|
|
204
|
+
strict_1.default.match(adapterPatterns, /runBrowserTool/);
|
|
205
|
+
strict_1.default.match(adapterPatterns, /runAgentStep/);
|
|
206
|
+
strict_1.default.match(adapterPatterns, /normalizeCodexRoute/);
|
|
207
|
+
strict_1.default.match(adapterPatterns, /connectCodexViaCli/);
|
|
208
|
+
strict_1.default.match(adapterPatterns, /connectCodexViaHttp/);
|
|
209
|
+
strict_1.default.match(adapterPatterns, /prepareToolPrompt/);
|
|
210
|
+
strict_1.default.match(adapterPatterns, /export async function connect\(/);
|
|
211
|
+
strict_1.default.match(adapterPatterns, /examples\/clients\/doctor-connect-wrapper\.ts/);
|
|
212
|
+
strict_1.default.match(adapterPatterns, /outcome` \/ `status` \/ `category` \/ `reason`/);
|
|
213
|
+
strict_1.default.match(readme, /examples\/clients\/doctor-connect-wrapper\.ts/);
|
|
214
|
+
strict_1.default.match(readme, /local-browser-bridge doctor --route/);
|
|
215
|
+
strict_1.default.match(readme, /outcome` \/ `status` \/ `category` \/ `reason`/);
|
|
216
|
+
strict_1.default.match(readme, /chrome-relay` read-only plus shared-tab scoped/);
|
|
217
|
+
strict_1.default.match(readme, /`browser_tabs` is available for Safari and `chrome-direct`/);
|
|
218
|
+
strict_1.default.match(readme, /structured non-error blocked result/);
|
|
219
|
+
strict_1.default.match(readme, /Runtime action tools such as `activate`, `navigate`, or `screenshot` are intentionally not part of this RC MCP surface/);
|
|
220
|
+
strict_1.default.match(readme, /examples\/mcp\/claude-code\.installed-package\.mcp\.json/);
|
|
221
|
+
strict_1.default.match(readme, /examples\/mcp\/generic-stdio\.repo-checkout\.json/);
|
|
222
|
+
strict_1.default.match(readme, /npm run cli -- --help/);
|
|
223
|
+
strict_1.default.doesNotMatch(readme, /npm run bridge -- --help/);
|
|
224
|
+
strict_1.default.match(readme, /consumer project[\s\S]*node_modules\/\.bin\/local-browser-bridge-mcp/);
|
|
225
|
+
strict_1.default.match(readme, /Equivalent direct repo-checkout command after `npm run build`:\s*```bash\s*node \.\/dist\/src\/mcp-stdio\.js\s*```/);
|
|
226
|
+
strict_1.default.match(readme, /node \.\/dist\/src\/mcp-stdio\.js/);
|
|
227
|
+
strict_1.default.doesNotMatch(readme, /Equivalent direct repo-checkout command after `npm run build`:\s*```bash\s*\.\/node_modules\/\.bin\/local-browser-bridge-mcp\s*```/);
|
|
228
|
+
});
|
|
229
|
+
(0, node_test_1.default)("chrome relay error schema artifact stays documented and aligned with the example", async () => {
|
|
230
|
+
const root = process.cwd();
|
|
231
|
+
const schema = await readJson((0, node_path_1.resolve)(root, "schema", "chrome-relay-error.schema.json"));
|
|
232
|
+
const readme = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "README.md"), "utf8");
|
|
233
|
+
const consumerGuide = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "docs", "consuming-the-bridge.md"), "utf8");
|
|
234
|
+
const adapterPatterns = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "docs", "adapter-patterns.md"), "utf8");
|
|
235
|
+
const integrationContract = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "docs", "agent-integration-contract.md"), "utf8");
|
|
236
|
+
const prd = await (0, promises_1.readFile)((0, node_path_1.resolve)(root, "PRD.md"), "utf8");
|
|
237
|
+
strict_1.default.match(schema.$id, /chrome-relay-error\.schema\.json$/);
|
|
238
|
+
strict_1.default.equal(schema.properties?.error?.properties?.details?.$ref, "#/$defs/chromeRelayErrorDetails");
|
|
239
|
+
strict_1.default.match(readme, /schema\/chrome-relay-error\.schema\.json/);
|
|
240
|
+
strict_1.default.match(readme, /examples\/error\.chrome-relay-share-required\.example\.json/);
|
|
241
|
+
strict_1.default.match(readme, /docs\/adapter-patterns\.md/);
|
|
242
|
+
strict_1.default.match(readme, /src\/index\.ts/);
|
|
243
|
+
strict_1.default.match(consumerGuide, /\.\/adapter-patterns\.md/);
|
|
244
|
+
strict_1.default.match(adapterPatterns, /Agent Integration Contract/);
|
|
245
|
+
strict_1.default.match(adapterPatterns, /Consuming local-browser-bridge/);
|
|
246
|
+
strict_1.default.match(consumerGuide, /schema\/chrome-relay-error\.schema\.json/);
|
|
247
|
+
strict_1.default.match(consumerGuide, /examples\/error\.chrome-relay-share-required\.example\.json/);
|
|
248
|
+
strict_1.default.match(integrationContract, /schema\/chrome-relay-error\.schema\.json/);
|
|
249
|
+
strict_1.default.match(integrationContract, /examples\/error\.chrome-relay-share-required\.example\.json/);
|
|
250
|
+
strict_1.default.match(integrationContract, /additive transport-neutral error envelope/i);
|
|
251
|
+
strict_1.default.match(integrationContract, /shared-tab read-only path/i);
|
|
252
|
+
strict_1.default.match(prd, /Chrome relay structured failure contract/);
|
|
253
|
+
strict_1.default.match(prd, /transport-neutral structured error details aligned across CLI and local HTTP/);
|
|
254
|
+
strict_1.default.match(prd, /error\.details\.relay\.sharedTabScope = "current-shared-tab"/);
|
|
255
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
7
|
+
const node_child_process_1 = require("node:child_process");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
const node_util_1 = require("node:util");
|
|
10
|
+
const node_test_1 = __importDefault(require("node:test"));
|
|
11
|
+
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
|
|
12
|
+
(0, node_test_1.default)("doctor/connect wrapper example surfaces blocked relay prompts", async () => {
|
|
13
|
+
const wrapperPath = (0, node_path_1.resolve)(process.cwd(), "examples/clients/doctor-connect-wrapper.ts");
|
|
14
|
+
const stubPath = (0, node_path_1.resolve)(process.cwd(), "dist/tests/fixtures/doctor-connect-cli-stub.js");
|
|
15
|
+
const result = await execFileAsync(process.execPath, ["--experimental-strip-types", wrapperPath, "chrome-relay"], {
|
|
16
|
+
cwd: process.cwd(),
|
|
17
|
+
env: {
|
|
18
|
+
...process.env,
|
|
19
|
+
LOCAL_BROWSER_BRIDGE_BIN: process.execPath,
|
|
20
|
+
LOCAL_BROWSER_BRIDGE_CLI_PATH: stubPath
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
const payload = JSON.parse(result.stdout);
|
|
24
|
+
strict_1.default.equal(payload.result.ok, false);
|
|
25
|
+
strict_1.default.equal(payload.result.stage, "doctor");
|
|
26
|
+
strict_1.default.equal(payload.result.outcome, "blocked");
|
|
27
|
+
strict_1.default.equal(payload.result.status, "blocked");
|
|
28
|
+
strict_1.default.equal(payload.result.category, "route-blocked");
|
|
29
|
+
strict_1.default.equal(payload.result.reason?.code, "relay_share_required");
|
|
30
|
+
strict_1.default.equal(payload.result.route, "chrome-relay");
|
|
31
|
+
strict_1.default.equal(payload.result.label, "Chrome (shared tab, read-only)");
|
|
32
|
+
strict_1.default.match(payload.result.prompt, /Share the tab first/i);
|
|
33
|
+
strict_1.default.equal(payload.result.nextStep.action, "fix-blocker");
|
|
34
|
+
strict_1.default.equal(payload.result.readOnly, true);
|
|
35
|
+
strict_1.default.equal(payload.result.sharedTabScoped, true);
|
|
36
|
+
});
|
|
37
|
+
(0, node_test_1.default)("doctor/connect wrapper example returns concise session results for Safari", async () => {
|
|
38
|
+
const wrapperPath = (0, node_path_1.resolve)(process.cwd(), "examples/clients/doctor-connect-wrapper.ts");
|
|
39
|
+
const stubPath = (0, node_path_1.resolve)(process.cwd(), "dist/tests/fixtures/doctor-connect-cli-stub.js");
|
|
40
|
+
const result = await execFileAsync(process.execPath, ["--experimental-strip-types", wrapperPath, "safari"], {
|
|
41
|
+
cwd: process.cwd(),
|
|
42
|
+
env: {
|
|
43
|
+
...process.env,
|
|
44
|
+
LOCAL_BROWSER_BRIDGE_BIN: process.execPath,
|
|
45
|
+
LOCAL_BROWSER_BRIDGE_CLI_PATH: stubPath
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
const payload = JSON.parse(result.stdout);
|
|
49
|
+
strict_1.default.equal(payload.wrapper, "doctor-connect");
|
|
50
|
+
strict_1.default.equal(payload.result.ok, true);
|
|
51
|
+
strict_1.default.equal(payload.result.stage, "connect");
|
|
52
|
+
strict_1.default.equal(payload.result.outcome, "success");
|
|
53
|
+
strict_1.default.equal(payload.result.status, "connected");
|
|
54
|
+
strict_1.default.equal(payload.result.category, "session-connected");
|
|
55
|
+
strict_1.default.equal(payload.result.route, "safari");
|
|
56
|
+
strict_1.default.equal(payload.result.label, "Safari (actionable)");
|
|
57
|
+
strict_1.default.equal(payload.result.readOnly, false);
|
|
58
|
+
strict_1.default.equal(payload.result.session?.id, "session-safari-demo");
|
|
59
|
+
strict_1.default.equal(payload.result.session?.kind, "safari-actionable");
|
|
60
|
+
strict_1.default.equal(payload.result.session?.canAct, true);
|
|
61
|
+
strict_1.default.deepEqual(payload.result.session?.suggestedActions, ["resume", "activate", "navigate", "screenshot"]);
|
|
62
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
function writeJson(payload) {
|
|
4
|
+
process.stdout.write(JSON.stringify(payload));
|
|
5
|
+
}
|
|
6
|
+
const [command, ...args] = process.argv.slice(2);
|
|
7
|
+
const route = args[1];
|
|
8
|
+
if (command === "doctor" && args[0] === "--route" && route === "chrome-relay") {
|
|
9
|
+
writeJson({
|
|
10
|
+
ok: false,
|
|
11
|
+
command: "doctor",
|
|
12
|
+
outcome: "blocked",
|
|
13
|
+
status: "blocked",
|
|
14
|
+
category: "route-blocked",
|
|
15
|
+
reason: {
|
|
16
|
+
code: "relay_share_required",
|
|
17
|
+
message: "Share the tab first."
|
|
18
|
+
},
|
|
19
|
+
summary: "Chrome (shared tab, read-only) is not ready yet. It remains read-only and only covers the currently shared tab.",
|
|
20
|
+
prompt: "Chrome relay only works for a tab you explicitly share. Share the tab first, then retry.",
|
|
21
|
+
nextStep: {
|
|
22
|
+
action: "fix-blocker",
|
|
23
|
+
prompt: "Chrome relay only works for a tab you explicitly share. Share the tab first, then retry."
|
|
24
|
+
},
|
|
25
|
+
routeUx: {
|
|
26
|
+
label: "Chrome (shared tab, read-only)",
|
|
27
|
+
state: "blocked",
|
|
28
|
+
readOnly: true,
|
|
29
|
+
sharedTabScoped: true
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else if (command === "doctor" && args[0] === "--route" && route === "safari") {
|
|
34
|
+
writeJson({
|
|
35
|
+
ok: true,
|
|
36
|
+
command: "doctor",
|
|
37
|
+
outcome: "success",
|
|
38
|
+
status: "ready",
|
|
39
|
+
category: "route-ready",
|
|
40
|
+
summary: "Safari (actionable) is ready for attach. It is actionable.",
|
|
41
|
+
nextStep: {
|
|
42
|
+
action: "connect",
|
|
43
|
+
prompt: "Run local-browser-bridge connect --route safari to continue.",
|
|
44
|
+
command: "local-browser-bridge connect --route safari"
|
|
45
|
+
},
|
|
46
|
+
routeUx: {
|
|
47
|
+
label: "Safari (actionable)",
|
|
48
|
+
state: "ready",
|
|
49
|
+
readOnly: false,
|
|
50
|
+
sharedTabScoped: false
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else if (command === "connect" && args[0] === "--route" && route === "safari") {
|
|
55
|
+
writeJson({
|
|
56
|
+
ok: true,
|
|
57
|
+
command: "connect",
|
|
58
|
+
connected: true,
|
|
59
|
+
outcome: "success",
|
|
60
|
+
status: "connected",
|
|
61
|
+
category: "session-connected",
|
|
62
|
+
summary: "Connected Safari (actionable) session session-safari-demo. It is actionable.",
|
|
63
|
+
nextStep: {
|
|
64
|
+
action: "session-ready",
|
|
65
|
+
prompt: "Use session session-safari-demo for follow-up actions like activate, navigate, or screenshot."
|
|
66
|
+
},
|
|
67
|
+
routeUx: {
|
|
68
|
+
label: "Safari (actionable)",
|
|
69
|
+
state: "ready",
|
|
70
|
+
readOnly: false,
|
|
71
|
+
sharedTabScoped: false
|
|
72
|
+
},
|
|
73
|
+
sessionUx: {
|
|
74
|
+
label: "Safari (actionable)",
|
|
75
|
+
state: "ready",
|
|
76
|
+
readOnly: false,
|
|
77
|
+
sharedTabScoped: false
|
|
78
|
+
},
|
|
79
|
+
session: {
|
|
80
|
+
id: "session-safari-demo",
|
|
81
|
+
kind: "safari-actionable",
|
|
82
|
+
capabilities: {
|
|
83
|
+
activate: true,
|
|
84
|
+
navigate: true,
|
|
85
|
+
screenshot: true
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
process.stderr.write(`Unexpected args: ${[command, ...args].join(" ")}`);
|
|
92
|
+
process.exitCode = 1;
|
|
93
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
declare const capabilities: {
|
|
2
|
+
schemaVersion: number;
|
|
3
|
+
kind: string;
|
|
4
|
+
product: {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
declare const diagnostics: {
|
|
10
|
+
browser: "chrome";
|
|
11
|
+
checkedAt: string;
|
|
12
|
+
runtime: {
|
|
13
|
+
platform: string;
|
|
14
|
+
arch: string;
|
|
15
|
+
nodeVersion: string;
|
|
16
|
+
safariRunning: boolean;
|
|
17
|
+
};
|
|
18
|
+
host: {
|
|
19
|
+
osascriptAvailable: boolean;
|
|
20
|
+
screencaptureAvailable: boolean;
|
|
21
|
+
safariApplicationAvailable: boolean;
|
|
22
|
+
};
|
|
23
|
+
supportedFeatures: {
|
|
24
|
+
inspectTabs: boolean;
|
|
25
|
+
attach: boolean;
|
|
26
|
+
activate: boolean;
|
|
27
|
+
navigate: boolean;
|
|
28
|
+
screenshot: boolean;
|
|
29
|
+
savedSessions: boolean;
|
|
30
|
+
cli: boolean;
|
|
31
|
+
httpApi: boolean;
|
|
32
|
+
};
|
|
33
|
+
constraints: never[];
|
|
34
|
+
attach: {
|
|
35
|
+
direct: {
|
|
36
|
+
mode: "direct";
|
|
37
|
+
source: "user-browser";
|
|
38
|
+
scope: "browser";
|
|
39
|
+
supported: boolean;
|
|
40
|
+
ready: boolean;
|
|
41
|
+
state: "ready";
|
|
42
|
+
blockers: never[];
|
|
43
|
+
};
|
|
44
|
+
relay: {
|
|
45
|
+
mode: "relay";
|
|
46
|
+
source: "extension-relay";
|
|
47
|
+
scope: "tab";
|
|
48
|
+
supported: boolean;
|
|
49
|
+
ready: boolean;
|
|
50
|
+
state: "ready";
|
|
51
|
+
blockers: never[];
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
declare const session: {
|
|
56
|
+
schemaVersion: 1;
|
|
57
|
+
id: string;
|
|
58
|
+
kind: "chrome-readonly";
|
|
59
|
+
browser: "chrome";
|
|
60
|
+
target: {
|
|
61
|
+
type: "front";
|
|
62
|
+
};
|
|
63
|
+
tab: {
|
|
64
|
+
browser: "chrome";
|
|
65
|
+
windowIndex: number;
|
|
66
|
+
tabIndex: number;
|
|
67
|
+
title: string;
|
|
68
|
+
url: string;
|
|
69
|
+
attachedAt: string;
|
|
70
|
+
identity: {
|
|
71
|
+
signature: string;
|
|
72
|
+
urlKey: string;
|
|
73
|
+
titleKey: string;
|
|
74
|
+
origin: string;
|
|
75
|
+
pathname: string;
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
frontTab: {
|
|
79
|
+
browser: "chrome";
|
|
80
|
+
windowIndex: number;
|
|
81
|
+
tabIndex: number;
|
|
82
|
+
title: string;
|
|
83
|
+
url: string;
|
|
84
|
+
attachedAt: string;
|
|
85
|
+
identity: {
|
|
86
|
+
signature: string;
|
|
87
|
+
urlKey: string;
|
|
88
|
+
titleKey: string;
|
|
89
|
+
origin: string;
|
|
90
|
+
pathname: string;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
attach: {
|
|
94
|
+
mode: "relay";
|
|
95
|
+
source: "extension-relay";
|
|
96
|
+
scope: "tab";
|
|
97
|
+
resumable: boolean;
|
|
98
|
+
};
|
|
99
|
+
semantics: {
|
|
100
|
+
inspect: "shared-tab-only";
|
|
101
|
+
list: "saved-session";
|
|
102
|
+
resume: "current-shared-tab";
|
|
103
|
+
tabReference: {
|
|
104
|
+
windowIndex: "synthetic-shared-tab-position";
|
|
105
|
+
tabIndex: "synthetic-shared-tab-position";
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
capabilities: {
|
|
109
|
+
resume: true;
|
|
110
|
+
activate: boolean;
|
|
111
|
+
navigate: boolean;
|
|
112
|
+
screenshot: boolean;
|
|
113
|
+
};
|
|
114
|
+
status: {
|
|
115
|
+
state: "read-only";
|
|
116
|
+
canAct: boolean;
|
|
117
|
+
};
|
|
118
|
+
createdAt: string;
|
|
119
|
+
};
|
|
120
|
+
declare const resumedSession: {
|
|
121
|
+
session: {
|
|
122
|
+
schemaVersion: 1;
|
|
123
|
+
id: string;
|
|
124
|
+
kind: "chrome-readonly";
|
|
125
|
+
browser: "chrome";
|
|
126
|
+
target: {
|
|
127
|
+
type: "front";
|
|
128
|
+
};
|
|
129
|
+
tab: {
|
|
130
|
+
browser: "chrome";
|
|
131
|
+
windowIndex: number;
|
|
132
|
+
tabIndex: number;
|
|
133
|
+
title: string;
|
|
134
|
+
url: string;
|
|
135
|
+
attachedAt: string;
|
|
136
|
+
identity: {
|
|
137
|
+
signature: string;
|
|
138
|
+
urlKey: string;
|
|
139
|
+
titleKey: string;
|
|
140
|
+
origin: string;
|
|
141
|
+
pathname: string;
|
|
142
|
+
};
|
|
143
|
+
};
|
|
144
|
+
frontTab: {
|
|
145
|
+
browser: "chrome";
|
|
146
|
+
windowIndex: number;
|
|
147
|
+
tabIndex: number;
|
|
148
|
+
title: string;
|
|
149
|
+
url: string;
|
|
150
|
+
attachedAt: string;
|
|
151
|
+
identity: {
|
|
152
|
+
signature: string;
|
|
153
|
+
urlKey: string;
|
|
154
|
+
titleKey: string;
|
|
155
|
+
origin: string;
|
|
156
|
+
pathname: string;
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
attach: {
|
|
160
|
+
mode: "relay";
|
|
161
|
+
source: "extension-relay";
|
|
162
|
+
scope: "tab";
|
|
163
|
+
resumable: boolean;
|
|
164
|
+
};
|
|
165
|
+
semantics: {
|
|
166
|
+
inspect: "shared-tab-only";
|
|
167
|
+
list: "saved-session";
|
|
168
|
+
resume: "current-shared-tab";
|
|
169
|
+
tabReference: {
|
|
170
|
+
windowIndex: "synthetic-shared-tab-position";
|
|
171
|
+
tabIndex: "synthetic-shared-tab-position";
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
capabilities: {
|
|
175
|
+
resume: true;
|
|
176
|
+
activate: boolean;
|
|
177
|
+
navigate: boolean;
|
|
178
|
+
screenshot: boolean;
|
|
179
|
+
};
|
|
180
|
+
status: {
|
|
181
|
+
state: "read-only";
|
|
182
|
+
canAct: boolean;
|
|
183
|
+
};
|
|
184
|
+
createdAt: string;
|
|
185
|
+
};
|
|
186
|
+
tab: {
|
|
187
|
+
browser: "chrome";
|
|
188
|
+
windowIndex: number;
|
|
189
|
+
tabIndex: number;
|
|
190
|
+
title: string;
|
|
191
|
+
url: string;
|
|
192
|
+
attachedAt: string;
|
|
193
|
+
identity: {
|
|
194
|
+
signature: string;
|
|
195
|
+
urlKey: string;
|
|
196
|
+
titleKey: string;
|
|
197
|
+
origin: string;
|
|
198
|
+
pathname: string;
|
|
199
|
+
};
|
|
200
|
+
};
|
|
201
|
+
resumedAt: string;
|
|
202
|
+
resolution: {
|
|
203
|
+
strategy: "front";
|
|
204
|
+
matched: boolean;
|
|
205
|
+
attachMode: "relay";
|
|
206
|
+
semantics: "current-shared-tab";
|
|
207
|
+
};
|
|
208
|
+
};
|
|
209
|
+
declare function writeJson(payload: unknown): void;
|
|
210
|
+
declare const command: string, args: string[];
|