@odla-ai/harness 0.6.0 → 0.7.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 +12 -12
- package/dist/{chunk-ZYNGL5SC.js → chunk-GYWQM76X.js} +197 -39
- package/dist/chunk-GYWQM76X.js.map +1 -0
- package/dist/code-runtime-cli.cjs +197 -39
- package/dist/code-runtime-cli.cjs.map +1 -1
- package/dist/code-runtime-cli.js +4 -4
- package/dist/code-runtime-cli.js.map +1 -1
- package/dist/node.cjs +197 -39
- package/dist/node.cjs.map +1 -1
- package/dist/node.d.cts +19 -13
- package/dist/node.d.ts +19 -13
- package/dist/node.js +3 -3
- package/package.json +1 -1
- package/dist/chunk-ZYNGL5SC.js.map +0 -1
package/dist/code-runtime-cli.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
CODE_RUNTIME_PROTOCOL_VERSION,
|
|
4
|
-
CodePiRuntimeEngine,
|
|
5
4
|
CodeRuntimeReconciler,
|
|
5
|
+
TheseusRuntimeEngine,
|
|
6
6
|
assertCodeBuildRecipe,
|
|
7
7
|
createCodeRuntimeControlClient,
|
|
8
8
|
runCodeRuntimeHeartbeatLoop
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-GYWQM76X.js";
|
|
10
10
|
import {
|
|
11
11
|
assertPinnedImage,
|
|
12
12
|
selectContainerEngine
|
|
@@ -85,8 +85,8 @@ async function main() {
|
|
|
85
85
|
};
|
|
86
86
|
const controller = new AbortController();
|
|
87
87
|
for (const signal of ["SIGINT", "SIGTERM"]) process.once(signal, () => controller.abort(signal));
|
|
88
|
-
const control = createCodeRuntimeControlClient({ endpoint: options.endpoint, token
|
|
89
|
-
const commandEngine = new
|
|
88
|
+
const control = createCodeRuntimeControlClient({ endpoint: options.endpoint, token });
|
|
89
|
+
const commandEngine = new TheseusRuntimeEngine({
|
|
90
90
|
control,
|
|
91
91
|
engine,
|
|
92
92
|
recipes: policy.recipes,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/code-runtime-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { cpus, totalmem } from \"node:os\";\nimport { readFile } from \"node:fs/promises\";\nimport {\n CODE_RUNTIME_PROTOCOL_VERSION,\n CodeRuntimeReconciler,\n createCodeRuntimeControlClient,\n runCodeRuntimeHeartbeatLoop,\n type CodeRuntimeCapabilities,\n} from \"./code-runtime\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../src/code-runtime-cli.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { cpus, totalmem } from \"node:os\";\nimport { readFile } from \"node:fs/promises\";\nimport {\n CODE_RUNTIME_PROTOCOL_VERSION,\n CodeRuntimeReconciler,\n createCodeRuntimeControlClient,\n runCodeRuntimeHeartbeatLoop,\n type CodeRuntimeCapabilities,\n} from \"./code-runtime\";\nimport { TheseusRuntimeEngine } from \"./code-runtime-engine\";\nimport { assertPinnedImage, selectContainerEngine, type ContainerEngine } from \"./container\";\nimport { assertCodeBuildRecipe } from \"./recipe-container\";\nimport type { CodeBuildRecipe } from \"./code-tool-types\";\n\nconst VERSION = \"0.1.0\";\n\nfunction usage(): string {\n return `Usage:\n ODLA_CODE_HOST_TOKEN=odla_code_host_... odla-code-runtime \\\\\n --endpoint https://odla.ai --image registry/odla-pi@sha256:... \\\\\n --build-policy ./odla-code-build.json [--engine auto|container|podman|docker] [--once]\n\nThe host token is read only from ODLA_CODE_HOST_TOKEN. The runtime makes\noutbound HTTPS heartbeats and never opens a listener.`;\n}\n\nfunction parse(argv: string[]): {\n endpoint: string; engine: ContainerEngine | \"auto\"; image: string;\n buildPolicy: string; heartbeatMs: number; once: boolean;\n} {\n const values = new Map<string, string>();\n const flags = new Set<string>();\n for (let index = 0; index < argv.length; index++) {\n const arg = argv[index]!;\n if (arg === \"--once\") { flags.add(arg); continue; }\n if (!arg.startsWith(\"--\") || !argv[index + 1]) throw new TypeError(usage());\n values.set(arg, argv[++index]!);\n }\n const endpoint = values.get(\"--endpoint\");\n const image = values.get(\"--image\");\n const buildPolicy = values.get(\"--build-policy\");\n const engine = values.get(\"--engine\") ?? \"auto\";\n const heartbeatMs = Number(values.get(\"--heartbeat-ms\") ?? 15_000);\n if (!endpoint || !image || !buildPolicy || ![\"auto\", \"container\", \"podman\", \"docker\"].includes(engine)) {\n throw new TypeError(usage());\n }\n assertPinnedImage(image);\n if (!Number.isSafeInteger(heartbeatMs) || heartbeatMs < 1_000 || heartbeatMs > 300_000) {\n throw new TypeError(\"--heartbeat-ms must be an integer from 1000 to 300000\");\n }\n return { endpoint, image, buildPolicy, engine: engine as ContainerEngine | \"auto\",\n heartbeatMs, once: flags.has(\"--once\") };\n}\n\nasync function readPolicy(path: string): Promise<{\n recipes: CodeBuildRecipe[]; recipeAuthorization: \"registered_recipe\" | \"exact_approval\";\n}> {\n const value = JSON.parse(await readFile(path, \"utf8\")) as Record<string, unknown>;\n if (!value || Object.keys(value).some((key) => ![\"recipes\", \"recipeAuthorization\"].includes(key))\n || !Array.isArray(value.recipes) || !value.recipes.length\n || (value.recipeAuthorization !== undefined && value.recipeAuthorization !== \"registered_recipe\"\n && value.recipeAuthorization !== \"exact_approval\")) throw new TypeError(\"invalid Code build policy file\");\n const recipes = value.recipes as CodeBuildRecipe[];\n for (const recipe of recipes) assertCodeBuildRecipe(recipe);\n const recipeAuthorization = value.recipeAuthorization === \"exact_approval\"\n ? \"exact_approval\" : \"registered_recipe\";\n return { recipes, recipeAuthorization };\n}\n\nasync function main(): Promise<void> {\n const token = process.env.ODLA_CODE_HOST_TOKEN;\n if (!token) throw new TypeError(\"ODLA_CODE_HOST_TOKEN is required\");\n const options = parse(process.argv.slice(2));\n if (process.platform !== \"darwin\" && process.platform !== \"linux\") throw new TypeError(\"Code runtime requires macOS or Linux\");\n const engine = await selectContainerEngine(options.engine);\n const policy = await readPolicy(options.buildPolicy);\n const capabilities: CodeRuntimeCapabilities = {\n protocolVersion: CODE_RUNTIME_PROTOCOL_VERSION,\n platform: process.platform === \"darwin\" ? \"macos\" : \"linux\",\n arch: process.arch,\n engines: [engine],\n cpuCount: cpus().length,\n memoryBytes: totalmem(),\n };\n const controller = new AbortController();\n for (const signal of [\"SIGINT\", \"SIGTERM\"] as const) process.once(signal, () => controller.abort(signal));\n // The heartbeat stops on the process signal, but the client must remain able\n // to report the active attempt's terminal events during engine.close().\n const control = createCodeRuntimeControlClient({ endpoint: options.endpoint, token });\n const commandEngine = new TheseusRuntimeEngine({\n control, engine, recipes: policy.recipes,\n recipeAuthorization: policy.recipeAuthorization,\n onDiagnostic: (message) => process.stderr.write(`[odla-code-runtime] agent failed · ${message}\\n`),\n });\n const reconciler = new CodeRuntimeReconciler(control, commandEngine);\n try {\n await runCodeRuntimeHeartbeatLoop({\n control, runtimeVersion: VERSION, capabilities, heartbeatMs: options.heartbeatMs,\n once: options.once, signal: controller.signal,\n onSnapshot: async (snapshot) => {\n process.stderr.write(\n `[odla-code-runtime] host ${snapshot.host.hostId} online · ${snapshot.bindings.length} active binding(s) · ${snapshot.commands.length} command(s)\\n`,\n );\n if (options.once && snapshot.commands.length) {\n throw new TypeError(\"--once is diagnostic-only and refuses pending Code commands\");\n }\n await reconciler.reconcile(snapshot);\n },\n onRetry: (error, delayMs) => {\n process.stderr.write(\n `[odla-code-runtime] control plane unavailable; retrying in ${delayMs}ms · ${error instanceof Error ? error.message : String(error)}\\n`,\n );\n },\n });\n } finally { await commandEngine.close(); }\n}\n\nmain().catch((error) => {\n process.stderr.write(`${error instanceof Error ? error.message : String(error)}\\n`);\n process.exitCode = 1;\n});\n"],"mappings":"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","names":[]}
|
package/dist/node.cjs
CHANGED
|
@@ -21,7 +21,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var node_exports = {};
|
|
22
22
|
__export(node_exports, {
|
|
23
23
|
CODE_RUNTIME_PROTOCOL_VERSION: () => CODE_RUNTIME_PROTOCOL_VERSION,
|
|
24
|
-
CodePiRuntimeEngine: () => CodePiRuntimeEngine,
|
|
25
24
|
CodeRuntimeCheckpointManager: () => CodeRuntimeCheckpointManager,
|
|
26
25
|
CodeRuntimeControlError: () => CodeRuntimeControlError,
|
|
27
26
|
CodeRuntimeReconciler: () => CodeRuntimeReconciler,
|
|
@@ -29,6 +28,7 @@ __export(node_exports, {
|
|
|
29
28
|
MAX_MEMORY_BODY: () => MAX_MEMORY_BODY,
|
|
30
29
|
MEASURED_PREMIUM: () => MEASURED_PREMIUM,
|
|
31
30
|
SYSTEM_PROMPT_FOR: () => SYSTEM_PROMPT_FOR,
|
|
31
|
+
TheseusRuntimeEngine: () => TheseusRuntimeEngine,
|
|
32
32
|
V1_SYSTEM_PROMPT: () => V1_SYSTEM_PROMPT,
|
|
33
33
|
V2_SYSTEM_PROMPT: () => V2_SYSTEM_PROMPT,
|
|
34
34
|
V3_SYSTEM_PROMPT: () => V3_SYSTEM_PROMPT,
|
|
@@ -1731,7 +1731,7 @@ var CodeRuntimeCheckpointManager = class {
|
|
|
1731
1731
|
await this.options.event(command, { type: "message", actor: "system", body: prepared.note }, active.conversationRefs).catch(() => void 0);
|
|
1732
1732
|
await active.workspace.cleanup();
|
|
1733
1733
|
await this.options.event(command, { type: "status", status: "checkpointed" }, active.conversationRefs).catch(() => void 0);
|
|
1734
|
-
return { status: "checkpointed", checkpoint: prepared.checkpoint, message: "
|
|
1734
|
+
return { status: "checkpointed", checkpoint: prepared.checkpoint, message: "Theseus stopped at a portable checkpoint" };
|
|
1735
1735
|
}
|
|
1736
1736
|
async acknowledged(command, result) {
|
|
1737
1737
|
if (command.kind !== "checkpoint_stop" || result.status !== "checkpointed") return false;
|
|
@@ -1973,7 +1973,7 @@ var import_ai2 = require("@odla-ai/ai");
|
|
|
1973
1973
|
var import_ai = require("@odla-ai/ai");
|
|
1974
1974
|
|
|
1975
1975
|
// src/code-agent-skill.ts
|
|
1976
|
-
var V1_SYSTEM_PROMPT = `You are
|
|
1976
|
+
var V1_SYSTEM_PROMPT = `You are Theseus, the coding agent inside an odla Code harness.
|
|
1977
1977
|
Use only the odla_read, odla_apply_git_diff, and odla_run_recipe tools.
|
|
1978
1978
|
For mutations, call odla_apply_git_diff with raw git diff text. It must start
|
|
1979
1979
|
with "diff --git a/<path> b/<path>", include matching "---" and "+++" file
|
|
@@ -1983,7 +1983,10 @@ Never claim a build or test passed unless odla_run_recipe returned that result.`
|
|
|
1983
1983
|
var V2_SYSTEM_PROMPT = `You are the coding agent inside an odla Code harness.
|
|
1984
1984
|
Start by orienting: odla_list shows the files in the workspace and odla_search
|
|
1985
1985
|
finds a literal string across them. Prefer those over guessing a path.
|
|
1986
|
-
Then odla_read a bounded range, and odla_apply_git_diff to mutate.
|
|
1986
|
+
Then odla_read a bounded range, and odla_apply_git_diff to mutate. When you
|
|
1987
|
+
need several independent searches or file ranges, issue those read-only calls
|
|
1988
|
+
together in one turn; their results stay ordered and the harness overlaps them.
|
|
1989
|
+
Never issue odla_apply_git_diff or odla_run_recipe alongside another tool call.
|
|
1987
1990
|
For mutations, call odla_apply_git_diff with raw git diff text. It must start
|
|
1988
1991
|
with "diff --git a/<path> b/<path>", include matching "---" and "+++" file
|
|
1989
1992
|
headers and numbered "@@" hunks, and never use "*** Begin Patch" wrappers.
|
|
@@ -2014,18 +2017,26 @@ var SYSTEM_PROMPT_FOR = {
|
|
|
2014
2017
|
};
|
|
2015
2018
|
function codeSkill(opts) {
|
|
2016
2019
|
let seq = 0;
|
|
2020
|
+
let nextCompletion = 1;
|
|
2021
|
+
const completed = /* @__PURE__ */ new Map();
|
|
2017
2022
|
const call = async (tool, input, signal) => {
|
|
2023
|
+
const sequence = ++seq;
|
|
2018
2024
|
const startedAt = Date.now();
|
|
2019
2025
|
const response2 = await opts.broker.execute(
|
|
2020
2026
|
{ lease: opts.lease, workspaceDir: opts.workspaceDir, signal },
|
|
2021
|
-
{ requestId: `bench-${tool}-${
|
|
2027
|
+
{ requestId: `bench-${tool}-${sequence}`, tool, input }
|
|
2022
2028
|
);
|
|
2023
|
-
|
|
2029
|
+
completed.set(sequence, {
|
|
2024
2030
|
tool,
|
|
2025
2031
|
ok: response2.ok,
|
|
2026
2032
|
durationMs: Date.now() - startedAt,
|
|
2027
2033
|
...response2.ok ? {} : { error: String(response2.content).slice(0, 300) }
|
|
2028
2034
|
});
|
|
2035
|
+
while (completed.has(nextCompletion)) {
|
|
2036
|
+
const completion = completed.get(nextCompletion);
|
|
2037
|
+
completed.delete(nextCompletion++);
|
|
2038
|
+
opts.onToolCall?.(completion);
|
|
2039
|
+
}
|
|
2029
2040
|
return { content: response2.content, isError: !response2.ok };
|
|
2030
2041
|
};
|
|
2031
2042
|
const read2 = {
|
|
@@ -2041,6 +2052,7 @@ function codeSkill(opts) {
|
|
|
2041
2052
|
},
|
|
2042
2053
|
additionalProperties: false
|
|
2043
2054
|
},
|
|
2055
|
+
concurrency: "parallel",
|
|
2044
2056
|
handler: (input, ctx) => call("sandbox.read", input, ctx.signal)
|
|
2045
2057
|
};
|
|
2046
2058
|
const applyPatch = {
|
|
@@ -2056,11 +2068,17 @@ function codeSkill(opts) {
|
|
|
2056
2068
|
};
|
|
2057
2069
|
const runRecipe = {
|
|
2058
2070
|
name: "odla_run_recipe",
|
|
2059
|
-
description:
|
|
2071
|
+
description: `Run one app-registered build or test recipe through CaMeL policy.${opts.recipeIds?.length ? ` Available recipes: ${opts.recipeIds.join(", ")}.` : ""}`,
|
|
2060
2072
|
inputSchema: {
|
|
2061
2073
|
type: "object",
|
|
2062
2074
|
required: ["recipeId"],
|
|
2063
|
-
properties: { recipeId: {
|
|
2075
|
+
properties: { recipeId: {
|
|
2076
|
+
type: "string",
|
|
2077
|
+
minLength: 1,
|
|
2078
|
+
maxLength: 120,
|
|
2079
|
+
pattern: "^[a-zA-Z0-9._:-]+$",
|
|
2080
|
+
...opts.recipeIds?.length ? { enum: [...opts.recipeIds] } : {}
|
|
2081
|
+
} },
|
|
2064
2082
|
additionalProperties: false
|
|
2065
2083
|
},
|
|
2066
2084
|
handler: (input, ctx) => call("sandbox.run_recipe", input, ctx.signal)
|
|
@@ -2076,6 +2094,7 @@ function codeSkill(opts) {
|
|
|
2076
2094
|
},
|
|
2077
2095
|
additionalProperties: false
|
|
2078
2096
|
},
|
|
2097
|
+
concurrency: "parallel",
|
|
2079
2098
|
handler: (input, ctx) => call("sandbox.list", input, ctx.signal)
|
|
2080
2099
|
};
|
|
2081
2100
|
const searchFiles = {
|
|
@@ -2092,11 +2111,13 @@ function codeSkill(opts) {
|
|
|
2092
2111
|
},
|
|
2093
2112
|
additionalProperties: false
|
|
2094
2113
|
},
|
|
2114
|
+
concurrency: "parallel",
|
|
2095
2115
|
handler: (input, ctx) => call("sandbox.search", input, ctx.signal)
|
|
2096
2116
|
};
|
|
2097
2117
|
const graphTool = (name, tool, description, required) => ({
|
|
2098
2118
|
name,
|
|
2099
2119
|
description,
|
|
2120
|
+
concurrency: "parallel",
|
|
2100
2121
|
inputSchema: {
|
|
2101
2122
|
type: "object",
|
|
2102
2123
|
...required ? { required: ["query"] } : {},
|
|
@@ -2144,6 +2165,7 @@ async function runCodeAgent(options) {
|
|
|
2144
2165
|
lease: options.lease,
|
|
2145
2166
|
workspaceDir: options.workspaceDir,
|
|
2146
2167
|
surface,
|
|
2168
|
+
...options.recipeIds ? { recipeIds: options.recipeIds } : {},
|
|
2147
2169
|
onToolCall: (call) => {
|
|
2148
2170
|
toolCalls.push(call);
|
|
2149
2171
|
options.onToolCall?.(call);
|
|
@@ -2174,7 +2196,7 @@ async function runCodeAgent(options) {
|
|
|
2174
2196
|
// src/code-runtime-attempt.ts
|
|
2175
2197
|
async function runCodeAgentAttempt(options) {
|
|
2176
2198
|
try {
|
|
2177
|
-
const surface = options.surface ?? "
|
|
2199
|
+
const surface = options.surface ?? "v3";
|
|
2178
2200
|
const { run } = await runCodeAgent({
|
|
2179
2201
|
inference: options.inference,
|
|
2180
2202
|
broker: options.broker,
|
|
@@ -2185,6 +2207,7 @@ async function runCodeAgentAttempt(options) {
|
|
|
2185
2207
|
// id only labels the request the control plane is about to rewrite.
|
|
2186
2208
|
model: "brokered",
|
|
2187
2209
|
surface,
|
|
2210
|
+
...options.recipeIds ? { recipeIds: options.recipeIds } : {},
|
|
2188
2211
|
...options.maxSteps === void 0 ? {} : { maxSteps: options.maxSteps },
|
|
2189
2212
|
...options.budget ? { budget: options.budget } : {},
|
|
2190
2213
|
...options.signal ? { signal: options.signal } : {},
|
|
@@ -2524,11 +2547,30 @@ function response(request, ok, content, details) {
|
|
|
2524
2547
|
var import_promises11 = require("fs/promises");
|
|
2525
2548
|
|
|
2526
2549
|
// src/code-tool-discovery.ts
|
|
2550
|
+
var import_node_child_process6 = require("child_process");
|
|
2527
2551
|
var import_promises9 = require("fs/promises");
|
|
2528
2552
|
var import_node_path9 = require("path");
|
|
2529
2553
|
var DEFAULT_MAX_FILES = 2e4;
|
|
2530
2554
|
var DEFAULT_MAX_RESULTS = 100;
|
|
2531
2555
|
var DEFAULT_MAX_FILE_BYTES = 512 * 1024;
|
|
2556
|
+
function createWorkspaceFileRegistry(limit = DEFAULT_MAX_FILES, enumerate = registeredFiles) {
|
|
2557
|
+
const cache2 = /* @__PURE__ */ new Map();
|
|
2558
|
+
return {
|
|
2559
|
+
files(root) {
|
|
2560
|
+
const existing = cache2.get(root);
|
|
2561
|
+
if (existing) return existing;
|
|
2562
|
+
const pending = enumerate(root, limit).then((paths) => Object.freeze(paths));
|
|
2563
|
+
cache2.set(root, pending);
|
|
2564
|
+
void pending.catch(() => {
|
|
2565
|
+
if (cache2.get(root) === pending) cache2.delete(root);
|
|
2566
|
+
});
|
|
2567
|
+
return pending;
|
|
2568
|
+
},
|
|
2569
|
+
invalidate(root) {
|
|
2570
|
+
cache2.delete(root);
|
|
2571
|
+
}
|
|
2572
|
+
};
|
|
2573
|
+
}
|
|
2532
2574
|
async function registeredFiles(root, limit = DEFAULT_MAX_FILES) {
|
|
2533
2575
|
const paths = [];
|
|
2534
2576
|
const walk = async (directory) => {
|
|
@@ -2559,28 +2601,122 @@ function listWorkspace(paths, options = {}) {
|
|
|
2559
2601
|
return scoped.slice(0, max);
|
|
2560
2602
|
}
|
|
2561
2603
|
async function searchWorkspace(root, paths, options) {
|
|
2562
|
-
|
|
2563
|
-
if (!query) throw new TypeError("search query must be a non-empty string");
|
|
2604
|
+
options.signal?.throwIfAborted();
|
|
2605
|
+
if (!options.query) throw new TypeError("search query must be a non-empty string");
|
|
2564
2606
|
const maxResults = options.maxResults ?? DEFAULT_MAX_RESULTS;
|
|
2565
2607
|
const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
|
|
2566
2608
|
const scoped = listWorkspace(paths, { ...options.prefix ? { prefix: options.prefix } : {}, maxEntries: paths.length });
|
|
2609
|
+
if (scoped.length === 0) return [];
|
|
2610
|
+
try {
|
|
2611
|
+
return await nativeSearch(root, scoped, { ...options, maxResults, maxFileBytes });
|
|
2612
|
+
} catch (error) {
|
|
2613
|
+
options.signal?.throwIfAborted();
|
|
2614
|
+
return fallbackSearch(root, scoped, { ...options, maxResults, maxFileBytes });
|
|
2615
|
+
}
|
|
2616
|
+
}
|
|
2617
|
+
var MAX_NATIVE_ARG_BYTES = 96 * 1024;
|
|
2618
|
+
async function nativeSearch(root, paths, options) {
|
|
2619
|
+
const batches = [];
|
|
2620
|
+
let batch = [];
|
|
2621
|
+
let bytes = 0;
|
|
2622
|
+
for (const path of paths) {
|
|
2623
|
+
const size = Buffer.byteLength(path) + 1;
|
|
2624
|
+
if (batch.length > 0 && bytes + size > MAX_NATIVE_ARG_BYTES) {
|
|
2625
|
+
batches.push(batch);
|
|
2626
|
+
batch = [];
|
|
2627
|
+
bytes = 0;
|
|
2628
|
+
}
|
|
2629
|
+
batch.push(path);
|
|
2630
|
+
bytes += size;
|
|
2631
|
+
}
|
|
2632
|
+
if (batch.length > 0) batches.push(batch);
|
|
2633
|
+
const matches = [];
|
|
2634
|
+
for (const files of batches) {
|
|
2635
|
+
const remaining = options.maxResults - matches.length;
|
|
2636
|
+
if (remaining <= 0) break;
|
|
2637
|
+
matches.push(...await nativeSearchBatch(root, files, options, remaining));
|
|
2638
|
+
}
|
|
2639
|
+
return matches;
|
|
2640
|
+
}
|
|
2641
|
+
function nativeSearchBatch(root, paths, options, remaining) {
|
|
2642
|
+
return new Promise((resolveMatches, reject) => {
|
|
2643
|
+
const args = [
|
|
2644
|
+
"--fixed-strings",
|
|
2645
|
+
"--json",
|
|
2646
|
+
"--no-messages",
|
|
2647
|
+
"--sort=path",
|
|
2648
|
+
`--max-filesize=${options.maxFileBytes}`,
|
|
2649
|
+
"--max-columns=4096",
|
|
2650
|
+
"--max-columns-preview",
|
|
2651
|
+
options.caseSensitive === false ? "--ignore-case" : "--case-sensitive",
|
|
2652
|
+
"--",
|
|
2653
|
+
options.query,
|
|
2654
|
+
...paths
|
|
2655
|
+
];
|
|
2656
|
+
const child = (0, import_node_child_process6.spawn)("rg", args, {
|
|
2657
|
+
cwd: root,
|
|
2658
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
2659
|
+
...options.signal ? { signal: options.signal } : {}
|
|
2660
|
+
});
|
|
2661
|
+
const matches = [];
|
|
2662
|
+
let carry = "";
|
|
2663
|
+
let stopped = false;
|
|
2664
|
+
const consume = (line) => {
|
|
2665
|
+
if (matches.length >= remaining) return;
|
|
2666
|
+
let event;
|
|
2667
|
+
try {
|
|
2668
|
+
event = JSON.parse(line);
|
|
2669
|
+
} catch {
|
|
2670
|
+
return;
|
|
2671
|
+
}
|
|
2672
|
+
const path = event.data?.path?.text;
|
|
2673
|
+
const lineNumber = event.data?.line_number;
|
|
2674
|
+
const source = event.data?.lines?.text;
|
|
2675
|
+
if (event.type !== "match" || path === void 0 || lineNumber === void 0 || source === void 0) return;
|
|
2676
|
+
matches.push({ path, line: lineNumber, text: source.trim().slice(0, 240) });
|
|
2677
|
+
if (matches.length >= remaining) {
|
|
2678
|
+
stopped = true;
|
|
2679
|
+
child.kill();
|
|
2680
|
+
}
|
|
2681
|
+
};
|
|
2682
|
+
child.stdout.setEncoding("utf8");
|
|
2683
|
+
child.stdout.on("data", (chunk) => {
|
|
2684
|
+
carry += chunk;
|
|
2685
|
+
let newline = carry.indexOf("\n");
|
|
2686
|
+
while (newline >= 0) {
|
|
2687
|
+
consume(carry.slice(0, newline));
|
|
2688
|
+
carry = carry.slice(newline + 1);
|
|
2689
|
+
newline = carry.indexOf("\n");
|
|
2690
|
+
}
|
|
2691
|
+
});
|
|
2692
|
+
child.once("error", reject);
|
|
2693
|
+
child.once("close", (code) => {
|
|
2694
|
+
if (carry) consume(carry);
|
|
2695
|
+
if (stopped || code === 0 || code === 1) resolveMatches(matches);
|
|
2696
|
+
else reject(new Error(`native search exited with status ${code ?? "unknown"}`));
|
|
2697
|
+
});
|
|
2698
|
+
});
|
|
2699
|
+
}
|
|
2700
|
+
async function fallbackSearch(root, scoped, options) {
|
|
2701
|
+
const query = options.caseSensitive === false ? options.query.toLowerCase() : options.query;
|
|
2567
2702
|
const matches = [];
|
|
2568
2703
|
for (const path of scoped) {
|
|
2569
|
-
|
|
2704
|
+
options.signal?.throwIfAborted();
|
|
2705
|
+
if (matches.length >= options.maxResults) break;
|
|
2570
2706
|
let source;
|
|
2571
2707
|
try {
|
|
2572
2708
|
source = await (0, import_promises9.readFile)((0, import_node_path9.resolve)(root, path));
|
|
2573
2709
|
} catch {
|
|
2574
2710
|
continue;
|
|
2575
2711
|
}
|
|
2576
|
-
if (source.byteLength > maxFileBytes || source.includes(0)) continue;
|
|
2712
|
+
if (source.byteLength > options.maxFileBytes || source.includes(0)) continue;
|
|
2577
2713
|
const lines = source.toString("utf8").split("\n");
|
|
2578
2714
|
for (let index = 0; index < lines.length; index += 1) {
|
|
2579
2715
|
const raw = lines[index];
|
|
2580
2716
|
const haystack = options.caseSensitive === false ? raw.toLowerCase() : raw;
|
|
2581
2717
|
if (!haystack.includes(query)) continue;
|
|
2582
2718
|
matches.push({ path, line: index + 1, text: raw.trim().slice(0, 240) });
|
|
2583
|
-
if (matches.length >= maxResults) break;
|
|
2719
|
+
if (matches.length >= options.maxResults) break;
|
|
2584
2720
|
}
|
|
2585
2721
|
}
|
|
2586
2722
|
return matches;
|
|
@@ -2605,6 +2741,9 @@ function workspaceGraphs(workspaceDir, paths) {
|
|
|
2605
2741
|
cache.set(workspaceDir, built);
|
|
2606
2742
|
return built;
|
|
2607
2743
|
}
|
|
2744
|
+
function forgetWorkspaceGraphs(workspaceDir) {
|
|
2745
|
+
cache.delete(workspaceDir);
|
|
2746
|
+
}
|
|
2608
2747
|
var shortId = (id) => id.slice(id.indexOf(":") + 1);
|
|
2609
2748
|
function renderOverview(graphs, prefix) {
|
|
2610
2749
|
const rows = (0, import_graph.rollup)(graphs.graph, import_code4.FILE, prefix === void 0 ? {} : { prefix });
|
|
@@ -2651,7 +2790,7 @@ var GRAPH_TOOLS = /* @__PURE__ */ new Set([
|
|
|
2651
2790
|
"sandbox.who_imports",
|
|
2652
2791
|
"sandbox.who_touches"
|
|
2653
2792
|
]);
|
|
2654
|
-
async function read(context, request, options, policy) {
|
|
2793
|
+
async function read(context, request, options, policy, registry) {
|
|
2655
2794
|
exactKeys(request.input, ["path", "startLine", "endLine"]);
|
|
2656
2795
|
const path = stringField(request.input, "path");
|
|
2657
2796
|
const startLine = optionalInteger(request.input.startLine) ?? 1;
|
|
@@ -2659,7 +2798,7 @@ async function read(context, request, options, policy) {
|
|
|
2659
2798
|
if (endLine < startLine || endLine - startLine + 1 > (options.maxReadLines ?? 2e3)) {
|
|
2660
2799
|
throw new TypeError("requested line range exceeds its bound");
|
|
2661
2800
|
}
|
|
2662
|
-
const paths = await
|
|
2801
|
+
const paths = await registry.files(context.workspaceDir);
|
|
2663
2802
|
if (!paths.includes(path)) {
|
|
2664
2803
|
throw new TypeError(`no such file in the staged workspace: "${path}". Use sandbox.overview, sandbox.where_is or sandbox.search to find the correct path.`);
|
|
2665
2804
|
}
|
|
@@ -2679,13 +2818,13 @@ async function read(context, request, options, policy) {
|
|
|
2679
2818
|
}
|
|
2680
2819
|
return response(request, true, content, { path, startLine, endLine: Math.min(endLine, lines.length) });
|
|
2681
2820
|
}
|
|
2682
|
-
async function list(context, request, options, policy) {
|
|
2821
|
+
async function list(context, request, options, policy, registry) {
|
|
2683
2822
|
exactKeys(request.input, ["prefix", "maxEntries"]);
|
|
2684
2823
|
const raw = request.input.prefix;
|
|
2685
2824
|
const prefix = typeof raw === "string" && raw.length > 0 ? raw : void 0;
|
|
2686
2825
|
const maxEntries = optionalInteger(request.input.maxEntries) ?? 1e3;
|
|
2687
2826
|
if (maxEntries > 5e3) throw new TypeError("maxEntries exceeds its bound");
|
|
2688
|
-
const paths = await
|
|
2827
|
+
const paths = await registry.files(context.workspaceDir);
|
|
2689
2828
|
const allowed = await policy.list(policyContext(context, request, options, { paths, ...prefix ? { prefix } : {} }));
|
|
2690
2829
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2691
2830
|
const entries = listWorkspace(paths, { ...prefix ? { prefix } : {}, maxEntries });
|
|
@@ -2703,7 +2842,7 @@ async function list(context, request, options, policy) {
|
|
|
2703
2842
|
{ count: entries.length, truncated }
|
|
2704
2843
|
);
|
|
2705
2844
|
}
|
|
2706
|
-
async function search(context, request, options, policy) {
|
|
2845
|
+
async function search(context, request, options, policy, registry) {
|
|
2707
2846
|
exactKeys(request.input, ["query", "prefix", "maxResults", "caseSensitive"]);
|
|
2708
2847
|
const query = stringField(request.input, "query");
|
|
2709
2848
|
if (query.length > 512) throw new TypeError("search query exceeds its bound");
|
|
@@ -2712,21 +2851,22 @@ async function search(context, request, options, policy) {
|
|
|
2712
2851
|
const maxResults = optionalInteger(request.input.maxResults) ?? 100;
|
|
2713
2852
|
if (maxResults > 500) throw new TypeError("maxResults exceeds its bound");
|
|
2714
2853
|
const caseSensitive = request.input.caseSensitive === void 0 ? true : request.input.caseSensitive === true;
|
|
2715
|
-
const paths = await
|
|
2854
|
+
const paths = await registry.files(context.workspaceDir);
|
|
2716
2855
|
const allowed = await policy.search(policyContext(context, request, options, { paths, query, ...prefix ? { prefix } : {} }));
|
|
2717
2856
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2718
2857
|
const matches = await searchWorkspace(context.workspaceDir, paths, {
|
|
2719
2858
|
query,
|
|
2720
2859
|
maxResults,
|
|
2721
2860
|
caseSensitive,
|
|
2722
|
-
...prefix ? { prefix } : {}
|
|
2861
|
+
...prefix ? { prefix } : {},
|
|
2862
|
+
...context.signal ? { signal: context.signal } : {}
|
|
2723
2863
|
});
|
|
2724
2864
|
if (!matches.length) return response(request, true, `No match for "${query}".`, { count: 0 });
|
|
2725
2865
|
return response(request, true, matches.map((match) => `${match.path}:${match.line}: ${match.text}`).join("\n"), {
|
|
2726
2866
|
count: matches.length
|
|
2727
2867
|
});
|
|
2728
2868
|
}
|
|
2729
|
-
async function graphQuery(context, request, options, policy) {
|
|
2869
|
+
async function graphQuery(context, request, options, policy, registry) {
|
|
2730
2870
|
exactKeys(request.input, ["query"]);
|
|
2731
2871
|
const raw = request.input.query;
|
|
2732
2872
|
const query = typeof raw === "string" ? raw : "";
|
|
@@ -2736,7 +2876,7 @@ async function graphQuery(context, request, options, policy) {
|
|
|
2736
2876
|
selector: query
|
|
2737
2877
|
}));
|
|
2738
2878
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2739
|
-
const paths = await
|
|
2879
|
+
const paths = await registry.files(context.workspaceDir);
|
|
2740
2880
|
const graphs = await workspaceGraphs(context.workspaceDir, paths);
|
|
2741
2881
|
if (request.tool === "sandbox.overview") {
|
|
2742
2882
|
return response(request, true, renderOverview(graphs, query || void 0));
|
|
@@ -2752,23 +2892,38 @@ function createCodeToolBroker(options) {
|
|
|
2752
2892
|
validateOptions(options);
|
|
2753
2893
|
const recipes = new Map(options.recipes.map((recipe2) => [recipe2.id, recipe2]));
|
|
2754
2894
|
const policy = createCodePolicyGate(options);
|
|
2755
|
-
|
|
2895
|
+
const registry = createWorkspaceFileRegistry();
|
|
2896
|
+
let barrier = Promise.resolve();
|
|
2897
|
+
const activeReads = /* @__PURE__ */ new Set();
|
|
2756
2898
|
return {
|
|
2757
2899
|
execute(context, request) {
|
|
2758
|
-
|
|
2759
|
-
|
|
2900
|
+
if (isReadTool(request.tool)) {
|
|
2901
|
+
const result2 = barrier.then(() => route(context, request, options, recipes, policy, registry));
|
|
2902
|
+
const settled = result2.then(() => void 0, () => void 0);
|
|
2903
|
+
activeReads.add(settled);
|
|
2904
|
+
void settled.then(() => {
|
|
2905
|
+
activeReads.delete(settled);
|
|
2906
|
+
});
|
|
2907
|
+
return result2;
|
|
2908
|
+
}
|
|
2909
|
+
const earlierReads = [...activeReads];
|
|
2910
|
+
const result = barrier.then(() => Promise.all(earlierReads)).then(() => route(context, request, options, recipes, policy, registry));
|
|
2911
|
+
barrier = result.then(() => void 0, () => void 0);
|
|
2760
2912
|
return result;
|
|
2761
2913
|
}
|
|
2762
2914
|
};
|
|
2763
2915
|
}
|
|
2764
|
-
|
|
2916
|
+
function isReadTool(tool) {
|
|
2917
|
+
return tool === "sandbox.read" || tool === "sandbox.list" || tool === "sandbox.search" || GRAPH_TOOLS.has(tool);
|
|
2918
|
+
}
|
|
2919
|
+
async function route(context, request, options, recipes, policy, registry) {
|
|
2765
2920
|
try {
|
|
2766
2921
|
if (context.signal?.aborted) throw new TypeError("tool request was cancelled");
|
|
2767
|
-
if (request.tool === "sandbox.read") return await read(context, request, options, policy);
|
|
2768
|
-
if (request.tool === "sandbox.list") return await list(context, request, options, policy);
|
|
2769
|
-
if (request.tool === "sandbox.search") return await search(context, request, options, policy);
|
|
2770
|
-
if (GRAPH_TOOLS.has(request.tool)) return await graphQuery(context, request, options, policy);
|
|
2771
|
-
if (request.tool === "sandbox.apply_patch") return await patch(context, request, options, policy);
|
|
2922
|
+
if (request.tool === "sandbox.read") return await read(context, request, options, policy, registry);
|
|
2923
|
+
if (request.tool === "sandbox.list") return await list(context, request, options, policy, registry);
|
|
2924
|
+
if (request.tool === "sandbox.search") return await search(context, request, options, policy, registry);
|
|
2925
|
+
if (GRAPH_TOOLS.has(request.tool)) return await graphQuery(context, request, options, policy, registry);
|
|
2926
|
+
if (request.tool === "sandbox.apply_patch") return await patch(context, request, options, policy, registry);
|
|
2772
2927
|
return await recipe(context, request, options, recipes, policy);
|
|
2773
2928
|
} catch (reason) {
|
|
2774
2929
|
return response(request, false, toolFailureMessage(reason));
|
|
@@ -2783,7 +2938,7 @@ function toolFailureMessage(reason) {
|
|
|
2783
2938
|
if (code === "EACCES" || code === "EPERM") return "that path is not readable through this tool";
|
|
2784
2939
|
return "tool failed closed";
|
|
2785
2940
|
}
|
|
2786
|
-
async function patch(context, request, options, policy) {
|
|
2941
|
+
async function patch(context, request, options, policy, registry) {
|
|
2787
2942
|
exactKeys(request.input, ["patch"]);
|
|
2788
2943
|
const value = stringField(request.input, "patch");
|
|
2789
2944
|
const paths = validateCodePatch(value, options.maxPatchBytes ?? 256 * 1024);
|
|
@@ -2793,6 +2948,8 @@ async function patch(context, request, options, policy) {
|
|
|
2793
2948
|
const allowed = await policy.patch(policyContext(context, request, options, { patch: value }));
|
|
2794
2949
|
if (!allowed) return response(request, false, "tool denied by CaMeL policy");
|
|
2795
2950
|
await applyCodePatch(context.workspaceDir, value, paths);
|
|
2951
|
+
registry.invalidate(context.workspaceDir);
|
|
2952
|
+
forgetWorkspaceGraphs(context.workspaceDir);
|
|
2796
2953
|
return response(request, true, `Applied patch to ${paths.length} file(s).`, { paths });
|
|
2797
2954
|
}
|
|
2798
2955
|
async function recipe(context, request, options, recipes, policy) {
|
|
@@ -3184,7 +3341,7 @@ var digestRuntimeValue = (value) => `sha256:${(0, import_node_crypto4.createHash
|
|
|
3184
3341
|
var runtimeErrorMessage = (value) => value instanceof Error ? value.message : String(value);
|
|
3185
3342
|
|
|
3186
3343
|
// src/code-runtime-engine.ts
|
|
3187
|
-
var
|
|
3344
|
+
var TheseusRuntimeEngine = class {
|
|
3188
3345
|
constructor(options) {
|
|
3189
3346
|
this.options = options;
|
|
3190
3347
|
this.#attempt = options.runAgentAttempt ?? runCodeAgentAttempt;
|
|
@@ -3270,7 +3427,7 @@ var CodePiRuntimeEngine = class {
|
|
|
3270
3427
|
await this.#failure(command, active, detail);
|
|
3271
3428
|
return null;
|
|
3272
3429
|
});
|
|
3273
|
-
return { status: "running", message: resume ? "
|
|
3430
|
+
return { status: "running", message: resume ? "Theseus resumed from a portable checkpoint" : "Theseus started" };
|
|
3274
3431
|
}
|
|
3275
3432
|
/**
|
|
3276
3433
|
* Pursue a goal: attempt, judge with the clean verifier, re-prompt from what
|
|
@@ -3358,7 +3515,7 @@ var CodePiRuntimeEngine = class {
|
|
|
3358
3515
|
await this.#failure(command, active, detail);
|
|
3359
3516
|
return null;
|
|
3360
3517
|
});
|
|
3361
|
-
return { status: "running", message: "
|
|
3518
|
+
return { status: "running", message: "Theseus accepted the owner prompt" };
|
|
3362
3519
|
}
|
|
3363
3520
|
async #runAttempt(command, metadata, active) {
|
|
3364
3521
|
const lease = fakeCodeLease(command, metadata);
|
|
@@ -3383,7 +3540,8 @@ var CodePiRuntimeEngine = class {
|
|
|
3383
3540
|
lease,
|
|
3384
3541
|
workspaceDir: active.workspace.workspaceDir,
|
|
3385
3542
|
prompt: metadata.prompt,
|
|
3386
|
-
signal: active.abort.signal
|
|
3543
|
+
signal: active.abort.signal,
|
|
3544
|
+
recipeIds: this.options.recipes.map((recipe2) => recipe2.id)
|
|
3387
3545
|
});
|
|
3388
3546
|
const closing = result.finalText.trim();
|
|
3389
3547
|
const completed = result.status === "completed" && Boolean(closing);
|
|
@@ -3447,7 +3605,7 @@ var CodePiRuntimeEngine = class {
|
|
|
3447
3605
|
}
|
|
3448
3606
|
}
|
|
3449
3607
|
async #diagnostic(command, active, value) {
|
|
3450
|
-
const detail = value.trim().slice(0, 2e3) || "
|
|
3608
|
+
const detail = value.trim().slice(0, 2e3) || "Theseus runtime failed";
|
|
3451
3609
|
this.options.onDiagnostic?.(detail);
|
|
3452
3610
|
await this.#event(
|
|
3453
3611
|
command,
|
|
@@ -3763,7 +3921,6 @@ async function installedDependencies(repoRoot) {
|
|
|
3763
3921
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3764
3922
|
0 && (module.exports = {
|
|
3765
3923
|
CODE_RUNTIME_PROTOCOL_VERSION,
|
|
3766
|
-
CodePiRuntimeEngine,
|
|
3767
3924
|
CodeRuntimeCheckpointManager,
|
|
3768
3925
|
CodeRuntimeControlError,
|
|
3769
3926
|
CodeRuntimeReconciler,
|
|
@@ -3771,6 +3928,7 @@ async function installedDependencies(repoRoot) {
|
|
|
3771
3928
|
MAX_MEMORY_BODY,
|
|
3772
3929
|
MEASURED_PREMIUM,
|
|
3773
3930
|
SYSTEM_PROMPT_FOR,
|
|
3931
|
+
TheseusRuntimeEngine,
|
|
3774
3932
|
V1_SYSTEM_PROMPT,
|
|
3775
3933
|
V2_SYSTEM_PROMPT,
|
|
3776
3934
|
V3_SYSTEM_PROMPT,
|