zelari-code 2.2.0 → 2.3.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/kraken/executor.js +9 -8
- package/dist/cli/kraken/executor.js.map +1 -1
- package/dist/cli/kraken/tentacle.js +1 -1
- package/dist/cli/kraken/tentacle.js.map +1 -1
- package/dist/cli/main.bundled.js +479 -126
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/tools/taskTool.js +88 -72
- package/dist/cli/tools/taskTool.js.map +1 -1
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -18246,14 +18246,15 @@ var init_filesystem = __esm({
|
|
|
18246
18246
|
init_toolTypes();
|
|
18247
18247
|
ReadFileArgsSchema = external_exports.object({
|
|
18248
18248
|
path: external_exports.string().min(1),
|
|
18249
|
-
startLine: external_exports.number().int().nonnegative().optional(),
|
|
18250
|
-
endLine: external_exports.number().int().positive().optional(),
|
|
18249
|
+
startLine: external_exports.number().int().nonnegative().optional().describe("0-based first line to include. Range is applied to the full file before maxBytes."),
|
|
18250
|
+
endLine: external_exports.number().int().positive().optional().describe("Exclusive 0-based end line. Omit to read through EOF (still capped by maxBytes)."),
|
|
18251
18251
|
maxBytes: external_exports.number().int().positive().max(1e7).default(1e6)
|
|
18252
18252
|
});
|
|
18253
18253
|
readFileTool = {
|
|
18254
18254
|
name: "read_file",
|
|
18255
|
-
description: "Read a file with optional line range. Returns content + metadata. Use before edit_file.",
|
|
18255
|
+
description: "Read a file with optional 0-based line range (endLine exclusive). maxBytes caps the selected range, not a prefix of the file. Returns content + metadata. Use before edit_file.",
|
|
18256
18256
|
permissions: ["read"],
|
|
18257
|
+
sideEffect: "none",
|
|
18257
18258
|
timeoutMs: 5e3,
|
|
18258
18259
|
inputSchema: ReadFileArgsSchema,
|
|
18259
18260
|
execute: async (args, ctx) => {
|
|
@@ -18262,24 +18263,31 @@ var init_filesystem = __esm({
|
|
|
18262
18263
|
const buf = await fs4.readFile(absPath, { encoding: "utf-8", signal: ctx.signal });
|
|
18263
18264
|
const content = typeof buf === "string" ? buf : buf.toString("utf-8");
|
|
18264
18265
|
const allLines = content.split("\n");
|
|
18265
|
-
const truncated = content.length > args.maxBytes ? content.slice(0, args.maxBytes) : content;
|
|
18266
|
-
const lines = truncated === content ? allLines : truncated.split("\n");
|
|
18267
18266
|
const totalLines = allLines.length;
|
|
18268
18267
|
const start = args.startLine ?? 0;
|
|
18269
|
-
const
|
|
18270
|
-
const wasTruncated = truncated !== content;
|
|
18268
|
+
const endExclusive = Math.min(args.endLine ?? totalLines, totalLines);
|
|
18271
18269
|
const empty = content.length === 0;
|
|
18272
|
-
const
|
|
18270
|
+
const rangeEmpty = !empty && (start >= totalLines || endExclusive <= start);
|
|
18271
|
+
const selected = rangeEmpty ? [] : allLines.slice(start, endExclusive);
|
|
18272
|
+
let text = selected.join("\n");
|
|
18273
|
+
const wasTruncated = text.length > args.maxBytes;
|
|
18274
|
+
if (wasTruncated)
|
|
18275
|
+
text = text.slice(0, args.maxBytes);
|
|
18276
|
+
const returnedLines = text.length === 0 ? 0 : text.split("\n").length;
|
|
18277
|
+
const readEnd = returnedLines === 0 ? Math.max(0, start - 1) : start + returnedLines - 1;
|
|
18278
|
+
const status = empty || rangeEmpty ? "empty" : wasTruncated ? "partial" : "complete";
|
|
18273
18279
|
const warnings = [];
|
|
18274
18280
|
if (empty)
|
|
18275
18281
|
warnings.push("EMPTY_FILE");
|
|
18282
|
+
if (rangeEmpty)
|
|
18283
|
+
warnings.push("LINE_RANGE_EMPTY");
|
|
18276
18284
|
if (wasTruncated)
|
|
18277
18285
|
warnings.push("MAX_BYTES_TRUNCATED");
|
|
18278
18286
|
return typedOk({
|
|
18279
18287
|
path: absPath,
|
|
18280
|
-
content:
|
|
18288
|
+
content: text,
|
|
18281
18289
|
totalLines,
|
|
18282
|
-
readLines: { start, end:
|
|
18290
|
+
readLines: { start, end: readEnd },
|
|
18283
18291
|
sizeBytes: content.length
|
|
18284
18292
|
}, {
|
|
18285
18293
|
status,
|
|
@@ -18305,6 +18313,7 @@ var init_filesystem = __esm({
|
|
|
18305
18313
|
name: "write_file",
|
|
18306
18314
|
description: "Write or create a file. Use createDirs=true to auto-create parent directories.",
|
|
18307
18315
|
permissions: ["write"],
|
|
18316
|
+
sideEffect: "local",
|
|
18308
18317
|
timeoutMs: 1e4,
|
|
18309
18318
|
inputSchema: WriteFileArgsSchema,
|
|
18310
18319
|
execute: async (args, ctx) => {
|
|
@@ -18330,6 +18339,7 @@ var init_filesystem = __esm({
|
|
|
18330
18339
|
name: "edit_file",
|
|
18331
18340
|
description: "Replace exact string match in a file. Idempotent: returns 0 occurrences if no match.",
|
|
18332
18341
|
permissions: ["write"],
|
|
18342
|
+
sideEffect: "local",
|
|
18333
18343
|
timeoutMs: 1e4,
|
|
18334
18344
|
inputSchema: EditFileArgsSchema,
|
|
18335
18345
|
execute: async (args, ctx) => {
|
|
@@ -18561,6 +18571,7 @@ var init_shell = __esm({
|
|
|
18561
18571
|
name: "bash",
|
|
18562
18572
|
description: "Run a shell command. On Windows uses Git Bash when available (POSIX semantics: ls, $VAR, && work); falls back to cmd.exe otherwise. Streams stdout/stderr. Respects timeout and cancellation. Returns exit code. stdin is CLOSED (non-interactive): any command that prompts for input will fail or be cancelled \u2014 always pass non-interactive flags (--yes, -y, --template), and if a scaffolder insists on prompting (e.g. create-vite in a non-empty directory), create the files manually with write_file instead.",
|
|
18563
18573
|
permissions: ["execute"],
|
|
18574
|
+
sideEffect: "local",
|
|
18564
18575
|
timeoutMs: 6e4,
|
|
18565
18576
|
inputSchema: BashArgsSchema,
|
|
18566
18577
|
execute: async (args, ctx) => {
|
|
@@ -18870,6 +18881,7 @@ var init_search = __esm({
|
|
|
18870
18881
|
name: "grep_content",
|
|
18871
18882
|
description: 'Regex search for content in a file OR recursively in a directory. When path is a directory, include/exclude globs filter which files are searched (default: all files, excluding node_modules/dist/.git/etc.). Glob semantics: "*" matches ONE path segment only ("*.ts" does NOT match "sub/file.ts"); use "**" for recursive matching ("**/*.ts" matches at any depth). include/exclude accept a single glob string (e.g. "*.ts") OR an array of globs. Returns matches with line numbers and context, plus filesWalked/filesInTree counts and a warning when the include globs matched suspiciously few files.',
|
|
18872
18883
|
permissions: ["read"],
|
|
18884
|
+
sideEffect: "none",
|
|
18873
18885
|
timeoutMs: 3e4,
|
|
18874
18886
|
inputSchema: GrepContentArgsSchema,
|
|
18875
18887
|
execute: async (args, ctx) => {
|
|
@@ -18987,6 +18999,7 @@ var init_listFiles = __esm({
|
|
|
18987
18999
|
name: "list_files",
|
|
18988
19000
|
description: "List files and directories in the given path (defaults to the working directory). Returns names with types (file/directory). Use this to discover the project structure before reading specific files. Supports a maxDepth for recursive listing and excludes common dependency/build directories by default.",
|
|
18989
19001
|
permissions: ["read"],
|
|
19002
|
+
sideEffect: "none",
|
|
18990
19003
|
timeoutMs: 15e3,
|
|
18991
19004
|
inputSchema: ListFilesArgsSchema,
|
|
18992
19005
|
execute: async (args, ctx) => {
|
|
@@ -19241,6 +19254,7 @@ var init_diff = __esm({
|
|
|
19241
19254
|
name: "show_diff",
|
|
19242
19255
|
description: "Show unified diff between current file content and proposed content. Read-only \u2014 does NOT modify the file. Use this to preview edits before applying with edit_file or apply_diff.",
|
|
19243
19256
|
permissions: ["read"],
|
|
19257
|
+
sideEffect: "none",
|
|
19244
19258
|
timeoutMs: 15e3,
|
|
19245
19259
|
inputSchema: ShowDiffArgsSchema,
|
|
19246
19260
|
execute: async (args, ctx) => {
|
|
@@ -19343,6 +19357,7 @@ var init_diff = __esm({
|
|
|
19343
19357
|
name: "apply_diff",
|
|
19344
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.",
|
|
19345
19359
|
permissions: ["write"],
|
|
19360
|
+
sideEffect: "local",
|
|
19346
19361
|
timeoutMs: 15e3,
|
|
19347
19362
|
inputSchema: ApplyDiffArgsSchema,
|
|
19348
19363
|
execute: async (args, ctx) => {
|
|
@@ -21471,6 +21486,42 @@ var init_types = __esm({
|
|
|
21471
21486
|
}
|
|
21472
21487
|
});
|
|
21473
21488
|
|
|
21489
|
+
// packages/core/dist/core/tools/concurrency.js
|
|
21490
|
+
function taskAgent(args) {
|
|
21491
|
+
if (!args || typeof args !== "object")
|
|
21492
|
+
return "explore";
|
|
21493
|
+
const agent = args.agent;
|
|
21494
|
+
return typeof agent === "string" && agent.trim() ? agent : "explore";
|
|
21495
|
+
}
|
|
21496
|
+
function classifyToolConcurrency(input) {
|
|
21497
|
+
const env = input.env ?? process.env;
|
|
21498
|
+
if (env.ZELARI_PARALLEL_TOOLS === "0")
|
|
21499
|
+
return "exclusive";
|
|
21500
|
+
const name = input.toolName;
|
|
21501
|
+
if (name === "task") {
|
|
21502
|
+
return taskAgent(input.args) === "general" ? "exclusive" : "parallel-safe";
|
|
21503
|
+
}
|
|
21504
|
+
if (input.registered === false) {
|
|
21505
|
+
if (name.startsWith("mcp_")) {
|
|
21506
|
+
const lower = name.toLowerCase();
|
|
21507
|
+
if (lower.includes("write") || lower.includes("edit") || lower.includes("delete")) {
|
|
21508
|
+
return "exclusive";
|
|
21509
|
+
}
|
|
21510
|
+
return "parallel-safe";
|
|
21511
|
+
}
|
|
21512
|
+
return "exclusive";
|
|
21513
|
+
}
|
|
21514
|
+
const perms = input.permissions ?? [];
|
|
21515
|
+
if (perms.includes("write") || perms.includes("execute"))
|
|
21516
|
+
return "exclusive";
|
|
21517
|
+
return "parallel-safe";
|
|
21518
|
+
}
|
|
21519
|
+
var init_concurrency = __esm({
|
|
21520
|
+
"packages/core/dist/core/tools/concurrency.js"() {
|
|
21521
|
+
"use strict";
|
|
21522
|
+
}
|
|
21523
|
+
});
|
|
21524
|
+
|
|
21474
21525
|
// packages/core/dist/core/contextGrowth.js
|
|
21475
21526
|
function emptyContextGrowthStats() {
|
|
21476
21527
|
return {
|
|
@@ -22022,6 +22073,7 @@ var init_AgentHarness = __esm({
|
|
|
22022
22073
|
"packages/core/dist/core/AgentHarness.js"() {
|
|
22023
22074
|
"use strict";
|
|
22024
22075
|
init_events();
|
|
22076
|
+
init_concurrency();
|
|
22025
22077
|
init_toolTypes();
|
|
22026
22078
|
init_contextGrowth();
|
|
22027
22079
|
init_requestSnapshot();
|
|
@@ -22106,30 +22158,19 @@ var init_AgentHarness = __esm({
|
|
|
22106
22158
|
};
|
|
22107
22159
|
}
|
|
22108
22160
|
/**
|
|
22109
|
-
* v1.8.0: true when a tool may run concurrently with other
|
|
22110
|
-
* tools. Write/execute
|
|
22111
|
-
*
|
|
22161
|
+
* v1.8.0 / 2.x F: true when a tool may run concurrently with other
|
|
22162
|
+
* parallel-safe tools. Write/execute stay serial. `task agent=general`
|
|
22163
|
+
* is exclusive (it writes); explore/verify tentacles stay parallel-safe.
|
|
22164
|
+
* Opt out: ZELARI_PARALLEL_TOOLS=0.
|
|
22112
22165
|
*/
|
|
22113
|
-
isParallelSafeTool(toolName) {
|
|
22114
|
-
if (process.env.ZELARI_PARALLEL_TOOLS === "0")
|
|
22115
|
-
return false;
|
|
22116
|
-
if (toolName === "task")
|
|
22117
|
-
return true;
|
|
22166
|
+
isParallelSafeTool(toolName, args) {
|
|
22118
22167
|
const def = this.config.toolRegistry?.get(toolName);
|
|
22119
|
-
|
|
22120
|
-
|
|
22121
|
-
|
|
22122
|
-
|
|
22123
|
-
|
|
22124
|
-
|
|
22125
|
-
return true;
|
|
22126
|
-
}
|
|
22127
|
-
return false;
|
|
22128
|
-
}
|
|
22129
|
-
const perms = def.permissions ?? [];
|
|
22130
|
-
if (perms.includes("write") || perms.includes("execute"))
|
|
22131
|
-
return false;
|
|
22132
|
-
return true;
|
|
22168
|
+
return classifyToolConcurrency({
|
|
22169
|
+
toolName,
|
|
22170
|
+
args,
|
|
22171
|
+
permissions: def?.permissions,
|
|
22172
|
+
registered: Boolean(def) || toolName === "task"
|
|
22173
|
+
}) === "parallel-safe";
|
|
22133
22174
|
}
|
|
22134
22175
|
/**
|
|
22135
22176
|
* Execute buffered native tool calls: consecutive parallel-safe tools run
|
|
@@ -22234,13 +22275,13 @@ ${shared2.content}`,
|
|
|
22234
22275
|
let i = 0;
|
|
22235
22276
|
while (i < pending.length) {
|
|
22236
22277
|
const p3 = pending[i];
|
|
22237
|
-
if (p3.skipped || p3.cached !== void 0 || !this.isParallelSafeTool(p3.toolName)) {
|
|
22278
|
+
if (p3.skipped || p3.cached !== void 0 || !this.isParallelSafeTool(p3.toolName, p3.args)) {
|
|
22238
22279
|
out[i] = toOut(p3, await invokeOne(p3));
|
|
22239
22280
|
i += 1;
|
|
22240
22281
|
continue;
|
|
22241
22282
|
}
|
|
22242
22283
|
let j = i;
|
|
22243
|
-
while (j < pending.length && !pending[j].skipped && pending[j].cached === void 0 && this.isParallelSafeTool(pending[j].toolName)) {
|
|
22284
|
+
while (j < pending.length && !pending[j].skipped && pending[j].cached === void 0 && this.isParallelSafeTool(pending[j].toolName, pending[j].args)) {
|
|
22244
22285
|
j += 1;
|
|
22245
22286
|
}
|
|
22246
22287
|
for (let off = i; off < j; off += maxParallel) {
|
|
@@ -28263,6 +28304,8 @@ var init_types8 = __esm({
|
|
|
28263
28304
|
"assistant.message",
|
|
28264
28305
|
"tool.call",
|
|
28265
28306
|
"tool.result",
|
|
28307
|
+
// 2.x B (crash-safe recovery): dangling call classified. State-only.
|
|
28308
|
+
"tool.interrupted",
|
|
28266
28309
|
"context.injected",
|
|
28267
28310
|
"session.compacted",
|
|
28268
28311
|
"task.created",
|
|
@@ -28515,6 +28558,82 @@ var init_writer = __esm({
|
|
|
28515
28558
|
}
|
|
28516
28559
|
});
|
|
28517
28560
|
|
|
28561
|
+
// packages/core/dist/session/recovery.js
|
|
28562
|
+
function sideEffectForTool(tool, declared) {
|
|
28563
|
+
if (declared)
|
|
28564
|
+
return declared;
|
|
28565
|
+
if (EXTERNAL.has(tool))
|
|
28566
|
+
return "external";
|
|
28567
|
+
if (READ_ONLY.has(tool))
|
|
28568
|
+
return "none";
|
|
28569
|
+
return "local";
|
|
28570
|
+
}
|
|
28571
|
+
function retrySafetyForSideEffect(sideEffect) {
|
|
28572
|
+
return sideEffect === "none" ? "safe" : "inspect-first";
|
|
28573
|
+
}
|
|
28574
|
+
function toolNameOf(call) {
|
|
28575
|
+
return typeof call.data.tool === "string" && call.data.tool.trim() ? call.data.tool : "unknown";
|
|
28576
|
+
}
|
|
28577
|
+
function callIdOf(call) {
|
|
28578
|
+
return typeof call.data.callId === "string" ? call.data.callId : `seq:${call.seq}`;
|
|
28579
|
+
}
|
|
28580
|
+
function classifyInterruptedTools(events, sideEffects = /* @__PURE__ */ new Map()) {
|
|
28581
|
+
const alreadyClassified = new Set(events.filter((e) => e.kind === "tool.interrupted").map((e) => typeof e.data.callId === "string" ? e.data.callId : void 0).filter((id) => Boolean(id)));
|
|
28582
|
+
const out = [];
|
|
28583
|
+
for (const pair of pairToolCalls(events)) {
|
|
28584
|
+
if (pair.result)
|
|
28585
|
+
continue;
|
|
28586
|
+
const callId = callIdOf(pair.call);
|
|
28587
|
+
if (alreadyClassified.has(callId))
|
|
28588
|
+
continue;
|
|
28589
|
+
const tool = toolNameOf(pair.call);
|
|
28590
|
+
const sideEffect = sideEffectForTool(tool, sideEffects.get(tool));
|
|
28591
|
+
const retrySafety = retrySafetyForSideEffect(sideEffect);
|
|
28592
|
+
out.push({
|
|
28593
|
+
toolCallSeq: pair.call.seq,
|
|
28594
|
+
callId,
|
|
28595
|
+
tool,
|
|
28596
|
+
state: retrySafety === "safe" ? "not-started" : "started-outcome-unknown",
|
|
28597
|
+
retrySafety,
|
|
28598
|
+
sideEffect
|
|
28599
|
+
});
|
|
28600
|
+
}
|
|
28601
|
+
return out;
|
|
28602
|
+
}
|
|
28603
|
+
function interruptedEventData(item) {
|
|
28604
|
+
return {
|
|
28605
|
+
toolCallSeq: item.toolCallSeq,
|
|
28606
|
+
callId: item.callId,
|
|
28607
|
+
tool: item.tool,
|
|
28608
|
+
state: item.state,
|
|
28609
|
+
retrySafety: item.retrySafety,
|
|
28610
|
+
sideEffect: item.sideEffect
|
|
28611
|
+
};
|
|
28612
|
+
}
|
|
28613
|
+
var READ_ONLY, EXTERNAL;
|
|
28614
|
+
var init_recovery = __esm({
|
|
28615
|
+
"packages/core/dist/session/recovery.js"() {
|
|
28616
|
+
"use strict";
|
|
28617
|
+
init_modelSurface();
|
|
28618
|
+
READ_ONLY = /* @__PURE__ */ new Set([
|
|
28619
|
+
"read_file",
|
|
28620
|
+
"list_files",
|
|
28621
|
+
"grep_content",
|
|
28622
|
+
"show_diff",
|
|
28623
|
+
"web_search",
|
|
28624
|
+
"fetch_url",
|
|
28625
|
+
"lsp_definition",
|
|
28626
|
+
"lsp_references",
|
|
28627
|
+
"lsp_hover",
|
|
28628
|
+
"lsp_symbols",
|
|
28629
|
+
"ast_outline",
|
|
28630
|
+
"ast_find_symbol",
|
|
28631
|
+
"semantic_search"
|
|
28632
|
+
]);
|
|
28633
|
+
EXTERNAL = /* @__PURE__ */ new Set(["fetch_url", "web_search"]);
|
|
28634
|
+
}
|
|
28635
|
+
});
|
|
28636
|
+
|
|
28518
28637
|
// packages/core/dist/session/replay.js
|
|
28519
28638
|
import { promises as fs10 } from "node:fs";
|
|
28520
28639
|
async function readSessionLog(filePath) {
|
|
@@ -28599,7 +28718,8 @@ function buildProjection(events, issues = []) {
|
|
|
28599
28718
|
missionPhases: [],
|
|
28600
28719
|
missionAdvice: [],
|
|
28601
28720
|
replans: 0,
|
|
28602
|
-
issues
|
|
28721
|
+
issues,
|
|
28722
|
+
interruptedTools: classifyInterruptedTools(events)
|
|
28603
28723
|
};
|
|
28604
28724
|
for (const e of events) {
|
|
28605
28725
|
switch (e.kind) {
|
|
@@ -28650,6 +28770,7 @@ var init_replay = __esm({
|
|
|
28650
28770
|
"use strict";
|
|
28651
28771
|
init_types8();
|
|
28652
28772
|
init_modelSurface();
|
|
28773
|
+
init_recovery();
|
|
28653
28774
|
}
|
|
28654
28775
|
});
|
|
28655
28776
|
|
|
@@ -28789,12 +28910,20 @@ async function forkSession(store6, parentSessionId, options = {}) {
|
|
|
28789
28910
|
}
|
|
28790
28911
|
async function resumeSession(store6, sessionId2) {
|
|
28791
28912
|
const opened = await store6.open(sessionId2);
|
|
28913
|
+
const classified = [];
|
|
28914
|
+
for (const item of classifyInterruptedTools(opened.report.events)) {
|
|
28915
|
+
classified.push(await opened.writer.append({
|
|
28916
|
+
kind: "tool.interrupted",
|
|
28917
|
+
actor: ACTOR_SYSTEM,
|
|
28918
|
+
data: interruptedEventData(item)
|
|
28919
|
+
}));
|
|
28920
|
+
}
|
|
28792
28921
|
const resumed = await opened.writer.append({
|
|
28793
28922
|
kind: "session.resumed",
|
|
28794
28923
|
actor: ACTOR_SYSTEM,
|
|
28795
28924
|
data: { fromSeq: opened.projection.lastSeq }
|
|
28796
28925
|
});
|
|
28797
|
-
const projection = buildProjection([...opened.report.events, resumed]);
|
|
28926
|
+
const projection = buildProjection([...opened.report.events, ...classified, resumed]);
|
|
28798
28927
|
return { writer: opened.writer, projection };
|
|
28799
28928
|
}
|
|
28800
28929
|
async function lineageOf(store6, sessionId2) {
|
|
@@ -28822,6 +28951,7 @@ var init_lineage = __esm({
|
|
|
28822
28951
|
"use strict";
|
|
28823
28952
|
init_types8();
|
|
28824
28953
|
init_replay();
|
|
28954
|
+
init_recovery();
|
|
28825
28955
|
}
|
|
28826
28956
|
});
|
|
28827
28957
|
|
|
@@ -28862,6 +28992,104 @@ var init_exportSession = __esm({
|
|
|
28862
28992
|
}
|
|
28863
28993
|
});
|
|
28864
28994
|
|
|
28995
|
+
// packages/core/dist/session/invariants.js
|
|
28996
|
+
function asSeq(value) {
|
|
28997
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
28998
|
+
}
|
|
28999
|
+
function collectEvidenceSeqs(events) {
|
|
29000
|
+
const out = [];
|
|
29001
|
+
const walk2 = (ownerSeq, value) => {
|
|
29002
|
+
if (Array.isArray(value)) {
|
|
29003
|
+
for (const item of value)
|
|
29004
|
+
walk2(ownerSeq, item);
|
|
29005
|
+
return;
|
|
29006
|
+
}
|
|
29007
|
+
if (!value || typeof value !== "object")
|
|
29008
|
+
return;
|
|
29009
|
+
const rec = value;
|
|
29010
|
+
const seq = asSeq(rec.seq);
|
|
29011
|
+
if (seq !== void 0 && ("digest" in rec || "tier" in rec || "ref" in rec)) {
|
|
29012
|
+
out.push({ ownerSeq, refSeq: seq });
|
|
29013
|
+
}
|
|
29014
|
+
for (const v of Object.values(rec))
|
|
29015
|
+
walk2(ownerSeq, v);
|
|
29016
|
+
};
|
|
29017
|
+
for (const e of events)
|
|
29018
|
+
walk2(e.seq, e.data);
|
|
29019
|
+
return out;
|
|
29020
|
+
}
|
|
29021
|
+
function validateSessionTrace(events, mode = "minimal") {
|
|
29022
|
+
const violations = [];
|
|
29023
|
+
let expected = 1;
|
|
29024
|
+
for (const e of events) {
|
|
29025
|
+
if (e.seq !== expected) {
|
|
29026
|
+
violations.push({
|
|
29027
|
+
code: "SEQ_NOT_MONOTONIC",
|
|
29028
|
+
seq: e.seq,
|
|
29029
|
+
message: `expected seq ${expected}, got ${e.seq}`
|
|
29030
|
+
});
|
|
29031
|
+
}
|
|
29032
|
+
expected = e.seq + 1;
|
|
29033
|
+
}
|
|
29034
|
+
const pairs = pairToolCalls(events);
|
|
29035
|
+
const resultCounts = /* @__PURE__ */ new Map();
|
|
29036
|
+
for (const e of events) {
|
|
29037
|
+
if (e.kind !== "tool.result")
|
|
29038
|
+
continue;
|
|
29039
|
+
const callId = typeof e.data.callId === "string" ? e.data.callId : `seq:${e.seq}`;
|
|
29040
|
+
resultCounts.set(callId, (resultCounts.get(callId) ?? 0) + 1);
|
|
29041
|
+
}
|
|
29042
|
+
for (const [callId, n] of resultCounts) {
|
|
29043
|
+
if (n > 1) {
|
|
29044
|
+
violations.push({
|
|
29045
|
+
code: "DUPLICATE_TOOL_RESULT",
|
|
29046
|
+
message: `callId ${callId} has ${n} tool.result events`
|
|
29047
|
+
});
|
|
29048
|
+
}
|
|
29049
|
+
}
|
|
29050
|
+
const interruptedCallIds = new Set(events.filter((e) => e.kind === "tool.interrupted").map((e) => typeof e.data.callId === "string" ? e.data.callId : void 0).filter((id) => Boolean(id)));
|
|
29051
|
+
for (const pair of pairs) {
|
|
29052
|
+
if (pair.result)
|
|
29053
|
+
continue;
|
|
29054
|
+
const callId = typeof pair.call.data.callId === "string" ? pair.call.data.callId : `seq:${pair.call.seq}`;
|
|
29055
|
+
if (interruptedCallIds.has(callId))
|
|
29056
|
+
continue;
|
|
29057
|
+
if (mode === "strict") {
|
|
29058
|
+
violations.push({
|
|
29059
|
+
code: "DANGLING_TOOL_CALL",
|
|
29060
|
+
seq: pair.call.seq,
|
|
29061
|
+
message: `tool.call ${callId} has no tool.result and no tool.interrupted`
|
|
29062
|
+
});
|
|
29063
|
+
}
|
|
29064
|
+
}
|
|
29065
|
+
const knownSeq = new Set(events.map((e) => e.seq));
|
|
29066
|
+
for (const ref of collectEvidenceSeqs(events)) {
|
|
29067
|
+
if (!knownSeq.has(ref.refSeq)) {
|
|
29068
|
+
violations.push({
|
|
29069
|
+
code: "EVIDENCE_SEQ_MISSING",
|
|
29070
|
+
seq: ref.ownerSeq,
|
|
29071
|
+
message: `EvidenceRef.seq ${ref.refSeq} is not an event in this trace`
|
|
29072
|
+
});
|
|
29073
|
+
}
|
|
29074
|
+
}
|
|
29075
|
+
const firstVerification = events.find((e) => e.kind === "verification.run");
|
|
29076
|
+
const firstEnded = events.find((e) => e.kind === "session.ended");
|
|
29077
|
+
if (firstVerification && firstEnded && firstEnded.seq < firstVerification.seq) {
|
|
29078
|
+
violations.push({
|
|
29079
|
+
code: "COMPLETION_BEFORE_VERIFICATION",
|
|
29080
|
+
seq: firstEnded.seq,
|
|
29081
|
+
message: `session.ended seq ${firstEnded.seq} precedes verification.run seq ${firstVerification.seq}`
|
|
29082
|
+
});
|
|
29083
|
+
}
|
|
29084
|
+
return violations;
|
|
29085
|
+
}
|
|
29086
|
+
var init_invariants = __esm({
|
|
29087
|
+
"packages/core/dist/session/invariants.js"() {
|
|
29088
|
+
"use strict";
|
|
29089
|
+
init_modelSurface();
|
|
29090
|
+
}
|
|
29091
|
+
});
|
|
29092
|
+
|
|
28865
29093
|
// packages/core/dist/session/index.js
|
|
28866
29094
|
var init_session = __esm({
|
|
28867
29095
|
"packages/core/dist/session/index.js"() {
|
|
@@ -28874,6 +29102,8 @@ var init_session = __esm({
|
|
|
28874
29102
|
init_store();
|
|
28875
29103
|
init_lineage();
|
|
28876
29104
|
init_exportSession();
|
|
29105
|
+
init_invariants();
|
|
29106
|
+
init_recovery();
|
|
28877
29107
|
}
|
|
28878
29108
|
});
|
|
28879
29109
|
|
|
@@ -29486,6 +29716,72 @@ var init_types9 = __esm({
|
|
|
29486
29716
|
}
|
|
29487
29717
|
});
|
|
29488
29718
|
|
|
29719
|
+
// packages/core/dist/verification/scopeDiscipline.js
|
|
29720
|
+
function normalize(p3) {
|
|
29721
|
+
return p3.replace(/\\/g, "/").replace(/^\.\//, "");
|
|
29722
|
+
}
|
|
29723
|
+
function isGeneratedPath(file2) {
|
|
29724
|
+
const n = normalize(file2);
|
|
29725
|
+
return GENERATED_NAME.test(n) || GENERATED_DIR.test(n);
|
|
29726
|
+
}
|
|
29727
|
+
function parseNameOnlyDiff(stdout) {
|
|
29728
|
+
return stdout.split(/\r?\n/).map((l) => l.trim()).filter(Boolean).map(normalize);
|
|
29729
|
+
}
|
|
29730
|
+
function analyzeScope(input) {
|
|
29731
|
+
const changed = input.changedFiles.map(normalize);
|
|
29732
|
+
if (changed.length === 0) {
|
|
29733
|
+
return {
|
|
29734
|
+
status: "unknown",
|
|
29735
|
+
expected: [],
|
|
29736
|
+
unexpected: [],
|
|
29737
|
+
generated: [],
|
|
29738
|
+
reasons: ["no changed files observed"]
|
|
29739
|
+
};
|
|
29740
|
+
}
|
|
29741
|
+
const expectedSet = new Set((input.expectedFiles ?? []).map(normalize));
|
|
29742
|
+
const generatedExtra = new Set((input.generatedFiles ?? []).map(normalize));
|
|
29743
|
+
const generated = [];
|
|
29744
|
+
const unexpected = [];
|
|
29745
|
+
const expectedHit = [];
|
|
29746
|
+
for (const file2 of changed) {
|
|
29747
|
+
if (generatedExtra.has(file2) || isGeneratedPath(file2)) {
|
|
29748
|
+
generated.push(file2);
|
|
29749
|
+
continue;
|
|
29750
|
+
}
|
|
29751
|
+
if (expectedSet.size === 0) {
|
|
29752
|
+
expectedHit.push(file2);
|
|
29753
|
+
continue;
|
|
29754
|
+
}
|
|
29755
|
+
if (expectedSet.has(file2))
|
|
29756
|
+
expectedHit.push(file2);
|
|
29757
|
+
else
|
|
29758
|
+
unexpected.push(file2);
|
|
29759
|
+
}
|
|
29760
|
+
const reasons = [];
|
|
29761
|
+
if (unexpected.length > 0) {
|
|
29762
|
+
reasons.push(`${unexpected.length} file(s) outside expected scope: ${unexpected.join(", ")}`);
|
|
29763
|
+
}
|
|
29764
|
+
if (generated.length > 0) {
|
|
29765
|
+
reasons.push(`${generated.length} generated/lockfile path(s) ignored for the concern`);
|
|
29766
|
+
}
|
|
29767
|
+
let status = "pass";
|
|
29768
|
+
if (expectedSet.size === 0) {
|
|
29769
|
+
status = "unknown";
|
|
29770
|
+
reasons.push("no expected-files allowlist \u2014 cannot judge scope");
|
|
29771
|
+
} else if (unexpected.length > 0) {
|
|
29772
|
+
status = "concern";
|
|
29773
|
+
}
|
|
29774
|
+
return { status, expected: expectedHit, unexpected, generated, reasons };
|
|
29775
|
+
}
|
|
29776
|
+
var GENERATED_NAME, GENERATED_DIR;
|
|
29777
|
+
var init_scopeDiscipline = __esm({
|
|
29778
|
+
"packages/core/dist/verification/scopeDiscipline.js"() {
|
|
29779
|
+
"use strict";
|
|
29780
|
+
GENERATED_NAME = /(?:^|\/)(?:package-lock\.json|pnpm-lock\.yaml|yarn\.lock|bun\.lockb|Cargo\.lock|go\.sum|poetry\.lock|composer\.lock)$/i;
|
|
29781
|
+
GENERATED_DIR = /(?:^|\/)(?:dist|build|out|coverage|\.next|node_modules)\//;
|
|
29782
|
+
}
|
|
29783
|
+
});
|
|
29784
|
+
|
|
29489
29785
|
// packages/core/dist/verification/engine.js
|
|
29490
29786
|
import { createHash as createHash4 } from "node:crypto";
|
|
29491
29787
|
function defaultSha256(input) {
|
|
@@ -29498,6 +29794,7 @@ var VerificationEngine;
|
|
|
29498
29794
|
var init_engine = __esm({
|
|
29499
29795
|
"packages/core/dist/verification/engine.js"() {
|
|
29500
29796
|
"use strict";
|
|
29797
|
+
init_scopeDiscipline();
|
|
29501
29798
|
VerificationEngine = class {
|
|
29502
29799
|
services;
|
|
29503
29800
|
options;
|
|
@@ -29509,7 +29806,7 @@ var init_engine = __esm({
|
|
|
29509
29806
|
async evaluate(criteria, context = {}) {
|
|
29510
29807
|
const results = [];
|
|
29511
29808
|
for (const criterion of criteria) {
|
|
29512
|
-
results.push(await this.evaluateOne(criterion));
|
|
29809
|
+
results.push(await this.evaluateOne(criterion, context.scope));
|
|
29513
29810
|
}
|
|
29514
29811
|
if (this.options.emit) {
|
|
29515
29812
|
try {
|
|
@@ -29559,7 +29856,7 @@ var init_engine = __esm({
|
|
|
29559
29856
|
return void 0;
|
|
29560
29857
|
}
|
|
29561
29858
|
}
|
|
29562
|
-
async evaluateOne(criterion) {
|
|
29859
|
+
async evaluateOne(criterion, scope) {
|
|
29563
29860
|
const started = this.options.now?.() ?? Date.now();
|
|
29564
29861
|
const base = {
|
|
29565
29862
|
criterionId: criterion.id,
|
|
@@ -29571,6 +29868,15 @@ var init_engine = __esm({
|
|
|
29571
29868
|
...patch,
|
|
29572
29869
|
durationMs: Math.max(0, (this.options.now?.() ?? Date.now()) - started)
|
|
29573
29870
|
});
|
|
29871
|
+
if (criterion.id === "quality.scope-discipline" && scope) {
|
|
29872
|
+
const analysis = analyzeScope(scope);
|
|
29873
|
+
const status = analysis.status === "pass" ? "pass" : "unknown";
|
|
29874
|
+
return done({
|
|
29875
|
+
status,
|
|
29876
|
+
evidence: [],
|
|
29877
|
+
detail: analysis.reasons.join("; ") || analysis.status
|
|
29878
|
+
});
|
|
29879
|
+
}
|
|
29574
29880
|
const check2 = criterion.check;
|
|
29575
29881
|
if (!check2 || check2.kind === "none") {
|
|
29576
29882
|
return done({
|
|
@@ -30184,6 +30490,7 @@ var init_verification2 = __esm({
|
|
|
30184
30490
|
init_criteriaPack_v1();
|
|
30185
30491
|
init_metrics();
|
|
30186
30492
|
init_verifier();
|
|
30493
|
+
init_scopeDiscipline();
|
|
30187
30494
|
}
|
|
30188
30495
|
});
|
|
30189
30496
|
|
|
@@ -30448,6 +30755,7 @@ __export(dist_exports, {
|
|
|
30448
30755
|
WorkspacePathEscapeError: () => WorkspacePathEscapeError,
|
|
30449
30756
|
WorktreeWorkspace: () => WorktreeWorkspace,
|
|
30450
30757
|
ZELARI_CODING_PACK_ID: () => ZELARI_CODING_PACK_ID,
|
|
30758
|
+
analyzeScope: () => analyzeScope,
|
|
30451
30759
|
applyCompletionRetry: () => applyCompletionRetry,
|
|
30452
30760
|
applyDeterministicAutofix: () => applyDeterministicAutofix,
|
|
30453
30761
|
applyImplementationWriteRetry: () => applyImplementationWriteRetry,
|
|
@@ -30478,6 +30786,7 @@ __export(dist_exports, {
|
|
|
30478
30786
|
checkImplementationDelivery: () => checkImplementationDelivery,
|
|
30479
30787
|
checkMemberToolEmissionSets: () => checkMemberToolEmissionSets,
|
|
30480
30788
|
checkMemberToolEmissions: () => checkMemberToolEmissions,
|
|
30789
|
+
classifyInterruptedTools: () => classifyInterruptedTools,
|
|
30481
30790
|
classifyMission: () => classifyMission,
|
|
30482
30791
|
classifyTaskScope: () => classifyTaskScope,
|
|
30483
30792
|
cleanAgentContent: () => cleanAgentContent,
|
|
@@ -30545,6 +30854,7 @@ __export(dist_exports, {
|
|
|
30545
30854
|
hasInteractiveClarification: () => hasInteractiveClarification,
|
|
30546
30855
|
hashToolCall: () => hashToolCall,
|
|
30547
30856
|
hookMatches: () => hookMatches,
|
|
30857
|
+
interruptedEventData: () => interruptedEventData,
|
|
30548
30858
|
isAnswerLeak: () => isAnswerLeak,
|
|
30549
30859
|
isBrainAgentEndEvent: () => isBrainAgentEndEvent,
|
|
30550
30860
|
isBrainAgentStartEvent: () => isBrainAgentStartEvent,
|
|
@@ -30568,6 +30878,7 @@ __export(dist_exports, {
|
|
|
30568
30878
|
isConverged: () => isConverged,
|
|
30569
30879
|
isEventBackedEvidence: () => isEventBackedEvidence,
|
|
30570
30880
|
isExperimentalEnabled: () => isExperimentalEnabled,
|
|
30881
|
+
isGeneratedPath: () => isGeneratedPath,
|
|
30571
30882
|
isModelSurfaceEvent: () => isModelSurfaceEvent,
|
|
30572
30883
|
isReviewerKind: () => isReviewerKind,
|
|
30573
30884
|
isSettled: () => isSettled,
|
|
@@ -30594,6 +30905,7 @@ __export(dist_exports, {
|
|
|
30594
30905
|
parseClarificationRequest: () => parseClarificationRequest,
|
|
30595
30906
|
parseEvidenceTier: () => parseEvidenceTier,
|
|
30596
30907
|
parseMinimaxStyleToolCalls: () => parseMinimaxStyleToolCalls,
|
|
30908
|
+
parseNameOnlyDiff: () => parseNameOnlyDiff,
|
|
30597
30909
|
parsePersonaVerdict: () => parsePersonaVerdict,
|
|
30598
30910
|
parseProjectRootFromWorkspaceContext: () => parseProjectRootFromWorkspaceContext,
|
|
30599
30911
|
parseTextToolCalls: () => parseTextToolCalls,
|
|
@@ -30631,6 +30943,7 @@ __export(dist_exports, {
|
|
|
30631
30943
|
resolveVerifyRetryTool: () => resolveVerifyRetryTool,
|
|
30632
30944
|
restrictImplementationWrites: () => restrictImplementationWrites,
|
|
30633
30945
|
resumeSession: () => resumeSession,
|
|
30946
|
+
retrySafetyForSideEffect: () => retrySafetyForSideEffect,
|
|
30634
30947
|
runChairmanDeliveryLoop: () => runChairmanDeliveryLoop,
|
|
30635
30948
|
runChairmanFixLoop: () => runChairmanFixLoop,
|
|
30636
30949
|
runChairmanMicroGate: () => runChairmanMicroGate,
|
|
@@ -30647,6 +30960,7 @@ __export(dist_exports, {
|
|
|
30647
30960
|
setWorkspaceStubs: () => setWorkspaceStubs,
|
|
30648
30961
|
sha256Hex: () => sha256Hex,
|
|
30649
30962
|
shouldRetryMember: () => shouldRetryMember,
|
|
30963
|
+
sideEffectForTool: () => sideEffectForTool,
|
|
30650
30964
|
slugify: () => slugify2,
|
|
30651
30965
|
snapshotToCompletionEvaluation: () => snapshotToCompletionEvaluation,
|
|
30652
30966
|
specificityFromAssumptions: () => specificityFromAssumptions,
|
|
@@ -30666,6 +30980,7 @@ __export(dist_exports, {
|
|
|
30666
30980
|
utf8Bytes: () => utf8Bytes,
|
|
30667
30981
|
validateCodingSkillRequires: () => validateCodingSkillRequires,
|
|
30668
30982
|
validateGraph: () => validateGraph,
|
|
30983
|
+
validateSessionTrace: () => validateSessionTrace,
|
|
30669
30984
|
verificationCostRatio: () => verificationCostRatio,
|
|
30670
30985
|
verifiedSolveRate: () => verifiedSolveRate,
|
|
30671
30986
|
verifyCitations: () => verifyCitations,
|
|
@@ -32967,9 +33282,25 @@ var init_registry2 = __esm({
|
|
|
32967
33282
|
return typedErr(`Invalid input: ${parsed.error.message}`);
|
|
32968
33283
|
}
|
|
32969
33284
|
const timeoutMs = options.timeoutMs ?? tool.timeoutMs ?? 3e4;
|
|
32970
|
-
const
|
|
33285
|
+
const parentSignal = options.signal;
|
|
33286
|
+
const controller = new AbortController();
|
|
33287
|
+
let timer;
|
|
33288
|
+
let rejectRace;
|
|
33289
|
+
const onParentAbort = () => {
|
|
33290
|
+
if (timer !== void 0)
|
|
33291
|
+
clearTimeout(timer);
|
|
33292
|
+
if (!controller.signal.aborted)
|
|
33293
|
+
controller.abort();
|
|
33294
|
+
rejectRace?.(new Error(`Tool "${name}" aborted`));
|
|
33295
|
+
};
|
|
33296
|
+
if (parentSignal) {
|
|
33297
|
+
if (parentSignal.aborted)
|
|
33298
|
+
onParentAbort();
|
|
33299
|
+
else
|
|
33300
|
+
parentSignal.addEventListener("abort", onParentAbort);
|
|
33301
|
+
}
|
|
32971
33302
|
const ctx = {
|
|
32972
|
-
signal:
|
|
33303
|
+
signal: controller.signal,
|
|
32973
33304
|
cwd: options.cwd ?? process.cwd(),
|
|
32974
33305
|
audit: () => {
|
|
32975
33306
|
},
|
|
@@ -32982,6 +33313,7 @@ var init_registry2 = __esm({
|
|
|
32982
33313
|
cwd: ctx.cwd
|
|
32983
33314
|
});
|
|
32984
33315
|
if (!pre.ok) {
|
|
33316
|
+
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
32985
33317
|
return typedErr(`[hook:${pre.hookName ?? "unknown"}] ${pre.reason ?? "denied"}`);
|
|
32986
33318
|
}
|
|
32987
33319
|
} catch (hookErr) {
|
|
@@ -32991,11 +33323,16 @@ var init_registry2 = __esm({
|
|
|
32991
33323
|
const result = await Promise.race([
|
|
32992
33324
|
tool.execute(parsed.data, ctx),
|
|
32993
33325
|
new Promise((_, reject) => {
|
|
32994
|
-
|
|
32995
|
-
|
|
32996
|
-
|
|
32997
|
-
|
|
32998
|
-
}
|
|
33326
|
+
rejectRace = reject;
|
|
33327
|
+
if (parentSignal?.aborted) {
|
|
33328
|
+
onParentAbort();
|
|
33329
|
+
return;
|
|
33330
|
+
}
|
|
33331
|
+
timer = setTimeout(() => {
|
|
33332
|
+
if (!controller.signal.aborted)
|
|
33333
|
+
controller.abort();
|
|
33334
|
+
reject(new Error(`Tool "${name}" timed out after ${timeoutMs}ms`));
|
|
33335
|
+
}, timeoutMs);
|
|
32999
33336
|
})
|
|
33000
33337
|
]);
|
|
33001
33338
|
if (result.ok) {
|
|
@@ -33030,6 +33367,11 @@ var init_registry2 = __esm({
|
|
|
33030
33367
|
} catch (err) {
|
|
33031
33368
|
const error51 = err instanceof Error ? err.message : String(err);
|
|
33032
33369
|
return typedErr(error51);
|
|
33370
|
+
} finally {
|
|
33371
|
+
rejectRace = void 0;
|
|
33372
|
+
if (timer !== void 0)
|
|
33373
|
+
clearTimeout(timer);
|
|
33374
|
+
parentSignal?.removeEventListener("abort", onParentAbort);
|
|
33033
33375
|
}
|
|
33034
33376
|
}
|
|
33035
33377
|
/** Return all tool definitions in OpenAI function-calling format (memoized). */
|
|
@@ -33829,7 +34171,7 @@ var init_candidateRegistry = __esm({
|
|
|
33829
34171
|
});
|
|
33830
34172
|
|
|
33831
34173
|
// src/cli/kraken/verifyReport.ts
|
|
33832
|
-
function
|
|
34174
|
+
function normalize2(text) {
|
|
33833
34175
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
33834
34176
|
}
|
|
33835
34177
|
function extractVerifyReportBlocks(raw) {
|
|
@@ -33858,11 +34200,11 @@ function extractVerifyReportBlocks(raw) {
|
|
|
33858
34200
|
function parseVerifyReport(raw, requiredChecks) {
|
|
33859
34201
|
const byCriterion = /* @__PURE__ */ new Map();
|
|
33860
34202
|
for (const block of extractVerifyReportBlocks(raw)) {
|
|
33861
|
-
byCriterion.set(
|
|
34203
|
+
byCriterion.set(normalize2(block.check), block);
|
|
33862
34204
|
}
|
|
33863
34205
|
const keys = [...byCriterion.keys()];
|
|
33864
34206
|
return requiredChecks.map((check2) => {
|
|
33865
|
-
const norm =
|
|
34207
|
+
const norm = normalize2(check2);
|
|
33866
34208
|
let block = byCriterion.get(norm) ?? null;
|
|
33867
34209
|
if (!block) {
|
|
33868
34210
|
for (const key of keys) {
|
|
@@ -33901,18 +34243,18 @@ var init_verifyReport = __esm({
|
|
|
33901
34243
|
});
|
|
33902
34244
|
|
|
33903
34245
|
// src/cli/kraken/completionGate.ts
|
|
33904
|
-
function
|
|
34246
|
+
function normalize3(text) {
|
|
33905
34247
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
33906
34248
|
}
|
|
33907
34249
|
function classifyKrakenChecks(requiredChecks, results) {
|
|
33908
34250
|
const byCriterion = /* @__PURE__ */ new Map();
|
|
33909
34251
|
for (const result of results ?? []) {
|
|
33910
|
-
byCriterion.set(
|
|
34252
|
+
byCriterion.set(normalize3(result.check), result);
|
|
33911
34253
|
}
|
|
33912
34254
|
const keys = [...byCriterion.keys()];
|
|
33913
34255
|
const out = { passed: [], failed: [], unknown: [] };
|
|
33914
34256
|
for (const check2 of requiredChecks) {
|
|
33915
|
-
const norm =
|
|
34257
|
+
const norm = normalize3(check2);
|
|
33916
34258
|
let result = byCriterion.get(norm) ?? null;
|
|
33917
34259
|
if (!result) {
|
|
33918
34260
|
for (const key of keys) {
|
|
@@ -34137,69 +34479,79 @@ async function runSubAgent(harness, opts = {}) {
|
|
|
34137
34479
|
let usage;
|
|
34138
34480
|
const pendingTools = /* @__PURE__ */ new Map();
|
|
34139
34481
|
const toolTrace = [];
|
|
34140
|
-
|
|
34141
|
-
|
|
34142
|
-
|
|
34143
|
-
|
|
34144
|
-
|
|
34145
|
-
|
|
34146
|
-
|
|
34147
|
-
|
|
34148
|
-
|
|
34149
|
-
|
|
34150
|
-
|
|
34151
|
-
|
|
34152
|
-
|
|
34153
|
-
|
|
34154
|
-
|
|
34155
|
-
|
|
34156
|
-
tool: started?.tool ?? "unknown",
|
|
34157
|
-
callId: ev.toolCallId,
|
|
34158
|
-
ok: !ev.isError,
|
|
34159
|
-
...started?.command ? { command: started.command } : {},
|
|
34160
|
-
output: String(ev.result ?? "").slice(0, TOOL_TRACE_OUTPUT_MAX),
|
|
34161
|
-
durationMs: ev.durationMs,
|
|
34162
|
-
endedAt: Date.now()
|
|
34163
|
-
});
|
|
34164
|
-
if (toolTrace.length > TOOL_TRACE_RING) {
|
|
34165
|
-
toolTrace.splice(0, toolTrace.length - TOOL_TRACE_RING);
|
|
34482
|
+
const onAbort = () => harness.cancel?.();
|
|
34483
|
+
if (signal?.aborted) {
|
|
34484
|
+
onAbort();
|
|
34485
|
+
return { result: "", aborted: true };
|
|
34486
|
+
}
|
|
34487
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
34488
|
+
try {
|
|
34489
|
+
for await (const ev of harness.run()) {
|
|
34490
|
+
if (signal?.aborted) {
|
|
34491
|
+
onAbort();
|
|
34492
|
+
return {
|
|
34493
|
+
result: (lastCompleted || current).trim(),
|
|
34494
|
+
...error51 ? { error: error51 } : {},
|
|
34495
|
+
aborted: true,
|
|
34496
|
+
...toolTrace.length > 0 ? { toolTrace } : {}
|
|
34497
|
+
};
|
|
34166
34498
|
}
|
|
34167
|
-
|
|
34168
|
-
|
|
34169
|
-
|
|
34170
|
-
|
|
34171
|
-
|
|
34172
|
-
|
|
34173
|
-
|
|
34174
|
-
|
|
34175
|
-
|
|
34176
|
-
|
|
34177
|
-
|
|
34178
|
-
|
|
34179
|
-
|
|
34180
|
-
|
|
34181
|
-
|
|
34182
|
-
|
|
34183
|
-
cachedPromptTokens: (usage.cachedPromptTokens ?? 0) + (ev.usage.cachedPromptTokens ?? 0)
|
|
34184
|
-
} : {}
|
|
34185
|
-
} : ev.usage;
|
|
34499
|
+
if (ev.type === "tool_execution_start") {
|
|
34500
|
+
pendingTools.set(ev.toolCallId, { tool: ev.toolName, command: toolCommandHint(ev.args) });
|
|
34501
|
+
} else if (ev.type === "tool_execution_end") {
|
|
34502
|
+
const started = pendingTools.get(ev.toolCallId);
|
|
34503
|
+
pendingTools.delete(ev.toolCallId);
|
|
34504
|
+
toolTrace.push({
|
|
34505
|
+
tool: started?.tool ?? "unknown",
|
|
34506
|
+
callId: ev.toolCallId,
|
|
34507
|
+
ok: !ev.isError,
|
|
34508
|
+
...started?.command ? { command: started.command } : {},
|
|
34509
|
+
output: String(ev.result ?? "").slice(0, TOOL_TRACE_OUTPUT_MAX),
|
|
34510
|
+
durationMs: ev.durationMs,
|
|
34511
|
+
endedAt: Date.now()
|
|
34512
|
+
});
|
|
34513
|
+
if (toolTrace.length > TOOL_TRACE_RING) {
|
|
34514
|
+
toolTrace.splice(0, toolTrace.length - TOOL_TRACE_RING);
|
|
34186
34515
|
}
|
|
34187
|
-
|
|
34188
|
-
|
|
34189
|
-
|
|
34190
|
-
|
|
34191
|
-
|
|
34192
|
-
|
|
34193
|
-
|
|
34516
|
+
}
|
|
34517
|
+
switch (ev.type) {
|
|
34518
|
+
case "message_start":
|
|
34519
|
+
current = "";
|
|
34520
|
+
break;
|
|
34521
|
+
case "message_delta":
|
|
34522
|
+
current += ev.delta;
|
|
34523
|
+
break;
|
|
34524
|
+
case "message_end":
|
|
34525
|
+
if (current.trim()) lastCompleted = current;
|
|
34526
|
+
if (ev.usage) {
|
|
34527
|
+
usage = usage ? {
|
|
34528
|
+
promptTokens: usage.promptTokens + ev.usage.promptTokens,
|
|
34529
|
+
completionTokens: usage.completionTokens + ev.usage.completionTokens,
|
|
34530
|
+
totalTokens: usage.totalTokens + ev.usage.totalTokens,
|
|
34531
|
+
...(usage.cachedPromptTokens ?? 0) + (ev.usage.cachedPromptTokens ?? 0) > 0 ? {
|
|
34532
|
+
cachedPromptTokens: (usage.cachedPromptTokens ?? 0) + (ev.usage.cachedPromptTokens ?? 0)
|
|
34533
|
+
} : {}
|
|
34534
|
+
} : ev.usage;
|
|
34535
|
+
}
|
|
34536
|
+
current = "";
|
|
34537
|
+
break;
|
|
34538
|
+
case "error":
|
|
34539
|
+
error51 = ev.message;
|
|
34540
|
+
break;
|
|
34541
|
+
default:
|
|
34542
|
+
break;
|
|
34543
|
+
}
|
|
34194
34544
|
}
|
|
34545
|
+
const result = (lastCompleted || current).trim();
|
|
34546
|
+
return {
|
|
34547
|
+
result,
|
|
34548
|
+
...error51 ? { error: error51 } : {},
|
|
34549
|
+
...usage ? { usage } : {},
|
|
34550
|
+
...toolTrace.length > 0 ? { toolTrace } : {}
|
|
34551
|
+
};
|
|
34552
|
+
} finally {
|
|
34553
|
+
signal?.removeEventListener("abort", onAbort);
|
|
34195
34554
|
}
|
|
34196
|
-
const result = (lastCompleted || current).trim();
|
|
34197
|
-
return {
|
|
34198
|
-
result,
|
|
34199
|
-
...error51 ? { error: error51 } : {},
|
|
34200
|
-
...usage ? { usage } : {},
|
|
34201
|
-
...toolTrace.length > 0 ? { toolTrace } : {}
|
|
34202
|
-
};
|
|
34203
34555
|
}
|
|
34204
34556
|
async function runTentacle(opts) {
|
|
34205
34557
|
const { deps, args, agent, thoroughness, parentCwd, sessionId: sessionId2 } = opts;
|
|
@@ -34429,7 +34781,7 @@ function createTaskTool(deps, policy = {}) {
|
|
|
34429
34781
|
description: "Delegate a focused sub-task to an isolated sub-agent with its own context; returns only a concise conclusion (keeps parent context lean).\n- agent=explore (default): read-only research/search\n- agent=general: can edit files for one bounded unit of work\n- agent=verify: read + bash to run tests/checks\nProvide a fully self-contained `prompt` (sub-agent cannot see this conversation). Optional scope[] + acceptance[] contracts. After general, follow up with verify." + (restricted ? `
|
|
34430
34782
|
RESTRICTED in this mode: only agent=${allowedAgents.join("|")} is allowed.` : ""),
|
|
34431
34783
|
permissions: ["read", "network", "write", "execute"],
|
|
34432
|
-
timeoutMs:
|
|
34784
|
+
timeoutMs: TASK_TOOL_TIMEOUT_MS,
|
|
34433
34785
|
inputSchema: inputSchema2,
|
|
34434
34786
|
execute: async (args, ctx) => {
|
|
34435
34787
|
const agent = args.agent ?? "explore";
|
|
@@ -34532,7 +34884,7 @@ ${res.result}${res.footer}`,
|
|
|
34532
34884
|
}
|
|
34533
34885
|
};
|
|
34534
34886
|
}
|
|
34535
|
-
var EXPLORE_PROMPT, GENERAL_PROMPT, VERIFY_PROMPT, TaskArgsSchema, TaskPurposeSchema, TaskArgsWithPurposeSchema, TOOL_TRACE_RING, TOOL_TRACE_OUTPUT_MAX;
|
|
34887
|
+
var TASK_TOOL_TIMEOUT_MS, EXPLORE_PROMPT, GENERAL_PROMPT, VERIFY_PROMPT, TaskArgsSchema, TaskPurposeSchema, TaskArgsWithPurposeSchema, TOOL_TRACE_RING, TOOL_TRACE_OUTPUT_MAX;
|
|
34536
34888
|
var init_taskTool = __esm({
|
|
34537
34889
|
"src/cli/tools/taskTool.ts"() {
|
|
34538
34890
|
"use strict";
|
|
@@ -34544,6 +34896,7 @@ var init_taskTool = __esm({
|
|
|
34544
34896
|
init_candidateRegistry();
|
|
34545
34897
|
init_verifyReport();
|
|
34546
34898
|
init_metrics3();
|
|
34899
|
+
TASK_TOOL_TIMEOUT_MS = 9e5;
|
|
34547
34900
|
EXPLORE_PROMPT = [
|
|
34548
34901
|
"You are a focused EXPLORE tentacle of Kraken (parent super-agent).",
|
|
34549
34902
|
"READ-ONLY tools only (read, list, grep, fetch). No edits, no shell.",
|
|
@@ -39077,7 +39430,7 @@ import path38 from "node:path";
|
|
|
39077
39430
|
function trustStorePath() {
|
|
39078
39431
|
return _overrideStorePath ?? path38.join(homedir8(), ".zelari-code", "trust.json");
|
|
39079
39432
|
}
|
|
39080
|
-
function
|
|
39433
|
+
function normalize4(p3) {
|
|
39081
39434
|
const resolved = path38.resolve(p3);
|
|
39082
39435
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
39083
39436
|
}
|
|
@@ -39114,14 +39467,14 @@ function isFolderTrusted(folderPath) {
|
|
|
39114
39467
|
const env = envTrustedFolder();
|
|
39115
39468
|
if (env === "all") return true;
|
|
39116
39469
|
if (env === "none") return false;
|
|
39117
|
-
if (env) return
|
|
39118
|
-
const target =
|
|
39119
|
-
return readStore3().folders.some((f) =>
|
|
39470
|
+
if (env) return normalize4(env) === normalize4(folderPath);
|
|
39471
|
+
const target = normalize4(folderPath);
|
|
39472
|
+
return readStore3().folders.some((f) => normalize4(f.path) === target);
|
|
39120
39473
|
}
|
|
39121
39474
|
function trustFolder(folderPath) {
|
|
39122
39475
|
const store6 = readStore3();
|
|
39123
39476
|
const normalized = path38.resolve(folderPath);
|
|
39124
|
-
if (!store6.folders.some((f) =>
|
|
39477
|
+
if (!store6.folders.some((f) => normalize4(f.path) === normalize4(normalized))) {
|
|
39125
39478
|
store6.folders.push({ path: normalized, trustedAt: (/* @__PURE__ */ new Date()).toISOString() });
|
|
39126
39479
|
writeStore3(store6);
|
|
39127
39480
|
}
|
|
@@ -39129,9 +39482,9 @@ function trustFolder(folderPath) {
|
|
|
39129
39482
|
}
|
|
39130
39483
|
function untrustFolder(folderPath) {
|
|
39131
39484
|
const store6 = readStore3();
|
|
39132
|
-
const target =
|
|
39485
|
+
const target = normalize4(folderPath);
|
|
39133
39486
|
const before = store6.folders.length;
|
|
39134
|
-
store6.folders = store6.folders.filter((f) =>
|
|
39487
|
+
store6.folders = store6.folders.filter((f) => normalize4(f.path) !== target);
|
|
39135
39488
|
if (store6.folders.length === before) return { ok: true, removed: false };
|
|
39136
39489
|
writeStore3(store6);
|
|
39137
39490
|
return { ok: true, removed: true };
|
|
@@ -47538,7 +47891,7 @@ var init_executor = __esm({
|
|
|
47538
47891
|
DEFAULT_MAX_REVIEW_ROUNDS = 1;
|
|
47539
47892
|
DEFAULT_GRAPH_TIMEOUT_MS = 0;
|
|
47540
47893
|
DEFAULT_NODE_TIMEOUT_MS = 3e5;
|
|
47541
|
-
DEFAULT_WRITER_NODE_TIMEOUT_MS =
|
|
47894
|
+
DEFAULT_WRITER_NODE_TIMEOUT_MS = TASK_TOOL_TIMEOUT_MS;
|
|
47542
47895
|
DEFAULT_CANCEL_GRACE_MS = 3e4;
|
|
47543
47896
|
MAX_UPSTREAM_CHARS_PER_DEP = 2800;
|
|
47544
47897
|
MAX_UPSTREAM_CHARS_TOTAL = 8e3;
|
|
@@ -55543,11 +55896,11 @@ function criterionId(check2, index) {
|
|
|
55543
55896
|
const slug = check2.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
55544
55897
|
return `check-${index + 1}-${slug || "criterion"}`;
|
|
55545
55898
|
}
|
|
55546
|
-
function
|
|
55899
|
+
function normalize5(text) {
|
|
55547
55900
|
return text.toLowerCase().replace(/\s+/g, " ").trim();
|
|
55548
55901
|
}
|
|
55549
55902
|
function matchResult(check2, byNormalized) {
|
|
55550
|
-
const norm =
|
|
55903
|
+
const norm = normalize5(check2);
|
|
55551
55904
|
const direct = byNormalized.get(norm);
|
|
55552
55905
|
if (direct) return direct;
|
|
55553
55906
|
for (const key of byNormalized.keys()) {
|
|
@@ -55559,7 +55912,7 @@ function matchResult(check2, byNormalized) {
|
|
|
55559
55912
|
}
|
|
55560
55913
|
function krakenResultsToContract(requiredChecks, results, now = Date.now()) {
|
|
55561
55914
|
const byNormalized = /* @__PURE__ */ new Map();
|
|
55562
|
-
for (const r of results ?? []) byNormalized.set(
|
|
55915
|
+
for (const r of results ?? []) byNormalized.set(normalize5(r.check), r);
|
|
55563
55916
|
const criteria = [];
|
|
55564
55917
|
const verifications = [];
|
|
55565
55918
|
requiredChecks.forEach((check2, i) => {
|
|
@@ -55595,16 +55948,16 @@ function sha256Hex2(input) {
|
|
|
55595
55948
|
return createHash10("sha256").update(input).digest("hex");
|
|
55596
55949
|
}
|
|
55597
55950
|
function matchNoteToToolTrace(note, trace) {
|
|
55598
|
-
const n =
|
|
55951
|
+
const n = normalize5(note);
|
|
55599
55952
|
if (!n) return null;
|
|
55600
55953
|
for (let i = trace.length - 1; i >= 0; i--) {
|
|
55601
55954
|
const t = trace[i];
|
|
55602
|
-
const cmd = t.command ?
|
|
55955
|
+
const cmd = t.command ? normalize5(t.command) : "";
|
|
55603
55956
|
if (cmd.length >= 4 && (n.includes(cmd) || cmd.includes(n))) return t;
|
|
55604
55957
|
}
|
|
55605
55958
|
for (let i = trace.length - 1; i >= 0; i--) {
|
|
55606
55959
|
const t = trace[i];
|
|
55607
|
-
const out =
|
|
55960
|
+
const out = normalize5(t.output);
|
|
55608
55961
|
if (!out) continue;
|
|
55609
55962
|
if (n.length >= 8 && out.includes(n)) return t;
|
|
55610
55963
|
const fragments = n.match(/\S*\d[\d.,/%]*\S*/g) ?? [];
|