@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/dist/code-runtime-cli.js
CHANGED
package/dist/node.cjs
CHANGED
|
@@ -27,6 +27,7 @@ __export(node_exports, {
|
|
|
27
27
|
DecompositionError: () => DecompositionError,
|
|
28
28
|
MAX_MEMORY_BODY: () => MAX_MEMORY_BODY,
|
|
29
29
|
MEASURED_PREMIUM: () => MEASURED_PREMIUM,
|
|
30
|
+
REPOSITORY_RECIPES_FILE: () => REPOSITORY_RECIPES_FILE,
|
|
30
31
|
SYSTEM_PROMPT_FOR: () => SYSTEM_PROMPT_FOR,
|
|
31
32
|
TheseusRuntimeEngine: () => TheseusRuntimeEngine,
|
|
32
33
|
V1_SYSTEM_PROMPT: () => V1_SYSTEM_PROMPT,
|
|
@@ -48,6 +49,7 @@ __export(node_exports, {
|
|
|
48
49
|
createCodeToolBroker: () => createCodeToolBroker,
|
|
49
50
|
createCodeWorkspaceCheckpoint: () => createCodeWorkspaceCheckpoint,
|
|
50
51
|
createContainerRecipeExecutor: () => createContainerRecipeExecutor,
|
|
52
|
+
describeCodeRecipes: () => describeCodeRecipes,
|
|
51
53
|
describePatchFailure: () => describePatchFailure,
|
|
52
54
|
digestStagedWorkspace: () => digestStagedWorkspace,
|
|
53
55
|
feedbackIsActionable: () => feedbackIsActionable,
|
|
@@ -62,16 +64,19 @@ __export(node_exports, {
|
|
|
62
64
|
materializeGitTree: () => materializeGitTree,
|
|
63
65
|
outcomeCloses: () => outcomeCloses,
|
|
64
66
|
outcomeMemory: () => outcomeMemory,
|
|
67
|
+
parseRepositoryRecipes: () => parseRepositoryRecipes,
|
|
65
68
|
patchPaths: () => patchPaths,
|
|
66
69
|
planReachCollisions: () => planReachCollisions,
|
|
67
70
|
prepareRuntimeCheckpoint: () => prepareRuntimeCheckpoint,
|
|
68
71
|
racedAttempt: () => racedAttempt,
|
|
69
72
|
readOnlyNotice: () => readOnlyNotice,
|
|
73
|
+
readRepositoryRecipes: () => readRepositoryRecipes,
|
|
70
74
|
recallAbout: () => recallAbout,
|
|
71
75
|
registeredFiles: () => registeredFiles,
|
|
72
76
|
renderMemories: () => renderMemories,
|
|
73
77
|
renderOutcome: () => renderOutcome,
|
|
74
78
|
resolveCodePath: () => resolveCodePath,
|
|
79
|
+
resolveCodeRecipes: () => resolveCodeRecipes,
|
|
75
80
|
restoreCodeWorkspaceCheckpoint: () => restoreCodeWorkspaceCheckpoint,
|
|
76
81
|
runCodeAgent: () => runCodeAgent,
|
|
77
82
|
runCodeAgentAttempt: () => runCodeAgentAttempt,
|
|
@@ -84,6 +89,7 @@ __export(node_exports, {
|
|
|
84
89
|
safeWorkspaceLabel: () => safeWorkspaceLabel,
|
|
85
90
|
selectContainerEngine: () => selectContainerEngine,
|
|
86
91
|
selectWinner: () => selectWinner,
|
|
92
|
+
sessionRecipesFor: () => sessionRecipesFor,
|
|
87
93
|
sessionSkillsFor: () => sessionSkillsFor,
|
|
88
94
|
stageWorkspace: () => stageWorkspace,
|
|
89
95
|
stageWorkspacePair: () => stageWorkspacePair,
|
|
@@ -1315,40 +1321,40 @@ async function readBoundedResponse(body, maximum) {
|
|
|
1315
1321
|
return result;
|
|
1316
1322
|
}
|
|
1317
1323
|
|
|
1318
|
-
// src/code-runtime.ts
|
|
1319
|
-
var
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
if (!
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1324
|
+
// src/code-runtime-overload.ts
|
|
1325
|
+
var OVERLOAD_RETRY_DELAYS_MS = [2e3, 4e3, 8e3, 16e3];
|
|
1326
|
+
var RETRYABLE_CODES = /* @__PURE__ */ new Set(["control_plane_overloaded", "registry_overloaded", "transport_unavailable"]);
|
|
1327
|
+
function overloadedControlFailure(cause) {
|
|
1328
|
+
if (!cause || typeof cause !== "object") return false;
|
|
1329
|
+
const failure = cause;
|
|
1330
|
+
return failure.status === 503 && typeof failure.code === "string" && RETRYABLE_CODES.has(failure.code);
|
|
1331
|
+
}
|
|
1332
|
+
async function withOverloadRetry(call, wait2, onRetry = () => void 0) {
|
|
1333
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
1328
1334
|
try {
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
if (
|
|
1333
|
-
await
|
|
1334
|
-
|
|
1335
|
-
if (options.signal?.aborted) return;
|
|
1336
|
-
if (options.once || !retryableControlFailure(error)) throw error;
|
|
1337
|
-
await options.onRetry?.(error, retryMs);
|
|
1338
|
-
await wait(retryMs, options.signal);
|
|
1339
|
-
retryMs = Math.min(retryMs * 2, 3e4);
|
|
1335
|
+
return await call();
|
|
1336
|
+
} catch (cause) {
|
|
1337
|
+
const delayMs = OVERLOAD_RETRY_DELAYS_MS[attempt];
|
|
1338
|
+
if (delayMs === void 0 || !overloadedControlFailure(cause)) throw cause;
|
|
1339
|
+
await onRetry(cause, delayMs);
|
|
1340
|
+
await wait2(delayMs);
|
|
1340
1341
|
}
|
|
1341
|
-
}
|
|
1342
|
+
}
|
|
1342
1343
|
}
|
|
1344
|
+
|
|
1345
|
+
// src/code-runtime-reconciler.ts
|
|
1346
|
+
var sleep = (ms) => new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
1343
1347
|
var CodeRuntimeReconciler = class {
|
|
1344
|
-
constructor(control, engine, onDiagnostic) {
|
|
1348
|
+
constructor(control, engine, onDiagnostic, options = {}) {
|
|
1345
1349
|
this.control = control;
|
|
1346
1350
|
this.engine = engine;
|
|
1347
1351
|
this.onDiagnostic = onDiagnostic;
|
|
1352
|
+
this.options = options;
|
|
1348
1353
|
}
|
|
1349
1354
|
control;
|
|
1350
1355
|
engine;
|
|
1351
1356
|
onDiagnostic;
|
|
1357
|
+
options;
|
|
1352
1358
|
results = /* @__PURE__ */ new Map();
|
|
1353
1359
|
async reconcile(snapshot) {
|
|
1354
1360
|
for (const command of snapshot.commands) {
|
|
@@ -1367,7 +1373,15 @@ var CodeRuntimeReconciler = class {
|
|
|
1367
1373
|
await this.control.acknowledge(command.commandId, completed.result);
|
|
1368
1374
|
if (!completed.notified) {
|
|
1369
1375
|
try {
|
|
1370
|
-
await
|
|
1376
|
+
await withOverloadRetry(
|
|
1377
|
+
async () => {
|
|
1378
|
+
await this.engine.acknowledged?.(command, completed.result);
|
|
1379
|
+
},
|
|
1380
|
+
(ms) => (this.options.wait ?? sleep)(ms),
|
|
1381
|
+
(cause, delayMs) => this.onDiagnostic?.(
|
|
1382
|
+
`command ${command.commandId} acknowledged handling waits ${delayMs}ms for an overloaded control plane \xB7 ${cause instanceof Error ? cause.message : String(cause)}`
|
|
1383
|
+
)
|
|
1384
|
+
);
|
|
1371
1385
|
} catch (error) {
|
|
1372
1386
|
this.onDiagnostic?.(
|
|
1373
1387
|
`command ${command.commandId} acknowledged handling failed \xB7 ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -1378,6 +1392,32 @@ var CodeRuntimeReconciler = class {
|
|
|
1378
1392
|
}
|
|
1379
1393
|
}
|
|
1380
1394
|
};
|
|
1395
|
+
|
|
1396
|
+
// src/code-runtime.ts
|
|
1397
|
+
var CODE_RUNTIME_PROTOCOL_VERSION = 3;
|
|
1398
|
+
async function runCodeRuntimeHeartbeatLoop(options) {
|
|
1399
|
+
const heartbeatMs = options.heartbeatMs ?? 15e3;
|
|
1400
|
+
if (!Number.isSafeInteger(heartbeatMs) || heartbeatMs < 1e3 || heartbeatMs > 3e5) {
|
|
1401
|
+
throw new TypeError("heartbeatMs must be an integer from 1000 to 300000");
|
|
1402
|
+
}
|
|
1403
|
+
let retryMs = 1e3;
|
|
1404
|
+
do {
|
|
1405
|
+
if (options.signal?.aborted) return;
|
|
1406
|
+
try {
|
|
1407
|
+
const snapshot = await options.control.heartbeat(options.runtimeVersion, options.capabilities);
|
|
1408
|
+
await options.onSnapshot?.(snapshot);
|
|
1409
|
+
retryMs = 1e3;
|
|
1410
|
+
if (options.once) return;
|
|
1411
|
+
await wait(heartbeatMs, options.signal);
|
|
1412
|
+
} catch (error) {
|
|
1413
|
+
if (options.signal?.aborted) return;
|
|
1414
|
+
if (options.once || !retryableControlFailure(error)) throw error;
|
|
1415
|
+
await options.onRetry?.(error, retryMs);
|
|
1416
|
+
await wait(retryMs, options.signal);
|
|
1417
|
+
retryMs = Math.min(retryMs * 2, 3e4);
|
|
1418
|
+
}
|
|
1419
|
+
} while (!options.signal?.aborted);
|
|
1420
|
+
}
|
|
1381
1421
|
function retryableControlFailure(value) {
|
|
1382
1422
|
if (!value || typeof value !== "object") return false;
|
|
1383
1423
|
const failure = value;
|
|
@@ -2000,8 +2040,8 @@ var CodeRuntimeCheckpointManager = class {
|
|
|
2000
2040
|
trustedBaseDigest: active.trustedBaseDigest,
|
|
2001
2041
|
planningInputDigest: active.planningInputDigest,
|
|
2002
2042
|
conversationRefs: active.conversationRefs,
|
|
2003
|
-
fallbackPolicyDigest: this.options.fallbackPolicyDigest,
|
|
2004
|
-
recipes: this.options.recipes,
|
|
2043
|
+
fallbackPolicyDigest: active.buildPolicyDigest ?? this.options.fallbackPolicyDigest,
|
|
2044
|
+
recipes: active.recipes ?? this.options.recipes,
|
|
2005
2045
|
recipeExecutor: this.options.recipeExecutor,
|
|
2006
2046
|
review: (patch2, verification) => this.options.control.review(command.sessionId, { patch: patch2, verification })
|
|
2007
2047
|
});
|
|
@@ -2942,13 +2982,19 @@ function createCodeRuntimeSessionSkillLoader(control) {
|
|
|
2942
2982
|
...tool.acceptsTaint === void 0 ? {} : { acceptsTaint: tool.acceptsTaint },
|
|
2943
2983
|
handler: async (input, context) => {
|
|
2944
2984
|
if (!context.toolCallId) throw new TypeError("collaboration tool call identity is required");
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2985
|
+
try {
|
|
2986
|
+
return await execute2(command.sessionId, {
|
|
2987
|
+
commandId: command.commandId,
|
|
2988
|
+
toolCallId: context.toolCallId,
|
|
2989
|
+
skill: manifest.name,
|
|
2990
|
+
tool: tool.name,
|
|
2991
|
+
input
|
|
2992
|
+
}, context.signal);
|
|
2993
|
+
} catch (cause) {
|
|
2994
|
+
if (context.signal?.aborted) throw cause;
|
|
2995
|
+
const detail = (cause instanceof Error ? cause.message : String(cause)).slice(0, 500);
|
|
2996
|
+
return { content: `Tool "${tool.name}" failed: ${detail}`, isError: true };
|
|
2997
|
+
}
|
|
2952
2998
|
}
|
|
2953
2999
|
}))
|
|
2954
3000
|
}));
|
|
@@ -2966,23 +3012,7 @@ async function sessionSkillsFor(options, command) {
|
|
|
2966
3012
|
}
|
|
2967
3013
|
|
|
2968
3014
|
// src/code-runtime-inference.ts
|
|
2969
|
-
var
|
|
2970
|
-
var RETRYABLE_CODES = /* @__PURE__ */ new Set(["control_plane_overloaded", "registry_overloaded", "transport_unavailable"]);
|
|
2971
|
-
function overloadedControlFailure(cause) {
|
|
2972
|
-
return cause instanceof CodeRuntimeControlError && cause.status === 503 && RETRYABLE_CODES.has(cause.code);
|
|
2973
|
-
}
|
|
2974
|
-
async function inferWithBackoff(infer, wait2, onRetry) {
|
|
2975
|
-
for (let attempt = 0; ; attempt += 1) {
|
|
2976
|
-
try {
|
|
2977
|
-
return await infer();
|
|
2978
|
-
} catch (cause) {
|
|
2979
|
-
const delayMs = OVERLOAD_RETRY_DELAYS_MS[attempt];
|
|
2980
|
-
if (delayMs === void 0 || !overloadedControlFailure(cause)) throw cause;
|
|
2981
|
-
await onRetry(cause, delayMs);
|
|
2982
|
-
await wait2(delayMs);
|
|
2983
|
-
}
|
|
2984
|
-
}
|
|
2985
|
-
}
|
|
3015
|
+
var inferWithBackoff = (infer, wait2, onRetry) => withOverloadRetry(infer, wait2, (cause, delayMs) => onRetry(cause, delayMs));
|
|
2986
3016
|
async function handleCodeRuntimeInference(input) {
|
|
2987
3017
|
const { command, request, state } = input;
|
|
2988
3018
|
const startedAt = Date.now();
|
|
@@ -4417,6 +4447,96 @@ function observeCodeRuntimeSessionSkills(command, skills, emit) {
|
|
|
4417
4447
|
}));
|
|
4418
4448
|
}
|
|
4419
4449
|
|
|
4450
|
+
// src/code-repository-recipes.ts
|
|
4451
|
+
var import_promises15 = require("fs/promises");
|
|
4452
|
+
var import_node_path13 = require("path");
|
|
4453
|
+
var REPOSITORY_RECIPES_FILE = "odla.recipes.json";
|
|
4454
|
+
var MAX_RECIPES = 16;
|
|
4455
|
+
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
4456
|
+
var MAX_TIMEOUT_MS = 15 * 6e4;
|
|
4457
|
+
var ID2 = /^[A-Za-z0-9._:-]{1,120}$/;
|
|
4458
|
+
var RECIPE_FIELDS = /* @__PURE__ */ new Set(["id", "command", "timeoutMs"]);
|
|
4459
|
+
var fault = (detail) => new TypeError(`${REPOSITORY_RECIPES_FILE} is malformed: ${detail}`);
|
|
4460
|
+
function parseRepositoryRecipes(text2, envelope) {
|
|
4461
|
+
let parsed;
|
|
4462
|
+
try {
|
|
4463
|
+
parsed = JSON.parse(text2);
|
|
4464
|
+
} catch {
|
|
4465
|
+
throw fault("not valid JSON");
|
|
4466
|
+
}
|
|
4467
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw fault("the document must be an object");
|
|
4468
|
+
const document = parsed;
|
|
4469
|
+
if (document.version !== 1) throw fault("version must be 1");
|
|
4470
|
+
const entries = document.recipes;
|
|
4471
|
+
if (!Array.isArray(entries) || entries.length < 1) throw fault("recipes must be a non-empty array");
|
|
4472
|
+
if (entries.length > MAX_RECIPES) throw fault(`at most ${MAX_RECIPES} recipes may be declared`);
|
|
4473
|
+
const recipes = [];
|
|
4474
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4475
|
+
entries.forEach((entry, index) => {
|
|
4476
|
+
const label = `recipe ${index + 1}`;
|
|
4477
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) throw fault(`${label} must be an object`);
|
|
4478
|
+
const row = entry;
|
|
4479
|
+
const unknown = Object.keys(row).filter((key) => !RECIPE_FIELDS.has(key));
|
|
4480
|
+
if (unknown.length) throw fault(`${label} has unsupported field ${unknown[0]}; the host owns image and resource limits`);
|
|
4481
|
+
if (typeof row.id !== "string" || !ID2.test(row.id)) throw fault(`${label} needs an id of 1 to 120 letters, digits, . _ : or -`);
|
|
4482
|
+
if (seen.has(row.id)) throw fault(`${label} repeats id ${row.id}`);
|
|
4483
|
+
seen.add(row.id);
|
|
4484
|
+
if (!Array.isArray(row.command) || row.command.length < 1 || row.command.some((part) => typeof part !== "string" || !part)) {
|
|
4485
|
+
throw fault(`${label} (${row.id}) needs command as a non-empty array of non-empty strings`);
|
|
4486
|
+
}
|
|
4487
|
+
const timeoutMs = row.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
4488
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > MAX_TIMEOUT_MS) {
|
|
4489
|
+
throw fault(`${label} (${row.id}) timeoutMs must be an integer from 1 to ${MAX_TIMEOUT_MS}`);
|
|
4490
|
+
}
|
|
4491
|
+
const recipe2 = {
|
|
4492
|
+
id: row.id,
|
|
4493
|
+
command: [...row.command],
|
|
4494
|
+
timeoutMs,
|
|
4495
|
+
image: envelope.image,
|
|
4496
|
+
maxOutputBytes: envelope.maxOutputBytes,
|
|
4497
|
+
cpus: envelope.cpus,
|
|
4498
|
+
memory: envelope.memory,
|
|
4499
|
+
pids: envelope.pids
|
|
4500
|
+
};
|
|
4501
|
+
try {
|
|
4502
|
+
assertCodeBuildRecipe(recipe2);
|
|
4503
|
+
} catch (cause) {
|
|
4504
|
+
throw fault(`${label} (${row.id}) is not a runnable recipe: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
4505
|
+
}
|
|
4506
|
+
recipes.push(recipe2);
|
|
4507
|
+
});
|
|
4508
|
+
return recipes;
|
|
4509
|
+
}
|
|
4510
|
+
async function readRepositoryRecipes(baselineDir, envelope) {
|
|
4511
|
+
let text2;
|
|
4512
|
+
try {
|
|
4513
|
+
text2 = await (0, import_promises15.readFile)((0, import_node_path13.join)(baselineDir, REPOSITORY_RECIPES_FILE), "utf8");
|
|
4514
|
+
} catch (cause) {
|
|
4515
|
+
if (cause.code === "ENOENT") return null;
|
|
4516
|
+
throw cause;
|
|
4517
|
+
}
|
|
4518
|
+
return parseRepositoryRecipes(text2, envelope);
|
|
4519
|
+
}
|
|
4520
|
+
async function resolveCodeRecipes(baselineDir, release, envelope) {
|
|
4521
|
+
const declared = envelope ? await readRepositoryRecipes(baselineDir, envelope) : null;
|
|
4522
|
+
return declared ? { recipes: declared, source: "repository" } : { recipes: release, source: "release" };
|
|
4523
|
+
}
|
|
4524
|
+
function describeCodeRecipes(resolved) {
|
|
4525
|
+
const ids = resolved.recipes.map((recipe2) => recipe2.id).join(", ");
|
|
4526
|
+
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}`;
|
|
4527
|
+
}
|
|
4528
|
+
async function sessionRecipesFor(workspace, options, resume) {
|
|
4529
|
+
const resolved = await resolveCodeRecipes(workspace.baselineDir, options.recipes, options.repositoryRecipes ?? null).catch(async (cause) => {
|
|
4530
|
+
await workspace.cleanup();
|
|
4531
|
+
throw cause;
|
|
4532
|
+
});
|
|
4533
|
+
return {
|
|
4534
|
+
...resolved,
|
|
4535
|
+
buildPolicyDigest: digestRuntimeValue(JSON.stringify(resolved.recipes)),
|
|
4536
|
+
note: !resume && resolved.source === "repository" ? describeCodeRecipes(resolved) : null
|
|
4537
|
+
};
|
|
4538
|
+
}
|
|
4539
|
+
|
|
4420
4540
|
// src/code-runtime-engine.ts
|
|
4421
4541
|
var TheseusRuntimeEngine = class {
|
|
4422
4542
|
constructor(options) {
|
|
@@ -4468,6 +4588,7 @@ var TheseusRuntimeEngine = class {
|
|
|
4468
4588
|
control: this.options.control,
|
|
4469
4589
|
...this.options.localSource ? { localSource: this.options.localSource } : {}
|
|
4470
4590
|
});
|
|
4591
|
+
const resolvedRecipes = await sessionRecipesFor(workspace, this.options, resume);
|
|
4471
4592
|
const abort = new AbortController(), startGate = codeRuntimeAcknowledgementGate(abort.signal);
|
|
4472
4593
|
const conversationRefs = [];
|
|
4473
4594
|
const active = {
|
|
@@ -4476,6 +4597,8 @@ var TheseusRuntimeEngine = class {
|
|
|
4476
4597
|
conversationRefs,
|
|
4477
4598
|
acknowledged: false,
|
|
4478
4599
|
startGate,
|
|
4600
|
+
recipes: resolvedRecipes.recipes,
|
|
4601
|
+
buildPolicyDigest: resolvedRecipes.buildPolicyDigest,
|
|
4479
4602
|
role: metadata.role,
|
|
4480
4603
|
readOnly: metadata.readOnly,
|
|
4481
4604
|
title: metadata.title,
|
|
@@ -4493,6 +4616,7 @@ var TheseusRuntimeEngine = class {
|
|
|
4493
4616
|
done: Promise.resolve(null)
|
|
4494
4617
|
};
|
|
4495
4618
|
this.#active.set(command.sessionId, active);
|
|
4619
|
+
if (resolvedRecipes.note) await this.#event(command, { type: "message", actor: "system", body: resolvedRecipes.note }, conversationRefs);
|
|
4496
4620
|
if (requestedLocal) {
|
|
4497
4621
|
await this.#event(command, {
|
|
4498
4622
|
type: "message",
|
|
@@ -4528,7 +4652,7 @@ var TheseusRuntimeEngine = class {
|
|
|
4528
4652
|
const active = await this.#takeOver(command, "pursue requires an active Code session");
|
|
4529
4653
|
active.done = startGoalPursuit({
|
|
4530
4654
|
spec,
|
|
4531
|
-
recipes:
|
|
4655
|
+
recipes: active.recipes,
|
|
4532
4656
|
recipeExecutor: this.options.recipeExecutor ?? createContainerRecipeExecutor(this.options.engine),
|
|
4533
4657
|
workspace: active.workspace,
|
|
4534
4658
|
baseCommitSha: active.baseCommitSha,
|
|
@@ -4607,7 +4731,7 @@ var TheseusRuntimeEngine = class {
|
|
|
4607
4731
|
async #runAttempt(command, metadata, active) {
|
|
4608
4732
|
const lease = fakeCodeLease(command, metadata);
|
|
4609
4733
|
const broker = this.#observed(command, active, createCodeRuntimeToolBroker({
|
|
4610
|
-
recipes:
|
|
4734
|
+
recipes: active.recipes,
|
|
4611
4735
|
engine: this.options.engine,
|
|
4612
4736
|
recipeAuthorization: this.options.recipeAuthorization
|
|
4613
4737
|
}, lease, metadata.role));
|
|
@@ -4633,7 +4757,7 @@ var TheseusRuntimeEngine = class {
|
|
|
4633
4757
|
// A review-role session is read-only and still runs the proof; a planner
|
|
4634
4758
|
// marked read-only by its payload runs nothing.
|
|
4635
4759
|
recipes: metadata.role === "review" || !metadata.readOnly,
|
|
4636
|
-
recipeIds:
|
|
4760
|
+
recipeIds: active.recipes.map((recipe2) => recipe2.id),
|
|
4637
4761
|
...extraSkills.length ? { extraSkills } : {}
|
|
4638
4762
|
});
|
|
4639
4763
|
const closing = result.finalText.trim();
|
|
@@ -4964,12 +5088,12 @@ function chooseStrategy(signals = {}) {
|
|
|
4964
5088
|
var feedbackIsActionable = actionable;
|
|
4965
5089
|
|
|
4966
5090
|
// src/code-recipe-dependencies.ts
|
|
4967
|
-
var
|
|
4968
|
-
var
|
|
5091
|
+
var import_promises16 = require("fs/promises");
|
|
5092
|
+
var import_node_path14 = require("path");
|
|
4969
5093
|
var RESERVED_MOUNTS = /* @__PURE__ */ new Set(["node_modules", "dist", "coverage"]);
|
|
4970
5094
|
function withRecipeDependencies(executor, dependencies) {
|
|
4971
5095
|
const mountAs = dependencies.mountAs ?? "node_modules";
|
|
4972
|
-
if (!(0,
|
|
5096
|
+
if (!(0, import_node_path14.isAbsolute)(dependencies.source)) {
|
|
4973
5097
|
throw new TypeError("recipe dependency source must be an absolute path");
|
|
4974
5098
|
}
|
|
4975
5099
|
if (!RESERVED_MOUNTS.has(mountAs)) {
|
|
@@ -4977,24 +5101,24 @@ function withRecipeDependencies(executor, dependencies) {
|
|
|
4977
5101
|
}
|
|
4978
5102
|
return {
|
|
4979
5103
|
run: async (input) => {
|
|
4980
|
-
const target = (0,
|
|
5104
|
+
const target = (0, import_node_path14.join)(input.workspaceDir, mountAs);
|
|
4981
5105
|
let linked = false;
|
|
4982
5106
|
try {
|
|
4983
|
-
const existing = await (0,
|
|
5107
|
+
const existing = await (0, import_promises16.lstat)(target).catch(() => null);
|
|
4984
5108
|
if (!existing) {
|
|
4985
|
-
await (0,
|
|
5109
|
+
await (0, import_promises16.symlink)(dependencies.source, target, "dir");
|
|
4986
5110
|
linked = true;
|
|
4987
5111
|
}
|
|
4988
5112
|
return await executor.run(input);
|
|
4989
5113
|
} finally {
|
|
4990
|
-
if (linked) await (0,
|
|
5114
|
+
if (linked) await (0, import_promises16.rm)(target, { force: true, recursive: false }).catch(() => void 0);
|
|
4991
5115
|
}
|
|
4992
5116
|
}
|
|
4993
5117
|
};
|
|
4994
5118
|
}
|
|
4995
5119
|
async function installedDependencies(repoRoot) {
|
|
4996
|
-
const source = (0,
|
|
4997
|
-
const info = await (0,
|
|
5120
|
+
const source = (0, import_node_path14.join)(repoRoot, "node_modules");
|
|
5121
|
+
const info = await (0, import_promises16.lstat)(source).catch(() => null);
|
|
4998
5122
|
return info?.isDirectory() ? { source } : null;
|
|
4999
5123
|
}
|
|
5000
5124
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -5006,6 +5130,7 @@ async function installedDependencies(repoRoot) {
|
|
|
5006
5130
|
DecompositionError,
|
|
5007
5131
|
MAX_MEMORY_BODY,
|
|
5008
5132
|
MEASURED_PREMIUM,
|
|
5133
|
+
REPOSITORY_RECIPES_FILE,
|
|
5009
5134
|
SYSTEM_PROMPT_FOR,
|
|
5010
5135
|
TheseusRuntimeEngine,
|
|
5011
5136
|
V1_SYSTEM_PROMPT,
|
|
@@ -5027,6 +5152,7 @@ async function installedDependencies(repoRoot) {
|
|
|
5027
5152
|
createCodeToolBroker,
|
|
5028
5153
|
createCodeWorkspaceCheckpoint,
|
|
5029
5154
|
createContainerRecipeExecutor,
|
|
5155
|
+
describeCodeRecipes,
|
|
5030
5156
|
describePatchFailure,
|
|
5031
5157
|
digestStagedWorkspace,
|
|
5032
5158
|
feedbackIsActionable,
|
|
@@ -5041,16 +5167,19 @@ async function installedDependencies(repoRoot) {
|
|
|
5041
5167
|
materializeGitTree,
|
|
5042
5168
|
outcomeCloses,
|
|
5043
5169
|
outcomeMemory,
|
|
5170
|
+
parseRepositoryRecipes,
|
|
5044
5171
|
patchPaths,
|
|
5045
5172
|
planReachCollisions,
|
|
5046
5173
|
prepareRuntimeCheckpoint,
|
|
5047
5174
|
racedAttempt,
|
|
5048
5175
|
readOnlyNotice,
|
|
5176
|
+
readRepositoryRecipes,
|
|
5049
5177
|
recallAbout,
|
|
5050
5178
|
registeredFiles,
|
|
5051
5179
|
renderMemories,
|
|
5052
5180
|
renderOutcome,
|
|
5053
5181
|
resolveCodePath,
|
|
5182
|
+
resolveCodeRecipes,
|
|
5054
5183
|
restoreCodeWorkspaceCheckpoint,
|
|
5055
5184
|
runCodeAgent,
|
|
5056
5185
|
runCodeAgentAttempt,
|
|
@@ -5063,6 +5192,7 @@ async function installedDependencies(repoRoot) {
|
|
|
5063
5192
|
safeWorkspaceLabel,
|
|
5064
5193
|
selectContainerEngine,
|
|
5065
5194
|
selectWinner,
|
|
5195
|
+
sessionRecipesFor,
|
|
5066
5196
|
sessionSkillsFor,
|
|
5067
5197
|
stageWorkspace,
|
|
5068
5198
|
stageWorkspacePair,
|