@odla-ai/harness 0.11.8 → 0.11.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -833,8 +833,9 @@ import { getgid, getuid } from "process";
833
833
  import { randomUUID } from "crypto";
834
834
  var ARTIFACT_PATH = /^[A-Za-z0-9_@+.,-]+(?:\/[A-Za-z0-9_@+.,-]+)*$/;
835
835
  var PRIVATE_ARTIFACT_PART = /^(?:\.git|\.odla|\.wrangler|\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json)$/i;
836
- function buildRecipeContainerArgs(engine, workspaceDir, recipe2, name = `odla-recipe-${randomUUID().slice(0, 12)}`) {
836
+ function buildRecipeContainerArgs(engine, workspaceDir, recipe2, name = `odla-recipe-${randomUUID().slice(0, 12)}`, dependencies = null) {
837
837
  assertCodeBuildRecipe(recipe2);
838
+ const mounts = dependencies ? [dependencyMount(engine, dependencies)] : [];
838
839
  if (/[,\r\n]/.test(workspaceDir)) throw new TypeError("workspace path contains unsupported mount characters");
839
840
  const uid = typeof getuid === "function" ? getuid() : 1e3;
840
841
  const gid = typeof getgid === "function" ? getgid() : 1e3;
@@ -857,6 +858,7 @@ function buildRecipeContainerArgs(engine, workspaceDir, recipe2, name = `odla-re
857
858
  `--user=${uid}:${gid}`,
858
859
  "--tmpfs=/tmp",
859
860
  `--mount=type=bind,source=${workspaceDir},target=/workspace`,
861
+ ...mounts,
860
862
  "--workdir=/workspace",
861
863
  "--env=CI=1",
862
864
  recipe2.image,
@@ -878,18 +880,28 @@ function buildRecipeContainerArgs(engine, workspaceDir, recipe2, name = `odla-re
878
880
  `--user=${uid}:${gid}`,
879
881
  `--tmpfs=/tmp:rw,noexec,nosuid,nodev,size=${limits.tmpfs}`,
880
882
  `--mount=type=bind,src=${workspaceDir},dst=/workspace`,
883
+ ...mounts,
881
884
  "--workdir=/workspace",
882
885
  "--env=CI=1",
883
886
  recipe2.image,
884
887
  ...recipe2.command
885
888
  ];
886
889
  }
887
- function createContainerRecipeExecutor(engine) {
890
+ var LENDABLE = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage"]);
891
+ function dependencyMount(engine, dependencies) {
892
+ const mountAs = dependencies.mountAs ?? "node_modules";
893
+ if (!dependencies.source.startsWith("/") || /[,\r\n]/.test(dependencies.source)) {
894
+ throw new TypeError("recipe dependency source must be an absolute path without mount separators");
895
+ }
896
+ if (!LENDABLE.has(mountAs)) throw new TypeError(`recipe dependencies must mount at a reserved name, not "${mountAs}"`);
897
+ return engine === "container" ? `--mount=type=bind,source=${dependencies.source},target=/workspace/${mountAs},readonly` : `--mount=type=bind,src=${dependencies.source},dst=/workspace/${mountAs},readonly`;
898
+ }
899
+ function createContainerRecipeExecutor(engine, options = {}) {
888
900
  return {
889
901
  async run(input) {
890
902
  await verifyContainerEngineBoundary(engine);
891
903
  const name = `odla-recipe-${randomUUID().slice(0, 12)}`;
892
- const args = buildRecipeContainerArgs(engine, input.workspaceDir, input.recipe, name);
904
+ const args = buildRecipeContainerArgs(engine, input.workspaceDir, input.recipe, name, options.dependencies ?? null);
893
905
  return execute(engine, args, name, input.recipe, input.signal);
894
906
  }
895
907
  };
@@ -910,6 +922,9 @@ function parseMemory(value) {
910
922
  return Number(match[1]) * scale;
911
923
  }
912
924
  function execute(engine, args, name, recipe2, signal) {
925
+ return runContainerCommand(engine, args, name, { timeoutMs: recipe2.timeoutMs, maxOutputBytes: recipe2.maxOutputBytes }, signal);
926
+ }
927
+ function runContainerCommand(engine, args, name, recipe2, signal) {
913
928
  return new Promise((accept, reject) => {
914
929
  const started = Date.now();
915
930
  const child = spawn2(engine, args, { shell: false, stdio: ["ignore", "pipe", "pipe"] });
@@ -3750,7 +3765,7 @@ var TheseusRuntimeEngine = class {
3750
3765
  this.#checkpoints = new CodeRuntimeCheckpointManager({
3751
3766
  control: options.control,
3752
3767
  recipes: options.recipes,
3753
- recipeExecutor: options.recipeExecutor ?? createContainerRecipeExecutor(options.engine),
3768
+ recipeExecutor: options.recipeExecutor ?? createContainerRecipeExecutor(options.engine, { dependencies: options.recipeDependencies ?? null }),
3754
3769
  fallbackPolicyDigest: this.#buildPolicyDigest,
3755
3770
  event: (command, event, refs) => this.#event(command, event, refs)
3756
3771
  });
@@ -3858,7 +3873,7 @@ var TheseusRuntimeEngine = class {
3858
3873
  active.done = startGoalPursuit({
3859
3874
  spec,
3860
3875
  recipes: active.recipes,
3861
- recipeExecutor: this.options.recipeExecutor ?? createContainerRecipeExecutor(this.options.engine),
3876
+ recipeExecutor: this.options.recipeExecutor ?? createContainerRecipeExecutor(this.options.engine, { dependencies: this.options.recipeDependencies ?? null }),
3862
3877
  workspace: active.workspace,
3863
3878
  baseCommitSha: active.baseCommitSha,
3864
3879
  trustedBaseDigest: active.trustedBaseDigest,
@@ -4050,6 +4065,7 @@ export {
4050
4065
  buildRecipeContainerArgs,
4051
4066
  createContainerRecipeExecutor,
4052
4067
  assertCodeBuildRecipe,
4068
+ runContainerCommand,
4053
4069
  verifyCodeCandidate,
4054
4070
  prepareRuntimeCheckpoint,
4055
4071
  describeGateFailure,
@@ -4087,4 +4103,4 @@ export {
4087
4103
  withProofRecipes,
4088
4104
  TheseusRuntimeEngine
4089
4105
  };
4090
- //# sourceMappingURL=chunk-NUDKRYL4.js.map
4106
+ //# sourceMappingURL=chunk-4IGSN53G.js.map