@mind-harness/mh-browser 0.2.6 → 0.2.7
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 +1992 -1539
- 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
package/lib/client.cjs
CHANGED
|
@@ -4,302 +4,92 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
7
|
-
let zod = require("zod");
|
|
8
7
|
let react = require("react");
|
|
9
|
-
//#region
|
|
10
|
-
|
|
8
|
+
//#region src/client/call.ts
|
|
9
|
+
const PACKAGE = "mh-browser";
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* input schemas and JSON Schema projections are cached only when requested.
|
|
15
|
-
* @param spec - compiler-produced method facts and Zod factories.
|
|
16
|
-
* @param zod - the generated artifact's Zod runtime for named-input parsers.
|
|
17
|
-
* @returns a lazy, mountable info instance with no registration or transport effects.
|
|
11
|
+
* `document.baseURI` keeps a mounted page on its prefix. dsh's file upload
|
|
12
|
+
* resolves the same way.
|
|
18
13
|
*/
|
|
19
|
-
function
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
return this.spec.package;
|
|
32
|
-
}
|
|
33
|
-
get descriptors() {
|
|
34
|
-
return this.resolve().descriptors;
|
|
35
|
-
}
|
|
36
|
-
get methods() {
|
|
37
|
-
return this.resolve().methods;
|
|
14
|
+
async function call(segment, init, signal) {
|
|
15
|
+
const url = new URL(`${PACKAGE}/api/${segment}`, document.baseURI);
|
|
16
|
+
if (init.query !== void 0) for (const [key, value] of Object.entries(init.query)) url.searchParams.set(key, value);
|
|
17
|
+
const request = {
|
|
18
|
+
method: init.method,
|
|
19
|
+
credentials: "same-origin",
|
|
20
|
+
cache: "no-store"
|
|
21
|
+
};
|
|
22
|
+
if (signal !== void 0) request.signal = signal;
|
|
23
|
+
if (init.method === "POST") {
|
|
24
|
+
request.headers = { "content-type": "application/json" };
|
|
25
|
+
request.body = JSON.stringify(init.body ?? {});
|
|
38
26
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const namespace = endpoint.slice(0, separator);
|
|
47
|
-
const method = endpoint.slice(separator + 1);
|
|
48
|
-
const parameters = definition.parameters.map((parameter) => ({
|
|
49
|
-
...parameter,
|
|
50
|
-
wire: parameter.wire ?? parameter.name
|
|
51
|
-
}));
|
|
52
|
-
const descriptor = {
|
|
53
|
-
...definition,
|
|
54
|
-
id: `${this.spec.package}#${endpoint}`,
|
|
55
|
-
namespace,
|
|
56
|
-
method,
|
|
57
|
-
parameters,
|
|
58
|
-
result: definition.result.description === void 0 ? definition.result : new ResultValue(definition.result)
|
|
59
|
-
};
|
|
60
|
-
if (definition.invocation.kind === "direct") {
|
|
61
|
-
const inputs = [];
|
|
62
|
-
methods[endpoint] = Object.assign(descriptor, {
|
|
63
|
-
input(options) {
|
|
64
|
-
const strict = options?.strict === true;
|
|
65
|
-
return inputs[strict ? 1 : 0] ??= new NamedInput(parameters, strict, zod);
|
|
66
|
-
},
|
|
67
|
-
invoke(remote, input, signal) {
|
|
68
|
-
const named = input;
|
|
69
|
-
const values = parameters.map((parameter) => named[parameter.wire]);
|
|
70
|
-
if (definition.cancellation !== void 0) values.push(signal);
|
|
71
|
-
const receiver = Reflect.get(remote, namespace);
|
|
72
|
-
return Reflect.get(receiver, method).apply(receiver, values);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
}
|
|
76
|
-
descriptors.push(descriptor);
|
|
77
|
-
}
|
|
78
|
-
return this.index = {
|
|
79
|
-
descriptors,
|
|
80
|
-
methods
|
|
81
|
-
};
|
|
27
|
+
try {
|
|
28
|
+
const payload = await (await fetch(url, request)).json();
|
|
29
|
+
if (isCallResult(payload)) return payload;
|
|
30
|
+
return fail("unreachable", "response was not understood");
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (signal?.aborted === true) return fail("cancelled", "cancelled");
|
|
33
|
+
return fail("unreachable", error instanceof Error ? error.message : "request failed");
|
|
82
34
|
}
|
|
83
|
-
};
|
|
84
|
-
function optional(parameter) {
|
|
85
|
-
return parameter.source === "json" && parameter.acceptsUndefined === true;
|
|
86
35
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
constructor(parameters, strict, zod) {
|
|
94
|
-
this.parameters = parameters;
|
|
95
|
-
this.strict = strict;
|
|
96
|
-
this.zod = zod;
|
|
97
|
-
}
|
|
98
|
-
codec(parameter) {
|
|
99
|
-
return this.strict ? parameter.strictCodec : parameter.codec;
|
|
100
|
-
}
|
|
101
|
-
create = () => this.schema ??= this.zod.strictObject(Object.fromEntries(this.parameters.map((parameter) => {
|
|
102
|
-
const value = this.codec(parameter).create();
|
|
103
|
-
return [parameter.wire, optional(parameter) ? value.optional() : value.nonoptional()];
|
|
104
|
-
})));
|
|
105
|
-
get jsonSchema() {
|
|
106
|
-
return this.project().jsonSchema;
|
|
107
|
-
}
|
|
108
|
-
get jsonSchemaError() {
|
|
109
|
-
return this.project().jsonSchemaError;
|
|
110
|
-
}
|
|
111
|
-
project() {
|
|
112
|
-
if (this.projection !== void 0) return this.projection;
|
|
113
|
-
const unavailable = this.parameters.find((parameter) => this.codec(parameter).jsonSchema === void 0);
|
|
114
|
-
if (unavailable !== void 0) return this.projection = { jsonSchemaError: this.codec(unavailable).jsonSchemaError ?? `No JSON Schema for parameter ${unavailable.wire}` };
|
|
115
|
-
return this.projection = { jsonSchema: {
|
|
116
|
-
type: "object",
|
|
117
|
-
properties: Object.fromEntries(this.parameters.map((parameter) => [parameter.wire, {
|
|
118
|
-
...this.codec(parameter).jsonSchema,
|
|
119
|
-
...parameter.description === void 0 ? {} : { description: parameter.description }
|
|
120
|
-
}])),
|
|
121
|
-
required: this.parameters.filter((parameter) => !optional(parameter)).map((parameter) => parameter.wire),
|
|
122
|
-
additionalProperties: false
|
|
123
|
-
} };
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
var ResultValue = class {
|
|
127
|
-
spec;
|
|
128
|
-
projection;
|
|
129
|
-
constructor(spec) {
|
|
130
|
-
this.spec = spec;
|
|
131
|
-
}
|
|
132
|
-
get mode() {
|
|
133
|
-
return this.spec.mode;
|
|
134
|
-
}
|
|
135
|
-
get typeSymbol() {
|
|
136
|
-
return this.spec.typeSymbol;
|
|
137
|
-
}
|
|
138
|
-
get create() {
|
|
139
|
-
return this.spec.create;
|
|
140
|
-
}
|
|
141
|
-
get decode() {
|
|
142
|
-
return this.spec.decode;
|
|
143
|
-
}
|
|
144
|
-
get encode() {
|
|
145
|
-
return this.spec.encode;
|
|
146
|
-
}
|
|
147
|
-
get description() {
|
|
148
|
-
return this.spec.description;
|
|
149
|
-
}
|
|
150
|
-
get jsonSchemaError() {
|
|
151
|
-
return this.spec.jsonSchemaError;
|
|
152
|
-
}
|
|
153
|
-
get jsonSchema() {
|
|
154
|
-
if (this.projection === void 0) {
|
|
155
|
-
const schema = this.spec.jsonSchema;
|
|
156
|
-
this.projection = { value: schema === void 0 ? void 0 : {
|
|
157
|
-
...schema,
|
|
158
|
-
description: this.spec.description
|
|
159
|
-
} };
|
|
160
|
-
}
|
|
161
|
-
return this.projection.value;
|
|
162
|
-
}
|
|
163
|
-
};
|
|
164
|
-
//#endregion
|
|
165
|
-
//#region lib/typert.remote-client.js
|
|
166
|
-
let _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema$value;
|
|
167
|
-
const _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema = () => _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema$value ??= zod.z.union([
|
|
168
|
-
zod.z.literal("chrome"),
|
|
169
|
-
zod.z.literal("msedge"),
|
|
170
|
-
zod.z.literal("chromium")
|
|
171
|
-
]);
|
|
172
|
-
let _mind_harness_mh_browser_mhBrowser_locateFor_result$schema$value;
|
|
173
|
-
const _mind_harness_mh_browser_mhBrowser_locateFor_result$schema = () => _mind_harness_mh_browser_mhBrowser_locateFor_result$schema$value ??= zod.z.union([zod.z.object({ "found": zod.z.string() }), zod.z.object({ "missing": zod.z.array(zod.z.object({
|
|
174
|
-
"path": zod.z.string(),
|
|
175
|
-
"reason": zod.z.string()
|
|
176
|
-
})) })]);
|
|
177
|
-
let _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema$value;
|
|
178
|
-
const _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema = () => _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema$value ??= zod.z.string();
|
|
179
|
-
let _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema$value;
|
|
180
|
-
const _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema = () => _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema$value ??= zod.z.object({ "status": zod.z.union([
|
|
181
|
-
zod.z.literal("revealed"),
|
|
182
|
-
zod.z.literal("not-handing-over"),
|
|
183
|
-
zod.z.literal("no-tab")
|
|
184
|
-
]) });
|
|
185
|
-
let _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema$value;
|
|
186
|
-
const _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema = () => _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema$value ??= zod.z.union([
|
|
187
|
-
zod.z.literal("chrome"),
|
|
188
|
-
zod.z.literal("msedge"),
|
|
189
|
-
zod.z.literal("chromium")
|
|
190
|
-
]);
|
|
191
|
-
let _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema$value;
|
|
192
|
-
const _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema = () => _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema$value ??= zod.z.string();
|
|
193
|
-
const TYPERT_REMOTE = createTypertRemoteInfo({
|
|
194
|
-
package: "@mind-harness/mh-browser",
|
|
195
|
-
methods: {
|
|
196
|
-
"mhBrowser/locateFor": {
|
|
197
|
-
service: "mhBrowser",
|
|
198
|
-
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.",
|
|
199
|
-
invocation: { kind: "direct" },
|
|
200
|
-
parameters: [{
|
|
201
|
-
name: "browser",
|
|
202
|
-
source: "json",
|
|
203
|
-
codec: {
|
|
204
|
-
mode: "strict",
|
|
205
|
-
typeSymbol: "@mind-harness/mh-browser/location#BrowserName",
|
|
206
|
-
create: _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0$schema,
|
|
207
|
-
jsonSchema: {
|
|
208
|
-
"type": "string",
|
|
209
|
-
"enum": [
|
|
210
|
-
"chrome",
|
|
211
|
-
"msedge",
|
|
212
|
-
"chromium"
|
|
213
|
-
]
|
|
214
|
-
}
|
|
215
|
-
},
|
|
216
|
-
strictCodec: {
|
|
217
|
-
mode: "strict",
|
|
218
|
-
typeSymbol: "@mind-harness/mh-browser/location#BrowserName",
|
|
219
|
-
create: _mind_harness_mh_browser_mhBrowser_locateFor_parameter_0_strict$schema,
|
|
220
|
-
jsonSchema: {
|
|
221
|
-
"type": "string",
|
|
222
|
-
"enum": [
|
|
223
|
-
"chrome",
|
|
224
|
-
"msedge",
|
|
225
|
-
"chromium"
|
|
226
|
-
]
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}],
|
|
230
|
-
cancellation: { parameter: "signal" },
|
|
231
|
-
result: {
|
|
232
|
-
mode: "strict",
|
|
233
|
-
typeSymbol: "@mind-harness/mh-browser/location#BrowserLocation",
|
|
234
|
-
create: _mind_harness_mh_browser_mhBrowser_locateFor_result$schema,
|
|
235
|
-
jsonSchemaError: "typert tool schema: selected union branches overlap or have no required discriminator"
|
|
236
|
-
},
|
|
237
|
-
sourceLocation: {
|
|
238
|
-
"file": "packages/mh-browser/src/service/service.ts",
|
|
239
|
-
"line": 474,
|
|
240
|
-
"column": 9
|
|
241
|
-
}
|
|
242
|
-
},
|
|
243
|
-
"mhBrowser/revealHandover": {
|
|
244
|
-
service: "mhBrowser",
|
|
245
|
-
description: "The person asked to see the page this Session handed over.",
|
|
246
|
-
invocation: { kind: "direct" },
|
|
247
|
-
parameters: [{
|
|
248
|
-
name: "sessionId",
|
|
249
|
-
source: "json",
|
|
250
|
-
codec: {
|
|
251
|
-
mode: "strict",
|
|
252
|
-
typeSymbol: "@mind-harness/mh-browser#mhBrowser/revealHandover:sessionId",
|
|
253
|
-
create: _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0$schema,
|
|
254
|
-
jsonSchema: { "type": "string" }
|
|
255
|
-
},
|
|
256
|
-
strictCodec: {
|
|
257
|
-
mode: "strict",
|
|
258
|
-
typeSymbol: "@mind-harness/mh-browser#mhBrowser/revealHandover:sessionId",
|
|
259
|
-
create: _mind_harness_mh_browser_mhBrowser_revealHandover_parameter_0_strict$schema,
|
|
260
|
-
jsonSchema: { "type": "string" }
|
|
261
|
-
}
|
|
262
|
-
}],
|
|
263
|
-
cancellation: { parameter: "signal" },
|
|
264
|
-
result: {
|
|
265
|
-
mode: "strict",
|
|
266
|
-
typeSymbol: "@mind-harness/mh-browser#mhBrowser/revealHandover:result",
|
|
267
|
-
create: _mind_harness_mh_browser_mhBrowser_revealHandover_result$schema,
|
|
268
|
-
jsonSchema: {
|
|
269
|
-
"type": "object",
|
|
270
|
-
"properties": { "status": {
|
|
271
|
-
"type": "string",
|
|
272
|
-
"enum": [
|
|
273
|
-
"revealed",
|
|
274
|
-
"not-handing-over",
|
|
275
|
-
"no-tab"
|
|
276
|
-
]
|
|
277
|
-
} },
|
|
278
|
-
"required": ["status"],
|
|
279
|
-
"additionalProperties": true
|
|
280
|
-
}
|
|
281
|
-
},
|
|
282
|
-
sourceLocation: {
|
|
283
|
-
"file": "packages/mh-browser/src/service/service.ts",
|
|
284
|
-
"line": 734,
|
|
285
|
-
"column": 9
|
|
286
|
-
}
|
|
36
|
+
function fail(code, message) {
|
|
37
|
+
return {
|
|
38
|
+
ok: false,
|
|
39
|
+
error: {
|
|
40
|
+
code: `${PACKAGE}/${code}`,
|
|
41
|
+
message
|
|
287
42
|
}
|
|
288
|
-
}
|
|
289
|
-
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function isCallResult(value) {
|
|
46
|
+
if (typeof value !== "object" || value === null || !("ok" in value)) return false;
|
|
47
|
+
if (value.ok === true) return "value" in value;
|
|
48
|
+
if (value.ok !== false || !("error" in value)) return false;
|
|
49
|
+
const error = value.error;
|
|
50
|
+
if (typeof error !== "object" || error === null) return false;
|
|
51
|
+
return "code" in error && typeof error.code === "string" && "message" in error && typeof error.message === "string";
|
|
52
|
+
}
|
|
290
53
|
//#endregion
|
|
291
54
|
//#region src/client/card.ts
|
|
292
|
-
/**
|
|
55
|
+
/**
|
|
56
|
+
* Host theme tokens only; the rules unmount with the row.
|
|
57
|
+
* The button copies the host primary control at its default size, and the
|
|
58
|
+
* right-up outline that control uses for leaving the app. This row loads no
|
|
59
|
+
* host client package.
|
|
60
|
+
*/
|
|
293
61
|
const STYLE$1 = `
|
|
294
62
|
.mh-br { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; color: var(--dsw-alias-label-primary); font-size: 14px; line-height: 20px; }
|
|
295
63
|
.mh-br-line { margin: 0; }
|
|
296
64
|
.mh-br-status { margin: 0; color: var(--dsw-alias-label-secondary); }
|
|
297
|
-
.mh-br-button {
|
|
65
|
+
.mh-br-button { box-sizing: border-box; display: inline-flex; align-items: center; justify-content: center; gap: 4px; height: 36px; padding: 0 14px; border: none; border-radius: var(--dsw-radius-md); background: var(--dsw-alias-button-primary-fill); color: var(--dsw-alias-label-primary-foreground); font-size: 14px; line-height: 22px; cursor: pointer; }
|
|
66
|
+
@media (hover: hover) { .mh-br-button:hover { background: var(--dsw-alias-button-primary-hover); } }
|
|
67
|
+
.mh-br-icon { display: inline-flex; width: 16px; height: 16px; align-items: center; justify-content: center; }
|
|
298
68
|
`;
|
|
299
|
-
/**
|
|
69
|
+
/** Corner of the host right-up outline, 16px viewBox, 1px stroke. */
|
|
70
|
+
const RIGHT_UP_CORNER = "M11.7256 2.77441C12.5538 2.77469 13.2256 3.44616 13.2256 4.27441V10.1416H12.2256V4.27441C12.2256 3.99844 12.0015 3.77469 11.7256 3.77441H5.7207V2.77441H11.7256Z";
|
|
71
|
+
/** Stem of the host right-up outline. */
|
|
72
|
+
const RIGHT_UP_STEM = "M2.77441 13.2255L12.3756 3.62427";
|
|
73
|
+
function revealIcon() {
|
|
74
|
+
return (0, react.createElement)("span", { className: "mh-br-icon" }, (0, react.createElement)("svg", {
|
|
75
|
+
width: 14,
|
|
76
|
+
height: 14,
|
|
77
|
+
viewBox: "0 0 16 16",
|
|
78
|
+
fill: "none",
|
|
79
|
+
strokeWidth: 1,
|
|
80
|
+
"aria-hidden": true
|
|
81
|
+
}, (0, react.createElement)("path", {
|
|
82
|
+
d: RIGHT_UP_CORNER,
|
|
83
|
+
fill: "currentColor"
|
|
84
|
+
}), (0, react.createElement)("path", {
|
|
85
|
+
d: RIGHT_UP_STEM,
|
|
86
|
+
stroke: "currentColor"
|
|
87
|
+
})));
|
|
88
|
+
}
|
|
89
|
+
/** The open handover: a short line and the button that raises its window. */
|
|
300
90
|
function HandoverRow(props) {
|
|
301
91
|
const [note, setNote] = (0, react.useState)(void 0);
|
|
302
|
-
return (0, react.createElement)("section", { className: "mh-br" }, (0, react.createElement)("style", null, STYLE$1), (0, react.createElement)("p", { className: "mh-br-line" }, props.t("waiting"
|
|
92
|
+
return (0, react.createElement)("section", { className: "mh-br" }, (0, react.createElement)("style", null, STYLE$1), (0, react.createElement)("p", { className: "mh-br-line" }, props.t("waiting")), (0, react.createElement)("button", {
|
|
303
93
|
type: "button",
|
|
304
94
|
className: "mh-br-button",
|
|
305
95
|
onClick: () => {
|
|
@@ -309,7 +99,7 @@ window.__ModuleLoader__.load({
|
|
|
309
99
|
setNote(props.t("failed"));
|
|
310
100
|
});
|
|
311
101
|
}
|
|
312
|
-
}, props.t("reveal")), note !== void 0 ? (0, react.createElement)("p", { className: "mh-br-status" }, note) : null);
|
|
102
|
+
}, revealIcon(), props.t("reveal")), note !== void 0 ? (0, react.createElement)("p", { className: "mh-br-status" }, note) : null);
|
|
313
103
|
}
|
|
314
104
|
/** `revealed` adds no status line. */
|
|
315
105
|
function noteFor(result, t) {
|
|
@@ -322,8 +112,8 @@ window.__ModuleLoader__.load({
|
|
|
322
112
|
/** Dictionary namespace for the handover row. */
|
|
323
113
|
const NS = "mh-browser";
|
|
324
114
|
const zh = {
|
|
325
|
-
waiting: "
|
|
326
|
-
reveal: "
|
|
115
|
+
waiting: "这一步要你在浏览器里做",
|
|
116
|
+
reveal: "打开浏览器里的页面",
|
|
327
117
|
notHandingOver: "这次交接已经结束",
|
|
328
118
|
noTab: "没有可以去的页面",
|
|
329
119
|
failed: "没能切到浏览器",
|
|
@@ -338,6 +128,10 @@ window.__ModuleLoader__.load({
|
|
|
338
128
|
pathDoesNotExist: "不存在",
|
|
339
129
|
pathIsDirectory: "是目录",
|
|
340
130
|
pathDenied: "没有权限({code})",
|
|
131
|
+
auto: "自动",
|
|
132
|
+
browserUsing: "当前使用:{name}。",
|
|
133
|
+
browserNone: "没有找到 Chrome 或 Edge。",
|
|
134
|
+
installChrome: "安装 Chrome",
|
|
341
135
|
chrome: "Google Chrome",
|
|
342
136
|
msedge: "Microsoft Edge",
|
|
343
137
|
chromium: "Chromium",
|
|
@@ -351,8 +145,8 @@ window.__ModuleLoader__.load({
|
|
|
351
145
|
discard: "放弃修改"
|
|
352
146
|
};
|
|
353
147
|
const en = {
|
|
354
|
-
waiting: "
|
|
355
|
-
reveal: "
|
|
148
|
+
waiting: "This step needs you in the browser",
|
|
149
|
+
reveal: "Open the page in the browser",
|
|
356
150
|
notHandingOver: "This handover has already ended",
|
|
357
151
|
noTab: "There is no page to open",
|
|
358
152
|
failed: "Could not switch to the browser",
|
|
@@ -367,6 +161,10 @@ window.__ModuleLoader__.load({
|
|
|
367
161
|
pathDoesNotExist: "does not exist",
|
|
368
162
|
pathIsDirectory: "is a directory",
|
|
369
163
|
pathDenied: "permission denied ({code})",
|
|
164
|
+
auto: "Automatic",
|
|
165
|
+
browserUsing: "In use: {name}.",
|
|
166
|
+
browserNone: "Chrome and Edge were not found.",
|
|
167
|
+
installChrome: "Install Chrome",
|
|
370
168
|
chrome: "Google Chrome",
|
|
371
169
|
msedge: "Microsoft Edge",
|
|
372
170
|
chromium: "Chromium",
|
|
@@ -388,6 +186,7 @@ window.__ModuleLoader__.load({
|
|
|
388
186
|
*/
|
|
389
187
|
const HANDOVER_KIND = "browser-handover";
|
|
390
188
|
const HANDOVER_TOOL = "browser_handover";
|
|
189
|
+
const ROW_DATA = {};
|
|
391
190
|
function isRecord$1(value) {
|
|
392
191
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
393
192
|
}
|
|
@@ -395,22 +194,11 @@ window.__ModuleLoader__.load({
|
|
|
395
194
|
if (!isRecord$1(data) || typeof data.turn !== "number") return void 0;
|
|
396
195
|
return data.turn;
|
|
397
196
|
}
|
|
398
|
-
function reasonOf(value) {
|
|
399
|
-
if (typeof value !== "string") return "";
|
|
400
|
-
try {
|
|
401
|
-
const parsed = JSON.parse(value);
|
|
402
|
-
if (!isRecord$1(parsed) || typeof parsed.reason !== "string") return "";
|
|
403
|
-
return parsed.reason;
|
|
404
|
-
} catch {
|
|
405
|
-
return "";
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
197
|
function callOf(data) {
|
|
409
198
|
if (!isRecord$1(data) || typeof data.callId !== "string" || typeof data.name !== "string") return void 0;
|
|
410
199
|
return {
|
|
411
200
|
callId: data.callId,
|
|
412
|
-
name: data.name
|
|
413
|
-
arguments: data.arguments
|
|
201
|
+
name: data.name
|
|
414
202
|
};
|
|
415
203
|
}
|
|
416
204
|
/** A result names its call on `message.source` and again on `message.toolCallId`. */
|
|
@@ -424,7 +212,7 @@ window.__ModuleLoader__.load({
|
|
|
424
212
|
return {
|
|
425
213
|
...current,
|
|
426
214
|
visibility: "hidden",
|
|
427
|
-
data:
|
|
215
|
+
data: ROW_DATA
|
|
428
216
|
};
|
|
429
217
|
}
|
|
430
218
|
/**
|
|
@@ -445,7 +233,7 @@ window.__ModuleLoader__.load({
|
|
|
445
233
|
location: context.start?.location ?? { kind: "unresolved" },
|
|
446
234
|
visibility: open === void 0 ? "hidden" : "visible",
|
|
447
235
|
groupTree: "turn",
|
|
448
|
-
data:
|
|
236
|
+
data: ROW_DATA
|
|
449
237
|
};
|
|
450
238
|
}
|
|
451
239
|
const handoverRowDefinition = {
|
|
@@ -483,7 +271,6 @@ window.__ModuleLoader__.load({
|
|
|
483
271
|
return {
|
|
484
272
|
open: {
|
|
485
273
|
callId: call.callId,
|
|
486
|
-
reason: reasonOf(call.arguments),
|
|
487
274
|
seq: event.seq
|
|
488
275
|
},
|
|
489
276
|
anchorSeq: event.seq
|
|
@@ -723,6 +510,7 @@ window.__ModuleLoader__.load({
|
|
|
723
510
|
.mh-browser-chevron { position: absolute; top: 50%; right: 12px; transform: translateY(-50%); color: var(--dsw-alias-label-tertiary); pointer-events: none; }
|
|
724
511
|
.mh-browser-invalid { margin: 0; font-size: 12px; line-height: 1.5; color: var(--dsw-alias-state-error-primary); }
|
|
725
512
|
.mh-browser-hint { margin: 0; font-size: 12px; line-height: 1.5; color: var(--dsw-alias-label-tertiary); }
|
|
513
|
+
.mh-browser-hint a { color: var(--dsw-alias-label-secondary); }
|
|
726
514
|
@media (hover: hover) {
|
|
727
515
|
.mh-browser-help-button:hover { background: var(--dsw-alias-bg-layer-4); color: var(--dsw-alias-label-secondary); }
|
|
728
516
|
.mh-browser-reset:hover:not(:disabled) { color: var(--dsw-alias-label-primary); }
|
|
@@ -874,10 +662,13 @@ window.__ModuleLoader__.load({
|
|
|
874
662
|
/** `plugins.row.config` key: the bundle package, then the row id. */
|
|
875
663
|
const ROW_KEY = "@mind-harness/mh-bundle#mh-browser";
|
|
876
664
|
const BROWSER_CHOICES = [
|
|
665
|
+
"auto",
|
|
877
666
|
"chrome",
|
|
878
667
|
"msedge",
|
|
879
668
|
"chromium"
|
|
880
669
|
];
|
|
670
|
+
/** Google's download page. Edge is not offered: its developer-mode prompt can disable the agent extension. */
|
|
671
|
+
const CHROME_INSTALL = "https://www.google.com/chrome/";
|
|
881
672
|
const LOADING = { status: "loading" };
|
|
882
673
|
/** Empty text clears the field. Anything else must be absolute, or start with `~`. */
|
|
883
674
|
function parseExecutable(text) {
|
|
@@ -896,7 +687,15 @@ window.__ModuleLoader__.load({
|
|
|
896
687
|
function pathPlaceholder(lookup, browser, t) {
|
|
897
688
|
if (lookup.status === "loading") return t("pathSearching");
|
|
898
689
|
if (lookup.status === "found") return lookup.path;
|
|
899
|
-
if (lookup.status === "missing") return t("pathMissing", { name: t(browser) });
|
|
690
|
+
if (lookup.status === "missing" && browser !== "auto") return t("pathMissing", { name: t(browser) });
|
|
691
|
+
}
|
|
692
|
+
/** The sentence under the browser menu: which browser automatic selection is using. */
|
|
693
|
+
function browserStatus(lookup, browser, t) {
|
|
694
|
+
const restart = t("browserHint");
|
|
695
|
+
if (browser !== "auto") return restart;
|
|
696
|
+
if (lookup.status === "found" && lookup.browser !== void 0) return `${t("browserUsing", { name: t(lookup.browser) })} ${restart}`;
|
|
697
|
+
if (lookup.status === "missing") return `${t("browserNone")} ${restart}`;
|
|
698
|
+
return restart;
|
|
900
699
|
}
|
|
901
700
|
/** The full path, or every place that was tried. Absent while looking or after a failed lookup. */
|
|
902
701
|
function pathHelpText(lookup, t) {
|
|
@@ -987,7 +786,10 @@ window.__ModuleLoader__.load({
|
|
|
987
786
|
}
|
|
988
787
|
};
|
|
989
788
|
function registerSettings(ctx) {
|
|
990
|
-
const form = new BrowserForm(ctx.configForms.get(ENTRY_ID), (browser, signal) =>
|
|
789
|
+
const form = new BrowserForm(ctx.configForms.get(ENTRY_ID), (browser, signal) => call("locate-for", {
|
|
790
|
+
method: "POST",
|
|
791
|
+
body: { browser }
|
|
792
|
+
}, signal));
|
|
991
793
|
ctx.effect(() => () => {
|
|
992
794
|
form.dispose();
|
|
993
795
|
});
|
|
@@ -1017,8 +819,9 @@ window.__ModuleLoader__.load({
|
|
|
1017
819
|
};
|
|
1018
820
|
}, [props.form]);
|
|
1019
821
|
const disabled = !state.writable || state.saving;
|
|
1020
|
-
const help = helpOf(lookup, props.t);
|
|
822
|
+
const help = helpOf(lookup, browser, props.t);
|
|
1021
823
|
const placeholder = state.executablePath.text === "" ? pathPlaceholder(lookup, browser, props.t) : void 0;
|
|
824
|
+
const offerChrome = browser === "auto" && lookup.status === "missing";
|
|
1022
825
|
return (0, react.createElement)(SettingsFrame, {
|
|
1023
826
|
labels: formLabels(props.t),
|
|
1024
827
|
state,
|
|
@@ -1027,7 +830,7 @@ window.__ModuleLoader__.load({
|
|
|
1027
830
|
}, (0, react.createElement)(ChoiceField, {
|
|
1028
831
|
id: "mh-browser-name",
|
|
1029
832
|
label: props.t("browserLabel"),
|
|
1030
|
-
hint: props.t
|
|
833
|
+
hint: browserStatus(lookup, browser, props.t),
|
|
1031
834
|
...state.browser,
|
|
1032
835
|
text: browser,
|
|
1033
836
|
options: BROWSER_CHOICES.map((name) => ({
|
|
@@ -1039,7 +842,11 @@ window.__ModuleLoader__.load({
|
|
|
1039
842
|
disabled,
|
|
1040
843
|
onEdit: (value) => props.form.edit("browser", value),
|
|
1041
844
|
onReset: () => props.form.reset("browser")
|
|
1042
|
-
}), (0, react.createElement)(
|
|
845
|
+
}), offerChrome ? (0, react.createElement)("p", { className: "mh-browser-hint" }, (0, react.createElement)("a", {
|
|
846
|
+
href: CHROME_INSTALL,
|
|
847
|
+
target: "_blank",
|
|
848
|
+
rel: "noopener noreferrer"
|
|
849
|
+
}, props.t("installChrome"))) : null, (0, react.createElement)(TextField, {
|
|
1043
850
|
id: "mh-browser-path",
|
|
1044
851
|
label: props.t("pathLabel"),
|
|
1045
852
|
hint: props.t("pathHint"),
|
|
@@ -1057,7 +864,7 @@ window.__ModuleLoader__.load({
|
|
|
1057
864
|
function browserField() {
|
|
1058
865
|
return {
|
|
1059
866
|
field: "browser",
|
|
1060
|
-
format: (value) => typeof value === "string" && isChoice(value) ? value : "
|
|
867
|
+
format: (value) => typeof value === "string" && isChoice(value) ? value : "auto",
|
|
1061
868
|
parse: (text) => isChoice(text) ? {
|
|
1062
869
|
kind: "set",
|
|
1063
870
|
value: text
|
|
@@ -1081,7 +888,7 @@ window.__ModuleLoader__.load({
|
|
|
1081
888
|
};
|
|
1082
889
|
}
|
|
1083
890
|
function choiceOf(text) {
|
|
1084
|
-
return isChoice(text) ? text : "
|
|
891
|
+
return isChoice(text) ? text : "auto";
|
|
1085
892
|
}
|
|
1086
893
|
function isChoice(value) {
|
|
1087
894
|
return BROWSER_CHOICES.includes(value);
|
|
@@ -1090,16 +897,25 @@ window.__ModuleLoader__.load({
|
|
|
1090
897
|
if (!result.ok) return { status: "failed" };
|
|
1091
898
|
if ("found" in result.value) return {
|
|
1092
899
|
status: "found",
|
|
1093
|
-
path: result.value.found
|
|
900
|
+
path: result.value.found,
|
|
901
|
+
...result.value.browser !== void 0 ? { browser: result.value.browser } : {}
|
|
1094
902
|
};
|
|
1095
903
|
return {
|
|
1096
904
|
status: "missing",
|
|
1097
905
|
tried: result.value.missing
|
|
1098
906
|
};
|
|
1099
907
|
}
|
|
1100
|
-
function helpOf(lookup, t) {
|
|
908
|
+
function helpOf(lookup, browser, t) {
|
|
1101
909
|
const text = pathHelpText(lookup, t);
|
|
1102
910
|
if (text === void 0) return void 0;
|
|
911
|
+
if (browser === "auto" && lookup.status === "missing") return {
|
|
912
|
+
label: t("pathHelp"),
|
|
913
|
+
content: (0, react.createElement)("span", null, text, " ", (0, react.createElement)("a", {
|
|
914
|
+
href: CHROME_INSTALL,
|
|
915
|
+
target: "_blank",
|
|
916
|
+
rel: "noopener noreferrer"
|
|
917
|
+
}, t("installChrome")))
|
|
918
|
+
};
|
|
1103
919
|
return {
|
|
1104
920
|
label: t("pathHelp"),
|
|
1105
921
|
content: text
|
|
@@ -1116,50 +932,58 @@ window.__ModuleLoader__.load({
|
|
|
1116
932
|
//#region src/client/client.ts
|
|
1117
933
|
/**
|
|
1118
934
|
* Cordis services this client reads. `dsh.client.inject` is package load
|
|
1119
|
-
* order, not this list.
|
|
935
|
+
* order, not this list.
|
|
1120
936
|
*/
|
|
1121
937
|
const inject = [
|
|
1122
938
|
"slots",
|
|
1123
939
|
"locale",
|
|
1124
|
-
"remote",
|
|
1125
940
|
"uiConversation",
|
|
1126
941
|
"configForms"
|
|
1127
942
|
];
|
|
1128
|
-
|
|
943
|
+
/** Host calls used by the handover row and the settings lookup. */
|
|
944
|
+
function browserApi() {
|
|
945
|
+
return {
|
|
946
|
+
revealHandover: (sessionId, signal) => call("reveal-handover", {
|
|
947
|
+
method: "POST",
|
|
948
|
+
body: { sessionId }
|
|
949
|
+
}, signal),
|
|
950
|
+
locateFor: (browser, signal) => call("locate-for", {
|
|
951
|
+
method: "POST",
|
|
952
|
+
body: { browser }
|
|
953
|
+
}, signal)
|
|
954
|
+
};
|
|
955
|
+
}
|
|
1129
956
|
async function apply(ctx) {
|
|
1130
|
-
const unmount = await ctx.remote.$mount(TYPERT_REMOTE);
|
|
1131
957
|
let release = () => void 0;
|
|
1132
|
-
await ctx.inject(
|
|
958
|
+
await ctx.inject([...inject], (inner) => {
|
|
1133
959
|
release = start(inner);
|
|
1134
960
|
registerSettings(inner);
|
|
1135
961
|
});
|
|
1136
962
|
return async () => {
|
|
1137
963
|
release();
|
|
1138
|
-
await unmount();
|
|
1139
964
|
};
|
|
1140
965
|
}
|
|
1141
966
|
/** Register the handover row. The tool call itself keeps the generic tool row. */
|
|
1142
|
-
function start(ctx) {
|
|
967
|
+
function start(ctx, api = browserApi()) {
|
|
1143
968
|
ctx.effect(() => ctx.locale.register(NS, {
|
|
1144
969
|
zh,
|
|
1145
970
|
en
|
|
1146
971
|
}));
|
|
1147
972
|
ctx.effect(() => ctx.uiConversation.events.register(handoverRowDefinition));
|
|
1148
|
-
const remote = ctx.remote.mhBrowser;
|
|
1149
973
|
ctx.slots.inject("conversation.chat.node", () => ctx.slots.register({
|
|
1150
974
|
name: "conversation.chat.node",
|
|
1151
975
|
key: HANDOVER_KIND,
|
|
1152
976
|
locale: NS
|
|
1153
977
|
}, (props) => (0, react.createElement)(HandoverRow, {
|
|
1154
978
|
sessionId: props.sessionId,
|
|
1155
|
-
reason: props.node.data.reason,
|
|
1156
979
|
t: props.t,
|
|
1157
|
-
reveal: (sessionId, signal) =>
|
|
980
|
+
reveal: (sessionId, signal) => api.revealHandover(sessionId, signal)
|
|
1158
981
|
})));
|
|
1159
982
|
return () => void 0;
|
|
1160
983
|
}
|
|
1161
984
|
//#endregion
|
|
1162
985
|
exports.apply = apply;
|
|
986
|
+
exports.browserApi = browserApi;
|
|
1163
987
|
exports.inject = inject;
|
|
1164
988
|
exports.start = start;
|
|
1165
989
|
return module.exports;
|