@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.
Files changed (72) hide show
  1. package/dist/agent/agent.d.ts +72 -0
  2. package/dist/agent/agent.js +114 -1
  3. package/dist/agent/agent.js.map +1 -1
  4. package/dist/agent/permissions.js +8 -0
  5. package/dist/agent/permissions.js.map +1 -1
  6. package/dist/browser/cdp.d.ts +75 -0
  7. package/dist/browser/cdp.js +136 -0
  8. package/dist/browser/cdp.js.map +1 -0
  9. package/dist/browser/chrome.d.ts +19 -0
  10. package/dist/browser/chrome.js +306 -0
  11. package/dist/browser/chrome.js.map +1 -0
  12. package/dist/browser/extension.d.ts +35 -0
  13. package/dist/browser/extension.js +297 -0
  14. package/dist/browser/extension.js.map +1 -0
  15. package/dist/browser/host-manifest.d.ts +78 -0
  16. package/dist/browser/host-manifest.js +166 -0
  17. package/dist/browser/host-manifest.js.map +1 -0
  18. package/dist/browser/host.d.ts +27 -0
  19. package/dist/browser/host.js +311 -0
  20. package/dist/browser/host.js.map +1 -0
  21. package/dist/browser/index.d.ts +26 -0
  22. package/dist/browser/index.js +15 -0
  23. package/dist/browser/index.js.map +1 -0
  24. package/dist/browser/login-import.d.ts +98 -0
  25. package/dist/browser/login-import.js +244 -0
  26. package/dist/browser/login-import.js.map +1 -0
  27. package/dist/browser/plugin.d.ts +109 -0
  28. package/dist/browser/plugin.js +22 -0
  29. package/dist/browser/plugin.js.map +1 -0
  30. package/dist/browser/presence.d.ts +29 -0
  31. package/dist/browser/presence.js +54 -0
  32. package/dist/browser/presence.js.map +1 -0
  33. package/dist/browser/provider.d.ts +17 -0
  34. package/dist/browser/provider.js +13 -0
  35. package/dist/browser/provider.js.map +1 -0
  36. package/dist/browser/screencast.d.ts +42 -0
  37. package/dist/browser/screencast.js +99 -0
  38. package/dist/browser/screencast.js.map +1 -0
  39. package/dist/browser/session.d.ts +320 -0
  40. package/dist/browser/session.js +837 -0
  41. package/dist/browser/session.js.map +1 -0
  42. package/dist/browser/snapshot.d.ts +49 -0
  43. package/dist/browser/snapshot.js +145 -0
  44. package/dist/browser/snapshot.js.map +1 -0
  45. package/dist/browser/socket.d.ts +15 -0
  46. package/dist/browser/socket.js +32 -0
  47. package/dist/browser/socket.js.map +1 -0
  48. package/dist/browser/target.d.ts +112 -0
  49. package/dist/browser/target.js +20 -0
  50. package/dist/browser/target.js.map +1 -0
  51. package/dist/browser/tools.d.ts +3 -0
  52. package/dist/browser/tools.js +537 -0
  53. package/dist/browser/tools.js.map +1 -0
  54. package/dist/config.d.ts +14 -0
  55. package/dist/config.js.map +1 -1
  56. package/dist/core/errors.d.ts +12 -0
  57. package/dist/core/errors.js +14 -1
  58. package/dist/core/errors.js.map +1 -1
  59. package/dist/harness.d.ts +49 -0
  60. package/dist/harness.js +97 -1
  61. package/dist/harness.js.map +1 -1
  62. package/dist/index.d.ts +1 -0
  63. package/dist/index.js +1 -0
  64. package/dist/index.js.map +1 -1
  65. package/dist/providers/piai.js +7 -2
  66. package/dist/providers/piai.js.map +1 -1
  67. package/dist/tools/define.d.ts +1 -0
  68. package/dist/tools/define.js +3 -0
  69. package/dist/tools/define.js.map +1 -1
  70. package/dist/tools/types.d.ts +11 -0
  71. package/dist/tools/types.js.map +1 -1
  72. 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;