@opengeni/runtime 4.0.1 → 4.0.3-canary.36199476632001

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 (61) 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-FAFZCSN7.js} +695 -210
  5. package/dist/chunk-FAFZCSN7.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-P4V7JGQ2.js} +1037 -105
  10. package/dist/chunk-P4V7JGQ2.js.map +1 -0
  11. package/dist/{chunk-SPT3PLMX.js → chunk-PRHMSM6C.js} +2 -2
  12. package/dist/codex-tool-search.d.ts +12 -0
  13. package/dist/context-compaction.d.ts +4 -2
  14. package/dist/index.d.ts +27 -8
  15. package/dist/index.js +23 -7
  16. package/dist/interaction-tools.d.ts +1 -1
  17. package/dist/{lazy-manifest-OEYEHNVY.js → lazy-manifest-GCGUFIWP.js} +3 -3
  18. package/dist/{localSources-TWHTEKGO.js → localSources-FDH65AFI.js} +4 -4
  19. package/dist/metrics.d.ts +17 -0
  20. package/dist/model-provider-routing.d.ts +14 -0
  21. package/dist/operational-instructions.d.ts +1 -1
  22. package/dist/provider-quota.d.ts +76 -0
  23. package/dist/sandbox/browser-control-client.d.ts +28 -1
  24. package/dist/sandbox/channel-a.d.ts +43 -0
  25. package/dist/sandbox/index.d.ts +3 -3
  26. package/dist/sandbox/index.js +10 -6
  27. package/dist/sandbox/providers/modal-command-router-wire.d.ts +8 -0
  28. package/dist/sandbox/providers/modal.d.ts +5 -6
  29. package/dist/workspace-tool-gateway.js +5 -5
  30. package/package.json +11 -11
  31. package/src/browser-action-json-schema.ts +10 -0
  32. package/src/bundled_artifact_skills/opengeni-documents/SKILL.md +4 -1
  33. package/src/bundled_artifact_skills/opengeni-documents/references/api.md +20 -0
  34. package/src/bundled_default_skills/opengeni-client/SKILL.md +4 -1
  35. package/src/bundled_default_skills/opengeni-client/references/discovery-and-autonomy.md +31 -0
  36. package/src/bundled_default_skills/opengeni-client/references/runtime-profile-and-verification.md +32 -0
  37. package/src/codex-tool-search.ts +54 -6
  38. package/src/context-compaction.ts +19 -3
  39. package/src/index.ts +285 -56
  40. package/src/interaction-tools.ts +656 -48
  41. package/src/lazy-tool-transport.ts +4 -0
  42. package/src/metrics.ts +26 -0
  43. package/src/model-context-inspector.ts +1 -0
  44. package/src/model-provider-client.ts +37 -16
  45. package/src/model-provider-routing.ts +32 -6
  46. package/src/operational-instructions.ts +1 -1
  47. package/src/provider-quota.ts +412 -0
  48. package/src/sandbox/browser-control-client.ts +241 -26
  49. package/src/sandbox/channel-a.ts +370 -0
  50. package/src/sandbox/index.ts +6 -1
  51. package/src/sandbox/providers/modal-command-control.ts +7 -1
  52. package/src/sandbox/providers/modal-command-router-wire.ts +47 -6
  53. package/src/sandbox/providers/modal.ts +16 -24
  54. package/src/sandbox/routing/routing-session.ts +29 -6
  55. package/dist/chunk-J5AR5XAJ.js.map +0 -1
  56. package/dist/chunk-J6J3VYFW.js.map +0 -1
  57. /package/dist/{agent-RJQLKFIW.js.map → agent-ME6HT4DH.js.map} +0 -0
  58. /package/dist/{chunk-ZG2YH25H.js.map → chunk-JAYHA6BF.js.map} +0 -0
  59. /package/dist/{chunk-SPT3PLMX.js.map → chunk-PRHMSM6C.js.map} +0 -0
  60. /package/dist/{lazy-manifest-OEYEHNVY.js.map → lazy-manifest-GCGUFIWP.js.map} +0 -0
  61. /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
  }
@@ -15606,6 +15606,9 @@ import {
15606
15606
  canonicalModalCheckpointProviderBinding
15607
15607
  } from "@opengeni/contracts";
15608
15608
 
15609
+ // src/sandbox/channel-a.ts
15610
+ import { constants as zlibConstants, createGunzip } from "zlib";
15611
+
15609
15612
  // src/sandbox/selfhosted/workspace-path.ts
15610
15613
  var MAX_MACHINE_PATH_LENGTH = 4096;
15611
15614
  var CONTROL_CHARACTER = /[\u0000-\u001f\u007f]/u;
@@ -15849,7 +15852,11 @@ function notifyDurableOpOwnershipTransferred(opId) {
15849
15852
  }
15850
15853
 
15851
15854
  // src/sandbox/routing/routing-session.ts
15852
- import { isDeepStrictEqual } from "util";
15855
+ import { SandboxFilesystemNotFoundError } from "modal";
15856
+
15857
+ // src/sandbox/providers/modal-command-router-wire.ts
15858
+ import { Client, Metadata, credentials, status } from "@grpc/grpc-js";
15859
+ import protobuf from "protobufjs";
15853
15860
 
15854
15861
  // src/sandbox/provider-command-session.ts
15855
15862
  import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
@@ -15895,6 +15902,219 @@ function admittedProviderCommandHandle() {
15895
15902
  return admission.getStore();
15896
15903
  }
15897
15904
 
