@zixt/host 0.0.156 → 0.0.157

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 +327 -9
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -28,7 +28,7 @@ import { homedir as homedir6 } from "node:os";
28
28
  // package.json
29
29
  var package_default = {
30
30
  name: "@zixt/host",
31
- version: "0.0.156",
31
+ version: "0.0.157",
32
32
  type: "module",
33
33
  exports: {
34
34
  ".": "./src/client.ts",
@@ -14881,6 +14881,23 @@ var BrowserFramePayload = external_exports.object({
14881
14881
  width: external_exports.number().int().min(1).max(3840),
14882
14882
  height: external_exports.number().int().min(1).max(2160)
14883
14883
  }).strict();
14884
+ var BrowserCookie = external_exports.object({
14885
+ name: external_exports.string().min(1).max(256),
14886
+ value: external_exports.string().max(8192),
14887
+ domain: external_exports.string().min(1).max(253),
14888
+ path: external_exports.string().min(1).max(2048),
14889
+ expires: external_exports.number().finite().min(-1).max(253402300799),
14890
+ httpOnly: external_exports.boolean(),
14891
+ secure: external_exports.boolean(),
14892
+ sameSite: external_exports.enum(["Strict", "Lax", "None"]),
14893
+ /** Chromium partition key for CHIPS cookies, when present. */
14894
+ partitionKey: external_exports.string().min(1).max(2048).optional()
14895
+ }).strict();
14896
+ var BROWSER_MAX_SYNCED_COOKIES = 512;
14897
+ var BrowserCookieState = external_exports.object({
14898
+ revision: external_exports.number().int().min(0),
14899
+ cookies: external_exports.array(BrowserCookie).max(BROWSER_MAX_SYNCED_COOKIES)
14900
+ }).strict();
14884
14901
  var inputCoordinate = external_exports.number().min(0).max(16384);
14885
14902
  var BrowserMouseButton = external_exports.enum(["left", "middle", "right"]);
14886
14903
  var BrowserInputEvent = external_exports.discriminatedUnion("kind", [
@@ -14940,7 +14957,7 @@ var BrowserSessionProjection = external_exports.object({
14940
14957
  canStart: external_exports.boolean(),
14941
14958
  /** Member-safe reason when canStart is false. */
14942
14959
  reason: external_exports.string().max(300).optional(),
14943
- /** Present only when active work must use a different Machine-local profile. */
14960
+ /** Present only when active work uses a different local profile Machine. */
14944
14961
  profileContext: BrowserProfileContext.optional()
14945
14962
  }).strict();
14946
14963
  var StartBrowserSessionRequest = external_exports.object({ url: external_exports.string().min(1).max(2e3).optional() }).strict();
@@ -18338,7 +18355,7 @@ var ListTasksResponse = external_exports.object({
18338
18355
  }).strict();
18339
18356
 
18340
18357
  // ../../packages/contracts/src/protocol.ts
18341
- var PROTOCOL_VERSION = 13;
18358
+ var PROTOCOL_VERSION = 14;
18342
18359
  var BROWSER_PROFILE_INVENTORY_PAGE_SIZE = 200;
18343
18360
  var HELLO_UNWOUND_ASSIGNMENT_LIMIT = 1e3;
18344
18361
  var TASK_CANCEL_ACK_EVENT = "zixt.task.cancel.acknowledged";
@@ -19512,6 +19529,44 @@ var BrowserSessionEndedFrame = external_exports.object({
19512
19529
  agentId: AgentId,
19513
19530
  reason: BrowserSessionEndReason
19514
19531
  });
19532
+ var BrowserCookieSyncFrame = external_exports.object({
19533
+ type: external_exports.literal("browser.cookies.sync"),
19534
+ requestId: external_exports.string().min(1).max(200),
19535
+ projectId: ProjectId,
19536
+ taskId: TaskId,
19537
+ agentId: AgentId,
19538
+ browserSessionId: external_exports.string().min(1).max(200),
19539
+ /** Omitted only by a Machine that has not received the canonical jar yet. */
19540
+ baseRevision: external_exports.number().int().min(0).optional(),
19541
+ cookies: external_exports.array(BrowserCookie).max(BROWSER_MAX_SYNCED_COOKIES)
19542
+ }).strict();
19543
+ var BrowserCookieSyncResultFrame = external_exports.discriminatedUnion("ok", [
19544
+ external_exports.object({
19545
+ type: external_exports.literal("browser.cookies.result"),
19546
+ requestId: external_exports.string().min(1).max(200),
19547
+ projectId: ProjectId,
19548
+ taskId: TaskId,
19549
+ agentId: AgentId,
19550
+ browserSessionId: external_exports.string().min(1).max(200),
19551
+ ok: external_exports.literal(true),
19552
+ /** False asks the Host to reconcile its local changes over this newer jar. */
19553
+ accepted: external_exports.boolean(),
19554
+ state: BrowserCookieState,
19555
+ error: external_exports.never().optional()
19556
+ }).strict(),
19557
+ external_exports.object({
19558
+ type: external_exports.literal("browser.cookies.result"),
19559
+ requestId: external_exports.string().min(1).max(200),
19560
+ projectId: ProjectId,
19561
+ taskId: TaskId,
19562
+ agentId: AgentId,
19563
+ browserSessionId: external_exports.string().min(1).max(200),
19564
+ ok: external_exports.literal(false),
19565
+ accepted: external_exports.never().optional(),
19566
+ state: external_exports.never().optional(),
19567
+ error: external_exports.string().min(1).max(300)
19568
+ }).strict()
19569
+ ]);
19515
19570
  var BrowserCredentialRequestFrame = external_exports.object({
19516
19571
  type: external_exports.literal("browser.credential.request"),
19517
19572
  projectId: ProjectId,
@@ -19939,6 +19994,7 @@ var HostToCloudFrame = external_exports.discriminatedUnion("type", [
19939
19994
  BrowserStateFrame,
19940
19995
  BrowserScreencastFrame,
19941
19996
  BrowserSessionEndedFrame,
19997
+ BrowserCookieSyncFrame,
19942
19998
  BrowserCredentialRequestFrame,
19943
19999
  BrowserProfilePurged,
19944
20000
  PingFrame,
@@ -19946,6 +20002,7 @@ var HostToCloudFrame = external_exports.discriminatedUnion("type", [
19946
20002
  ]);
19947
20003
  var CloudToHostFrame = external_exports.discriminatedUnion("type", [
19948
20004
  HelloAckFrame,
20005
+ BrowserCookieSyncResultFrame,
19949
20006
  DeliverFrame,
19950
20007
  ConnectionProbeFrame,
19951
20008
  ApiOperationCallFrame,
@@ -25813,6 +25870,8 @@ var HostClient = class _HostClient {
25813
25870
  operationGrantWaiters = /* @__PURE__ */ new Map();
25814
25871
  /** Project/Task-qualified, socket-generation-bound web_login exchanges. */
25815
25872
  browserCredentialWaiters = /* @__PURE__ */ new Map();
25873
+ /** Project-scoped, socket-generation-bound Browser cookie exchanges. */
25874
+ browserCookieSyncWaiters = /* @__PURE__ */ new Map();
25816
25875
  /** True only after the connected cloud's helloAck advertised the feature. */
25817
25876
  browserFeatureActive = false;
25818
25877
  workingContextFeatureActive = false;
@@ -25978,6 +26037,13 @@ var HostClient = class _HostClient {
25978
26037
  waiter.deny("No sign-in was attempted: this machine lost its connection to Zixt.");
25979
26038
  }
25980
26039
  }
26040
+ rejectBrowserCookieSyncWaiters() {
26041
+ for (const [requestId, waiter] of this.browserCookieSyncWaiters) {
26042
+ clearTimeout(waiter.timer);
26043
+ this.browserCookieSyncWaiters.delete(requestId);
26044
+ waiter.deny("Browser cookie synchronization lost its Zixt connection.");
26045
+ }
26046
+ }
25981
26047
  async unwindAllRuns(reason, stopReason) {
25982
26048
  const runs = [...this.activeRuns.values()];
25983
26049
  const unwindingAssignments = [...this.activeAssignments.values()];
@@ -26017,6 +26083,7 @@ var HostClient = class _HostClient {
26017
26083
  }
26018
26084
  this.rejectOperationGrantWaiters();
26019
26085
  this.rejectBrowserCredentialWaiters();
26086
+ this.rejectBrowserCookieSyncWaiters();
26020
26087
  for (const deadline of this.authorityExpiryTimers.values()) clearTimeout(deadline.timer);
26021
26088
  this.cancels.clear();
26022
26089
  this.secretGrants.clear();
@@ -26369,10 +26436,46 @@ var HostClient = class _HostClient {
26369
26436
  * frame at a non-advertising cloud would each close the socket outright.
26370
26437
  */
26371
26438
  sendBrowserFrame(frame) {
26372
- if (!this.browserFeatureActive) return;
26439
+ if (!this.browserFeatureActive) return false;
26373
26440
  const projectId = frame.type === "browser.state" ? frame.state.projectId : frame.type === "browser.frame" ? frame.frame.projectId : frame.projectId;
26374
- if (this.purgingProjects.has(projectId)) return;
26375
- this.send(frame);
26441
+ if (this.purgingProjects.has(projectId)) return false;
26442
+ return this.send(frame);
26443
+ }
26444
+ requestBrowserCookieSync(input) {
26445
+ const socket = this.ws;
26446
+ if (!socket || !this.browserFeatureActive || !this.protocolReady) {
26447
+ return Promise.reject(
26448
+ new Error("Browser cookie synchronization has no live Zixt connection.")
26449
+ );
26450
+ }
26451
+ const requestId = crypto.randomUUID();
26452
+ return new Promise((resolve24, reject3) => {
26453
+ const timer = setTimeout(() => {
26454
+ if (this.browserCookieSyncWaiters.delete(requestId)) {
26455
+ reject3(new Error("Zixt did not answer Browser cookie synchronization in time."));
26456
+ }
26457
+ }, 3e4);
26458
+ timer.unref?.();
26459
+ this.browserCookieSyncWaiters.set(requestId, {
26460
+ projectId: input.projectId,
26461
+ taskId: input.taskId,
26462
+ agentId: input.agentId,
26463
+ browserSessionId: input.browserSessionId,
26464
+ socket,
26465
+ timer,
26466
+ accept: resolve24,
26467
+ deny: (reason) => reject3(new Error(reason))
26468
+ });
26469
+ if (!this.sendBrowserFrame({
26470
+ type: "browser.cookies.sync",
26471
+ requestId,
26472
+ ...input
26473
+ })) {
26474
+ clearTimeout(timer);
26475
+ this.browserCookieSyncWaiters.delete(requestId);
26476
+ reject3(new Error("Browser cookie synchronization has no live Zixt connection."));
26477
+ }
26478
+ });
26376
26479
  }
26377
26480
  replaceablePendingUp(message) {
26378
26481
  return message.type === "host.report" || message.type === "task.working_context" || message.type === "task.runner_runtime" || message.type === "task.title" || message.type === "task.event" && message.event.ephemeral === true;
@@ -26594,7 +26697,8 @@ var HostClient = class _HostClient {
26594
26697
  taskId,
26595
26698
  agentId,
26596
26699
  reason
26597
- })
26700
+ }),
26701
+ syncCookies: (input) => this.requestBrowserCookieSync(input)
26598
26702
  });
26599
26703
  } else {
26600
26704
  this.opts.browser?.attach(null);
@@ -26708,6 +26812,17 @@ var HostClient = class _HostClient {
26708
26812
  waiter.accept(grant);
26709
26813
  return;
26710
26814
  }
26815
+ case "browser.cookies.result": {
26816
+ const waiter = this.browserCookieSyncWaiters.get(frame.requestId);
26817
+ if (!waiter || waiter.socket !== sourceSocket || waiter.projectId !== frame.projectId || waiter.taskId !== frame.taskId || waiter.agentId !== frame.agentId || waiter.browserSessionId !== frame.browserSessionId) {
26818
+ return;
26819
+ }
26820
+ clearTimeout(waiter.timer);
26821
+ this.browserCookieSyncWaiters.delete(frame.requestId);
26822
+ if (frame.ok) waiter.accept({ accepted: frame.accepted, state: frame.state });
26823
+ else waiter.deny(frame.error);
26824
+ return;
26825
+ }
26711
26826
  case "browser.open": {
26712
26827
  if (!this.acceptsVolatileProjectWork(frame.projectId, frame.projectWorkFenceRevision)) {
26713
26828
  return;
@@ -32486,6 +32601,7 @@ function createDemoBrowserAdapterFactory() {
32486
32601
  const tabs = [newDemoTab()];
32487
32602
  let activeIndex = 0;
32488
32603
  let sink = null;
32604
+ let cookies = [];
32489
32605
  const listeners = [];
32490
32606
  const frame = () => ({
32491
32607
  jpegBase64: DEMO_FRAME_JPEG_BASE64,
@@ -32629,6 +32745,12 @@ function createDemoBrowserAdapterFactory() {
32629
32745
  }
32630
32746
  emit();
32631
32747
  },
32748
+ async cookies() {
32749
+ return cookies.map((cookie) => ({ ...cookie }));
32750
+ },
32751
+ async replaceCookies(next) {
32752
+ cookies = next.map((cookie) => ({ ...cookie }));
32753
+ },
32632
32754
  async close() {
32633
32755
  sink = null;
32634
32756
  }
@@ -44384,6 +44506,10 @@ var BrowserManager = class {
44384
44506
  deniedAuthorizations = /* @__PURE__ */ new Map();
44385
44507
  /** Serializes profile lifecycle and session open/close per teammate. */
44386
44508
  locks = /* @__PURE__ */ new Map();
44509
+ /** Last cloud-canonical jar observed for each exact Project teammate. */
44510
+ cookieStates = /* @__PURE__ */ new Map();
44511
+ cookieSyncTails = /* @__PURE__ */ new Map();
44512
+ cookieSyncTimers = /* @__PURE__ */ new Map();
44387
44513
  events = null;
44388
44514
  profileRoot;
44389
44515
  profileStateRoot;
@@ -44400,8 +44526,15 @@ var BrowserManager = class {
44400
44526
  attach(events) {
44401
44527
  this.events = events;
44402
44528
  if (!events) return;
44529
+ const scheduledProfiles = /* @__PURE__ */ new Set();
44403
44530
  for (const session of this.sessions.values()) {
44404
- if (!session.closed) events.state(this.stateOf(session));
44531
+ if (session.closed) continue;
44532
+ events.state(this.stateOf(session));
44533
+ const profileKey = this.profileKey(session.projectId, session.agentId);
44534
+ if (!scheduledProfiles.has(profileKey)) {
44535
+ scheduledProfiles.add(profileKey);
44536
+ this.scheduleCookieSync(session, 0);
44537
+ }
44405
44538
  }
44406
44539
  }
44407
44540
  capability() {
@@ -44486,6 +44619,39 @@ var BrowserManager = class {
44486
44619
  profileKey(projectId, agentId) {
44487
44620
  return `${projectId}:${agentId}`;
44488
44621
  }
44622
+ cookieKey(cookie) {
44623
+ return `${cookie.name}\0${cookie.domain}\0${cookie.path}\0${cookie.partitionKey ?? ""}`;
44624
+ }
44625
+ normalizedCookies(cookies) {
44626
+ return [
44627
+ ...new Map(cookies.map((cookie) => [this.cookieKey(cookie), { ...cookie }])).values()
44628
+ ].sort((left, right) => this.cookieKey(left).localeCompare(this.cookieKey(right)));
44629
+ }
44630
+ cookiesEqual(left, right) {
44631
+ return JSON.stringify(this.normalizedCookies(left)) === JSON.stringify(this.normalizedCookies(right));
44632
+ }
44633
+ /**
44634
+ * Rebase only the changes this Machine made since its last canonical jar
44635
+ * over the newer jar returned by another Machine. Unchanged cookies retain
44636
+ * the remote value; local additions, changes, and deletions win per cookie.
44637
+ */
44638
+ mergeCookieChanges(base, local, remote) {
44639
+ const baseByKey = new Map(base.map((cookie) => [this.cookieKey(cookie), cookie]));
44640
+ const localByKey = new Map(local.map((cookie) => [this.cookieKey(cookie), cookie]));
44641
+ const merged = new Map(remote.map((cookie) => [this.cookieKey(cookie), { ...cookie }]));
44642
+ for (const [key, baseCookie] of baseByKey) {
44643
+ const localCookie = localByKey.get(key);
44644
+ if (!localCookie) {
44645
+ merged.delete(key);
44646
+ } else if (!this.cookiesEqual([baseCookie], [localCookie])) {
44647
+ merged.set(key, { ...localCookie });
44648
+ }
44649
+ }
44650
+ for (const [key, localCookie] of localByKey) {
44651
+ if (!baseByKey.has(key)) merged.set(key, { ...localCookie });
44652
+ }
44653
+ return this.normalizedCookies([...merged.values()]);
44654
+ }
44489
44655
  exactChild(root, child) {
44490
44656
  const canonicalRoot = resolve16(root);
44491
44657
  const target = resolve16(canonicalRoot, child);
@@ -44606,6 +44772,85 @@ var BrowserManager = class {
44606
44772
  throw error52;
44607
44773
  }
44608
44774
  }
44775
+ synchronizeCookies(session) {
44776
+ const profileKey = this.profileKey(session.projectId, session.agentId);
44777
+ const tail = this.cookieSyncTails.get(profileKey) ?? Promise.resolve();
44778
+ const next = tail.then(async () => {
44779
+ if (session.closed) return;
44780
+ const synchronize = this.events?.syncCookies;
44781
+ if (!synchronize) return;
44782
+ let baseline = this.cookieStates.get(profileKey);
44783
+ let observedLocal = this.normalizedCookies(await session.adapter.cookies());
44784
+ let desired = observedLocal;
44785
+ for (let attempt = 0; attempt < 8; attempt++) {
44786
+ if (desired.length > BROWSER_MAX_SYNCED_COOKIES) {
44787
+ throw new Error(
44788
+ `the browser profile has more than ${BROWSER_MAX_SYNCED_COOKIES} cookies and cannot be synchronized safely`
44789
+ );
44790
+ }
44791
+ const result = await synchronize({
44792
+ projectId: session.projectId,
44793
+ taskId: session.taskId,
44794
+ agentId: session.agentId,
44795
+ browserSessionId: session.browserSessionId,
44796
+ ...baseline ? { baseRevision: baseline.revision } : {},
44797
+ cookies: desired
44798
+ });
44799
+ if (result.accepted) {
44800
+ const canonical = {
44801
+ revision: result.state.revision,
44802
+ cookies: this.normalizedCookies(result.state.cookies)
44803
+ };
44804
+ this.cookieStates.set(profileKey, canonical);
44805
+ const current2 = this.normalizedCookies(await session.adapter.cookies());
44806
+ if (!this.cookiesEqual(current2, observedLocal)) {
44807
+ baseline = canonical;
44808
+ desired = this.mergeCookieChanges(observedLocal, current2, canonical.cookies);
44809
+ observedLocal = current2;
44810
+ continue;
44811
+ }
44812
+ if (!this.cookiesEqual(current2, canonical.cookies)) {
44813
+ await session.adapter.replaceCookies(canonical.cookies);
44814
+ }
44815
+ return;
44816
+ }
44817
+ const remote = {
44818
+ revision: result.state.revision,
44819
+ cookies: this.normalizedCookies(result.state.cookies)
44820
+ };
44821
+ if (!baseline) {
44822
+ this.cookieStates.set(profileKey, remote);
44823
+ await session.adapter.replaceCookies(remote.cookies);
44824
+ return;
44825
+ }
44826
+ const current = this.normalizedCookies(await session.adapter.cookies());
44827
+ const currentDesired = this.cookiesEqual(current, observedLocal) ? desired : this.mergeCookieChanges(observedLocal, current, desired);
44828
+ desired = this.mergeCookieChanges(baseline.cookies, currentDesired, remote.cookies);
44829
+ baseline = remote;
44830
+ observedLocal = current;
44831
+ }
44832
+ throw new Error("browser cookies changed too many times while synchronizing");
44833
+ });
44834
+ const tracked = next.finally(() => {
44835
+ if (this.cookieSyncTails.get(profileKey) === tracked) this.cookieSyncTails.delete(profileKey);
44836
+ });
44837
+ this.cookieSyncTails.set(profileKey, tracked);
44838
+ return next;
44839
+ }
44840
+ scheduleCookieSync(session, delayMs = 250) {
44841
+ if (session.closed || !this.events?.syncCookies) return;
44842
+ const profileKey = this.profileKey(session.projectId, session.agentId);
44843
+ const existing = this.cookieSyncTimers.get(profileKey);
44844
+ if (existing) clearTimeout(existing);
44845
+ const timer = setTimeout(() => {
44846
+ if (this.cookieSyncTimers.get(profileKey) !== timer) return;
44847
+ this.cookieSyncTimers.delete(profileKey);
44848
+ void this.synchronizeCookies(session).catch(() => {
44849
+ });
44850
+ }, delayMs);
44851
+ timer.unref?.();
44852
+ this.cookieSyncTimers.set(profileKey, timer);
44853
+ }
44609
44854
  /**
44610
44855
  * Ensure a live session for this Task. An existing session is adopted
44611
44856
  * as-is (the cloud-minted id loses to the live one — the cloud reconciles
@@ -44683,8 +44928,20 @@ var BrowserManager = class {
44683
44928
  closeFailed: false
44684
44929
  };
44685
44930
  this.sessions.set(taskKey, session);
44931
+ try {
44932
+ await this.synchronizeCookies(session);
44933
+ } catch (error52) {
44934
+ session.closed = true;
44935
+ this.sessions.delete(taskKey);
44936
+ await adapter.close().catch(() => {
44937
+ });
44938
+ throw error52;
44939
+ }
44686
44940
  adapter.onStateChanged(() => {
44687
- if (!session.closed) this.events?.state(this.stateOf(session));
44941
+ if (!session.closed) {
44942
+ this.events?.state(this.stateOf(session));
44943
+ this.scheduleCookieSync(session);
44944
+ }
44688
44945
  });
44689
44946
  this.armIdleTimer(session);
44690
44947
  this.events?.state(this.stateOf(session));
@@ -44714,6 +44971,14 @@ var BrowserManager = class {
44714
44971
  return;
44715
44972
  }
44716
44973
  if (!session || session.closed && !session.closeFailed) return;
44974
+ const profileKey = this.profileKey(session.projectId, session.agentId);
44975
+ const pendingCookieTimer = this.cookieSyncTimers.get(profileKey);
44976
+ if (pendingCookieTimer) {
44977
+ clearTimeout(pendingCookieTimer);
44978
+ this.cookieSyncTimers.delete(profileKey);
44979
+ }
44980
+ await this.synchronizeCookies(session).catch(() => {
44981
+ });
44717
44982
  session.closed = true;
44718
44983
  session.closeFailed = false;
44719
44984
  if (session.frameTimer) clearTimeout(session.frameTimer);
@@ -44763,6 +45028,12 @@ var BrowserManager = class {
44763
45028
  force: true,
44764
45029
  maxRetries: 3
44765
45030
  });
45031
+ const profileKey = this.profileKey(projectId, agentId);
45032
+ const timer = this.cookieSyncTimers.get(profileKey);
45033
+ if (timer) clearTimeout(timer);
45034
+ this.cookieSyncTimers.delete(profileKey);
45035
+ this.cookieSyncTails.delete(profileKey);
45036
+ this.cookieStates.delete(profileKey);
44766
45037
  await this.syncDirectory(this.projectProfileRoot(projectId));
44767
45038
  });
44768
45039
  }
@@ -44797,6 +45068,17 @@ var BrowserManager = class {
44797
45068
  this.deniedAuthorizations.forEach((_revision, key) => {
44798
45069
  if (key.startsWith(`${projectId}:`)) this.deniedAuthorizations.delete(key);
44799
45070
  });
45071
+ this.cookieSyncTimers.forEach((timer, key) => {
45072
+ if (!key.startsWith(`${projectId}:`)) return;
45073
+ clearTimeout(timer);
45074
+ this.cookieSyncTimers.delete(key);
45075
+ });
45076
+ this.cookieSyncTails.forEach((_tail, key) => {
45077
+ if (key.startsWith(`${projectId}:`)) this.cookieSyncTails.delete(key);
45078
+ });
45079
+ this.cookieStates.forEach((_state, key) => {
45080
+ if (key.startsWith(`${projectId}:`)) this.cookieStates.delete(key);
45081
+ });
44800
45082
  await this.syncDirectory(this.profileRoot);
44801
45083
  await this.syncDirectory(this.profileStateRoot);
44802
45084
  }
@@ -44865,6 +45147,11 @@ var BrowserManager = class {
44865
45147
  const next = session.inputQueue.then(work, work);
44866
45148
  session.inputQueue = next.catch(() => {
44867
45149
  });
45150
+ void next.then(
45151
+ () => this.scheduleCookieSync(session),
45152
+ () => {
45153
+ }
45154
+ );
44868
45155
  return next;
44869
45156
  }
44870
45157
  /** Tool surface: every call ensures the session and counts as activity. */
@@ -45666,6 +45953,37 @@ function createPlaywrightBrowserAdapterFactory(dependencies = {}) {
45666
45953
  }
45667
45954
  }
45668
45955
  },
45956
+ async cookies() {
45957
+ return (await context.cookies()).map((cookie) => ({
45958
+ name: cookie.name,
45959
+ value: cookie.value,
45960
+ domain: cookie.domain,
45961
+ path: cookie.path,
45962
+ expires: cookie.expires,
45963
+ httpOnly: cookie.httpOnly,
45964
+ secure: cookie.secure,
45965
+ sameSite: cookie.sameSite,
45966
+ ...cookie.partitionKey ? { partitionKey: cookie.partitionKey } : {}
45967
+ }));
45968
+ },
45969
+ async replaceCookies(cookies) {
45970
+ await context.clearCookies();
45971
+ if (cookies.length > 0) {
45972
+ await context.addCookies(
45973
+ cookies.map((cookie) => ({
45974
+ name: cookie.name,
45975
+ value: cookie.value,
45976
+ domain: cookie.domain,
45977
+ path: cookie.path,
45978
+ expires: cookie.expires,
45979
+ httpOnly: cookie.httpOnly,
45980
+ secure: cookie.secure,
45981
+ sameSite: cookie.sameSite,
45982
+ ...cookie.partitionKey !== void 0 ? { partitionKey: cookie.partitionKey } : {}
45983
+ }))
45984
+ );
45985
+ }
45986
+ },
45669
45987
  async close() {
45670
45988
  closed = true;
45671
45989
  for (const tab of [...tabs]) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.156",
3
+ "version": "0.0.157",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",