@opengeni/runtime 4.0.1 → 4.0.3-canary.36079201993001

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 (48) hide show
  1. package/dist/{agent-RJQLKFIW.js → agent-ME6HT4DH.js} +2 -2
  2. package/dist/assets/codemode-client.json +1 -1
  3. package/dist/browser-action-json-schema.d.ts +4 -0
  4. package/dist/{chunk-J5AR5XAJ.js → chunk-GBVN7WSK.js} +377 -210
  5. package/dist/chunk-GBVN7WSK.js.map +1 -0
  6. package/dist/{chunk-ZG2YH25H.js → chunk-JAYHA6BF.js} +2 -2
  7. package/dist/{chunk-UNICCRW5.js → chunk-LZIXCZUV.js} +6 -3
  8. package/dist/{chunk-UNICCRW5.js.map → chunk-LZIXCZUV.js.map} +1 -1
  9. package/dist/{chunk-J6J3VYFW.js → chunk-OGG5NQLA.js} +597 -65
  10. package/dist/chunk-OGG5NQLA.js.map +1 -0
  11. package/dist/{chunk-SPT3PLMX.js → chunk-PRHMSM6C.js} +2 -2
  12. package/dist/context-compaction.d.ts +4 -2
  13. package/dist/index.d.ts +8 -6
  14. package/dist/index.js +9 -7
  15. package/dist/interaction-tools.d.ts +1 -1
  16. package/dist/{lazy-manifest-OEYEHNVY.js → lazy-manifest-GCGUFIWP.js} +3 -3
  17. package/dist/{localSources-TWHTEKGO.js → localSources-FDH65AFI.js} +4 -4
  18. package/dist/operational-instructions.d.ts +1 -1
  19. package/dist/sandbox/browser-control-client.d.ts +28 -1
  20. package/dist/sandbox/index.d.ts +2 -2
  21. package/dist/sandbox/index.js +6 -6
  22. package/dist/sandbox/providers/modal-command-router-wire.d.ts +8 -0
  23. package/dist/sandbox/providers/modal.d.ts +5 -6
  24. package/dist/workspace-tool-gateway.js +5 -5
  25. package/package.json +11 -11
  26. package/src/browser-action-json-schema.ts +10 -0
  27. package/src/bundled_artifact_skills/opengeni-documents/SKILL.md +4 -1
  28. package/src/bundled_artifact_skills/opengeni-documents/references/api.md +20 -0
  29. package/src/bundled_default_skills/opengeni-client/SKILL.md +4 -1
  30. package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +31 -0
  31. package/src/bundled_default_skills/opengeni-client/references/runtime-profile-and-verification.md +32 -0
  32. package/src/context-compaction.ts +19 -3
  33. package/src/index.ts +100 -36
  34. package/src/interaction-tools.ts +656 -48
  35. package/src/operational-instructions.ts +1 -1
  36. package/src/sandbox/browser-control-client.ts +241 -26
  37. package/src/sandbox/index.ts +3 -1
  38. package/src/sandbox/providers/modal-command-control.ts +7 -1
  39. package/src/sandbox/providers/modal-command-router-wire.ts +47 -6
  40. package/src/sandbox/providers/modal.ts +16 -24
  41. package/src/sandbox/routing/routing-session.ts +4 -2
  42. package/dist/chunk-J5AR5XAJ.js.map +0 -1
  43. package/dist/chunk-J6J3VYFW.js.map +0 -1
  44. /package/dist/{agent-RJQLKFIW.js.map → agent-ME6HT4DH.js.map} +0 -0
  45. /package/dist/{chunk-ZG2YH25H.js.map → chunk-JAYHA6BF.js.map} +0 -0
  46. /package/dist/{chunk-SPT3PLMX.js.map → chunk-PRHMSM6C.js.map} +0 -0
  47. /package/dist/{lazy-manifest-OEYEHNVY.js.map → lazy-manifest-GCGUFIWP.js.map} +0 -0
  48. /package/dist/{localSources-TWHTEKGO.js.map → localSources-FDH65AFI.js.map} +0 -0
@@ -26,14 +26,14 @@ import {
26
26
  truncateOutput,
27
27
  validateCredentialPair,
28
28
  validateRemoteSandboxPathForManifest
29
- } from "./chunk-SPT3PLMX.js";
29
+ } from "./chunk-PRHMSM6C.js";
30
30
  import {
31
31
  NoopSnapshotSpec,
32
32
  isNoopSnapshotSpec,
33
33
  normalizeSandboxClientCreateArgs,
34
34
  resolveSandboxArchiveLimits,
35
35
  validateSandboxArchiveLimits
36
- } from "./chunk-ZG2YH25H.js";
36
+ } from "./chunk-JAYHA6BF.js";
37
37
  import {
38
38
  Environment,
39
39
  FileMode,
@@ -96,7 +96,7 @@ import {
96
96
  shellQuote,
97
97
  stableJsonStringify,
98
98
  withSandboxSpan
99
- } from "./chunk-UNICCRW5.js";
99
+ } from "./chunk-LZIXCZUV.js";
100
100
 
101
101
  // src/sandbox/index.ts
102
102
  import { collectSandboxEnvironment, parseExposedPorts } from "@opengeni/config";
