zelari-code 2.12.0 → 2.13.0
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/cli/main.bundled.js +208 -53
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/safety/policyEngine.js +61 -26
- package/dist/cli/safety/policyEngine.js.map +1 -1
- package/dist/cli/safety/policyLayers.js +55 -0
- package/dist/cli/safety/policyLayers.js.map +1 -0
- package/dist/cli/toolRegistry.js +19 -10
- package/dist/cli/toolRegistry.js.map +1 -1
- package/dist/cli/tools/krakenCsvFanout.js +4 -4
- package/dist/cli/tools/krakenCsvFanout.js.map +1 -1
- package/dist/cli/tools/taskTool.js +4 -3
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -18235,15 +18235,66 @@ var init_toolTypes = __esm({
|
|
|
18235
18235
|
}
|
|
18236
18236
|
});
|
|
18237
18237
|
|
|
18238
|
+
// packages/core/dist/core/tools/builtin/newlines.js
|
|
18239
|
+
function detectNewline(text) {
|
|
18240
|
+
if (text.includes("\r\n"))
|
|
18241
|
+
return "\r\n";
|
|
18242
|
+
if (text.includes("\r"))
|
|
18243
|
+
return "\r";
|
|
18244
|
+
return "\n";
|
|
18245
|
+
}
|
|
18246
|
+
function toLF(text) {
|
|
18247
|
+
return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
18248
|
+
}
|
|
18249
|
+
function fromLF(text, nl) {
|
|
18250
|
+
if (nl === "\n")
|
|
18251
|
+
return text;
|
|
18252
|
+
return text.replace(/\n/g, nl);
|
|
18253
|
+
}
|
|
18254
|
+
function splitLinesLF(text) {
|
|
18255
|
+
return toLF(text).split("\n");
|
|
18256
|
+
}
|
|
18257
|
+
var init_newlines = __esm({
|
|
18258
|
+
"packages/core/dist/core/tools/builtin/newlines.js"() {
|
|
18259
|
+
"use strict";
|
|
18260
|
+
}
|
|
18261
|
+
});
|
|
18262
|
+
|
|
18238
18263
|
// packages/core/dist/core/tools/builtin/filesystem.js
|
|
18239
18264
|
import { promises as fs4 } from "node:fs";
|
|
18240
18265
|
import path6 from "node:path";
|
|
18266
|
+
function replaceFileString(text, oldString, newString, replaceAll) {
|
|
18267
|
+
const exact = replaceOnceOrAll(text, oldString, newString, replaceAll);
|
|
18268
|
+
if (exact.occurrences > 0)
|
|
18269
|
+
return exact;
|
|
18270
|
+
const nl = detectNewline(text);
|
|
18271
|
+
const normalized = replaceOnceOrAll(toLF(text), toLF(oldString), toLF(newString), replaceAll);
|
|
18272
|
+
if (normalized.occurrences === 0)
|
|
18273
|
+
return normalized;
|
|
18274
|
+
return { occurrences: normalized.occurrences, newContent: fromLF(normalized.newContent, nl) };
|
|
18275
|
+
}
|
|
18276
|
+
function replaceOnceOrAll(text, oldString, newString, replaceAll) {
|
|
18277
|
+
if (replaceAll) {
|
|
18278
|
+
if (!text.includes(oldString))
|
|
18279
|
+
return { occurrences: 0, newContent: text };
|
|
18280
|
+
const parts = text.split(oldString);
|
|
18281
|
+
return { occurrences: parts.length - 1, newContent: parts.join(newString) };
|
|
18282
|
+
}
|
|
18283
|
+
const idx = text.indexOf(oldString);
|
|
18284
|
+
if (idx === -1)
|
|
18285
|
+
return { occurrences: 0, newContent: text };
|
|
18286
|
+
return {
|
|
18287
|
+
occurrences: 1,
|
|
18288
|
+
newContent: text.slice(0, idx) + newString + text.slice(idx + oldString.length)
|
|
18289
|
+
};
|
|
18290
|
+
}
|
|
18241
18291
|
var ReadFileArgsSchema, readFileTool, WriteFileArgsSchema, writeFileTool, EditFileArgsSchema, editFileTool;
|
|
18242
18292
|
var init_filesystem = __esm({
|
|
18243
18293
|
"packages/core/dist/core/tools/builtin/filesystem.js"() {
|
|
18244
18294
|
"use strict";
|
|
18245
18295
|
init_zod();
|
|
18246
18296
|
init_toolTypes();
|
|
18297
|
+
init_newlines();
|
|
18247
18298
|
ReadFileArgsSchema = external_exports.object({
|
|
18248
18299
|
path: external_exports.string().min(1),
|
|
18249
18300
|
startLine: external_exports.number().int().nonnegative().optional().describe("0-based first line to include. Range is applied to the full file before maxBytes."),
|
|
@@ -18337,7 +18388,7 @@ var init_filesystem = __esm({
|
|
|
18337
18388
|
});
|
|
18338
18389
|
editFileTool = {
|
|
18339
18390
|
name: "edit_file",
|
|
18340
|
-
description: "Replace
|
|
18391
|
+
description: "Replace a string in a file. Matching ignores CRLF vs LF; the file keeps its original line endings. Returns an error if oldString is not found.",
|
|
18341
18392
|
permissions: ["write"],
|
|
18342
18393
|
sideEffect: "local",
|
|
18343
18394
|
timeoutMs: 1e4,
|
|
@@ -18347,22 +18398,7 @@ var init_filesystem = __esm({
|
|
|
18347
18398
|
const absPath = path6.isAbsolute(args.path) ? args.path : path6.join(ctx.cwd, args.path);
|
|
18348
18399
|
const content = await fs4.readFile(absPath, { encoding: "utf-8", signal: ctx.signal });
|
|
18349
18400
|
const text = typeof content === "string" ? content : content.toString("utf-8");
|
|
18350
|
-
|
|
18351
|
-
let newContent;
|
|
18352
|
-
if (args.replaceAll) {
|
|
18353
|
-
const parts = text.split(args.oldString);
|
|
18354
|
-
occurrences = parts.length - 1;
|
|
18355
|
-
newContent = parts.join(args.newString);
|
|
18356
|
-
} else {
|
|
18357
|
-
const idx = text.indexOf(args.oldString);
|
|
18358
|
-
if (idx === -1) {
|
|
18359
|
-
occurrences = 0;
|
|
18360
|
-
newContent = text;
|
|
18361
|
-
} else {
|
|
18362
|
-
occurrences = 1;
|
|
18363
|
-
newContent = text.slice(0, idx) + args.newString + text.slice(idx + args.oldString.length);
|
|
18364
|
-
}
|
|
18365
|
-
}
|
|
18401
|
+
const { occurrences, newContent } = replaceFileString(text, args.oldString, args.newString, args.replaceAll);
|
|
18366
18402
|
if (occurrences === 0) {
|
|
18367
18403
|
return typedErr(`edit_file: no match for oldString in ${args.path}. Use read_file to copy the exact text (whitespace included) and retry.`);
|
|
18368
18404
|
}
|
|
@@ -19114,7 +19150,7 @@ function formatUnified(hunks, oldLabel, newLabel) {
|
|
|
19114
19150
|
return lines.join("\n");
|
|
19115
19151
|
}
|
|
19116
19152
|
function parseUnified(raw) {
|
|
19117
|
-
const lines = raw
|
|
19153
|
+
const lines = splitLinesLF(raw);
|
|
19118
19154
|
if (lines.length < 2 || !lines[0].startsWith("--- ") || !lines[1].startsWith("+++ ")) {
|
|
19119
19155
|
throw new Error("Invalid unified diff: missing --- / +++ headers");
|
|
19120
19156
|
}
|
|
@@ -19170,6 +19206,72 @@ function parseUnified(raw) {
|
|
|
19170
19206
|
function normalizeWhitespace(s) {
|
|
19171
19207
|
return s.replace(/\s+/g, " ").trim();
|
|
19172
19208
|
}
|
|
19209
|
+
function linesEqual(fileLine, opText, fuzzy) {
|
|
19210
|
+
if (fileLine === opText)
|
|
19211
|
+
return true;
|
|
19212
|
+
if (fuzzy && normalizeWhitespace(fileLine) === normalizeWhitespace(opText))
|
|
19213
|
+
return true;
|
|
19214
|
+
return false;
|
|
19215
|
+
}
|
|
19216
|
+
function hunkOldNeedle(hunk) {
|
|
19217
|
+
return hunk.ops.filter((op) => op.kind !== "+").map((op) => op.text);
|
|
19218
|
+
}
|
|
19219
|
+
function matchAt(lines, at, needle, fuzzy) {
|
|
19220
|
+
if (needle.length === 0)
|
|
19221
|
+
return at >= 0 && at <= lines.length;
|
|
19222
|
+
if (at < 0 || at + needle.length > lines.length)
|
|
19223
|
+
return false;
|
|
19224
|
+
for (let i = 0; i < needle.length; i++) {
|
|
19225
|
+
if (!linesEqual(lines[at + i] ?? "", needle[i], fuzzy))
|
|
19226
|
+
return false;
|
|
19227
|
+
}
|
|
19228
|
+
return true;
|
|
19229
|
+
}
|
|
19230
|
+
function locateHunk(lines, hunk, fileIdx, fuzzy) {
|
|
19231
|
+
const needle = hunkOldNeedle(hunk);
|
|
19232
|
+
const preferred = hunk.oldStart - 1;
|
|
19233
|
+
if (needle.length === 0) {
|
|
19234
|
+
const start = Math.max(fileIdx, preferred >= 0 ? preferred : fileIdx);
|
|
19235
|
+
return { start };
|
|
19236
|
+
}
|
|
19237
|
+
if (preferred >= fileIdx && matchAt(lines, preferred, needle, fuzzy)) {
|
|
19238
|
+
return { start: preferred };
|
|
19239
|
+
}
|
|
19240
|
+
const hits = [];
|
|
19241
|
+
for (let i = fileIdx; i <= lines.length - needle.length; i++) {
|
|
19242
|
+
if (matchAt(lines, i, needle, fuzzy))
|
|
19243
|
+
hits.push(i);
|
|
19244
|
+
}
|
|
19245
|
+
if (hits.length === 0) {
|
|
19246
|
+
if (preferred >= fileIdx) {
|
|
19247
|
+
let fileAt = preferred;
|
|
19248
|
+
for (const op of hunk.ops) {
|
|
19249
|
+
if (op.kind === "+")
|
|
19250
|
+
continue;
|
|
19251
|
+
const fileLine = lines[fileAt] ?? "";
|
|
19252
|
+
if (!linesEqual(fileLine, op.text, fuzzy)) {
|
|
19253
|
+
const label = op.kind === "-" ? "Delete mismatch" : "Context mismatch";
|
|
19254
|
+
return {
|
|
19255
|
+
error: `${label} at line ${fileAt + 1}: expected "${op.text.slice(0, 60)}", got "${fileLine.slice(0, 60)}"`
|
|
19256
|
+
};
|
|
19257
|
+
}
|
|
19258
|
+
fileAt++;
|
|
19259
|
+
}
|
|
19260
|
+
}
|
|
19261
|
+
return { error: `Hunk context not found (oldStart ${hunk.oldStart})` };
|
|
19262
|
+
}
|
|
19263
|
+
if (hits.length === 1)
|
|
19264
|
+
return { start: hits[0] };
|
|
19265
|
+
hits.sort((a, b) => Math.abs(a - preferred) - Math.abs(b - preferred) || a - b);
|
|
19266
|
+
const bestDist = Math.abs(hits[0] - preferred);
|
|
19267
|
+
const tied = hits.filter((h) => Math.abs(h - preferred) === bestDist);
|
|
19268
|
+
if (tied.length > 1) {
|
|
19269
|
+
return {
|
|
19270
|
+
error: `Ambiguous hunk at oldStart ${hunk.oldStart}: ${tied.length} equally close matches (refusing to guess)`
|
|
19271
|
+
};
|
|
19272
|
+
}
|
|
19273
|
+
return { start: hits[0] };
|
|
19274
|
+
}
|
|
19173
19275
|
function applyAllHunks(originalLines, hunks, fuzzy) {
|
|
19174
19276
|
const out = [];
|
|
19175
19277
|
let fileIdx = 0;
|
|
@@ -19177,17 +19279,13 @@ function applyAllHunks(originalLines, hunks, fuzzy) {
|
|
|
19177
19279
|
let hunksSkipped = 0;
|
|
19178
19280
|
let lastReason;
|
|
19179
19281
|
for (const hunk of hunks) {
|
|
19180
|
-
const
|
|
19181
|
-
if (
|
|
19282
|
+
const located = locateHunk(originalLines, hunk, fileIdx, fuzzy);
|
|
19283
|
+
if ("error" in located) {
|
|
19182
19284
|
hunksSkipped++;
|
|
19183
|
-
lastReason =
|
|
19184
|
-
|
|
19185
|
-
}
|
|
19186
|
-
if (startIdx > originalLines.length) {
|
|
19187
|
-
hunksSkipped++;
|
|
19188
|
-
lastReason = `oldStart ${hunk.oldStart} beyond file end (length ${originalLines.length})`;
|
|
19189
|
-
continue;
|
|
19285
|
+
lastReason = located.error;
|
|
19286
|
+
break;
|
|
19190
19287
|
}
|
|
19288
|
+
const startIdx = located.start;
|
|
19191
19289
|
while (fileIdx < startIdx) {
|
|
19192
19290
|
out.push(originalLines[fileIdx]);
|
|
19193
19291
|
fileIdx++;
|
|
@@ -19200,7 +19298,7 @@ function applyAllHunks(originalLines, hunks, fuzzy) {
|
|
|
19200
19298
|
const op = hunk.ops[hunkIdx];
|
|
19201
19299
|
if (op.kind === " ") {
|
|
19202
19300
|
const fileLine = originalLines[hunkFileIdx] ?? "";
|
|
19203
|
-
if (fileLine
|
|
19301
|
+
if (linesEqual(fileLine, op.text, fuzzy)) {
|
|
19204
19302
|
hunkOut.push(fileLine);
|
|
19205
19303
|
hunkFileIdx++;
|
|
19206
19304
|
hunkIdx++;
|
|
@@ -19211,7 +19309,7 @@ function applyAllHunks(originalLines, hunks, fuzzy) {
|
|
|
19211
19309
|
}
|
|
19212
19310
|
} else if (op.kind === "-") {
|
|
19213
19311
|
const fileLine = originalLines[hunkFileIdx] ?? "";
|
|
19214
|
-
if (fileLine
|
|
19312
|
+
if (linesEqual(fileLine, op.text, fuzzy)) {
|
|
19215
19313
|
hunkFileIdx++;
|
|
19216
19314
|
hunkIdx++;
|
|
19217
19315
|
} else {
|
|
@@ -19244,6 +19342,7 @@ var init_diff = __esm({
|
|
|
19244
19342
|
"use strict";
|
|
19245
19343
|
init_zod();
|
|
19246
19344
|
init_toolTypes();
|
|
19345
|
+
init_newlines();
|
|
19247
19346
|
LCS_MAX_CELLS = 4e6;
|
|
19248
19347
|
ShowDiffArgsSchema = external_exports.object({
|
|
19249
19348
|
path: external_exports.string().min(1),
|
|
@@ -19268,8 +19367,8 @@ var init_diff = __esm({
|
|
|
19268
19367
|
return typedErr(err instanceof Error ? err.message : String(err));
|
|
19269
19368
|
}
|
|
19270
19369
|
}
|
|
19271
|
-
const a = current
|
|
19272
|
-
const b = args.proposedContent
|
|
19370
|
+
const a = splitLinesLF(current);
|
|
19371
|
+
const b = splitLinesLF(args.proposedContent);
|
|
19273
19372
|
const CONTEXT = args.contextLines;
|
|
19274
19373
|
const rawOps = diffOps(a, b);
|
|
19275
19374
|
if (rawOps === null) {
|
|
@@ -19355,7 +19454,7 @@ var init_diff = __esm({
|
|
|
19355
19454
|
});
|
|
19356
19455
|
applyDiffTool = {
|
|
19357
19456
|
name: "apply_diff",
|
|
19358
|
-
description: "Apply a unified diff patch to a file. Parses ---/+++/@@ headers and applies each hunk sequentially. With fuzzyMatch=true, tolerates whitespace differences. With dryRun=true, returns the final content without writing. Atomic: if any hunk fails, no partial write occurs.",
|
|
19457
|
+
description: "Apply a unified diff patch to a file. Parses ---/+++/@@ headers and applies each hunk sequentially. CRLF vs LF is ignored; the file keeps its original line endings. Hunks whose @@ line numbers drifted (common after an earlier insert) are relocated by matching context. With fuzzyMatch=true, also tolerates whitespace differences. With dryRun=true, returns the final content without writing. Atomic: if any hunk fails, no partial write occurs.",
|
|
19359
19458
|
permissions: ["write"],
|
|
19360
19459
|
sideEffect: "local",
|
|
19361
19460
|
timeoutMs: 15e3,
|
|
@@ -19380,9 +19479,10 @@ var init_diff = __esm({
|
|
|
19380
19479
|
if (parsed.hunks.length === 0) {
|
|
19381
19480
|
return typedErr("No hunks found in diff");
|
|
19382
19481
|
}
|
|
19383
|
-
const
|
|
19482
|
+
const nl = detectNewline(current);
|
|
19483
|
+
const originalLines = splitLinesLF(current);
|
|
19384
19484
|
const result = applyAllHunks(originalLines, parsed.hunks, args.fuzzyMatch);
|
|
19385
|
-
const finalContent = result.lines.join("\n");
|
|
19485
|
+
const finalContent = fromLF(result.lines.join("\n"), nl);
|
|
19386
19486
|
const ok = result.hunksSkipped === 0;
|
|
19387
19487
|
if (ok && !args.dryRun) {
|
|
19388
19488
|
await fs7.mkdir(path10.dirname(absPath), { recursive: true });
|
|
@@ -39312,7 +39412,7 @@ var init_taskTool = __esm({
|
|
|
39312
39412
|
init_candidateRegistry();
|
|
39313
39413
|
init_verifyReport();
|
|
39314
39414
|
init_metrics2();
|
|
39315
|
-
TASK_TOOL_TIMEOUT_MS =
|
|
39415
|
+
TASK_TOOL_TIMEOUT_MS = 27e5;
|
|
39316
39416
|
EXPLORE_PROMPT = [
|
|
39317
39417
|
"You are a focused EXPLORE tentacle of Kraken (parent super-agent).",
|
|
39318
39418
|
"READ-ONLY tools only (read, list, grep, fetch). No edits, no shell.",
|
|
@@ -45291,10 +45391,10 @@ import { readFileSync as readFileSync22 } from "node:fs";
|
|
|
45291
45391
|
import { homedir as homedir10 } from "node:os";
|
|
45292
45392
|
import path40 from "node:path";
|
|
45293
45393
|
function emptyPolicySet() {
|
|
45294
|
-
return { agents: /* @__PURE__ */ new Map(), warnings: [] };
|
|
45394
|
+
return { agents: /* @__PURE__ */ new Map(), warnings: [], precedence: policyPrecedenceFromEnv() };
|
|
45295
45395
|
}
|
|
45296
|
-
function
|
|
45297
|
-
return set2.agents.get(agent) ??
|
|
45396
|
+
function agentLayersFor(set2, agent) {
|
|
45397
|
+
return set2.agents.get(agent) ?? EMPTY_POLICY_LAYERS;
|
|
45298
45398
|
}
|
|
45299
45399
|
function globToRegExp(pattern) {
|
|
45300
45400
|
let src = "^";
|
|
@@ -45357,6 +45457,10 @@ function isPolicyEngineDisabled() {
|
|
|
45357
45457
|
const v = process.env.ZELARI_POLICY?.trim().toLowerCase();
|
|
45358
45458
|
return v === "0" || v === "false" || v === "no" || v === "off";
|
|
45359
45459
|
}
|
|
45460
|
+
function policyPrecedenceFromEnv() {
|
|
45461
|
+
const v = process.env.ZELARI_POLICY_PRECEDENCE?.trim().toLowerCase();
|
|
45462
|
+
return v === "legacy" ? "legacy" : "restrict-only";
|
|
45463
|
+
}
|
|
45360
45464
|
function isPlainObject2(v) {
|
|
45361
45465
|
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
45362
45466
|
}
|
|
@@ -45447,29 +45551,70 @@ function readPolicyFile(file2, warnings) {
|
|
|
45447
45551
|
function loadPolicySet(root, opts = {}) {
|
|
45448
45552
|
if (isPolicyEngineDisabled()) return emptyPolicySet();
|
|
45449
45553
|
const warnings = [];
|
|
45554
|
+
const precedence = policyPrecedenceFromEnv();
|
|
45450
45555
|
const project = readPolicyFile(path40.join(root, ".zelari", "policy.json"), warnings);
|
|
45451
45556
|
const global = readPolicyFile(path40.join(opts.homeDir ?? homedir10(), ".zelari", "policy.json"), warnings);
|
|
45452
45557
|
const agents = /* @__PURE__ */ new Map();
|
|
45453
|
-
for (const [agent, g] of global) {
|
|
45454
|
-
agents.set(agent, { shell: [...g.shell], edit: [...g.edit] });
|
|
45455
|
-
}
|
|
45456
45558
|
for (const [agent, p3] of project) {
|
|
45457
|
-
|
|
45458
|
-
agents.set(agent, { shell: [...p3.shell, ...g.shell], edit: [...p3.edit, ...g.edit] });
|
|
45559
|
+
agents.set(agent, { project: p3, global: EMPTY_POLICY_RULE_SET });
|
|
45459
45560
|
}
|
|
45460
|
-
|
|
45561
|
+
for (const [agent, g] of global) {
|
|
45562
|
+
const l = agents.get(agent);
|
|
45563
|
+
agents.set(agent, l ? { ...l, global: g } : { project: EMPTY_POLICY_RULE_SET, global: g });
|
|
45564
|
+
}
|
|
45565
|
+
return { agents, warnings, precedence };
|
|
45461
45566
|
}
|
|
45462
|
-
var POLICY_AGENTS, KNOWN_AGENTS, EMPTY_POLICY_RULE_SET, EFFECT_RANK;
|
|
45567
|
+
var POLICY_AGENTS, KNOWN_AGENTS, EMPTY_POLICY_RULE_SET, EMPTY_POLICY_LAYERS, EFFECT_RANK;
|
|
45463
45568
|
var init_policyEngine = __esm({
|
|
45464
45569
|
"src/cli/safety/policyEngine.ts"() {
|
|
45465
45570
|
"use strict";
|
|
45466
45571
|
POLICY_AGENTS = ["lead", "explore", "general", "verify"];
|
|
45467
45572
|
KNOWN_AGENTS = new Set(POLICY_AGENTS);
|
|
45468
45573
|
EMPTY_POLICY_RULE_SET = { shell: [], edit: [] };
|
|
45574
|
+
EMPTY_POLICY_LAYERS = {
|
|
45575
|
+
global: EMPTY_POLICY_RULE_SET,
|
|
45576
|
+
project: EMPTY_POLICY_RULE_SET
|
|
45577
|
+
};
|
|
45469
45578
|
EFFECT_RANK = { allow: 0, ask: 1, deny: 2 };
|
|
45470
45579
|
}
|
|
45471
45580
|
});
|
|
45472
45581
|
|
|
45582
|
+
// src/cli/safety/policyLayers.ts
|
|
45583
|
+
function intersectEffects(...effects) {
|
|
45584
|
+
let best;
|
|
45585
|
+
for (const effect of effects) {
|
|
45586
|
+
if (effect === void 0) continue;
|
|
45587
|
+
if (best === void 0 || EFFECT_RANK[effect] > EFFECT_RANK[best]) best = effect;
|
|
45588
|
+
}
|
|
45589
|
+
return best ?? "allow";
|
|
45590
|
+
}
|
|
45591
|
+
function matchAgentPolicyRuleLayered(layers, precedence, required2, args, root) {
|
|
45592
|
+
if (!layers) return null;
|
|
45593
|
+
if (precedence === "legacy") {
|
|
45594
|
+
return matchAgentPolicyRule(
|
|
45595
|
+
{
|
|
45596
|
+
shell: [...layers.project.shell, ...layers.global.shell],
|
|
45597
|
+
edit: [...layers.project.edit, ...layers.global.edit]
|
|
45598
|
+
},
|
|
45599
|
+
required2,
|
|
45600
|
+
args,
|
|
45601
|
+
root
|
|
45602
|
+
);
|
|
45603
|
+
}
|
|
45604
|
+
const g = matchAgentPolicyRule(layers.global, required2, args, root);
|
|
45605
|
+
const p3 = matchAgentPolicyRule(layers.project, required2, args, root);
|
|
45606
|
+
if (!g) return p3;
|
|
45607
|
+
if (!p3) return g;
|
|
45608
|
+
const win = intersectEffects(p3.effect, g.effect);
|
|
45609
|
+
return p3.effect === win ? p3 : g;
|
|
45610
|
+
}
|
|
45611
|
+
var init_policyLayers = __esm({
|
|
45612
|
+
"src/cli/safety/policyLayers.ts"() {
|
|
45613
|
+
"use strict";
|
|
45614
|
+
init_policyEngine();
|
|
45615
|
+
}
|
|
45616
|
+
});
|
|
45617
|
+
|
|
45473
45618
|
// src/cli/toolResultCache.ts
|
|
45474
45619
|
import { createHash as createHash13 } from "node:crypto";
|
|
45475
45620
|
import { promises as fs19 } from "node:fs";
|
|
@@ -45810,11 +45955,19 @@ function createBuiltinToolRegistry(options = {}) {
|
|
|
45810
45955
|
const allowMutators = !readOnly && !verifyMode && !gauntletParent;
|
|
45811
45956
|
const allowBash = (allowMutators || verifyMode) && !gauntletParent;
|
|
45812
45957
|
const permPolicy = options.permissionPolicy ?? defaultPermissionPolicy();
|
|
45813
|
-
const
|
|
45814
|
-
|
|
45958
|
+
const agentPolicySet = loadPolicySet(root);
|
|
45959
|
+
const agentPolicyLayers = agentLayersFor(
|
|
45960
|
+
agentPolicySet,
|
|
45815
45961
|
options.policyAgent ?? "lead"
|
|
45816
45962
|
);
|
|
45817
|
-
const withPerm = (t) => wrapWithPermissions(
|
|
45963
|
+
const withPerm = (t) => wrapWithPermissions(
|
|
45964
|
+
t,
|
|
45965
|
+
permPolicy,
|
|
45966
|
+
options.onPermissionAsk,
|
|
45967
|
+
agentPolicyLayers,
|
|
45968
|
+
agentPolicySet.precedence,
|
|
45969
|
+
root
|
|
45970
|
+
);
|
|
45818
45971
|
registry4.register(withPerm(safeReadFile));
|
|
45819
45972
|
registry4.register(withPerm(safeGrepContent));
|
|
45820
45973
|
registry4.register(withPerm(safeListFiles));
|
|
@@ -46081,7 +46234,7 @@ function createKrakenSubAgentContextFactory(opts) {
|
|
|
46081
46234
|
};
|
|
46082
46235
|
};
|
|
46083
46236
|
}
|
|
46084
|
-
function wrapWithPermissions(original, policy, onAsk,
|
|
46237
|
+
function wrapWithPermissions(original, policy, onAsk, agentLayers, precedence = "restrict-only", root) {
|
|
46085
46238
|
const required2 = original.permissions ?? [];
|
|
46086
46239
|
const decisionProbe = resolveToolPermission(original.name, required2, policy);
|
|
46087
46240
|
if (decisionProbe.action === "allow" && !required2.includes("write") && !required2.includes("execute")) {
|
|
@@ -46090,8 +46243,9 @@ function wrapWithPermissions(original, policy, onAsk, agentRules, root) {
|
|
|
46090
46243
|
...original,
|
|
46091
46244
|
execute: async (input, ctx) => {
|
|
46092
46245
|
const decision = resolveToolPermission(original.name, required2, policy);
|
|
46093
|
-
const rule =
|
|
46094
|
-
|
|
46246
|
+
const rule = agentLayers ? matchAgentPolicyRuleLayered(
|
|
46247
|
+
agentLayers,
|
|
46248
|
+
precedence,
|
|
46095
46249
|
required2,
|
|
46096
46250
|
input ?? {},
|
|
46097
46251
|
root ?? process.cwd()
|
|
@@ -46321,6 +46475,7 @@ var init_toolRegistry = __esm({
|
|
|
46321
46475
|
init_toolPermissions();
|
|
46322
46476
|
init_lifecycleHooks();
|
|
46323
46477
|
init_policyEngine();
|
|
46478
|
+
init_policyLayers();
|
|
46324
46479
|
init_toolResultCache();
|
|
46325
46480
|
init_toolTypes();
|
|
46326
46481
|
init_skills2();
|
|
@@ -69165,7 +69320,7 @@ var CsvFanoutArgsSchema = external_exports.object({
|
|
|
69165
69320
|
scope_template: external_exports.array(external_exports.string()).optional(),
|
|
69166
69321
|
/** Default: ZELARI_KRAKEN_MAX_PARALLEL. */
|
|
69167
69322
|
max_concurrency: external_exports.number().int().positive().optional(),
|
|
69168
|
-
/** Per-row timeout (ms). Default: 5 min for verify,
|
|
69323
|
+
/** Per-row timeout (ms). Default: 5 min for verify, 45 min for general. */
|
|
69169
69324
|
max_runtime_seconds: external_exports.number().int().positive().optional()
|
|
69170
69325
|
});
|
|
69171
69326
|
async function readCsv(filePath) {
|
|
@@ -69256,7 +69411,7 @@ async function runCsvFanout(args, deps, opts) {
|
|
|
69256
69411
|
}
|
|
69257
69412
|
const concurrency = args.max_concurrency ?? resolveMaxConcurrency();
|
|
69258
69413
|
opts.onLog?.(`csv fanout: ${rows.length} rows \xD7 ${args.agent_kind} @ concurrency=${concurrency}`);
|
|
69259
|
-
const perRowMs = args.max_runtime_seconds !== void 0 ? args.max_runtime_seconds * 1e3 : args.agent_kind === "general" ?
|
|
69414
|
+
const perRowMs = args.max_runtime_seconds !== void 0 ? args.max_runtime_seconds * 1e3 : args.agent_kind === "general" ? TASK_TOOL_TIMEOUT_MS : 3e5;
|
|
69260
69415
|
const outputRecords = rows.map((r) => ({ ...r, status: "pending", result: "", error: "" }));
|
|
69261
69416
|
const outHeaders = [...headers2, "status", "result", "error"];
|
|
69262
69417
|
let writeChain2 = Promise.resolve();
|