@opengeni/runtime 3.0.0-canary.1 → 3.0.1-canary.1

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.
@@ -15860,6 +15860,36 @@ function admittedProviderCommandHandle() {
15860
15860
  return admission.getStore();
15861
15861
  }
15862
15862
 
15863
+ // src/sandbox/materialization-verification-error.ts
15864
+ var EXPLANATIONS = {
15865
+ path_not_visible: "the provider could not see the destination path",
15866
+ command_failed: "the visibility-check command exited unsuccessfully",
15867
+ command_pending: "the visibility-check command was still running; path visibility is unconfirmed",
15868
+ invalid_response: "the visibility check returned no valid success confirmation",
15869
+ command_error: "the provider could not complete the visibility-check command"
15870
+ };
15871
+ var SandboxMaterializationVerificationError = class extends Error {
15872
+ constructor(diagnostic, options) {
15873
+ super(
15874
+ `Sandbox materialization verification failed: ${EXPLANATIONS[diagnostic.reason]}: ${diagnostic.path}`,
15875
+ options
15876
+ );
15877
+ this.diagnostic = diagnostic;
15878
+ this.name = "SandboxMaterializationVerificationError";
15879
+ }
15880
+ code = "sandbox_materialization_verification_failed";
15881
+ };
15882
+ var providerDiagnostics = /* @__PURE__ */ new WeakMap();
15883
+ function retainMaterializationVerificationDiagnostic(error, diagnostic) {
15884
+ if (error !== null && (typeof error === "object" || typeof error === "function")) {
15885
+ providerDiagnostics.set(error, diagnostic);
15886
+ }
15887
+ }
15888
+ function materializationVerificationDiagnostic(error) {
15889
+ if (error instanceof SandboxMaterializationVerificationError) return error.diagnostic;
15890
+ return error !== null && (typeof error === "object" || typeof error === "function") ? providerDiagnostics.get(error) : void 0;
15891
+ }
15892
+
15863
15893
  // src/sandbox/routing/routing-session.ts
15864
15894
  import { CAPABILITY_DESCRIPTORS as CAPABILITY_DESCRIPTORS2 } from "@opengeni/contracts";
15865
15895
 
