@odla-ai/harness 0.9.2 → 0.9.4

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.
@@ -1266,12 +1266,24 @@ async function materializeCommandWorkspace(input) {
1266
1266
  resume
1267
1267
  });
1268
1268
  if (command.payload.sourceSet) {
1269
- const selected = await input.control.source(command.sessionId);
1270
- if (selected.repository !== metadata.repository || selected.commitSha !== metadata.baseCommitSha || selected.treeDigest !== metadata.sourceTreeDigest) {
1269
+ if (prepared.trustedBaseDigest !== metadata.sourceTreeDigest) {
1271
1270
  await prepared.workspace.cleanup();
1272
1271
  throw new TypeError("Code local source does not match the selected GitHub primary source");
1273
1272
  }
1274
- await attachCodeRuntimeReferences(prepared.workspace, selected.references ?? []);
1273
+ const set = command.payload.sourceSet && typeof command.payload.sourceSet === "object" && !Array.isArray(command.payload.sourceSet) ? command.payload.sourceSet : null;
1274
+ const references = set?.references;
1275
+ if (!Array.isArray(references)) {
1276
+ await prepared.workspace.cleanup();
1277
+ throw new TypeError("Code selected source set is invalid");
1278
+ }
1279
+ if (references.length) {
1280
+ const selected = await input.control.source(command.sessionId);
1281
+ if (selected.repository !== metadata.repository || selected.commitSha !== metadata.baseCommitSha || selected.treeDigest !== metadata.sourceTreeDigest) {
1282
+ await prepared.workspace.cleanup();
1283
+ throw new TypeError("Code local source does not match the selected GitHub primary source");
1284
+ }
1285
+ await attachCodeRuntimeReferences(prepared.workspace, selected.references ?? []);
1286
+ }
1275
1287
  }
1276
1288
  return {
1277
1289
  workspace: prepared.workspace,
@@ -1477,7 +1489,8 @@ function codeSkill(opts) {
1477
1489
  true
1478
1490
  )
1479
1491
  ];
1480
- const tools = opts.surface === "v3" ? [...orientation, searchFiles, read2, applyPatch, runRecipe] : opts.surface === "v2" ? [listFiles, searchFiles, read2, applyPatch, runRecipe] : [read2, applyPatch, runRecipe];
1492
+ const effects = opts.readOnly ? [] : [applyPatch, runRecipe];
1493
+ const tools = opts.surface === "v3" ? [...orientation, searchFiles, read2, ...effects] : opts.surface === "v2" ? [listFiles, searchFiles, read2, ...effects] : [read2, ...effects];
1481
1494
  return { name: "code", tools };
1482
1495
  }
1483
1496
 
@@ -1494,6 +1507,7 @@ async function runCodeAgent(options) {
1494
1507
  lease: options.lease,
1495
1508
  workspaceDir: options.workspaceDir,
1496
1509
  surface,
1510
+ ...options.readOnly === void 0 ? {} : { readOnly: options.readOnly },
1497
1511
  ...options.recipeIds ? { recipeIds: options.recipeIds } : {},
1498
1512
  onToolCall: (call) => {
1499
1513
  toolCalls.push(call);
@@ -1506,7 +1520,7 @@ async function runCodeAgent(options) {
1506
1520
  {
1507
1521
  name: "odla-code",
1508
1522
  model: options.model,
1509
- system: options.system ?? SYSTEM_PROMPT_FOR[surface],
1523
+ system: options.system ?? `${SYSTEM_PROMPT_FOR[surface]}${options.readOnly ? "\n\nThis session is read-only. Inspect and report; repository mutation and recipe execution are intentionally unavailable." : ""}`,
1510
1524
  skills: [skill, ...options.extraSkills ?? []],
1511
1525
  maxSteps: options.maxSteps ?? 24,
1512
1526
  maxTokens: options.maxTokens ?? 16384
@@ -1537,6 +1551,7 @@ async function runCodeAgentAttempt(options) {
1537
1551
  // id only labels the request the control plane is about to rewrite.
1538
1552
  model: "brokered",
1539
1553
  surface,
1554
+ ...options.readOnly === void 0 ? {} : { readOnly: options.readOnly },
1540
1555
  ...options.recipeIds ? { recipeIds: options.recipeIds } : {},
1541
1556
  ...options.extraSkills ? { extraSkills: options.extraSkills } : {},
1542
1557
  ...options.maxSteps === void 0 ? {} : { maxSteps: options.maxSteps },
@@ -2561,7 +2576,16 @@ function createCodeRuntimeToolBroker(input, lease, role) {
2561
2576
  readerId: `code-session:${lease.task.taskId}`,
2562
2577
  readOnlyPrefixes: [".odla-references"]
2563
2578
  });
2564
- return role === "coding" ? broker : { execute: (context, request) => request.tool === "sandbox.read" ? broker.execute(context, request) : Promise.resolve({ requestId: request.requestId, ok: false, content: "review sessions are read-only" }) };
2579
+ const reviewReads = /* @__PURE__ */ new Set([
2580
+ "sandbox.read",
2581
+ "sandbox.list",
2582
+ "sandbox.search",
2583
+ "sandbox.overview",
2584
+ "sandbox.where_is",
2585
+ "sandbox.who_imports",
2586
+ "sandbox.who_touches"
2587
+ ]);
2588
+ return role === "coding" ? broker : { execute: (context, request) => reviewReads.has(request.tool) ? broker.execute(context, request) : Promise.resolve({ requestId: request.requestId, ok: false, content: "review sessions are read-only" }) };
2565
2589
  }
2566
2590
 
2567
2591
  // src/code-runtime-goal.ts
@@ -3010,6 +3034,7 @@ var TheseusRuntimeEngine = class {
3010
3034
  workspaceDir: active.workspace.workspaceDir,
3011
3035
  prompt: metadata.prompt,
3012
3036
  signal: active.abort.signal,
3037
+ readOnly: metadata.role === "review",
3013
3038
  recipeIds: this.options.recipes.map((recipe2) => recipe2.id),
3014
3039
  ...extraSkills.length ? { extraSkills } : {}
3015
3040
  });
@@ -3121,4 +3146,4 @@ export {
3121
3146
  runGoal,
3122
3147
  TheseusRuntimeEngine
3123
3148
  };
3124
- //# sourceMappingURL=chunk-Q4NL5XO3.js.map
3149
+ //# sourceMappingURL=chunk-XSUUHWNX.js.map