@trusty-squire/mcp 1.1.13 → 1.1.14-rc.10

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 (163) hide show
  1. package/README.md +94 -110
  2. package/{LICENSE → assets/licenses/browser-use-MIT.txt} +1 -1
  3. package/dist/api-client.d.ts +9 -0
  4. package/dist/api-client.d.ts.map +1 -1
  5. package/dist/api-client.js +11 -0
  6. package/dist/api-client.js.map +1 -1
  7. package/dist/bin.js +7 -1
  8. package/dist/bin.js.map +1 -1
  9. package/dist/bot/broker/admission-context.d.ts +11 -0
  10. package/dist/bot/broker/admission-context.d.ts.map +1 -0
  11. package/dist/bot/broker/admission-context.js +17 -0
  12. package/dist/bot/broker/admission-context.js.map +1 -0
  13. package/dist/bot/broker/authority.d.ts +76 -0
  14. package/dist/bot/broker/authority.d.ts.map +1 -0
  15. package/dist/bot/broker/authority.js +528 -0
  16. package/dist/bot/broker/authority.js.map +1 -0
  17. package/dist/bot/broker/custody.d.ts +20 -0
  18. package/dist/bot/broker/custody.d.ts.map +1 -0
  19. package/dist/bot/broker/custody.js +10 -0
  20. package/dist/bot/broker/custody.js.map +1 -0
  21. package/dist/bot/broker/daemon.d.ts +24 -0
  22. package/dist/bot/broker/daemon.d.ts.map +1 -0
  23. package/dist/bot/broker/daemon.js +371 -0
  24. package/dist/bot/broker/daemon.js.map +1 -0
  25. package/dist/bot/broker/discovery.d.ts +9 -0
  26. package/dist/bot/broker/discovery.d.ts.map +1 -0
  27. package/dist/bot/broker/discovery.js +167 -0
  28. package/dist/bot/broker/discovery.js.map +1 -0
  29. package/dist/bot/broker/dispatch-journal.d.ts +71 -0
  30. package/dist/bot/broker/dispatch-journal.d.ts.map +1 -0
  31. package/dist/bot/broker/dispatch-journal.js +319 -0
  32. package/dist/bot/broker/dispatch-journal.js.map +1 -0
  33. package/dist/bot/broker/forwarder.d.ts +35 -0
  34. package/dist/bot/broker/forwarder.d.ts.map +1 -0
  35. package/dist/bot/broker/forwarder.js +150 -0
  36. package/dist/bot/broker/forwarder.js.map +1 -0
  37. package/dist/bot/broker/identity-lane.d.ts +3 -0
  38. package/dist/bot/broker/identity-lane.d.ts.map +1 -0
  39. package/dist/bot/broker/identity-lane.js +15 -0
  40. package/dist/bot/broker/identity-lane.js.map +1 -0
  41. package/dist/bot/broker/lineage.d.ts +3 -0
  42. package/dist/bot/broker/lineage.d.ts.map +1 -0
  43. package/dist/bot/broker/lineage.js +16 -0
  44. package/dist/bot/broker/lineage.js.map +1 -0
  45. package/dist/bot/broker/maintenance.d.ts +4 -0
  46. package/dist/bot/broker/maintenance.d.ts.map +1 -0
  47. package/dist/bot/broker/maintenance.js +49 -0
  48. package/dist/bot/broker/maintenance.js.map +1 -0
  49. package/dist/bot/broker/operator.d.ts +48 -0
  50. package/dist/bot/broker/operator.d.ts.map +1 -0
  51. package/dist/bot/broker/operator.js +523 -0
  52. package/dist/bot/broker/operator.js.map +1 -0
  53. package/dist/bot/broker/qualification.d.ts +5 -0
  54. package/dist/bot/broker/qualification.d.ts.map +1 -0
  55. package/dist/bot/broker/qualification.js +67 -0
  56. package/dist/bot/broker/qualification.js.map +1 -0
  57. package/dist/bot/broker/runtime.d.ts +36 -0
  58. package/dist/bot/broker/runtime.d.ts.map +1 -0
  59. package/dist/bot/broker/runtime.js +202 -0
  60. package/dist/bot/broker/runtime.js.map +1 -0
  61. package/dist/bot/broker/scheduler.d.ts +20 -0
  62. package/dist/bot/broker/scheduler.d.ts.map +1 -0
  63. package/dist/bot/broker/scheduler.js +94 -0
  64. package/dist/bot/broker/scheduler.js.map +1 -0
  65. package/dist/bot/broker/transport.d.ts +27 -0
  66. package/dist/bot/broker/transport.d.ts.map +1 -0
  67. package/dist/bot/broker/transport.js +265 -0
  68. package/dist/bot/broker/transport.js.map +1 -0
  69. package/dist/bot/browser-process-owner.d.ts +75 -0
  70. package/dist/bot/browser-process-owner.d.ts.map +1 -0
  71. package/dist/bot/browser-process-owner.js +939 -0
  72. package/dist/bot/browser-process-owner.js.map +1 -0
  73. package/dist/bot/browser-process-runtime.d.ts +168 -0
  74. package/dist/bot/browser-process-runtime.d.ts.map +1 -0
  75. package/dist/bot/browser-process-runtime.js +940 -0
  76. package/dist/bot/browser-process-runtime.js.map +1 -0
  77. package/dist/bot/browser-use-capture.d.ts +15 -0
  78. package/dist/bot/browser-use-capture.d.ts.map +1 -0
  79. package/dist/bot/browser-use-capture.js +975 -0
  80. package/dist/bot/browser-use-capture.js.map +1 -0
  81. package/dist/bot/browser-use-paint-order.d.ts +12 -0
  82. package/dist/bot/browser-use-paint-order.d.ts.map +1 -0
  83. package/dist/bot/browser-use-paint-order.js +73 -0
  84. package/dist/bot/browser-use-paint-order.js.map +1 -0
  85. package/dist/bot/browser-use-serializer.d.ts +67 -0
  86. package/dist/bot/browser-use-serializer.d.ts.map +1 -0
  87. package/dist/bot/browser-use-serializer.js +1027 -0
  88. package/dist/bot/browser-use-serializer.js.map +1 -0
  89. package/dist/bot/browser.d.ts +158 -264
  90. package/dist/bot/browser.d.ts.map +1 -1
  91. package/dist/bot/browser.js +1681 -2830
  92. package/dist/bot/browser.js.map +1 -1
  93. package/dist/bot/compact-observation-v2.d.ts +54 -45
  94. package/dist/bot/compact-observation-v2.d.ts.map +1 -1
  95. package/dist/bot/compact-observation-v2.js +454 -165
  96. package/dist/bot/compact-observation-v2.js.map +1 -1
  97. package/dist/bot/credential-shape.d.ts.map +1 -1
  98. package/dist/bot/credential-shape.js +7 -0
  99. package/dist/bot/credential-shape.js.map +1 -1
  100. package/dist/bot/identity-runtime.d.ts +56 -0
  101. package/dist/bot/identity-runtime.d.ts.map +1 -0
  102. package/dist/bot/identity-runtime.js +141 -0
  103. package/dist/bot/identity-runtime.js.map +1 -0
  104. package/dist/bot/mutation-dispatch-evidence.d.ts +13 -0
  105. package/dist/bot/mutation-dispatch-evidence.d.ts.map +1 -0
  106. package/dist/bot/mutation-dispatch-evidence.js +19 -0
  107. package/dist/bot/mutation-dispatch-evidence.js.map +1 -0
  108. package/dist/bot/owned-pages.d.ts +16 -0
  109. package/dist/bot/owned-pages.d.ts.map +1 -0
  110. package/dist/bot/owned-pages.js +58 -0
  111. package/dist/bot/owned-pages.js.map +1 -0
  112. package/dist/bot/page-driver.d.ts +37 -0
  113. package/dist/bot/page-driver.d.ts.map +1 -0
  114. package/dist/bot/page-driver.js +303 -0
  115. package/dist/bot/page-driver.js.map +1 -0
  116. package/dist/bot/pay-operator.d.ts +1 -0
  117. package/dist/bot/pay-operator.d.ts.map +1 -1
  118. package/dist/bot/pay-operator.js +10 -0
  119. package/dist/bot/pay-operator.js.map +1 -1
  120. package/dist/bot/profile.d.ts +9 -0
  121. package/dist/bot/profile.d.ts.map +1 -1
  122. package/dist/bot/profile.js +16 -11
  123. package/dist/bot/profile.js.map +1 -1
  124. package/dist/bot/provision-session.d.ts +32 -7
  125. package/dist/bot/provision-session.d.ts.map +1 -1
  126. package/dist/bot/provision-session.js +1008 -471
  127. package/dist/bot/provision-session.js.map +1 -1
  128. package/dist/bot/session/lifecycle.d.ts +5 -2
  129. package/dist/bot/session/lifecycle.d.ts.map +1 -1
  130. package/dist/bot/session/lifecycle.js +303 -34
  131. package/dist/bot/session/lifecycle.js.map +1 -1
  132. package/dist/bot/session/multisession-flag.d.ts +2 -0
  133. package/dist/bot/session/multisession-flag.d.ts.map +1 -0
  134. package/dist/bot/session/multisession-flag.js +23 -0
  135. package/dist/bot/session/multisession-flag.js.map +1 -0
  136. package/dist/install/cli.d.ts.map +1 -1
  137. package/dist/install/cli.js +2 -1
  138. package/dist/install/cli.js.map +1 -1
  139. package/dist/server-instance-registry.d.ts +18 -6
  140. package/dist/server-instance-registry.d.ts.map +1 -1
  141. package/dist/server-instance-registry.js +49 -28
  142. package/dist/server-instance-registry.js.map +1 -1
  143. package/dist/server.d.ts +6 -3
  144. package/dist/server.d.ts.map +1 -1
  145. package/dist/server.js +122 -29
  146. package/dist/server.js.map +1 -1
  147. package/dist/tools/audit-log.d.ts.map +1 -1
  148. package/dist/tools/audit-log.js +1 -5
  149. package/dist/tools/audit-log.js.map +1 -1
  150. package/dist/tools/audit-rollup.d.ts +2 -5
  151. package/dist/tools/audit-rollup.d.ts.map +1 -1
  152. package/dist/tools/audit-rollup.js +0 -0
  153. package/dist/tools/audit-rollup.js.map +1 -1
  154. package/dist/tools/credential-mutations.d.ts +16 -16
  155. package/dist/tools/index.js +2 -2
  156. package/dist/tools/index.js.map +1 -1
  157. package/dist/tools/operate-pay.d.ts +18 -18
  158. package/dist/tools/provision-drive.d.ts +263 -555
  159. package/dist/tools/provision-drive.d.ts.map +1 -1
  160. package/dist/tools/provision-drive.js +404 -1139
  161. package/dist/tools/provision-drive.js.map +1 -1
  162. package/dist/tools/use-credential.d.ts +6 -6
  163. package/package.json +1 -1