@@ -6567,7 +6567,7 @@ var CloudflareSandboxSession = class {
6567
6567
  async materializeEntry(args) {
6568
6568
  assertSandboxEntryMetadataSupported("CloudflareSandboxClient", args.path, args.entry, MOUNT_MANIFEST_METADATA_SUPPORT);
6569
6569
  if (entryContainsLocalSource(args.entry)) {
6570
- const { applyLocalSourceManifestEntryToState: applyLocalSourceManifestEntryToState2 } = await import("./localSources-TWHTEKGO.js");
6570
+ const { applyLocalSourceManifestEntryToState: applyLocalSourceManifestEntryToState2 } = await import("./localSources-FDH65AFI.js");
6571
6571
  await applyLocalSourceManifestEntryToState2(this.state, args.path, args.entry, "cloudflare", this.writer(), this.remotePathResolver, this.manifestMaterializationOptions(args.runAs));
6572
6572
  return;
6573
6573
  }
@@ -6578,7 +6578,7 @@ var CloudflareSandboxSession = class {
6578
6578
  assertSandboxManifestMetadataSupported("CloudflareSandboxClient", manifest, MOUNT_MANIFEST_METADATA_SUPPORT);
6579
6579
  assertCloudflareManifestMountsSupported(manifest);
6580
6580
  if (manifestContainsLocalSource(manifest)) {
6581
- const { applyLocalSourceManifestToState: applyLocalSourceManifestToState2 } = await import("./localSources-TWHTEKGO.js");
6581
+ const { applyLocalSourceManifestToState: applyLocalSourceManifestToState2 } = await import("./localSources-FDH65AFI.js");
6582
6582
  await applyLocalSourceManifestToState2(this.state, manifest, "cloudflare", this.writer(), this.remotePathResolver, this.manifestMaterializationOptions(runAs));
6583
6583
  return;
6584
6584
  }
@@ -15848,8 +15848,9 @@ function notifyDurableOpOwnershipTransferred(opId) {
15848
15848
  storage.getStore()?.onDurableOpOwnershipTransferred?.(opId);
15849
15849
  }
15850
15850
 
15851
- // src/sandbox/routing/routing-session.ts
15852
- import { isDeepStrictEqual } from "util";
15851
+ // src/sandbox/providers/modal-command-router-wire.ts
15852
+ import { Client, Metadata, credentials, status } from "@grpc/grpc-js";
15853
+ import protobuf from "protobufjs";
15853
15854
 
15854
15855
  // src/sandbox/provider-command-session.ts
15855
15856
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
@@ -15895,6 +15896,219 @@ function admittedProviderCommandHandle() {
15895
15896
  return admission.getStore();
15896
15897
  }
15897
15898
 
15899
+ // src/sandbox/providers/modal-command-router-wire.ts
15900
+ var modalRouterWire = protobuf.parse(`syntax = "proto3";
15901
+ message Identity { string task_id = 1; string exec_id = 2; }
15902
+ message Pty {
15903
+ bool enabled = 1; uint32 winsz_rows = 2; uint32 winsz_cols = 3;
15904
+ string env_term = 4; string env_colorterm = 5; string env_term_program = 6;
15905
+ int32 pty_type = 7; bool no_terminate_on_idle_stdin = 8;
15906
+ }
15907
+ message Start {
15908
+ string task_id = 1; string exec_id = 2; repeated string command_args = 3;
15909
+ int32 stdout_config = 4; int32 stderr_config = 5;
15910
+ optional uint32 timeout_secs = 6; optional string workdir = 7;
15911
+ repeated string secret_ids = 8; optional Pty pty_info = 9;
15912
+ bool runtime_debug = 10; string container_id = 11; map<string,string> env = 12;
15913
+ }
15914
+ message Read {
15915
+ string task_id = 1; string exec_id = 2; uint64 offset = 3; int32 file_descriptor = 4;
15916
+ }
15917
+ message Data { bytes data = 1; }
15918
+ message Poll { optional int32 code = 1; optional int32 signal = 2; }
15919
+ message Write {
15920
+ string task_id = 1; string exec_id = 2; uint64 offset = 3; bytes data = 4; bool eof = 5;
15921
+ }
15922
+ message Empty {}
15923
+ `).root;
15924
+ var prefix = "/modal.task_command_router.TaskCommandRouter/";
15925
+ var maxPageBytes = 64 * 1024;
15926
+ var maxWireBytes = 4 * 1024 * 1024;
15927
+ var ModalCommandStartRejectedError = class extends ProviderCommandStartRejectedError {
15928
+ constructor(code, cause) {
15929
+ super(cause);
15930
+ this.code = code;
15931
+ this.name = "ModalCommandStartRejectedError";
15932
+ }
15933
+ };
15934
+ var ModalCommandStartPreDispatchUnavailableError = class _ModalCommandStartPreDispatchUnavailableError extends Error {
15935
+ constructor(cause) {
15936
+ super("Modal command router was not ready before Start dispatch", { cause });
15937
+ this.name = "ModalCommandStartPreDispatchUnavailableError";
15938
+ }
15939
+ static async ensureReady(client, signal) {
15940
+ signal?.throwIfAborted();
15941
+ await new Promise((resolve7, reject) => {
15942
+ let settled = false;
15943
+ const finish = (error) => {
15944
+ if (settled) return;
15945
+ settled = true;
15946
+ signal?.removeEventListener("abort", abort);
15947
+ if (signal?.aborted) reject(signal.reason);
15948
+ else if (error) reject(new _ModalCommandStartPreDispatchUnavailableError(error));
15949
+ else resolve7();
15950
+ };
15951
+ const abort = () => finish();
15952
+ signal?.addEventListener("abort", abort, { once: true });
15953
+ client.waitForReady(Date.now() + 5e3, finish);
15954
+ if (signal?.aborted) abort();
15955
+ });
15956
+ }
15957
+ };
15958
+ function encode(type, value) {
15959
+ const codec = modalRouterWire.lookupType(type);
15960
+ return Buffer.from(codec.encode(codec.fromObject(value)).finish());
15961
+ }
15962
+ var ModalCommandRouterWire = class {
15963
+ client;
15964
+ metadata;
15965
+ closed = false;
15966
+ constructor(access, trustedRoots) {
15967
+ const url = new URL(access.url);
15968
+ if (url.protocol !== "https:" || url.username || url.password || !access.jwt)
15969
+ throw new Error("Modal command router requires authenticated TLS");
15970
+ this.client = new Client(
15971
+ `${url.hostname}:${url.port || "443"}`,
15972
+ credentials.createSsl(trustedRoots),
15973
+ {
15974
+ "grpc.max_receive_message_length": maxWireBytes,
15975
+ "grpc.max_send_message_length": maxWireBytes,
15976
+ "grpc.enable_retries": 0
15977
+ }
15978
+ );
15979
+ this.metadata = new Metadata();
15980
+ this.metadata.set("authorization", `Bearer ${access.jwt}`);
15981
+ }
15982
+ close() {
15983
+ this.closed = true;
15984
+ this.client.close();
15985
+ }
15986
+ async unary(method, requestType, responseType, request, signal) {
15987
+ signal?.throwIfAborted();
15988
+ if (this.closed) throw new Error("Modal command router is closed");
15989
+ return await new Promise((resolve7, reject) => {
15990
+ const call = this.client.makeUnaryRequest(
15991
+ prefix + method,
15992
+ (value) => encode(requestType, value),
15993
+ (bytes) => modalRouterWire.lookupType(responseType).decode(bytes),
15994
+ request,
15995
+ this.metadata,
15996
+ { deadline: Date.now() + 3e4 },
15997
+ (error, result) => {
15998
+ signal?.removeEventListener("abort", abort);
15999
+ if (signal?.aborted) reject(signal.reason);
16000
+ else if (error) reject(error);
16001
+ else if (result) resolve7(result);
16002
+ else reject(new Error("Modal command router returned no response"));
16003
+ }
16004
+ );
16005
+ const abort = () => call.cancel();
16006
+ signal?.addEventListener("abort", abort, { once: true });
16007
+ if (signal?.aborted) abort();
16008
+ });
16009
+ }
16010
+ async start(request, signal) {
16011
+ if (this.closed) throw new Error("Modal command router is closed");
16012
+ try {
16013
+ await ModalCommandStartPreDispatchUnavailableError.ensureReady(this.client, signal);
16014
+ } catch (error) {
16015
+ if (this.closed) throw new Error("Modal command router is closed", { cause: error });
16016
+ throw error;
16017
+ }
16018
+ try {
16019
+ await this.unary(
16020
+ "TaskExecStart",
16021
+ "Start",
16022
+ "Empty",
16023
+ {
16024
+ ...request,
16025
+ stdoutConfig: 1,
16026
+ stderrConfig: 1
16027
+ },
16028
+ signal
16029
+ );
16030
+ } catch (error) {
16031
+ const code = error?.code;
16032
+ if (typeof code === "number" && [
16033
+ status.INVALID_ARGUMENT,
16034
+ status.NOT_FOUND,
16035
+ status.PERMISSION_DENIED,
16036
+ status.UNAUTHENTICATED,
16037
+ status.UNIMPLEMENTED
16038
+ ].includes(code))
16039
+ throw new ModalCommandStartRejectedError(code, error);
16040
+ throw error;
16041
+ }
16042
+ }
16043
+ async write(identity, offset, data, signal) {
16044
+ if (!Number.isSafeInteger(offset) || offset < 0)
16045
+ throw new Error("Invalid Modal stdin byte offset");
16046
+ await this.unary(
16047
+ "TaskExecStdinWrite",
16048
+ "Write",
16049
+ "Empty",
16050
+ { ...identity, offset, data, eof: false },
16051
+ signal
16052
+ );
16053
+ }
16054
+ async poll(identity, signal) {
16055
+ const value = await this.unary("TaskExecPoll", "Identity", "Poll", identity, signal);
16056
+ const decoded = modalRouterWire.lookupType("Poll").toObject(value);
16057
+ if (decoded.code !== void 0) return decoded.code;
16058
+ if (decoded.signal !== void 0) return 128 + decoded.signal;
16059
+ return null;
16060
+ }
16061
+ async read(identity, stream, offset, waitMs, signal) {
16062
+ signal?.throwIfAborted();
16063
+ if (this.closed) throw new Error("Modal command router is closed");
16064
+ if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isFinite(waitMs) || waitMs < 0 || waitMs > 5e4)
16065
+ throw new Error("Invalid Modal output read bounds");
16066
+ const chunks = [];
16067
+ let length = 0;
16068
+ let limited = false;
16069
+ return await new Promise((resolve7, reject) => {
16070
+ const call = this.client.makeServerStreamRequest(
16071
+ prefix + "TaskExecStdioRead",
16072
+ (value) => encode("Read", value),
16073
+ (bytes) => modalRouterWire.lookupType("Data").decode(bytes),
16074
+ { ...identity, offset, fileDescriptor: stream === "stdout" ? 0 : 1 },
16075
+ this.metadata,
16076
+ { deadline: Date.now() + Math.max(1, waitMs) }
16077
+ );
16078
+ const abort = () => call.cancel();
16079
+ const finish = (eof, error) => {
16080
+ signal?.removeEventListener("abort", abort);
16081
+ if (signal?.aborted) reject(signal.reason);
16082
+ else if (error) reject(error);
16083
+ else resolve7({ bytes: Buffer.concat(chunks, length), eof });
16084
+ };
16085
+ call.on("data", (value) => {
16086
+ if (limited) return;
16087
+ const part = Buffer.from(value.data).subarray(0, maxPageBytes - length);
16088
+ if (part.length) {
16089
+ chunks.push(part);
16090
+ length += part.length;
16091
+ }
16092
+ if (length === maxPageBytes) {
16093
+ limited = true;
16094
+ call.cancel();
16095
+ }
16096
+ });
16097
+ call.once("error", (error) => {
16098
+ if (limited && error.code === status.CANCELLED || error.code === status.DEADLINE_EXCEEDED)
16099
+ finish(false);
16100
+ else finish(false, error);
16101
+ });
16102
+ call.once("end", () => finish(!limited));
16103
+ signal?.addEventListener("abort", abort, { once: true });
16104
+ if (signal?.aborted) abort();
16105
+ });
16106
+ }
16107
+ };
16108
+
16109
+ // src/sandbox/routing/routing-session.ts
16110
+ import { isDeepStrictEqual } from "util";
16111
+
15898
16112
  // src/sandbox/materialization-verification-error.ts
15899
16113
  var EXPLANATIONS = {
15900
16114
  path_not_visible: "the provider could not see the destination path",
@@ -17341,7 +17555,7 @@ var RoutingSandboxSession = class {
17341
17555
  }
17342
17556
  } catch (error) {
17343
17557
  if (reservedProcess) {
17344
- if (error instanceof ProviderCommandStartRejectedError && reservedProcess.providerCommand?.kind === "modal-router-v1") {
17558
+ if ((error instanceof ProviderCommandStartRejectedError || error instanceof ModalCommandStartPreDispatchUnavailableError) && reservedProcess.providerCommand?.kind === "modal-router-v1") {
17345
17559
  const persistence = this.deps.providerCommandPersistence?.(reservedProcess);
17346
17560
  if (persistence?.rejectSupervisedLaunch) {
17347
17561
  try {
@@ -17349,7 +17563,7 @@ var RoutingSandboxSession = class {
17349
17563
  } catch (cause) {
17350
17564
  throw new RoutingMutationOutcomeUnknownError(
17351
17565
  op,
17352
- "Never-started provider rejection could not settle its exact reservation",
17566
+ "Never-started provider call could not settle its exact reservation",
17353
17567
  { cause, retainedProcess: reservedProcess }
17354
17568
  );
17355
17569
  }
@@ -22716,183 +22930,6 @@ var ModalCommandControl = class _ModalCommandControl {
22716
22930
  }
22717
22931
  };
22718
22932
 
22719
- // src/sandbox/providers/modal-command-router-wire.ts
22720
- import { Client, Metadata, credentials, status } from "@grpc/grpc-js";
22721
- import protobuf from "protobufjs";
22722
- var modalRouterWire = protobuf.parse(`syntax = "proto3";
22723
- message Identity { string task_id = 1; string exec_id = 2; }
22724
- message Pty {
22725
- bool enabled = 1; uint32 winsz_rows = 2; uint32 winsz_cols = 3;
22726
- string env_term = 4; string env_colorterm = 5; string env_term_program = 6;
22727
- int32 pty_type = 7; bool no_terminate_on_idle_stdin = 8;
22728
- }
22729
- message Start {
22730
- string task_id = 1; string exec_id = 2; repeated string command_args = 3;
22731
- int32 stdout_config = 4; int32 stderr_config = 5;
22732
- optional uint32 timeout_secs = 6; optional string workdir = 7;
22733
- repeated string secret_ids = 8; optional Pty pty_info = 9;
22734
- bool runtime_debug = 10; string container_id = 11; map<string,string> env = 12;
22735
- }
22736
- message Read {
22737
- string task_id = 1; string exec_id = 2; uint64 offset = 3; int32 file_descriptor = 4;
22738
- }
22739
- message Data { bytes data = 1; }
22740
- message Poll { optional int32 code = 1; optional int32 signal = 2; }
22741
- message Write {
22742
- string task_id = 1; string exec_id = 2; uint64 offset = 3; bytes data = 4; bool eof = 5;
22743
- }
22744
- message Empty {}
22745
- `).root;
22746
- var prefix = "/modal.task_command_router.TaskCommandRouter/";
22747
- var maxPageBytes = 64 * 1024;
22748
- var maxWireBytes = 4 * 1024 * 1024;
22749
- var ModalCommandStartRejectedError = class extends ProviderCommandStartRejectedError {
22750
- constructor(code, cause) {
22751
- super(cause);
22752
- this.code = code;
22753
- this.name = "ModalCommandStartRejectedError";
22754
- }
22755
- };
22756
- function encode(type, value) {
22757
- const codec = modalRouterWire.lookupType(type);
22758
- return Buffer.from(codec.encode(codec.fromObject(value)).finish());
22759
- }
22760
- var ModalCommandRouterWire = class {
22761
- client;
22762
- metadata;
22763
- closed = false;
22764
- constructor(access, trustedRoots) {
22765
- const url = new URL(access.url);
22766
- if (url.protocol !== "https:" || url.username || url.password || !access.jwt)
22767
- throw new Error("Modal command router requires authenticated TLS");
22768
- this.client = new Client(url.host, credentials.createSsl(trustedRoots), {
22769
- "grpc.max_receive_message_length": maxWireBytes,
22770
- "grpc.max_send_message_length": maxWireBytes,
22771
- "grpc.enable_retries": 0
22772
- });
22773
- this.metadata = new Metadata();
22774
- this.metadata.set("authorization", `Bearer ${access.jwt}`);
22775
- }
22776
- close() {
22777
- this.closed = true;
22778
- this.client.close();
22779
- }
22780
- async unary(method, requestType, responseType, request, signal) {
22781
- signal?.throwIfAborted();
22782
- if (this.closed) throw new Error("Modal command router is closed");
22783
- return await new Promise((resolve7, reject) => {
22784
- const call = this.client.makeUnaryRequest(
22785
- prefix + method,
22786
- (value) => encode(requestType, value),
22787
- (bytes) => modalRouterWire.lookupType(responseType).decode(bytes),
22788
- request,
22789
- this.metadata,
22790
- { deadline: Date.now() + 3e4 },
22791
- (error, result) => {
22792
- signal?.removeEventListener("abort", abort);
22793
- if (signal?.aborted) reject(signal.reason);
22794
- else if (error) reject(error);
22795
- else if (result) resolve7(result);
22796
- else reject(new Error("Modal command router returned no response"));
22797
- }
22798
- );
22799
- const abort = () => call.cancel();
22800
- signal?.addEventListener("abort", abort, { once: true });
22801
- if (signal?.aborted) abort();
22802
- });
22803
- }
22804
- async start(request, signal) {
22805
- try {
22806
- await this.unary(
22807
- "TaskExecStart",
22808
- "Start",
22809
- "Empty",
22810
- {
22811
- ...request,
22812
- stdoutConfig: 1,
22813
- stderrConfig: 1
22814
- },
22815
- signal
22816
- );
22817
- } catch (error) {
22818
- const code = error?.code;
22819
- if (typeof code === "number" && [
22820
- status.INVALID_ARGUMENT,
22821
- status.NOT_FOUND,
22822
- status.PERMISSION_DENIED,
22823
- status.UNAUTHENTICATED,
22824
- status.UNIMPLEMENTED
22825
- ].includes(code))
22826
- throw new ModalCommandStartRejectedError(code, error);
22827
- throw error;
22828
- }
22829
- }
22830
- async write(identity, offset, data, signal) {
22831
- if (!Number.isSafeInteger(offset) || offset < 0)
22832
- throw new Error("Invalid Modal stdin byte offset");
22833
- await this.unary(
22834
- "TaskExecStdinWrite",
22835
- "Write",
22836
- "Empty",
22837
- { ...identity, offset, data, eof: false },
22838
- signal
22839
- );
22840
- }
22841
- async poll(identity, signal) {
22842
- const value = await this.unary("TaskExecPoll", "Identity", "Poll", identity, signal);
22843
- const decoded = modalRouterWire.lookupType("Poll").toObject(value);
22844
- if (decoded.code !== void 0) return decoded.code;
22845
- if (decoded.signal !== void 0) return 128 + decoded.signal;
22846
- return null;
22847
- }
22848
- async read(identity, stream, offset, waitMs, signal) {
22849
- signal?.throwIfAborted();
22850
- if (this.closed) throw new Error("Modal command router is closed");
22851
- if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isFinite(waitMs) || waitMs < 0 || waitMs > 5e4)
22852
- throw new Error("Invalid Modal output read bounds");
22853
- const chunks = [];
22854
- let length = 0;
22855
- let limited = false;
22856
- return await new Promise((resolve7, reject) => {
22857
- const call = this.client.makeServerStreamRequest(
22858
- prefix + "TaskExecStdioRead",
22859
- (value) => encode("Read", value),
22860
- (bytes) => modalRouterWire.lookupType("Data").decode(bytes),
22861
- { ...identity, offset, fileDescriptor: stream === "stdout" ? 0 : 1 },
22862
- this.metadata,
22863
- { deadline: Date.now() + Math.max(1, waitMs) }
22864
- );
22865
- const abort = () => call.cancel();
22866
- const finish = (eof, error) => {
22867
- signal?.removeEventListener("abort", abort);
22868
- if (signal?.aborted) reject(signal.reason);
22869
- else if (error) reject(error);
22870
- else resolve7({ bytes: Buffer.concat(chunks, length), eof });
22871
- };
22872
- call.on("data", (value) => {
22873
- if (limited) return;
22874
- const part = Buffer.from(value.data).subarray(0, maxPageBytes - length);
22875
- if (part.length) {
22876
- chunks.push(part);
22877
- length += part.length;
22878
- }
22879
- if (length === maxPageBytes) {
22880
- limited = true;
22881
- call.cancel();
22882
- }
22883
- });
22884
- call.once("error", (error) => {
22885
- if (limited && error.code === status.CANCELLED || error.code === status.DEADLINE_EXCEEDED)
22886
- finish(false);
22887
- else finish(false, error);
22888
- });
22889
- call.once("end", () => finish(!limited));
22890
- signal?.addEventListener("abort", abort, { once: true });
22891
- if (signal?.aborted) abort();
22892
- });
22893
- }
22894
- };
22895
-
22896
22933
  // src/sandbox/providers/modal-command-control.ts
22897
22934
  var ModalCommandControl2 = class _ModalCommandControl {
22898
22935
  constructor(client, sandboxIdentity, root, environment) {
@@ -23063,7 +23100,8 @@ var ModalCommandControl2 = class _ModalCommandControl {
23063
23100
  )
23064
23101
  );
23065
23102
  } catch (error) {
23066
- if (!supervision || error instanceof ModalCommandStartRejectedError) throw error;
23103
+ if (!supervision || error instanceof ModalCommandStartRejectedError || error instanceof ModalCommandStartPreDispatchUnavailableError)
23104
+ throw error;
23067
23105
  }
23068
23106
  return command;
23069
23107
  }
@@ -23329,8 +23367,6 @@ function installModalListDirCompatibility(session) {
23329
23367
  }
23330
23368
  var MODAL_EXEC_STDIN_WRITE_PATH = "/modal.task_command_router.TaskCommandRouter/TaskExecStdinWrite";
23331
23369
  var MODAL_EXEC_ALREADY_COMPLETED_DETAILS = /^Exec has already completed; stdin is no longer accepting writes(?: \(Error code: [A-Z0-9]+\))?$/;
23332
- var MODAL_TASK_EXEC_START_PATH = "/modal.task_command_router.TaskCommandRouter/TaskExecStart";
23333
- var MODAL_TASK_EXEC_START_DNS_RESOLUTION_DETAILS = /^Name resolution failed for target dns:task-[a-z0-9]+\.w\.modal\.host:443$/;
23334
23370
  var MODAL_TASK_EXEC_START_ERROR_MAX_DEPTH = 8;
23335
23371
  var MODAL_TASK_EXEC_START_ERROR_MAX_NODES = 64;
23336
23372
  var MODAL_TASK_EXEC_START_ERROR_MAX_AGGREGATE_ERRORS = 32;
@@ -23352,10 +23388,7 @@ function hasContradictoryModalHttpStatus(record) {
23352
23388
  }
23353
23389
  return values.some((value) => modalHttpStatus(value) !== null);
23354
23390
  }
23355
- function isModalTaskExecStartDnsResolutionLeaf(record) {
23356
- return record.name === "ClientError" && record.path === MODAL_TASK_EXEC_START_PATH && (record.code === 14 || record.code === "UNAVAILABLE") && typeof record.details === "string" && MODAL_TASK_EXEC_START_DNS_RESOLUTION_DETAILS.test(record.details);
23357
- }
23358
- function isModalTaskExecStartDnsResolutionError(error) {
23391
+ function isModalTaskExecStartPreDispatchUnavailableError(error) {
23359
23392
  const pending = [{ depth: 0, value: error }];
23360
23393
  const seen = /* @__PURE__ */ new WeakSet();
23361
23394
  let inspected = 0;
@@ -23372,7 +23405,12 @@ function isModalTaskExecStartDnsResolutionError(error) {
23372
23405
  let nested;
23373
23406
  try {
23374
23407
  const record = current.value;
23408
+ if (isRoutingMutationOutcomeUnknownError(current.value)) return false;
23375
23409
  if (hasContradictoryModalHttpStatus(record)) return false;
23410
+ if (current.value instanceof ModalCommandStartPreDispatchUnavailableError) {
23411
+ matchingLeaves += 1;
23412
+ continue;
23413
+ }
23376
23414
  nested = [];
23377
23415
  for (const key of ["cause", "error"]) {
23378
23416
  const value = record[key];
@@ -23385,11 +23423,7 @@ function isModalTaskExecStartDnsResolutionError(error) {
23385
23423
  }
23386
23424
  nested.push(...errors);
23387
23425
  }
23388
- if (nested.length === 0) {
23389
- if (!isModalTaskExecStartDnsResolutionLeaf(record)) return false;
23390
- matchingLeaves += 1;
23391
- continue;
23392
- }
23426
+ if (nested.length === 0) return false;
23393
23427
  } catch {
23394
23428
  return false;
23395
23429
  }
@@ -33049,6 +33083,7 @@ function shellQuote5(value) {
33049
33083
  // src/sandbox/browser-control-client.ts
33050
33084
  import { createHash as createHash7, randomUUID as randomUUID8 } from "crypto";
33051
33085
  import { posix as posixPath2 } from "path";
33086
+ import { parseBrowserFrameMetadata } from "@opengeni/sdk";
33052
33087
  import {
33053
33088
  BROWSER_CONTROL_MAX_JSON_BYTES,
33054
33089
  BROWSER_CONTROL_PORT as BROWSER_CONTROL_PORT2,
@@ -33063,6 +33098,8 @@ import {
33063
33098
  BrowserDownloadExportReceipt,
33064
33099
  BrowserDownloadExportRequest,
33065
33100
  BrowserDownloadListResponse,
33101
+ BrowserDomReadRequest,
33102
+ BrowserDomReadResponse,
33066
33103
  BrowserExternalAuthCommand,
33067
33104
  BrowserExternalAuthResult,
33068
33105
  BrowserObservation,
@@ -33070,6 +33107,7 @@ import {
33070
33107
  BrowserProtectedAuthFillReceipt,
33071
33108
  BrowserRevisionMaterialization,
33072
33109
  BrowserTarget,
33110
+ BrowserTargetState,
33073
33111
  BrowserWorkspaceFileStageRequest,
33074
33112
  BrowserWorkspaceFileStageResponse,
33075
33113
  ComputerActionCommand,
@@ -33536,7 +33574,10 @@ var BrowserControlClient = class {
33536
33574
  return await this.requestJson(input);
33537
33575
  }
33538
33576
  async requestBytesForSession(input) {
33539
- return await this.requestBytes(input);
33577
+ return await this.requestBytes({ ...input, surface: "computer" });
33578
+ }
33579
+ async requestBrowserBytesForSession(input) {
33580
+ return await this.requestBytes({ ...input, surface: "browser" });
33540
33581
  }
33541
33582
  async requestJson(input, retryNativeEndpoint = true) {
33542
33583
  const requireHostFetch = this.session.requireHostFetchController === true;
@@ -33772,10 +33813,10 @@ var BrowserControlClient = class {
33772
33813
  const data = await readBytes(
33773
33814
  this.session,
33774
33815
  responsePath,
33775
- COMPUTER_SCREENSHOT_MAX_BYTES,
33816
+ input.surface === "browser" ? 24 * 1024 * 1024 : COMPUTER_SCREENSHOT_MAX_BYTES,
33776
33817
  timeoutMs
33777
33818
  );
33778
- return computerControlFrame(data, headers, input.expectedFrameEvidence);
33819
+ return controllerImageFrame(data, headers, input);
33779
33820
  } catch (error) {
33780
33821
  if (error instanceof BrowserControlRequestError || error instanceof BrowserControlProtocolError || error instanceof RangeError) {
33781
33822
  throw error;
@@ -33923,6 +33964,75 @@ var BrowserControlSessionClient = class {
33923
33964
  })
33924
33965
  );
33925
33966
  }
33967
+ async targetState(targetId) {
33968
+ let state;
33969
+ try {
33970
+ state = BrowserTargetState.parse(
33971
+ await this.parent.requestForSession({
33972
+ method: "GET",
33973
+ path: this.targetPath(targetId, "state"),
33974
+ token: this.viewToken
33975
+ })
33976
+ );
33977
+ } catch (error) {
33978
+ if (!(error instanceof BrowserControlRequestError) || error.status !== 404 || error.error.code !== "resource_not_found" || error.error.message !== "route not found") {
33979
+ throw error;
33980
+ }
33981
+ const observation = await this.observe(targetId);
33982
+ state = BrowserTargetState.parse({
33983
+ browserSessionId: observation.browserSessionId,
33984
+ controllerGeneration: observation.target.controllerGeneration,
33985
+ targetId: observation.target.id,
33986
+ targetGeneration: observation.target.targetGeneration,
33987
+ documentGeneration: observation.target.documentGeneration,
33988
+ frameId: observation.frameId
33989
+ });
33990
+ }
33991
+ if (state.browserSessionId !== this.reference.browserSessionId || state.controllerGeneration !== this.reference.controllerGeneration || state.targetId !== targetId) {
33992
+ throw new BrowserControlProtocolError("browser target state belongs to another binding");
33993
+ }
33994
+ return state;
33995
+ }
33996
+ async readDom(targetId, requestInput) {
33997
+ const request = BrowserDomReadRequest.parse(requestInput);
33998
+ const result = BrowserDomReadResponse.parse(
33999
+ await this.parent.requestForSession({
34000
+ method: "POST",
34001
+ path: this.targetPath(targetId, "dom-read"),
34002
+ token: this.viewToken,
34003
+ body: request
34004
+ })
34005
+ );
34006
+ if (result.browserSessionId !== this.reference.browserSessionId || result.controllerGeneration !== this.reference.controllerGeneration || result.targetId !== targetId || result.targetGeneration !== request.expectedTargetGeneration || result.documentGeneration !== request.expectedDocumentGeneration || result.frameId !== request.expectedFrameId || result.kind !== request.kind) {
34007
+ throw new BrowserControlProtocolError("browser DOM read belongs to another binding");
34008
+ }
34009
+ return result;
34010
+ }
34011
+ async capture(targetId, options = {}) {
34012
+ const query = new URLSearchParams({
34013
+ format: options.format ?? "jpeg",
34014
+ quality: String(boundedInteger(options.quality ?? 55, 1, 100, "browser screenshot quality"))
34015
+ });
34016
+ if (options.format !== void 0 && options.format !== "jpeg" && options.format !== "png") {
34017
+ throw new RangeError("browser screenshot format is invalid");
34018
+ }
34019
+ if (options.fullPage !== void 0) {
34020
+ if (typeof options.fullPage !== "boolean") {
34021
+ throw new RangeError("browser screenshot fullPage is invalid");
34022
+ }
34023
+ query.set("fullPage", String(options.fullPage));
34024
+ }
34025
+ return await this.parent.requestBrowserBytesForSession({
34026
+ method: "GET",
34027
+ path: this.targetPath(targetId, `screenshot?${query}`),
34028
+ token: this.viewToken,
34029
+ expectedFrameEvidence: {
34030
+ browserSessionId: this.reference.browserSessionId,
34031
+ controllerGeneration: this.reference.controllerGeneration,
34032
+ targetId: requireOpaqueId(targetId, "browser target id")
34033
+ }
34034
+ });
34035
+ }
33926
34036
  async readClipboard() {
33927
34037
  return BrowserClipboard.parse(
33928
34038
  await this.parent.requestForSession({
@@ -34256,12 +34366,69 @@ async function requestExposedControllerBytes(endpoint, input, defaultTimeoutMs)
34256
34366
  throw new BrowserControlProtocolError("browser controller image response is invalid");
34257
34367
  }
34258
34368
  const declaredLength = Number(response.headers.get("content-length"));
34259
- if (Number.isFinite(declaredLength) && declaredLength > COMPUTER_SCREENSHOT_MAX_BYTES) {
34260
- await response.body?.cancel("computer frame exceeds its byte bound").catch(() => void 0);
34261
- throw new RangeError("computer frame exceeds its byte bound");
34369
+ const maxBytes = input.surface === "browser" ? 24 * 1024 * 1024 : COMPUTER_SCREENSHOT_MAX_BYTES;
34370
+ if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
34371
+ await response.body?.cancel("frame exceeds its byte bound").catch(() => void 0);
34372
+ throw new RangeError("frame exceeds its byte bound");
34373
+ }
34374
+ const data = await readBoundedFrameResponse(response, maxBytes);
34375
+ return controllerImageFrame(data, response.headers, input);
34376
+ }
34377
+ async function readBoundedFrameResponse(response, maxBytes) {
34378
+ if (!response.body) throw new BrowserControlProtocolError("browser controller image is empty");
34379
+ const reader = response.body.getReader();
34380
+ const chunks = [];
34381
+ let size = 0;
34382
+ try {
34383
+ for (; ; ) {
34384
+ const { done, value } = await reader.read();
34385
+ if (done) break;
34386
+ size += value.byteLength;
34387
+ if (size > maxBytes) {
34388
+ await reader.cancel("frame exceeds its byte bound").catch(() => void 0);
34389
+ throw new RangeError("frame exceeds its byte bound");
34390
+ }
34391
+ chunks.push(value);
34392
+ }
34393
+ } finally {
34394
+ reader.releaseLock();
34262
34395
  }
34263
- const data = new Uint8Array(await response.arrayBuffer());
34264
- return computerControlFrame(data, response.headers, input.expectedFrameEvidence);
34396
+ const data = new Uint8Array(size);
34397
+ let offset = 0;
34398
+ for (const chunk of chunks) {
34399
+ data.set(chunk, offset);
34400
+ offset += chunk.byteLength;
34401
+ }
34402
+ return data;
34403
+ }
34404
+ function controllerImageFrame(data, headers, input) {
34405
+ return input.surface === "browser" ? browserControlFrame(data, headers, input.expectedFrameEvidence) : computerControlFrame(data, headers, input.expectedFrameEvidence);
34406
+ }
34407
+ function browserControlFrame(data, headers, expected) {
34408
+ if (data.byteLength < 1 || data.byteLength > 24 * 1024 * 1024) {
34409
+ throw new RangeError("browser frame exceeds its byte bound");
34410
+ }
34411
+ const get = (name) => headers.get(name.toLowerCase()) ?? null;
34412
+ const mediaType = get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
34413
+ if (mediaType !== "image/jpeg" && mediaType !== "image/png") {
34414
+ throw new BrowserControlProtocolError("browser frame media type is invalid");
34415
+ }
34416
+ const metadataHeader = get("x-opengeni-browser-frame");
34417
+ if (!metadataHeader || metadataHeader.length > 64 * 1024 || !/^[A-Za-z0-9_-]+$/u.test(metadataHeader)) {
34418
+ throw new BrowserControlProtocolError("browser frame metadata is invalid");
34419
+ }
34420
+ let metadata;
34421
+ try {
34422
+ metadata = parseBrowserFrameMetadata(
34423
+ JSON.parse(Buffer.from(metadataHeader, "base64url").toString("utf8"))
34424
+ );
34425
+ } catch {
34426
+ throw new BrowserControlProtocolError("browser frame metadata is invalid");
34427
+ }
34428
+ if (metadata.browserSessionId !== expected.browserSessionId || metadata.controllerGeneration !== expected.controllerGeneration || metadata.targetId !== expected.targetId || metadata.mediaType !== mediaType) {
34429
+ throw new BrowserControlProtocolError("browser frame evidence does not match its request");
34430
+ }
34431
+ return { data, mediaType, metadataHeader, metadata };
34265
34432
  }
34266
34433
  function computerControlFrame(data, headers, expected) {
34267
34434
  if (data.byteLength < 1 || data.byteLength > COMPUTER_SCREENSHOT_MAX_BYTES) {
@@ -34936,7 +35103,7 @@ async function readText(session, path, maxBytes, timeoutMs) {
34936
35103
  }
34937
35104
  async function readBytes(session, path, maxBytes, timeoutMs) {
34938
35105
  const privatePath = absolutePrivatePath(path, "browser private binary response path");
34939
- if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > COMPUTER_SCREENSHOT_MAX_BYTES) {
35106
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > Math.max(24 * 1024 * 1024, COMPUTER_SCREENSHOT_MAX_BYTES)) {
34940
35107
  throw new RangeError("browser private binary response limit is invalid");
34941
35108
  }
34942
35109
  const sizeMarker = `OPENGENI_BROWSER_PRIVATE_SIZE_${randomUUID8()}`;
@@ -34955,7 +35122,7 @@ async function readBytes(session, path, maxBytes, timeoutMs) {
34955
35122
  "browser private binary response size"
34956
35123
  );
34957
35124
  if (size < 1 || size > maxBytes) {
34958
- throw new RangeError("computer frame exceeds its byte bound");
35125
+ throw new RangeError("frame exceeds its byte bound");
34959
35126
  }
34960
35127
  const chunks = [];
34961
35128
  for (let offset = 0; offset < size; offset += PRIVATE_READ_CHUNK_BYTES) {
@@ -38388,7 +38555,7 @@ export {
38388
38555
  assertDescriptorRegistryInvariants,
38389
38556
  modalSandboxAttributionEnvironment,
38390
38557
  modalSandboxAttributionTags,
38391
- isModalTaskExecStartDnsResolutionError,
38558
+ isModalTaskExecStartPreDispatchUnavailableError,
38392
38559
  ensureModalRegistryImage,
38393
38560
  resolveModalCheckpointProviderBindingForSession,
38394
38561
  modalSessionMatchesCheckpointProviderBinding,
@@ -38571,4 +38738,4 @@ export {
38571
38738
  collectSandboxEnvironment2 as collectSandboxEnvironment,
38572
38739
  parseExposedPorts2 as parseExposedPorts
38573
38740
  };
38574
- //# sourceMappingURL=chunk-J5AR5XAJ.js.map
38741
+ //# sourceMappingURL=chunk-GBVN7WSK.js.map