@mind-harness/mh-browser 0.2.5 → 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/extension/manifest.json +1 -1
- package/lib/client.cjs +772 -51
- package/lib/index.js +449 -49
- package/lib/typert.host.js +88 -4
- package/lib/typert.remote-client.d.ts +4 -0
- package/lib/typert.remote-client.js +45 -1
- package/lib/types/client.d.ts +15 -1
- package/lib/types/config.d.ts +23 -10
- package/lib/types/index.d.ts +23 -2
- package/lib/types/locales.d.ts +22 -0
- package/lib/types/location.d.ts +12 -0
- package/lib/types/location.js +3 -0
- package/lib/types/service/browser.d.ts +11 -5
- package/lib/types/service/control.d.ts +5 -0
- package/lib/types/service/locate.d.ts +65 -0
- package/lib/types/service/service.d.ts +34 -3
- package/lib/types/service/test-hooks.d.ts +3 -0
- package/lib/types/settings-form.d.ts +142 -0
- package/lib/types/settings.d.ts +121 -0
- package/lib/types/typeprobe.d.ts +49 -0
- package/package.json +10 -2
package/lib/typert.host.js
CHANGED
|
@@ -3,18 +3,62 @@ import { z } from 'zod'
|
|
|
3
3
|
|
|
4
4
|
import { createTypertRemoteInfo } from '@deepseek-ai/dsh-typert-protocol/remote-info'
|
|
5
5
|
|
|
6
|
+
let _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema$value
|
|
7
|
+
const _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema = () => (_mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema$value ??= z.union([z.literal("chrome"), z.literal("msedge"), z.literal("chromium")]))
|
|
8
|
+
let _mind_harness_mh_browser_mhBrowser_locateFor_result$schema$value
|
|
9
|
+
const _mind_harness_mh_browser_mhBrowser_locateFor_result$schema = () => (_mind_harness_mh_browser_mhBrowser_locateFor_result$schema$value ??= z.union([z.object({
|
|
10
|
+
'found': z.string(),
|
|
11
|
+
}), z.object({
|
|
12
|
+
'missing': z.array(z.object({
|
|
13
|
+
'path': z.string(),
|
|
14
|
+
'reason': z.string(),
|
|
15
|
+
})),
|
|
16
|
+
})]))
|
|
6
17
|
let _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema$value
|
|
7
18
|
const _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema = () => (_mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema$value ??= z.string())
|
|
8
19
|
let _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema$value
|
|
9
20
|
const _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema = () => (_mind_harness_mh_browser_mhBrowser_revealHandover_result$schema$value ??= z.object({
|
|
10
21
|
'status': z.union([z.literal("revealed"), z.literal("not-handing-over"), z.literal("no-tab")]),
|
|
11
22
|
}))
|
|
23
|
+
let _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema$value
|
|
24
|
+
const _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema = () => (_mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema$value ??= z.union([z.literal("chrome"), z.literal("msedge"), z.literal("chromium")]))
|
|
12
25
|
let _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema$value
|
|
13
26
|
const _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema = () => (_mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema$value ??= z.string())
|
|
14
27
|
|
|
15
28
|
const $remote = createTypertRemoteInfo({
|
|
16
29
|
package: '@mind-harness/mh-browser',
|
|
17
30
|
methods: {
|
|
31
|
+
'mhBrowser/locateFor': {
|
|
32
|
+
service: 'mhBrowser',
|
|
33
|
+
description: 'Where `browser` would be launched from when no path is configured. The configured path is not consulted: the answer is what an empty path uses.',
|
|
34
|
+
invocation: { kind: 'direct' },
|
|
35
|
+
parameters: [
|
|
36
|
+
{
|
|
37
|
+
name: 'browser',
|
|
38
|
+
source: 'json',
|
|
39
|
+
codec: {
|
|
40
|
+
mode: 'strict',
|
|
41
|
+
typeSymbol: '@mind-harness/mh-browser/location#BrowserName',
|
|
42
|
+
create: _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema,
|
|
43
|
+
jsonSchema: {"type":"string","enum":["chrome","msedge","chromium"]},
|
|
44
|
+
},
|
|
45
|
+
strictCodec: {
|
|
46
|
+
mode: 'strict',
|
|
47
|
+
typeSymbol: '@mind-harness/mh-browser/location#BrowserName',
|
|
48
|
+
create: _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema,
|
|
49
|
+
jsonSchema: {"type":"string","enum":["chrome","msedge","chromium"]},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
cancellation: { parameter: 'signal' },
|
|
54
|
+
result: {
|
|
55
|
+
mode: 'strict',
|
|
56
|
+
typeSymbol: '@mind-harness/mh-browser/location#BrowserLocation',
|
|
57
|
+
create: _mind_harness_mh_browser_mhBrowser_locateFor_result$schema,
|
|
58
|
+
jsonSchemaError: 'typert tool schema: selected union branches overlap or have no required discriminator',
|
|
59
|
+
},
|
|
60
|
+
sourceLocation: {"file":"packages/mh-browser/src/service/service.ts","line":474,"column":9},
|
|
61
|
+
},
|
|
18
62
|
'mhBrowser/revealHandover': {
|
|
19
63
|
service: 'mhBrowser',
|
|
20
64
|
description: 'The person asked to see the page this Session handed over.',
|
|
@@ -44,7 +88,7 @@ const $remote = createTypertRemoteInfo({
|
|
|
44
88
|
create: _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema,
|
|
45
89
|
jsonSchema: {"type":"object","properties":{"status":{"type":"string","enum":["revealed","not-handing-over","no-tab"]}},"required":["status"],"additionalProperties":true},
|
|
46
90
|
},
|
|
47
|
-
sourceLocation: {"file":"packages/mh-browser/src/service/service.ts","line":
|
|
91
|
+
sourceLocation: {"file":"packages/mh-browser/src/service/service.ts","line":734,"column":9},
|
|
48
92
|
},
|
|
49
93
|
},
|
|
50
94
|
}, z)
|
|
@@ -172,6 +216,13 @@ export const TYPERT = {
|
|
|
172
216
|
"name": "[testHooks]",
|
|
173
217
|
"signature": "[testHooks](): TestHooks"
|
|
174
218
|
},
|
|
219
|
+
{
|
|
220
|
+
"kind": "method",
|
|
221
|
+
"name": "locateFor",
|
|
222
|
+
"signature": "@Remote async locateFor(browser: BrowserName, signal?: AbortSignal): Promise<BrowserLocation>",
|
|
223
|
+
"summary": "Where `browser` would be launched from when no path is configured.",
|
|
224
|
+
"jsDoc": "/**\n * Where `browser` would be launched from when no path is configured.\n * The configured path is not consulted: the answer is what an empty path uses.\n */"
|
|
225
|
+
},
|
|
175
226
|
{
|
|
176
227
|
"kind": "method",
|
|
177
228
|
"name": "act",
|
|
@@ -265,7 +316,7 @@ export const TYPERT = {
|
|
|
265
316
|
"name": "takePersonHandback",
|
|
266
317
|
"signature": "takePersonHandback(owner: string): HandBack | undefined",
|
|
267
318
|
"summary": "The person took over between turns.",
|
|
268
|
-
"jsDoc": "/**\n * The person took over between turns. The next message they send is the\n * hand-back. A handover that is still waiting on its card is not.\n */"
|
|
319
|
+
"jsDoc": "/**\n * The person took over between turns. The next message they send is the\n * hand-back. A handover that is still waiting on its card is not.\n * The addresses are read before a waiting restart closes the pages.\n */"
|
|
269
320
|
}
|
|
270
321
|
],
|
|
271
322
|
"types": [
|
|
@@ -273,6 +324,18 @@ export const TYPERT = {
|
|
|
273
324
|
"name": "ActionResponse",
|
|
274
325
|
"declaration": "export interface ActionResponse {\n name: string;\n status?: number;\n location?: string;\n mediaType?: string;\n body?: string;\n bytes?: number;\n lost?: boolean;\n}"
|
|
275
326
|
},
|
|
327
|
+
{
|
|
328
|
+
"name": "BrowserLocation",
|
|
329
|
+
"declaration": "export type BrowserLocation = { found: string; } | { missing: BrowserLocationMiss[]; };"
|
|
330
|
+
},
|
|
331
|
+
{
|
|
332
|
+
"name": "BrowserLocationMiss",
|
|
333
|
+
"declaration": "export interface BrowserLocationMiss {\n path: string;\n reason: string;\n}"
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
"name": "BrowserName",
|
|
337
|
+
"declaration": "export type BrowserName = 'chrome' | 'msedge' | 'chromium';"
|
|
338
|
+
},
|
|
276
339
|
{
|
|
277
340
|
"name": "Dialog",
|
|
278
341
|
"declaration": "export interface Dialog {\n type: string;\n message: string;\n}"
|
|
@@ -293,6 +356,10 @@ export const TYPERT = {
|
|
|
293
356
|
"name": "HeldPage",
|
|
294
357
|
"declaration": "export interface HeldPage {\n url: string;\n source: PresenceSource;\n state: 'committed' | 'pending';\n order: number;\n seen?: { version?: string; digest: string; observedAt: string; id?: string; } | { absent: string; };\n title?: string;\n representation?: 'agent-view' | 'snapshot';\n body?: string;\n agentViewError?: string;\n fragment?: string;\n requires?: string[];\n viewUrl?: string;\n}"
|
|
295
358
|
},
|
|
359
|
+
{
|
|
360
|
+
"name": "InstalledBrowser",
|
|
361
|
+
"declaration": "export type InstalledBrowser = Exclude<BrowserName, 'chromium'>;"
|
|
362
|
+
},
|
|
296
363
|
{
|
|
297
364
|
"name": "InvokeCall",
|
|
298
365
|
"declaration": "export interface InvokeCall {\n name: string;\n item?: string;\n input?: Record<string, unknown>;\n shown: { url: string; text: string; };\n}"
|
|
@@ -301,6 +368,10 @@ export const TYPERT = {
|
|
|
301
368
|
"name": "InvokeSent",
|
|
302
369
|
"declaration": "export interface InvokeSent {\n schemaRejected: boolean;\n response?: ActionResponse;\n page: PageView | PageError;\n}"
|
|
303
370
|
},
|
|
371
|
+
{
|
|
372
|
+
"name": "LocateEnv",
|
|
373
|
+
"declaration": "export interface LocateEnv {\n platform: NodeJS.Platform;\n env: NodeJS.ProcessEnv;\n home: string;\n access(path: string): PathAccess;\n discover(browser: InstalledBrowser, signal?: AbortSignal): Promise<string[]>;\n}"
|
|
374
|
+
},
|
|
304
375
|
{
|
|
305
376
|
"name": "Modifier",
|
|
306
377
|
"declaration": "export type Modifier = 'Alt' | 'Control' | 'ControlOrMeta' | 'Meta' | 'Shift';"
|
|
@@ -317,6 +388,10 @@ export const TYPERT = {
|
|
|
317
388
|
"name": "PageView",
|
|
318
389
|
"declaration": "export interface PageView {\n tab?: TabId;\n url: string;\n title: string;\n observedAt: string;\n representation: { kind: 'agent-view'; text: string; version?: string; href?: string; } | { kind: 'snapshot'; text: string; agentViewError?: string; agentView?: { version?: string; }; };\n fragment?: string;\n status?: number;\n mediaType?: string;\n body?: string;\n inPresence: boolean;\n headerOnly?: boolean;\n dialog?: Dialog;\n incomplete?: { load: boolean; pendingRequests: number; };\n waited?: { met: 'text' | 'textGone' | 'time' | false; seconds: number; };\n download?: Download;\n summary?: string;\n detail?: string;\n writes?: { method: string; origin: string; fromCall: boolean; count: number; }[];\n shot?: { mediaType: 'image/png' | 'image/jpeg' | 'image/webp'; bytes: Uint8Array; };\n}"
|
|
319
390
|
},
|
|
391
|
+
{
|
|
392
|
+
"name": "PathAccess",
|
|
393
|
+
"declaration": "export type PathAccess = 'ok' | { code: string; };"
|
|
394
|
+
},
|
|
320
395
|
{
|
|
321
396
|
"name": "PendingOp",
|
|
322
397
|
"declaration": "export interface PendingOp {\n op: 'put' | 'remove';\n url: string;\n}"
|
|
@@ -359,7 +434,7 @@ export const TYPERT = {
|
|
|
359
434
|
},
|
|
360
435
|
{
|
|
361
436
|
"name": "TestHooks",
|
|
362
|
-
"declaration": "export interface TestHooks {\n crash(): Promise<void>;\n page(owner: string, tab: string): unknown;\n running(): boolean;\n pages(): unknown[];\n pid(): number | undefined;\n}"
|
|
437
|
+
"declaration": "export interface TestHooks {\n crash(): Promise<void>;\n page(owner: string, tab: string): unknown;\n running(): boolean;\n pages(): unknown[];\n pid(): number | undefined;\n useLocator(env: LocateEnv | undefined): void;\n}"
|
|
363
438
|
},
|
|
364
439
|
{
|
|
365
440
|
"name": "WaitFor",
|
|
@@ -372,7 +447,16 @@ export const TYPERT = {
|
|
|
372
447
|
]
|
|
373
448
|
}
|
|
374
449
|
],
|
|
375
|
-
"events": [
|
|
450
|
+
"events": [
|
|
451
|
+
{
|
|
452
|
+
"description": "Volatile config was committed on this plugin fiber. Paths are key arrays.",
|
|
453
|
+
"summary": "Volatile config was committed on this plugin fiber.",
|
|
454
|
+
"tags": [],
|
|
455
|
+
"jsDoc": "/** Volatile config was committed on this plugin fiber. Paths are key arrays. */",
|
|
456
|
+
"name": "loader/volatile-update",
|
|
457
|
+
"signature": "'loader/volatile-update'(paths: readonly (readonly string[])[]): void"
|
|
458
|
+
}
|
|
459
|
+
],
|
|
376
460
|
"objects": []
|
|
377
461
|
},
|
|
378
462
|
}
|
|
@@ -4,12 +4,15 @@ import type {
|
|
|
4
4
|
TypertRemoteInfo,
|
|
5
5
|
TypertRemoteMethod,
|
|
6
6
|
} from '@deepseek-ai/dsh-typert-protocol'
|
|
7
|
+
import type { BrowserLocation, BrowserName } from '@mind-harness/mh-browser/location'
|
|
7
8
|
|
|
8
9
|
declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
9
10
|
interface TypertRemoteNamespace$6d6842726f77736572 {
|
|
11
|
+
locateFor: (browser: BrowserName, signal?: AbortSignal) => Promise<RemoteResult<BrowserLocation>>
|
|
10
12
|
revealHandover: (sessionId: string, signal?: AbortSignal) => Promise<RemoteResult<{ status: 'revealed' | 'not-handing-over' | 'no-tab'; }>>
|
|
11
13
|
}
|
|
12
14
|
interface TypertRemoteMap {
|
|
15
|
+
'mhBrowser/locateFor': (browser: BrowserName, signal?: AbortSignal) => Promise<RemoteResult<BrowserLocation>>
|
|
13
16
|
'mhBrowser/revealHandover': (sessionId: string, signal?: AbortSignal) => Promise<RemoteResult<{ status: 'revealed' | 'not-handing-over' | 'no-tab'; }>>
|
|
14
17
|
}
|
|
15
18
|
interface TypertRemoteNamespaceMap {
|
|
@@ -18,6 +21,7 @@ declare module '@deepseek-ai/dsh-typert-protocol' {
|
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
export declare const TYPERT_REMOTE: TypertRemoteInfo<{
|
|
24
|
+
readonly 'mhBrowser/locateFor': TypertRemoteMethod<{ readonly 'browser': BrowserName }, BrowserLocation>
|
|
21
25
|
readonly 'mhBrowser/revealHandover': TypertRemoteMethod<{ readonly 'sessionId': string }, { status: 'revealed' | 'not-handing-over' | 'no-tab'; }>
|
|
22
26
|
}>
|
|
23
27
|
export default TYPERT_REMOTE
|
|
@@ -3,18 +3,62 @@ import { z } from 'zod'
|
|
|
3
3
|
|
|
4
4
|
import { createTypertRemoteInfo } from '@deepseek-ai/dsh-typert-protocol/remote-info'
|
|
5
5
|
|
|
6
|
+
let _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema$value
|
|
7
|
+
const _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema = () => (_mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema$value ??= z.union([z.literal("chrome"), z.literal("msedge"), z.literal("chromium")]))
|
|
8
|
+
let _mind_harness_mh_browser_mhBrowser_locateFor_result$schema$value
|
|
9
|
+
const _mind_harness_mh_browser_mhBrowser_locateFor_result$schema = () => (_mind_harness_mh_browser_mhBrowser_locateFor_result$schema$value ??= z.union([z.object({
|
|
10
|
+
'found': z.string(),
|
|
11
|
+
}), z.object({
|
|
12
|
+
'missing': z.array(z.object({
|
|
13
|
+
'path': z.string(),
|
|
14
|
+
'reason': z.string(),
|
|
15
|
+
})),
|
|
16
|
+
})]))
|
|
6
17
|
let _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema$value
|
|
7
18
|
const _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema = () => (_mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema$value ??= z.string())
|
|
8
19
|
let _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema$value
|
|
9
20
|
const _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema = () => (_mind_harness_mh_browser_mhBrowser_revealHandover_result$schema$value ??= z.object({
|
|
10
21
|
'status': z.union([z.literal("revealed"), z.literal("not-handing-over"), z.literal("no-tab")]),
|
|
11
22
|
}))
|
|
23
|
+
let _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema$value
|
|
24
|
+
const _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema = () => (_mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema$value ??= z.union([z.literal("chrome"), z.literal("msedge"), z.literal("chromium")]))
|
|
12
25
|
let _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema$value
|
|
13
26
|
const _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema = () => (_mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema$value ??= z.string())
|
|
14
27
|
|
|
15
28
|
export const TYPERT_REMOTE = createTypertRemoteInfo({
|
|
16
29
|
package: '@mind-harness/mh-browser',
|
|
17
30
|
methods: {
|
|
31
|
+
'mhBrowser/locateFor': {
|
|
32
|
+
service: 'mhBrowser',
|
|
33
|
+
description: 'Where `browser` would be launched from when no path is configured. The configured path is not consulted: the answer is what an empty path uses.',
|
|
34
|
+
invocation: { kind: 'direct' },
|
|
35
|
+
parameters: [
|
|
36
|
+
{
|
|
37
|
+
name: 'browser',
|
|
38
|
+
source: 'json',
|
|
39
|
+
codec: {
|
|
40
|
+
mode: 'strict',
|
|
41
|
+
typeSymbol: '@mind-harness/mh-browser/location#BrowserName',
|
|
42
|
+
create: _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema,
|
|
43
|
+
jsonSchema: {"type":"string","enum":["chrome","msedge","chromium"]},
|
|
44
|
+
},
|
|
45
|
+
strictCodec: {
|
|
46
|
+
mode: 'strict',
|
|
47
|
+
typeSymbol: '@mind-harness/mh-browser/location#BrowserName',
|
|
48
|
+
create: _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema,
|
|
49
|
+
jsonSchema: {"type":"string","enum":["chrome","msedge","chromium"]},
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
cancellation: { parameter: 'signal' },
|
|
54
|
+
result: {
|
|
55
|
+
mode: 'strict',
|
|
56
|
+
typeSymbol: '@mind-harness/mh-browser/location#BrowserLocation',
|
|
57
|
+
create: _mind_harness_mh_browser_mhBrowser_locateFor_result$schema,
|
|
58
|
+
jsonSchemaError: 'typert tool schema: selected union branches overlap or have no required discriminator',
|
|
59
|
+
},
|
|
60
|
+
sourceLocation: {"file":"packages/mh-browser/src/service/service.ts","line":474,"column":9},
|
|
61
|
+
},
|
|
18
62
|
'mhBrowser/revealHandover': {
|
|
19
63
|
service: 'mhBrowser',
|
|
20
64
|
description: 'The person asked to see the page this Session handed over.',
|
|
@@ -44,7 +88,7 @@ export const TYPERT_REMOTE = createTypertRemoteInfo({
|
|
|
44
88
|
create: _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema,
|
|
45
89
|
jsonSchema: {"type":"object","properties":{"status":{"type":"string","enum":["revealed","not-handing-over","no-tab"]}},"required":["status"],"additionalProperties":true},
|
|
46
90
|
},
|
|
47
|
-
sourceLocation: {"file":"packages/mh-browser/src/service/service.ts","line":
|
|
91
|
+
sourceLocation: {"file":"packages/mh-browser/src/service/service.ts","line":734,"column":9},
|
|
48
92
|
},
|
|
49
93
|
},
|
|
50
94
|
}, z)
|
package/lib/types/client.d.ts
CHANGED
|
@@ -2,13 +2,16 @@ import { type ReactElement } from 'react';
|
|
|
2
2
|
import { type RevealResult } from './card.ts';
|
|
3
3
|
import { type Translate } from './locales.ts';
|
|
4
4
|
import { handoverRowDefinition } from './row.ts';
|
|
5
|
+
import type { SettingsFormScope } from './settings-form.ts';
|
|
6
|
+
import { type LocateFor } from './settings.ts';
|
|
5
7
|
/**
|
|
6
8
|
* Cordis services this client reads. `dsh.client.inject` is package load
|
|
7
9
|
* order, not this list. `remote.mhBrowser` is absent until `$mount`.
|
|
8
10
|
*/
|
|
9
|
-
export declare const inject: readonly ["slots", "locale", "remote", "uiConversation"];
|
|
11
|
+
export declare const inject: readonly ["slots", "locale", "remote", "uiConversation", "configForms"];
|
|
10
12
|
export interface MhBrowserRemote {
|
|
11
13
|
revealHandover(sessionId: string, signal?: AbortSignal): Promise<RevealResult>;
|
|
14
|
+
locateFor: LocateFor;
|
|
12
15
|
}
|
|
13
16
|
interface RemoteCarrier {
|
|
14
17
|
$mount(contribution: object): Promise<() => Promise<void>>;
|
|
@@ -31,10 +34,21 @@ export interface ClientHost {
|
|
|
31
34
|
key: string;
|
|
32
35
|
locale: string;
|
|
33
36
|
}, component: (props: HostRowProps) => ReactElement): () => void;
|
|
37
|
+
register(options: {
|
|
38
|
+
name: string;
|
|
39
|
+
key: string;
|
|
40
|
+
locale: string;
|
|
41
|
+
}, component: (props: {
|
|
42
|
+
t: Translate;
|
|
43
|
+
view?: 'summary' | 'page';
|
|
44
|
+
}) => ReactElement | null): () => void;
|
|
34
45
|
};
|
|
35
46
|
locale: {
|
|
36
47
|
register(ns: string, dicts: Record<'zh' | 'en', Record<string, string>>): () => void;
|
|
37
48
|
};
|
|
49
|
+
configForms: {
|
|
50
|
+
get<T>(entryId: string): SettingsFormScope<T>;
|
|
51
|
+
};
|
|
38
52
|
uiConversation: {
|
|
39
53
|
events: {
|
|
40
54
|
register(definition: typeof handoverRowDefinition): () => void;
|
package/lib/types/config.d.ts
CHANGED
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
import z from '@deepseek-ai/schemastery';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
export declare const browserConfig: z<Schemastery.ObjectS<NoInfer<{
|
|
3
|
+
presence: z<Schemastery.ObjectS<NoInfer<{
|
|
4
|
+
maxBytes: z<number, number, "defined">;
|
|
5
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
6
|
+
maxBytes: z<number, number, "defined">;
|
|
7
|
+
}>>, "defined">;
|
|
8
|
+
browser: z<"chrome" | "msedge" | "chromium", "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
9
|
+
executablePath: z<string, string, "volatile">;
|
|
10
|
+
profileDir: z<string, string, "plain">;
|
|
11
|
+
headless: z<boolean, boolean, "defined">;
|
|
12
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
13
|
+
presence: z<Schemastery.ObjectS<NoInfer<{
|
|
14
|
+
maxBytes: z<number, number, "defined">;
|
|
15
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
16
|
+
maxBytes: z<number, number, "defined">;
|
|
17
|
+
}>>, "defined">;
|
|
18
|
+
browser: z<"chrome" | "msedge" | "chromium", "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
19
|
+
executablePath: z<string, string, "volatile">;
|
|
20
|
+
profileDir: z<string, string, "plain">;
|
|
21
|
+
headless: z<boolean, boolean, "defined">;
|
|
22
|
+
}>>, "plain">;
|
|
23
|
+
/** What {@link browserConfig} returns. `browser` and `executablePath` are read with `get()`. */
|
|
24
|
+
export type BrowserConfig = ReturnType<typeof browserConfig>;
|
|
12
25
|
/**
|
|
13
26
|
* Browser profile directory when the configuration names none. Each dsh profile gets its own:
|
|
14
27
|
* a browser profile directory admits one running browser, so two dsh profiles sharing one
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1,11 +1,32 @@
|
|
|
1
1
|
import type { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import type { BrowserConfig } from './config.ts';
|
|
3
|
+
import { browserConfig } from './config.ts';
|
|
3
4
|
import { MhBrowserService } from './service/service.ts';
|
|
4
5
|
export declare const name = "mh-browser";
|
|
5
6
|
export declare const inject: string[];
|
|
6
7
|
export type Config = BrowserConfig;
|
|
7
|
-
export declare const Config: import("@deepseek-ai/schemastery").default<
|
|
8
|
-
|
|
8
|
+
export declare const Config: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
9
|
+
presence: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
10
|
+
maxBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
11
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
12
|
+
maxBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
13
|
+
}>>, "defined">;
|
|
14
|
+
browser: import("@deepseek-ai/schemastery").default<"chrome" | "msedge" | "chromium", "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
15
|
+
executablePath: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
16
|
+
profileDir: import("@deepseek-ai/schemastery").default<string, string, "plain">;
|
|
17
|
+
headless: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
18
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
19
|
+
presence: import("@deepseek-ai/schemastery").default<Schemastery.ObjectS<NoInfer<{
|
|
20
|
+
maxBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
21
|
+
}>>, Schemastery.ObjectT<NoInfer<{
|
|
22
|
+
maxBytes: import("@deepseek-ai/schemastery").default<number, number, "defined">;
|
|
23
|
+
}>>, "defined">;
|
|
24
|
+
browser: import("@deepseek-ai/schemastery").default<"chrome" | "msedge" | "chromium", "chrome" | "msedge" | "chromium", "volatile-defined">;
|
|
25
|
+
executablePath: import("@deepseek-ai/schemastery").default<string, string, "volatile">;
|
|
26
|
+
profileDir: import("@deepseek-ai/schemastery").default<string, string, "plain">;
|
|
27
|
+
headless: import("@deepseek-ai/schemastery").default<boolean, boolean, "defined">;
|
|
28
|
+
}>>, "plain">;
|
|
29
|
+
export declare function apply(ctx: Context, config: Config | NonNullable<Parameters<typeof browserConfig>[0]>): Promise<void>;
|
|
9
30
|
export { MhBrowserService };
|
|
10
31
|
export { readAgentView } from './representation/agent-view.ts';
|
|
11
32
|
export type { AgentViewDoc, AgentViewLink, AgentViewRead } from './representation/agent-view.ts';
|
package/lib/types/locales.d.ts
CHANGED
|
@@ -6,6 +6,28 @@ export declare const zh: {
|
|
|
6
6
|
readonly notHandingOver: "这次交接已经结束";
|
|
7
7
|
readonly noTab: "没有可以去的页面";
|
|
8
8
|
readonly failed: "没能切到浏览器";
|
|
9
|
+
readonly browserLabel: "浏览器";
|
|
10
|
+
readonly browserHint: "保存后,浏览器空闲时会关掉再按这个选择打开。已经打开的标签页会关掉。";
|
|
11
|
+
readonly pathLabel: "浏览器路径";
|
|
12
|
+
readonly pathHint: "留空就用自动找到的。可以填绝对路径,也可以用 ~。保存后同样在空闲时重启。";
|
|
13
|
+
readonly pathInvalid: "需要绝对路径,或以 ~ 开头";
|
|
14
|
+
readonly pathSearching: "正在查找…";
|
|
15
|
+
readonly pathMissing: "未找到{name},请填写路径";
|
|
16
|
+
readonly pathHelp: "说明";
|
|
17
|
+
readonly pathDoesNotExist: "不存在";
|
|
18
|
+
readonly pathIsDirectory: "是目录";
|
|
19
|
+
readonly pathDenied: "没有权限({code})";
|
|
20
|
+
readonly chrome: "Google Chrome";
|
|
21
|
+
readonly msedge: "Microsoft Edge";
|
|
22
|
+
readonly chromium: "Chromium";
|
|
23
|
+
readonly overridden: "已覆盖";
|
|
24
|
+
readonly reset: "恢复";
|
|
25
|
+
readonly save: "保存";
|
|
26
|
+
readonly saving: "保存中";
|
|
27
|
+
readonly settingsUnavailable: "这个配置现在不可用";
|
|
28
|
+
readonly settingsReadOnly: "这次启动的配置不能在页面上改";
|
|
29
|
+
readonly settingsSaveFailed: "没有保存:设置可能在别处改过,或这个值不被接受。修改还在,检查后可以再保存";
|
|
30
|
+
readonly discard: "放弃修改";
|
|
9
31
|
};
|
|
10
32
|
export type CardKey = keyof typeof zh;
|
|
11
33
|
export declare const en: Record<CardKey, string>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Where a browser name resolves when no path is configured. */
|
|
2
|
+
export type { BrowserName } from './types.ts';
|
|
3
|
+
export interface BrowserLocationMiss {
|
|
4
|
+
path: string;
|
|
5
|
+
reason: string;
|
|
6
|
+
}
|
|
7
|
+
export type BrowserLocation = {
|
|
8
|
+
found: string;
|
|
9
|
+
} | {
|
|
10
|
+
missing: BrowserLocationMiss[];
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=location.d.ts.map
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { BrowserContext } from 'playwright';
|
|
2
|
+
import type { BrowserLocation } from '../location.ts';
|
|
2
3
|
import type { BrowserName } from '../types.ts';
|
|
4
|
+
import { type LocateEnv } from './locate.ts';
|
|
3
5
|
export interface LaunchOptions {
|
|
4
6
|
browser: BrowserName;
|
|
5
7
|
headless: boolean;
|
|
6
8
|
profileDir: string;
|
|
7
|
-
/**
|
|
9
|
+
/** Absolute path of the browser to launch. `~` is already expanded. */
|
|
8
10
|
executablePath?: string;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
@@ -15,11 +17,15 @@ export interface LaunchOptions {
|
|
|
15
17
|
*/
|
|
16
18
|
export declare function chromiumSandboxEnabled(browser: BrowserName, platform?: NodeJS.Platform): boolean;
|
|
17
19
|
/**
|
|
18
|
-
* One persistent context for the whole process.
|
|
19
|
-
*
|
|
20
|
-
*
|
|
20
|
+
* One persistent context for the whole process. An installed browser is located
|
|
21
|
+
* here and passed as `executablePath`; `channel` names which install that was.
|
|
22
|
+
* `chromium` omits `channel` so Playwright uses its own browser unless a path
|
|
23
|
+
* is configured. A missing browser is reported and not downloaded. A launch
|
|
24
|
+
* that fails after the executable was found is reported as Playwright said.
|
|
21
25
|
*/
|
|
22
|
-
export declare function launchBrowser(options: LaunchOptions): Promise<BrowserContext>;
|
|
26
|
+
export declare function launchBrowser(options: LaunchOptions, env?: LocateEnv): Promise<BrowserContext>;
|
|
27
|
+
/** Playwright's own Chromium, or why that file cannot be run. */
|
|
28
|
+
export declare function bundledChromiumLocation(access: LocateEnv['access']): BrowserLocation;
|
|
23
29
|
/**
|
|
24
30
|
* Process id of the browser's main process. Playwright gives none for a
|
|
25
31
|
* persistent context. Asks the browser first; on POSIX the profile's
|
|
@@ -13,6 +13,11 @@ export declare class Control {
|
|
|
13
13
|
private readonly tabs;
|
|
14
14
|
private readonly since;
|
|
15
15
|
private readonly named;
|
|
16
|
+
/**
|
|
17
|
+
* A handover is waiting, or the person holds a tab. The browser is not
|
|
18
|
+
* restarted out from under either.
|
|
19
|
+
*/
|
|
20
|
+
busy(): boolean;
|
|
16
21
|
/** Whether the person holds any tab, or a handover is waiting. */
|
|
17
22
|
of(owner: string): 'model' | 'person';
|
|
18
23
|
/** The person holds this tab until they hand it back. */
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { BrowserLocation, BrowserLocationMiss } from '../location.ts';
|
|
2
|
+
import type { BrowserName } from '../types.ts';
|
|
3
|
+
/** A browser the person installs. Playwright's Chromium is not located this way. */
|
|
4
|
+
export type InstalledBrowser = Exclude<BrowserName, 'chromium'>;
|
|
5
|
+
/** `ok`, or the errno from checking that the file can be executed. */
|
|
6
|
+
export type PathAccess = 'ok' | {
|
|
7
|
+
code: string;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Everything location reads from the machine. Tests pass a stand-in, so a
|
|
11
|
+
* case does not depend on what that machine has installed.
|
|
12
|
+
*/
|
|
13
|
+
export interface LocateEnv {
|
|
14
|
+
platform: NodeJS.Platform;
|
|
15
|
+
env: NodeJS.ProcessEnv;
|
|
16
|
+
home: string;
|
|
17
|
+
/** Whether `path` can be executed. */
|
|
18
|
+
access(path: string): PathAccess;
|
|
19
|
+
/**
|
|
20
|
+
* Paths from the platform's own lookup, already resolved. Called only after
|
|
21
|
+
* every fixed candidate missed. An empty list means the lookup found nothing
|
|
22
|
+
* or did not run.
|
|
23
|
+
*/
|
|
24
|
+
discover(browser: InstalledBrowser, signal?: AbortSignal): Promise<string[]>;
|
|
25
|
+
}
|
|
26
|
+
/** The fixed paths checked for `browser` on `env`, in the order they are tried. */
|
|
27
|
+
export declare function candidatePaths(browser: InstalledBrowser, env: LocateEnv): string[];
|
|
28
|
+
/**
|
|
29
|
+
* `configured` is used as given: a path that cannot be run is a failure, and
|
|
30
|
+
* nothing else is searched. `~` expands to `env.home`.
|
|
31
|
+
*/
|
|
32
|
+
export declare function checkConfigured(configured: string, env: LocateEnv): {
|
|
33
|
+
ok: true;
|
|
34
|
+
path: string;
|
|
35
|
+
} | {
|
|
36
|
+
ok: false;
|
|
37
|
+
path: string;
|
|
38
|
+
code: string;
|
|
39
|
+
};
|
|
40
|
+
/** Failure for a path the configuration names. */
|
|
41
|
+
export declare function configuredPathError(path: string, code: string): Error;
|
|
42
|
+
/** Failure listing every path that was tried. */
|
|
43
|
+
export declare function browserNotFoundError(browser: InstalledBrowser, missing: BrowserLocationMiss[]): Error;
|
|
44
|
+
/**
|
|
45
|
+
* The path to launch. A configured path is checked and never replaced.
|
|
46
|
+
* `chromium` without one returns undefined, so Playwright uses its own build.
|
|
47
|
+
* An installed browser that cannot be found throws.
|
|
48
|
+
*/
|
|
49
|
+
export declare function resolveExecutable(browser: BrowserName, configured: string | undefined, env: LocateEnv, signal?: AbortSignal): Promise<string | undefined>;
|
|
50
|
+
/**
|
|
51
|
+
* Where `browser` is installed when the configuration names no path.
|
|
52
|
+
* Fixed candidates first, then `env.discover`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function locateInstalled(browser: InstalledBrowser, env: LocateEnv, signal?: AbortSignal): Promise<BrowserLocation>;
|
|
55
|
+
/** `path` is Playwright's Chromium. Missing or not executable is `missing`. */
|
|
56
|
+
export declare function locateBundled(path: string, access: LocateEnv['access']): BrowserLocation;
|
|
57
|
+
/** This machine: fixed paths, then Spotlight, App Paths, or `PATH`. */
|
|
58
|
+
export declare function hostLocateEnv(): LocateEnv;
|
|
59
|
+
/** A `.app` bundle path reported by Spotlight, turned into its executable. */
|
|
60
|
+
export declare function executableInApp(reported: string, binary: string): string | undefined;
|
|
61
|
+
/** The default value from `reg query ... /ve` output. */
|
|
62
|
+
export declare function regValue(stdout: string): string | undefined;
|
|
63
|
+
/** Text for an errno from {@link LocateEnv.access}. */
|
|
64
|
+
export declare function reasonForCode(code: string): string;
|
|
65
|
+
//# sourceMappingURL=locate.d.ts.map
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { Context } from '@deepseek-ai/cordis';
|
|
2
2
|
import { TypertRemoteService } from '@deepseek-ai/dsh-typert-protocol';
|
|
3
3
|
import type { BrowserConfig } from '../config.ts';
|
|
4
|
+
import type { BrowserLocation } from '../location.ts';
|
|
4
5
|
import type { HeldPage, PresenceReceipt, PresenceRecord, PresenceSource } from '../presence/record.ts';
|
|
5
6
|
import type { PendingOp } from '../presence/fold.ts';
|
|
6
|
-
import type { Download, FetchResponseBody, InvokeCall, InvokeSent, PageError, PageOp, PageView, TabInfo, WaitFor } from '../types.ts';
|
|
7
|
+
import type { BrowserName, Download, FetchResponseBody, InvokeCall, InvokeSent, PageError, PageOp, PageView, TabInfo, WaitFor } from '../types.ts';
|
|
7
8
|
import { type Taken } from './control.ts';
|
|
8
9
|
import { testHooks, type TestHooks } from './test-hooks.ts';
|
|
9
10
|
declare module '@deepseek-ai/cordis' {
|
|
10
11
|
interface Context {
|
|
11
12
|
mhBrowser: MhBrowserService;
|
|
12
13
|
}
|
|
14
|
+
interface Events {
|
|
15
|
+
/** Volatile config was committed on this plugin fiber. Paths are key arrays. */
|
|
16
|
+
'loader/volatile-update'(paths: readonly (readonly string[])[]): void;
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
export type WriteTarget = {
|
|
15
20
|
root: string;
|
|
@@ -30,13 +35,23 @@ export interface HandBack extends Taken {
|
|
|
30
35
|
* also has an Agent View.
|
|
31
36
|
*/
|
|
32
37
|
export declare class MhBrowserService extends TypertRemoteService {
|
|
33
|
-
static Config: import("@deepseek-ai/schemastery").default<BrowserConfig>;
|
|
34
38
|
private readonly windows;
|
|
35
|
-
private readonly
|
|
39
|
+
private readonly headless;
|
|
40
|
+
private readonly profileDir;
|
|
41
|
+
private readonly browserName;
|
|
42
|
+
private readonly executablePath;
|
|
43
|
+
/** Tests replace the machine lookup. Unset uses this machine. */
|
|
44
|
+
private locator;
|
|
36
45
|
private context;
|
|
37
46
|
private readonly pids;
|
|
38
47
|
private ready;
|
|
39
48
|
private closing;
|
|
49
|
+
/** A browser restart was requested and has not run yet. */
|
|
50
|
+
private relaunchWanted;
|
|
51
|
+
/** Counts browser and path changes. A start that sampled the latest one clears the restart. */
|
|
52
|
+
private configEpoch;
|
|
53
|
+
/** The running browser is being closed so the new configuration can start. */
|
|
54
|
+
private replacing;
|
|
40
55
|
/** The browser is not running. The next call that needs a page starts it. */
|
|
41
56
|
private exited;
|
|
42
57
|
private readonly exits;
|
|
@@ -112,6 +127,11 @@ export declare class MhBrowserService extends TypertRemoteService {
|
|
|
112
127
|
/** The person asked for the browser: start it if it exited, past the exit limit. */
|
|
113
128
|
startForPerson(): Promise<void>;
|
|
114
129
|
[testHooks](): TestHooks;
|
|
130
|
+
/**
|
|
131
|
+
* Where `browser` would be launched from when no path is configured.
|
|
132
|
+
* The configured path is not consulted: the answer is what an empty path uses.
|
|
133
|
+
*/
|
|
134
|
+
locateFor(browser: BrowserName, signal?: AbortSignal): Promise<BrowserLocation>;
|
|
115
135
|
act(owner: string, tab: string, op: PageOp, signal?: AbortSignal): Promise<PageView>;
|
|
116
136
|
holdHandover(owner: string, tab: string): void;
|
|
117
137
|
releaseHandover(owner: string): void;
|
|
@@ -152,6 +172,7 @@ export declare class MhBrowserService extends TypertRemoteService {
|
|
|
152
172
|
/**
|
|
153
173
|
* The person took over between turns. The next message they send is the
|
|
154
174
|
* hand-back. A handover that is still waiting on its card is not.
|
|
175
|
+
* The addresses are read before a waiting restart closes the pages.
|
|
155
176
|
*/
|
|
156
177
|
takePersonHandback(owner: string): HandBack | undefined;
|
|
157
178
|
/**
|
|
@@ -243,5 +264,15 @@ export declare class MhBrowserService extends TypertRemoteService {
|
|
|
243
264
|
private presenceUrls;
|
|
244
265
|
private snapshotNamed;
|
|
245
266
|
private exclusive;
|
|
267
|
+
private launchChoice;
|
|
268
|
+
private locateEnv;
|
|
269
|
+
private idle;
|
|
270
|
+
/**
|
|
271
|
+
* Close and start again when a configuration change is waiting and nothing
|
|
272
|
+
* is using the browser. A browser that is not running keeps the new values
|
|
273
|
+
* for the next start. The close is not counted as a crash.
|
|
274
|
+
*/
|
|
275
|
+
private relaunchIfIdle;
|
|
276
|
+
private replaceBrowser;
|
|
246
277
|
}
|
|
247
278
|
//# sourceMappingURL=service.d.ts.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LocateEnv } from './locate.ts';
|
|
1
2
|
/** Key of the hooks tests use to crash the browser and reach a live page. Not exported by the package. */
|
|
2
3
|
export declare const testHooks: unique symbol;
|
|
3
4
|
export interface TestHooks {
|
|
@@ -9,5 +10,7 @@ export interface TestHooks {
|
|
|
9
10
|
pages(): unknown[];
|
|
10
11
|
/** The main browser process id recorded at start. */
|
|
11
12
|
pid(): number | undefined;
|
|
13
|
+
/** Use this lookup instead of the machine's. `undefined` restores the machine. */
|
|
14
|
+
useLocator(env: LocateEnv | undefined): void;
|
|
12
15
|
}
|
|
13
16
|
//# sourceMappingURL=test-hooks.d.ts.map
|