15905
+ // src/sandbox/providers/modal-command-router-wire.ts
15906
+ var modalRouterWire = protobuf.parse(`syntax = "proto3";
15907
+ message Identity { string task_id = 1; string exec_id = 2; }
15908
+ message Pty {
15909
+ bool enabled = 1; uint32 winsz_rows = 2; uint32 winsz_cols = 3;
15910
+ string env_term = 4; string env_colorterm = 5; string env_term_program = 6;
15911
+ int32 pty_type = 7; bool no_terminate_on_idle_stdin = 8;
15912
+ }
15913
+ message Start {
15914
+ string task_id = 1; string exec_id = 2; repeated string command_args = 3;
15915
+ int32 stdout_config = 4; int32 stderr_config = 5;
15916
+ optional uint32 timeout_secs = 6; optional string workdir = 7;
15917
+ repeated string secret_ids = 8; optional Pty pty_info = 9;
15918
+ bool runtime_debug = 10; string container_id = 11; map<string,string> env = 12;
15919
+ }
15920
+ message Read {
15921
+ string task_id = 1; string exec_id = 2; uint64 offset = 3; int32 file_descriptor = 4;
15922
+ }
15923
+ message Data { bytes data = 1; }
15924
+ message Poll { optional int32 code = 1; optional int32 signal = 2; }
15925
+ message Write {
15926
+ string task_id = 1; string exec_id = 2; uint64 offset = 3; bytes data = 4; bool eof = 5;
15927
+ }
15928
+ message Empty {}
15929
+ `).root;
15930
+ var prefix = "/modal.task_command_router.TaskCommandRouter/";
15931
+ var maxPageBytes = 64 * 1024;
15932
+ var maxWireBytes = 4 * 1024 * 1024;
15933
+ var ModalCommandStartRejectedError = class extends ProviderCommandStartRejectedError {
15934
+ constructor(code, cause) {
15935
+ super(cause);
15936
+ this.code = code;
15937
+ this.name = "ModalCommandStartRejectedError";
15938
+ }
15939
+ };
15940
+ var ModalCommandStartPreDispatchUnavailableError = class _ModalCommandStartPreDispatchUnavailableError extends Error {
15941
+ constructor(cause) {
15942
+ super("Modal command router was not ready before Start dispatch", { cause });
15943
+ this.name = "ModalCommandStartPreDispatchUnavailableError";
15944
+ }
15945
+ static async ensureReady(client, signal) {
15946
+ signal?.throwIfAborted();
15947
+ await new Promise((resolve7, reject) => {
15948
+ let settled = false;
15949
+ const finish = (error) => {
15950
+ if (settled) return;
15951
+ settled = true;
15952
+ signal?.removeEventListener("abort", abort);
15953
+ if (signal?.aborted) reject(signal.reason);
15954
+ else if (error) reject(new _ModalCommandStartPreDispatchUnavailableError(error));
15955
+ else resolve7();
15956
+ };
15957
+ const abort = () => finish();
15958
+ signal?.addEventListener("abort", abort, { once: true });
15959
+ client.waitForReady(Date.now() + 5e3, finish);
15960
+ if (signal?.aborted) abort();
15961
+ });
15962
+ }
15963
+ };
15964
+ function encode(type, value) {
15965
+ const codec = modalRouterWire.lookupType(type);
15966
+ return Buffer.from(codec.encode(codec.fromObject(value)).finish());
15967
+ }
15968
+ var ModalCommandRouterWire = class {
15969
+ client;
15970
+ metadata;
15971
+ closed = false;
15972
+ constructor(access, trustedRoots) {
15973
+ const url = new URL(access.url);
15974
+ if (url.protocol !== "https:" || url.username || url.password || !access.jwt)
15975
+ throw new Error("Modal command router requires authenticated TLS");
15976
+ this.client = new Client(
15977
+ `${url.hostname}:${url.port || "443"}`,
15978
+ credentials.createSsl(trustedRoots),
15979
+ {
15980
+ "grpc.max_receive_message_length": maxWireBytes,
15981
+ "grpc.max_send_message_length": maxWireBytes,
15982
+ "grpc.enable_retries": 0
15983
+ }
15984
+ );
15985
+ this.metadata = new Metadata();
15986
+ this.metadata.set("authorization", `Bearer ${access.jwt}`);
15987
+ }
15988
+ close() {
15989
+ this.closed = true;
15990
+ this.client.close();
15991
+ }
15992
+ async unary(method, requestType, responseType, request, signal) {
15993
+ signal?.throwIfAborted();
15994
+ if (this.closed) throw new Error("Modal command router is closed");
15995
+ return await new Promise((resolve7, reject) => {
15996
+ const call = this.client.makeUnaryRequest(
15997
+ prefix + method,
15998
+ (value) => encode(requestType, value),
15999
+ (bytes) => modalRouterWire.lookupType(responseType).decode(bytes),
16000
+ request,
16001
+ this.metadata,
16002
+ { deadline: Date.now() + 3e4 },
16003
+ (error, result) => {
16004
+ signal?.removeEventListener("abort", abort);
16005
+ if (signal?.aborted) reject(signal.reason);
16006
+ else if (error) reject(error);
16007
+ else if (result) resolve7(result);
16008
+ else reject(new Error("Modal command router returned no response"));
16009
+ }
16010
+ );
16011
+ const abort = () => call.cancel();
16012
+ signal?.addEventListener("abort", abort, { once: true });
16013
+ if (signal?.aborted) abort();
16014
+ });
16015
+ }
16016
+ async start(request, signal) {
16017
+ if (this.closed) throw new Error("Modal command router is closed");
16018
+ try {
16019
+ await ModalCommandStartPreDispatchUnavailableError.ensureReady(this.client, signal);
16020
+ } catch (error) {
16021
+ if (this.closed) throw new Error("Modal command router is closed", { cause: error });
16022
+ throw error;
16023
+ }
16024
+ try {
16025
+ await this.unary(
16026
+ "TaskExecStart",
16027
+ "Start",
16028
+ "Empty",
16029
+ {
16030
+ ...request,
16031
+ stdoutConfig: 1,
16032
+ stderrConfig: 1
16033
+ },
16034
+ signal
16035
+ );
16036
+ } catch (error) {
16037
+ const code = error?.code;
16038
+ if (typeof code === "number" && [
16039
+ status.INVALID_ARGUMENT,
16040
+ status.NOT_FOUND,
16041
+ status.PERMISSION_DENIED,
16042
+ status.UNAUTHENTICATED,
16043
+ status.UNIMPLEMENTED
16044
+ ].includes(code))
16045
+ throw new ModalCommandStartRejectedError(code, error);
16046
+ throw error;
16047
+ }
16048
+ }
16049
+ async write(identity, offset, data, signal) {
16050
+ if (!Number.isSafeInteger(offset) || offset < 0)
16051
+ throw new Error("Invalid Modal stdin byte offset");
16052
+ await this.unary(
16053
+ "TaskExecStdinWrite",
16054
+ "Write",
16055
+ "Empty",
16056
+ { ...identity, offset, data, eof: false },
16057
+ signal
16058
+ );
16059
+ }
16060
+ async poll(identity, signal) {
16061
+ const value = await this.unary("TaskExecPoll", "Identity", "Poll", identity, signal);
16062
+ const decoded = modalRouterWire.lookupType("Poll").toObject(value);
16063
+ if (decoded.code !== void 0) return decoded.code;
16064
+ if (decoded.signal !== void 0) return 128 + decoded.signal;
16065
+ return null;
16066
+ }
16067
+ async read(identity, stream, offset, waitMs, signal) {
16068
+ signal?.throwIfAborted();
16069
+ if (this.closed) throw new Error("Modal command router is closed");
16070
+ if (!Number.isSafeInteger(offset) || offset < 0 || !Number.isFinite(waitMs) || waitMs < 0 || waitMs > 5e4)
16071
+ throw new Error("Invalid Modal output read bounds");
16072
+ const chunks = [];
16073
+ let length = 0;
16074
+ let limited = false;
16075
+ return await new Promise((resolve7, reject) => {
16076
+ const call = this.client.makeServerStreamRequest(
16077
+ prefix + "TaskExecStdioRead",
16078
+ (value) => encode("Read", value),
16079
+ (bytes) => modalRouterWire.lookupType("Data").decode(bytes),
16080
+ { ...identity, offset, fileDescriptor: stream === "stdout" ? 0 : 1 },
16081
+ this.metadata,
16082
+ { deadline: Date.now() + Math.max(1, waitMs) }
16083
+ );
16084
+ const abort = () => call.cancel();
16085
+ const finish = (eof, error) => {
16086
+ signal?.removeEventListener("abort", abort);
16087
+ if (signal?.aborted) reject(signal.reason);
16088
+ else if (error) reject(error);
16089
+ else resolve7({ bytes: Buffer.concat(chunks, length), eof });
16090
+ };
16091
+ call.on("data", (value) => {
16092
+ if (limited) return;
16093
+ const part = Buffer.from(value.data).subarray(0, maxPageBytes - length);
16094
+ if (part.length) {
16095
+ chunks.push(part);
16096
+ length += part.length;
16097
+ }
16098
+ if (length === maxPageBytes) {
16099
+ limited = true;
16100
+ call.cancel();
16101
+ }
16102
+ });
16103
+ call.once("error", (error) => {
16104
+ if (limited && error.code === status.CANCELLED || error.code === status.DEADLINE_EXCEEDED)
16105
+ finish(false);
16106
+ else finish(false, error);
16107
+ });
16108
+ call.once("end", () => finish(!limited));
16109
+ signal?.addEventListener("abort", abort, { once: true });
16110
+ if (signal?.aborted) abort();
16111
+ });
16112
+ }
16113
+ };
16114
+
16115
+ // src/sandbox/routing/routing-session.ts
16116
+ import { isDeepStrictEqual } from "util";
16117
+
15898
16118
  // src/sandbox/materialization-verification-error.ts
