@odla-ai/harness 0.11.8 → 0.11.9

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.
@@ -1075,8 +1075,9 @@ async function verifyContainerEngineBoundary(engine, options = {}) {
1075
1075
  // src/recipe-container.ts
1076
1076
  var ARTIFACT_PATH = /^[A-Za-z0-9_@+.,-]+(?:\/[A-Za-z0-9_@+.,-]+)*$/;
1077
1077
  var PRIVATE_ARTIFACT_PART = /^(?:\.git|\.odla|\.wrangler|\.env(?:\..+)?|\.dev\.vars|credentials(?:\..+)?\.json)$/i;
1078
- function buildRecipeContainerArgs(engine, workspaceDir, recipe2, name = `odla-recipe-${(0, import_node_crypto.randomUUID)().slice(0, 12)}`) {
1078
+ function buildRecipeContainerArgs(engine, workspaceDir, recipe2, name = `odla-recipe-${(0, import_node_crypto.randomUUID)().slice(0, 12)}`, dependencies = null) {
1079
1079
  assertCodeBuildRecipe(recipe2);
1080
+ const mounts = dependencies ? [dependencyMount(engine, dependencies)] : [];
1080
1081
  if (/[,\r\n]/.test(workspaceDir)) throw new TypeError("workspace path contains unsupported mount characters");
1081
1082
  const uid = typeof import_node_process2.getuid === "function" ? (0, import_node_process2.getuid)() : 1e3;
1082
1083
  const gid = typeof import_node_process2.getgid === "function" ? (0, import_node_process2.getgid)() : 1e3;
@@ -1099,6 +1100,7 @@ function buildRecipeContainerArgs(engine, workspaceDir, recipe2, name = `odla-re
1099
1100
  `--user=${uid}:${gid}`,
1100
1101
  "--tmpfs=/tmp",
1101
1102
  `--mount=type=bind,source=${workspaceDir},target=/workspace`,
1103
+ ...mounts,
1102
1104
  "--workdir=/workspace",
1103
1105
  "--env=CI=1",
1104
1106
  recipe2.image,
@@ -1120,18 +1122,28 @@ function buildRecipeContainerArgs(engine, workspaceDir, recipe2, name = `odla-re
1120
1122
  `--user=${uid}:${gid}`,
1121
1123
  `--tmpfs=/tmp:rw,noexec,nosuid,nodev,size=${limits.tmpfs}`,
1122
1124
  `--mount=type=bind,src=${workspaceDir},dst=/workspace`,
1125
+ ...mounts,
1123
1126
  "--workdir=/workspace",
1124
1127
  "--env=CI=1",
1125
1128
  recipe2.image,
1126
1129
  ...recipe2.command
1127
1130
  ];
1128
1131
  }
1129
- function createContainerRecipeExecutor(engine) {
1132
+ var LENDABLE = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage"]);
1133
+ function dependencyMount(engine, dependencies) {
1134
+ const mountAs = dependencies.mountAs ?? "node_modules";
1135
+ if (!dependencies.source.startsWith("/") || /[,\r\n]/.test(dependencies.source)) {
1136
+ throw new TypeError("recipe dependency source must be an absolute path without mount separators");
1137
+ }
1138
+ if (!LENDABLE.has(mountAs)) throw new TypeError(`recipe dependencies must mount at a reserved name, not "${mountAs}"`);
1139
+ return engine === "container" ? `--mount=type=bind,source=${dependencies.source},target=/workspace/${mountAs},readonly` : `--mount=type=bind,src=${dependencies.source},dst=/workspace/${mountAs},readonly`;
1140
+ }
1141
+ function createContainerRecipeExecutor(engine, options = {}) {
1130
1142
  return {
1131
1143
  async run(input) {
1132
1144
  await verifyContainerEngineBoundary(engine);
1133
1145
  const name = `odla-recipe-${(0, import_node_crypto.randomUUID)().slice(0, 12)}`;
1134
- const args = buildRecipeContainerArgs(engine, input.workspaceDir, input.recipe, name);
1146
+ const args = buildRecipeContainerArgs(engine, input.workspaceDir, input.recipe, name, options.dependencies ?? null);
1135
1147
  return execute(engine, args, name, input.recipe, input.signal);
1136
1148
  }
1137
1149
  };
@@ -4148,7 +4160,7 @@ var TheseusRuntimeEngine = class {
4148
4160
  this.#checkpoints = new CodeRuntimeCheckpointManager({
4149
4161
  control: options.control,
4150
4162
  recipes: options.recipes,
4151
- recipeExecutor: options.recipeExecutor ?? createContainerRecipeExecutor(options.engine),
4163
+ recipeExecutor: options.recipeExecutor ?? createContainerRecipeExecutor(options.engine, { dependencies: options.recipeDependencies ?? null }),
4152
4164
  fallbackPolicyDigest: this.#buildPolicyDigest,
4153
4165
  event: (command, event, refs) => this.#event(command, event, refs)
4154
4166
  });
@@ -4256,7 +4268,7 @@ var TheseusRuntimeEngine = class {
4256
4268
  active.done = startGoalPursuit({
4257
4269
  spec,
4258
4270
  recipes: active.recipes,
4259
- recipeExecutor: this.options.recipeExecutor ?? createContainerRecipeExecutor(this.options.engine),
4271
+ recipeExecutor: this.options.recipeExecutor ?? createContainerRecipeExecutor(this.options.engine, { dependencies: this.options.recipeDependencies ?? null }),
4260
4272
  workspace: active.workspace,
4261
4273
  baseCommitSha: active.baseCommitSha,
4262
4274
  trustedBaseDigest: active.trustedBaseDigest,