@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.
@@ -7,7 +7,7 @@ import {
7
7
  createCodeRuntimeControlClient,
8
8
  createCodeRuntimeSessionSkillLoader,
9
9
  runCodeRuntimeHeartbeatLoop
10
- } from "./chunk-Q4NL5XO3.js";
10
+ } from "./chunk-XSUUHWNX.js";
11
11
  import "./chunk-FAN2R3GW.js";
12
12
  import {
13
13
  assertPinnedImage,
package/dist/node.cjs CHANGED
@@ -2116,12 +2116,24 @@ async function materializeCommandWorkspace(input) {
2116
2116
  resume
2117
2117
  });
2118
2118
  if (command.payload.sourceSet) {
2119
- const selected = await input.control.source(command.sessionId);
2120
- if (selected.repository !== metadata.repository || selected.commitSha !== metadata.baseCommitSha || selected.treeDigest !== metadata.sourceTreeDigest) {
2119
+ if (prepared.trustedBaseDigest !== metadata.sourceTreeDigest) {
2121
2120
  await prepared.workspace.cleanup();
2122
2121
  throw new TypeError("Code local source does not match the selected GitHub primary source");
2123
2122
  }
2124
- await attachCodeRuntimeReferences(prepared.workspace, selected.references ?? []);
2123
+ const set = command.payload.sourceSet && typeof command.payload.sourceSet === "object" && !Array.isArray(command.payload.sourceSet) ? command.payload.sourceSet : null;
2124
+ const references = set?.references;
2125
+ if (!Array.isArray(references)) {
2126
+ await prepared.workspace.cleanup();
2127
+ throw new TypeError("Code selected source set is invalid");
2128
+ }
2129
+ if (references.length) {
2130
+ const selected = await input.control.source(command.sessionId);
2131
+ if (selected.repository !== metadata.repository || selected.commitSha !== metadata.baseCommitSha || selected.treeDigest !== metadata.sourceTreeDigest) {
2132
+ await prepared.workspace.cleanup();
2133
+ throw new TypeError("Code local source does not match the selected GitHub primary source");
2134
+ }
2135
+ await attachCodeRuntimeReferences(prepared.workspace, selected.references ?? []);
2136
+ }
2125
2137
  }
2126
2138
  return {
2127
2139
  workspace: prepared.workspace,
@@ -2333,7 +2345,8 @@ function codeSkill(opts) {
2333
2345
  true
2334
2346
  )
2335
2347
  ];
2336
- const tools = opts.surface === "v3" ? [...orientation, searchFiles, read2, applyPatch, runRecipe] : opts.surface === "v2" ? [listFiles, searchFiles, read2, applyPatch, runRecipe] : [read2, applyPatch, runRecipe];
2348
+ const effects = opts.readOnly ? [] : [applyPatch, runRecipe];
2349
+ const tools = opts.surface === "v3" ? [...orientation, searchFiles, read2, ...effects] : opts.surface === "v2" ? [listFiles, searchFiles, read2, ...effects] : [read2, ...effects];
2337
2350
  return { name: "code", tools };
2338
2351
  }
2339
2352
 
@@ -2346,6 +2359,7 @@ async function runCodeAgent(options) {
2346
2359
  lease: options.lease,
2347
2360
  workspaceDir: options.workspaceDir,
2348
2361
  surface,
2362
+ ...options.readOnly === void 0 ? {} : { readOnly: options.readOnly },
2349
2363
  ...options.recipeIds ? { recipeIds: options.recipeIds } : {},
2350
2364
  onToolCall: (call) => {
2351
2365
  toolCalls.push(call);
@@ -2358,7 +2372,7 @@ async function runCodeAgent(options) {
2358
2372
  {
2359
2373
  name: "odla-code",
2360
2374
  model: options.model,
2361
- system: options.system ?? SYSTEM_PROMPT_FOR[surface],
2375
+ 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." : ""}`,
2362
2376
  skills: [skill, ...options.extraSkills ?? []],
2363
2377
  maxSteps: options.maxSteps ?? 24,
2364
2378
  maxTokens: options.maxTokens ?? 16384
@@ -2388,6 +2402,7 @@ async function runCodeAgentAttempt(options) {
2388
2402
  // id only labels the request the control plane is about to rewrite.
2389
2403
  model: "brokered",
2390
2404
  surface,
2405
+ ...options.readOnly === void 0 ? {} : { readOnly: options.readOnly },
2391
2406
  ...options.recipeIds ? { recipeIds: options.recipeIds } : {},
2392
2407
  ...options.extraSkills ? { extraSkills: options.extraSkills } : {},
2393
2408
  ...options.maxSteps === void 0 ? {} : { maxSteps: options.maxSteps },
@@ -3405,7 +3420,16 @@ function createCodeRuntimeToolBroker(input, lease, role) {
3405
3420
  readerId: `code-session:${lease.task.taskId}`,
3406
3421
  readOnlyPrefixes: [".odla-references"]
3407
3422
  });
3408
- 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" }) };
3423
+ const reviewReads = /* @__PURE__ */ new Set([
3424
+ "sandbox.read",
3425
+ "sandbox.list",
3426
+ "sandbox.search",
3427
+ "sandbox.overview",
3428
+ "sandbox.where_is",
3429
+ "sandbox.who_imports",
3430
+ "sandbox.who_touches"
3431
+ ]);
3432
+ 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" }) };
3409
3433
  }
3410
3434
 
3411
3435
  // src/code-memory.ts
@@ -4006,6 +4030,7 @@ var TheseusRuntimeEngine = class {
4006
4030
  workspaceDir: active.workspace.workspaceDir,
4007
4031
  prompt: metadata.prompt,
4008
4032
  signal: active.abort.signal,
4033
+ readOnly: metadata.role === "review",
4009
4034
  recipeIds: this.options.recipes.map((recipe2) => recipe2.id),
4010
4035
  ...extraSkills.length ? { extraSkills } : {}
4011
4036
  });