@odla-ai/harness 0.10.4 → 0.11.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.
- package/README.md +24 -0
- package/dist/{chunk-IV3VMKDV.js → chunk-DP6LOGBF.js} +193 -67
- package/dist/chunk-DP6LOGBF.js.map +1 -0
- package/dist/code-runtime-cli.cjs +173 -55
- package/dist/code-runtime-cli.cjs.map +1 -1
- package/dist/code-runtime-cli.js +1 -1
- package/dist/node.cjs +192 -62
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +90 -14
- package/dist/node.d.ts +90 -14
- package/dist/node.js +13 -1
- package/dist/node.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-IV3VMKDV.js.map +0 -1
package/README.md
CHANGED
|
@@ -109,6 +109,30 @@ before approval:
|
|
|
109
109
|
}
|
|
110
110
|
~~~
|
|
111
111
|
|
|
112
|
+
A repository can replace that release-owned list with its own. Code reads
|
|
113
|
+
`odla.recipes.json` from the root of the trusted base (the default-branch
|
|
114
|
+
snapshot it staged, never the candidate's working tree) when a session starts:
|
|
115
|
+
|
|
116
|
+
~~~json
|
|
117
|
+
{
|
|
118
|
+
"version": 1,
|
|
119
|
+
"recipes": [
|
|
120
|
+
{ "id": "engine-tests", "command": ["node", "--test", "test/"] },
|
|
121
|
+
{ "id": "gates", "command": ["node", "scripts/gates.mjs"], "timeoutMs": 60000 }
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
~~~
|
|
125
|
+
|
|
126
|
+
The repository chooses each recipe's `id`, argv `command`, and optional
|
|
127
|
+
`timeoutMs` (default 120000, at most 900000, up to 16 recipes); the host
|
|
128
|
+
supplies the digest-pinned image and the resource limits, and a declaration that
|
|
129
|
+
names an `image` or any other field is refused. A malformed file fails the
|
|
130
|
+
session start with the fault named rather than falling back, and the session
|
|
131
|
+
thread's first system message says which list gates it and where that list came
|
|
132
|
+
from. Every declared recipe runs in the same fresh, networkless container as the
|
|
133
|
+
release list, so a repository whose tests need `node_modules` still cannot run
|
|
134
|
+
them here.
|
|
135
|
+
|
|
112
136
|
The runtime validates HTTPS, never places its credential in a request body,
|
|
113
137
|
never opens a listener, and rejects malformed or cross-host binding responses.
|
|
114
138
|
Theseus reads, patches, and runs only registered build recipes through the typed
|
|
@@ -260,40 +260,40 @@ async function readBoundedResponse(body, maximum) {
|
|
|
260
260
|
return result;
|
|
261
261
|
}
|
|
262
262
|
|
|
263
|
-
// src/code-runtime.ts
|
|
264
|
-
var
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (!
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
263
|
+
// src/code-runtime-overload.ts
|
|
264
|
+
var OVERLOAD_RETRY_DELAYS_MS = [2e3, 4e3, 8e3, 16e3];
|
|
265
|
+
var RETRYABLE_CODES = /* @__PURE__ */ new Set(["control_plane_overloaded", "registry_overloaded", "transport_unavailable"]);
|
|
266
|
+
function overloadedControlFailure(cause) {
|
|
267
|
+
if (!cause || typeof cause !== "object") return false;
|
|
268
|
+
const failure = cause;
|
|
269
|
+
return failure.status === 503 && typeof failure.code === "string" && RETRYABLE_CODES.has(failure.code);
|
|
270
|
+
}
|
|
271
|
+
async function withOverloadRetry(call, wait2, onRetry = () => void 0) {
|
|
272
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
273
273
|
try {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
if (
|
|
278
|
-
await
|
|
279
|
-
|
|
280
|
-
if (options.signal?.aborted) return;
|
|
281
|
-
if (options.once || !retryableControlFailure(error)) throw error;
|
|
282
|
-
await options.onRetry?.(error, retryMs);
|
|
283
|
-
await wait(retryMs, options.signal);
|
|
284
|
-
retryMs = Math.min(retryMs * 2, 3e4);
|
|
274
|
+
return await call();
|
|
275
|
+
} catch (cause) {
|
|
276
|
+
const delayMs = OVERLOAD_RETRY_DELAYS_MS[attempt];
|
|
277
|
+
if (delayMs === void 0 || !overloadedControlFailure(cause)) throw cause;
|
|
278
|
+
await onRetry(cause, delayMs);
|
|
279
|
+
await wait2(delayMs);
|
|
285
280
|
}
|
|
286
|
-
}
|
|
281
|
+
}
|
|
287
282
|
}
|
|
283
|
+
|
|
284
|
+
// src/code-runtime-reconciler.ts
|
|
285
|
+
var sleep = (ms) => new Promise((resolve6) => setTimeout(resolve6, ms));
|
|
288
286
|
var CodeRuntimeReconciler = class {
|
|
289
|
-
constructor(control, engine, onDiagnostic) {
|
|
287
|
+
constructor(control, engine, onDiagnostic, options = {}) {
|
|
290
288
|
this.control = control;
|
|
291
289
|
this.engine = engine;
|
|
292
290
|
this.onDiagnostic = onDiagnostic;
|
|
291
|
+
this.options = options;
|
|
293
292
|
}
|
|
294
293
|
control;
|
|
295
294
|
engine;
|
|
296
295
|
onDiagnostic;
|
|
296
|
+
options;
|
|
297
297
|
results = /* @__PURE__ */ new Map();
|
|
298
298
|
async reconcile(snapshot) {
|
|
299
299
|
for (const command of snapshot.commands) {
|
|
@@ -312,7 +312,15 @@ var CodeRuntimeReconciler = class {
|
|
|
312
312
|
await this.control.acknowledge(command.commandId, completed.result);
|
|
313
313
|
if (!completed.notified) {
|
|
314
314
|
try {
|
|
315
|
-
await
|
|
315
|
+
await withOverloadRetry(
|
|
316
|
+
async () => {
|
|
317
|
+
await this.engine.acknowledged?.(command, completed.result);
|
|
318
|
+
},
|
|
319
|
+
(ms) => (this.options.wait ?? sleep)(ms),
|
|
320
|
+
(cause, delayMs) => this.onDiagnostic?.(
|
|
321
|
+
`command ${command.commandId} acknowledged handling waits ${delayMs}ms for an overloaded control plane \xB7 ${cause instanceof Error ? cause.message : String(cause)}`
|
|
322
|
+
)
|
|
323
|
+
);
|
|
316
324
|
} catch (error) {
|
|
317
325
|
this.onDiagnostic?.(
|
|
318
326
|
`command ${command.commandId} acknowledged handling failed \xB7 ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -323,6 +331,32 @@ var CodeRuntimeReconciler = class {
|
|
|
323
331
|
}
|
|
324
332
|
}
|
|
325
333
|
};
|
|
334
|
+
|
|
335
|
+
// src/code-runtime.ts
|
|
336
|
+
var CODE_RUNTIME_PROTOCOL_VERSION = 3;
|
|
337
|
+
async function runCodeRuntimeHeartbeatLoop(options) {
|
|
338
|
+
const heartbeatMs = options.heartbeatMs ?? 15e3;
|
|
339
|
+
if (!Number.isSafeInteger(heartbeatMs) || heartbeatMs < 1e3 || heartbeatMs > 3e5) {
|
|
340
|
+
throw new TypeError("heartbeatMs must be an integer from 1000 to 300000");
|
|
341
|
+
}
|
|
342
|
+
let retryMs = 1e3;
|
|
343
|
+
do {
|
|
344
|
+
if (options.signal?.aborted) return;
|
|
345
|
+
try {
|
|
346
|
+
const snapshot = await options.control.heartbeat(options.runtimeVersion, options.capabilities);
|
|
347
|
+
await options.onSnapshot?.(snapshot);
|
|
348
|
+
retryMs = 1e3;
|
|
349
|
+
if (options.once) return;
|
|
350
|
+
await wait(heartbeatMs, options.signal);
|
|
351
|
+
} catch (error) {
|
|
352
|
+
if (options.signal?.aborted) return;
|
|
353
|
+
if (options.once || !retryableControlFailure(error)) throw error;
|
|
354
|
+
await options.onRetry?.(error, retryMs);
|
|
355
|
+
await wait(retryMs, options.signal);
|
|
356
|
+
retryMs = Math.min(retryMs * 2, 3e4);
|
|
357
|
+
}
|
|
358
|
+
} while (!options.signal?.aborted);
|
|
359
|
+
}
|
|
326
360
|
function retryableControlFailure(value) {
|
|
327
361
|
if (!value || typeof value !== "object") return false;
|
|
328
362
|
const failure = value;
|
|
@@ -1148,8 +1182,8 @@ var CodeRuntimeCheckpointManager = class {
|
|
|
1148
1182
|
trustedBaseDigest: active.trustedBaseDigest,
|
|
1149
1183
|
planningInputDigest: active.planningInputDigest,
|
|
1150
1184
|
conversationRefs: active.conversationRefs,
|
|
1151
|
-
fallbackPolicyDigest: this.options.fallbackPolicyDigest,
|
|
1152
|
-
recipes: this.options.recipes,
|
|
1185
|
+
fallbackPolicyDigest: active.buildPolicyDigest ?? this.options.fallbackPolicyDigest,
|
|
1186
|
+
recipes: active.recipes ?? this.options.recipes,
|
|
1153
1187
|
recipeExecutor: this.options.recipeExecutor,
|
|
1154
1188
|
review: (patch2, verification) => this.options.control.review(command.sessionId, { patch: patch2, verification })
|
|
1155
1189
|
});
|
|
@@ -2089,13 +2123,19 @@ function createCodeRuntimeSessionSkillLoader(control) {
|
|
|
2089
2123
|
...tool.acceptsTaint === void 0 ? {} : { acceptsTaint: tool.acceptsTaint },
|
|
2090
2124
|
handler: async (input, context) => {
|
|
2091
2125
|
if (!context.toolCallId) throw new TypeError("collaboration tool call identity is required");
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2126
|
+
try {
|
|
2127
|
+
return await execute2(command.sessionId, {
|
|
2128
|
+
commandId: command.commandId,
|
|
2129
|
+
toolCallId: context.toolCallId,
|
|
2130
|
+
skill: manifest.name,
|
|
2131
|
+
tool: tool.name,
|
|
2132
|
+
input
|
|
2133
|
+
}, context.signal);
|
|
2134
|
+
} catch (cause) {
|
|
2135
|
+
if (context.signal?.aborted) throw cause;
|
|
2136
|
+
const detail = (cause instanceof Error ? cause.message : String(cause)).slice(0, 500);
|
|
2137
|
+
return { content: `Tool "${tool.name}" failed: ${detail}`, isError: true };
|
|
2138
|
+
}
|
|
2099
2139
|
}
|
|
2100
2140
|
}))
|
|
2101
2141
|
}));
|
|
@@ -2113,23 +2153,7 @@ async function sessionSkillsFor(options, command) {
|
|
|
2113
2153
|
}
|
|
2114
2154
|
|
|
2115
2155
|
// src/code-runtime-inference.ts
|
|
2116
|
-
var
|
|
2117
|
-
var RETRYABLE_CODES = /* @__PURE__ */ new Set(["control_plane_overloaded", "registry_overloaded", "transport_unavailable"]);
|
|
2118
|
-
function overloadedControlFailure(cause) {
|
|
2119
|
-
return cause instanceof CodeRuntimeControlError && cause.status === 503 && RETRYABLE_CODES.has(cause.code);
|
|
2120
|
-
}
|
|
2121
|
-
async function inferWithBackoff(infer, wait2, onRetry) {
|
|
2122
|
-
for (let attempt = 0; ; attempt += 1) {
|
|
2123
|
-
try {
|
|
2124
|
-
return await infer();
|
|
2125
|
-
} catch (cause) {
|
|
2126
|
-
const delayMs = OVERLOAD_RETRY_DELAYS_MS[attempt];
|
|
2127
|
-
if (delayMs === void 0 || !overloadedControlFailure(cause)) throw cause;
|
|
2128
|
-
await onRetry(cause, delayMs);
|
|
2129
|
-
await wait2(delayMs);
|
|
2130
|
-
}
|
|
2131
|
-
}
|
|
2132
|
-
}
|
|
2156
|
+
var inferWithBackoff = (infer, wait2, onRetry) => withOverloadRetry(infer, wait2, (cause, delayMs) => onRetry(cause, delayMs));
|
|
2133
2157
|
async function handleCodeRuntimeInference(input) {
|
|
2134
2158
|
const { command, request, state } = input;
|
|
2135
2159
|
const startedAt = Date.now();
|
|
@@ -3150,6 +3174,110 @@ function assertBudget(budget) {
|
|
|
3150
3174
|
}
|
|
3151
3175
|
}
|
|
3152
3176
|
|
|
3177
|
+
// src/code-repository-recipes.ts
|
|
3178
|
+
import { readFile as readFile6 } from "fs/promises";
|
|
3179
|
+
import { join as join6 } from "path";
|
|
3180
|
+
|
|
3181
|
+
// src/code-runtime-events.ts
|
|
3182
|
+
import { createHash as createHash3 } from "crypto";
|
|
3183
|
+
async function appendCodeRuntimeEvent(control, command, event, refs) {
|
|
3184
|
+
const eventId = `${command.commandId.slice(0, 45)}:${refs.length + 1}`;
|
|
3185
|
+
refs.push(eventId);
|
|
3186
|
+
const attributed = { ...event, interactionId: command.commandId };
|
|
3187
|
+
const bounded = attributed.type === "message" ? { ...attributed, body: attributed.body.trim().slice(0, 2e4) || `${attributed.actor} event` } : attributed;
|
|
3188
|
+
await control.appendSessionEvent(command.sessionId, eventId, bounded);
|
|
3189
|
+
}
|
|
3190
|
+
var digestRuntimeValue = (value) => `sha256:${createHash3("sha256").update(value).digest("hex")}`;
|
|
3191
|
+
var runtimeErrorMessage = (value) => value instanceof Error ? value.message : String(value);
|
|
3192
|
+
|
|
3193
|
+
// src/code-repository-recipes.ts
|
|
3194
|
+
var REPOSITORY_RECIPES_FILE = "odla.recipes.json";
|
|
3195
|
+
var MAX_RECIPES = 16;
|
|
3196
|
+
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
3197
|
+
var MAX_TIMEOUT_MS = 15 * 6e4;
|
|
3198
|
+
var ID2 = /^[A-Za-z0-9._:-]{1,120}$/;
|
|
3199
|
+
var RECIPE_FIELDS = /* @__PURE__ */ new Set(["id", "command", "timeoutMs"]);
|
|
3200
|
+
var fault = (detail) => new TypeError(`${REPOSITORY_RECIPES_FILE} is malformed: ${detail}`);
|
|
3201
|
+
function parseRepositoryRecipes(text, envelope) {
|
|
3202
|
+
let parsed;
|
|
3203
|
+
try {
|
|
3204
|
+
parsed = JSON.parse(text);
|
|
3205
|
+
} catch {
|
|
3206
|
+
throw fault("not valid JSON");
|
|
3207
|
+
}
|
|
3208
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw fault("the document must be an object");
|
|
3209
|
+
const document = parsed;
|
|
3210
|
+
if (document.version !== 1) throw fault("version must be 1");
|
|
3211
|
+
const entries = document.recipes;
|
|
3212
|
+
if (!Array.isArray(entries) || entries.length < 1) throw fault("recipes must be a non-empty array");
|
|
3213
|
+
if (entries.length > MAX_RECIPES) throw fault(`at most ${MAX_RECIPES} recipes may be declared`);
|
|
3214
|
+
const recipes = [];
|
|
3215
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3216
|
+
entries.forEach((entry, index) => {
|
|
3217
|
+
const label = `recipe ${index + 1}`;
|
|
3218
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) throw fault(`${label} must be an object`);
|
|
3219
|
+
const row = entry;
|
|
3220
|
+
const unknown = Object.keys(row).filter((key) => !RECIPE_FIELDS.has(key));
|
|
3221
|
+
if (unknown.length) throw fault(`${label} has unsupported field ${unknown[0]}; the host owns image and resource limits`);
|
|
3222
|
+
if (typeof row.id !== "string" || !ID2.test(row.id)) throw fault(`${label} needs an id of 1 to 120 letters, digits, . _ : or -`);
|
|
3223
|
+
if (seen.has(row.id)) throw fault(`${label} repeats id ${row.id}`);
|
|
3224
|
+
seen.add(row.id);
|
|
3225
|
+
if (!Array.isArray(row.command) || row.command.length < 1 || row.command.some((part) => typeof part !== "string" || !part)) {
|
|
3226
|
+
throw fault(`${label} (${row.id}) needs command as a non-empty array of non-empty strings`);
|
|
3227
|
+
}
|
|
3228
|
+
const timeoutMs = row.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
3229
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > MAX_TIMEOUT_MS) {
|
|
3230
|
+
throw fault(`${label} (${row.id}) timeoutMs must be an integer from 1 to ${MAX_TIMEOUT_MS}`);
|
|
3231
|
+
}
|
|
3232
|
+
const recipe2 = {
|
|
3233
|
+
id: row.id,
|
|
3234
|
+
command: [...row.command],
|
|
3235
|
+
timeoutMs,
|
|
3236
|
+
image: envelope.image,
|
|
3237
|
+
maxOutputBytes: envelope.maxOutputBytes,
|
|
3238
|
+
cpus: envelope.cpus,
|
|
3239
|
+
memory: envelope.memory,
|
|
3240
|
+
pids: envelope.pids
|
|
3241
|
+
};
|
|
3242
|
+
try {
|
|
3243
|
+
assertCodeBuildRecipe(recipe2);
|
|
3244
|
+
} catch (cause) {
|
|
3245
|
+
throw fault(`${label} (${row.id}) is not a runnable recipe: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
3246
|
+
}
|
|
3247
|
+
recipes.push(recipe2);
|
|
3248
|
+
});
|
|
3249
|
+
return recipes;
|
|
3250
|
+
}
|
|
3251
|
+
async function readRepositoryRecipes(baselineDir, envelope) {
|
|
3252
|
+
let text;
|
|
3253
|
+
try {
|
|
3254
|
+
text = await readFile6(join6(baselineDir, REPOSITORY_RECIPES_FILE), "utf8");
|
|
3255
|
+
} catch (cause) {
|
|
3256
|
+
if (cause.code === "ENOENT") return null;
|
|
3257
|
+
throw cause;
|
|
3258
|
+
}
|
|
3259
|
+
return parseRepositoryRecipes(text, envelope);
|
|
3260
|
+
}
|
|
3261
|
+
async function resolveCodeRecipes(baselineDir, release, envelope) {
|
|
3262
|
+
const declared = envelope ? await readRepositoryRecipes(baselineDir, envelope) : null;
|
|
3263
|
+
return declared ? { recipes: declared, source: "repository" } : { recipes: release, source: "release" };
|
|
3264
|
+
}
|
|
3265
|
+
function describeCodeRecipes(resolved) {
|
|
3266
|
+
const ids = resolved.recipes.map((recipe2) => recipe2.id).join(", ");
|
|
3267
|
+
return resolved.source === "repository" ? `Verification recipes: declared by the repository in ${REPOSITORY_RECIPES_FILE} \xB7 ${ids}` : `Verification recipes: release-owned (the repository declares none in ${REPOSITORY_RECIPES_FILE}) \xB7 ${ids}`;
|
|
3268
|
+
}
|
|
3269
|
+
async function sessionRecipesFor(workspace, options, resume) {
|
|
3270
|
+
const resolved = await resolveCodeRecipes(workspace.baselineDir, options.recipes, options.repositoryRecipes ?? null).catch(async (cause) => {
|
|
3271
|
+
await workspace.cleanup();
|
|
3272
|
+
throw cause;
|
|
3273
|
+
});
|
|
3274
|
+
return {
|
|
3275
|
+
...resolved,
|
|
3276
|
+
buildPolicyDigest: digestRuntimeValue(JSON.stringify(resolved.recipes)),
|
|
3277
|
+
note: !resume && resolved.source === "repository" ? describeCodeRecipes(resolved) : null
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3153
3281
|
// src/code-runtime-broker.ts
|
|
3154
3282
|
function createCodeRuntimeToolBroker(input, lease, role) {
|
|
3155
3283
|
const broker = createCodeToolBroker({
|
|
@@ -3331,18 +3459,6 @@ async function startGoalPursuit(input) {
|
|
|
3331
3459
|
return { status: run.met ? "completed" : "failed", finalText: "" };
|
|
3332
3460
|
}
|
|
3333
3461
|
|
|
3334
|
-
// src/code-runtime-events.ts
|
|
3335
|
-
import { createHash as createHash3 } from "crypto";
|
|
3336
|
-
async function appendCodeRuntimeEvent(control, command, event, refs) {
|
|
3337
|
-
const eventId = `${command.commandId.slice(0, 45)}:${refs.length + 1}`;
|
|
3338
|
-
refs.push(eventId);
|
|
3339
|
-
const attributed = { ...event, interactionId: command.commandId };
|
|
3340
|
-
const bounded = attributed.type === "message" ? { ...attributed, body: attributed.body.trim().slice(0, 2e4) || `${attributed.actor} event` } : attributed;
|
|
3341
|
-
await control.appendSessionEvent(command.sessionId, eventId, bounded);
|
|
3342
|
-
}
|
|
3343
|
-
var digestRuntimeValue = (value) => `sha256:${createHash3("sha256").update(value).digest("hex")}`;
|
|
3344
|
-
var runtimeErrorMessage = (value) => value instanceof Error ? value.message : String(value);
|
|
3345
|
-
|
|
3346
3462
|
// src/code-runtime-acknowledgement-gate.ts
|
|
3347
3463
|
function codeRuntimeAcknowledgementGate(signal) {
|
|
3348
3464
|
let settle;
|
|
@@ -3464,6 +3580,7 @@ var TheseusRuntimeEngine = class {
|
|
|
3464
3580
|
control: this.options.control,
|
|
3465
3581
|
...this.options.localSource ? { localSource: this.options.localSource } : {}
|
|
3466
3582
|
});
|
|
3583
|
+
const resolvedRecipes = await sessionRecipesFor(workspace, this.options, resume);
|
|
3467
3584
|
const abort = new AbortController(), startGate = codeRuntimeAcknowledgementGate(abort.signal);
|
|
3468
3585
|
const conversationRefs = [];
|
|
3469
3586
|
const active = {
|
|
@@ -3472,6 +3589,8 @@ var TheseusRuntimeEngine = class {
|
|
|
3472
3589
|
conversationRefs,
|
|
3473
3590
|
acknowledged: false,
|
|
3474
3591
|
startGate,
|
|
3592
|
+
recipes: resolvedRecipes.recipes,
|
|
3593
|
+
buildPolicyDigest: resolvedRecipes.buildPolicyDigest,
|
|
3475
3594
|
role: metadata.role,
|
|
3476
3595
|
readOnly: metadata.readOnly,
|
|
3477
3596
|
title: metadata.title,
|
|
@@ -3489,6 +3608,7 @@ var TheseusRuntimeEngine = class {
|
|
|
3489
3608
|
done: Promise.resolve(null)
|
|
3490
3609
|
};
|
|
3491
3610
|
this.#active.set(command.sessionId, active);
|
|
3611
|
+
if (resolvedRecipes.note) await this.#event(command, { type: "message", actor: "system", body: resolvedRecipes.note }, conversationRefs);
|
|
3492
3612
|
if (requestedLocal) {
|
|
3493
3613
|
await this.#event(command, {
|
|
3494
3614
|
type: "message",
|
|
@@ -3524,7 +3644,7 @@ var TheseusRuntimeEngine = class {
|
|
|
3524
3644
|
const active = await this.#takeOver(command, "pursue requires an active Code session");
|
|
3525
3645
|
active.done = startGoalPursuit({
|
|
3526
3646
|
spec,
|
|
3527
|
-
recipes:
|
|
3647
|
+
recipes: active.recipes,
|
|
3528
3648
|
recipeExecutor: this.options.recipeExecutor ?? createContainerRecipeExecutor(this.options.engine),
|
|
3529
3649
|
workspace: active.workspace,
|
|
3530
3650
|
baseCommitSha: active.baseCommitSha,
|
|
@@ -3603,7 +3723,7 @@ var TheseusRuntimeEngine = class {
|
|
|
3603
3723
|
async #runAttempt(command, metadata, active) {
|
|
3604
3724
|
const lease = fakeCodeLease(command, metadata);
|
|
3605
3725
|
const broker = this.#observed(command, active, createCodeRuntimeToolBroker({
|
|
3606
|
-
recipes:
|
|
3726
|
+
recipes: active.recipes,
|
|
3607
3727
|
engine: this.options.engine,
|
|
3608
3728
|
recipeAuthorization: this.options.recipeAuthorization
|
|
3609
3729
|
}, lease, metadata.role));
|
|
@@ -3629,7 +3749,7 @@ var TheseusRuntimeEngine = class {
|
|
|
3629
3749
|
// A review-role session is read-only and still runs the proof; a planner
|
|
3630
3750
|
// marked read-only by its payload runs nothing.
|
|
3631
3751
|
recipes: metadata.role === "review" || !metadata.readOnly,
|
|
3632
|
-
recipeIds:
|
|
3752
|
+
recipeIds: active.recipes.map((recipe2) => recipe2.id),
|
|
3633
3753
|
...extraSkills.length ? { extraSkills } : {}
|
|
3634
3754
|
});
|
|
3635
3755
|
const closing = result.finalText.trim();
|
|
@@ -3697,9 +3817,9 @@ export {
|
|
|
3697
3817
|
digestStagedWorkspace,
|
|
3698
3818
|
CodeRuntimeControlError,
|
|
3699
3819
|
createCodeRuntimeControlClient,
|
|
3820
|
+
CodeRuntimeReconciler,
|
|
3700
3821
|
CODE_RUNTIME_PROTOCOL_VERSION,
|
|
3701
3822
|
runCodeRuntimeHeartbeatLoop,
|
|
3702
|
-
CodeRuntimeReconciler,
|
|
3703
3823
|
stripPatchEnvelope,
|
|
3704
3824
|
applyPatchDialectToDiff,
|
|
3705
3825
|
validateCodePatch,
|
|
@@ -3740,6 +3860,12 @@ export {
|
|
|
3740
3860
|
renderMemories,
|
|
3741
3861
|
hazardFromAttempt,
|
|
3742
3862
|
runGoal,
|
|
3863
|
+
REPOSITORY_RECIPES_FILE,
|
|
3864
|
+
parseRepositoryRecipes,
|
|
3865
|
+
readRepositoryRecipes,
|
|
3866
|
+
resolveCodeRecipes,
|
|
3867
|
+
describeCodeRecipes,
|
|
3868
|
+
sessionRecipesFor,
|
|
3743
3869
|
TheseusRuntimeEngine
|
|
3744
3870
|
};
|
|
3745
|
-
//# sourceMappingURL=chunk-
|
|
3871
|
+
//# sourceMappingURL=chunk-DP6LOGBF.js.map
|