@mind-harness/mh-browser 0.2.6 → 0.2.8
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/extension/manifest.json +1 -1
- package/extension/welcome.html +4 -0
- package/extension/welcome.js +10 -0
- package/lib/client.cjs +143 -319
- package/lib/index.js +1994 -1540
- package/lib/types/call.d.ts +23 -0
- package/lib/types/card.d.ts +1 -2
- package/lib/types/client.d.ts +6 -17
- package/lib/types/config.d.ts +4 -2
- package/lib/types/index.d.ts +2 -2
- package/lib/types/locales.d.ts +6 -2
- package/lib/types/location.d.ts +3 -1
- package/lib/types/routes.d.ts +43 -0
- package/lib/types/row.d.ts +2 -4
- package/lib/types/service/browser.d.ts +5 -0
- package/lib/types/service/extension.d.ts +7 -0
- package/lib/types/service/launch-plan.d.ts +30 -0
- package/lib/types/service/locate.d.ts +17 -1
- package/lib/types/service/profile.d.ts +11 -0
- package/lib/types/service/service.d.ts +10 -7
- package/lib/types/settings.d.ts +9 -6
- package/lib/types/types.d.ts +13 -1
- package/package.json +16 -31
- package/THIRD-PARTY-NOTICES +0 -23
- package/lib/typert.host.d.ts +0 -3
- package/lib/typert.host.js +0 -462
- package/lib/typert.remote-client.d.ts +0 -28
- package/lib/typert.remote-client.js +0 -96
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** One Host call from this package's client. Same shape the UI already reads. */
|
|
2
|
+
export type CallResult<T> = {
|
|
3
|
+
ok: true;
|
|
4
|
+
value: T;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
error: {
|
|
8
|
+
code: string;
|
|
9
|
+
message: string;
|
|
10
|
+
details?: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
export interface CallInit {
|
|
14
|
+
method: 'GET' | 'POST';
|
|
15
|
+
body?: unknown;
|
|
16
|
+
query?: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* `document.baseURI` keeps a mounted page on its prefix. dsh's file upload
|
|
20
|
+
* resolves the same way.
|
|
21
|
+
*/
|
|
22
|
+
export declare function call<T>(segment: string, init: CallInit, signal?: AbortSignal): Promise<CallResult<T>>;
|
|
23
|
+
//# sourceMappingURL=call.d.ts.map
|
package/lib/types/card.d.ts
CHANGED
|
@@ -15,10 +15,9 @@ export type RevealResult = {
|
|
|
15
15
|
};
|
|
16
16
|
export interface HandoverRowProps {
|
|
17
17
|
sessionId: string;
|
|
18
|
-
reason: string;
|
|
19
18
|
t: Translate;
|
|
20
19
|
reveal: (sessionId: string, signal: AbortSignal) => Promise<RevealResult>;
|
|
21
20
|
}
|
|
22
|
-
/** The open handover:
|
|
21
|
+
/** The open handover: a short line and the button that raises its window. */
|
|
23
22
|
export declare function HandoverRow(props: HandoverRowProps): ReactElement;
|
|
24
23
|
//# sourceMappingURL=card.d.ts.map
|
package/lib/types/client.d.ts
CHANGED
|
@@ -6,24 +6,15 @@ import type { SettingsFormScope } from './settings-form.ts';
|
|
|
6
6
|
import { type LocateFor } from './settings.ts';
|
|
7
7
|
/**
|
|
8
8
|
* Cordis services this client reads. `dsh.client.inject` is package load
|
|
9
|
-
* order, not this list.
|
|
9
|
+
* order, not this list.
|
|
10
10
|
*/
|
|
11
|
-
export declare const inject: readonly ["slots", "locale", "
|
|
12
|
-
export interface
|
|
11
|
+
export declare const inject: readonly ["slots", "locale", "uiConversation", "configForms"];
|
|
12
|
+
export interface MhBrowserApi {
|
|
13
13
|
revealHandover(sessionId: string, signal?: AbortSignal): Promise<RevealResult>;
|
|
14
14
|
locateFor: LocateFor;
|
|
15
15
|
}
|
|
16
|
-
interface RemoteCarrier {
|
|
17
|
-
$mount(contribution: object): Promise<() => Promise<void>>;
|
|
18
|
-
}
|
|
19
|
-
/** Props the session-scoped chat-node seat passes in. The session id is that seat's. */
|
|
20
16
|
export interface HostRowProps {
|
|
21
17
|
sessionId: string;
|
|
22
|
-
node: {
|
|
23
|
-
readonly data: {
|
|
24
|
-
readonly reason: string;
|
|
25
|
-
};
|
|
26
|
-
};
|
|
27
18
|
t: Translate;
|
|
28
19
|
}
|
|
29
20
|
export interface ClientHost {
|
|
@@ -55,13 +46,11 @@ export interface ClientHost {
|
|
|
55
46
|
};
|
|
56
47
|
};
|
|
57
48
|
effect(execute: () => () => void): unknown;
|
|
58
|
-
remote: RemoteCarrier & {
|
|
59
|
-
mhBrowser: MhBrowserRemote;
|
|
60
|
-
};
|
|
61
49
|
inject(names: readonly string[], apply: (ctx: ClientHost) => void): PromiseLike<unknown>;
|
|
62
50
|
}
|
|
51
|
+
/** Host calls used by the handover row and the settings lookup. */
|
|
52
|
+
export declare function browserApi(): MhBrowserApi;
|
|
63
53
|
export declare function apply(ctx: ClientHost): Promise<() => Promise<void>>;
|
|
64
54
|
/** Register the handover row. The tool call itself keeps the generic tool row. */
|
|
65
|
-
export declare function start(ctx: ClientHost): () => void;
|
|
66
|
-
export {};
|
|
55
|
+
export declare function start(ctx: ClientHost, api?: MhBrowserApi): () => void;
|
|
67
56
|
//# sourceMappingURL=client.d.ts.map
|
package/lib/types/config.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export declare const browserConfig: z<Schemastery.ObjectS<NoInfer<{
|
|
|
5
5
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
6
6
|
maxBytes: z<number, number, "defined">;
|
|
7
7
|
}>>, "defined">;
|
|
8
|
-
browser: z<"chrome" | "msedge" | "chromium", "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
8
|
+
browser: z<"auto" | "chrome" | "msedge" | "chromium", "auto" | "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
9
9
|
executablePath: z<string, string, "volatile">;
|
|
10
10
|
profileDir: z<string, string, "plain">;
|
|
11
11
|
headless: z<boolean, boolean, "defined">;
|
|
@@ -15,7 +15,7 @@ export declare const browserConfig: z<Schemastery.ObjectS<NoInfer<{
|
|
|
15
15
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
16
16
|
maxBytes: z<number, number, "defined">;
|
|
17
17
|
}>>, "defined">;
|
|
18
|
-
browser: z<"chrome" | "msedge" | "chromium", "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
18
|
+
browser: z<"auto" | "chrome" | "msedge" | "chromium", "auto" | "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
19
19
|
executablePath: z<string, string, "volatile">;
|
|
20
20
|
profileDir: z<string, string, "plain">;
|
|
21
21
|
headless: z<boolean, boolean, "defined">;
|
|
@@ -30,4 +30,6 @@ export type BrowserConfig = ReturnType<typeof browserConfig>;
|
|
|
30
30
|
export declare function defaultProfileDir(profile: {
|
|
31
31
|
name: string;
|
|
32
32
|
} | undefined, home?: string): string;
|
|
33
|
+
/** One subdirectory of the default profile root per browser, so logins do not cross browsers. */
|
|
34
|
+
export declare function profileDirFor(root: string, browser: string): string;
|
|
33
35
|
//# sourceMappingURL=config.d.ts.map
|
package/lib/types/index.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
11
11
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
12
12
|
maxBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
13
13
|
}>>, "defined">;
|
|
14
|
-
browser: import("@deepseek-ai/schemastery").default<"chrome" | "msedge" | "chromium", "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
14
|
+
browser: import("@deepseek-ai/schemastery").default<"auto" | "chrome" | "msedge" | "chromium", "auto" | "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
15
15
|
executablePath: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
16
16
|
profileDir: import("@deepseek-ai/schemastery").default<string, string, "plain">;
|
|
17
17
|
headless: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
@@ -21,7 +21,7 @@ export declare const Config: import("@deepseek-ai/schemastery").default<Schemast
|
|
|
21
21
|
}>>, Schemastery.ObjectT<NoInfer<{
|
|
22
22
|
maxBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
23
23
|
}>>, "defined">;
|
|
24
|
-
browser: import("@deepseek-ai/schemastery").default<"chrome" | "msedge" | "chromium", "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
24
|
+
browser: import("@deepseek-ai/schemastery").default<"auto" | "chrome" | "msedge" | "chromium", "auto" | "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
25
25
|
executablePath: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
26
26
|
profileDir: import("@deepseek-ai/schemastery").default<string, string, "plain">;
|
|
27
27
|
headless: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
package/lib/types/locales.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/** Dictionary namespace for the handover row. */
|
|
2
2
|
export declare const NS = "mh-browser";
|
|
3
3
|
export declare const zh: {
|
|
4
|
-
readonly waiting: "
|
|
5
|
-
readonly reveal: "
|
|
4
|
+
readonly waiting: "这一步要你在浏览器里做";
|
|
5
|
+
readonly reveal: "打开浏览器里的页面";
|
|
6
6
|
readonly notHandingOver: "这次交接已经结束";
|
|
7
7
|
readonly noTab: "没有可以去的页面";
|
|
8
8
|
readonly failed: "没能切到浏览器";
|
|
@@ -17,6 +17,10 @@ export declare const zh: {
|
|
|
17
17
|
readonly pathDoesNotExist: "不存在";
|
|
18
18
|
readonly pathIsDirectory: "是目录";
|
|
19
19
|
readonly pathDenied: "没有权限({code})";
|
|
20
|
+
readonly auto: "自动";
|
|
21
|
+
readonly browserUsing: "当前使用:{name}。";
|
|
22
|
+
readonly browserNone: "没有找到 Chrome 或 Edge。";
|
|
23
|
+
readonly installChrome: "安装 Chrome";
|
|
20
24
|
readonly chrome: "Google Chrome";
|
|
21
25
|
readonly msedge: "Microsoft Edge";
|
|
22
26
|
readonly chromium: "Chromium";
|
package/lib/types/location.d.ts
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
/** Where a browser name resolves when no path is configured. */
|
|
2
|
-
|
|
2
|
+
import type { BrowserChoice, BrowserName } from './types.ts';
|
|
3
|
+
export type { BrowserChoice, BrowserName };
|
|
3
4
|
export interface BrowserLocationMiss {
|
|
4
5
|
path: string;
|
|
5
6
|
reason: string;
|
|
6
7
|
}
|
|
7
8
|
export type BrowserLocation = {
|
|
8
9
|
found: string;
|
|
10
|
+
browser?: BrowserName;
|
|
9
11
|
} | {
|
|
10
12
|
missing: BrowserLocationMiss[];
|
|
11
13
|
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { IncomingMessage, ServerResponse } from 'node:http';
|
|
2
|
+
import type { Context } from '@deepseek-ai/cordis';
|
|
3
|
+
import type { BrowserLocation } from './location.ts';
|
|
4
|
+
import { type BrowserChoice } from './types.ts';
|
|
5
|
+
interface ApiRouteHost {
|
|
6
|
+
webServer: {
|
|
7
|
+
register(route: {
|
|
8
|
+
kind: 'prefix';
|
|
9
|
+
path: string;
|
|
10
|
+
handler(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
11
|
+
}): () => void;
|
|
12
|
+
};
|
|
13
|
+
connection: {
|
|
14
|
+
admit(request: {
|
|
15
|
+
headers: IncomingMessage['headers'];
|
|
16
|
+
}): {
|
|
17
|
+
readonly peer: unknown;
|
|
18
|
+
} | {
|
|
19
|
+
readonly rejection: 401 | 403;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
effect(execute: () => () => void): unknown;
|
|
23
|
+
}
|
|
24
|
+
export interface BrowserRouteHost extends ApiRouteHost {
|
|
25
|
+
mhBrowser: {
|
|
26
|
+
locateFor(browser: BrowserChoice, signal?: AbortSignal): Promise<BrowserLocation>;
|
|
27
|
+
revealHandover(sessionId: string, signal?: AbortSignal): Promise<{
|
|
28
|
+
status: 'revealed' | 'not-handing-over' | 'no-tab';
|
|
29
|
+
}>;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Routes for the browser client. A composition without `webServer` never
|
|
34
|
+
* starts this plugin; the browser tools do not depend on it.
|
|
35
|
+
*/
|
|
36
|
+
export declare const browserRoutesPlugin: {
|
|
37
|
+
name: string;
|
|
38
|
+
inject: readonly string[];
|
|
39
|
+
apply(ctx: Context): void;
|
|
40
|
+
};
|
|
41
|
+
export declare function registerBrowserRoutes(ctx: BrowserRouteHost): void;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=routes.d.ts.map
|
package/lib/types/row.d.ts
CHANGED
|
@@ -4,12 +4,10 @@
|
|
|
4
4
|
* the same key and hides the row; a hidden row is omitted from group order.
|
|
5
5
|
*/
|
|
6
6
|
export declare const HANDOVER_KIND = "browser-handover";
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
7
|
+
/** The row carries no call payload. The reason stays on the question card. */
|
|
8
|
+
export type HandoverRowData = Record<string, never>;
|
|
10
9
|
interface OpenCall {
|
|
11
10
|
readonly callId: string;
|
|
12
|
-
readonly reason: string;
|
|
13
11
|
readonly seq: number;
|
|
14
12
|
}
|
|
15
13
|
export interface HandoverTurnState {
|
|
@@ -8,6 +8,11 @@ export interface LaunchOptions {
|
|
|
8
8
|
profileDir: string;
|
|
9
9
|
/** Absolute path of the browser to launch. `~` is already expanded. */
|
|
10
10
|
executablePath?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Pass `channel`. False when a path was configured without naming a browser:
|
|
13
|
+
* the path is launched as itself.
|
|
14
|
+
*/
|
|
15
|
+
channel?: boolean;
|
|
11
16
|
}
|
|
12
17
|
/**
|
|
13
18
|
* Playwright appends `--no-sandbox` unless this is true, and branded Chrome
|
|
@@ -11,6 +11,7 @@ export declare function extensionDir(): string;
|
|
|
11
11
|
export declare class Extension {
|
|
12
12
|
private readonly context;
|
|
13
13
|
private readonly id;
|
|
14
|
+
private readonly browserSession;
|
|
14
15
|
private workerPage;
|
|
15
16
|
private constructor();
|
|
16
17
|
static load(context: BrowserContext, browserSession: CDPSession): Promise<Extension>;
|
|
@@ -30,6 +31,12 @@ export declare class Extension {
|
|
|
30
31
|
private answer;
|
|
31
32
|
private worker;
|
|
32
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* The service worker, reloading the extension once when it is gone.
|
|
36
|
+
* A worker that comes back on its own during the first wait is used as it is.
|
|
37
|
+
* After a reload that still has no worker, the extension was turned off.
|
|
38
|
+
*/
|
|
39
|
+
export declare function restoreWorker(context: BrowserContext, id: string, reload: () => Promise<void>, signal?: AbortSignal, appearMs?: number): Promise<Worker>;
|
|
33
40
|
/** The extension's service worker. Looks once more after the wait times out. */
|
|
34
41
|
export declare function findWorker(context: BrowserContext, id: string, timeoutMs?: number): Promise<Worker>;
|
|
35
42
|
//# sourceMappingURL=extension.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { BrowserLocation } from '../location.ts';
|
|
2
|
+
import type { BrowserChoice, BrowserName } from '../types.ts';
|
|
3
|
+
import { type LocateEnv } from './locate.ts';
|
|
4
|
+
/** What one launch uses. `channel` is false when the path does not name a browser channel. */
|
|
5
|
+
export interface LaunchPlan {
|
|
6
|
+
browser: BrowserName;
|
|
7
|
+
channel: boolean;
|
|
8
|
+
profileDir: string;
|
|
9
|
+
executablePath?: string;
|
|
10
|
+
/** Written after the browser starts. Absent when a path was given without naming a browser. */
|
|
11
|
+
remember?: BrowserName;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Which browser, path, and profile directory to launch.
|
|
15
|
+
* A configured path is checked and never replaced. Automatic selection keeps the
|
|
16
|
+
* remembered browser while it can be found, then Chrome, then Edge.
|
|
17
|
+
* Playwright's Chromium is used only when it is selected, or when it is the remembered one.
|
|
18
|
+
*/
|
|
19
|
+
export declare function planLaunch(input: {
|
|
20
|
+
choice: BrowserChoice;
|
|
21
|
+
configured: string | undefined;
|
|
22
|
+
root: string;
|
|
23
|
+
/** The default profile root gets one subdirectory per browser. A configured directory does not. */
|
|
24
|
+
split: boolean;
|
|
25
|
+
env: LocateEnv;
|
|
26
|
+
remembered: BrowserName | undefined;
|
|
27
|
+
bundled: BrowserLocation;
|
|
28
|
+
signal?: AbortSignal;
|
|
29
|
+
}): Promise<LaunchPlan>;
|
|
30
|
+
//# sourceMappingURL=launch-plan.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { BrowserLocation, BrowserLocationMiss } from '../location.ts';
|
|
2
|
-
import type { BrowserName } from '../types.ts';
|
|
2
|
+
import type { BrowserName, MissingBrowser } from '../types.ts';
|
|
3
3
|
/** A browser the person installs. Playwright's Chromium is not located this way. */
|
|
4
4
|
export type InstalledBrowser = Exclude<BrowserName, 'chromium'>;
|
|
5
5
|
/** `ok`, or the errno from checking that the file can be executed. */
|
|
@@ -39,6 +39,22 @@ export declare function checkConfigured(configured: string, env: LocateEnv): {
|
|
|
39
39
|
};
|
|
40
40
|
/** Failure for a path the configuration names. */
|
|
41
41
|
export declare function configuredPathError(path: string, code: string): Error;
|
|
42
|
+
/** Chrome and Edge were both missed. The message asks for Chrome only. */
|
|
43
|
+
export declare class BrowserNotFoundError extends Error {
|
|
44
|
+
readonly notFound: MissingBrowser;
|
|
45
|
+
constructor(misses: {
|
|
46
|
+
browser: InstalledBrowser;
|
|
47
|
+
missing: BrowserLocationMiss[];
|
|
48
|
+
}[]);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* The installed browser to launch when the choice is automatic.
|
|
52
|
+
* The remembered browser wins while it can still be found; otherwise Chrome, then Edge.
|
|
53
|
+
*/
|
|
54
|
+
export declare function resolveAuto(env: LocateEnv, remembered: BrowserName | undefined, signal?: AbortSignal): Promise<{
|
|
55
|
+
browser: InstalledBrowser;
|
|
56
|
+
path: string;
|
|
57
|
+
}>;
|
|
42
58
|
/** Failure listing every path that was tried. */
|
|
43
59
|
export declare function browserNotFoundError(browser: InstalledBrowser, missing: BrowserLocationMiss[]): Error;
|
|
44
60
|
/**
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { BrowserName } from '../types.ts';
|
|
2
|
+
/** The browser recorded after the last successful launch, if the file names one. */
|
|
3
|
+
export declare function readLastBrowser(root: string): Promise<BrowserName | undefined>;
|
|
4
|
+
/** Remember which browser actually launched, so automatic selection keeps using it. */
|
|
5
|
+
export declare function writeLastBrowser(root: string, browser: BrowserName): Promise<void>;
|
|
6
|
+
/**
|
|
7
|
+
* Move a profile that older versions kept in the root into `browser`'s subdirectory.
|
|
8
|
+
* A root without Chrome's `Local State`, or one whose subdirectory already exists, stays as it is.
|
|
9
|
+
*/
|
|
10
|
+
export declare function migrateLegacyProfile(root: string, browser: string): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=profile.d.ts.map
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { Context } from '@deepseek-ai/cordis';
|
|
2
|
-
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
1
|
+
import { Context, Service } from '@deepseek-ai/cordis';
|
|
3
2
|
import type { BrowserConfig } from '../config.ts';
|
|
4
3
|
import type { BrowserLocation } from '../location.ts';
|
|
5
4
|
import type { HeldPage, PresenceReceipt, PresenceRecord, PresenceSource } from '../presence/record.ts';
|
|
6
5
|
import type { PendingOp } from '../presence/fold.ts';
|
|
7
|
-
import type {
|
|
6
|
+
import type { BrowserChoice, Download, FetchResponseBody, InvokeCall, InvokeSent, PageError, PageOp, PageView, TabInfo, WaitFor } from '../types.ts';
|
|
8
7
|
import { type Taken } from './control.ts';
|
|
9
8
|
import { testHooks, type TestHooks } from './test-hooks.ts';
|
|
10
9
|
declare module '@deepseek-ai/cordis' {
|
|
@@ -34,10 +33,13 @@ export interface HandBack extends Taken {
|
|
|
34
33
|
* the session's browser. `act` returns a snapshot, including on a page that
|
|
35
34
|
* also has an Agent View.
|
|
36
35
|
*/
|
|
37
|
-
export declare class MhBrowserService extends
|
|
36
|
+
export declare class MhBrowserService extends Service {
|
|
38
37
|
private readonly windows;
|
|
39
38
|
private readonly headless;
|
|
40
|
-
|
|
39
|
+
/** Profile root. The default root gets one subdirectory per browser at launch. */
|
|
40
|
+
private readonly profileRoot;
|
|
41
|
+
/** A configured profile directory is used as given, without a per-browser subdirectory. */
|
|
42
|
+
private readonly splitProfile;
|
|
41
43
|
private readonly browserName;
|
|
42
44
|
private readonly executablePath;
|
|
43
45
|
/** Tests replace the machine lookup. Unset uses this machine. */
|
|
@@ -130,8 +132,10 @@ export declare class MhBrowserService extends TypertRemoteService {
|
|
|
130
132
|
/**
|
|
131
133
|
* Where `browser` would be launched from when no path is configured.
|
|
132
134
|
* The configured path is not consulted: the answer is what an empty path uses.
|
|
135
|
+
* `auto` reports the browser automatic selection would launch.
|
|
133
136
|
*/
|
|
134
|
-
locateFor(browser:
|
|
137
|
+
locateFor(browser: BrowserChoice, signal?: AbortSignal): Promise<BrowserLocation>;
|
|
138
|
+
private locateAuto;
|
|
135
139
|
act(owner: string, tab: string, op: PageOp, signal?: AbortSignal): Promise<PageView>;
|
|
136
140
|
holdHandover(owner: string, tab: string): void;
|
|
137
141
|
releaseHandover(owner: string): void;
|
|
@@ -264,7 +268,6 @@ export declare class MhBrowserService extends TypertRemoteService {
|
|
|
264
268
|
private presenceUrls;
|
|
265
269
|
private snapshotNamed;
|
|
266
270
|
private exclusive;
|
|
267
|
-
private launchChoice;
|
|
268
271
|
private locateEnv;
|
|
269
272
|
private idle;
|
|
270
273
|
/**
|
package/lib/types/settings.d.ts
CHANGED
|
@@ -5,15 +5,20 @@ import { type FieldState, type FieldWrite, type FormShell, type SettingsFormScop
|
|
|
5
5
|
export declare const ENTRY_ID = "mh-browser";
|
|
6
6
|
/** `plugins.row.config` key: the bundle package, then the row id. */
|
|
7
7
|
export declare const ROW_KEY = "@mind-harness/mh-bundle#mh-browser";
|
|
8
|
-
export declare const BROWSER_CHOICES: readonly ["chrome", "msedge", "chromium"];
|
|
8
|
+
export declare const BROWSER_CHOICES: readonly ["auto", "chrome", "msedge", "chromium"];
|
|
9
9
|
export type BrowserChoice = (typeof BROWSER_CHOICES)[number];
|
|
10
|
+
/** Google's download page. Edge is not offered: its developer-mode prompt can disable the agent extension. */
|
|
11
|
+
export declare const CHROME_INSTALL = "https://www.google.com/chrome/";
|
|
10
12
|
/** Matches the host's `BrowserLocation`. The client bundle cannot import the host file. */
|
|
13
|
+
export type NamedBrowser = 'chrome' | 'msedge' | 'chromium';
|
|
11
14
|
export type BrowserLocation = {
|
|
12
15
|
found: string;
|
|
16
|
+
browser?: NamedBrowser;
|
|
13
17
|
} | {
|
|
14
18
|
missing: {
|
|
15
19
|
path: string;
|
|
16
20
|
reason: string;
|
|
21
|
+
browser?: NamedBrowser;
|
|
17
22
|
}[];
|
|
18
23
|
};
|
|
19
24
|
export type LocateResult = {
|
|
@@ -32,6 +37,7 @@ export type LookupView = {
|
|
|
32
37
|
} | {
|
|
33
38
|
status: 'found';
|
|
34
39
|
path: string;
|
|
40
|
+
browser?: NamedBrowser;
|
|
35
41
|
} | {
|
|
36
42
|
status: 'missing';
|
|
37
43
|
tried: {
|
|
@@ -66,17 +72,14 @@ export interface SettingsHost {
|
|
|
66
72
|
}) => ReactElement | null): () => void;
|
|
67
73
|
};
|
|
68
74
|
configForms: ConfigForms;
|
|
69
|
-
remote: {
|
|
70
|
-
mhBrowser: {
|
|
71
|
-
locateFor: LocateFor;
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
75
|
effect(execute: () => () => void): unknown;
|
|
75
76
|
}
|
|
76
77
|
/** Empty text clears the field. Anything else must be absolute, or start with `~`. */
|
|
77
78
|
export declare function parseExecutable(text: string): FieldWrite | undefined;
|
|
78
79
|
/** Placeholder for an empty path field: the path an empty value would use. */
|
|
79
80
|
export declare function pathPlaceholder(lookup: LookupView, browser: BrowserChoice, t: Translate): string | undefined;
|
|
81
|
+
/** The sentence under the browser menu: which browser automatic selection is using. */
|
|
82
|
+
export declare function browserStatus(lookup: LookupView, browser: BrowserChoice, t: Translate): string;
|
|
80
83
|
/** The full path, or every place that was tried. Absent while looking or after a failed lookup. */
|
|
81
84
|
export declare function pathHelpText(lookup: LookupView, t: Translate): string | undefined;
|
|
82
85
|
/**
|
package/lib/types/types.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
/** Public browser types. Playwright types stay inside the service. */
|
|
2
2
|
export type BrowserName = 'chrome' | 'msedge' | 'chromium';
|
|
3
|
+
/** `auto` keeps the browser that launched last, or Chrome and then Edge. */
|
|
4
|
+
export type BrowserChoice = BrowserName | 'auto';
|
|
5
|
+
/** An automatic launch found neither Chrome nor Edge. Plugins read this; the model sees the message. */
|
|
6
|
+
export interface MissingBrowser {
|
|
7
|
+
browsers: ('chrome' | 'msedge')[];
|
|
8
|
+
tried: {
|
|
9
|
+
browser: 'chrome' | 'msedge';
|
|
10
|
+
path: string;
|
|
11
|
+
reason: string;
|
|
12
|
+
}[];
|
|
13
|
+
}
|
|
3
14
|
export type OwnerId = string;
|
|
4
15
|
export type TabId = string;
|
|
5
16
|
export interface WaitFor {
|
|
@@ -181,7 +192,8 @@ export type BrowserCode = (typeof BROWSER_CODES)[number];
|
|
|
181
192
|
export declare class MhBrowserError extends Error {
|
|
182
193
|
readonly code: BrowserCode;
|
|
183
194
|
readonly page?: PageView;
|
|
184
|
-
|
|
195
|
+
readonly notFound?: MissingBrowser;
|
|
196
|
+
constructor(code: BrowserCode, message: string, page?: PageView, notFound?: MissingBrowser);
|
|
185
197
|
}
|
|
186
198
|
/** Owner of the person's own window. It belongs to no Session. */
|
|
187
199
|
export declare const PERSON_OWNER = "person";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mind-harness/mh-browser",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "Opens pages in a real browser for the agent, keeps chosen Agent Views in context, and hands the browser to you when a person is needed.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"files": [
|
|
@@ -8,15 +8,10 @@
|
|
|
8
8
|
"lib/types/representation/agent-view.js",
|
|
9
9
|
"lib/types/location.js",
|
|
10
10
|
"lib/types/**/*.d.ts",
|
|
11
|
-
"lib/typert.host.js",
|
|
12
|
-
"lib/typert.host.d.ts",
|
|
13
|
-
"lib/typert.remote-client.js",
|
|
14
|
-
"lib/typert.remote-client.d.ts",
|
|
15
11
|
"lib/client.cjs",
|
|
16
12
|
"locale/*.json",
|
|
17
13
|
"icon.svg",
|
|
18
|
-
"extension/*"
|
|
19
|
-
"THIRD-PARTY-NOTICES"
|
|
14
|
+
"extension/*"
|
|
20
15
|
],
|
|
21
16
|
"type": "module",
|
|
22
17
|
"main": "./lib/index.js",
|
|
@@ -34,14 +29,6 @@
|
|
|
34
29
|
"types": "./lib/types/location.d.ts",
|
|
35
30
|
"default": "./lib/types/location.js"
|
|
36
31
|
},
|
|
37
|
-
"./typert": {
|
|
38
|
-
"types": "./lib/typert.host.d.ts",
|
|
39
|
-
"default": "./lib/typert.host.js"
|
|
40
|
-
},
|
|
41
|
-
"./remote": {
|
|
42
|
-
"types": "./lib/typert.remote-client.d.ts",
|
|
43
|
-
"default": "./lib/typert.remote-client.js"
|
|
44
|
-
},
|
|
45
32
|
"./client": {
|
|
46
33
|
"types": "./lib/types/client.d.ts",
|
|
47
34
|
"default": "./lib/client.cjs"
|
|
@@ -60,21 +47,20 @@
|
|
|
60
47
|
},
|
|
61
48
|
"devDependencies": {
|
|
62
49
|
"@deepseek-ai/cordis": "~4.1.0",
|
|
63
|
-
"@deepseek-ai/dsh-agent": "^0.2.2-rc.
|
|
64
|
-
"@deepseek-ai/dsh-agent-loop": "^0.2.2-rc.
|
|
65
|
-
"@deepseek-ai/dsh-agent-loop-testkit": "^0.2.2-rc.
|
|
66
|
-
"@deepseek-ai/dsh-attachment": "^0.2.2-rc.
|
|
67
|
-
"@deepseek-ai/dsh-browser-use": "^0.2.2-rc.
|
|
68
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.2.2-rc.
|
|
69
|
-
"@deepseek-ai/dsh-home-paths": "^0.2.2-rc.
|
|
70
|
-
"@deepseek-ai/dsh-llm": "^0.2.2-rc.
|
|
71
|
-
"@deepseek-ai/dsh-llm-mock-server": "^0.2.2-rc.
|
|
72
|
-
"@deepseek-ai/dsh-sandbox-policy": "^0.2.2-rc.
|
|
73
|
-
"@deepseek-ai/dsh-session": "^0.2.2-rc.
|
|
74
|
-
"@deepseek-ai/dsh-session-projection": "^0.2.2-rc.
|
|
75
|
-
"@deepseek-ai/dsh-tools": "^0.2.2-rc.
|
|
76
|
-
"@deepseek-ai/dsh-
|
|
77
|
-
"@deepseek-ai/dsh-user-questions": "^0.2.2-rc.1",
|
|
50
|
+
"@deepseek-ai/dsh-agent": "^0.2.2-rc.2",
|
|
51
|
+
"@deepseek-ai/dsh-agent-loop": "^0.2.2-rc.2",
|
|
52
|
+
"@deepseek-ai/dsh-agent-loop-testkit": "^0.2.2-rc.2",
|
|
53
|
+
"@deepseek-ai/dsh-attachment": "^0.2.2-rc.2",
|
|
54
|
+
"@deepseek-ai/dsh-browser-use": "^0.2.2-rc.2",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.2.2-rc.2",
|
|
56
|
+
"@deepseek-ai/dsh-home-paths": "^0.2.2-rc.2",
|
|
57
|
+
"@deepseek-ai/dsh-llm": "^0.2.2-rc.2",
|
|
58
|
+
"@deepseek-ai/dsh-llm-mock-server": "^0.2.2-rc.2",
|
|
59
|
+
"@deepseek-ai/dsh-sandbox-policy": "^0.2.2-rc.2",
|
|
60
|
+
"@deepseek-ai/dsh-session": "^0.2.2-rc.2",
|
|
61
|
+
"@deepseek-ai/dsh-session-projection": "^0.2.2-rc.2",
|
|
62
|
+
"@deepseek-ai/dsh-tools": "^0.2.2-rc.2",
|
|
63
|
+
"@deepseek-ai/dsh-user-questions": "^0.2.2-rc.2",
|
|
78
64
|
"@deepseek-ai/schemastery": "~3.19.0",
|
|
79
65
|
"@types/react": "^19",
|
|
80
66
|
"@types/react-dom": "^19",
|
|
@@ -87,7 +73,6 @@
|
|
|
87
73
|
"@deepseek-ai/dsh-home-paths": ">=0.2.2-rc.1 <0.2.3-0",
|
|
88
74
|
"@deepseek-ai/dsh-llm": ">=0.2.2-rc.1 <0.2.3-0",
|
|
89
75
|
"@deepseek-ai/dsh-tools": ">=0.2.2-rc.1 <0.2.3-0",
|
|
90
|
-
"@deepseek-ai/dsh-typert-protocol": ">=0.2.2-rc.1 <0.2.3-0",
|
|
91
76
|
"@deepseek-ai/dsh-user-questions": ">=0.2.2-rc.1 <0.2.3-0",
|
|
92
77
|
"@deepseek-ai/schemastery": "^3.19.0",
|
|
93
78
|
"react": "^19.2.8"
|
package/THIRD-PARTY-NOTICES
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
lib/client.cjs includes code from @deepseek-ai/dsh-typert-protocol, distributed under the following license.
|
|
2
|
-
|
|
3
|
-
MIT License
|
|
4
|
-
|
|
5
|
-
Copyright (c) 2026 DeepSeek
|
|
6
|
-
|
|
7
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
-
in the Software without restriction, including without limitation the rights
|
|
10
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
-
furnished to do so, subject to the following conditions:
|
|
13
|
-
|
|
14
|
-
The above copyright notice and this permission notice shall be included in all
|
|
15
|
-
copies or substantial portions of the Software.
|
|
16
|
-
|
|
17
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
-
SOFTWARE.
|
package/lib/typert.host.d.ts
DELETED