@@ -17305,11 +17335,13 @@ var RoutingSandboxSession = class {
17305
17335
  async invokeProviderOperation(op, backend, fn, onCaptureWait) {
17306
17336
  const startedAt = performance.now();
17307
17337
  let outcome = "failed";
17338
+ let materializationFailureReason;
17308
17339
  try {
17309
17340
  const result = await withSandboxProviderOperation(backend.session, fn, onCaptureWait);
17310
17341
  outcome = "ok";
17311
17342
  return result;
17312
17343
  } catch (error) {
17344
+ materializationFailureReason = materializationVerificationDiagnostic(error)?.reason;
17313
17345
  if ((op === "readFile" || op === "listDir" || op === "pathExists" || op === "viewImage") && isDefinitePathNotFoundError(error)) {
17314
17346
  outcome = "not_found";
17315
17347
  }
@@ -17320,7 +17352,8 @@ var RoutingSandboxSession = class {
17320
17352
  backend: backend.kind,
17321
17353
  op,
17322
17354
  outcome,
17323
- durationMs: Math.max(0, performance.now() - startedAt)
17355
+ durationMs: Math.max(0, performance.now() - startedAt),
17356
+ ...materializationFailureReason ? { materializationFailureReason } : {}
17324
17357
  });
17325
17358
  } catch {
17326
17359
  }
@@ -17793,6 +17826,9 @@ var RoutingSandboxSession = class {
17793
17826
  };
17794
17827
  var MATERIALIZED_PATH_MARKER = "__OPENGENI_MATERIALIZED_PATH_VISIBLE__";
17795
17828
  async function assertProviderCanSeeMaterializedPath(session, path) {
17829
+ if (session.verifyMaterializedPath) {
17830
+ return session.verifyMaterializedPath(path, providerManifestRoot(session) ?? "/workspace");
17831
+ }
17796
17832
  const command = `test -e ${shellSingleQuote(path)} && printf %s ${shellSingleQuote(
17797
17833
  MATERIALIZED_PATH_MARKER
17798
17834
  )}`;
@@ -17804,18 +17840,56 @@ async function assertProviderCanSeeMaterializedPath(session, path) {
17804
17840
  tty: false
17805
17841
  };
17806
17842
  let output;
17807
- if (session.execCommand) {
17808
- output = await session.execCommand(args);
17809
- } else if (session.exec) {
17810
- output = formatExecResult(await session.exec(args));
17811
- } else {
17843
+ let result;
17844
+ if (!session.execCommand && !session.exec) {
17812
17845
  throw new RoutingUnsupportedError("materializeEntry.verify", "unknown");
17813
17846
  }
17814
- if (!output.includes(MATERIALIZED_PATH_MARKER)) {
17815
- throw new Error(
17816
- `Sandbox materialization completed but the provider cannot read the destination path: ${path}`
17817
- );
17847
+ try {
17848
+ result = session.execCommand ? await session.execCommand(args) : await session.exec(args);
17849
+ } catch (cause) {
17850
+ retainMaterializationVerificationDiagnostic(cause, {
17851
+ reason: "command_error",
17852
+ path,
17853
+ workdir: args.workdir,
17854
+ command,
17855
+ output: null,
17856
+ exitCode: null,
17857
+ providerSessionId: null,
17858
+ causeMessage: cause instanceof Error ? cause.message : String(cause)
17859
+ });
17860
+ throw cause;
17861
+ }
17862
+ try {
17863
+ output = formatExecResult(result);
17864
+ } catch (cause) {
17865
+ const record = result && typeof result === "object" ? result : {};
17866
+ const returnedOutput = [record.output, record.stderr, record.stdout].filter((value) => typeof value === "string").join("\n");
17867
+ throw new SandboxMaterializationVerificationError({
17868
+ reason: "invalid_response",
17869
+ path,
17870
+ workdir: args.workdir,
17871
+ command,
17872
+ output: returnedOutput || null,
17873
+ exitCode: null,
17874
+ providerSessionId: null,
17875
+ causeMessage: cause instanceof Error ? cause.message : String(cause)
17876
+ });
17877
+ }
17878
+ const status = parseExecResponseBanner(output);
17879
+ const markerPresent = stripExecBanner(output).includes(MATERIALIZED_PATH_MARKER);
17880
+ if (markerPresent && (status.kind === "absent" || status.kind === "exited" && status.exitCode === 0)) {
17881
+ return;
17818
17882
  }
17883
+ const reason = status.kind === "running" ? "command_pending" : status.kind === "exited" && status.exitCode === 1 ? "path_not_visible" : status.kind === "exited" && status.exitCode !== 0 ? "command_failed" : "invalid_response";
17884
+ throw new SandboxMaterializationVerificationError({
17885
+ reason,
17886
+ path,
17887
+ workdir: args.workdir,
17888
+ command,
17889
+ output,
17890
+ exitCode: status.kind === "exited" ? status.exitCode : null,
17891
+ providerSessionId: status.kind === "running" ? status.sessionId : null
17892
+ });
17819
17893
  }
17820
17894
  function providerManifestRoot(session) {
17821
17895
  const root = session.state?.manifest?.root;
@@ -21793,6 +21867,96 @@ function parseUnifiedPatch(patch) {
21793
21867
 
21794
21868
  // src/sandbox/providers/modal-command-session.ts
21795
21869
  import { randomUUID as randomUUID5 } from "crypto";
21870
+
21871
+ // src/sandbox/providers/modal-materialization-verification.ts
21872
+ var MARKER = "__OPENGENI_MATERIALIZED_PATH_VISIBLE__";
21873
+ var OUTPUT_LIMIT = 16 * 1024;
21874
+ async function verifyModalMaterializedPath(control, path, workdir, pending, observationTimeoutMs = 3e4) {
21875
+ const quote = (value) => `'${value.replaceAll("'", `'"'"'`)}'`;
21876
+ const command = `test -e ${quote(path)} && printf %s ${quote(MARKER)}`;
21877
+ const cancellation = new AbortController();
21878
+ const deadlineReason = new Error("Materialization visibility observation deadline exceeded");
21879
+ let providerCommand;
21880
+ let stdout = "";
21881
+ let stderr = "";
21882
+ const diagnostic = (reason, exitCode = null) => ({
21883
+ reason,
21884
+ path,
21885
+ workdir,
21886
+ command,
21887
+ output: (stdout + stderr).slice(0, OUTPUT_LIMIT),
21888
+ exitCode,
21889
+ providerSessionId: null,
21890
+ ...providerCommand ? {
21891
+ providerExecution: {
21892
+ sandboxId: providerCommand.sandboxId,
21893
+ taskId: providerCommand.taskId,
21894
+ execId: providerCommand.execId
21895
+ }
21896
+ } : {}
21897
+ });
21898
+ const timer = setTimeout(() => {
21899
+ cancellation.abort(deadlineReason);
21900
+ }, observationTimeoutMs);
21901
+ timer.unref();
21902
+ pending.add(cancellation);
21903
+ try {
21904
+ providerCommand = await control.start(
21905
+ { cmd: command, workdir, shell: "sh", login: false, tty: false },
21906
+ cancellation.signal
21907
+ );
21908
+ for (; ; ) {
21909
+ cancellation.signal.throwIfAborted();
21910
+ const page = await control.readProbe(providerCommand, 1e3, cancellation);
21911
+ cancellation.signal.throwIfAborted();
21912
+ if (page.command.sandboxId !== providerCommand.sandboxId || page.command.taskId !== providerCommand.taskId || page.command.execId !== providerCommand.execId) {
21913
+ throw new SandboxMaterializationVerificationError(diagnostic("invalid_response"));
21914
+ }
21915
+ providerCommand = page.command;
21916
+ for (const chunk of page.chunks) {
21917
+ if (chunk.stream === "stdout") stdout += chunk.text;
21918
+ else stderr += chunk.text;
21919
+ }
21920
+ if (stdout.length + stderr.length > OUTPUT_LIMIT) {
21921
+ throw new SandboxMaterializationVerificationError(diagnostic("invalid_response"));
21922
+ }
21923
+ if (page.exitCode === null) {
21924
+ await new Promise((resolve6) => setImmediate(resolve6));
21925
+ continue;
21926
+ }
21927
+ if (page.exitCode === 0 && stdout === MARKER) return;
21928
+ throw new SandboxMaterializationVerificationError(
21929
+ diagnostic(
21930
+ page.exitCode === 1 ? "path_not_visible" : page.exitCode === 0 ? "invalid_response" : "command_failed",
21931
+ page.exitCode
21932
+ )
21933
+ );
21934
+ }
21935
+ } catch (error) {
21936
+ if (cancellation.signal.reason === deadlineReason) {
21937
+ throw new SandboxMaterializationVerificationError(
21938
+ {
21939
+ ...diagnostic("command_pending"),
21940
+ causeMessage: "Observation deadline exceeded; provider process completion is unconfirmed"
21941
+ },
21942
+ { cause: error }
21943
+ );
21944
+ }
21945
+ if (!(error instanceof SandboxMaterializationVerificationError)) {
21946
+ retainMaterializationVerificationDiagnostic(error, {
21947
+ ...diagnostic("command_error"),
21948
+ causeMessage: error instanceof Error ? error.message : String(error)
21949
+ });
21950
+ }
21951
+ throw error;
21952
+ } finally {
21953
+ cancellation.abort(new Error("Materialization visibility observation finished"));
21954
+ clearTimeout(timer);
21955
+ pending.delete(cancellation);
21956
+ }
21957
+ }
21958
+
21959
+ // src/sandbox/providers/modal-command-session.ts
21796
21960
  function sameExecution(a, b) {
21797
21961
  return a.sandboxId === b.sandboxId && a.taskId === b.taskId && a.execId === b.execId && Boolean(a.pty) === Boolean(b.pty);
21798
21962
  }
@@ -21802,6 +21966,7 @@ function installModalCommandSession(session, control) {
21802
21966
  const originalWrite = session.writeStdin?.bind(session);
21803
21967
  const cancelLegacyStart = session.cancelPendingExecCommand?.bind(session);
21804
21968
  const pendingStarts = /* @__PURE__ */ new Set();
21969
+ session.verifyMaterializedPath = (path, workdir) => verifyModalMaterializedPath(control, path, workdir, pendingStarts);
21805
21970
  const entries = /* @__PURE__ */ new Map();
21806
21971
  const setupHandles = /* @__PURE__ */ new Map();
21807
21972
  let nextSetupHandle = MAX_PROVIDER_COMMAND_HANDLE + 1;
@@ -22074,49 +22239,76 @@ var ModalCommandControl = class _ModalCommandControl {
22074
22239
  };
22075
22240
  }
22076
22241
  async read(command, yieldTimeMs, signal) {
22242
+ return this.readOutput(command, yieldTimeMs, signal);
22243
+ }
22244
+ /** Fixed internal probes own their cancellation controller and must drain
22245
+ * both reads before relinquishing the surrounding provider-operation gate.
22246
+ * Retained-command readers keep their existing signal/receipt contract.
22247
+ */
22248
+ async readProbe(command, yieldTimeMs, cancellation) {
22249
+ return this.readOutput(
22250
+ command,
22251
+ yieldTimeMs,
22252
+ cancellation.signal,
22253
+ (error) => cancellation.abort(error)
22254
+ );
22255
+ }
22256
+ async readOutput(command, yieldTimeMs, signal, cancelSiblings) {
22077
22257
  signal?.throwIfAborted();
22078
22258
  this.assertIdentity(command);
22079
22259
  const next = structuredClone(command);
22080
- const pages = await Promise.all(
22081
- ["stdout", "stderr"].map(async (stream) => {
22082
- const cursor = command.streams[stream];
22083
- if (cursor.exitCode !== null) return null;
22084
- const descriptor = stream === "stdout" ? 1 : 2;
22085
- for await (const batch of this.client.containerExecGetOutput(
22086
- {
22087
- execId: command.execId,
22088
- timeout: Math.max(0, yieldTimeMs) / 1e3,
22089
- lastBatchIndex: cursor.batchIndex,
22090
- fileDescriptor: descriptor,
22091
- getRawBytes: true
22092
- },
22093
- signal ? { signal } : void 0
22094
- )) {
22095
- if (batch.batchIndex <= cursor.batchIndex) continue;
22096
- if (!Number.isSafeInteger(batch.batchIndex))
22097
- throw new Error("Invalid Modal output cursor");
22098
- const terminal = batch.exitCode !== void 0;
22099
- if (terminal && !Number.isSafeInteger(batch.exitCode))
22100
- throw new Error("Invalid Modal exit status");
22101
- const decoded = decodePage(
22102
- cursor.utf8Remainder,
22103
- batch.items.filter((item) => item.fileDescriptor === descriptor).map((item) => item.messageBytes),
22104
- terminal
22105
- );
22106
- next.streams[stream] = {
22107
- batchIndex: batch.batchIndex,
22108
- utf8Remainder: decoded.remainder,
22109
- exitCode: terminal ? batch.exitCode : null
22110
- };
22111
- return {
22112
- stream,
22113
- chunkId: `modal:${command.execId}:${stream}:${cursor.batchIndex}:${batch.batchIndex}`,
22114
- text: decoded.text
22115
- };
22116
- }
22117
- return null;
22260
+ let failure;
22261
+ const reads = ["stdout", "stderr"].map(async (stream) => {
22262
+ const cursor = command.streams[stream];
22263
+ if (cursor.exitCode !== null) return null;
22264
+ const descriptor = stream === "stdout" ? 1 : 2;
22265
+ for await (const batch of this.client.containerExecGetOutput(
22266
+ {
22267
+ execId: command.execId,
22268
+ timeout: Math.max(0, yieldTimeMs) / 1e3,
22269
+ lastBatchIndex: cursor.batchIndex,
22270
+ fileDescriptor: descriptor,
22271
+ getRawBytes: true
22272
+ },
22273
+ signal ? { signal } : void 0
22274
+ )) {
22275
+ if (batch.batchIndex <= cursor.batchIndex) continue;
22276
+ if (!Number.isSafeInteger(batch.batchIndex))
22277
+ throw new Error("Invalid Modal output cursor");
22278
+ const terminal = batch.exitCode !== void 0;
22279
+ if (terminal && !Number.isSafeInteger(batch.exitCode))
22280
+ throw new Error("Invalid Modal exit status");
22281
+ const decoded = decodePage(
22282
+ cursor.utf8Remainder,
22283
+ batch.items.filter((item) => item.fileDescriptor === descriptor).map((item) => item.messageBytes),
22284
+ terminal
22285
+ );
22286
+ next.streams[stream] = {
22287
+ batchIndex: batch.batchIndex,
22288
+ utf8Remainder: decoded.remainder,
22289
+ exitCode: terminal ? batch.exitCode : null
22290
+ };
22291
+ return {
22292
+ stream,
22293
+ chunkId: `modal:${command.execId}:${stream}:${cursor.batchIndex}:${batch.batchIndex}`,
22294
+ text: decoded.text
22295
+ };
22296
+ }
22297
+ return null;
22298
+ }).map(
22299
+ (read) => !cancelSiblings ? read : read.catch((error) => {
22300
+ failure ??= { error };
22301
+ cancelSiblings(error);
22302
+ throw error;
22118
22303
  })
22119
22304
  );
22305
+ const pages = cancelSiblings ? await Promise.allSettled(reads).then((results) => {
22306
+ if (failure) throw failure.error;
22307
+ return results.map((result) => {
22308
+ if (result.status === "rejected") throw result.reason;
22309
+ return result.value;
22310
+ });
22311
+ }) : await Promise.all(reads);
22120
22312
  const stdoutExit = next.streams.stdout.exitCode;
22121
22313
  const stderrExit = next.streams.stderr.exitCode;
22122
22314
  if (stdoutExit !== null && stderrExit !== null && stdoutExit !== stderrExit)
@@ -37040,6 +37232,8 @@ export {
37040
37232
  parseExecBannerSessionId,
37041
37233
  parseExecBannerExitCode,
37042
37234
  isExecSessionLostBanner,
37235
+ SandboxMaterializationVerificationError,
37236
+ materializationVerificationDiagnostic,
37043
37237
  normalizeConnectedMachineWorkspaceRoot,
37044
37238
  isWindowsConnectedMachinePath,
37045
37239
  isConnectedMachineAbsolutePath,
@@ -37293,4 +37487,4 @@ export {
37293
37487
  collectSandboxEnvironment2 as collectSandboxEnvironment,
37294
37488
  parseExposedPorts2 as parseExposedPorts
37295
37489
  };
37296
- //# sourceMappingURL=chunk-46BFUGFL.js.map
37490
+ //# sourceMappingURL=chunk-FQM5VV5D.js.map