open-agents-ai 0.187.554 → 0.187.556
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/dist/index.js +563 -176
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2877,6 +2877,43 @@ Annotated files:`);
|
|
|
2877
2877
|
}
|
|
2878
2878
|
});
|
|
2879
2879
|
|
|
2880
|
+
// packages/execution/dist/tools/edit-metadata.js
|
|
2881
|
+
import { createHash } from "node:crypto";
|
|
2882
|
+
function contentHash(content) {
|
|
2883
|
+
return createHash("sha256").update(content, "utf8").digest("hex");
|
|
2884
|
+
}
|
|
2885
|
+
function normalizeExpectedHash(value2) {
|
|
2886
|
+
if (typeof value2 !== "string")
|
|
2887
|
+
return null;
|
|
2888
|
+
const raw = value2.trim();
|
|
2889
|
+
if (!raw)
|
|
2890
|
+
return null;
|
|
2891
|
+
const stripped = raw.replace(/^sha256:/i, "").toLowerCase();
|
|
2892
|
+
return /^[a-f0-9]{64}$/.test(stripped) ? stripped : null;
|
|
2893
|
+
}
|
|
2894
|
+
function extractExpectedHash(args) {
|
|
2895
|
+
return normalizeExpectedHash(args["expected_hash"] ?? args["expectedHash"] ?? args["before_hash"] ?? args["beforeHash"]);
|
|
2896
|
+
}
|
|
2897
|
+
function hashMismatchMessage(filePath, expectedHash, actualHash) {
|
|
2898
|
+
return [
|
|
2899
|
+
`Refusing to edit ${filePath}: expected_hash does not match current file content.`,
|
|
2900
|
+
`expected_hash: ${expectedHash}`,
|
|
2901
|
+
`current_hash: ${actualHash}`,
|
|
2902
|
+
`Re-read the file and rebuild the edit from the current content before retrying.`
|
|
2903
|
+
].join("\n");
|
|
2904
|
+
}
|
|
2905
|
+
function fileContextHeader(filePath, content, range) {
|
|
2906
|
+
const totalLines = content.split("\n").length;
|
|
2907
|
+
const hash = contentHash(content);
|
|
2908
|
+
const shown = range && (range.offset !== void 0 || range.limit !== void 0) ? ` showing=${range.offset ?? 1}-${range.limit ? (range.offset ?? 1) + range.limit - 1 : "end"}` : "";
|
|
2909
|
+
return `[FILE CONTEXT path=${filePath} sha256=${hash} lines=${totalLines}${shown}]`;
|
|
2910
|
+
}
|
|
2911
|
+
var init_edit_metadata = __esm({
|
|
2912
|
+
"packages/execution/dist/tools/edit-metadata.js"() {
|
|
2913
|
+
"use strict";
|
|
2914
|
+
}
|
|
2915
|
+
});
|
|
2916
|
+
|
|
2880
2917
|
// packages/execution/dist/tools/file-read.js
|
|
2881
2918
|
import { readFile } from "node:fs/promises";
|
|
2882
2919
|
import { resolve as resolve2 } from "node:path";
|
|
@@ -2964,6 +3001,7 @@ var init_file_read = __esm({
|
|
|
2964
3001
|
"packages/execution/dist/tools/file-read.js"() {
|
|
2965
3002
|
"use strict";
|
|
2966
3003
|
init_semantic_map();
|
|
3004
|
+
init_edit_metadata();
|
|
2967
3005
|
SIG_PATTERNS = [
|
|
2968
3006
|
/^\s*(export\s+)?(async\s+)?function\s+\w+/,
|
|
2969
3007
|
/^\s*(export\s+)?(abstract\s+)?class\s+\w+/,
|
|
@@ -3019,10 +3057,15 @@ var init_file_read = __esm({
|
|
|
3019
3057
|
const startIdx = Math.max(0, (offset ?? 1) - 1);
|
|
3020
3058
|
lines = lines.slice(startIdx, limit ? startIdx + limit : void 0);
|
|
3021
3059
|
const numbered2 = lines.map((line, i2) => `${String(startIdx + i2 + 1).padStart(6)} | ${line}`).join("\n");
|
|
3060
|
+
const hash = contentHash(content);
|
|
3022
3061
|
return {
|
|
3023
3062
|
success: true,
|
|
3024
|
-
output:
|
|
3025
|
-
|
|
3063
|
+
output: `${fileContextHeader(filePath, content, { offset, limit })}
|
|
3064
|
+
${numbered2}`,
|
|
3065
|
+
durationMs: performance.now() - start2,
|
|
3066
|
+
mutated: false,
|
|
3067
|
+
mutatedFiles: [],
|
|
3068
|
+
beforeHash: hash
|
|
3026
3069
|
};
|
|
3027
3070
|
}
|
|
3028
3071
|
touchFile(this.workingDir, filePath);
|
|
@@ -3031,15 +3074,23 @@ var init_file_read = __esm({
|
|
|
3031
3074
|
const notes2 = getFileNotes(this.workingDir, filePath);
|
|
3032
3075
|
return {
|
|
3033
3076
|
success: true,
|
|
3034
|
-
output:
|
|
3035
|
-
|
|
3077
|
+
output: `${fileContextHeader(filePath, content)}
|
|
3078
|
+
${buildStructuralPreview(lines, filePath, maxLines)}${notes2 ? "\n\n" + notes2 : ""}`,
|
|
3079
|
+
durationMs: performance.now() - start2,
|
|
3080
|
+
mutated: false,
|
|
3081
|
+
mutatedFiles: [],
|
|
3082
|
+
beforeHash: contentHash(content)
|
|
3036
3083
|
};
|
|
3037
3084
|
}
|
|
3038
3085
|
const numbered = lines.map((line, i2) => `${String(i2 + 1).padStart(6)} | ${line}`).join("\n");
|
|
3039
3086
|
return {
|
|
3040
3087
|
success: true,
|
|
3041
|
-
output:
|
|
3042
|
-
|
|
3088
|
+
output: `${fileContextHeader(filePath, content)}
|
|
3089
|
+
${numbered}`,
|
|
3090
|
+
durationMs: performance.now() - start2,
|
|
3091
|
+
mutated: false,
|
|
3092
|
+
mutatedFiles: [],
|
|
3093
|
+
beforeHash: contentHash(content)
|
|
3043
3094
|
};
|
|
3044
3095
|
} catch (error) {
|
|
3045
3096
|
const errMsg = error instanceof Error ? error.message : String(error);
|
|
@@ -3223,6 +3274,7 @@ var init_file_write = __esm({
|
|
|
3223
3274
|
"packages/execution/dist/tools/file-write.js"() {
|
|
3224
3275
|
"use strict";
|
|
3225
3276
|
init_change_log();
|
|
3277
|
+
init_edit_metadata();
|
|
3226
3278
|
FileWriteTool = class {
|
|
3227
3279
|
name = "file_write";
|
|
3228
3280
|
description = "Write content to a file, creating directories as needed";
|
|
@@ -3230,7 +3282,15 @@ var init_file_write = __esm({
|
|
|
3230
3282
|
type: "object",
|
|
3231
3283
|
properties: {
|
|
3232
3284
|
path: { type: "string", description: "Absolute or relative file path" },
|
|
3233
|
-
content: { type: "string", description: "File content to write" }
|
|
3285
|
+
content: { type: "string", description: "File content to write" },
|
|
3286
|
+
overwrite: {
|
|
3287
|
+
type: "boolean",
|
|
3288
|
+
description: "Required when overwriting an existing file with different content."
|
|
3289
|
+
},
|
|
3290
|
+
expected_hash: {
|
|
3291
|
+
type: "string",
|
|
3292
|
+
description: "SHA-256 hash from the most recent file_read. Required with overwrite=true for existing files."
|
|
3293
|
+
}
|
|
3234
3294
|
},
|
|
3235
3295
|
required: ["path", "content"]
|
|
3236
3296
|
};
|
|
@@ -3241,6 +3301,8 @@ var init_file_write = __esm({
|
|
|
3241
3301
|
async execute(args) {
|
|
3242
3302
|
const filePath = extractWritePath(args);
|
|
3243
3303
|
const content = args["content"] ?? args["text"] ?? args["data"];
|
|
3304
|
+
const overwrite = args["overwrite"] === true || args["overwriteExisting"] === true;
|
|
3305
|
+
const expectedHash = extractExpectedHash(args);
|
|
3244
3306
|
const start2 = performance.now();
|
|
3245
3307
|
if (!filePath) {
|
|
3246
3308
|
return {
|
|
@@ -3261,14 +3323,57 @@ var init_file_write = __esm({
|
|
|
3261
3323
|
try {
|
|
3262
3324
|
const fullPath = resolve3(this.workingDir, filePath);
|
|
3263
3325
|
const isNew = !existsSync6(fullPath);
|
|
3326
|
+
const newHash = contentHash(content);
|
|
3264
3327
|
if (!isNew) {
|
|
3265
3328
|
try {
|
|
3266
3329
|
const existing = await readFile2(fullPath, "utf-8");
|
|
3330
|
+
const beforeHash = contentHash(existing);
|
|
3267
3331
|
if (existing === content) {
|
|
3268
3332
|
return {
|
|
3269
3333
|
success: true,
|
|
3270
3334
|
output: `[NO-OP — file ${filePath} already contains these exact bytes (${content.length}B). Skipped redundant write. If you intended to make a change, the content is identical to disk — you may be replaying an earlier plan. Update todo_write and proceed to the next pending task.]`,
|
|
3271
|
-
durationMs: performance.now() - start2
|
|
3335
|
+
durationMs: performance.now() - start2,
|
|
3336
|
+
mutated: false,
|
|
3337
|
+
mutatedFiles: [],
|
|
3338
|
+
noop: true,
|
|
3339
|
+
beforeHash,
|
|
3340
|
+
afterHash: beforeHash
|
|
3341
|
+
};
|
|
3342
|
+
}
|
|
3343
|
+
if (!overwrite) {
|
|
3344
|
+
return {
|
|
3345
|
+
success: false,
|
|
3346
|
+
output: "",
|
|
3347
|
+
error: `Refusing to overwrite existing file ${filePath} without overwrite=true. Use file_edit/file_patch for targeted changes, or re-read the file and call file_write with overwrite=true and expected_hash=${beforeHash}.`,
|
|
3348
|
+
durationMs: performance.now() - start2,
|
|
3349
|
+
mutated: false,
|
|
3350
|
+
mutatedFiles: [],
|
|
3351
|
+
beforeHash,
|
|
3352
|
+
afterHash: beforeHash
|
|
3353
|
+
};
|
|
3354
|
+
}
|
|
3355
|
+
if (!expectedHash) {
|
|
3356
|
+
return {
|
|
3357
|
+
success: false,
|
|
3358
|
+
output: "",
|
|
3359
|
+
error: `Refusing to overwrite existing file ${filePath} without expected_hash. Re-read the file first; file_read returns a sha256 header to pass as expected_hash.`,
|
|
3360
|
+
durationMs: performance.now() - start2,
|
|
3361
|
+
mutated: false,
|
|
3362
|
+
mutatedFiles: [],
|
|
3363
|
+
beforeHash,
|
|
3364
|
+
afterHash: beforeHash
|
|
3365
|
+
};
|
|
3366
|
+
}
|
|
3367
|
+
if (expectedHash !== beforeHash) {
|
|
3368
|
+
return {
|
|
3369
|
+
success: false,
|
|
3370
|
+
output: "",
|
|
3371
|
+
error: hashMismatchMessage(filePath, expectedHash, beforeHash),
|
|
3372
|
+
durationMs: performance.now() - start2,
|
|
3373
|
+
mutated: false,
|
|
3374
|
+
mutatedFiles: [],
|
|
3375
|
+
beforeHash,
|
|
3376
|
+
afterHash: beforeHash
|
|
3272
3377
|
};
|
|
3273
3378
|
}
|
|
3274
3379
|
} catch {
|
|
@@ -3284,8 +3389,13 @@ var init_file_write = __esm({
|
|
|
3284
3389
|
});
|
|
3285
3390
|
return {
|
|
3286
3391
|
success: true,
|
|
3287
|
-
output:
|
|
3288
|
-
durationMs: performance.now() - start2
|
|
3392
|
+
output: `${isNew ? "Created" : "Overwrote"} ${content.length} bytes at ${fullPath} (sha256 ${newHash})`,
|
|
3393
|
+
durationMs: performance.now() - start2,
|
|
3394
|
+
mutated: true,
|
|
3395
|
+
mutatedFiles: [filePath],
|
|
3396
|
+
noop: false,
|
|
3397
|
+
beforeHash: isNew ? void 0 : expectedHash ?? void 0,
|
|
3398
|
+
afterHash: newHash
|
|
3289
3399
|
};
|
|
3290
3400
|
} catch (error) {
|
|
3291
3401
|
return {
|
|
@@ -4211,6 +4321,7 @@ var init_file_edit = __esm({
|
|
|
4211
4321
|
"use strict";
|
|
4212
4322
|
init_change_log();
|
|
4213
4323
|
init_edit_snippet_finder();
|
|
4324
|
+
init_edit_metadata();
|
|
4214
4325
|
FileEditTool = class {
|
|
4215
4326
|
name = "file_edit";
|
|
4216
4327
|
description = "Make a precise edit to a file by replacing an exact string match. The old_string must be unique in the file unless replace_all is true. Use replace_all to rename variables or change repeated patterns throughout the file.";
|
|
@@ -4229,6 +4340,10 @@ var init_file_edit = __esm({
|
|
|
4229
4340
|
replace_all: {
|
|
4230
4341
|
type: "boolean",
|
|
4231
4342
|
description: "Replace ALL occurrences instead of just the first. Use for variable renames, import path changes, etc. Default: false"
|
|
4343
|
+
},
|
|
4344
|
+
expected_hash: {
|
|
4345
|
+
type: "string",
|
|
4346
|
+
description: "Optional SHA-256 from the most recent file_read. If provided, edit is refused when the file changed."
|
|
4232
4347
|
}
|
|
4233
4348
|
},
|
|
4234
4349
|
required: ["path", "old_string", "new_string"]
|
|
@@ -4242,6 +4357,7 @@ var init_file_edit = __esm({
|
|
|
4242
4357
|
const oldString = args["old_string"] ?? args["oldString"] ?? args["search"] ?? args["find"];
|
|
4243
4358
|
const newString = args["new_string"] ?? args["newString"] ?? args["replace"] ?? args["replacement"];
|
|
4244
4359
|
const replaceAll = args["replace_all"] === true || args["replaceAll"] === true;
|
|
4360
|
+
const expectedHash = extractExpectedHash(args);
|
|
4245
4361
|
const start2 = performance.now();
|
|
4246
4362
|
if (!filePath) {
|
|
4247
4363
|
return {
|
|
@@ -4270,6 +4386,19 @@ var init_file_edit = __esm({
|
|
|
4270
4386
|
try {
|
|
4271
4387
|
const fullPath = resolve6(this.workingDir, filePath);
|
|
4272
4388
|
const content = await readFile3(fullPath, "utf-8");
|
|
4389
|
+
const beforeHash = contentHash(content);
|
|
4390
|
+
if (expectedHash && expectedHash !== beforeHash) {
|
|
4391
|
+
return {
|
|
4392
|
+
success: false,
|
|
4393
|
+
output: "",
|
|
4394
|
+
error: hashMismatchMessage(filePath, expectedHash, beforeHash),
|
|
4395
|
+
durationMs: performance.now() - start2,
|
|
4396
|
+
mutated: false,
|
|
4397
|
+
mutatedFiles: [],
|
|
4398
|
+
beforeHash,
|
|
4399
|
+
afterHash: beforeHash
|
|
4400
|
+
};
|
|
4401
|
+
}
|
|
4273
4402
|
const occurrences = countOccurrences(content, oldString);
|
|
4274
4403
|
if (occurrences === 0) {
|
|
4275
4404
|
const snippet = findClosestSnippet(content, oldString, 5);
|
|
@@ -4289,7 +4418,11 @@ Use the EXACT current content above to construct a working old_string. Do not re
|
|
|
4289
4418
|
success: false,
|
|
4290
4419
|
output: "",
|
|
4291
4420
|
error: errorMsg,
|
|
4292
|
-
durationMs: performance.now() - start2
|
|
4421
|
+
durationMs: performance.now() - start2,
|
|
4422
|
+
mutated: false,
|
|
4423
|
+
mutatedFiles: [],
|
|
4424
|
+
beforeHash,
|
|
4425
|
+
afterHash: beforeHash
|
|
4293
4426
|
};
|
|
4294
4427
|
}
|
|
4295
4428
|
if (!replaceAll && occurrences > 1) {
|
|
@@ -4308,7 +4441,11 @@ ${s2.content}`;
|
|
|
4308
4441
|
${snippets}
|
|
4309
4442
|
|
|
4310
4443
|
Add UNIQUE surrounding context (a function name, distinctive comment, or unique line above/below) to disambiguate. Or set replace_all=true if you want all ${occurrences} occurrences replaced identically.`,
|
|
4311
|
-
durationMs: performance.now() - start2
|
|
4444
|
+
durationMs: performance.now() - start2,
|
|
4445
|
+
mutated: false,
|
|
4446
|
+
mutatedFiles: [],
|
|
4447
|
+
beforeHash,
|
|
4448
|
+
afterHash: beforeHash
|
|
4312
4449
|
};
|
|
4313
4450
|
}
|
|
4314
4451
|
let updated;
|
|
@@ -4322,19 +4459,40 @@ Add UNIQUE surrounding context (a function name, distinctive comment, or unique
|
|
|
4322
4459
|
editedLines = [lineNumber];
|
|
4323
4460
|
updated = content.slice(0, index) + newString + content.slice(index + oldString.length);
|
|
4324
4461
|
}
|
|
4462
|
+
const afterHash = contentHash(updated);
|
|
4463
|
+
const diff = buildCompactDiff(oldString, newString);
|
|
4464
|
+
if (afterHash === beforeHash) {
|
|
4465
|
+
return {
|
|
4466
|
+
success: true,
|
|
4467
|
+
output: `[NO-OP — ${filePath} already matches the requested file_edit at ${editedLines.length === 1 ? `line ${editedLines[0]}` : `${editedLines.length} locations`}.]`,
|
|
4468
|
+
durationMs: performance.now() - start2,
|
|
4469
|
+
mutated: false,
|
|
4470
|
+
mutatedFiles: [],
|
|
4471
|
+
diff,
|
|
4472
|
+
noop: true,
|
|
4473
|
+
beforeHash,
|
|
4474
|
+
afterHash
|
|
4475
|
+
};
|
|
4476
|
+
}
|
|
4325
4477
|
await writeFile2(fullPath, updated, "utf-8");
|
|
4326
4478
|
recordChange(this.workingDir, {
|
|
4327
4479
|
tool: "file_edit",
|
|
4328
4480
|
file: filePath,
|
|
4329
4481
|
lineRange: editedLines.length > 0 ? [editedLines[0], editedLines[editedLines.length - 1]] : void 0,
|
|
4330
4482
|
summary: replaceAll ? `Replaced ${editedLines.length} occurrences in ${filePath}` : `Edited ${filePath} at line ${editedLines[0]}`,
|
|
4331
|
-
diff
|
|
4483
|
+
diff
|
|
4332
4484
|
});
|
|
4333
4485
|
const linesInfo = editedLines.length === 1 ? `line ${editedLines[0]}` : `${editedLines.length} locations (lines ${editedLines.join(", ")})`;
|
|
4334
4486
|
return {
|
|
4335
4487
|
success: true,
|
|
4336
|
-
output: `Edited ${filePath} at ${linesInfo}`,
|
|
4337
|
-
durationMs: performance.now() - start2
|
|
4488
|
+
output: `Edited ${filePath} at ${linesInfo} (sha256 ${beforeHash} → ${afterHash})`,
|
|
4489
|
+
durationMs: performance.now() - start2,
|
|
4490
|
+
mutated: true,
|
|
4491
|
+
mutatedFiles: [filePath],
|
|
4492
|
+
diff,
|
|
4493
|
+
noop: false,
|
|
4494
|
+
beforeHash,
|
|
4495
|
+
afterHash
|
|
4338
4496
|
};
|
|
4339
4497
|
} catch (error) {
|
|
4340
4498
|
return {
|
|
@@ -4889,7 +5047,7 @@ var init_explore_tools = __esm({
|
|
|
4889
5047
|
memory_write: "Store a fact in persistent memory",
|
|
4890
5048
|
memory_search: "Search all memories by relevance",
|
|
4891
5049
|
batch_edit: "Apply multiple file edits atomically",
|
|
4892
|
-
file_patch: "Apply
|
|
5050
|
+
file_patch: "Apply version-checked line-range patches to files",
|
|
4893
5051
|
git_info: "Get git status, branch, recent commits",
|
|
4894
5052
|
codebase_map: "Generate overview of project structure",
|
|
4895
5053
|
diagnostic: "Run project diagnostics (build, test, lint)",
|
|
@@ -5829,6 +5987,7 @@ var init_batch_edit = __esm({
|
|
|
5829
5987
|
"use strict";
|
|
5830
5988
|
init_change_log();
|
|
5831
5989
|
init_edit_snippet_finder();
|
|
5990
|
+
init_edit_metadata();
|
|
5832
5991
|
BatchEditTool = class {
|
|
5833
5992
|
name = "batch_edit";
|
|
5834
5993
|
description = "Make multiple precise edits across one or more files in a single call. More efficient than calling file_edit repeatedly. Each edit replaces an exact string match with uniqueness validation. Edits are applied in order within each file. Set replace_all on individual edits for bulk renames.";
|
|
@@ -5856,6 +6015,10 @@ var init_batch_edit = __esm({
|
|
|
5856
6015
|
replace_all: {
|
|
5857
6016
|
type: "boolean",
|
|
5858
6017
|
description: "Replace all occurrences (for renames). Default: false"
|
|
6018
|
+
},
|
|
6019
|
+
expected_hash: {
|
|
6020
|
+
type: "string",
|
|
6021
|
+
description: "SHA-256 from the most recent file_read for this file. All edits for a file must use the same hash if provided."
|
|
5859
6022
|
}
|
|
5860
6023
|
},
|
|
5861
6024
|
required: ["path", "old_string", "new_string"]
|
|
@@ -5888,15 +6051,33 @@ var init_batch_edit = __esm({
|
|
|
5888
6051
|
old_string: edit.old_string,
|
|
5889
6052
|
new_string: edit.new_string,
|
|
5890
6053
|
replace_all: edit.replace_all,
|
|
6054
|
+
expected_hash: edit.expected_hash,
|
|
5891
6055
|
relPath: edit.path
|
|
5892
6056
|
});
|
|
5893
6057
|
}
|
|
5894
6058
|
const results = [];
|
|
5895
6059
|
let successCount = 0;
|
|
5896
6060
|
let failCount = 0;
|
|
6061
|
+
const pendingWrites = [];
|
|
5897
6062
|
for (const [fullPath, fileEdits] of byFile) {
|
|
5898
6063
|
try {
|
|
5899
6064
|
let content = await readFile7(fullPath, "utf-8");
|
|
6065
|
+
const beforeHash = contentHash(content);
|
|
6066
|
+
const expectedHashes = new Set(fileEdits.map((edit) => extractExpectedHash({ expected_hash: edit.expected_hash })).filter((h) => !!h));
|
|
6067
|
+
if (expectedHashes.size > 1) {
|
|
6068
|
+
results.push(`ERROR: ${fileEdits[0].relPath}: conflicting expected_hash values in one batch`);
|
|
6069
|
+
failCount += fileEdits.length;
|
|
6070
|
+
continue;
|
|
6071
|
+
}
|
|
6072
|
+
const expectedHash = expectedHashes.values().next().value;
|
|
6073
|
+
if (expectedHash && expectedHash !== beforeHash) {
|
|
6074
|
+
results.push(hashMismatchMessage(fileEdits[0].relPath, expectedHash, beforeHash));
|
|
6075
|
+
failCount += fileEdits.length;
|
|
6076
|
+
continue;
|
|
6077
|
+
}
|
|
6078
|
+
const originalContent = content;
|
|
6079
|
+
let fileSuccessCount = 0;
|
|
6080
|
+
let fileFailed = false;
|
|
5900
6081
|
for (const edit of fileEdits) {
|
|
5901
6082
|
const occurrences = countOccurrences2(content, edit.old_string);
|
|
5902
6083
|
if (occurrences === 0) {
|
|
@@ -5911,7 +6092,8 @@ ${snippet.content}
|
|
|
5911
6092
|
results.push(`SKIP: old_string not found in ${edit.relPath} (file empty or binary)`);
|
|
5912
6093
|
}
|
|
5913
6094
|
failCount++;
|
|
5914
|
-
|
|
6095
|
+
fileFailed = true;
|
|
6096
|
+
break;
|
|
5915
6097
|
}
|
|
5916
6098
|
if (!edit.replace_all && occurrences > 1) {
|
|
5917
6099
|
const offsets = findMatchOffsetsBatch(content, edit.old_string).slice(0, 4);
|
|
@@ -5924,7 +6106,8 @@ ${s2.content}`;
|
|
|
5924
6106
|
results.push(`AMBIGUOUS: old_string has ${occurrences} matches in ${edit.relPath}.${snippets}
|
|
5925
6107
|
Add UNIQUE surrounding context, or use replace_all=true.`);
|
|
5926
6108
|
failCount++;
|
|
5927
|
-
|
|
6109
|
+
fileFailed = true;
|
|
6110
|
+
break;
|
|
5928
6111
|
}
|
|
5929
6112
|
if (edit.replace_all) {
|
|
5930
6113
|
content = content.split(edit.old_string).join(edit.new_string);
|
|
@@ -5935,26 +6118,55 @@ ${s2.content}`;
|
|
|
5935
6118
|
content = content.slice(0, index) + edit.new_string + content.slice(index + edit.old_string.length);
|
|
5936
6119
|
results.push(`EDIT: ${edit.relPath} line ${lineNumber}`);
|
|
5937
6120
|
}
|
|
5938
|
-
|
|
6121
|
+
fileSuccessCount++;
|
|
5939
6122
|
}
|
|
5940
|
-
|
|
5941
|
-
|
|
5942
|
-
|
|
5943
|
-
|
|
5944
|
-
|
|
6123
|
+
if (fileFailed) {
|
|
6124
|
+
content = originalContent;
|
|
6125
|
+
continue;
|
|
6126
|
+
}
|
|
6127
|
+
const afterHash = contentHash(content);
|
|
6128
|
+
if (afterHash === beforeHash) {
|
|
6129
|
+
results.push(`NO-OP: ${fileEdits[0].relPath} batch produced no disk changes`);
|
|
6130
|
+
continue;
|
|
6131
|
+
}
|
|
6132
|
+
pendingWrites.push({
|
|
6133
|
+
fullPath,
|
|
6134
|
+
relPath: fileEdits[0].relPath,
|
|
6135
|
+
content,
|
|
6136
|
+
beforeHash,
|
|
6137
|
+
afterHash,
|
|
6138
|
+
editCount: fileSuccessCount
|
|
5945
6139
|
});
|
|
6140
|
+
successCount += fileSuccessCount;
|
|
5946
6141
|
} catch (error) {
|
|
5947
6142
|
results.push(`ERROR: ${fullPath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
5948
6143
|
failCount++;
|
|
5949
6144
|
}
|
|
5950
6145
|
}
|
|
5951
|
-
|
|
6146
|
+
if (failCount === 0) {
|
|
6147
|
+
for (const write2 of pendingWrites) {
|
|
6148
|
+
await writeFile4(write2.fullPath, write2.content, "utf-8");
|
|
6149
|
+
recordChange(this.workingDir, {
|
|
6150
|
+
tool: "batch_edit",
|
|
6151
|
+
file: write2.relPath,
|
|
6152
|
+
summary: `Batch: ${write2.editCount} edit(s) in ${write2.relPath}`
|
|
6153
|
+
});
|
|
6154
|
+
}
|
|
6155
|
+
}
|
|
6156
|
+
const appliedCount = failCount === 0 ? successCount : 0;
|
|
6157
|
+
const summary = `${appliedCount} edit(s) applied, ${failCount} failed across ${byFile.size} file(s)` + (failCount > 0 ? " — atomic batch aborted; no files modified" : "");
|
|
5952
6158
|
return {
|
|
5953
6159
|
success: failCount === 0,
|
|
5954
6160
|
output: `${summary}
|
|
5955
6161
|
${results.join("\n")}`,
|
|
5956
6162
|
error: failCount > 0 ? `${failCount} edit(s) failed` : void 0,
|
|
5957
|
-
durationMs: performance.now() - start2
|
|
6163
|
+
durationMs: performance.now() - start2,
|
|
6164
|
+
mutated: failCount === 0 && pendingWrites.length > 0,
|
|
6165
|
+
mutatedFiles: failCount === 0 ? pendingWrites.map((w) => w.relPath) : [],
|
|
6166
|
+
noop: failCount === 0 && pendingWrites.length === 0,
|
|
6167
|
+
partial: false,
|
|
6168
|
+
beforeHash: pendingWrites.length === 1 ? pendingWrites[0].beforeHash : void 0,
|
|
6169
|
+
afterHash: pendingWrites.length === 1 ? pendingWrites[0].afterHash : void 0
|
|
5958
6170
|
};
|
|
5959
6171
|
}
|
|
5960
6172
|
};
|
|
@@ -5969,6 +6181,7 @@ var init_file_patch = __esm({
|
|
|
5969
6181
|
"packages/execution/dist/tools/file-patch.js"() {
|
|
5970
6182
|
"use strict";
|
|
5971
6183
|
init_change_log();
|
|
6184
|
+
init_edit_metadata();
|
|
5972
6185
|
FilePatchTool = class {
|
|
5973
6186
|
name = "file_patch";
|
|
5974
6187
|
description = "Edit specific line ranges in a file. More precise than string matching for large files. Modes: 'replace' replaces lines start_line..end_line with new_content, 'insert_before' inserts before start_line, 'insert_after' inserts after start_line, 'delete' removes lines start_line..end_line. Use dry_run to preview changes.";
|
|
@@ -5989,7 +6202,19 @@ var init_file_patch = __esm({
|
|
|
5989
6202
|
},
|
|
5990
6203
|
new_content: {
|
|
5991
6204
|
type: "string",
|
|
5992
|
-
description: "Replacement content (for replace mode) or content to insert (for insert modes). Not needed for delete mode."
|
|
6205
|
+
description: "Replacement content (for replace mode) or content to insert (for insert modes). Required for replace and insert modes. Not needed for delete mode."
|
|
6206
|
+
},
|
|
6207
|
+
expected_hash: {
|
|
6208
|
+
type: "string",
|
|
6209
|
+
description: "SHA-256 from the most recent file_read. Required for insert modes and accepted for all modes."
|
|
6210
|
+
},
|
|
6211
|
+
expected_old_content: {
|
|
6212
|
+
type: "string",
|
|
6213
|
+
description: "Exact current content in start_line..end_line. Required for replace/delete unless expected_hash is provided."
|
|
6214
|
+
},
|
|
6215
|
+
allow_empty_content: {
|
|
6216
|
+
type: "boolean",
|
|
6217
|
+
description: "Set true only when an intentional blank replacement/insert is required."
|
|
5993
6218
|
},
|
|
5994
6219
|
mode: {
|
|
5995
6220
|
type: "string",
|
|
@@ -6011,9 +6236,13 @@ var init_file_patch = __esm({
|
|
|
6011
6236
|
const filePath = args["path"];
|
|
6012
6237
|
const startLine = args["start_line"];
|
|
6013
6238
|
const endLine = args["end_line"] ?? startLine;
|
|
6014
|
-
const newContent = args["new_content"] ?? "";
|
|
6015
6239
|
const mode = args["mode"] ?? "replace";
|
|
6016
6240
|
const dryRun = args["dry_run"] === true;
|
|
6241
|
+
const hasNewContent = typeof args["new_content"] === "string";
|
|
6242
|
+
const newContent = hasNewContent ? args["new_content"] : "";
|
|
6243
|
+
const expectedHash = extractExpectedHash(args);
|
|
6244
|
+
const expectedOldContent = typeof args["expected_old_content"] === "string" ? args["expected_old_content"] : void 0;
|
|
6245
|
+
const allowEmptyContent = args["allow_empty_content"] === true;
|
|
6017
6246
|
const start2 = performance.now();
|
|
6018
6247
|
try {
|
|
6019
6248
|
if (!Number.isInteger(startLine) || startLine < 1) {
|
|
@@ -6034,8 +6263,21 @@ var init_file_patch = __esm({
|
|
|
6034
6263
|
}
|
|
6035
6264
|
const fullPath = resolve12(this.workingDir, filePath);
|
|
6036
6265
|
const content = await readFile8(fullPath, "utf-8");
|
|
6266
|
+
const beforeHash = contentHash(content);
|
|
6037
6267
|
const lines = content.split("\n");
|
|
6038
6268
|
const totalLines = lines.length;
|
|
6269
|
+
if (expectedHash && expectedHash !== beforeHash) {
|
|
6270
|
+
return {
|
|
6271
|
+
success: false,
|
|
6272
|
+
output: "",
|
|
6273
|
+
error: hashMismatchMessage(filePath, expectedHash, beforeHash),
|
|
6274
|
+
durationMs: performance.now() - start2,
|
|
6275
|
+
mutated: false,
|
|
6276
|
+
mutatedFiles: [],
|
|
6277
|
+
beforeHash,
|
|
6278
|
+
afterHash: beforeHash
|
|
6279
|
+
};
|
|
6280
|
+
}
|
|
6039
6281
|
if (startLine > totalLines) {
|
|
6040
6282
|
return {
|
|
6041
6283
|
success: false,
|
|
@@ -6047,6 +6289,60 @@ var init_file_patch = __esm({
|
|
|
6047
6289
|
const effectiveEnd = Math.min(endLine, totalLines);
|
|
6048
6290
|
const startIdx = startLine - 1;
|
|
6049
6291
|
const endIdx = effectiveEnd;
|
|
6292
|
+
const oldTargetContent = lines.slice(startIdx, endIdx).join("\n");
|
|
6293
|
+
if ((mode === "replace" || mode === "delete") && !expectedHash && expectedOldContent === void 0) {
|
|
6294
|
+
return {
|
|
6295
|
+
success: false,
|
|
6296
|
+
output: "",
|
|
6297
|
+
error: `file_patch ${mode} requires targeted context: pass expected_hash from file_read or expected_old_content copied exactly from lines ${startLine}-${effectiveEnd}.`,
|
|
6298
|
+
durationMs: performance.now() - start2,
|
|
6299
|
+
mutated: false,
|
|
6300
|
+
mutatedFiles: [],
|
|
6301
|
+
beforeHash,
|
|
6302
|
+
afterHash: beforeHash
|
|
6303
|
+
};
|
|
6304
|
+
}
|
|
6305
|
+
if ((mode === "insert_before" || mode === "insert_after") && !expectedHash) {
|
|
6306
|
+
return {
|
|
6307
|
+
success: false,
|
|
6308
|
+
output: "",
|
|
6309
|
+
error: `file_patch ${mode} requires expected_hash from the most recent file_read so line numbers are versioned.`,
|
|
6310
|
+
durationMs: performance.now() - start2,
|
|
6311
|
+
mutated: false,
|
|
6312
|
+
mutatedFiles: [],
|
|
6313
|
+
beforeHash,
|
|
6314
|
+
afterHash: beforeHash
|
|
6315
|
+
};
|
|
6316
|
+
}
|
|
6317
|
+
if (expectedOldContent !== void 0 && expectedOldContent !== oldTargetContent) {
|
|
6318
|
+
return {
|
|
6319
|
+
success: false,
|
|
6320
|
+
output: "",
|
|
6321
|
+
error: `Refusing to patch ${filePath}: expected_old_content does not match current lines ${startLine}-${effectiveEnd}.
|
|
6322
|
+
|
|
6323
|
+
Current content:
|
|
6324
|
+
${oldTargetContent}
|
|
6325
|
+
|
|
6326
|
+
Re-read the target range and retry with exact current content.`,
|
|
6327
|
+
durationMs: performance.now() - start2,
|
|
6328
|
+
mutated: false,
|
|
6329
|
+
mutatedFiles: [],
|
|
6330
|
+
beforeHash,
|
|
6331
|
+
afterHash: beforeHash
|
|
6332
|
+
};
|
|
6333
|
+
}
|
|
6334
|
+
if ((mode === "replace" || mode === "insert_before" || mode === "insert_after") && (!hasNewContent || newContent.length === 0 && !allowEmptyContent)) {
|
|
6335
|
+
return {
|
|
6336
|
+
success: false,
|
|
6337
|
+
output: "",
|
|
6338
|
+
error: `file_patch mode=${mode} requires non-empty new_content. Use mode="delete" for removal, or set allow_empty_content=true for an intentional blank edit.`,
|
|
6339
|
+
durationMs: performance.now() - start2,
|
|
6340
|
+
mutated: false,
|
|
6341
|
+
mutatedFiles: [],
|
|
6342
|
+
beforeHash,
|
|
6343
|
+
afterHash: beforeHash
|
|
6344
|
+
};
|
|
6345
|
+
}
|
|
6050
6346
|
const newLines = newContent.length > 0 ? newContent.split("\n") : [];
|
|
6051
6347
|
let resultLines;
|
|
6052
6348
|
let description;
|
|
@@ -6110,10 +6406,31 @@ ${newSection}`;
|
|
|
6110
6406
|
output: `[DRY RUN] ${diff}
|
|
6111
6407
|
|
|
6112
6408
|
File NOT modified. Remove dry_run to apply.`,
|
|
6113
|
-
durationMs: performance.now() - start2
|
|
6409
|
+
durationMs: performance.now() - start2,
|
|
6410
|
+
mutated: false,
|
|
6411
|
+
mutatedFiles: [],
|
|
6412
|
+
diff,
|
|
6413
|
+
dryRun: true,
|
|
6414
|
+
beforeHash,
|
|
6415
|
+
afterHash: beforeHash
|
|
6114
6416
|
};
|
|
6115
6417
|
}
|
|
6116
|
-
|
|
6418
|
+
const updatedContent = resultLines.join("\n");
|
|
6419
|
+
const afterHash = contentHash(updatedContent);
|
|
6420
|
+
if (afterHash === beforeHash) {
|
|
6421
|
+
return {
|
|
6422
|
+
success: true,
|
|
6423
|
+
output: `[NO-OP — ${filePath}: ${description}; resulting content is identical to disk.]`,
|
|
6424
|
+
durationMs: performance.now() - start2,
|
|
6425
|
+
mutated: false,
|
|
6426
|
+
mutatedFiles: [],
|
|
6427
|
+
diff,
|
|
6428
|
+
noop: true,
|
|
6429
|
+
beforeHash,
|
|
6430
|
+
afterHash
|
|
6431
|
+
};
|
|
6432
|
+
}
|
|
6433
|
+
await writeFile5(fullPath, updatedContent, "utf-8");
|
|
6117
6434
|
recordChange(this.workingDir, {
|
|
6118
6435
|
tool: "file_patch",
|
|
6119
6436
|
file: filePath,
|
|
@@ -6123,10 +6440,16 @@ File NOT modified. Remove dry_run to apply.`,
|
|
|
6123
6440
|
});
|
|
6124
6441
|
return {
|
|
6125
6442
|
success: true,
|
|
6126
|
-
output: `${filePath}: ${description} (${totalLines} → ${resultLines.length} total lines)
|
|
6443
|
+
output: `${filePath}: ${description} (${totalLines} → ${resultLines.length} total lines, sha256 ${beforeHash} → ${afterHash})
|
|
6127
6444
|
|
|
6128
6445
|
${diff}`,
|
|
6129
|
-
durationMs: performance.now() - start2
|
|
6446
|
+
durationMs: performance.now() - start2,
|
|
6447
|
+
mutated: true,
|
|
6448
|
+
mutatedFiles: [filePath],
|
|
6449
|
+
diff,
|
|
6450
|
+
noop: false,
|
|
6451
|
+
beforeHash,
|
|
6452
|
+
afterHash
|
|
6130
6453
|
};
|
|
6131
6454
|
} catch (error) {
|
|
6132
6455
|
return {
|
|
@@ -6706,7 +7029,7 @@ var init_git_info = __esm({
|
|
|
6706
7029
|
});
|
|
6707
7030
|
|
|
6708
7031
|
// packages/execution/dist/tools/jibberlink.js
|
|
6709
|
-
import { createCipheriv, createDecipheriv, createHash, randomBytes as randomBytes5 } from "node:crypto";
|
|
7032
|
+
import { createCipheriv, createDecipheriv, createHash as createHash2, randomBytes as randomBytes5 } from "node:crypto";
|
|
6710
7033
|
function crc16(bytes) {
|
|
6711
7034
|
let crc = 65535;
|
|
6712
7035
|
for (let i2 = 0; i2 < bytes.length; i2++) {
|
|
@@ -6719,7 +7042,7 @@ function crc16(bytes) {
|
|
|
6719
7042
|
}
|
|
6720
7043
|
function deriveRoomKey(roomId, secret = "jibberlink-v1") {
|
|
6721
7044
|
const material = `${secret}\0${roomId}`;
|
|
6722
|
-
return
|
|
7045
|
+
return createHash2("sha256").update(material).digest();
|
|
6723
7046
|
}
|
|
6724
7047
|
function aesGcmEncrypt(key, plaintext) {
|
|
6725
7048
|
if (key.length !== 32)
|
|
@@ -6805,7 +7128,7 @@ __export(nexus_exports, {
|
|
|
6805
7128
|
import { readFile as readFile9, writeFile as writeFile6, mkdir as mkdir3, chmod, unlink, readdir as readdir2, open as fsOpen, copyFile as copyFile2 } from "node:fs/promises";
|
|
6806
7129
|
import { existsSync as existsSync14, readFileSync as readFileSync12, watch as fsWatchLocal } from "node:fs";
|
|
6807
7130
|
import { resolve as resolve13, join as join18 } from "node:path";
|
|
6808
|
-
import { randomBytes as randomBytes6, createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, scryptSync, createHash as
|
|
7131
|
+
import { randomBytes as randomBytes6, createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2, scryptSync, createHash as createHash3 } from "node:crypto";
|
|
6809
7132
|
import { execSync as execSync8, spawn as spawn2 } from "node:child_process";
|
|
6810
7133
|
import { hostname, userInfo, homedir as homedir4 } from "node:os";
|
|
6811
7134
|
function readBundledDependencySpec(packageName, fallback) {
|
|
@@ -12087,7 +12410,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12087
12410
|
// =========================================================================
|
|
12088
12411
|
async doConnect(args) {
|
|
12089
12412
|
await this.ensureDir();
|
|
12090
|
-
const currentScriptHash =
|
|
12413
|
+
const currentScriptHash = createHash3("sha256").update(DAEMON_SCRIPT).digest("hex").slice(0, 16);
|
|
12091
12414
|
const existingPid = this.getDaemonPid();
|
|
12092
12415
|
if (existingPid) {
|
|
12093
12416
|
let processAlive = false;
|
|
@@ -12693,7 +13016,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12693
13016
|
} catch {
|
|
12694
13017
|
const privKey = randomBytes6(32);
|
|
12695
13018
|
privKeyHex = privKey.toString("hex");
|
|
12696
|
-
address = "0x" +
|
|
13019
|
+
address = "0x" + createHash3("sha256").update(privKey).digest("hex").slice(0, 40);
|
|
12697
13020
|
privKey.fill(0);
|
|
12698
13021
|
}
|
|
12699
13022
|
const salt = randomBytes6(32);
|
|
@@ -12755,7 +13078,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
12755
13078
|
} catch {
|
|
12756
13079
|
const privKey = randomBytes6(32);
|
|
12757
13080
|
privKeyHex = privKey.toString("hex");
|
|
12758
|
-
address = "0x" +
|
|
13081
|
+
address = "0x" + createHash3("sha256").update(privKey).digest("hex").slice(0, 40);
|
|
12759
13082
|
privKey.fill(0);
|
|
12760
13083
|
}
|
|
12761
13084
|
const salt = randomBytes6(32);
|
|
@@ -13278,7 +13601,7 @@ process.on('SIGINT', () => process.emit('SIGTERM'));
|
|
|
13278
13601
|
}
|
|
13279
13602
|
}
|
|
13280
13603
|
const nonce = randomBytes6(16).toString("hex");
|
|
13281
|
-
const hash =
|
|
13604
|
+
const hash = createHash3("sha256").update(`${modelName}:${nonce}:${Date.now()}`).digest("hex");
|
|
13282
13605
|
const bar = (s2) => "█".repeat(Math.round(s2 / 5)) + "░".repeat(20 - Math.round(s2 / 5));
|
|
13283
13606
|
const mem = vramMb > 24e3 ? 95 : vramMb > 16e3 ? 80 : vramMb > 8e3 ? 60 : vramMb > 0 ? 40 : 20;
|
|
13284
13607
|
await this.ensureDir();
|
|
@@ -13483,6 +13806,10 @@ Process error: ${err.message}`;
|
|
|
13483
13806
|
return null;
|
|
13484
13807
|
return toInfo(entry);
|
|
13485
13808
|
}
|
|
13809
|
+
getLatestTask() {
|
|
13810
|
+
const entry = Array.from(this.tasks.values()).at(-1);
|
|
13811
|
+
return entry ? toInfo(entry) : null;
|
|
13812
|
+
}
|
|
13486
13813
|
getOutput(id, tail) {
|
|
13487
13814
|
const entry = this.tasks.get(id);
|
|
13488
13815
|
if (!entry)
|
|
@@ -13573,7 +13900,7 @@ Process error: ${err.message}`;
|
|
|
13573
13900
|
workingDir;
|
|
13574
13901
|
manager;
|
|
13575
13902
|
name = "background_run";
|
|
13576
|
-
description =
|
|
13903
|
+
description = `Run a shell command in the background. Returns a task ID immediately. Use task_status(task_id="...") to check progress and task_output(task_id="...") to read results. Useful for long-running commands (builds, tests) that shouldn't block the agent.`;
|
|
13577
13904
|
parameters = {
|
|
13578
13905
|
type: "object",
|
|
13579
13906
|
properties: {
|
|
@@ -13598,7 +13925,7 @@ Process error: ${err.message}`;
|
|
|
13598
13925
|
success: true,
|
|
13599
13926
|
output: `Background task started: ${taskId}
|
|
13600
13927
|
Command: ${command}
|
|
13601
|
-
Use task_status or task_output to check progress.`,
|
|
13928
|
+
Use task_status(task_id="${taskId}") or task_output(task_id="${taskId}") to check progress.`,
|
|
13602
13929
|
durationMs: Date.now() - start2
|
|
13603
13930
|
};
|
|
13604
13931
|
}
|
|
@@ -13650,32 +13977,43 @@ Exit code: ${task.exitCode ?? "N/A"}`,
|
|
|
13650
13977
|
TaskOutputTool = class {
|
|
13651
13978
|
manager;
|
|
13652
13979
|
name = "task_output";
|
|
13653
|
-
description = "Read the output of a background task. Returns stdout+stderr combined. Use tail parameter to get only the last N lines.";
|
|
13980
|
+
description = "Read the output of a background task. Returns stdout+stderr combined. If task_id is omitted, uses the most recently created task. Use tail parameter to get only the last N lines.";
|
|
13654
13981
|
parameters = {
|
|
13655
13982
|
type: "object",
|
|
13656
13983
|
properties: {
|
|
13657
|
-
task_id: { type: "string", description: "Task ID to read output from" },
|
|
13984
|
+
task_id: { type: "string", description: "Task ID to read output from (optional — falls back to most recent task)" },
|
|
13658
13985
|
tail: { type: "number", description: "Only return the last N lines (optional)" }
|
|
13659
|
-
}
|
|
13660
|
-
required: ["task_id"]
|
|
13986
|
+
}
|
|
13661
13987
|
};
|
|
13662
13988
|
constructor(manager) {
|
|
13663
13989
|
this.manager = manager;
|
|
13664
13990
|
}
|
|
13665
13991
|
async execute(args) {
|
|
13666
13992
|
const start2 = Date.now();
|
|
13667
|
-
const
|
|
13993
|
+
const explicitTaskId = typeof args["task_id"] === "string" ? args["task_id"].trim() : "";
|
|
13994
|
+
const fallbackTask = explicitTaskId ? null : this.manager.getLatestTask();
|
|
13995
|
+
const taskId = explicitTaskId || fallbackTask?.id || "";
|
|
13668
13996
|
const tail = typeof args["tail"] === "number" ? args["tail"] : void 0;
|
|
13669
13997
|
const output = this.manager.getOutput(taskId, tail);
|
|
13670
13998
|
if (output === null) {
|
|
13999
|
+
if (!taskId) {
|
|
14000
|
+
return {
|
|
14001
|
+
success: false,
|
|
14002
|
+
output: "",
|
|
14003
|
+
error: "task_id is required when no background tasks exist yet",
|
|
14004
|
+
durationMs: Date.now() - start2
|
|
14005
|
+
};
|
|
14006
|
+
}
|
|
13671
14007
|
return { success: false, output: "", error: `Task not found: ${taskId}`, durationMs: Date.now() - start2 };
|
|
13672
14008
|
}
|
|
13673
14009
|
const task = this.manager.getTask(taskId);
|
|
13674
14010
|
const header = task ? `[${task.status}${task.exitCode !== null ? `, exit ${task.exitCode}` : ""}]
|
|
14011
|
+
` : "";
|
|
14012
|
+
const fallbackNote = explicitTaskId ? "" : fallbackTask ? `[fallback to ${taskId}]
|
|
13675
14013
|
` : "";
|
|
13676
14014
|
return {
|
|
13677
14015
|
success: true,
|
|
13678
|
-
output: header + (output || "(no output yet)"),
|
|
14016
|
+
output: fallbackNote + header + (output || "(no output yet)"),
|
|
13679
14017
|
durationMs: Date.now() - start2
|
|
13680
14018
|
};
|
|
13681
14019
|
}
|
|
@@ -89943,7 +90281,7 @@ var require_auto = __commonJS({
|
|
|
89943
90281
|
// ../node_modules/acme-client/src/client.js
|
|
89944
90282
|
var require_client = __commonJS({
|
|
89945
90283
|
"../node_modules/acme-client/src/client.js"(exports, module) {
|
|
89946
|
-
var { createHash:
|
|
90284
|
+
var { createHash: createHash21 } = __require("crypto");
|
|
89947
90285
|
var { getPemBodyAsB64u } = require_crypto();
|
|
89948
90286
|
var { log: log22 } = require_logger();
|
|
89949
90287
|
var HttpClient = require_http();
|
|
@@ -90254,14 +90592,14 @@ var require_client = __commonJS({
|
|
|
90254
90592
|
*/
|
|
90255
90593
|
async getChallengeKeyAuthorization(challenge) {
|
|
90256
90594
|
const jwk = this.http.getJwk();
|
|
90257
|
-
const keysum =
|
|
90595
|
+
const keysum = createHash21("sha256").update(JSON.stringify(jwk));
|
|
90258
90596
|
const thumbprint = keysum.digest("base64url");
|
|
90259
90597
|
const result = `${challenge.token}.${thumbprint}`;
|
|
90260
90598
|
if (challenge.type === "http-01") {
|
|
90261
90599
|
return result;
|
|
90262
90600
|
}
|
|
90263
90601
|
if (challenge.type === "dns-01") {
|
|
90264
|
-
return
|
|
90602
|
+
return createHash21("sha256").update(result).digest("base64url");
|
|
90265
90603
|
}
|
|
90266
90604
|
if (challenge.type === "tls-alpn-01") {
|
|
90267
90605
|
return result;
|
|
@@ -232941,7 +233279,7 @@ var require_websocket2 = __commonJS({
|
|
|
232941
233279
|
var http6 = __require("http");
|
|
232942
233280
|
var net5 = __require("net");
|
|
232943
233281
|
var tls2 = __require("tls");
|
|
232944
|
-
var { randomBytes: randomBytes25, createHash:
|
|
233282
|
+
var { randomBytes: randomBytes25, createHash: createHash21 } = __require("crypto");
|
|
232945
233283
|
var { Duplex: Duplex3, Readable } = __require("stream");
|
|
232946
233284
|
var { URL: URL3 } = __require("url");
|
|
232947
233285
|
var PerMessageDeflate2 = require_permessage_deflate2();
|
|
@@ -233601,7 +233939,7 @@ var require_websocket2 = __commonJS({
|
|
|
233601
233939
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
233602
233940
|
return;
|
|
233603
233941
|
}
|
|
233604
|
-
const digest3 =
|
|
233942
|
+
const digest3 = createHash21("sha1").update(key + GUID).digest("base64");
|
|
233605
233943
|
if (res.headers["sec-websocket-accept"] !== digest3) {
|
|
233606
233944
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
233607
233945
|
return;
|
|
@@ -233968,7 +234306,7 @@ var require_websocket_server = __commonJS({
|
|
|
233968
234306
|
var EventEmitter13 = __require("events");
|
|
233969
234307
|
var http6 = __require("http");
|
|
233970
234308
|
var { Duplex: Duplex3 } = __require("stream");
|
|
233971
|
-
var { createHash:
|
|
234309
|
+
var { createHash: createHash21 } = __require("crypto");
|
|
233972
234310
|
var extension2 = require_extension2();
|
|
233973
234311
|
var PerMessageDeflate2 = require_permessage_deflate2();
|
|
233974
234312
|
var subprotocol2 = require_subprotocol();
|
|
@@ -234269,7 +234607,7 @@ var require_websocket_server = __commonJS({
|
|
|
234269
234607
|
);
|
|
234270
234608
|
}
|
|
234271
234609
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
234272
|
-
const digest3 =
|
|
234610
|
+
const digest3 = createHash21("sha1").update(key + GUID).digest("base64");
|
|
234273
234611
|
const headers = [
|
|
234274
234612
|
"HTTP/1.1 101 Switching Protocols",
|
|
234275
234613
|
"Upgrade: websocket",
|
|
@@ -247076,13 +247414,13 @@ Justification: ${justification || "(none provided)"}`,
|
|
|
247076
247414
|
}
|
|
247077
247415
|
const snapshot = JSON.stringify(this.selfState, null, 2);
|
|
247078
247416
|
try {
|
|
247079
|
-
const { createHash:
|
|
247417
|
+
const { createHash: createHash21 } = await import("node:crypto");
|
|
247080
247418
|
const snapshotDir = join27(this.cwd, ".oa", "identity", "snapshots");
|
|
247081
247419
|
await mkdir6(snapshotDir, { recursive: true });
|
|
247082
247420
|
const version4 = this.selfState.version;
|
|
247083
247421
|
const snapshotPath = join27(snapshotDir, `v${version4}.json`);
|
|
247084
247422
|
await writeFile11(snapshotPath, snapshot, "utf8");
|
|
247085
|
-
const hash =
|
|
247423
|
+
const hash = createHash21("sha256").update(snapshot).digest("hex");
|
|
247086
247424
|
await writeFile11(join27(this.cwd, ".oa", "identity", "latest-hash.txt"), hash, "utf8");
|
|
247087
247425
|
let ipfsCid = "";
|
|
247088
247426
|
try {
|
|
@@ -247215,8 +247553,8 @@ New: ${newNarrative.slice(0, 200)}...`,
|
|
|
247215
247553
|
}
|
|
247216
247554
|
// ── Helpers ──────────────────────────────────────────────────────────────
|
|
247217
247555
|
createDefaultState() {
|
|
247218
|
-
const { createHash:
|
|
247219
|
-
const machineId =
|
|
247556
|
+
const { createHash: createHash21 } = __require("node:crypto");
|
|
247557
|
+
const machineId = createHash21("sha256").update(this.cwd).digest("hex").slice(0, 12);
|
|
247220
247558
|
return {
|
|
247221
247559
|
self_id: `oa-${machineId}`,
|
|
247222
247560
|
version: 1,
|
|
@@ -247298,9 +247636,9 @@ New: ${newNarrative.slice(0, 200)}...`,
|
|
|
247298
247636
|
let cid;
|
|
247299
247637
|
if (this.selfState.version > prevVersion) {
|
|
247300
247638
|
try {
|
|
247301
|
-
const { createHash:
|
|
247639
|
+
const { createHash: createHash21 } = await import("node:crypto");
|
|
247302
247640
|
const stateJson = JSON.stringify(this.selfState);
|
|
247303
|
-
const hash =
|
|
247641
|
+
const hash = createHash21("sha256").update(stateJson).digest("hex").slice(0, 32);
|
|
247304
247642
|
const cidsPath = join27(this.cwd, ".oa", "identity", "cids.json");
|
|
247305
247643
|
const cidsData = { latest: "", hash, version: this.selfState.version };
|
|
247306
247644
|
try {
|
|
@@ -253007,7 +253345,7 @@ import { execSync as execSync22, exec as execCb, spawnSync as spawnSync2 } from
|
|
|
253007
253345
|
import { readFile as readFile16, writeFile as writeFile17, mkdir as mkdir12 } from "node:fs/promises";
|
|
253008
253346
|
import { resolve as resolve24, join as join41 } from "node:path";
|
|
253009
253347
|
import { homedir as homedir10 } from "node:os";
|
|
253010
|
-
import { randomBytes as randomBytes11, createHash as
|
|
253348
|
+
import { randomBytes as randomBytes11, createHash as createHash4 } from "node:crypto";
|
|
253011
253349
|
function isValidCron(expr) {
|
|
253012
253350
|
const parts = expr.trim().split(/\s+/);
|
|
253013
253351
|
if (parts.length !== 5)
|
|
@@ -253330,7 +253668,7 @@ var init_scheduler = __esm({
|
|
|
253330
253668
|
}
|
|
253331
253669
|
const scope = String(args["scope"] ?? "local");
|
|
253332
253670
|
const fingerprint = `${resolve24(this.workingDir)}|${task}|${cronExpr}|${scope}`;
|
|
253333
|
-
const id = `sched-${
|
|
253671
|
+
const id = `sched-${createHash4("sha1").update(fingerprint).digest("hex").slice(0, 8)}`;
|
|
253334
253672
|
const oneShot = Boolean(args["one_shot"]);
|
|
253335
253673
|
const maxRuns = typeof args["max_runs"] === "number" ? args["max_runs"] : void 0;
|
|
253336
253674
|
const newTask = {
|
|
@@ -256873,7 +257211,7 @@ var init_import_graph = __esm({
|
|
|
256873
257211
|
import { createRequire as __createRequireGlob } from "node:module";
|
|
256874
257212
|
import ignore from "ignore";
|
|
256875
257213
|
import { readFile as readFile21, stat as stat4 } from "node:fs/promises";
|
|
256876
|
-
import { createHash as
|
|
257214
|
+
import { createHash as createHash5 } from "node:crypto";
|
|
256877
257215
|
import { join as join49, relative as relative4, extname as extname8, basename as basename11 } from "node:path";
|
|
256878
257216
|
var __requireGlob, glob2, DEFAULT_EXCLUDE, LANGUAGE_MAP, CodebaseIndexer;
|
|
256879
257217
|
var init_codebase_indexer = __esm({
|
|
@@ -256941,7 +257279,7 @@ var init_codebase_indexer = __esm({
|
|
|
256941
257279
|
if (fileStat.size > this.config.maxFileSize)
|
|
256942
257280
|
continue;
|
|
256943
257281
|
const content = await readFile21(fullPath);
|
|
256944
|
-
const hash =
|
|
257282
|
+
const hash = createHash5("sha256").update(content).digest("hex");
|
|
256945
257283
|
const ext = extname8(relativePath);
|
|
256946
257284
|
indexed.push({
|
|
256947
257285
|
path: fullPath,
|
|
@@ -501260,7 +501598,7 @@ var init_ts_morph_parser = __esm({
|
|
|
501260
501598
|
|
|
501261
501599
|
// packages/indexer/dist/code-graph-db.js
|
|
501262
501600
|
import { createRequire as createRequire2 } from "node:module";
|
|
501263
|
-
import { createHash as
|
|
501601
|
+
import { createHash as createHash6 } from "node:crypto";
|
|
501264
501602
|
import { mkdirSync as mkdirSync12, readFileSync as readFileSync26 } from "node:fs";
|
|
501265
501603
|
import { join as join50, dirname as dirname14, extname as extname9 } from "node:path";
|
|
501266
501604
|
function loadDatabaseCtor() {
|
|
@@ -501332,7 +501670,7 @@ function extractFileImports(content, filePath) {
|
|
|
501332
501670
|
return imports.map((p2) => p2.replace(/\.(js|ts|jsx|tsx|mjs|cjs)$/, ""));
|
|
501333
501671
|
}
|
|
501334
501672
|
function hashContent(content) {
|
|
501335
|
-
return
|
|
501673
|
+
return createHash6("sha1").update(content).digest("hex").slice(0, 16);
|
|
501336
501674
|
}
|
|
501337
501675
|
function detectLanguage(filePath) {
|
|
501338
501676
|
return EXT_TO_LANG[extname9(filePath)] ?? "unknown";
|
|
@@ -509952,7 +510290,7 @@ var init_environment_snapshot = __esm({
|
|
|
509952
510290
|
import { execSync as execSync42 } from "node:child_process";
|
|
509953
510291
|
import { existsSync as existsSync47, mkdirSync as mkdirSync24, writeFileSync as writeFileSync22, readFileSync as readFileSync39, readdirSync as readdirSync14, unlinkSync as unlinkSync11 } from "node:fs";
|
|
509954
510292
|
import { join as join64, basename as basename12 } from "node:path";
|
|
509955
|
-
import { createHash as
|
|
510293
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
509956
510294
|
function isYouTubeUrl2(url) {
|
|
509957
510295
|
return /(?:youtube\.com\/(?:watch|shorts|live|embed|v\/)|youtu\.be\/)/i.test(url);
|
|
509958
510296
|
}
|
|
@@ -509980,7 +510318,7 @@ function ensureFfmpeg() {
|
|
|
509980
510318
|
function imageHash(imagePath) {
|
|
509981
510319
|
try {
|
|
509982
510320
|
const data = readFileSync39(imagePath);
|
|
509983
|
-
return
|
|
510321
|
+
return createHash7("md5").update(data).digest("hex").slice(0, 12);
|
|
509984
510322
|
} catch {
|
|
509985
510323
|
return "unknown";
|
|
509986
510324
|
}
|
|
@@ -514004,14 +514342,14 @@ var init_artifact_inspector = __esm({
|
|
|
514004
514342
|
// packages/orchestrator/dist/lesson-bank.js
|
|
514005
514343
|
import { existsSync as existsSync53, mkdirSync as mkdirSync27, appendFileSync as appendFileSync2, readFileSync as readFileSync44 } from "node:fs";
|
|
514006
514344
|
import { join as join69, dirname as dirname19 } from "node:path";
|
|
514007
|
-
import { createHash as
|
|
514345
|
+
import { createHash as createHash8 } from "node:crypto";
|
|
514008
514346
|
function tokenize2(text) {
|
|
514009
514347
|
if (!text)
|
|
514010
514348
|
return [];
|
|
514011
514349
|
return text.toLowerCase().split(TOKENIZE_RE).filter((t2) => t2.length >= 3).slice(0, 80);
|
|
514012
514350
|
}
|
|
514013
514351
|
function shortHash(s2) {
|
|
514014
|
-
return
|
|
514352
|
+
return createHash8("sha256").update(s2).digest("hex").slice(0, 16);
|
|
514015
514353
|
}
|
|
514016
514354
|
function solicit(args) {
|
|
514017
514355
|
const { taskGoal, stem, reflections, successOutputPreview } = args;
|
|
@@ -517476,7 +517814,7 @@ var init_pprRetrieval = __esm({
|
|
|
517476
517814
|
import { join as join75 } from "node:path";
|
|
517477
517815
|
import { mkdirSync as mkdirSync29, existsSync as existsSync59 } from "node:fs";
|
|
517478
517816
|
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
517479
|
-
import { createHash as
|
|
517817
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
517480
517818
|
function readEpisodeAffect2(metadata) {
|
|
517481
517819
|
if (!metadata || typeof metadata !== "object")
|
|
517482
517820
|
return null;
|
|
@@ -517682,7 +518020,7 @@ var init_episodeStore = __esm({
|
|
|
517682
518020
|
insert(ep) {
|
|
517683
518021
|
const id = randomUUID8();
|
|
517684
518022
|
const now = Date.now();
|
|
517685
|
-
const
|
|
518023
|
+
const contentHash2 = createHash9("sha256").update(ep.content).digest("hex").slice(0, 16);
|
|
517686
518024
|
const modality = ep.modality ?? "text";
|
|
517687
518025
|
const rawImportance = ep.importance ?? autoImportance(ep.toolName ?? null, modality, ep.content);
|
|
517688
518026
|
const modulated = ep.emotionalState ? modulateImportance(sanitizeImportance(rawImportance), ep.emotionalState) : sanitizeImportance(rawImportance);
|
|
@@ -517691,13 +518029,13 @@ var init_episodeStore = __esm({
|
|
|
517691
518029
|
return "";
|
|
517692
518030
|
}
|
|
517693
518031
|
const decayClass = ep.decayClass ?? autoDecayClass(ep.toolName ?? null, modality, ep.content);
|
|
517694
|
-
const existing = this.db.prepare("SELECT id FROM episodes WHERE content_hash = ? AND session_id = ? LIMIT 1").get(
|
|
518032
|
+
const existing = this.db.prepare("SELECT id FROM episodes WHERE content_hash = ? AND session_id = ? LIMIT 1").get(contentHash2, ep.sessionId ?? null);
|
|
517695
518033
|
if (existing)
|
|
517696
518034
|
return existing.id;
|
|
517697
518035
|
this.db.prepare(`
|
|
517698
518036
|
INSERT INTO episodes (id, timestamp, session_id, task_id, turn_number, modality, tool_name, content, content_hash, metadata, importance, decay_class, strength)
|
|
517699
518037
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 1.0)
|
|
517700
|
-
`).run(id, now, ep.sessionId ?? null, ep.taskId ?? null, ep.turnNumber ?? null, modality, ep.toolName ?? null, ep.content,
|
|
518038
|
+
`).run(id, now, ep.sessionId ?? null, ep.taskId ?? null, ep.turnNumber ?? null, modality, ep.toolName ?? null, ep.content, contentHash2, ep.metadata ? JSON.stringify(ep.metadata) : null, importance, decayClass);
|
|
517701
518039
|
if (this.graph) {
|
|
517702
518040
|
try {
|
|
517703
518041
|
const episode = this.get(id);
|
|
@@ -522251,7 +522589,7 @@ var init_memoryStageContext = __esm({
|
|
|
522251
522589
|
});
|
|
522252
522590
|
|
|
522253
522591
|
// packages/memory/dist/sessionGist.js
|
|
522254
|
-
import { createHash as
|
|
522592
|
+
import { createHash as createHash10 } from "node:crypto";
|
|
522255
522593
|
function inferDomain(input) {
|
|
522256
522594
|
const blob = [
|
|
522257
522595
|
input.goal,
|
|
@@ -522276,7 +522614,7 @@ function inferDomain(input) {
|
|
|
522276
522614
|
return ranked[0][0];
|
|
522277
522615
|
}
|
|
522278
522616
|
function computeGoalHash(goal) {
|
|
522279
|
-
return
|
|
522617
|
+
return createHash10("sha256").update(goal.trim().toLowerCase()).digest("hex").slice(0, 16);
|
|
522280
522618
|
}
|
|
522281
522619
|
function clip(text, n2) {
|
|
522282
522620
|
if (!text)
|
|
@@ -522487,12 +522825,12 @@ var init_toolOutcomes = __esm({
|
|
|
522487
522825
|
});
|
|
522488
522826
|
|
|
522489
522827
|
// packages/memory/dist/stagnationRecipes.js
|
|
522490
|
-
import { createHash as
|
|
522828
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
522491
522829
|
function fingerprintSignature(fp) {
|
|
522492
522830
|
const normClusters = (fp.errorClusters ?? []).map((s2) => (s2 || "").toLowerCase().replace(/[0-9]+/g, "N").replace(/\s+/g, " ").trim()).filter(Boolean).sort();
|
|
522493
522831
|
const tool = (fp.stuckTool ?? "").toLowerCase().trim();
|
|
522494
522832
|
const blob = `tool=${tool};clusters=${normClusters.join("|")}`;
|
|
522495
|
-
return
|
|
522833
|
+
return createHash11("sha256").update(blob).digest("hex").slice(0, 16);
|
|
522496
522834
|
}
|
|
522497
522835
|
function crystallize(store2, input) {
|
|
522498
522836
|
const sig = fingerprintSignature(input.fingerprint);
|
|
@@ -522549,7 +522887,7 @@ var init_stagnationRecipes = __esm({
|
|
|
522549
522887
|
});
|
|
522550
522888
|
|
|
522551
522889
|
// packages/memory/dist/codebaseMap.js
|
|
522552
|
-
import { createHash as
|
|
522890
|
+
import { createHash as createHash12, randomUUID as randomUUID12 } from "node:crypto";
|
|
522553
522891
|
function freshNodeId() {
|
|
522554
522892
|
return randomUUID12();
|
|
522555
522893
|
}
|
|
@@ -522563,7 +522901,7 @@ var init_codebaseMap = __esm({
|
|
|
522563
522901
|
touchCount = /* @__PURE__ */ new Map();
|
|
522564
522902
|
constructor(db, repoRoot, commitSha) {
|
|
522565
522903
|
this.db = db;
|
|
522566
|
-
this.repoFp =
|
|
522904
|
+
this.repoFp = createHash12("sha256").update(`${repoRoot}::${commitSha ?? "no-commit"}`).digest("hex").slice(0, 16);
|
|
522567
522905
|
this.ensureSchema();
|
|
522568
522906
|
}
|
|
522569
522907
|
ensureSchema() {
|
|
@@ -522699,7 +523037,7 @@ var init_codebaseMap = __esm({
|
|
|
522699
523037
|
}
|
|
522700
523038
|
/** Stable composite id: `<kind>:<sha16(path)>` so insert ON CONFLICT works. */
|
|
522701
523039
|
idFor(kind, path11) {
|
|
522702
|
-
const h =
|
|
523040
|
+
const h = createHash12("sha256").update(`${this.repoFp}:${kind}:${path11}`).digest("hex").slice(0, 24);
|
|
522703
523041
|
return `${kind}-${h}`;
|
|
522704
523042
|
}
|
|
522705
523043
|
};
|
|
@@ -524758,7 +525096,7 @@ import { existsSync as existsSync66, readFileSync as readFileSync54, statSync as
|
|
|
524758
525096
|
import { execSync as execSync45 } from "node:child_process";
|
|
524759
525097
|
import { homedir as homedir22, platform as platform2, arch as arch2, totalmem as totalmem2, freemem as freemem2, hostname as hostname3 } from "node:os";
|
|
524760
525098
|
import { join as join82 } from "node:path";
|
|
524761
|
-
import { createHash as
|
|
525099
|
+
import { createHash as createHash13 } from "node:crypto";
|
|
524762
525100
|
function capturePreflightSnapshot(workingDir) {
|
|
524763
525101
|
const warnings = [];
|
|
524764
525102
|
const configFingerprints = {};
|
|
@@ -524925,7 +525263,7 @@ function expandPath(p2) {
|
|
|
524925
525263
|
return p2;
|
|
524926
525264
|
}
|
|
524927
525265
|
function sha2563(s2) {
|
|
524928
|
-
return
|
|
525266
|
+
return createHash13("sha256").update(s2).digest("hex").slice(0, 16);
|
|
524929
525267
|
}
|
|
524930
525268
|
function freeDiskBytes(path11 = "/tmp") {
|
|
524931
525269
|
try {
|
|
@@ -524997,6 +525335,9 @@ function classifyShellIntent(cmd) {
|
|
|
524997
525335
|
if (tokens.length === 0)
|
|
524998
525336
|
return { klass: "other", verb: "", tool: "" };
|
|
524999
525337
|
const first2 = tokens[0].toLowerCase();
|
|
525338
|
+
if (first2 === "test" || first2 === "[" || first2 === "[[") {
|
|
525339
|
+
return { klass: "read", verb: "test", tool: first2 };
|
|
525340
|
+
}
|
|
525000
525341
|
const isRunner = RUNNERS.has(first2);
|
|
525001
525342
|
let verbToken;
|
|
525002
525343
|
if (isRunner && tokens.length >= 2) {
|
|
@@ -526876,14 +527217,14 @@ Your NEXT tool call MUST be EXACTLY ONE of:
|
|
|
526876
527217
|
• file_write — create a new file
|
|
526877
527218
|
• file_edit — modify an existing file (find/replace)
|
|
526878
527219
|
• batch_edit — multiple find/replace edits in one call
|
|
526879
|
-
• file_patch — apply a
|
|
527220
|
+
• file_patch — apply a version-checked line-range patch
|
|
526880
527221
|
|
|
526881
527222
|
These are the ONLY four tools that count as creative edits. The following do NOT count and will NOT satisfy this directive:
|
|
526882
527223
|
• todo_write (only updates the todo list, not the filesystem)
|
|
526883
527224
|
• memory_write (writes to memory store, not the project)
|
|
526884
527225
|
• list_directory / file_read / file_explore / grep_search / shell
|
|
526885
527226
|
|
|
526886
|
-
Pick the SMALLEST concrete deliverable from the spec — typically the project entry point or the file most other modules depend on. Write a
|
|
527227
|
+
Pick the SMALLEST concrete deliverable from the spec — typically the project entry point or the file most other modules depend on. Write a complete, version-checked slice that changes disk state; you can iterate later. Do NOT issue another read or todo update before producing the next file_write/file_edit/batch_edit/file_patch.`;
|
|
526887
527228
|
messages2.push({ role: "system", content: reg61Msg });
|
|
526888
527229
|
const _cyclePart = cycleLabel ? ` (${cycleLabel})` : "";
|
|
526889
527230
|
this.emit({
|
|
@@ -526918,8 +527259,9 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
|
|
|
526918
527259
|
const _editTools = /* @__PURE__ */ new Set(["file_write", "file_edit", "batch_edit", "file_patch"]);
|
|
526919
527260
|
if (!_editTools.has(tc.name))
|
|
526920
527261
|
return null;
|
|
526921
|
-
const
|
|
526922
|
-
|
|
527262
|
+
const _editPaths = this._extractToolTargetPaths(tc.name, tc.arguments);
|
|
527263
|
+
const _editPath = _editPaths.find((p2) => !this._decomp2MainContextFiles.has(p2)) ?? "";
|
|
527264
|
+
if (!_editPath)
|
|
526923
527265
|
return null;
|
|
526924
527266
|
const _filesList = [...this._decomp2MainContextFiles].slice(0, 8).map((p2) => ` • ${p2}`).join("\n");
|
|
526925
527267
|
const _moreFiles = this._decomp2MainContextFiles.size > 8 ? `
|
|
@@ -526979,21 +527321,18 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
|
|
|
526979
527321
|
_trackDecomp2(tc, result, turn) {
|
|
526980
527322
|
if (process.env["OA_DISABLE_DECOMP2"] === "1")
|
|
526981
527323
|
return;
|
|
526982
|
-
if (
|
|
526983
|
-
const
|
|
526984
|
-
|
|
526985
|
-
|
|
526986
|
-
|
|
526987
|
-
|
|
526988
|
-
|
|
526989
|
-
|
|
526990
|
-
|
|
526991
|
-
this.
|
|
526992
|
-
|
|
526993
|
-
|
|
526994
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
526995
|
-
});
|
|
526996
|
-
}
|
|
527324
|
+
if (this._isRealProjectMutation(tc.name, result)) {
|
|
527325
|
+
const _editPaths = this._extractToolTargetPaths(tc.name, tc.arguments, result);
|
|
527326
|
+
for (const _editPath of _editPaths) {
|
|
527327
|
+
this._decomp2MainContextFiles.add(_editPath);
|
|
527328
|
+
const DECOMP2_FILE_SPREAD_THRESHOLD = 5;
|
|
527329
|
+
if (!this._decomp2GateActive && this._decomp2MainContextFiles.size >= DECOMP2_FILE_SPREAD_THRESHOLD && this._decomp2SubAgentCalls === 0) {
|
|
527330
|
+
this._decomp2GateActive = true;
|
|
527331
|
+
this.emit({
|
|
527332
|
+
type: "status",
|
|
527333
|
+
content: `DECOMP-2 NEW-FILE GATE ACTIVATED — ${this._decomp2MainContextFiles.size} distinct files edited in main context, 0 sub_agent calls; further edits to NEW files will be blocked until sub_agent is invoked`,
|
|
527334
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
527335
|
+
});
|
|
526997
527336
|
}
|
|
526998
527337
|
}
|
|
526999
527338
|
}
|
|
@@ -527101,6 +527440,31 @@ Pick the SMALLEST concrete deliverable from the spec — typically the project e
|
|
|
527101
527440
|
return null;
|
|
527102
527441
|
}
|
|
527103
527442
|
}
|
|
527443
|
+
_isProjectEditTool(toolName) {
|
|
527444
|
+
return toolName === "file_write" || toolName === "file_edit" || toolName === "batch_edit" || toolName === "file_patch";
|
|
527445
|
+
}
|
|
527446
|
+
_extractToolTargetPaths(toolName, args, result) {
|
|
527447
|
+
const fromResult = Array.isArray(result?.mutatedFiles) ? result.mutatedFiles.filter((p3) => typeof p3 === "string" && p3.trim().length > 0) : [];
|
|
527448
|
+
if (fromResult.length > 0)
|
|
527449
|
+
return [...new Set(fromResult)];
|
|
527450
|
+
if (toolName === "batch_edit" && Array.isArray(args?.["edits"])) {
|
|
527451
|
+
const paths = args["edits"].map((edit) => edit && typeof edit === "object" ? edit["path"] : null).filter((p3) => typeof p3 === "string" && p3.trim().length > 0);
|
|
527452
|
+
return [...new Set(paths)];
|
|
527453
|
+
}
|
|
527454
|
+
const p2 = args?.["path"] ?? args?.["file_path"] ?? args?.["file"] ?? args?.["filename"] ?? args?.["filepath"] ?? args?.["filePath"];
|
|
527455
|
+
return typeof p2 === "string" && p2.trim().length > 0 ? [p2.trim()] : [];
|
|
527456
|
+
}
|
|
527457
|
+
_isRealProjectMutation(toolName, result) {
|
|
527458
|
+
if (!this._isProjectEditTool(toolName))
|
|
527459
|
+
return false;
|
|
527460
|
+
if (!result || result.success === false)
|
|
527461
|
+
return false;
|
|
527462
|
+
if (typeof result.mutated === "boolean")
|
|
527463
|
+
return result.mutated;
|
|
527464
|
+
if (result.dryRun || result.noop || result.partial)
|
|
527465
|
+
return false;
|
|
527466
|
+
return true;
|
|
527467
|
+
}
|
|
527104
527468
|
/** Track the turn index of the last todo_write call so the reminder
|
|
527105
527469
|
* path can compute `turnsSinceLastTodoWrite` cheaply without walking
|
|
527106
527470
|
* the entire messages array. Reset on run(). */
|
|
@@ -527765,7 +528129,7 @@ ${body}`;
|
|
|
527765
528129
|
* converging — particularly common when a build error names a specific
|
|
527766
528130
|
* file the agent thinks needs more work.
|
|
527767
528131
|
*
|
|
527768
|
-
|
|
528132
|
+
* Suggests targeted alternatives (file_edit/file_patch) and "good enough"
|
|
527769
528133
|
* recognition. Returns null when no churn is happening.
|
|
527770
528134
|
*/
|
|
527771
528135
|
_renderWriteChurnBlock(turn) {
|
|
@@ -527789,7 +528153,7 @@ ${body}`;
|
|
|
527789
528153
|
for (const c9 of top) {
|
|
527790
528154
|
lines.push(` • ${c9.path} — ${c9.writes} writes (most recent ${c9.ageTurns} turn${c9.ageTurns === 1 ? "" : "s"} ago)`);
|
|
527791
528155
|
}
|
|
527792
|
-
lines.push("Refining the same file again and again rarely converges. If you have a specific change in mind, use file_edit or
|
|
528156
|
+
lines.push("Refining the same file again and again rarely converges. If you have a specific change in mind, use file_edit or file_patch for targeted changes. If you're trying different approaches, read the file once with file_read to see current state, then decide. If the current version is reasonable but a downstream tool fails, the bug is probably in the OTHER file (importer, schema, dep) — not this one.");
|
|
527793
528157
|
lines.push(`(turn ${turn} — this warning auto-clears when no path has ≥3 writes within 10 turns)`);
|
|
527794
528158
|
return lines.join("\n");
|
|
527795
528159
|
}
|
|
@@ -527810,6 +528174,10 @@ ${body}`;
|
|
|
527810
528174
|
return false;
|
|
527811
528175
|
if (/(^|[^&\d])(>|>>)\s*\S/.test(cmd))
|
|
527812
528176
|
return false;
|
|
528177
|
+
if (/(^|[^<])<\s*\S/.test(cmd))
|
|
528178
|
+
return false;
|
|
528179
|
+
if (/\bpatch\b/i.test(cmd))
|
|
528180
|
+
return false;
|
|
527813
528181
|
const MUTATE_BINS = [
|
|
527814
528182
|
// POSIX file/process mutators
|
|
527815
528183
|
"rm",
|
|
@@ -528013,8 +528381,6 @@ ${body}`;
|
|
|
528013
528381
|
"unexpand",
|
|
528014
528382
|
"diff",
|
|
528015
528383
|
"cmp",
|
|
528016
|
-
"patch",
|
|
528017
|
-
// patch with -R or no-args could be mutating; --dry-run only is read
|
|
528018
528384
|
"echo",
|
|
528019
528385
|
"printf",
|
|
528020
528386
|
"pwd",
|
|
@@ -528206,10 +528572,7 @@ ${body}`;
|
|
|
528206
528572
|
*/
|
|
528207
528573
|
_renderTodoStateBlock(turn) {
|
|
528208
528574
|
try {
|
|
528209
|
-
const
|
|
528210
|
-
const { getTodoSessionId: getTodoSessionId2 } = __require("@open-agents/execution");
|
|
528211
|
-
const sessionId = getTodoSessionId2();
|
|
528212
|
-
const todos = readTodos2(sessionId);
|
|
528575
|
+
const todos = this.readSessionTodos();
|
|
528213
528576
|
if (!todos || todos.length === 0)
|
|
528214
528577
|
return null;
|
|
528215
528578
|
const lines = ["[CURRENT TODO PLAN — already in your state, no need to call todo_write to see it]"];
|
|
@@ -529399,7 +529762,6 @@ If the hypothesis cannot be tested by a creative edit, ask the human via task_co
|
|
|
529399
529762
|
content: `REG-58 NO-WRITE STAGNATION — ${gap} turns since last creative edit (turn ${this._lastFileWriteTurn})${_telSuffix58}`,
|
|
529400
529763
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
529401
529764
|
});
|
|
529402
|
-
this._lastFileWriteTurn = turn;
|
|
529403
529765
|
}
|
|
529404
529766
|
const REG60_WINDOW_MS = 60 * 60 * 1e3;
|
|
529405
529767
|
const REG60_MIN_WRITES = 3;
|
|
@@ -529626,8 +529988,11 @@ If this matches your current shape, try it before continuing.`
|
|
|
529626
529988
|
if (_readClass.has(c9.name)) {
|
|
529627
529989
|
_readCount++;
|
|
529628
529990
|
} else if (_mutationClass.has(c9.name)) {
|
|
529629
|
-
if (
|
|
529991
|
+
if (c9.mutated === true) {
|
|
529992
|
+
_mutationCount++;
|
|
529993
|
+
} else if (c9.success === true && c9.mutated !== false && !_isStale) {
|
|
529630
529994
|
_mutationCount++;
|
|
529995
|
+
}
|
|
529631
529996
|
} else if (c9.name === "shell") {
|
|
529632
529997
|
if (c9.success === true && !_isStale) {
|
|
529633
529998
|
_readCount++;
|
|
@@ -529801,6 +530166,14 @@ ${_staleSamples.join("\n")}` : ``,
|
|
|
529801
530166
|
for (const c9 of _wtWindow) {
|
|
529802
530167
|
if (!_wtWriteClass.has(c9.name))
|
|
529803
530168
|
continue;
|
|
530169
|
+
if (c9.mutated === false)
|
|
530170
|
+
continue;
|
|
530171
|
+
if (Array.isArray(c9.mutatedFiles) && c9.mutatedFiles.length > 0) {
|
|
530172
|
+
for (const p2 of c9.mutatedFiles) {
|
|
530173
|
+
_wtFileCounts.set(p2, (_wtFileCounts.get(p2) ?? 0) + 1);
|
|
530174
|
+
}
|
|
530175
|
+
continue;
|
|
530176
|
+
}
|
|
529804
530177
|
const _ak = c9.argsKey || "";
|
|
529805
530178
|
const _m = /(?:^|,)path=([^,]+)/.exec(_ak);
|
|
529806
530179
|
const _pk = _m ? _m[1].slice(0, 200) : _ak.slice(0, 200);
|
|
@@ -530428,8 +530801,8 @@ If you're stuck, try a completely different approach. Do NOT repeat what failed
|
|
|
530428
530801
|
if (process.env["OA_DISABLE_ADAPTIVE_RETRIEVAL"] !== "1") {
|
|
530429
530802
|
const goalForSig = (this._taskState.goal || "").slice(0, 200);
|
|
530430
530803
|
const recentTools = this._toolSequence.slice(-5).join("|");
|
|
530431
|
-
const { createHash:
|
|
530432
|
-
const sig =
|
|
530804
|
+
const { createHash: createHash21 } = await import("node:crypto");
|
|
530805
|
+
const sig = createHash21("sha256").update(`${goalForSig}::${recentTools}`).digest("hex").slice(0, 16);
|
|
530433
530806
|
if (this._lastPprSig === sig && this._lastPprMemoryLines.length > 0) {
|
|
530434
530807
|
compacted.push({
|
|
530435
530808
|
role: "system",
|
|
@@ -531005,14 +531378,6 @@ ${memoryLines.join("\n")}`
|
|
|
531005
531378
|
"priority_delegate",
|
|
531006
531379
|
"background_run"
|
|
531007
531380
|
]);
|
|
531008
|
-
if (REG61_EDIT_TOOLS.has(tc.name) && this._reg61PerpetualGateActive) {
|
|
531009
|
-
this._reg61PerpetualGateActive = false;
|
|
531010
|
-
this.emit({
|
|
531011
|
-
type: "status",
|
|
531012
|
-
content: `REG-61 GATE CLEARED — '${tc.name}' satisfied REG-61 directive at turn ${turn}`,
|
|
531013
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
531014
|
-
});
|
|
531015
|
-
}
|
|
531016
531381
|
if (this._reg61PerpetualGateActive && !REG61_BYPASS_TOOLS.has(tc.name) && process.env["OA_DISABLE_REG61_COERCE"] !== "1") {
|
|
531017
531382
|
this.emit({
|
|
531018
531383
|
type: "tool_call",
|
|
@@ -531038,7 +531403,7 @@ ${memoryLines.join("\n")}`
|
|
|
531038
531403
|
``,
|
|
531039
531404
|
`This is NOT random guessing — it's targeted hypothesis falsification. Reading the same files 5+ times has already proven uninformative; only a state change will move the system.`,
|
|
531040
531405
|
``,
|
|
531041
|
-
`Issue EXACTLY ONE of: file_write / file_edit / batch_edit / file_patch on a single concrete change. The
|
|
531406
|
+
`Issue EXACTLY ONE of: file_write / file_edit / batch_edit / file_patch on a single concrete change. The edit must actually change disk state; dry-runs and no-ops do not clear this directive.`,
|
|
531042
531407
|
``,
|
|
531043
531408
|
`Allowed bypasses (will not be blocked but will not clear the directive either):`,
|
|
531044
531409
|
` • web_search — search the EXACT recurring error string`,
|
|
@@ -531055,14 +531420,14 @@ ${memoryLines.join("\n")}`
|
|
|
531055
531420
|
` • file_write — create a new file`,
|
|
531056
531421
|
` • file_edit — modify an existing file (find/replace)`,
|
|
531057
531422
|
` • batch_edit — multiple find/replace edits in one call`,
|
|
531058
|
-
` • file_patch — apply a
|
|
531423
|
+
` • file_patch — apply a version-checked line-range patch`,
|
|
531059
531424
|
``,
|
|
531060
531425
|
`These tools are also allowed while the directive is active (will not be blocked, will not clear the gate):`,
|
|
531061
531426
|
` • web_search — for genuinely-unknown APIs / error strings`,
|
|
531062
531427
|
` • task_complete — to exit if you cannot make any progress`,
|
|
531063
531428
|
` • ask_user — to escalate to human (if available)`,
|
|
531064
531429
|
``,
|
|
531065
|
-
`Until you issue a creative edit, ALL of these will be BLOCKED again on every turn: file_read, file_explore, list_directory, grep_search, shell, todo_write, todo_read, memory_read, memory_write, etc. Pick the smallest concrete change that moves work forward
|
|
531430
|
+
`Until you issue a creative edit that actually changes disk, ALL of these will be BLOCKED again on every turn: file_read, file_explore, list_directory, grep_search, shell, todo_write, todo_read, memory_read, memory_write, etc. Pick the smallest concrete change that moves work forward.`
|
|
531066
531431
|
].join("\n");
|
|
531067
531432
|
this.emit({
|
|
531068
531433
|
type: "tool_result",
|
|
@@ -531514,6 +531879,16 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
531514
531879
|
}
|
|
531515
531880
|
}
|
|
531516
531881
|
}
|
|
531882
|
+
const realFileMutation = this._isRealProjectMutation(tc.name, result);
|
|
531883
|
+
const realMutationPaths = realFileMutation ? this._extractToolTargetPaths(tc.name, tc.arguments, result) : [];
|
|
531884
|
+
if (realFileMutation && this._reg61PerpetualGateActive) {
|
|
531885
|
+
this._reg61PerpetualGateActive = false;
|
|
531886
|
+
this.emit({
|
|
531887
|
+
type: "status",
|
|
531888
|
+
content: `REG-61 GATE CLEARED — '${tc.name}' landed real file mutation at turn ${turn}`,
|
|
531889
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
531890
|
+
});
|
|
531891
|
+
}
|
|
531517
531892
|
const updated = this._argCohorts.get(cohortKey) || { success: 0, failure: 0, lastOutcomeTurn: turn };
|
|
531518
531893
|
if (result.success)
|
|
531519
531894
|
updated.success++;
|
|
@@ -531522,9 +531897,9 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
531522
531897
|
updated.lastOutcomeTurn = turn;
|
|
531523
531898
|
this._argCohorts.set(cohortKey, updated);
|
|
531524
531899
|
try {
|
|
531525
|
-
if (
|
|
531526
|
-
const
|
|
531527
|
-
|
|
531900
|
+
if (realFileMutation) {
|
|
531901
|
+
const paths = realMutationPaths.length > 0 ? realMutationPaths : this._extractToolTargetPaths(tc.name, tc.arguments, result);
|
|
531902
|
+
for (const p2 of paths) {
|
|
531528
531903
|
const prev = this._worldFacts.files.get(p2);
|
|
531529
531904
|
this._worldFacts.files.set(p2, {
|
|
531530
531905
|
exists: true,
|
|
@@ -531534,7 +531909,9 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
531534
531909
|
lastWriteTurn: turn,
|
|
531535
531910
|
writeCount: (prev?.writeCount ?? 0) + 1
|
|
531536
531911
|
});
|
|
531537
|
-
|
|
531912
|
+
}
|
|
531913
|
+
if (paths.length > 0) {
|
|
531914
|
+
this._writesSinceLastTodoWrite += paths.length;
|
|
531538
531915
|
if (this._writesSinceLastTodoWrite >= 6 && !this._progressGateActive) {
|
|
531539
531916
|
this._progressGateActive = true;
|
|
531540
531917
|
this.emit({
|
|
@@ -531907,12 +532284,17 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
531907
532284
|
const lastLog = toolCallLog[toolCallLog.length - 1];
|
|
531908
532285
|
if (lastLog) {
|
|
531909
532286
|
lastLog.success = false;
|
|
532287
|
+
lastLog.mutated = false;
|
|
532288
|
+
lastLog.mutatedFiles = [];
|
|
531910
532289
|
lastLog.outputPreview = errorText.slice(0, 100);
|
|
531911
532290
|
}
|
|
531912
532291
|
} else if (result.success) {
|
|
531913
532292
|
const lastLog = toolCallLog[toolCallLog.length - 1];
|
|
531914
|
-
if (lastLog)
|
|
532293
|
+
if (lastLog) {
|
|
531915
532294
|
lastLog.success = true;
|
|
532295
|
+
lastLog.mutated = realFileMutation;
|
|
532296
|
+
lastLog.mutatedFiles = realMutationPaths;
|
|
532297
|
+
}
|
|
531916
532298
|
if (tc.name === "shell") {
|
|
531917
532299
|
const _shellCmd = String(tc.arguments?.["command"] ?? tc.arguments?.["cmd"] ?? "");
|
|
531918
532300
|
const _typecheckOnly = /\b(--noEmit|--dry-run|--check\b|\bmypy\b|\bruff check\b|\bcargo check\b|\bstylelint --check\b|\bpylint\b(?!.*--exit-zero))\b/i.test(_shellCmd);
|
|
@@ -532013,16 +532395,16 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
532013
532395
|
} catch {
|
|
532014
532396
|
}
|
|
532015
532397
|
}
|
|
532016
|
-
if (
|
|
532398
|
+
if (realFileMutation && this._patchHistoryStore) {
|
|
532017
532399
|
try {
|
|
532018
|
-
const
|
|
532019
|
-
|
|
532400
|
+
const patchFiles = realMutationPaths.length > 0 ? realMutationPaths : this._extractToolTargetPaths(tc.name, tc.arguments, result);
|
|
532401
|
+
for (const filePath2 of patchFiles) {
|
|
532020
532402
|
this._patchHistoryStore.insert({
|
|
532021
532403
|
taskId: this._sessionId,
|
|
532022
532404
|
sessionId: this._sessionId,
|
|
532023
532405
|
repoRoot: process.cwd(),
|
|
532024
532406
|
filePath: filePath2,
|
|
532025
|
-
diff: JSON.stringify(tc.arguments).slice(0, 1e3),
|
|
532407
|
+
diff: (result.diff ?? JSON.stringify(tc.arguments)).slice(0, 1e3),
|
|
532026
532408
|
status: "applied",
|
|
532027
532409
|
appliedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
532028
532410
|
revertedAt: null,
|
|
@@ -532043,13 +532425,13 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
532043
532425
|
}
|
|
532044
532426
|
}
|
|
532045
532427
|
}
|
|
532046
|
-
const isFileMutation =
|
|
532047
|
-
if (isFileMutation &&
|
|
532428
|
+
const isFileMutation = realFileMutation;
|
|
532429
|
+
if (isFileMutation && dedupHitCount.size > 0) {
|
|
532048
532430
|
dedupHitCount.clear();
|
|
532049
532431
|
}
|
|
532050
|
-
if (isFileMutation
|
|
532051
|
-
this._fileWritesSinceLastWorldState
|
|
532052
|
-
this._fileWritesThisRun
|
|
532432
|
+
if (isFileMutation) {
|
|
532433
|
+
this._fileWritesSinceLastWorldState += Math.max(1, realMutationPaths.length);
|
|
532434
|
+
this._fileWritesThisRun += Math.max(1, realMutationPaths.length);
|
|
532053
532435
|
}
|
|
532054
532436
|
if (result.success) {
|
|
532055
532437
|
this._recentFailures = this._recentFailures.filter((f2) => f2.fingerprint !== toolFingerprint);
|
|
@@ -532197,14 +532579,14 @@ Respond with EXACTLY this structure before your next tool call:
|
|
|
532197
532579
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
532198
532580
|
});
|
|
532199
532581
|
this._taskState.toolCallCount++;
|
|
532200
|
-
if (
|
|
532201
|
-
|
|
532202
|
-
|
|
532203
|
-
|
|
532582
|
+
if (realFileMutation) {
|
|
532583
|
+
this._lastFileWriteTurn = turn;
|
|
532584
|
+
const writeEvents = Math.max(1, realMutationPaths.length);
|
|
532585
|
+
for (let i2 = 0; i2 < writeEvents; i2++) {
|
|
532204
532586
|
this._fileWriteTimestamps.push(Date.now());
|
|
532205
|
-
|
|
532206
|
-
|
|
532207
|
-
|
|
532587
|
+
}
|
|
532588
|
+
while (this._fileWriteTimestamps.length > 200) {
|
|
532589
|
+
this._fileWriteTimestamps.shift();
|
|
532208
532590
|
}
|
|
532209
532591
|
}
|
|
532210
532592
|
this._trackDecomp2(tc, result, turn);
|
|
@@ -544333,7 +544715,7 @@ var require_websocket3 = __commonJS({
|
|
|
544333
544715
|
var http6 = __require("http");
|
|
544334
544716
|
var net5 = __require("net");
|
|
544335
544717
|
var tls2 = __require("tls");
|
|
544336
|
-
var { randomBytes: randomBytes25, createHash:
|
|
544718
|
+
var { randomBytes: randomBytes25, createHash: createHash21 } = __require("crypto");
|
|
544337
544719
|
var { Duplex: Duplex3, Readable } = __require("stream");
|
|
544338
544720
|
var { URL: URL3 } = __require("url");
|
|
544339
544721
|
var PerMessageDeflate2 = require_permessage_deflate3();
|
|
@@ -544993,7 +545375,7 @@ var require_websocket3 = __commonJS({
|
|
|
544993
545375
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
544994
545376
|
return;
|
|
544995
545377
|
}
|
|
544996
|
-
const digest3 =
|
|
545378
|
+
const digest3 = createHash21("sha1").update(key + GUID).digest("base64");
|
|
544997
545379
|
if (res.headers["sec-websocket-accept"] !== digest3) {
|
|
544998
545380
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
544999
545381
|
return;
|
|
@@ -545360,7 +545742,7 @@ var require_websocket_server2 = __commonJS({
|
|
|
545360
545742
|
var EventEmitter13 = __require("events");
|
|
545361
545743
|
var http6 = __require("http");
|
|
545362
545744
|
var { Duplex: Duplex3 } = __require("stream");
|
|
545363
|
-
var { createHash:
|
|
545745
|
+
var { createHash: createHash21 } = __require("crypto");
|
|
545364
545746
|
var extension2 = require_extension3();
|
|
545365
545747
|
var PerMessageDeflate2 = require_permessage_deflate3();
|
|
545366
545748
|
var subprotocol2 = require_subprotocol2();
|
|
@@ -545661,7 +546043,7 @@ var require_websocket_server2 = __commonJS({
|
|
|
545661
546043
|
);
|
|
545662
546044
|
}
|
|
545663
546045
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
545664
|
-
const digest3 =
|
|
546046
|
+
const digest3 = createHash21("sha1").update(key + GUID).digest("base64");
|
|
545665
546047
|
const headers = [
|
|
545666
546048
|
"HTTP/1.1 101 Switching Protocols",
|
|
545667
546049
|
"Upgrade: websocket",
|
|
@@ -546721,7 +547103,7 @@ __export(oa_directory_exports, {
|
|
|
546721
547103
|
import { existsSync as existsSync74, mkdirSync as mkdirSync42, readFileSync as readFileSync61, writeFileSync as writeFileSync38, readdirSync as readdirSync21, statSync as statSync25, unlinkSync as unlinkSync14, openSync as openSync2, closeSync as closeSync2, renameSync as renameSync3 } from "node:fs";
|
|
546722
547104
|
import { join as join93, relative as relative8, basename as basename14, dirname as dirname27 } from "node:path";
|
|
546723
547105
|
import { homedir as homedir26 } from "node:os";
|
|
546724
|
-
import { createHash as
|
|
547106
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
546725
547107
|
function findGitRoot(startDir) {
|
|
546726
547108
|
let dir = startDir;
|
|
546727
547109
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -547086,7 +547468,7 @@ function buildHandoffPrompt(repoRoot) {
|
|
|
547086
547468
|
return lines.join("\n");
|
|
547087
547469
|
}
|
|
547088
547470
|
function computeDedupeHash(task, savedAt) {
|
|
547089
|
-
return
|
|
547471
|
+
return createHash14("sha256").update(`${task}|${savedAt}`).digest("hex").slice(0, 16);
|
|
547090
547472
|
}
|
|
547091
547473
|
function generateSessionId() {
|
|
547092
547474
|
const timestamp = Date.now().toString(36);
|
|
@@ -575641,7 +576023,7 @@ var init_types = __esm({
|
|
|
575641
576023
|
});
|
|
575642
576024
|
|
|
575643
576025
|
// packages/cli/src/tui/p2p/secret-vault.ts
|
|
575644
|
-
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes19, scryptSync as scryptSync2, createHash as
|
|
576026
|
+
import { createCipheriv as createCipheriv3, createDecipheriv as createDecipheriv3, randomBytes as randomBytes19, scryptSync as scryptSync2, createHash as createHash15 } from "node:crypto";
|
|
575645
576027
|
import { readFileSync as readFileSync71, writeFileSync as writeFileSync46, existsSync as existsSync86, mkdirSync as mkdirSync50 } from "node:fs";
|
|
575646
576028
|
import { dirname as dirname31 } from "node:path";
|
|
575647
576029
|
var PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, CIPHER_ALGO, SALT_LEN, IV_LEN, KEY_LEN, SecretVault;
|
|
@@ -575886,7 +576268,7 @@ var init_secret_vault = __esm({
|
|
|
575886
576268
|
/** Generate a deterministic fingerprint of vault contents (for sync verification) */
|
|
575887
576269
|
fingerprint() {
|
|
575888
576270
|
const names = Array.from(this.secrets.keys()).sort();
|
|
575889
|
-
const hash =
|
|
576271
|
+
const hash = createHash15("sha256");
|
|
575890
576272
|
for (const name10 of names) {
|
|
575891
576273
|
hash.update(name10 + ":");
|
|
575892
576274
|
hash.update(this.secrets.get(name10).value);
|
|
@@ -575901,7 +576283,7 @@ var init_secret_vault = __esm({
|
|
|
575901
576283
|
// packages/cli/src/tui/p2p/peer-mesh.ts
|
|
575902
576284
|
import { EventEmitter as EventEmitter7 } from "node:events";
|
|
575903
576285
|
import { createServer as createServer5 } from "node:http";
|
|
575904
|
-
import { randomBytes as randomBytes20, createHash as
|
|
576286
|
+
import { randomBytes as randomBytes20, createHash as createHash16, generateKeyPairSync } from "node:crypto";
|
|
575905
576287
|
var PING_INTERVAL_MS, PEER_TIMEOUT_MS, GOSSIP_INTERVAL_MS, MAX_PEERS, PeerMesh;
|
|
575906
576288
|
var init_peer_mesh = __esm({
|
|
575907
576289
|
"packages/cli/src/tui/p2p/peer-mesh.ts"() {
|
|
@@ -575918,7 +576300,7 @@ var init_peer_mesh = __esm({
|
|
|
575918
576300
|
const { publicKey: publicKey2, privateKey } = generateKeyPairSync("ed25519");
|
|
575919
576301
|
this.publicKey = publicKey2.export({ type: "spki", format: "der" });
|
|
575920
576302
|
this.privateKey = privateKey.export({ type: "pkcs8", format: "der" });
|
|
575921
|
-
this.peerId =
|
|
576303
|
+
this.peerId = createHash16("sha256").update(this.publicKey).digest("base64url").slice(0, 22);
|
|
575922
576304
|
this.capabilities = options2.capabilities;
|
|
575923
576305
|
this.displayName = options2.displayName;
|
|
575924
576306
|
this._authKey = options2.authKey ?? randomBytes20(24).toString("base64url");
|
|
@@ -585025,14 +585407,14 @@ var init_access_policy = __esm({
|
|
|
585025
585407
|
});
|
|
585026
585408
|
|
|
585027
585409
|
// packages/cli/src/api/project-preferences.ts
|
|
585028
|
-
import { createHash as
|
|
585410
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
585029
585411
|
import { existsSync as existsSync97, mkdirSync as mkdirSync59, readFileSync as readFileSync81, renameSync as renameSync7, writeFileSync as writeFileSync53, unlinkSync as unlinkSync22 } from "node:fs";
|
|
585030
585412
|
import { homedir as homedir36 } from "node:os";
|
|
585031
585413
|
import { join as join116, resolve as resolve36 } from "node:path";
|
|
585032
585414
|
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
585033
585415
|
function projectKey(root) {
|
|
585034
585416
|
const canonical = resolve36(root);
|
|
585035
|
-
return
|
|
585417
|
+
return createHash17("sha256").update(canonical).digest("hex").slice(0, 16);
|
|
585036
585418
|
}
|
|
585037
585419
|
function projectDir(root) {
|
|
585038
585420
|
return join116(PROJECTS_DIR, projectKey(root));
|
|
@@ -586210,7 +586592,7 @@ var init_disk_task_output = __esm({
|
|
|
586210
586592
|
});
|
|
586211
586593
|
|
|
586212
586594
|
// packages/cli/src/api/http.ts
|
|
586213
|
-
import { createHash as
|
|
586595
|
+
import { createHash as createHash18 } from "node:crypto";
|
|
586214
586596
|
function problemDetails(opts) {
|
|
586215
586597
|
const p2 = {
|
|
586216
586598
|
type: opts.type ?? "about:blank",
|
|
@@ -586273,7 +586655,7 @@ function paginated(items, page2, total) {
|
|
|
586273
586655
|
}
|
|
586274
586656
|
function computeEtag(payload) {
|
|
586275
586657
|
const json = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
586276
|
-
const hash =
|
|
586658
|
+
const hash = createHash18("sha1").update(json).digest("hex").slice(0, 16);
|
|
586277
586659
|
return `W/"${hash}"`;
|
|
586278
586660
|
}
|
|
586279
586661
|
function checkNotModified(req2, res, etag) {
|
|
@@ -600253,7 +600635,7 @@ import { homedir as homedir43 } from "node:os";
|
|
|
600253
600635
|
import { spawn as spawn26, execSync as execSync57 } from "node:child_process";
|
|
600254
600636
|
import { mkdirSync as mkdirSync67, writeFileSync as writeFileSync59, readFileSync as readFileSync89, readdirSync as readdirSync36, existsSync as existsSync108, watch as fsWatch3, renameSync as renameSync8, unlinkSync as unlinkSync24 } from "node:fs";
|
|
600255
600637
|
import { randomBytes as randomBytes23, randomUUID as randomUUID16 } from "node:crypto";
|
|
600256
|
-
import { createHash as
|
|
600638
|
+
import { createHash as createHash20 } from "node:crypto";
|
|
600257
600639
|
function getVersion3() {
|
|
600258
600640
|
try {
|
|
600259
600641
|
const thisDir = dirname36(fileURLToPath17(import.meta.url));
|
|
@@ -605894,7 +606276,7 @@ function listScheduledTasks() {
|
|
|
605894
606276
|
const schedule = String(t2?.schedule || t2?.cron || t2?.when || "");
|
|
605895
606277
|
const enabled2 = typeof t2?.enabled === "boolean" ? t2.enabled : true;
|
|
605896
606278
|
const realId = typeof t2?.id === "string" && t2.id ? t2.id : null;
|
|
605897
|
-
const fallbackId =
|
|
606279
|
+
const fallbackId = createHash20("sha1").update(`${file}#${i2}`).digest("hex").slice(0, 16);
|
|
605898
606280
|
const uid = realId || fallbackId;
|
|
605899
606281
|
const key = `${uid}`;
|
|
605900
606282
|
if (seen.has(key)) return;
|
|
@@ -606011,8 +606393,8 @@ function deleteScheduledById(id) {
|
|
|
606011
606393
|
if (id) candidates.push(id);
|
|
606012
606394
|
if (typeof entry?.id === "string" && entry.id && !candidates.includes(entry.id)) candidates.push(entry.id);
|
|
606013
606395
|
try {
|
|
606014
|
-
const { createHash:
|
|
606015
|
-
const fallback =
|
|
606396
|
+
const { createHash: createHash21 } = require3("node:crypto");
|
|
606397
|
+
const fallback = createHash21("sha1").update(`${target.file}#${target.index}`).digest("hex").slice(0, 16);
|
|
606016
606398
|
if (!candidates.includes(fallback)) candidates.push(fallback);
|
|
606017
606399
|
} catch {
|
|
606018
606400
|
}
|
|
@@ -608186,7 +608568,7 @@ function createSubAgentTool(config, repoRoot, ctxWindowSize) {
|
|
|
608186
608568
|
success: true,
|
|
608187
608569
|
output: `Sub-agent started in background: ${taskId}
|
|
608188
608570
|
Task: ${task}
|
|
608189
|
-
Use task_status("${taskId}") or task_output("${taskId}") to check progress.`
|
|
608571
|
+
Use task_status(task_id="${taskId}") or task_output(task_id="${taskId}") to check progress.`
|
|
608190
608572
|
};
|
|
608191
608573
|
}
|
|
608192
608574
|
if (onViewStatus) onViewStatus(agentId, "running");
|
|
@@ -610102,13 +610484,10 @@ async function startInteractive(config, repoPath) {
|
|
|
610102
610484
|
} catch {
|
|
610103
610485
|
}
|
|
610104
610486
|
}
|
|
610105
|
-
if (!isResumed &&
|
|
610106
|
-
const
|
|
610107
|
-
|
|
610108
|
-
|
|
610109
|
-
const freshConfig = loadConfig();
|
|
610110
|
-
config = { ...config, ...freshConfig, model: setupModel ?? freshConfig.model };
|
|
610111
|
-
}
|
|
610487
|
+
if (!isResumed && await shouldRunFirstRunSetup(config)) {
|
|
610488
|
+
const setupModel = await runSetupWizard(config);
|
|
610489
|
+
const freshConfig = loadConfig();
|
|
610490
|
+
config = { ...config, ...freshConfig, model: setupModel ?? freshConfig.model };
|
|
610112
610491
|
}
|
|
610113
610492
|
let carouselPhrases = null;
|
|
610114
610493
|
try {
|
|
@@ -613679,13 +614058,13 @@ NEW TASK: ${fullInput}`;
|
|
|
613679
614058
|
writeContent(() => renderError2(errMsg));
|
|
613680
614059
|
if (failureStore) {
|
|
613681
614060
|
try {
|
|
613682
|
-
const { createHash:
|
|
614061
|
+
const { createHash: createHash21 } = await import("node:crypto");
|
|
613683
614062
|
failureStore.insert({
|
|
613684
614063
|
taskId: "",
|
|
613685
614064
|
sessionId: `${Date.now()}`,
|
|
613686
614065
|
repoRoot,
|
|
613687
614066
|
failureType: "runtime-error",
|
|
613688
|
-
fingerprint:
|
|
614067
|
+
fingerprint: createHash21("sha256").update(errMsg.slice(0, 200)).digest("hex").slice(0, 16),
|
|
613689
614068
|
filePath: null,
|
|
613690
614069
|
errorMessage: errMsg.slice(0, 500),
|
|
613691
614070
|
context: null,
|
|
@@ -613928,11 +614307,19 @@ ${c3.dim("(Use /quit to exit)")}
|
|
|
613928
614307
|
showPrompt();
|
|
613929
614308
|
};
|
|
613930
614309
|
}
|
|
614310
|
+
async function shouldRunFirstRunSetup(config, firstRun = isFirstRun()) {
|
|
614311
|
+
if (config.backendType !== "ollama") return false;
|
|
614312
|
+
if (!firstRun) return false;
|
|
614313
|
+
try {
|
|
614314
|
+
return !await isModelAvailable(config);
|
|
614315
|
+
} catch {
|
|
614316
|
+
return false;
|
|
614317
|
+
}
|
|
614318
|
+
}
|
|
613931
614319
|
async function runWithTUI(task, config, repoPath, callbacks) {
|
|
613932
614320
|
const repoRoot = resolve39(repoPath ?? cwd());
|
|
613933
614321
|
initOaDirectory(repoRoot);
|
|
613934
|
-
|
|
613935
|
-
if (needsSetup && config.backendType === "ollama") {
|
|
614322
|
+
if (await shouldRunFirstRunSetup(config)) {
|
|
613936
614323
|
const setupModel = await runSetupWizard(config);
|
|
613937
614324
|
const freshConfig = loadConfig();
|
|
613938
614325
|
config = { ...config, ...freshConfig, model: setupModel ?? freshConfig.model };
|