@opengeni/runtime 3.2.2 → 3.4.0

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 (69) hide show
  1. package/dist/agent-LJT5NPWT.js +9 -0
  2. package/dist/assets/codemode-client.json +1 -1
  3. package/dist/browser-current-tab.d.ts +46 -0
  4. package/dist/browser-model-text.d.ts +126 -0
  5. package/dist/{chunk-2AUDDDO2.js → chunk-3DFH3ZHU.js} +784 -121
  6. package/dist/chunk-3DFH3ZHU.js.map +1 -0
  7. package/dist/{chunk-HJSIPTFA.js → chunk-4XDJ4TJA.js} +2 -2
  8. package/dist/{chunk-XQ23VCZ4.js → chunk-6FQ6KEII.js} +3 -3
  9. package/dist/{chunk-7LJ7KDPI.js → chunk-ERD4ICVB.js} +4 -3
  10. package/dist/{chunk-462CH77G.js → chunk-ETTCGPBT.js} +400 -9
  11. package/dist/chunk-ETTCGPBT.js.map +1 -0
  12. package/dist/{chunk-7OUG7WBV.js → chunk-GWRBALGQ.js} +181 -13
  13. package/dist/chunk-GWRBALGQ.js.map +1 -0
  14. package/dist/{chunk-YG26XE7B.js → chunk-JYDG2A7H.js} +2 -2
  15. package/dist/{chunk-RSHQSLEJ.js → chunk-KIL4FGX5.js} +3 -3
  16. package/dist/{chunk-NWS4HPB7.js → chunk-MIAL5I4O.js} +2 -2
  17. package/dist/{chunk-Z5U6WE22.js → chunk-PRZPGRIK.js} +2 -2
  18. package/dist/{chunk-KCPW4K7L.js → chunk-PZQUUBEB.js} +2 -2
  19. package/dist/{chunk-5WJOPANS.js → chunk-Y5THZH5N.js} +7 -7
  20. package/dist/codex-tool-search.d.ts +9 -0
  21. package/dist/gmail-rest-mcp.js +8 -8
  22. package/dist/index.d.ts +3 -0
  23. package/dist/index.js +14 -12
  24. package/dist/interaction-tool-json-schema.d.ts +27 -0
  25. package/dist/{lazy-manifest-AJ6XPJ4F.js → lazy-manifest-BLZ3UZLX.js} +4 -4
  26. package/dist/lazy-tool-transport.d.ts +10 -0
  27. package/dist/{localSources-SSIEH5F5.js → localSources-I6SIQ6CX.js} +6 -6
  28. package/dist/model-call.js +3 -3
  29. package/dist/sandbox/browser-control-client.d.ts +87 -0
  30. package/dist/sandbox/browser-control-http.d.ts +33 -0
  31. package/dist/sandbox/index.d.ts +1 -1
  32. package/dist/sandbox/index.js +7 -7
  33. package/dist/sandbox/routing/backend-resolver.d.ts +1 -0
  34. package/dist/sandbox/selfhosted/session.d.ts +22 -0
  35. package/dist/slack-rest-mcp.js +8 -8
  36. package/dist/workspace-tool-gateway.js +12 -12
  37. package/package.json +14 -14
  38. package/src/browser-current-tab.ts +139 -0
  39. package/src/browser-model-text.ts +378 -0
  40. package/src/bundled_site_skills/opengeni-sites/SKILL.md +46 -12
  41. package/src/codex-tool-search.ts +53 -0
  42. package/src/index.ts +39 -1
  43. package/src/interaction-tool-json-schema.ts +281 -0
  44. package/src/interaction-tools.ts +425 -235
  45. package/src/lazy-tool-transport.ts +229 -10
  46. package/src/model-input.ts +12 -1
  47. package/src/sandbox/browser-control-client.ts +425 -0
  48. package/src/sandbox/browser-control-http.ts +32 -0
  49. package/src/sandbox/index.ts +4 -0
  50. package/src/sandbox/routing/backend-resolver.ts +2 -0
  51. package/src/sandbox/selfhosted/session.ts +154 -0
  52. package/dist/agent-CTPLA3HP.js +0 -9
  53. package/dist/browser-action-json-schema.d.ts +0 -4
  54. package/dist/chunk-2AUDDDO2.js.map +0 -1
  55. package/dist/chunk-462CH77G.js.map +0 -1
  56. package/dist/chunk-7OUG7WBV.js.map +0 -1
  57. package/src/browser-action-json-schema.ts +0 -10
  58. /package/dist/{agent-CTPLA3HP.js.map → agent-LJT5NPWT.js.map} +0 -0
  59. /package/dist/{chunk-HJSIPTFA.js.map → chunk-4XDJ4TJA.js.map} +0 -0
  60. /package/dist/{chunk-XQ23VCZ4.js.map → chunk-6FQ6KEII.js.map} +0 -0
  61. /package/dist/{chunk-7LJ7KDPI.js.map → chunk-ERD4ICVB.js.map} +0 -0
  62. /package/dist/{chunk-YG26XE7B.js.map → chunk-JYDG2A7H.js.map} +0 -0
  63. /package/dist/{chunk-RSHQSLEJ.js.map → chunk-KIL4FGX5.js.map} +0 -0
  64. /package/dist/{chunk-NWS4HPB7.js.map → chunk-MIAL5I4O.js.map} +0 -0
  65. /package/dist/{chunk-Z5U6WE22.js.map → chunk-PRZPGRIK.js.map} +0 -0
  66. /package/dist/{chunk-KCPW4K7L.js.map → chunk-PZQUUBEB.js.map} +0 -0
  67. /package/dist/{chunk-5WJOPANS.js.map → chunk-Y5THZH5N.js.map} +0 -0
  68. /package/dist/{lazy-manifest-AJ6XPJ4F.js.map → lazy-manifest-BLZ3UZLX.js.map} +0 -0
  69. /package/dist/{localSources-SSIEH5F5.js.map → localSources-I6SIQ6CX.js.map} +0 -0
