@zixt/host 0.0.146 → 0.0.148
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +98 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28,7 +28,7 @@ import { homedir as homedir4 } from "node:os";
|
|
|
28
28
|
// package.json
|
|
29
29
|
var package_default = {
|
|
30
30
|
name: "@zixt/host",
|
|
31
|
-
version: "0.0.
|
|
31
|
+
version: "0.0.148",
|
|
32
32
|
type: "module",
|
|
33
33
|
exports: {
|
|
34
34
|
".": "./src/client.ts",
|
|
@@ -14826,6 +14826,7 @@ var BrowserTab = external_exports.object({
|
|
|
14826
14826
|
loading: external_exports.boolean()
|
|
14827
14827
|
}).strict();
|
|
14828
14828
|
var BROWSER_MAX_TABS = 12;
|
|
14829
|
+
var ApprovalSignIn = external_exports.object({ origin: external_exports.string().min(1).max(300) }).strict();
|
|
14829
14830
|
var TeammateQuestionAttention = external_exports.enum(["browser", "answer"]);
|
|
14830
14831
|
var BrowserSessionState = external_exports.object({
|
|
14831
14832
|
browserSessionId: BrowserSessionId,
|
|
@@ -15093,6 +15094,12 @@ var Approval = external_exports.object({
|
|
|
15093
15094
|
questionnaire: Questionnaire.optional(),
|
|
15094
15095
|
/** Exact submitted questionnaire response, once answered. */
|
|
15095
15096
|
questionnaireAnswers: QuestionnaireAnswers.optional(),
|
|
15097
|
+
/**
|
|
15098
|
+
* Present when the Host raised this ask from a run stopped at a sign-in
|
|
15099
|
+
* wall. Every "a person is needed at the Browser" surface reads this rather
|
|
15100
|
+
* than hunting for the word "browser" in text the model wrote.
|
|
15101
|
+
*/
|
|
15102
|
+
signIn: ApprovalSignIn.optional(),
|
|
15096
15103
|
status: ApprovalStatus,
|
|
15097
15104
|
deliveryStatus: ApprovalDeliveryStatus,
|
|
15098
15105
|
/** Why delivery became impossible; null while pending or after delivery. */
|
|
@@ -19605,7 +19612,13 @@ var ApprovalRequest = external_exports.object({
|
|
|
19605
19612
|
/** Optional structured answers for agent.question; absent means free text. */
|
|
19606
19613
|
questionChoices: QuestionChoices.optional(),
|
|
19607
19614
|
/** Optional submit-once questionnaire for agent.question. */
|
|
19608
|
-
questionnaire: Questionnaire.optional()
|
|
19615
|
+
questionnaire: Questionnaire.optional(),
|
|
19616
|
+
/**
|
|
19617
|
+
* Set by the Host when this ask comes from a run stopped at a sign-in wall
|
|
19618
|
+
* its own Browser detected. This is what makes "a person is needed at the
|
|
19619
|
+
* Browser" a fact on the wire rather than a word the model had to type.
|
|
19620
|
+
*/
|
|
19621
|
+
signIn: ApprovalSignIn.optional()
|
|
19609
19622
|
});
|
|
19610
19623
|
var JournalAppend = external_exports.object({
|
|
19611
19624
|
type: external_exports.literal("journal.append"),
|
|
@@ -21535,6 +21548,14 @@ var AttentionItem = external_exports.object({
|
|
|
21535
21548
|
version: external_exports.string().min(1)
|
|
21536
21549
|
}),
|
|
21537
21550
|
href: external_exports.string().min(1),
|
|
21551
|
+
/**
|
|
21552
|
+
* This item is a teammate waiting at a sign-in it cannot pass. The
|
|
21553
|
+
* destination is therefore the teammate's Browser rather than a thread, and
|
|
21554
|
+
* every surface that rebuilds an item's link has to leave `href` alone —
|
|
21555
|
+
* sending someone to the conversation is exactly the dead end that made a
|
|
21556
|
+
* person go find the Browser themselves.
|
|
21557
|
+
*/
|
|
21558
|
+
needsBrowser: external_exports.boolean().optional(),
|
|
21538
21559
|
actions: external_exports.array(
|
|
21539
21560
|
external_exports.object({
|
|
21540
21561
|
kind: external_exports.enum([
|
|
@@ -26103,7 +26124,7 @@ var HostClient = class _HostClient {
|
|
|
26103
26124
|
const { provider: _provider, ...legacyGrant } = grant;
|
|
26104
26125
|
return legacyGrant;
|
|
26105
26126
|
};
|
|
26106
|
-
const requestApproval = (category, summary, payload, questionChoices, questionnaire) => {
|
|
26127
|
+
const requestApproval = (category, summary, payload, questionChoices, questionnaire, signIn) => {
|
|
26107
26128
|
if (authorityController.signal.aborted) {
|
|
26108
26129
|
return Promise.resolve({ approved: false, guidance: "task was cancelled" });
|
|
26109
26130
|
}
|
|
@@ -26117,7 +26138,8 @@ var HostClient = class _HostClient {
|
|
|
26117
26138
|
summary: safe(summary, 500),
|
|
26118
26139
|
payload: safe(payload, 5e4),
|
|
26119
26140
|
...questionChoices ? { questionChoices: [...questionChoices] } : {},
|
|
26120
|
-
...questionnaire ? { questionnaire } : {}
|
|
26141
|
+
...questionnaire ? { questionnaire } : {},
|
|
26142
|
+
...signIn ? { signIn: { origin: safe(signIn.origin, 300) } } : {}
|
|
26121
26143
|
});
|
|
26122
26144
|
return new Promise((resolve20) => {
|
|
26123
26145
|
const waiters = this.approvalWaiters.get(cancelKey) ?? /* @__PURE__ */ new Map();
|
|
@@ -31500,6 +31522,47 @@ async function installChromium() {
|
|
|
31500
31522
|
});
|
|
31501
31523
|
}
|
|
31502
31524
|
var KEY_ALIASES = { " ": "Space" };
|
|
31525
|
+
async function captureUserAgentMetadata(context) {
|
|
31526
|
+
let probe = null;
|
|
31527
|
+
try {
|
|
31528
|
+
probe = await context.newPage();
|
|
31529
|
+
await probe.route(
|
|
31530
|
+
"**/*",
|
|
31531
|
+
(route) => route.fulfill({ status: 200, contentType: "text/html", body: "<!doctype html>" })
|
|
31532
|
+
);
|
|
31533
|
+
await probe.goto("https://user-agent.zixt.invalid/", { waitUntil: "domcontentloaded" });
|
|
31534
|
+
return await probe.evaluate(async () => {
|
|
31535
|
+
const data = navigator.userAgentData;
|
|
31536
|
+
if (!data) return null;
|
|
31537
|
+
const hints = await data.getHighEntropyValues([
|
|
31538
|
+
"architecture",
|
|
31539
|
+
"bitness",
|
|
31540
|
+
"model",
|
|
31541
|
+
"platformVersion",
|
|
31542
|
+
"uaFullVersion",
|
|
31543
|
+
"fullVersionList",
|
|
31544
|
+
"wow64"
|
|
31545
|
+
]);
|
|
31546
|
+
return {
|
|
31547
|
+
brands: hints["brands"] ?? [],
|
|
31548
|
+
fullVersionList: hints["fullVersionList"] ?? [],
|
|
31549
|
+
fullVersion: String(hints["uaFullVersion"] ?? ""),
|
|
31550
|
+
platform: String(hints["platform"] ?? ""),
|
|
31551
|
+
platformVersion: String(hints["platformVersion"] ?? ""),
|
|
31552
|
+
architecture: String(hints["architecture"] ?? ""),
|
|
31553
|
+
model: String(hints["model"] ?? ""),
|
|
31554
|
+
mobile: Boolean(hints["mobile"]),
|
|
31555
|
+
bitness: String(hints["bitness"] ?? ""),
|
|
31556
|
+
wow64: Boolean(hints["wow64"])
|
|
31557
|
+
};
|
|
31558
|
+
});
|
|
31559
|
+
} catch {
|
|
31560
|
+
return null;
|
|
31561
|
+
} finally {
|
|
31562
|
+
if (probe) await probe.close().catch(() => {
|
|
31563
|
+
});
|
|
31564
|
+
}
|
|
31565
|
+
}
|
|
31503
31566
|
function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
|
|
31504
31567
|
const load = dependencies.loadPlaywright ?? loadPlaywright;
|
|
31505
31568
|
const install = dependencies.installChromium ?? installChromium;
|
|
@@ -31529,7 +31592,8 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
|
|
|
31529
31592
|
args: ["--disable-blink-features=AutomationControlled"]
|
|
31530
31593
|
});
|
|
31531
31594
|
await Promise.all(context.pages().map((page2) => page2.close()));
|
|
31532
|
-
|
|
31595
|
+
const userAgentMetadata = await captureUserAgentMetadata(context);
|
|
31596
|
+
runtime = { context, references: 0, userAgentMetadata };
|
|
31533
31597
|
runtimes.set(profileDir, runtime);
|
|
31534
31598
|
}
|
|
31535
31599
|
runtime.references += 1;
|
|
@@ -31703,7 +31767,8 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
|
|
|
31703
31767
|
realisticUserAgent = reported.replace("HeadlessChrome/", "Chrome/");
|
|
31704
31768
|
}
|
|
31705
31769
|
await tab.cdp.send("Emulation.setUserAgentOverride", {
|
|
31706
|
-
userAgent: realisticUserAgent
|
|
31770
|
+
userAgent: realisticUserAgent,
|
|
31771
|
+
...runtime.userAgentMetadata ? { userAgentMetadata: runtime.userAgentMetadata } : {}
|
|
31707
31772
|
});
|
|
31708
31773
|
} catch {
|
|
31709
31774
|
}
|
|
@@ -31959,7 +32024,11 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
|
|
|
31959
32024
|
};
|
|
31960
32025
|
},
|
|
31961
32026
|
async screenshot() {
|
|
31962
|
-
const image = await requireActive().page.screenshot({
|
|
32027
|
+
const image = await requireActive().page.screenshot({
|
|
32028
|
+
type: "jpeg",
|
|
32029
|
+
quality: 70,
|
|
32030
|
+
caret: "initial"
|
|
32031
|
+
});
|
|
31963
32032
|
return {
|
|
31964
32033
|
jpegBase64: image.toString("base64"),
|
|
31965
32034
|
width: liveViewport.width,
|
|
@@ -32115,7 +32184,7 @@ function authenticationWallGuidance(origin) {
|
|
|
32115
32184
|
return [
|
|
32116
32185
|
`This page is asking someone to sign in to ${origin}.`,
|
|
32117
32186
|
"If a saved website-login Credential covers this site, call browser_login with its name.",
|
|
32118
|
-
"Otherwise stop here and use ask_user to ask the person to sign in at the Browser panel
|
|
32187
|
+
"Otherwise stop here and use ask_user to ask the person to sign in at the Browser panel; say plainly which site and why you are stopped, and their panel opens on this page for them.",
|
|
32119
32188
|
"That is the route to ask for, because a saved login is filled by Host code, is never shown to you, and is scrubbed from anything you write.",
|
|
32120
32189
|
"This browser and its profile outlive the run, so a person can sign in after your session checkpoints and you continue on the authenticated page.",
|
|
32121
32190
|
"A one-time code expires and a person is faster at their own password prompt, so do not ask for either instead of the handoff; if they choose to send you a credential anyway, use it without repeating it.",
|
|
@@ -32252,8 +32321,7 @@ var BROWSER_TOOL_DEFINITIONS = [
|
|
|
32252
32321
|
];
|
|
32253
32322
|
|
|
32254
32323
|
// src/tool-packs/browser/index.ts
|
|
32255
|
-
function
|
|
32256
|
-
const wall = detectAuthenticationWall(page2);
|
|
32324
|
+
function externalPageOutcome(page2, data, truncated, wall) {
|
|
32257
32325
|
return {
|
|
32258
32326
|
ok: true,
|
|
32259
32327
|
result: {
|
|
@@ -32269,6 +32337,11 @@ var asNumber = (value) => typeof value === "number" && Number.isFinite(value) ?
|
|
|
32269
32337
|
function createBrowserToolPack(deps) {
|
|
32270
32338
|
const { manager, taskId, agentId } = deps;
|
|
32271
32339
|
let detached = false;
|
|
32340
|
+
let signInWall = null;
|
|
32341
|
+
const externalPage = (page2, data, truncated = false) => {
|
|
32342
|
+
signInWall = detectAuthenticationWall(page2);
|
|
32343
|
+
return externalPageOutcome(page2, data, truncated, signInWall);
|
|
32344
|
+
};
|
|
32272
32345
|
const guard = () => {
|
|
32273
32346
|
if (detached) return "this run has ended; the browser tool is detached";
|
|
32274
32347
|
if (deps.authoritySignal.aborted || deps.cancelledNow()) return "task was cancelled";
|
|
@@ -32477,6 +32550,7 @@ function createBrowserToolPack(deps) {
|
|
|
32477
32550
|
version: 1,
|
|
32478
32551
|
tools: BROWSER_TOOL_DEFINITIONS,
|
|
32479
32552
|
call,
|
|
32553
|
+
currentSignInWall: () => signInWall ? { origin: signInWall.origin } : null,
|
|
32480
32554
|
async close() {
|
|
32481
32555
|
detached = true;
|
|
32482
32556
|
}
|
|
@@ -42014,18 +42088,18 @@ function createCliRunner(adapter, opts = {}) {
|
|
|
42014
42088
|
"This Task needs a web browser, but the Browser is no longer available on this Machine. Install the pinned Chromium build or continue the Task on a Browser-ready Machine."
|
|
42015
42089
|
);
|
|
42016
42090
|
}
|
|
42091
|
+
let browserPack = null;
|
|
42017
42092
|
if (task.spec.requiresBrowser && opts.browserManager && browserAvailable) {
|
|
42018
|
-
|
|
42019
|
-
|
|
42020
|
-
|
|
42021
|
-
|
|
42022
|
-
|
|
42023
|
-
|
|
42024
|
-
|
|
42025
|
-
|
|
42026
|
-
|
|
42027
|
-
|
|
42028
|
-
);
|
|
42093
|
+
browserPack = createBrowserToolPack({
|
|
42094
|
+
manager: opts.browserManager,
|
|
42095
|
+
taskId: task.taskId,
|
|
42096
|
+
agentId: task.agentId,
|
|
42097
|
+
authoritySignal: task.authoritySignal,
|
|
42098
|
+
cancelledNow: task.cancelledNow,
|
|
42099
|
+
requestWebLogin: task.requestWebLogin,
|
|
42100
|
+
event: task.event
|
|
42101
|
+
});
|
|
42102
|
+
toolPacks.push(browserPack);
|
|
42029
42103
|
}
|
|
42030
42104
|
let preparedWorkspace = null;
|
|
42031
42105
|
if (task.spec.providerWorkspace) {
|
|
@@ -42044,12 +42118,14 @@ function createCliRunner(adapter, opts = {}) {
|
|
|
42044
42118
|
askUser: async (question, context, choices, questionnaire) => {
|
|
42045
42119
|
pendingAsks++;
|
|
42046
42120
|
try {
|
|
42121
|
+
const signInWall = browserPack?.currentSignInWall?.() ?? null;
|
|
42047
42122
|
const decision = await task.requestApproval(
|
|
42048
42123
|
"agent.question",
|
|
42049
42124
|
question.slice(0, 500),
|
|
42050
42125
|
(context || question).slice(0, MAX_APPROVAL_PAYLOAD),
|
|
42051
42126
|
choices,
|
|
42052
|
-
questionnaire
|
|
42127
|
+
questionnaire,
|
|
42128
|
+
signInWall ?? void 0
|
|
42053
42129
|
);
|
|
42054
42130
|
return decision.guidance ?? (decision.approved ? "Approved. Proceed." : "No. Do not proceed.");
|
|
42055
42131
|
} finally {
|