@oharness/engine 0.7.0 → 0.8.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/dist/agent/agent.d.ts +72 -0
- package/dist/agent/agent.js +114 -1
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/permissions.js +8 -0
- package/dist/agent/permissions.js.map +1 -1
- package/dist/browser/cdp.d.ts +75 -0
- package/dist/browser/cdp.js +136 -0
- package/dist/browser/cdp.js.map +1 -0
- package/dist/browser/chrome.d.ts +19 -0
- package/dist/browser/chrome.js +306 -0
- package/dist/browser/chrome.js.map +1 -0
- package/dist/browser/extension.d.ts +35 -0
- package/dist/browser/extension.js +297 -0
- package/dist/browser/extension.js.map +1 -0
- package/dist/browser/host-manifest.d.ts +78 -0
- package/dist/browser/host-manifest.js +166 -0
- package/dist/browser/host-manifest.js.map +1 -0
- package/dist/browser/host.d.ts +27 -0
- package/dist/browser/host.js +311 -0
- package/dist/browser/host.js.map +1 -0
- package/dist/browser/index.d.ts +26 -0
- package/dist/browser/index.js +15 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/login-import.d.ts +98 -0
- package/dist/browser/login-import.js +244 -0
- package/dist/browser/login-import.js.map +1 -0
- package/dist/browser/plugin.d.ts +109 -0
- package/dist/browser/plugin.js +22 -0
- package/dist/browser/plugin.js.map +1 -0
- package/dist/browser/presence.d.ts +29 -0
- package/dist/browser/presence.js +54 -0
- package/dist/browser/presence.js.map +1 -0
- package/dist/browser/provider.d.ts +17 -0
- package/dist/browser/provider.js +13 -0
- package/dist/browser/provider.js.map +1 -0
- package/dist/browser/screencast.d.ts +42 -0
- package/dist/browser/screencast.js +99 -0
- package/dist/browser/screencast.js.map +1 -0
- package/dist/browser/session.d.ts +320 -0
- package/dist/browser/session.js +837 -0
- package/dist/browser/session.js.map +1 -0
- package/dist/browser/snapshot.d.ts +49 -0
- package/dist/browser/snapshot.js +145 -0
- package/dist/browser/snapshot.js.map +1 -0
- package/dist/browser/socket.d.ts +15 -0
- package/dist/browser/socket.js +32 -0
- package/dist/browser/socket.js.map +1 -0
- package/dist/browser/target.d.ts +112 -0
- package/dist/browser/target.js +20 -0
- package/dist/browser/target.js.map +1 -0
- package/dist/browser/tools.d.ts +3 -0
- package/dist/browser/tools.js +537 -0
- package/dist/browser/tools.js.map +1 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.js.map +1 -1
- package/dist/core/errors.d.ts +12 -0
- package/dist/core/errors.js +14 -1
- package/dist/core/errors.js.map +1 -1
- package/dist/harness.d.ts +49 -0
- package/dist/harness.js +97 -1
- package/dist/harness.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/piai.js +7 -2
- package/dist/providers/piai.js.map +1 -1
- package/dist/tools/define.d.ts +1 -0
- package/dist/tools/define.js +3 -0
- package/dist/tools/define.js.map +1 -1
- package/dist/tools/types.d.ts +11 -0
- package/dist/tools/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export class ScreencastHub {
|
|
2
|
+
page;
|
|
3
|
+
subscribers = new Set();
|
|
4
|
+
detach;
|
|
5
|
+
last;
|
|
6
|
+
constructor(page) {
|
|
7
|
+
this.page = page;
|
|
8
|
+
}
|
|
9
|
+
/** The most recent frame, for a viewer that has just arrived. */
|
|
10
|
+
async seed(quality) {
|
|
11
|
+
if (this.last)
|
|
12
|
+
return this.last;
|
|
13
|
+
try {
|
|
14
|
+
const result = await this.page.send("Page.captureScreenshot", { format: "jpeg", quality });
|
|
15
|
+
const data = result["data"];
|
|
16
|
+
if (typeof data === "string")
|
|
17
|
+
this.last = Buffer.from(data, "base64");
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
// A page that cannot be captured yet will produce frames when it paints.
|
|
21
|
+
}
|
|
22
|
+
return this.last;
|
|
23
|
+
}
|
|
24
|
+
async start(opts) {
|
|
25
|
+
if (this.detach)
|
|
26
|
+
return;
|
|
27
|
+
this.detach = this.page.on("Page.screencastFrame", (params) => {
|
|
28
|
+
const data = params["data"];
|
|
29
|
+
const sessionId = params["sessionId"];
|
|
30
|
+
// The ack is the backpressure: without it Chrome stops after a frame or
|
|
31
|
+
// two, which looks exactly like a page that stopped changing.
|
|
32
|
+
if (typeof sessionId === "number") {
|
|
33
|
+
void this.page.send("Page.screencastFrameAck", { sessionId }).catch(() => { });
|
|
34
|
+
}
|
|
35
|
+
if (typeof data !== "string")
|
|
36
|
+
return;
|
|
37
|
+
this.last = Buffer.from(data, "base64");
|
|
38
|
+
for (const push of this.subscribers)
|
|
39
|
+
push(this.last);
|
|
40
|
+
});
|
|
41
|
+
await this.page.send("Page.startScreencast", {
|
|
42
|
+
format: "jpeg",
|
|
43
|
+
quality: opts.quality ?? 85,
|
|
44
|
+
...(opts.maxWidth ? { maxWidth: opts.maxWidth } : {}),
|
|
45
|
+
...(opts.maxHeight ? { maxHeight: opts.maxHeight } : {}),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
async stop() {
|
|
49
|
+
if (this.subscribers.size > 0 || !this.detach)
|
|
50
|
+
return;
|
|
51
|
+
this.detach();
|
|
52
|
+
this.detach = undefined;
|
|
53
|
+
await this.page.send("Page.stopScreencast").catch(() => { });
|
|
54
|
+
}
|
|
55
|
+
/** Newest frame only: a viewer behind wants the current picture, not a queue. */
|
|
56
|
+
async *frames(opts = {}) {
|
|
57
|
+
let pending = await this.seed(opts.quality ?? 85);
|
|
58
|
+
let wake;
|
|
59
|
+
let closed = false;
|
|
60
|
+
const push = (frame) => {
|
|
61
|
+
if (frame === undefined)
|
|
62
|
+
closed = true;
|
|
63
|
+
else
|
|
64
|
+
pending = frame;
|
|
65
|
+
wake?.();
|
|
66
|
+
};
|
|
67
|
+
this.subscribers.add(push);
|
|
68
|
+
await this.start(opts);
|
|
69
|
+
try {
|
|
70
|
+
for (;;) {
|
|
71
|
+
if (pending !== undefined) {
|
|
72
|
+
const frame = pending;
|
|
73
|
+
pending = undefined;
|
|
74
|
+
yield frame;
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (closed)
|
|
78
|
+
return;
|
|
79
|
+
await new Promise((resolve) => {
|
|
80
|
+
wake = resolve;
|
|
81
|
+
});
|
|
82
|
+
wake = undefined;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
finally {
|
|
86
|
+
this.subscribers.delete(push);
|
|
87
|
+
await this.stop();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/** The page went away; every watcher ends rather than waiting on it. */
|
|
91
|
+
close() {
|
|
92
|
+
for (const push of this.subscribers)
|
|
93
|
+
push(undefined);
|
|
94
|
+
this.subscribers.clear();
|
|
95
|
+
this.detach?.();
|
|
96
|
+
this.detach = undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=screencast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screencast.js","sourceRoot":"","sources":["../../src/browser/screencast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import type { Logger } from "../util/logger.ts";
|
|
2
|
+
import type { BrowserProviderPlugin } from "./provider.ts";
|
|
3
|
+
import { LoginImportMemory } from "./login-import.ts";
|
|
4
|
+
import type { ExternalSite, ImportedSite } from "./login-import.ts";
|
|
5
|
+
import type { Snapshot, SnapshotOptions } from "./snapshot.ts";
|
|
6
|
+
import type { BrowserInputEvent, BrowserPage, BrowserTargetFactory, FrameOptions } from "./target.ts";
|
|
7
|
+
export interface ConsoleEntry {
|
|
8
|
+
level: string;
|
|
9
|
+
text: string;
|
|
10
|
+
url?: string;
|
|
11
|
+
at: number;
|
|
12
|
+
}
|
|
13
|
+
export interface NetworkEntry {
|
|
14
|
+
requestId: string;
|
|
15
|
+
method: string;
|
|
16
|
+
url: string;
|
|
17
|
+
status?: number;
|
|
18
|
+
mimeType?: string;
|
|
19
|
+
failed?: string;
|
|
20
|
+
at: number;
|
|
21
|
+
}
|
|
22
|
+
export interface BrowserSessionOptions {
|
|
23
|
+
/** Overrides whatever `mode` would have chosen — the seam the desktop shell uses. */
|
|
24
|
+
target?: BrowserTargetFactory;
|
|
25
|
+
/** Host implementations. The plugin matching `mode` is selected lazily. */
|
|
26
|
+
providers?: readonly BrowserProviderPlugin[];
|
|
27
|
+
/**
|
|
28
|
+
* `builtin` starts a browser of our own; `extension` drives the person's real
|
|
29
|
+
* one through the OHarness extension; `auto` holds both and lets each call
|
|
30
|
+
* say which it needs (see `sideFor`). An explicit `target` wins over all three.
|
|
31
|
+
*/
|
|
32
|
+
mode?: BrowserPolicy;
|
|
33
|
+
headless?: boolean;
|
|
34
|
+
logger?: Logger;
|
|
35
|
+
/** Where "already imported / don't ask again" is kept. Shared by default. */
|
|
36
|
+
loginMemory?: LoginImportMemory;
|
|
37
|
+
/** The owning conversation's name; see BrowserTargetContext.label. */
|
|
38
|
+
label?: () => string | undefined;
|
|
39
|
+
/** The owning conversation's project; see BrowserTargetContext.cwd. */
|
|
40
|
+
cwd?: string;
|
|
41
|
+
}
|
|
42
|
+
/** One of the two browsers a session can drive. */
|
|
43
|
+
export type BrowserSide = "builtin" | "extension";
|
|
44
|
+
/** Which of them a session may use: one of them always, or either as each call needs. */
|
|
45
|
+
export type BrowserPolicy = BrowserSide | "auto";
|
|
46
|
+
export declare class BrowserSession {
|
|
47
|
+
/**
|
|
48
|
+
* Both browsers' state, each started only when first used. Everything below
|
|
49
|
+
* reads the one in use through the accessors, so a call that switches
|
|
50
|
+
* browsers finds the other one's tab, refs and origin exactly as it left
|
|
51
|
+
* them — the built-in browser keeps its page while the person's is used.
|
|
52
|
+
*/
|
|
53
|
+
private readonly sides;
|
|
54
|
+
private get side();
|
|
55
|
+
private get target();
|
|
56
|
+
private set target(value);
|
|
57
|
+
private get starting();
|
|
58
|
+
private set starting(value);
|
|
59
|
+
private get active();
|
|
60
|
+
private set active(value);
|
|
61
|
+
private get pageStarting();
|
|
62
|
+
private set pageStarting(value);
|
|
63
|
+
private get refs();
|
|
64
|
+
private set refs(value);
|
|
65
|
+
private get wired();
|
|
66
|
+
private set wired(value);
|
|
67
|
+
private get currentOrigin();
|
|
68
|
+
private set currentOrigin(value);
|
|
69
|
+
private readonly consoleLog;
|
|
70
|
+
private readonly network;
|
|
71
|
+
private readonly opts;
|
|
72
|
+
private sessionId?;
|
|
73
|
+
private label?;
|
|
74
|
+
/** The browser in use now. */
|
|
75
|
+
private mode;
|
|
76
|
+
/** Which browsers this session may use. */
|
|
77
|
+
private policy;
|
|
78
|
+
/** Said once, with the next tool result: a fallback the model should know about. */
|
|
79
|
+
private readonly notices;
|
|
80
|
+
private importing;
|
|
81
|
+
private probing?;
|
|
82
|
+
private readonly suggestions;
|
|
83
|
+
constructor(opts?: BrowserSessionOptions);
|
|
84
|
+
/** Name the conversation this browser works for. Read lazily, so it may change. */
|
|
85
|
+
setLabel(label: () => string | undefined): void;
|
|
86
|
+
/** Bind the lazily-created browser to its owning conversation. */
|
|
87
|
+
bind(sessionId: string): void;
|
|
88
|
+
/** Whether a browser is running, without starting one to find out. */
|
|
89
|
+
get running(): boolean;
|
|
90
|
+
/**
|
|
91
|
+
* The origin the permission engine asks about.
|
|
92
|
+
*
|
|
93
|
+
* Undefined before the first navigation, which is what makes the very first
|
|
94
|
+
* `browser_navigate` the call that gets asked: after that the origin is known
|
|
95
|
+
* and an approval for it covers the clicking and typing that follow.
|
|
96
|
+
*/
|
|
97
|
+
origin(): string | undefined;
|
|
98
|
+
page(): Promise<BrowserPage>;
|
|
99
|
+
private start;
|
|
100
|
+
/**
|
|
101
|
+
* Which browser a call that can open a page will use.
|
|
102
|
+
*
|
|
103
|
+
* Pure and synchronous, because the permission check asks it before the
|
|
104
|
+
* call runs: what is approved has to be what then happens. A fixed policy
|
|
105
|
+
* always answers itself. In auto, the call's own `browser` wins — the model
|
|
106
|
+
* reads the person's intent, and says "yours" when the task needs their
|
|
107
|
+
* accounts or a page they have open. Without one, the conversation stays in
|
|
108
|
+
* the browser it is already working in, so a task never changes browsers
|
|
109
|
+
* halfway and loses the page it was on.
|
|
110
|
+
*/
|
|
111
|
+
sideFor(request?: "yours" | "builtin"): BrowserSide;
|
|
112
|
+
/** The browser in use now, and which ones this session may use. */
|
|
113
|
+
current(): {
|
|
114
|
+
side: BrowserSide;
|
|
115
|
+
policy: BrowserPolicy;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Move to the browser a call asked for, before it runs. A request a fixed
|
|
119
|
+
* policy cannot honour is answered with why, rather than ignored.
|
|
120
|
+
*/
|
|
121
|
+
use(request?: "yours" | "builtin"): void;
|
|
122
|
+
/** What the model has not been told yet. Each notice is handed out once. */
|
|
123
|
+
takeNotices(): string[];
|
|
124
|
+
/** Make `page` the one the tools act on, wiring its log streams once. */
|
|
125
|
+
adopt(page: BrowserPage): Promise<void>;
|
|
126
|
+
private record;
|
|
127
|
+
navigate(url: string): Promise<{
|
|
128
|
+
url: string;
|
|
129
|
+
status?: number;
|
|
130
|
+
}>;
|
|
131
|
+
private waitForUrlChange;
|
|
132
|
+
reload(): Promise<{
|
|
133
|
+
url: string;
|
|
134
|
+
}>;
|
|
135
|
+
/**
|
|
136
|
+
* Wait for the page to stop changing, with a ceiling.
|
|
137
|
+
*
|
|
138
|
+
* `Page.loadEventFired` is the signal, but a single-page app may never fire
|
|
139
|
+
* another one after the first route, so the timeout is the real contract: this
|
|
140
|
+
* returns when the page looks ready *or* soon, and never blocks a turn on a
|
|
141
|
+
* page that streams forever.
|
|
142
|
+
*/
|
|
143
|
+
private settle;
|
|
144
|
+
url(): Promise<string>;
|
|
145
|
+
snapshot(opts?: SnapshotOptions): Promise<Snapshot>;
|
|
146
|
+
/** Where a ref sits on screen, in viewport coordinates. */
|
|
147
|
+
locate(ref: string): Promise<{
|
|
148
|
+
x: number;
|
|
149
|
+
y: number;
|
|
150
|
+
}>;
|
|
151
|
+
resolveObject(ref: string): Promise<string>;
|
|
152
|
+
/** Every open tab. Starts the browser if nothing has yet. */
|
|
153
|
+
tabs(): Promise<BrowserPage[]>;
|
|
154
|
+
/**
|
|
155
|
+
* Every open tab, described without attaching to any. Starts the browser if
|
|
156
|
+
* nothing has yet. In the person's own browser this is the whole window
|
|
157
|
+
* list, and a tab is only attached — and bannered — once it is selected.
|
|
158
|
+
*/
|
|
159
|
+
tabList(): Promise<Array<{
|
|
160
|
+
id: string;
|
|
161
|
+
url: string;
|
|
162
|
+
title?: string;
|
|
163
|
+
active: boolean;
|
|
164
|
+
mine: boolean;
|
|
165
|
+
}>>;
|
|
166
|
+
/** Open a tab and make it the active one. */
|
|
167
|
+
newTab(url?: string): Promise<BrowserPage>;
|
|
168
|
+
/** Where a specific tab is, without switching to it. */
|
|
169
|
+
tabUrl(page: BrowserPage): Promise<string>;
|
|
170
|
+
/** A non-launching description of the tabs for the session Browser pane. */
|
|
171
|
+
paneTabs(): Promise<Array<{
|
|
172
|
+
id: string;
|
|
173
|
+
url: string;
|
|
174
|
+
title?: string;
|
|
175
|
+
active: boolean;
|
|
176
|
+
mine?: false;
|
|
177
|
+
}>>;
|
|
178
|
+
/** Switch the pane and subsequent browser tools to an already-open tab. */
|
|
179
|
+
selectPaneTab(id: string): Promise<{
|
|
180
|
+
id: string;
|
|
181
|
+
url: string;
|
|
182
|
+
}>;
|
|
183
|
+
/**
|
|
184
|
+
* Give this conversation one of the person's own tabs, because they asked —
|
|
185
|
+
* from the extension's side panel, on the tab in front of them. Their asking
|
|
186
|
+
* is what makes it this conversation's tab; it is not a permission to act on
|
|
187
|
+
* the site, which the first action there still asks for as ever.
|
|
188
|
+
*/
|
|
189
|
+
adoptYourTab(id: string): Promise<{
|
|
190
|
+
id: string;
|
|
191
|
+
url: string;
|
|
192
|
+
}>;
|
|
193
|
+
/**
|
|
194
|
+
* Close one page without disturbing its siblings; the last one releases the
|
|
195
|
+
* target. A tab the person had open before the conversation was pointed at
|
|
196
|
+
* it is let go of rather than closed — it was theirs, not the agent's.
|
|
197
|
+
*/
|
|
198
|
+
closePaneTab(id: string): Promise<{
|
|
199
|
+
closed: string;
|
|
200
|
+
released?: boolean;
|
|
201
|
+
active?: string;
|
|
202
|
+
running: boolean;
|
|
203
|
+
}>;
|
|
204
|
+
/**
|
|
205
|
+
* What a pane needs to draw itself without starting anything.
|
|
206
|
+
*
|
|
207
|
+
* Asked on an interval by every open page, so it must never be the call that
|
|
208
|
+
* launches a browser: somebody who opened the pane to look at it has not
|
|
209
|
+
* asked for Chrome, and a pane that started one would make the feature cost
|
|
210
|
+
* memory for people who never use it.
|
|
211
|
+
*/
|
|
212
|
+
state(): {
|
|
213
|
+
running: boolean;
|
|
214
|
+
origin?: string;
|
|
215
|
+
presentation?: "stream" | "native";
|
|
216
|
+
mode?: BrowserSide;
|
|
217
|
+
policy?: BrowserPolicy;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* The page's own coordinate space.
|
|
221
|
+
*
|
|
222
|
+
* A screencast frame is not the page: Chrome scales it down, so a 1280-wide
|
|
223
|
+
* viewport arrives as a 756-wide picture. A pane that treated the picture's
|
|
224
|
+
* pixels as the page's would put every human click in the wrong place — near
|
|
225
|
+
* enough to look plausible, far enough to miss the button. This is what the
|
|
226
|
+
* pane scales by.
|
|
227
|
+
*/
|
|
228
|
+
viewport(): Promise<{
|
|
229
|
+
width: number;
|
|
230
|
+
height: number;
|
|
231
|
+
} | undefined>;
|
|
232
|
+
/** Frames for a viewer. Starts nothing — an idle session yields nothing. */
|
|
233
|
+
frames(opts?: FrameOptions): AsyncIterable<Buffer>;
|
|
234
|
+
/**
|
|
235
|
+
* Input from a person who has taken the pane over.
|
|
236
|
+
*
|
|
237
|
+
* The same channel the tools use, deliberately: a human click and a model
|
|
238
|
+
* click arrive at the page identically, so there is no second code path that
|
|
239
|
+
* can drift, and no state the page can be in that only one of them reaches.
|
|
240
|
+
*/
|
|
241
|
+
forward(event: BrowserInputEvent): Promise<void>;
|
|
242
|
+
consoleEntries(): readonly ConsoleEntry[];
|
|
243
|
+
networkEntries(): readonly NetworkEntry[];
|
|
244
|
+
/** Let go of both browsers: the built-in one closes, the person's is detached. */
|
|
245
|
+
close(): Promise<void>;
|
|
246
|
+
/** Let go of one browser, leaving the other as it is. */
|
|
247
|
+
private closeSide;
|
|
248
|
+
/**
|
|
249
|
+
* Change which browsers this session may use.
|
|
250
|
+
*
|
|
251
|
+
* Takes effect on the next browser call. Pinning it to one browser lets go
|
|
252
|
+
* of the other — the built-in one closes, the person's is only detached,
|
|
253
|
+
* their tabs never closed. Moving to auto keeps whatever is open, since
|
|
254
|
+
* either browser is now fair game.
|
|
255
|
+
*/
|
|
256
|
+
setMode(mode: BrowserPolicy): Promise<void>;
|
|
257
|
+
/**
|
|
258
|
+
* The external browser a sign-in can be imported from, and the sites it has
|
|
259
|
+
* open. Lists tabs only — nothing is attached, so the person's browser shows
|
|
260
|
+
* no debugging banner just because the dialog was opened.
|
|
261
|
+
*/
|
|
262
|
+
loginImportSources(): Promise<{
|
|
263
|
+
browser: string;
|
|
264
|
+
sites: ExternalSite[];
|
|
265
|
+
current?: string;
|
|
266
|
+
}>;
|
|
267
|
+
/**
|
|
268
|
+
* Copy the chosen sites' sign-in into the built-in browser's profile.
|
|
269
|
+
*
|
|
270
|
+
* Only ever called from the confirmation dialog. In extension mode this is
|
|
271
|
+
* also the migration: the session lets go of the person's browser (detaching,
|
|
272
|
+
* never closing their tabs) and continues in the built-in one, on the site it
|
|
273
|
+
* just imported.
|
|
274
|
+
*/
|
|
275
|
+
importLogin(sites: readonly string[]): Promise<{
|
|
276
|
+
browser: string;
|
|
277
|
+
imported: ImportedSite[];
|
|
278
|
+
migrated: boolean;
|
|
279
|
+
url?: string;
|
|
280
|
+
}>;
|
|
281
|
+
/**
|
|
282
|
+
* Offer an import when the built-in browser reaches a site the person has
|
|
283
|
+
* open in their own browser.
|
|
284
|
+
*
|
|
285
|
+
* Asked by the pane's state poll, so it never waits on the extension: the
|
|
286
|
+
* first call for a site starts one probe and answers nothing, and a later poll
|
|
287
|
+
* picks the result up. The probe lists tabs only and attaches to none.
|
|
288
|
+
*/
|
|
289
|
+
loginImportSuggestion(): {
|
|
290
|
+
site: string;
|
|
291
|
+
browser: string;
|
|
292
|
+
} | undefined;
|
|
293
|
+
/**
|
|
294
|
+
* Whether the person has this site open in their own browser, while this
|
|
295
|
+
* session works on it in the built-in one without its sign-in. The model is
|
|
296
|
+
* told, and decides; nothing moves on the strength of it. Lists tabs only,
|
|
297
|
+
* attaches to none, and gives up quickly when the extension is not there.
|
|
298
|
+
*/
|
|
299
|
+
openInYourBrowser(url: string, timeoutMs?: number): Promise<boolean>;
|
|
300
|
+
/** "Don't ask again" for one site, remembered with the shared profile. */
|
|
301
|
+
dismissLoginImport(site: string): Promise<void>;
|
|
302
|
+
private loginMemory;
|
|
303
|
+
/**
|
|
304
|
+
* The external browser, for the length of one read.
|
|
305
|
+
*
|
|
306
|
+
* In extension mode that is the session's own target. Otherwise a connection
|
|
307
|
+
* is opened for the read and closed after it, so the extension is free again
|
|
308
|
+
* and the person's tabs are detached, not closed.
|
|
309
|
+
*/
|
|
310
|
+
private withExternal;
|
|
311
|
+
/**
|
|
312
|
+
* Put localStorage in place before the site's own scripts run.
|
|
313
|
+
*
|
|
314
|
+
* Written from a script injected ahead of the document rather than after the
|
|
315
|
+
* load: a signed-out page that loaded first could overwrite the keys it finds
|
|
316
|
+
* missing, and would then need a reload that sees the same state it wrote.
|
|
317
|
+
*/
|
|
318
|
+
private seedLocalStorage;
|
|
319
|
+
}
|
|
320
|
+
export declare function originOf(url: string): string | undefined;
|