@@ -45,6 +45,11 @@ import {
45
45
  import { Manifest } from "@openai/agents/sandbox";
46
46
  import { formatExecResponse } from "@openai/agents-core/sandbox/internal";
47
47
  import type { ExposedPortEndpoint } from "../stream-port";
48
+ import {
49
+ BROWSER_CONTROL_HTTP_REPLY_GRACE_MS,
50
+ type BrowserControlHttpCall,
51
+ type BrowserControlHttpOutcome,
52
+ } from "../browser-control-http";
48
53
  import {
49
54
  agentErrorToControlError,
50
55
  drainingExhaustedError,
@@ -279,12 +284,17 @@ export interface SelfhostedBackgroundCommandAdoption {
279
284
  connectionInstanceId: string;
280
285
  opId: string;
281
286
  command: string;
287
+ /** The exec already failed because the machine stopped answering. Record it
288
+ * with a stop request instead of as a running background command. */
289
+ abandoned?: boolean;
282
290
  }
283
291
 
284
292
  /** Exact command-admission snapshot. A worker resolves this immediately before
285
293
  * every exec/Git admission; retries and already-started operations retain it. */
286
294
  export interface SelfhostedOperationAdmission {
287
295
  transactionalFsWriteSupported?: boolean;
296
+ /** The live runner serves in-process browser/computer controller requests. */
297
+ browserControlHttpSupported?: boolean;
288
298
  /** Workspace segment of the physical agent/relay route. Personal machines may
289
299
  * originate in a different same-organization workspace than the session. */
290
300
  workspaceId?: string;
@@ -309,6 +319,9 @@ export interface SelfhostedOperationAdmission {
309
319
  export interface SelfhostedSessionDeps {
310
320
  /** Exact live daemon capability; absent preserves legacy small-file writes. */
311
321
  transactionalFsWriteSupported?: boolean;
322
+ /** Exact live daemon capability; absent keeps controller requests on the
323
+ * command transport. */
324
+ browserControlHttpSupported?: boolean;
312
325
  /** Authorization/session workspace. */
313
326
  workspaceId: string;
314
327
  /** Physical control-plane workspace. Defaults to workspaceId for legacy and
@@ -521,6 +534,7 @@ export class SelfhostedSession {
521
534
  private readonly resourcePolicySupported: boolean;
522
535
  private readonly operationCpuQuotaSupported: boolean;
523
536
  private readonly transactionalFsWriteSupported: boolean;
537
+ private readonly browserControlHttpSupported: boolean;
524
538
  private readonly defaultOpStream: SelfhostedOpStreamDeps | undefined;
525
539
  private readonly connectionInstanceId: string;
526
540
  private readonly resolveOperationAdmission:
@@ -594,6 +608,7 @@ export class SelfhostedSession {
594
608
  this.resourcePolicySupported = deps.operationResourcePolicySupported === true;
595
609
  this.operationCpuQuotaSupported = deps.operationCpuQuotaSupported === true;
596
610
  this.transactionalFsWriteSupported = deps.transactionalFsWriteSupported === true;
611
+ this.browserControlHttpSupported = deps.browserControlHttpSupported === true;
597
612
  this.defaultOpStream = deps.opStream;
598
613
  this.connectionInstanceId = deps.connectionInstanceId;
599
614
  this.resolveOperationAdmission = deps.resolveOperationAdmission;
@@ -612,6 +627,7 @@ export class SelfhostedSession {
612
627
  resourcePolicy: this.resourcePolicy,
613
628
  opStream: deps.opStream,
614
629
  transactionalFsWriteSupported: this.transactionalFsWriteSupported,
630
+ browserControlHttpSupported: this.browserControlHttpSupported,
615
631
  })
616
632
  : undefined;
617
633
  // A valid Manifest whose root is the machine's actual effective root. There
@@ -680,6 +696,7 @@ export class SelfhostedSession {
680
696
 
681
697
  private async admitOperation(commandPolicy: boolean): Promise<{
682
698
  transactionalFsWriteSupported: boolean;
699
+ browserControlHttpSupported: boolean;
683
700
  controlWorkspaceId: string;
684
701
  connectionInstanceId: string;
685
702
  subject: string;
@@ -701,6 +718,7 @@ export class SelfhostedSession {
701
718
  resourcePolicy: commandPolicy ? this.resourcePolicy : undefined,
702
719
  opStream: this.defaultOpStream,
703
720
  transactionalFsWriteSupported: this.transactionalFsWriteSupported,
721
+ browserControlHttpSupported: this.browserControlHttpSupported,
704
722
  };
705
723
  }
706
724
 
@@ -736,6 +754,7 @@ export class SelfhostedSession {
736
754
  resourcePolicy: commandPolicy ? resourcePolicy : undefined,
737
755
  opStream: resolved.opStream,
738
756
  transactionalFsWriteSupported: resolved.transactionalFsWriteSupported === true,
757
+ browserControlHttpSupported: resolved.browserControlHttpSupported === true,
739
758
  };
740
759
  }
741
760
 
@@ -1343,6 +1362,34 @@ export class SelfhostedSession {
1343
1362
  reason: null,
1344
1363
  retryable: false,
1345
1364
  });
1365
+ if (
1366
+ !terminalProof &&
1367
+ !adoptedCommandId &&
1368
+ !controlError.neverSent &&
1369
+ machineStoppedAnswering(controlError) &&
1370
+ this.adoptBackgroundCommand
1371
+ ) {
1372
+ // The machine went away mid-operation. The command may still run there,
1373
+ // but only the machine can stop or report it, so this turn must not wait
1374
+ // for it. Hand it to the session's command ledger with a stop request;
1375
+ // the reconciler stops or settles it once the machine returns or its
1376
+ // runner is retired. If recording fails, turn cleanup keeps ownership.
1377
+ try {
1378
+ notifyDurableOpOwnershipTransferStarted(opId);
1379
+ const abandoned = await this.adoptBackgroundCommand({
1380
+ controlWorkspaceId: admission.controlWorkspaceId,
1381
+ enrollmentId: this.agentId,
1382
+ connectionInstanceId: admission.connectionInstanceId,
1383
+ opId,
1384
+ command,
1385
+ abandoned: true,
1386
+ });
1387
+ adoptedCommandId = abandoned.commandId;
1388
+ notifyDurableOpOwnershipTransferred(opId);
1389
+ } catch {
1390
+ notifyDurableOpOwnershipTransferFailed(opId);
1391
+ }
1392
+ }
1346
1393
  this.emitOp({
1347
1394
  op: "exec",
1348
1395
  outcome: "failed",
@@ -1955,6 +2002,99 @@ export class SelfhostedSession {
1955
2002
  return result.browserControlEnsure;
1956
2003
  }
1957
2004
 
2005
+ /** Send one request to the agent-owned controller of an exact authority
2006
+ * scope, served inside the runner over loopback without starting a process.
2007
+ * `unsupported` means this connection's runner does not serve it and nothing
2008
+ * was sent. `controller_absent` means no controller for that scope and
2009
+ * generation accepted the request, so it was not delivered and the caller may
2010
+ * ensure the controller and send again. A body too large for one reply is
2011
+ * drained from the runner's spool; the request is never repeated. */
2012
+ async browserControlHttp(request: BrowserControlHttpCall): Promise<BrowserControlHttpOutcome> {
2013
+ const admission = await this.admitOperation(false);
2014
+ if (!admission.browserControlHttpSupported) return { kind: "unsupported" };
2015
+ // The runner bounds the request by timeoutMs; allow the reply to arrive.
2016
+ const rpcTimeoutMs = request.timeoutMs + BROWSER_CONTROL_HTTP_REPLY_GRACE_MS;
2017
+ let result: NonNullable<ControlResponse["result"]>;
2018
+ try {
2019
+ result = await this.call(
2020
+ {
2021
+ $case: "browserControlHttp",
2022
+ browserControlHttp: {
2023
+ scopeId: request.scopeId,
2024
+ scopeGeneration: request.scopeGeneration,
2025
+ method: request.method,
2026
+ path: request.path,
2027
+ bearerToken: request.bearerToken,
2028
+ body: request.body ?? new Uint8Array(),
2029
+ hasBody: request.body !== undefined,
2030
+ timeoutMs: request.timeoutMs,
2031
+ maxResponseBytes: String(request.maxResponseBytes),
2032
+ },
2033
+ },
2034
+ rpcTimeoutMs,
2035
+ admission,
2036
+ );
2037
+ } catch (error) {
2038
+ if (
2039
+ error instanceof SelfhostedControlError &&
2040
+ error.code === ErrorCode.ERROR_CODE_NOT_FOUND
2041
+ ) {
2042
+ return { kind: "controller_absent" };
2043
+ }
2044
+ throw error;
2045
+ }
2046
+ if (result.$case !== "browserControlHttp") {
2047
+ throw new Error(`selfhosted browserControlHttp: unexpected result ${result.$case}`);
2048
+ }
2049
+ const response = result.browserControlHttp;
2050
+ const totalBytes = Number(response.totalBytes);
2051
+ if (
2052
+ !Number.isSafeInteger(totalBytes) ||
2053
+ totalBytes < response.body.byteLength ||
2054
+ totalBytes > request.maxResponseBytes
2055
+ ) {
2056
+ throw new Error("selfhosted browserControlHttp: response length is invalid");
2057
+ }
2058
+ let body = response.body;
2059
+ if (response.spoolId) {
2060
+ const complete = new Uint8Array(totalBytes);
2061
+ complete.set(response.body, 0);
2062
+ let offset = response.body.byteLength;
2063
+ for (;;) {
2064
+ const read = await this.call(
2065
+ {
2066
+ $case: "browserControlHttpRead",
2067
+ browserControlHttpRead: { spoolId: response.spoolId, offset: String(offset) },
2068
+ },
2069
+ this.timeoutMs,
2070
+ admission,
2071
+ );
2072
+ if (read.$case !== "browserControlHttpRead") {
2073
+ throw new Error(`selfhosted browserControlHttpRead: unexpected result ${read.$case}`);
2074
+ }
2075
+ const part = read.browserControlHttpRead;
2076
+ if (offset + part.data.byteLength > totalBytes) {
2077
+ throw new Error("selfhosted browserControlHttpRead: response exceeds its length");
2078
+ }
2079
+ complete.set(part.data, offset);
2080
+ offset += part.data.byteLength;
2081
+ if (part.done) break;
2082
+ if (part.data.byteLength === 0) {
2083
+ throw new Error("selfhosted browserControlHttpRead: spool made no progress");
2084
+ }
2085
+ }
2086
+ if (offset !== totalBytes) {
2087
+ throw new Error("selfhosted browserControlHttpRead: response is incomplete");
2088
+ }
2089
+ body = complete;
2090
+ } else if (response.body.byteLength !== totalBytes) {
2091
+ throw new Error("selfhosted browserControlHttp: response is incomplete");
2092
+ }
2093
+ const headers = new Map<string, string>();
2094
+ for (const header of response.headers) headers.set(header.name.toLowerCase(), header.value);
2095
+ return { kind: "response", status: response.status, headers, body };
2096
+ }
2097
+
1958
2098
  /** Open one browser-native frame producer and return its canonical relay
1959
2099
  * endpoint. This does not route through `resolveExposedPort`: that legacy
1960
2100
  * method allocates PTY/desktop resources based on fixed ports, while this op
@@ -2145,6 +2285,7 @@ export class SelfhostedSandboxClient {
2145
2285
  private readonly operationResourcePolicySupported: boolean | undefined;
2146
2286
  private readonly operationCpuQuotaSupported: boolean | undefined;
2147
2287
  private readonly transactionalFsWriteSupported: boolean | undefined;
2288
+ private readonly browserControlHttpSupported: boolean | undefined;
2148
2289
  private readonly resolveOperationAdmission:
2149
2290
  | (() => Promise<SelfhostedOperationAdmission | null>)
2150
2291
  | undefined;
@@ -2186,6 +2327,7 @@ export class SelfhostedSandboxClient {
2186
2327
  operationResourcePolicySupported?: boolean;
2187
2328
  operationCpuQuotaSupported?: boolean;
2188
2329
  transactionalFsWriteSupported?: boolean;
2330
+ browserControlHttpSupported?: boolean;
2189
2331
  resolveOperationAdmission?: () => Promise<SelfhostedOperationAdmission | null>;
2190
2332
  adoptBackgroundCommand?: SelfhostedSessionDeps["adoptBackgroundCommand"];
2191
2333
  settleBackgroundCommand?: SelfhostedSessionDeps["settleBackgroundCommand"];
@@ -2218,6 +2360,7 @@ export class SelfhostedSandboxClient {
2218
2360
  this.operationResourcePolicySupported = opts.operationResourcePolicySupported;
2219
2361
  this.operationCpuQuotaSupported = opts.operationCpuQuotaSupported;
2220
2362
  this.transactionalFsWriteSupported = opts.transactionalFsWriteSupported;
2363
+ this.browserControlHttpSupported = opts.browserControlHttpSupported;
2221
2364
  this.resolveOperationAdmission = opts.resolveOperationAdmission;
2222
2365
  this.adoptBackgroundCommand = opts.adoptBackgroundCommand;
2223
2366
  this.settleBackgroundCommand = opts.settleBackgroundCommand;
@@ -2262,6 +2405,7 @@ export class SelfhostedSandboxClient {
2262
2405
  ? { operationCpuQuotaSupported: this.operationCpuQuotaSupported }
2263
2406
  : {}),
2264
2407
  transactionalFsWriteSupported: this.transactionalFsWriteSupported === true,
2408
+ browserControlHttpSupported: this.browserControlHttpSupported === true,
2265
2409
  ...(this.resolveOperationAdmission !== undefined
2266
2410
  ? { resolveOperationAdmission: this.resolveOperationAdmission }
2267
2411
  : {}),
@@ -2382,6 +2526,8 @@ export interface SelfhostedSessionBuild {
2382
2526
  /** Exact live CPU enforcement capability paired with the initial snapshot. */
2383
2527
  operationCpuQuotaSupported?: boolean;
2384
2528
  transactionalFsWriteSupported?: boolean;
2529
+ /** Exact live runner capability for in-process controller requests. */
2530
+ browserControlHttpSupported?: boolean;
2385
2531
  /** Live last-boundary operation admission resolver; see SelfhostedSessionDeps. */
2386
2532
  resolveOperationAdmission?: () => Promise<SelfhostedOperationAdmission | null>;
2387
2533
  adoptBackgroundCommand?: SelfhostedSessionDeps["adoptBackgroundCommand"];
@@ -2438,6 +2584,7 @@ export async function buildSelfhostedBackendSession(
2438
2584
  ? { operationCpuQuotaSupported: deps.operationCpuQuotaSupported }
2439
2585
  : {}),
2440
2586
  transactionalFsWriteSupported: deps.transactionalFsWriteSupported === true,
2587
+ browserControlHttpSupported: deps.browserControlHttpSupported === true,
2441
2588
  ...(deps.resolveOperationAdmission !== undefined
2442
2589
  ? { resolveOperationAdmission: deps.resolveOperationAdmission }
2443
2590
  : {}),
@@ -2587,6 +2734,13 @@ function mediaTypeFromPath(path: string): string | undefined {
2587
2734
 
2588
2735
  /** A random uint64-safe numeric nonce (the wire `PingRequest.nonce` is a uint64,
2589
2736
  * represented as a numeric string by ts-proto). */
2737
+ /** The machine itself stopped answering (offline, reconnecting past the hold
2738
+ * window, or draining), as opposed to an answer that the operation failed. */
2739
+ function machineStoppedAnswering(error: SelfhostedControlError): boolean {
2740
+ const faultClass = selfhostedFaultClass(error);
2741
+ return faultClass === "offline" || faultClass === "reconnecting" || faultClass === "draining";
2742
+ }
2743
+
2590
2744
  function randomNonce(): string {
2591
2745
  // 2^53-safe random integer as a decimal string.
2592
2746
  return String(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER));
@@ -1,9 +0,0 @@
1
- import {
2
- SandboxAgent
3
- } from "./chunk-HJSIPTFA.js";
4
- import "./chunk-7LJ7KDPI.js";
5
- import "./chunk-PLDDJCW6.js";
6
- export {
7
- SandboxAgent
8
- };
9
- //# sourceMappingURL=agent-CTPLA3HP.js.map
@@ -1,4 +0,0 @@
1
- import type { AttemptToolJsonSchema } from "@opengeni/contracts";
2
- import { z } from "zod";
3
- /** Keep repeated browser action and locator variants once in the model schema. */
4
- export declare function browserActionInputJsonSchema(schema: z.ZodType): AttemptToolJsonSchema;