@@ -4,7 +4,7 @@ import type { OAuthProviderId } from "../oauth-providers.js";
4
4
  import type { Session } from "./model.js";
5
5
  import type { CompactV2StartMetadata, Observation } from "../provision-session.js";
6
6
  export interface SessionStartPorts {
7
- observeSession: (session: Session, detail: "compact" | "full", startMetadata?: CompactV2StartMetadata) => Promise<Observation>;
7
+ observeSession: (session: Session, format: "compact" | "full", startMetadata?: CompactV2StartMetadata) => Promise<Observation>;
8
8
  compactV2StartMetadata: (registryHint: string | undefined, loginHint: string, userEmail: string | null) => CompactV2StartMetadata;
9
9
  }
10
10
  export declare function audit(sessionId: string, event: string, detail?: Record<string, unknown>): void;
@@ -15,6 +15,8 @@ export declare function withPaymentSessionCall<T>(sessionId: string | undefined,
15
15
  export declare function observeSnapshotDir(sessionId: string): string;
16
16
  export interface StartOptions {
17
17
  serviceUrl: string;
18
+ /** Observation shape returned by this start. Compact is the public default. */
19
+ format?: "compact" | "full";
18
20
  profileDir?: string;
19
21
  proxyUrl?: string;
20
22
  extraAllowedHosts?: readonly string[];
@@ -24,7 +26,7 @@ export interface StartOptions {
24
26
  }
25
27
  export interface HarnessStartOptions extends Omit<StartOptions, "profileDir" | "proxyUrl"> {
26
28
  browser: BrowserController;
27
- observationFormat?: "v1" | "compact-v2";
29
+ observationFormat?: "v1" | "browser-use-dom";
28
30
  }
29
31
  export interface NeedsUserLogin {
30
32
  wall: "google_session";
@@ -51,6 +53,7 @@ export interface PreparedFinishResult<T> {
51
53
  }
52
54
  export declare function finishProvisionSessionWithPreparation<T>(sessionId: string, prepare: () => Promise<T>, successfulOutcome?: () => boolean): Promise<PreparedFinishResult<T>>;
53
55
  export declare function finishProvisionSession(sessionId: string): Promise<FinishResult>;
56
+ export declare function forceFinishProvisionSession(sessionId: string): Promise<boolean>;
54
57
  export declare function closeAllProvisionSessions(): Promise<void>;
55
58
  export declare function activeSessionCount(): number;
56
59
  //# sourceMappingURL=lifecycle.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/bot/session/lifecycle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/bot/session/lifecycle.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,5 @@
1
+ import { reserveBrokerAdmission } from "../broker/admission-context.js";
2
+ import { brokerBrowserCustody } from "../broker/custody.js";
1
3
  // Phase 2 of the operator session-management restructure: the session
2
4
  // lifecycle, moved out of provision-session.ts as ONE transaction.
3
5
  //
@@ -30,6 +32,8 @@ import { compactV2AuditValue } from "../compact-observation-v2.js";
30
32
  import { acquireProfileOperationGuard, CHROME_PROFILE_DIR, ProfileBusyError, waitForProfileFree, } from "../profile.js";
31
33
  import { loginSessionGuidance } from "../skill-hint.js";
32
34
  import { OperatorBrowserWatchdog, } from "../operator-browser-watchdog.js";
35
+ import { IdentityRuntime, IncompatibleIdentityRuntimeSettingsError, } from "../identity-runtime.js";
36
+ import { experimentalMultiSessionEnabled } from "./multisession-flag.js";
33
37
  import { createSession } from "./model.js";
34
38
  import { hostStrings, merchantSiblingSeedHosts, registrableHost, requestScopeHostStrings, } from "./hosts.js";
35
39
  const sessions = new Map();
@@ -37,6 +41,9 @@ const sessions = new Map();
37
41
  // but it never creates a browser session. Its terminal acknowledgement is a
38
42
  // no-op rather than an "unknown session" error.
39
43
  const refusedStartSessionIds = new Set();
44
+ // At most one live group per process today (one shared operator profile).
45
+ let sharedIdentityGroup = null;
46
+ const operatorIdentityRuntime = new IdentityRuntime();
40
47
  const leasedBrowsers = new Map();
41
48
  const startingBrowsers = new Set();
42
49
  let shutdownGeneration = 0;
@@ -109,16 +116,120 @@ function assertProvisionStartAdmitted(generation) {
109
116
  throw new Error("operate_start cancelled: operator server is shutting down");
110
117
  }
111
118
  }
119
+ // Experimental (TRUSTY_SQUIRE_EXPERIMENTAL_MULTISESSION) — a second (or Nth)
120
+ // operate_start joining an identity that is already live or mid-launch IN
121
+ // THIS PROCESS. Returns null when there is nothing of ours to join (the busy
122
+ // signal is from an unrelated process, or a genuinely different profile), so
123
+ // the caller re-throws the original ProfileBusyError instead of silently
124
+ // swallowing a real cross-process busy condition.
125
+ //
126
+ // Deliberately does NOT re-acquire the profile-operation guard: that lease is
127
+ // the group's, held once by whichever session became primary (see
128
+ // acquireWarmBrowser) and released only when the group empties (see
129
+ // releaseWarmBrowserPage). Joining here only ever reuses operatorIdentityRuntime's
130
+ // already-live handle — its own single-flight is what makes this race-free
131
+ // against a primary launch still in flight.
132
+ async function tryAcquireSatelliteBrowser(opts, profileDir, generation, sessionId) {
133
+ if (!operatorIdentityRuntime.isLive() && !operatorIdentityRuntime.isLaunching())
134
+ return null;
135
+ const identitySettings = {
136
+ profileDir,
137
+ ...(opts.proxyUrl !== undefined ? { proxyUrl: opts.proxyUrl } : {}),
138
+ };
139
+ let acquired;
140
+ try {
141
+ acquired = await operatorIdentityRuntime.acquire(identitySettings, async () => {
142
+ throw new Error("operate_start (TRUSTY_SQUIRE_EXPERIMENTAL_MULTISESSION): expected to join an already-live " +
143
+ "identity but the runtime attempted a fresh launch instead — this should be unreachable");
144
+ });
145
+ }
146
+ catch (err) {
147
+ if (err instanceof IncompatibleIdentityRuntimeSettingsError)
148
+ return null;
149
+ throw err;
150
+ }
151
+ const joinable = (group) => group !== null && group.profileDir === profileDir && group.refCount > 0;
152
+ if (!acquired.reused || !joinable(sharedIdentityGroup)) {
153
+ acquired.releaseTabs();
154
+ return null;
155
+ }
156
+ const group = sharedIdentityGroup;
157
+ try {
158
+ assertProvisionStartAdmitted(generation);
159
+ }
160
+ catch (err) {
161
+ acquired.releaseTabs();
162
+ throw err;
163
+ }
164
+ let satellite;
165
+ try {
166
+ satellite = await BrowserController.attachSatellite(group.primary, {
167
+ profileDir,
168
+ ...(opts.proxyUrl !== undefined ? { proxyUrl: opts.proxyUrl } : {}),
169
+ });
170
+ }
171
+ catch (err) {
172
+ acquired.releaseTabs();
173
+ throw err;
174
+ }
175
+ // The last live session's teardown may have emptied the group while the
176
+ // attach was in flight; a satellite must never be committed onto it.
177
+ if (sharedIdentityGroup !== group || !joinable(group)) {
178
+ await satellite.closeOwnPagesOnly().catch(() => undefined);
179
+ acquired.releaseTabs();
180
+ return null;
181
+ }
182
+ group.refCount += 1;
183
+ audit(sessionId, "multisession_satellite_attach", { profile_dir: profileDir });
184
+ leasedBrowsers.set(satellite, {
185
+ controller: satellite,
186
+ profileDir,
187
+ lease: group.lease,
188
+ shutdownGeneration: generation,
189
+ identityLease: acquired.releaseTabs,
190
+ identityGroup: group,
191
+ ...(opts.proxyUrl === undefined ? {} : { proxyUrl: opts.proxyUrl }),
192
+ });
193
+ return { controller: satellite, profileDir, shutdownGeneration: generation };
194
+ }
112
195
  async function acquireWarmBrowser(opts, sessionId) {
113
196
  const generation = provisionStartGeneration();
197
+ const custody = brokerBrowserCustody();
198
+ if (custody !== undefined) {
199
+ const acquired = await custody.acquire(opts);
200
+ try {
201
+ assertProvisionStartAdmitted(generation);
202
+ }
203
+ catch (error) {
204
+ await custody.release(acquired.browser);
205
+ throw error;
206
+ }
207
+ return {
208
+ controller: acquired.browser,
209
+ profileDir: acquired.profileDir,
210
+ shutdownGeneration: generation,
211
+ };
212
+ }
114
213
  if ((process.env.BOT_CDP_ENDPOINT ?? "").trim().length > 0) {
115
214
  throw new Error("operate_start does not support remote CDP with the local Chrome profile");
116
215
  }
117
216
  const profileDir = opts.profileDir ?? CHROME_PROFILE_DIR;
217
+ const multiSession = experimentalMultiSessionEnabled();
118
218
  // This lease is held for the complete operate session. Its on-disk owner
119
219
  // records host + pid + process birth time, so a crashed holder is reclaimed
120
220
  // while a live or indeterminate holder is never stolen.
121
- const lease = acquireProfileOperationGuard(profileDir);
221
+ let lease;
222
+ try {
223
+ lease = acquireProfileOperationGuard(profileDir);
224
+ }
225
+ catch (err) {
226
+ if (multiSession && err instanceof ProfileBusyError) {
227
+ const satellite = await tryAcquireSatelliteBrowser(opts, profileDir, generation, sessionId);
228
+ if (satellite !== null)
229
+ return satellite;
230
+ }
231
+ throw err;
232
+ }
122
233
  if (!(await waitForProfileFree(profileDir, { deadlineMs: 0 }))) {
123
234
  lease.release();
124
235
  throw new ProfileBusyError("another Trusty Squire session is already using the browser — close it first");
@@ -134,42 +245,70 @@ async function acquireWarmBrowser(opts, sessionId) {
134
245
  };
135
246
  startingBrowsers.add(pending);
136
247
  let controller = null;
248
+ let identityLease = null;
137
249
  try {
138
250
  if (pending.cancelRequested) {
139
251
  throw new Error("operate_start cancelled: operator server is shutting down");
140
252
  }
141
- controller = new BrowserController({
253
+ const identitySettings = {
142
254
  profileDir,
143
255
  ...(opts.proxyUrl !== undefined ? { proxyUrl: opts.proxyUrl } : {}),
256
+ };
257
+ // Single-flighted through operatorIdentityRuntime rather than constructed
258
+ // inline: today it always launches fresh (production still forgets this
259
+ // identity at every session finish, below), but the acquisition itself
260
+ // now goes through the one place that will later decide whether to reuse
261
+ // a still-live Chrome instead of relaunching it.
262
+ const acquired = await operatorIdentityRuntime.acquire(identitySettings, async (settings) => {
263
+ const launched = new BrowserController({
264
+ profileDir: settings.profileDir,
265
+ ...(settings.proxyUrl !== undefined ? { proxyUrl: settings.proxyUrl } : {}),
266
+ });
267
+ pending.controller = launched;
268
+ pending.launch = startBrowserBounded(launched, sessionId, async () => {
269
+ await cancelStartingBrowser(pending);
270
+ });
271
+ await pending.launch;
272
+ return launched;
144
273
  });
145
- pending.controller = controller;
146
- pending.launch = startBrowserBounded(controller, sessionId, async () => {
147
- await cancelStartingBrowser(pending);
148
- });
149
- await pending.launch;
274
+ controller = acquired.handle;
275
+ identityLease = acquired.releaseTabs;
150
276
  if (pending.cancelRequested) {
151
277
  throw new Error("operate_start cancelled: operator server is shutting down");
152
278
  }
153
279
  assertProvisionStartAdmitted(generation);
154
280
  }
155
281
  catch (err) {
156
- if (controller !== null)
157
- await controller.close().catch(() => undefined);
282
+ const constructed = controller ?? pending.controller;
283
+ if (constructed !== null) {
284
+ identityLease?.();
285
+ await constructed.close().catch(() => undefined);
286
+ operatorIdentityRuntime.forgetAfterShutdown();
287
+ }
158
288
  lease.release();
159
289
  throw err;
160
290
  }
161
291
  finally {
162
292
  startingBrowsers.delete(pending);
163
293
  }
164
- if (controller === null) {
294
+ if (controller === null || identityLease === null) {
165
295
  throw new Error("operate_start cancelled before browser initialization");
166
296
  }
297
+ // This session became primary: form the shared group so a subsequent
298
+ // busy-guard failure (above) knows there is something of ours to join, and
299
+ // so releaseWarmBrowserPage/forceReleaseWarmBrowserPage know who actually
300
+ // owns the profile-operation lease and the real teardown.
301
+ const identityGroup = multiSession
302
+ ? (sharedIdentityGroup = { primary: controller, profileDir, lease, refCount: 1 })
303
+ : undefined;
167
304
  leasedBrowsers.set(controller, {
168
305
  controller,
169
306
  profileDir,
170
307
  lease,
171
308
  shutdownGeneration: generation,
309
+ identityLease,
172
310
  ...(opts.proxyUrl === undefined ? {} : { proxyUrl: opts.proxyUrl }),
311
+ ...(identityGroup !== undefined ? { identityGroup } : {}),
173
312
  });
174
313
  return {
175
314
  controller,
@@ -178,25 +317,118 @@ async function acquireWarmBrowser(opts, sessionId) {
178
317
  };
179
318
  }
180
319
  async function releaseWarmBrowserPage(browser, _persistState, owner) {
320
+ const custody = brokerBrowserCustody();
321
+ if (custody !== undefined) {
322
+ await custody.release(browser);
323
+ return;
324
+ }
181
325
  const leased = leasedBrowsers.get(browser);
326
+ const group = leased?.identityGroup;
327
+ // A forced teardown of a GROUPED session belongs wholly to
328
+ // forceReleaseWarmBrowserPage, which the forcing path runs next on this same
329
+ // session: it performs the group's one decrement and, when last, the
330
+ // primary close. Touching the refcount, the lease, or the leasedBrowsers
331
+ // entry here first would discard the group before anything closed the
332
+ // shared Chrome. The ungrouped (flag-off) path is unchanged.
333
+ if (group !== undefined && owner?.forced) {
334
+ throw new Error("operator browser terminal teardown was forced");
335
+ }
336
+ if (group !== undefined)
337
+ group.refCount -= 1;
338
+ const emptiedGroup = group !== undefined && group.refCount <= 0;
182
339
  try {
183
340
  if (owner?.forced)
184
341
  throw new Error("operator browser terminal teardown was forced");
185
- await browser.close();
342
+ if (group === undefined) {
343
+ // Production still tears the identity's Chrome down at every session
344
+ // finish (flag off, or no multisession group formed).
345
+ await browser.close();
346
+ }
347
+ else if (!emptiedGroup) {
348
+ await browser.closeOwnPagesOnly();
349
+ }
350
+ else {
351
+ if (browser !== group.primary)
352
+ await browser.closeOwnPagesOnly().catch(() => undefined);
353
+ await group.primary.close();
354
+ }
186
355
  }
187
356
  finally {
188
357
  leasedBrowsers.delete(browser);
189
- leased?.lease.release();
358
+ if (leased !== undefined) {
359
+ if (group === undefined) {
360
+ leased.lease.release();
361
+ leased.identityLease();
362
+ operatorIdentityRuntime.forgetAfterShutdown();
363
+ }
364
+ else {
365
+ leased.identityLease();
366
+ if (emptiedGroup) {
367
+ group.lease.release();
368
+ operatorIdentityRuntime.forgetAfterShutdown();
369
+ if (sharedIdentityGroup === group)
370
+ sharedIdentityGroup = null;
371
+ }
372
+ }
373
+ }
190
374
  }
191
375
  }
192
376
  async function forceReleaseWarmBrowserPage(browser, owner) {
377
+ const custody = brokerBrowserCustody();
378
+ if (custody !== undefined) {
379
+ await custody.release(browser);
380
+ return;
381
+ }
193
382
  const leased = leasedBrowsers.get(browser);
194
- await closeBrowserUntilProven(browser, false, "operator browser force-close timed out", () => owner?.requireProvenBrowserClose === true);
383
+ const group = leased?.identityGroup;
384
+ // The group's one decrement for a forced session happens here, never in a
385
+ // preempted releaseWarmBrowserPage (see there), so whichever session's
386
+ // teardown empties the group — primary or satellite, graceful or forced —
387
+ // is the one that closes the shared Chrome.
388
+ if (group !== undefined)
389
+ group.refCount -= 1;
390
+ const emptiedGroup = group !== undefined && group.refCount <= 0;
391
+ try {
392
+ if (group === undefined) {
393
+ await closeBrowserUntilProven(browser, false, "operator browser force-close timed out", () => owner?.requireProvenBrowserClose === true);
394
+ }
395
+ else if (!emptiedGroup) {
396
+ await closeOwnPagesBounded(browser);
397
+ }
398
+ else {
399
+ if (browser !== group.primary)
400
+ await closeOwnPagesBounded(browser);
401
+ await closeBrowserUntilProven(group.primary, false, "operator browser force-close timed out", () => owner?.requireProvenBrowserClose === true);
402
+ }
403
+ }
404
+ finally {
405
+ if (leased !== undefined) {
406
+ leased.identityLease();
407
+ if (group === undefined) {
408
+ operatorIdentityRuntime.forgetAfterShutdown();
409
+ }
410
+ else if (emptiedGroup) {
411
+ operatorIdentityRuntime.forgetAfterShutdown();
412
+ if (sharedIdentityGroup === group)
413
+ sharedIdentityGroup = null;
414
+ }
415
+ }
416
+ }
195
417
  if (leased === undefined)
196
418
  return;
197
- leased.lease.release();
419
+ if (group === undefined)
420
+ leased.lease.release();
421
+ else if (emptiedGroup)
422
+ group.lease.release();
198
423
  leasedBrowsers.delete(browser);
199
424
  }
425
+ // The forced-teardown counterpart of closeOwnPagesOnly: page.close() can hang
426
+ // indefinitely on a wedged Chrome, so the grouped forced path keeps the same
427
+ // bounded contract closeBrowserBounded gives the ungrouped one.
428
+ async function closeOwnPagesBounded(browser) {
429
+ const timeoutMs = positiveTimeout("TRUSTY_SQUIRE_OPERATOR_FORCE_CLOSE_TIMEOUT_MS", DEFAULT_OPERATOR_FORCE_CLOSE_TIMEOUT_MS);
430
+ await withTerminalTimeout(browser.closeOwnPagesOnly(), timeoutMs, "operator browser own-page force-close timed out").catch(() => undefined);
431
+ }
200
432
  async function closeBrowserBounded(browser, cancelStart, timeoutMessage, maximumTimeoutMs) {
201
433
  const forceClose = browser.forceCloseOwnedProcessTree;
202
434
  const ordinaryClose = browser
@@ -410,7 +642,10 @@ function startSessionWatchdog(session) {
410
642
  const watchdog = new OperatorBrowserWatchdog({
411
643
  startedAt: session.startedAt,
412
644
  lastActivityAt: () => session.lastActivityAt,
413
- hasActiveCall: () => session.initializing || session.callCount > 0 || session.paymentCallCount > 0,
645
+ hasActiveCall: () => brokerBrowserCustody() !== undefined ||
646
+ session.initializing ||
647
+ session.callCount > 0 ||
648
+ session.paymentCallCount > 0,
414
649
  processMarker: () => session.browser.operatorBrowserMarker?.() ?? null,
415
650
  onTerminate: async (reason) => await terminateExpiredProvisionSession(session, reason),
416
651
  });
@@ -578,15 +813,28 @@ async function ensureProvisionPrimaryProviderSession(browser) {
578
813
  });
579
814
  }
580
815
  export async function startProvisionSession(opts, ports) {
581
- const id = randomUUID();
816
+ const id = reserveBrokerAdmission([opts.serviceUrl, ...(opts.extraAllowedHosts ?? [])]) ?? randomUUID();
582
817
  const compactV2Mode = configuredCompactV2Mode();
818
+ const requestedFormat = opts.format ?? (compactV2Mode === "on" ? "full" : "compact");
583
819
  let browser;
584
820
  let liveProviders;
585
821
  let workerEmail = null;
586
822
  const acquired = await acquireWarmBrowser(opts, id);
587
823
  browser = acquired.controller;
588
824
  try {
589
- liveProviders = await ensureProvisionPrimaryProviderSession(browser);
825
+ const probe = async () => {
826
+ const providers = await ensureProvisionPrimaryProviderSession(browser);
827
+ workerEmail =
828
+ typeof browser.detectGoogleAccountEmail === "function"
829
+ ? await browser.detectGoogleAccountEmail().catch(() => null)
830
+ : null;
831
+ return providers;
832
+ };
833
+ const custody = brokerBrowserCustody();
834
+ liveProviders =
835
+ custody === undefined
836
+ ? await ensureProvisionPrimaryProviderSession(browser)
837
+ : await custody.identity(probe);
590
838
  assertProvisionStartAdmitted(acquired.shutdownGeneration);
591
839
  const gate = googleSessionGate(liveProviders);
592
840
  if (!gate.ok) {
@@ -594,20 +842,29 @@ export async function startProvisionSession(opts, ports) {
594
842
  await releaseWarmBrowserPage(browser, false);
595
843
  refusedStartSessionIds.add(id);
596
844
  return compactV2Mode === "on"
597
- ? {
598
- session_id: id,
599
- format: "compact-v2",
600
- stage: "auth",
601
- url: "",
602
- text: "",
603
- needs_user: gate.needs_user,
604
- }
845
+ ? requestedFormat === "full"
846
+ ? {
847
+ session_id: id,
848
+ format: "browser-use-dom",
849
+ stage: "auth",
850
+ url: "",
851
+ needs_user: gate.needs_user,
852
+ }
853
+ : {
854
+ session_id: id,
855
+ format: "browser-use-control-query",
856
+ stage: "auth",
857
+ url: "",
858
+ safe_table: [],
859
+ needs_user: gate.needs_user,
860
+ }
605
861
  : { session_id: id, url: "", text: "", elements: [], needs_user: gate.needs_user };
606
862
  }
607
- workerEmail =
608
- typeof browser.detectGoogleAccountEmail === "function"
609
- ? await browser.detectGoogleAccountEmail().catch(() => null)
610
- : null;
863
+ if (custody === undefined)
864
+ workerEmail =
865
+ typeof browser.detectGoogleAccountEmail === "function"
866
+ ? await browser.detectGoogleAccountEmail().catch(() => null)
867
+ : null;
611
868
  }
612
869
  catch (error) {
613
870
  await releaseWarmBrowserPage(browser, false);
@@ -669,10 +926,11 @@ export async function startProvisionSession(opts, ports) {
669
926
  // doesn't have to guess. Composed with the skill route hint (if any).
670
927
  const loginHint = loginSessionGuidance(liveProviders);
671
928
  const hintParts = [loginHint, ...(opts.hint !== undefined ? [opts.hint] : [])];
672
- const observation = await ports.observeSession(session, "compact", ports.compactV2StartMetadata(opts.hint, loginHint, session.userEmail));
929
+ const observation = await ports.observeSession(session, requestedFormat, ports.compactV2StartMetadata(opts.hint, loginHint, session.userEmail));
673
930
  session.initializing = false;
674
931
  session.lastActivityAt = Date.now();
675
- if (observation.format === "compact-v2")
932
+ if (observation.format === "browser-use-dom" ||
933
+ observation.format === "browser-use-control-query")
676
934
  return observation;
677
935
  return {
678
936
  ...observation,
@@ -690,6 +948,7 @@ export async function startProvisionSession(opts, ports) {
690
948
  /** Start a normal guarded session on a caller-owned harness page. */
691
949
  export async function startHarnessProvisionSession(opts, ports) {
692
950
  const id = randomUUID();
951
+ const requestedFormat = opts.format ?? (opts.observationFormat === "browser-use-dom" ? "full" : "compact");
693
952
  const targetHost = registrableHost(opts.serviceUrl);
694
953
  const allowedHosts = [
695
954
  ...(targetHost === null ? [] : [targetHost]),
@@ -704,7 +963,7 @@ export async function startHarnessProvisionSession(opts, ports) {
704
963
  id,
705
964
  browser: opts.browser,
706
965
  allowedHosts,
707
- compactV2Mode: opts.observationFormat === "compact-v2" ? "on" : "off",
966
+ compactV2Mode: opts.observationFormat === "browser-use-dom" ? "on" : "off",
708
967
  startUrl: opts.serviceUrl,
709
968
  hintServed: opts.hint !== undefined,
710
969
  consentInboxRead: opts.consentInboxRead !== false,
@@ -719,10 +978,11 @@ export async function startHarnessProvisionSession(opts, ports) {
719
978
  allowed_hosts: hostStrings(session),
720
979
  });
721
980
  await opts.browser.goto(opts.serviceUrl);
722
- const observation = await ports.observeSession(session, "compact", ports.compactV2StartMetadata(opts.hint, "", null));
981
+ const observation = await ports.observeSession(session, requestedFormat, ports.compactV2StartMetadata(opts.hint, "", null));
723
982
  session.initializing = false;
724
983
  session.lastActivityAt = Date.now();
725
- if (observation.format === "compact-v2")
984
+ if (observation.format === "browser-use-dom" ||
985
+ observation.format === "browser-use-control-query")
726
986
  return observation;
727
987
  return { ...observation, hint: opts.hint ?? "" };
728
988
  }
@@ -922,6 +1182,15 @@ export async function finishProvisionSession(sessionId) {
922
1182
  }
923
1183
  return (await finishProvisionSessionWithPreparation(sessionId, async () => undefined)).finish;
924
1184
  }
1185
+ export async function forceFinishProvisionSession(sessionId) {
1186
+ const session = sessionForCall(sessionId);
1187
+ if (session === undefined)
1188
+ return true;
1189
+ const terminalError = await forceTerminateProvisionSession(session, "broker_detached_expiry", {
1190
+ reason: "stuck_dispatched_operation",
1191
+ });
1192
+ return terminalError === undefined && sessionForCall(sessionId) === undefined;
1193
+ }
925
1194
  // Test/teardown helper — close every live session (used by the dev shim on exit).
926
1195
  export async function closeAllProvisionSessions() {
927
1196
  shutdownGeneration += 1;