@zixt/host 0.0.147 → 0.0.149

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +99 -23
  2. 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.147",
31
+ version: "0.0.149",
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. */
@@ -15901,7 +15908,7 @@ var CompanyProfileSource = external_exports.enum([
15901
15908
  var CompanyProfileTrust = external_exports.enum(["internal", "external"]);
15902
15909
  var COMPANY_PROFILE_SUBJECT_MAX = 60;
15903
15910
  var COMPANY_PROFILE_TEXT_MAX = 300;
15904
- var COMPANY_PROFILE_MAX_ENTRIES = 80;
15911
+ var COMPANY_PROFILE_MAX_ENTRIES = 500;
15905
15912
  var COMPANY_PROFILE_SOURCE_URL_MAX = 500;
15906
15913
  var CompanyProfileEntry = external_exports.object({
15907
15914
  id: CompanyProfileEntryId,
@@ -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
- runtime = { context, references: 0 };
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({ type: "jpeg", quality: 70 });
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, naming the Browser in the question so their panel opens.",
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 externalPage(page2, data, truncated = false) {
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
- toolPacks.push(
42019
- createBrowserToolPack({
42020
- manager: opts.browserManager,
42021
- taskId: task.taskId,
42022
- agentId: task.agentId,
42023
- authoritySignal: task.authoritySignal,
42024
- cancelledNow: task.cancelledNow,
42025
- requestWebLogin: task.requestWebLogin,
42026
- event: task.event
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.147",
3
+ "version": "0.0.149",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",