15899
16119
  var EXPLANATIONS = {
15900
16120
  path_not_visible: "the provider could not see the destination path",
@@ -16365,6 +16585,10 @@ function eligibleForSupervision(args) {
16365
16585
  args && typeof args === "object" && !args.tty && !args.runAs
16366
16586
  );
16367
16587
  }
16588
+ var READ_ONLY_PATH_PROBE_OPERATIONS = /* @__PURE__ */ new Set(["readFile", "listDir", "pathExists", "viewImage"]);
16589
+ function isReadOnlyPathProbeMiss(op, error) {
16590
+ return READ_ONLY_PATH_PROBE_OPERATIONS.has(op) && (isDefinitePathNotFoundError(error) || error instanceof SandboxWorkspaceReadNotFoundError || error instanceof SandboxFilesystemNotFoundError);
16591
+ }
16368
16592
  function recordFirstOperationPhase(timing, phase, durationMs, outcome) {
16369
16593
  if (!timing) return;
16370
16594
  const prior = timing.phases[phase];
@@ -17172,6 +17396,9 @@ var RoutingSandboxSession = class {
17172
17396
  );
17173
17397
  outcome = "completed";
17174
17398
  return result;
17399
+ } catch (error) {
17400
+ if (isReadOnlyPathProbeMiss(op, error)) outcome = "completed";
17401
+ throw error;
17175
17402
  } finally {
17176
17403
  try {
17177
17404
  firstOperationObserver({
@@ -17331,6 +17558,9 @@ var RoutingSandboxSession = class {
17331
17558
  }
17332
17559
  );
17333
17560
  providerOutcome = "completed";
17561
+ } catch (error) {
17562
+ if (isReadOnlyPathProbeMiss(op, error)) providerOutcome = "completed";
17563
+ throw error;
17334
17564
  } finally {
17335
17565
  recordFirstOperationPhase(
17336
17566
  firstOperationTiming,
@@ -17341,7 +17571,7 @@ var RoutingSandboxSession = class {
17341
17571
  }
17342
17572
  } catch (error) {
17343
17573
  if (reservedProcess) {
17344
- if (error instanceof ProviderCommandStartRejectedError && reservedProcess.providerCommand?.kind === "modal-router-v1") {
17574
+ if ((error instanceof ProviderCommandStartRejectedError || error instanceof ModalCommandStartPreDispatchUnavailableError) && reservedProcess.providerCommand?.kind === "modal-router-v1") {
17345
17575
  const persistence = this.deps.providerCommandPersistence?.(reservedProcess);
17346
17576
  if (persistence?.rejectSupervisedLaunch) {
17347
17577
  try {
@@ -17349,7 +17579,7 @@ var RoutingSandboxSession = class {
17349
17579
  } catch (cause) {
17350
17580
  throw new RoutingMutationOutcomeUnknownError(
17351
17581
  op,
17352
- "Never-started provider rejection could not settle its exact reservation",
17582
+ "Never-started provider call could not settle its exact reservation",
17353
17583
  { cause, retainedProcess: reservedProcess }
17354
17584
  );
17355
17585
  }
@@ -17541,7 +17771,7 @@ var RoutingSandboxSession = class {
17541
17771
  return result;
17542
17772
  } catch (error) {
17543
17773
  materializationFailureReason = materializationVerificationDiagnostic(error)?.reason;
17544
- if ((op === "readFile" || op === "listDir" || op === "pathExists" || op === "viewImage") && isDefinitePathNotFoundError(error)) {
17774
+ if (isReadOnlyPathProbeMiss(op, error)) {
17545
17775
  outcome = "not_found";
17546
17776
  }
17547
17777
  throw error;
@@ -19667,6 +19897,97 @@ var ChannelAPartialMutationError = class extends Error {
19667
19897
  };
19668
19898
  var REPOSITORY_DISCOVERY_LIMIT = 256;
19669
19899
  var REPOSITORY_DISCOVERY_TRUNCATED_SENTINEL = "__OPENGENI_REPOSITORY_DISCOVERY_TRUNCATED__";
19900
+ var CODE_SEARCH_RG_MAX_BYTES = 64 * 1024 * 1024;
19901
+ var CODE_SEARCH_RG_CHUNK_BYTES = 512 * 1024;
19902
+ var CODE_SEARCH_RG_FRAME_CHARS = 768 * 1024;
19903
+ var CODE_SEARCH_RG_MAX_TRANSFER_BYTES = 8 * 1024 * 1024;
19904
+ var CODE_SEARCH_RG_TOKEN = /^opengeni-code-search\.[A-Za-z0-9]+$/;
19905
+ var CODE_SEARCH_RG_BEGIN = "__OPENGENI_CODE_SEARCH_RG_BEGIN__";
19906
+ var CODE_SEARCH_RG_END = "__OPENGENI_CODE_SEARCH_RG_END__";
19907
+ var CODE_SEARCH_RG_TRAILER = new RegExp(
19908
+ `${CODE_SEARCH_RG_END}(\\d+):([01])(?::(\\d+):([A-Za-z0-9._-]+)(?::(\\d+):([01]))?)?__`
19909
+ );
19910
+ var CODE_SEARCH_RG_STORE_FAILED = "code search could not store its output on this machine; its temporary directory may be full";
19911
+ var CODE_SEARCH_KINDS_BEGIN = "__OPENGENI_CODE_SEARCH_KINDS_BEGIN__";
19912
+ var CODE_SEARCH_KINDS_END = "__OPENGENI_CODE_SEARCH_KINDS_END__";
19913
+ var CODE_SEARCH_RG_FLAGS = /* @__PURE__ */ new Set([
19914
+ "--files",
19915
+ "--null",
19916
+ "--line-number",
19917
+ "--with-filename",
19918
+ "--no-heading",
19919
+ "-i",
19920
+ "-w",
19921
+ "--no-require-git",
19922
+ "--hidden"
19923
+ ]);
19924
+ var CODE_SEARCH_RG_VALUE_FLAGS = /* @__PURE__ */ new Map([
19925
+ ["--color", (value) => value === "never"],
19926
+ ["-m", (value) => /^[1-9]\d{0,5}$/.test(value)],
19927
+ ["--max-columns", (value) => /^[1-9]\d{0,6}$/.test(value)],
19928
+ ["--max-filesize", (value) => /^[1-9]\d{0,9}$/.test(value)],
19929
+ ["-g", (value) => value.length > 0 && value.length <= 512],
19930
+ ["-e", (value) => value.length > 0 && value.length <= 16384]
19931
+ ]);
19932
+ function validateCodeSearchRipgrepArgs(args, workspaceRoot = "") {
19933
+ const out = [];
19934
+ let index = 0;
19935
+ for (; index < args.length; index++) {
19936
+ const arg = args[index];
19937
+ if (arg.includes(NUL)) throw new ChannelAValidationError("ripgrep argument contains NUL");
19938
+ if (arg === "--") break;
19939
+ if (CODE_SEARCH_RG_FLAGS.has(arg)) {
19940
+ out.push(arg);
19941
+ continue;
19942
+ }
19943
+ const valid = CODE_SEARCH_RG_VALUE_FLAGS.get(arg);
19944
+ const value = args[index + 1];
19945
+ if (!valid || value === void 0 || value.includes(NUL) || !valid(value)) {
19946
+ throw new ChannelAValidationError(`ripgrep argument is not allowed: ${arg}`);
19947
+ }
19948
+ out.push(arg, value);
19949
+ index++;
19950
+ }
19951
+ const paths = args.slice(index + 1);
19952
+ if (index >= args.length || paths.length === 0) {
19953
+ throw new ChannelAValidationError("ripgrep arguments must end with -- and paths");
19954
+ }
19955
+ out.push("--");
19956
+ for (const path of paths) {
19957
+ if (path.includes(NUL) || path.startsWith("-") || path.startsWith("/")) {
19958
+ throw new ChannelAValidationError(`ripgrep path is not allowed: ${path}`);
19959
+ }
19960
+ out.push(assertSafeRelPathOrRoot(path, workspaceRoot) || ".");
19961
+ }
19962
+ return ["--no-config", ...out];
19963
+ }
19964
+ function decodeCodeSearchChunk(stdout, trailerIndex) {
19965
+ const begin = stdout.indexOf(CODE_SEARCH_RG_BEGIN);
19966
+ if (begin < 0 || begin > trailerIndex) {
19967
+ throw new ChannelAUnavailableError("code search output frame is missing");
19968
+ }
19969
+ const encoded = stdout.slice(begin + CODE_SEARCH_RG_BEGIN.length, trailerIndex).replace(/\s+/g, "");
19970
+ if (encoded.length > Math.ceil(CODE_SEARCH_RG_CHUNK_BYTES / 3) * 4) {
19971
+ throw new ChannelAUnavailableError("code search output frame is malformed");
19972
+ }
19973
+ return Buffer.from(encoded, "base64");
19974
+ }
19975
+ async function gunzipCodeSearchPrefix(input, limit) {
19976
+ const gunzip = createGunzip({ finishFlush: zlibConstants.Z_SYNC_FLUSH, chunkSize: 64 * 1024 });
19977
+ gunzip.end(input);
19978
+ const chunks = [];
19979
+ let size = 0;
19980
+ try {
19981
+ for await (const chunk of gunzip) {
19982
+ chunks.push(chunk);
19983
+ size += chunk.length;
19984
+ if (size >= limit) break;
19985
+ }
19986
+ } catch {
19987
+ throw new ChannelAUnavailableError("code search output could not be decoded");
19988
+ }
19989
+ return Buffer.concat(chunks, size).subarray(0, limit);
19990
+ }
19670
19991
  var REPOSITORY_DISCOVERY_STATUS_PREFIX = "__OPENGENI_REPOSITORY_DISCOVERY_STATUS__:";
19671
19992
  var NUL = String.fromCharCode(0);
19672
19993
  var FS_LIST_TRUNCATED_MARKER = "__OPENGENI_FS_LIST_TRUNCATED__";
@@ -21257,6 +21578,215 @@ var SandboxChannelAService = class {
21257
21578
  async detectRepos() {
21258
21579
  return (await this.detectReposDetailed()).repos;
21259
21580
  }
21581
+ // ═════════════════════════ Code search (worker-only) ═══════════════════════
21582
+ /**
21583
+ * Run ripgrep read-only in the workspace root for the Jev `code_search` tool.
21584
+ * Arguments are checked against a closed allowlist (no `--pre`, `-z` or other
21585
+ * flags that run programs), so the command is provably read-only and skips
21586
+ * durable mutation admission. stdout is capped at `maxBytes`, gzip+base64
21587
+ * framed so providers that drop newlines or retain limited output cannot
21588
+ * corrupt it, and bounded by a wall-clock watchdog (not GNU `timeout`, which
21589
+ * stock macOS lacks). Resolves `available: false` when `rg` is not installed,
21590
+ * and throws when the box could not store the output whole (a full
21591
+ * temporary directory) rather than returning a prefix as complete.
21592
+ */
21593
+ async codeSearchRipgrep(args, options) {
21594
+ const argv = validateCodeSearchRipgrepArgs(args, this.workspaceRoot);
21595
+ const maxBytes = Math.max(1, Math.min(CODE_SEARCH_RG_MAX_BYTES, Math.floor(options.maxBytes)));
21596
+ const maxTransferBytes = Math.max(
21597
+ CODE_SEARCH_RG_CHUNK_BYTES,
21598
+ Math.min(
21599
+ CODE_SEARCH_RG_MAX_TRANSFER_BYTES,
21600
+ Math.floor(options.maxTransferBytes ?? CODE_SEARCH_RG_MAX_TRANSFER_BYTES)
21601
+ )
21602
+ );
21603
+ const seconds = Math.max(1, Math.min(120, Math.ceil(options.timeoutMs / 1e3)));
21604
+ const script = [
21605
+ // Remove output a previous call could not fetch (worker gone mid-transfer).
21606
+ // The trailing slash makes find enter a symlinked /tmp, as on macOS.
21607
+ `find "\${TMPDIR:-/tmp}/" -maxdepth 1 -name 'opengeni-code-search.*' -mmin +15 -exec rm -f {} + 2>/dev/null`,
21608
+ 'gz_file=$(mktemp "${TMPDIR:-/tmp}/opengeni-code-search.XXXXXX") || exit 70',
21609
+ 'status_file="${gz_file}.status"',
21610
+ 'timeout_file="${gz_file}.timed-out"',
21611
+ "keep_gz=",
21612
+ "search_pid=",
21613
+ "watchdog_pid=",
21614
+ 'cleanup() { if [ -n "$search_pid" ]; then kill -TERM -- "-$search_pid" 2>/dev/null || kill "$search_pid" 2>/dev/null || true; fi; if [ -n "$watchdog_pid" ]; then kill "$watchdog_pid" 2>/dev/null || true; fi; rm -f "$status_file" "$timeout_file"; [ -n "$keep_gz" ] || rm -f "$gz_file"; }',
21615
+ "abort() { trap - EXIT; keep_gz=; cleanup; exit 143; }",
21616
+ "trap cleanup EXIT",
21617
+ "trap abort HUP INT TERM",
21618
+ `if ! command -v rg >/dev/null 2>&1; then printf '${CODE_SEARCH_RG_END}127:0__'; exit 0; fi`,
21619
+ // Job control gives the pipeline its own process group, so the watchdog
21620
+ // and cleanup stop ripgrep itself rather than only the subshell. Output is
21621
+ // compressed once, straight into the kept file: providers retain only
21622
+ // about 1 MiB per output stream, and later chunks are fetched by name.
21623
+ // That TERM stops only ripgrep and head. The subshell and gzip ignore it
21624
+ // (bash 3.2 runs a trap before the pipeline ends), so a stopped search
21625
+ // still stores a whole member and records every stage's status.
21626
+ "set -m",
21627
+ `( trap '' TERM; ( trap - TERM; exec rg ${argv.map(shellQuote3).join(" ")} ) 2>/dev/null | ( trap - TERM; exec head -c ${maxBytes + 1} ) | gzip -c > "$gz_file"; printf '%s %s %s' "\${PIPESTATUS[0]}" "\${PIPESTATUS[1]}" "\${PIPESTATUS[2]}" > "$status_file" ) </dev/null >/dev/null 2>&1 &`,
21628
+ "search_pid=$!",
21629
+ `(sleeper_pid=; stop_watchdog() { if [ -n "$sleeper_pid" ]; then kill "$sleeper_pid" 2>/dev/null || true; wait "$sleeper_pid" 2>/dev/null || true; fi; exit 0; }; trap stop_watchdog HUP INT TERM; sleep ${seconds} & sleeper_pid=$!; wait "$sleeper_pid"; sleeper_pid=; if kill -TERM -- "-$search_pid" 2>/dev/null; then : > "$timeout_file"; fi) </dev/null >/dev/null 2>&1 &`,
21630
+ "watchdog_pid=$!",
21631
+ 'wait "$search_pid" 2>/dev/null',
21632
+ "search_pid=",
21633
+ 'kill "$watchdog_pid" 2>/dev/null || true',
21634
+ 'wait "$watchdog_pid" 2>/dev/null || true',
21635
+ "watchdog_pid=",
21636
+ "set +m",
21637
+ "rg_status= head_status= gzip_status=",
21638
+ 'if [ -f "$status_file" ]; then read -r rg_status head_status gzip_status < "$status_file"; fi',
21639
+ '[ -n "$rg_status" ] || rg_status=125',
21640
+ "timed_out=0",
21641
+ 'if [ -f "$timeout_file" ]; then timed_out=1; fi',
21642
+ // A full temporary directory cuts the member without a word, so decode it
21643
+ // end to end: that yields the raw size and fails on a cut or corrupt member.
21644
+ "stored=0",
21645
+ `if raw_size=$(set -o pipefail; gzip -dc < "$gz_file" 2>/dev/null | wc -c | tr -d ' ') && [ "$head_status" = 0 ] && [ "$gzip_status" = 0 ]; then stored=1; fi`,
21646
+ '[ -n "$raw_size" ] || raw_size=0',
21647
+ `gz_size=$(wc -c < "$gz_file" | tr -d ' ')`,
21648
+ '[ -n "$gz_size" ] || gz_size=0',
21649
+ "token=-",
21650
+ // The worker fails an unstored search that did not time out, so only
21651
+ // keep output it will fetch.
21652
+ `if [ "$gz_size" -gt ${CODE_SEARCH_RG_CHUNK_BYTES} ] && { [ "$stored" = 1 ] || [ "$timed_out" = 1 ]; }; then keep_gz=1; token=$(basename "$gz_file"); fi`,
21653
+ `printf '${CODE_SEARCH_RG_BEGIN}'`,
21654
+ `head -c ${CODE_SEARCH_RG_CHUNK_BYTES} "$gz_file" | base64 | tr -d '\\r\\n'`,
21655
+ `printf '${CODE_SEARCH_RG_END}%s:%s:%s:%s:%s:%s__' "$rg_status" "$timed_out" "$gz_size" "$token" "$raw_size" "$stored"`
21656
+ ].join("\n");
21657
+ const { stdout } = await this.runReadOnly({
21658
+ cmd: internalBashCommand(script),
21659
+ workdir: this.providerWorkspaceRoot(),
21660
+ yieldTimeMs: (seconds + 15) * 1e3,
21661
+ maxOutputTokens: CODE_SEARCH_RG_FRAME_CHARS
21662
+ });
21663
+ const trailer = CODE_SEARCH_RG_TRAILER.exec(stdout);
21664
+ if (!trailer) {
21665
+ throw new ChannelAUnavailableError("code search did not complete in this workspace");
21666
+ }
21667
+ const exitCode = Number.parseInt(trailer[1], 10);
21668
+ if (exitCode === 127) {
21669
+ return { available: false, stdout: "", exitCode: null, truncated: false, timedOut: false };
21670
+ }
21671
+ if (trailer[3] === void 0 || trailer[5] === void 0) {
21672
+ throw new ChannelAUnavailableError("code search output trailer is malformed");
21673
+ }
21674
+ const timedOut = trailer[2] === "1";
21675
+ if (!timedOut && exitCode === 125) {
21676
+ throw new ChannelAUnavailableError(
21677
+ "code search did not record its status on this machine; its temporary directory may be full"
21678
+ );
21679
+ }
21680
+ if (!timedOut && trailer[6] !== "1") {
21681
+ throw new ChannelAUnavailableError(CODE_SEARCH_RG_STORE_FAILED);
21682
+ }
21683
+ const first = decodeCodeSearchChunk(stdout, trailer.index);
21684
+ const reportedSize = Number.parseInt(trailer[3], 10);
21685
+ const rawSize = Number.parseInt(trailer[5], 10);
21686
+ const token = trailer[4] === "-" ? null : trailer[4];
21687
+ const parts = [first];
21688
+ let fetched = first.length;
21689
+ if (token !== null && reportedSize > fetched) {
21690
+ if (!CODE_SEARCH_RG_TOKEN.test(token)) {
21691
+ throw new ChannelAUnavailableError("code search output frame is malformed");
21692
+ }
21693
+ const target = Math.min(reportedSize, maxTransferBytes);
21694
+ const maxCalls = Math.ceil(maxTransferBytes / CODE_SEARCH_RG_CHUNK_BYTES);
21695
+ for (let call = 0; call < maxCalls && fetched < target; call++) {
21696
+ const length = Math.min(CODE_SEARCH_RG_CHUNK_BYTES, target - fetched);
21697
+ const chunk = await this.codeSearchRipgrepChunk(
21698
+ token,
21699
+ fetched,
21700
+ length,
21701
+ fetched + length >= target
21702
+ );
21703
+ if (chunk === null) break;
21704
+ parts.push(chunk);
21705
+ fetched += chunk.length;
21706
+ if (chunk.length < length) break;
21707
+ }
21708
+ }
21709
+ const transferCut = fetched < reportedSize;
21710
+ const compressed = Buffer.concat(parts);
21711
+ const raw = compressed.length ? await gunzipCodeSearchPrefix(compressed, maxBytes + 1) : Buffer.alloc(0);
21712
+ const rawCut = raw.length > maxBytes;
21713
+ const sizeMismatch = !rawCut && !transferCut && !timedOut && raw.length !== rawSize;
21714
+ const truncated = rawCut || transferCut || sizeMismatch;
21715
+ let text = (rawCut ? raw.subarray(0, maxBytes) : raw).toString("utf8");
21716
+ if (truncated || timedOut) {
21717
+ const lastNewline = text.lastIndexOf("\n");
21718
+ text = lastNewline >= 0 ? text.slice(0, lastNewline + 1) : "";
21719
+ }
21720
+ return {
21721
+ available: true,
21722
+ stdout: text,
21723
+ exitCode: timedOut ? null : exitCode,
21724
+ truncated,
21725
+ timedOut
21726
+ };
21727
+ }
21728
+ /**
21729
+ * Fetch one chunk of compressed ripgrep output kept on the box by a previous
21730
+ * codeSearchRipgrep call. The last fetch deletes the file. Null when the
21731
+ * file is gone.
21732
+ */
21733
+ async codeSearchRipgrepChunk(token, offset, length, last) {
21734
+ const script = [
21735
+ 'f="${TMPDIR:-/tmp}/$1"',
21736
+ `if [ ! -f "$f" ]; then printf '${CODE_SEARCH_RG_END}0:0:0:missing__'; exit 0; fi`,
21737
+ `printf '${CODE_SEARCH_RG_BEGIN}'`,
21738
+ `tail -c +"$2" "$f" | head -c "$3" | base64 | tr -d '\\r\\n'`,
21739
+ `printf '${CODE_SEARCH_RG_END}0:0:0:-__'`,
21740
+ 'if [ "$4" = 1 ]; then rm -f "$f"; fi'
21741
+ ].join("\n");
21742
+ const { stdout } = await this.runReadOnly({
21743
+ cmd: `${internalBashCommand(script)} opengeni-code-search ${shellQuote3(token)} ${offset + 1} ${length} ${last ? 1 : 0}`,
21744
+ workdir: this.providerWorkspaceRoot(),
21745
+ yieldTimeMs: 3e4,
21746
+ maxOutputTokens: CODE_SEARCH_RG_FRAME_CHARS
21747
+ });
21748
+ const trailer = CODE_SEARCH_RG_TRAILER.exec(stdout);
21749
+ if (!trailer) {
21750
+ throw new ChannelAUnavailableError("code search did not complete in this workspace");
21751
+ }
21752
+ if (trailer[4] === "missing") return null;
21753
+ const chunk = decodeCodeSearchChunk(stdout, trailer.index);
21754
+ if (chunk.length > length) {
21755
+ throw new ChannelAUnavailableError("code search output frame is malformed");
21756
+ }
21757
+ return chunk;
21758
+ }
21759
+ /** Classify workspace-relative paths for `code_search` path filters. */
21760
+ async codeSearchPathKinds(paths) {
21761
+ const checked = paths.map((path) => {
21762
+ if (path.startsWith("-")) throw new ChannelAValidationError(`invalid path: ${path}`);
21763
+ return assertSafeRelPathOrRoot(path, this.workspaceRoot) || ".";
21764
+ });
21765
+ if (checked.length === 0) return {};
21766
+ const script = [
21767
+ `printf '${CODE_SEARCH_KINDS_BEGIN}'`,
21768
+ 'for p in "$@"; do if [ -d "$p" ]; then printf d; elif [ -e "$p" ]; then printf f; else printf m; fi; done',
21769
+ `printf '${CODE_SEARCH_KINDS_END}'`
21770
+ ].join("\n");
21771
+ const { stdout } = await this.runReadOnly({
21772
+ cmd: `${internalBashCommand(script)} opengeni-code-search ${checked.map(shellQuote3).join(" ")}`,
21773
+ workdir: this.providerWorkspaceRoot(),
21774
+ yieldTimeMs: 2e4,
21775
+ maxOutputTokens: 4096
21776
+ });
21777
+ const match = new RegExp(`${CODE_SEARCH_KINDS_BEGIN}([dfm]*)${CODE_SEARCH_KINDS_END}`).exec(
21778
+ stdout
21779
+ );
21780
+ if (!match || match[1].length !== checked.length) {
21781
+ throw new ChannelAUnavailableError("code search path check did not complete");
21782
+ }
21783
+ const kinds = {};
21784
+ paths.forEach((path, index) => {
21785
+ const code = match[1][index];
21786
+ kinds[path] = code === "d" ? "directory" : code === "f" ? "file" : "missing";
21787
+ });
21788
+ return kinds;
21789
+ }
21260
21790
  // ════════════════════════ Terminal exec + PTY (A2) ════════════════════════
21261
21791
  /** Run a bounded command to physical completion and return buffered output.
21262
21792
  * A deadline cancels the exact provider operation, proves its process group
@@ -22716,183 +23246,6 @@ var ModalCommandControl = class _ModalCommandControl {
22716
23246
  }
22717
23247
  };
22718
23248
 
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
23249
  // src/sandbox/providers/modal-command-control.ts
22897
23250
  var ModalCommandControl2 = class _ModalCommandControl {
22898
23251
  constructor(client, sandboxIdentity, root, environment) {
@@ -23063,7 +23416,8 @@ var ModalCommandControl2 = class _ModalCommandControl {
23063
23416
  )
23064
23417
  );
23065
23418
  } catch (error) {
23066
- if (!supervision || error instanceof ModalCommandStartRejectedError) throw error;
23419
+ if (!supervision || error instanceof ModalCommandStartRejectedError || error instanceof ModalCommandStartPreDispatchUnavailableError)
23420
+ throw error;
23067
23421
  }
23068
23422
  return command;
23069
23423
  }
@@ -23329,8 +23683,6 @@ function installModalListDirCompatibility(session) {
23329
23683
  }
23330
23684
  var MODAL_EXEC_STDIN_WRITE_PATH = "/modal.task_command_router.TaskCommandRouter/TaskExecStdinWrite";
23331
23685
  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
23686
  var MODAL_TASK_EXEC_START_ERROR_MAX_DEPTH = 8;
23335
23687
  var MODAL_TASK_EXEC_START_ERROR_MAX_NODES = 64;
23336
23688
  var MODAL_TASK_EXEC_START_ERROR_MAX_AGGREGATE_ERRORS = 32;
@@ -23352,10 +23704,7 @@ function hasContradictoryModalHttpStatus(record) {
23352
23704
  }
23353
23705
  return values.some((value) => modalHttpStatus(value) !== null);
23354
23706
  }
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) {
23707
+ function isModalTaskExecStartPreDispatchUnavailableError(error) {
23359
23708
  const pending = [{ depth: 0, value: error }];
23360
23709
  const seen = /* @__PURE__ */ new WeakSet();
23361
23710
  let inspected = 0;
@@ -23372,7 +23721,12 @@ function isModalTaskExecStartDnsResolutionError(error) {
23372
23721
  let nested;
23373
23722
  try {
23374
23723
  const record = current.value;
23724
+ if (isRoutingMutationOutcomeUnknownError(current.value)) return false;
23375
23725
  if (hasContradictoryModalHttpStatus(record)) return false;
23726
+ if (current.value instanceof ModalCommandStartPreDispatchUnavailableError) {
23727
+ matchingLeaves += 1;
23728
+ continue;
23729
+ }
23376
23730
  nested = [];
23377
23731
  for (const key of ["cause", "error"]) {
23378
23732
  const value = record[key];
@@ -23385,11 +23739,7 @@ function isModalTaskExecStartDnsResolutionError(error) {
23385
23739
  }
23386
23740
  nested.push(...errors);
23387
23741
  }
23388
- if (nested.length === 0) {
23389
- if (!isModalTaskExecStartDnsResolutionLeaf(record)) return false;
23390
- matchingLeaves += 1;
23391
- continue;
23392
- }
23742
+ if (nested.length === 0) return false;
23393
23743
  } catch {
23394
23744
  return false;
23395
23745
  }
@@ -33049,6 +33399,7 @@ function shellQuote5(value) {
33049
33399
  // src/sandbox/browser-control-client.ts
33050
33400
  import { createHash as createHash7, randomUUID as randomUUID8 } from "crypto";
33051
33401
  import { posix as posixPath2 } from "path";
33402
+ import { parseBrowserFrameMetadata } from "@opengeni/sdk";
33052
33403
  import {
33053
33404
  BROWSER_CONTROL_MAX_JSON_BYTES,
33054
33405
  BROWSER_CONTROL_PORT as BROWSER_CONTROL_PORT2,
@@ -33063,6 +33414,8 @@ import {
33063
33414
  BrowserDownloadExportReceipt,
33064
33415
  BrowserDownloadExportRequest,
33065
33416
  BrowserDownloadListResponse,
33417
+ BrowserDomReadRequest,
33418
+ BrowserDomReadResponse,
33066
33419
  BrowserExternalAuthCommand,
33067
33420
  BrowserExternalAuthResult,
33068
33421
  BrowserObservation,
@@ -33070,6 +33423,7 @@ import {
33070
33423
  BrowserProtectedAuthFillReceipt,
33071
33424
  BrowserRevisionMaterialization,
33072
33425
  BrowserTarget,
33426
+ BrowserTargetState,
33073
33427
  BrowserWorkspaceFileStageRequest,
33074
33428
  BrowserWorkspaceFileStageResponse,
33075
33429
  ComputerActionCommand,
@@ -33536,7 +33890,10 @@ var BrowserControlClient = class {
33536
33890
  return await this.requestJson(input);
33537
33891
  }
33538
33892
  async requestBytesForSession(input) {
33539
- return await this.requestBytes(input);
33893
+ return await this.requestBytes({ ...input, surface: "computer" });
33894
+ }
33895
+ async requestBrowserBytesForSession(input) {
33896
+ return await this.requestBytes({ ...input, surface: "browser" });
33540
33897
  }
33541
33898
  async requestJson(input, retryNativeEndpoint = true) {
33542
33899
  const requireHostFetch = this.session.requireHostFetchController === true;
@@ -33772,10 +34129,10 @@ var BrowserControlClient = class {
33772
34129
  const data = await readBytes(
33773
34130
  this.session,
33774
34131
  responsePath,
33775
- COMPUTER_SCREENSHOT_MAX_BYTES,
34132
+ input.surface === "browser" ? 24 * 1024 * 1024 : COMPUTER_SCREENSHOT_MAX_BYTES,
33776
34133
  timeoutMs
33777
34134
  );
33778
- return computerControlFrame(data, headers, input.expectedFrameEvidence);
34135
+ return controllerImageFrame(data, headers, input);
33779
34136
  } catch (error) {
33780
34137
  if (error instanceof BrowserControlRequestError || error instanceof BrowserControlProtocolError || error instanceof RangeError) {
33781
34138
  throw error;
@@ -33923,6 +34280,75 @@ var BrowserControlSessionClient = class {
33923
34280
  })
33924
34281
  );
33925
34282
  }
34283
+ async targetState(targetId) {
34284
+ let state;
34285
+ try {
34286
+ state = BrowserTargetState.parse(
34287
+ await this.parent.requestForSession({
34288
+ method: "GET",
34289
+ path: this.targetPath(targetId, "state"),
34290
+ token: this.viewToken
34291
+ })
34292
+ );
34293
+ } catch (error) {
34294
+ if (!(error instanceof BrowserControlRequestError) || error.status !== 404 || error.error.code !== "resource_not_found" || error.error.message !== "route not found") {
34295
+ throw error;
34296
+ }
34297
+ const observation = await this.observe(targetId);
34298
+ state = BrowserTargetState.parse({
34299
+ browserSessionId: observation.browserSessionId,
34300
+ controllerGeneration: observation.target.controllerGeneration,
34301
+ targetId: observation.target.id,
34302
+ targetGeneration: observation.target.targetGeneration,
34303
+ documentGeneration: observation.target.documentGeneration,
34304
+ frameId: observation.frameId
34305
+ });
34306
+ }
34307
+ if (state.browserSessionId !== this.reference.browserSessionId || state.controllerGeneration !== this.reference.controllerGeneration || state.targetId !== targetId) {
34308
+ throw new BrowserControlProtocolError("browser target state belongs to another binding");
34309
+ }
34310
+ return state;
34311
+ }
34312
+ async readDom(targetId, requestInput) {
34313
+ const request = BrowserDomReadRequest.parse(requestInput);
34314
+ const result = BrowserDomReadResponse.parse(
34315
+ await this.parent.requestForSession({
34316
+ method: "POST",
34317
+ path: this.targetPath(targetId, "dom-read"),
34318
+ token: this.viewToken,
34319
+ body: request
34320
+ })
34321
+ );
34322
+ 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) {
34323
+ throw new BrowserControlProtocolError("browser DOM read belongs to another binding");
34324
+ }
34325
+ return result;
34326
+ }
34327
+ async capture(targetId, options = {}) {
34328
+ const query = new URLSearchParams({
34329
+ format: options.format ?? "jpeg",
34330
+ quality: String(boundedInteger(options.quality ?? 55, 1, 100, "browser screenshot quality"))
34331
+ });
34332
+ if (options.format !== void 0 && options.format !== "jpeg" && options.format !== "png") {
34333
+ throw new RangeError("browser screenshot format is invalid");
34334
+ }
34335
+ if (options.fullPage !== void 0) {
34336
+ if (typeof options.fullPage !== "boolean") {
34337
+ throw new RangeError("browser screenshot fullPage is invalid");
34338
+ }
34339
+ query.set("fullPage", String(options.fullPage));
34340
+ }
34341
+ return await this.parent.requestBrowserBytesForSession({
34342
+ method: "GET",
34343
+ path: this.targetPath(targetId, `screenshot?${query}`),
34344
+ token: this.viewToken,
34345
+ expectedFrameEvidence: {
34346
+ browserSessionId: this.reference.browserSessionId,
34347
+ controllerGeneration: this.reference.controllerGeneration,
34348
+ targetId: requireOpaqueId(targetId, "browser target id")
34349
+ }
34350
+ });
34351
+ }
33926
34352
  async readClipboard() {
33927
34353
  return BrowserClipboard.parse(
33928
34354
  await this.parent.requestForSession({
@@ -34256,12 +34682,69 @@ async function requestExposedControllerBytes(endpoint, input, defaultTimeoutMs)
34256
34682
  throw new BrowserControlProtocolError("browser controller image response is invalid");
34257
34683
  }
34258
34684
  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");
34685
+ const maxBytes = input.surface === "browser" ? 24 * 1024 * 1024 : COMPUTER_SCREENSHOT_MAX_BYTES;
34686
+ if (Number.isFinite(declaredLength) && declaredLength > maxBytes) {
34687
+ await response.body?.cancel("frame exceeds its byte bound").catch(() => void 0);
34688
+ throw new RangeError("frame exceeds its byte bound");
34262
34689
  }
34263
- const data = new Uint8Array(await response.arrayBuffer());
34264
- return computerControlFrame(data, response.headers, input.expectedFrameEvidence);
34690
+ const data = await readBoundedFrameResponse(response, maxBytes);
34691
+ return controllerImageFrame(data, response.headers, input);
34692
+ }
34693
+ async function readBoundedFrameResponse(response, maxBytes) {
34694
+ if (!response.body) throw new BrowserControlProtocolError("browser controller image is empty");
34695
+ const reader = response.body.getReader();
34696
+ const chunks = [];
34697
+ let size = 0;
34698
+ try {
34699
+ for (; ; ) {
34700
+ const { done, value } = await reader.read();
34701
+ if (done) break;
34702
+ size += value.byteLength;
34703
+ if (size > maxBytes) {
34704
+ await reader.cancel("frame exceeds its byte bound").catch(() => void 0);
34705
+ throw new RangeError("frame exceeds its byte bound");
34706
+ }
34707
+ chunks.push(value);
34708
+ }
34709
+ } finally {
34710
+ reader.releaseLock();
34711
+ }
34712
+ const data = new Uint8Array(size);
34713
+ let offset = 0;
34714
+ for (const chunk of chunks) {
34715
+ data.set(chunk, offset);
34716
+ offset += chunk.byteLength;
34717
+ }
34718
+ return data;
34719
+ }
34720
+ function controllerImageFrame(data, headers, input) {
34721
+ return input.surface === "browser" ? browserControlFrame(data, headers, input.expectedFrameEvidence) : computerControlFrame(data, headers, input.expectedFrameEvidence);
34722
+ }
34723
+ function browserControlFrame(data, headers, expected) {
34724
+ if (data.byteLength < 1 || data.byteLength > 24 * 1024 * 1024) {
34725
+ throw new RangeError("browser frame exceeds its byte bound");
34726
+ }
34727
+ const get = (name) => headers.get(name.toLowerCase()) ?? null;
34728
+ const mediaType = get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
34729
+ if (mediaType !== "image/jpeg" && mediaType !== "image/png") {
34730
+ throw new BrowserControlProtocolError("browser frame media type is invalid");
34731
+ }
34732
+ const metadataHeader = get("x-opengeni-browser-frame");
34733
+ if (!metadataHeader || metadataHeader.length > 64 * 1024 || !/^[A-Za-z0-9_-]+$/u.test(metadataHeader)) {
34734
+ throw new BrowserControlProtocolError("browser frame metadata is invalid");
34735
+ }
34736
+ let metadata;
34737
+ try {
34738
+ metadata = parseBrowserFrameMetadata(
34739
+ JSON.parse(Buffer.from(metadataHeader, "base64url").toString("utf8"))
34740
+ );
34741
+ } catch {
34742
+ throw new BrowserControlProtocolError("browser frame metadata is invalid");
34743
+ }
34744
+ if (metadata.browserSessionId !== expected.browserSessionId || metadata.controllerGeneration !== expected.controllerGeneration || metadata.targetId !== expected.targetId || metadata.mediaType !== mediaType) {
34745
+ throw new BrowserControlProtocolError("browser frame evidence does not match its request");
34746
+ }
34747
+ return { data, mediaType, metadataHeader, metadata };
34265
34748
  }
34266
34749
  function computerControlFrame(data, headers, expected) {
34267
34750
  if (data.byteLength < 1 || data.byteLength > COMPUTER_SCREENSHOT_MAX_BYTES) {
@@ -34936,7 +35419,7 @@ async function readText(session, path, maxBytes, timeoutMs) {
34936
35419
  }
34937
35420
  async function readBytes(session, path, maxBytes, timeoutMs) {
34938
35421
  const privatePath = absolutePrivatePath(path, "browser private binary response path");
34939
- if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > COMPUTER_SCREENSHOT_MAX_BYTES) {
35422
+ if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > Math.max(24 * 1024 * 1024, COMPUTER_SCREENSHOT_MAX_BYTES)) {
34940
35423
  throw new RangeError("browser private binary response limit is invalid");
34941
35424
  }
34942
35425
  const sizeMarker = `OPENGENI_BROWSER_PRIVATE_SIZE_${randomUUID8()}`;
@@ -34955,7 +35438,7 @@ async function readBytes(session, path, maxBytes, timeoutMs) {
34955
35438
  "browser private binary response size"
34956
35439
  );
34957
35440
  if (size < 1 || size > maxBytes) {
34958
- throw new RangeError("computer frame exceeds its byte bound");
35441
+ throw new RangeError("frame exceeds its byte bound");
34959
35442
  }
34960
35443
  const chunks = [];
34961
35444
  for (let offset = 0; offset < size; offset += PRIVATE_READ_CHUNK_BYTES) {
@@ -38353,6 +38836,8 @@ export {
38353
38836
  ChannelAUnsupportedError,
38354
38837
  ChannelAPartialMutationError,
38355
38838
  REPOSITORY_DISCOVERY_LIMIT,
38839
+ CODE_SEARCH_RG_MAX_BYTES,
38840
+ validateCodeSearchRipgrepArgs,
38356
38841
  SandboxChannelAService,
38357
38842
  stripExecBanner,
38358
38843
  isDefinitePathNotFoundError,
@@ -38388,7 +38873,7 @@ export {
38388
38873
  assertDescriptorRegistryInvariants,
38389
38874
  modalSandboxAttributionEnvironment,
38390
38875
  modalSandboxAttributionTags,
38391
- isModalTaskExecStartDnsResolutionError,
38876
+ isModalTaskExecStartPreDispatchUnavailableError,
38392
38877
  ensureModalRegistryImage,
38393
38878
  resolveModalCheckpointProviderBindingForSession,
38394
38879
  modalSessionMatchesCheckpointProviderBinding,
@@ -38571,4 +39056,4 @@ export {
38571
39056
  collectSandboxEnvironment2 as collectSandboxEnvironment,
38572
39057
  parseExposedPorts2 as parseExposedPorts
38573
39058
  };
38574
- //# sourceMappingURL=chunk-J5AR5XAJ.js.map
39059
+ //# sourceMappingURL=chunk-FAFZCSN7.js.map