@skein-code/cli 0.3.15 → 0.3.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cli.js +361 -131
- package/dist/cli.js.map +1 -1
- package/docs/ARCHITECTURE.md +10 -0
- package/docs/NEXT_STEPS.md +14 -4
- package/package.json +4 -1
package/dist/cli.js
CHANGED
|
@@ -220,7 +220,7 @@ function isSqliteBusy(error) {
|
|
|
220
220
|
// package.json
|
|
221
221
|
var package_default = {
|
|
222
222
|
name: "@skein-code/cli",
|
|
223
|
-
version: "0.3.
|
|
223
|
+
version: "0.3.16",
|
|
224
224
|
description: "A context-first, model-agnostic coding agent with an auditable terminal workspace.",
|
|
225
225
|
type: "module",
|
|
226
226
|
license: "MIT",
|
|
@@ -236,6 +236,9 @@ var package_default = {
|
|
|
236
236
|
},
|
|
237
237
|
skein: {
|
|
238
238
|
releaseNotes: [
|
|
239
|
+
"Duplication warnings now aggregate into the single completion receipt without changing verified status",
|
|
240
|
+
"Exact match ids support bounded, reason-coded suppression with audit and credential/code-block safeguards",
|
|
241
|
+
"Duplication audit tools are disclosed only when active warnings exist and repaired paths clear stale matches",
|
|
239
242
|
"Warning-only TS/JS duplication audit compares new functions with the pre-write index generation",
|
|
240
243
|
"Deterministic Type-1/2 and Type-3 receipts retain only hashes, locations, scores, and bounded counts",
|
|
241
244
|
"Ordinary edits, renames, moves, deletions, small functions, tests, generated paths, and failed writes stay quiet",
|
|
@@ -5673,6 +5676,15 @@ var reuseReceiptSchema = z5.object({
|
|
|
5673
5676
|
status: z5.enum(["warning", "skipped", "unresolved"]),
|
|
5674
5677
|
warningOnly: z5.literal(true)
|
|
5675
5678
|
}).strict();
|
|
5679
|
+
var duplicationMatchSchema = z5.object({
|
|
5680
|
+
matchId: z5.string().regex(/^[a-f0-9]{24}$/u).optional(),
|
|
5681
|
+
changedPath: z5.string(),
|
|
5682
|
+
changedSymbol: z5.string(),
|
|
5683
|
+
candidatePath: z5.string(),
|
|
5684
|
+
candidateSymbol: z5.string(),
|
|
5685
|
+
kind: z5.enum(["type-1-or-2", "type-3"]),
|
|
5686
|
+
similarity: z5.number().min(0).max(1)
|
|
5687
|
+
}).strict();
|
|
5676
5688
|
var duplicationAuditSchema = z5.object({
|
|
5677
5689
|
baselineGeneration: z5.string().min(1),
|
|
5678
5690
|
changeSequence: z5.number().int().nonnegative(),
|
|
@@ -5680,16 +5692,16 @@ var duplicationAuditSchema = z5.object({
|
|
|
5680
5692
|
warningOnly: z5.literal(true),
|
|
5681
5693
|
checkedFunctions: z5.number().int().nonnegative(),
|
|
5682
5694
|
skippedSmallFunctions: z5.number().int().nonnegative(),
|
|
5683
|
-
matches: z5.array(
|
|
5684
|
-
changedPath: z5.string(),
|
|
5685
|
-
changedSymbol: z5.string(),
|
|
5686
|
-
candidatePath: z5.string(),
|
|
5687
|
-
candidateSymbol: z5.string(),
|
|
5688
|
-
kind: z5.enum(["type-1-or-2", "type-3"]),
|
|
5689
|
-
similarity: z5.number().min(0).max(1)
|
|
5690
|
-
}).strict()).max(8),
|
|
5695
|
+
matches: z5.array(duplicationMatchSchema).max(8),
|
|
5691
5696
|
rationale: z5.string().max(500)
|
|
5692
5697
|
}).strict();
|
|
5698
|
+
var duplicationSuppressionSchema = z5.object({
|
|
5699
|
+
matchId: z5.string().regex(/^[a-f0-9]{24}$/u),
|
|
5700
|
+
reasonCode: z5.enum(["separate-boundary", "protocol-required", "generated-contract", "false-positive", "other"]),
|
|
5701
|
+
reason: z5.string().min(12).max(240),
|
|
5702
|
+
createdAt: z5.string().datetime(),
|
|
5703
|
+
toolCallId: z5.string().min(1).max(512)
|
|
5704
|
+
}).strict();
|
|
5693
5705
|
var auditMetadataSchema = z5.record(z5.string(), z5.unknown()).superRefine((metadata, ctx) => {
|
|
5694
5706
|
const receipt = metadata.reuseReceipt;
|
|
5695
5707
|
if (receipt !== void 0 && !reuseReceiptSchema.safeParse(receipt).success) {
|
|
@@ -5699,6 +5711,14 @@ var auditMetadataSchema = z5.record(z5.string(), z5.unknown()).superRefine((meta
|
|
|
5699
5711
|
if (duplication !== void 0 && !duplicationAuditSchema.safeParse(duplication).success) {
|
|
5700
5712
|
ctx.addIssue({ code: "custom", message: "Invalid duplication audit receipt" });
|
|
5701
5713
|
}
|
|
5714
|
+
const suppression = metadata.duplicationSuppression;
|
|
5715
|
+
if (suppression !== void 0 && !duplicationSuppressionSchema.safeParse(suppression).success) {
|
|
5716
|
+
ctx.addIssue({ code: "custom", message: "Invalid duplication suppression receipt" });
|
|
5717
|
+
}
|
|
5718
|
+
const activeMatches = metadata.activeDuplicationMatches;
|
|
5719
|
+
if (activeMatches !== void 0 && !z5.array(z5.string().regex(/^[a-f0-9]{24}$/u)).max(8).safeParse(activeMatches).success) {
|
|
5720
|
+
ctx.addIssue({ code: "custom", message: "Invalid active duplication matches" });
|
|
5721
|
+
}
|
|
5702
5722
|
});
|
|
5703
5723
|
var auditSchema = z5.object({
|
|
5704
5724
|
id: z5.string(),
|
|
@@ -5738,6 +5758,16 @@ var lastRunSchema = z5.object({
|
|
|
5738
5758
|
checks: z5.array(verificationEvidenceSchema),
|
|
5739
5759
|
detail: z5.string(),
|
|
5740
5760
|
mutationTracking: z5.enum(["complete", "unknown"]).optional(),
|
|
5761
|
+
duplication: z5.object({
|
|
5762
|
+
enforcement: z5.literal("warning"),
|
|
5763
|
+
status: z5.enum(["clear", "warning", "unresolved", "suppressed"]),
|
|
5764
|
+
warningCount: z5.number().int().nonnegative(),
|
|
5765
|
+
unresolvedCount: z5.number().int().nonnegative(),
|
|
5766
|
+
suppressedCount: z5.number().int().nonnegative(),
|
|
5767
|
+
matches: z5.array(duplicationMatchSchema.extend({
|
|
5768
|
+
matchId: z5.string().regex(/^[a-f0-9]{24}$/u)
|
|
5769
|
+
})).max(8)
|
|
5770
|
+
}).strict().optional(),
|
|
5741
5771
|
acceptance: z5.object({
|
|
5742
5772
|
state: z5.enum(["draft", "active", "satisfied", "blocked"]),
|
|
5743
5773
|
total: z5.number().int().nonnegative(),
|
|
@@ -5803,6 +5833,7 @@ var sessionSchema = z5.object({
|
|
|
5803
5833
|
contextSources: z5.array(contextSourceSchema).max(64).optional(),
|
|
5804
5834
|
toolArtifacts: z5.array(toolArtifactSchema).max(200).optional(),
|
|
5805
5835
|
taskContract: taskContractSchema.optional(),
|
|
5836
|
+
duplicationSuppressions: z5.array(duplicationSuppressionSchema).max(64).optional(),
|
|
5806
5837
|
lastRun: lastRunSchema.optional(),
|
|
5807
5838
|
usage: z5.object({
|
|
5808
5839
|
inputTokens: z5.number().nonnegative(),
|
|
@@ -8332,7 +8363,7 @@ function captureVerification(call, result, changeSequence, configuredCommands) {
|
|
|
8332
8363
|
commandKey: createHash11("sha256").update(normalized).digest("hex")
|
|
8333
8364
|
};
|
|
8334
8365
|
}
|
|
8335
|
-
function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutationTracking = "complete", taskContract, audit = []) {
|
|
8366
|
+
function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutationTracking = "complete", taskContract, audit = [], duplication) {
|
|
8336
8367
|
const files = [...new Set(changedFiles)];
|
|
8337
8368
|
const acceptance = taskContract ? buildAcceptance(taskContract, audit, evidence, currentChangeSequence) : void 0;
|
|
8338
8369
|
if (mutationTracking === "unknown") {
|
|
@@ -8342,6 +8373,7 @@ function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutat
|
|
|
8342
8373
|
checks: [],
|
|
8343
8374
|
detail: files.length ? `Workspace changes were observed, but a dynamic shell command prevented complete mutation tracking for ${fileCount(files.length)}.` : "A dynamic shell command may have changed workspace files, but reliable mutation tracking was unavailable.",
|
|
8344
8375
|
mutationTracking,
|
|
8376
|
+
...duplication ? { duplication } : {},
|
|
8345
8377
|
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "unverified") } : {}
|
|
8346
8378
|
};
|
|
8347
8379
|
}
|
|
@@ -8352,7 +8384,8 @@ function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutat
|
|
|
8352
8384
|
changedFiles: [],
|
|
8353
8385
|
checks: [],
|
|
8354
8386
|
detail: acceptanceDetail(acceptance),
|
|
8355
|
-
acceptance: acceptanceForCompletion(acceptance, "unverified")
|
|
8387
|
+
acceptance: acceptanceForCompletion(acceptance, "unverified"),
|
|
8388
|
+
...duplication ? { duplication } : {}
|
|
8356
8389
|
};
|
|
8357
8390
|
}
|
|
8358
8391
|
return {
|
|
@@ -8360,7 +8393,8 @@ function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutat
|
|
|
8360
8393
|
changedFiles: [],
|
|
8361
8394
|
checks: [],
|
|
8362
8395
|
detail: "No workspace files changed in this run.",
|
|
8363
|
-
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "no_changes") } : {}
|
|
8396
|
+
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "no_changes") } : {},
|
|
8397
|
+
...duplication ? { duplication } : {}
|
|
8364
8398
|
};
|
|
8365
8399
|
}
|
|
8366
8400
|
const latestByCommand = /* @__PURE__ */ new Map();
|
|
@@ -8376,7 +8410,8 @@ function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutat
|
|
|
8376
8410
|
changedFiles: files,
|
|
8377
8411
|
checks,
|
|
8378
8412
|
detail: `No successful verification was recorded after the last change to ${fileCount(files.length)}.`,
|
|
8379
|
-
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "unverified") } : {}
|
|
8413
|
+
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "unverified") } : {},
|
|
8414
|
+
...duplication ? { duplication } : {}
|
|
8380
8415
|
};
|
|
8381
8416
|
}
|
|
8382
8417
|
const failures = checks.filter((check) => !check.ok);
|
|
@@ -8386,7 +8421,8 @@ function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutat
|
|
|
8386
8421
|
changedFiles: files,
|
|
8387
8422
|
checks,
|
|
8388
8423
|
detail: `${failures.length} of ${checks.length} current verification ${checks.length === 1 ? "check" : "checks"} failed.`,
|
|
8389
|
-
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "verification_failed") } : {}
|
|
8424
|
+
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "verification_failed") } : {},
|
|
8425
|
+
...duplication ? { duplication } : {}
|
|
8390
8426
|
};
|
|
8391
8427
|
}
|
|
8392
8428
|
if (acceptance && acceptanceUnresolved(acceptance)) {
|
|
@@ -8395,7 +8431,8 @@ function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutat
|
|
|
8395
8431
|
changedFiles: files,
|
|
8396
8432
|
checks,
|
|
8397
8433
|
detail: acceptanceDetail(acceptance),
|
|
8398
|
-
acceptance: acceptanceForCompletion(acceptance, "unverified")
|
|
8434
|
+
acceptance: acceptanceForCompletion(acceptance, "unverified"),
|
|
8435
|
+
...duplication ? { duplication } : {}
|
|
8399
8436
|
};
|
|
8400
8437
|
}
|
|
8401
8438
|
return {
|
|
@@ -8403,7 +8440,8 @@ function buildRunCompletion(changedFiles, evidence, currentChangeSequence, mutat
|
|
|
8403
8440
|
changedFiles: files,
|
|
8404
8441
|
checks,
|
|
8405
8442
|
detail: `${checks.length} current verification ${checks.length === 1 ? "check" : "checks"} passed for ${fileCount(files.length)}.`,
|
|
8406
|
-
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "verified") } : {}
|
|
8443
|
+
...acceptance ? { acceptance: acceptanceForCompletion(acceptance, "verified") } : {},
|
|
8444
|
+
...duplication ? { duplication } : {}
|
|
8407
8445
|
};
|
|
8408
8446
|
}
|
|
8409
8447
|
function completionRecoveryDirective(completion) {
|
|
@@ -8815,6 +8853,139 @@ function render(memory) {
|
|
|
8815
8853
|
].join("\n");
|
|
8816
8854
|
}
|
|
8817
8855
|
|
|
8856
|
+
// src/tools/duplication.ts
|
|
8857
|
+
import { z as z17 } from "zod";
|
|
8858
|
+
|
|
8859
|
+
// src/agent/duplication-state.ts
|
|
8860
|
+
function buildDuplicationCompletion(audit, suppressions = [], runStartedAt) {
|
|
8861
|
+
const active = /* @__PURE__ */ new Map();
|
|
8862
|
+
const unresolved2 = /* @__PURE__ */ new Map();
|
|
8863
|
+
let sawCurrentReceipt = false;
|
|
8864
|
+
for (const event of audit) {
|
|
8865
|
+
if (runStartedAt && event.createdAt < runStartedAt) continue;
|
|
8866
|
+
const receipt = duplicationReceipt(event.metadata?.duplicationAudit);
|
|
8867
|
+
if (!receipt) continue;
|
|
8868
|
+
if (receipt.status === "clear" || receipt.status === "unresolved" || receipt.matches.some((match) => typeof match.matchId === "string")) sawCurrentReceipt = true;
|
|
8869
|
+
const changedPaths2 = changedPathsFor(event, receipt);
|
|
8870
|
+
for (const path of changedPaths2) {
|
|
8871
|
+
for (const [id, match] of active) if (match.changedPath === path) active.delete(id);
|
|
8872
|
+
unresolved2.delete(path);
|
|
8873
|
+
}
|
|
8874
|
+
if (receipt.status === "unresolved") {
|
|
8875
|
+
for (const path of changedPaths2) unresolved2.set(path, receipt.changeSequence);
|
|
8876
|
+
}
|
|
8877
|
+
for (const match of receipt.matches) {
|
|
8878
|
+
if (typeof match.matchId === "string") {
|
|
8879
|
+
active.set(match.matchId, match);
|
|
8880
|
+
}
|
|
8881
|
+
}
|
|
8882
|
+
}
|
|
8883
|
+
if (!active.size && !unresolved2.size && !sawCurrentReceipt) return void 0;
|
|
8884
|
+
const activeIds = new Set(active.keys());
|
|
8885
|
+
const suppressedIds = new Set(suppressions.filter((item) => activeIds.has(item.matchId)).map((item) => item.matchId));
|
|
8886
|
+
const warnings = [...active.values()].filter((match) => !suppressedIds.has(match.matchId));
|
|
8887
|
+
const suppressedCount = active.size - warnings.length;
|
|
8888
|
+
return {
|
|
8889
|
+
enforcement: "warning",
|
|
8890
|
+
status: unresolved2.size ? "unresolved" : warnings.length ? "warning" : suppressedCount ? "suppressed" : "clear",
|
|
8891
|
+
warningCount: warnings.length,
|
|
8892
|
+
unresolvedCount: unresolved2.size,
|
|
8893
|
+
suppressedCount,
|
|
8894
|
+
matches: warnings.slice(0, 8)
|
|
8895
|
+
};
|
|
8896
|
+
}
|
|
8897
|
+
function activeDuplicationMatchIds(audit, suppressions = []) {
|
|
8898
|
+
const completion = buildDuplicationCompletion(audit, suppressions);
|
|
8899
|
+
return new Set(completion?.matches.map((match) => match.matchId) ?? []);
|
|
8900
|
+
}
|
|
8901
|
+
function pruneDuplicationSuppressions(audit, suppressions = []) {
|
|
8902
|
+
if (!suppressions.length) return [];
|
|
8903
|
+
const active = new Set(buildDuplicationCompletion(audit, [])?.matches.map((match) => match.matchId) ?? []);
|
|
8904
|
+
return suppressions.filter((item) => active.has(item.matchId)).slice(-64);
|
|
8905
|
+
}
|
|
8906
|
+
function findActiveDuplicationMatches(audit, suppressions = []) {
|
|
8907
|
+
return buildDuplicationCompletion(audit, suppressions)?.matches ?? [];
|
|
8908
|
+
}
|
|
8909
|
+
function hasDuplicationActivity(audit, runStartedAt) {
|
|
8910
|
+
return audit.some(
|
|
8911
|
+
(event) => (!runStartedAt || event.createdAt >= runStartedAt) && (duplicationReceipt(event.metadata?.duplicationAudit) !== void 0 || event.metadata?.duplicationSuppression !== void 0 || event.metadata?.activeDuplicationMatches !== void 0)
|
|
8912
|
+
);
|
|
8913
|
+
}
|
|
8914
|
+
function duplicationReceipt(value) {
|
|
8915
|
+
if (!value || typeof value !== "object") return void 0;
|
|
8916
|
+
const receipt = value;
|
|
8917
|
+
if (!Array.isArray(receipt.matches) || typeof receipt.changeSequence !== "number" || !["clear", "warning", "unresolved"].includes(String(receipt.status))) return void 0;
|
|
8918
|
+
return receipt;
|
|
8919
|
+
}
|
|
8920
|
+
function changedPathsFor(event, receipt) {
|
|
8921
|
+
const metadataPaths = event.metadata?.changedFiles;
|
|
8922
|
+
const fromMetadata = Array.isArray(metadataPaths) ? metadataPaths.filter((path) => typeof path === "string") : [];
|
|
8923
|
+
return [.../* @__PURE__ */ new Set([...fromMetadata, ...receipt.matches.map((match) => match.changedPath)])];
|
|
8924
|
+
}
|
|
8925
|
+
|
|
8926
|
+
// src/tools/duplication.ts
|
|
8927
|
+
var inputSchema12 = z17.discriminatedUnion("action", [
|
|
8928
|
+
z17.object({ action: z17.literal("show") }).strict(),
|
|
8929
|
+
z17.object({
|
|
8930
|
+
action: z17.literal("suppress"),
|
|
8931
|
+
match_id: z17.string().regex(/^[a-f0-9]{24}$/u),
|
|
8932
|
+
reason_code: z17.enum(["separate-boundary", "protocol-required", "generated-contract", "false-positive", "other"]),
|
|
8933
|
+
reason: z17.string().trim().min(12).max(240)
|
|
8934
|
+
}).strict()
|
|
8935
|
+
]);
|
|
8936
|
+
var duplicationTool = {
|
|
8937
|
+
definition: {
|
|
8938
|
+
name: "duplication_audit",
|
|
8939
|
+
description: "Inspect active duplicate-function warnings or suppress one exact match with an auditable reason. Suppression does not bypass correctness, security, accessibility, concurrency, or verification requirements.",
|
|
8940
|
+
category: "read",
|
|
8941
|
+
inputSchema: jsonSchema({
|
|
8942
|
+
action: { type: "string", enum: ["show", "suppress"] },
|
|
8943
|
+
match_id: { type: "string", description: "Exact 24-character match id from the current audit." },
|
|
8944
|
+
reason_code: { type: "string", enum: ["separate-boundary", "protocol-required", "generated-contract", "false-positive", "other"] },
|
|
8945
|
+
reason: { type: "string", description: "Specific 12-240 character explanation; code blocks and credentials are rejected." }
|
|
8946
|
+
}, ["action"])
|
|
8947
|
+
},
|
|
8948
|
+
async execute(arguments_, context) {
|
|
8949
|
+
const input2 = inputSchema12.parse(arguments_);
|
|
8950
|
+
const suppressions = pruneDuplicationSuppressions(
|
|
8951
|
+
context.session.audit ?? [],
|
|
8952
|
+
context.session.duplicationSuppressions ?? []
|
|
8953
|
+
);
|
|
8954
|
+
context.session.duplicationSuppressions = suppressions;
|
|
8955
|
+
const active = activeDuplicationMatchIds(context.session.audit ?? [], suppressions);
|
|
8956
|
+
if (input2.action === "suppress") {
|
|
8957
|
+
if (!active.has(input2.match_id)) {
|
|
8958
|
+
throw new Error(`Unknown, stale, or already suppressed duplication match: ${input2.match_id}`);
|
|
8959
|
+
}
|
|
8960
|
+
suppressions.push({
|
|
8961
|
+
matchId: input2.match_id,
|
|
8962
|
+
reasonCode: input2.reason_code,
|
|
8963
|
+
reason: cleanReason(input2.reason),
|
|
8964
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8965
|
+
toolCallId: context.toolCallId ?? "unavailable"
|
|
8966
|
+
});
|
|
8967
|
+
context.session.duplicationSuppressions = suppressions.slice(-64);
|
|
8968
|
+
return {
|
|
8969
|
+
content: `Suppressed duplication match ${input2.match_id}. This does not waive verification or safety requirements.`,
|
|
8970
|
+
metadata: { duplicationSuppression: context.session.duplicationSuppressions.at(-1) }
|
|
8971
|
+
};
|
|
8972
|
+
}
|
|
8973
|
+
const matches = findActiveDuplicationMatches(context.session.audit ?? [], suppressions);
|
|
8974
|
+
return {
|
|
8975
|
+
content: matches.length ? matches.map(
|
|
8976
|
+
(match) => `- ${match.matchId}: ${match.changedPath}#${match.changedSymbol} -> ${match.candidatePath}#${match.candidateSymbol} (${match.kind}, ${match.similarity.toFixed(3)})`
|
|
8977
|
+
).join("\n") : "No unsuppressed duplication matches.",
|
|
8978
|
+
metadata: { activeDuplicationMatches: matches.map((match) => match.matchId) }
|
|
8979
|
+
};
|
|
8980
|
+
}
|
|
8981
|
+
};
|
|
8982
|
+
function cleanReason(value) {
|
|
8983
|
+
if (/```|~~~|\b(?:api[_-]?key|access[_-]?token|authorization|cookie|password|secret)\s*[:=]/iu.test(value) || /\b(?:sk-[A-Za-z0-9_-]{12,}|AIza[0-9A-Za-z_-]{20,})\b/u.test(value)) {
|
|
8984
|
+
throw new Error("Suppression reasons cannot contain code blocks or credentials.");
|
|
8985
|
+
}
|
|
8986
|
+
return value.replace(/[\u0000-\u001f\u007f-\u009f]/gu, " ").replace(/\s+/gu, " ").trim();
|
|
8987
|
+
}
|
|
8988
|
+
|
|
8818
8989
|
// src/tools/index.ts
|
|
8819
8990
|
function createDefaultToolRegistry(_options = {}) {
|
|
8820
8991
|
return new ToolRegistry([
|
|
@@ -8828,6 +8999,7 @@ function createDefaultToolRegistry(_options = {}) {
|
|
|
8828
8999
|
gitTool,
|
|
8829
9000
|
taskTool,
|
|
8830
9001
|
taskContractTool,
|
|
9002
|
+
duplicationTool,
|
|
8831
9003
|
workingMemoryTool
|
|
8832
9004
|
]);
|
|
8833
9005
|
}
|
|
@@ -9633,6 +9805,7 @@ function roundScore(value) {
|
|
|
9633
9805
|
}
|
|
9634
9806
|
|
|
9635
9807
|
// src/agent/duplication-audit.ts
|
|
9808
|
+
import { createHash as createHash14 } from "node:crypto";
|
|
9636
9809
|
import { readFile as readFile15 } from "node:fs/promises";
|
|
9637
9810
|
var NEAR_CLONE_THRESHOLD = 0.55;
|
|
9638
9811
|
var MAX_MATCHES = 8;
|
|
@@ -9658,13 +9831,16 @@ async function auditChangedFunctions(input2) {
|
|
|
9658
9831
|
return unresolved(input2.changeSequence, input2.baseline?.generation);
|
|
9659
9832
|
}
|
|
9660
9833
|
const currentFunctions = reports.flatMap((report) => report.functions.map(withoutTokens));
|
|
9661
|
-
if (!currentFunctions.length)
|
|
9834
|
+
if (!currentFunctions.length) {
|
|
9835
|
+
return auditableFiles.some((path) => input2.recheckPaths?.has(path)) && input2.baseline ? clear(input2.baseline.generation, input2.changeSequence, skippedSmallFunctions) : void 0;
|
|
9836
|
+
}
|
|
9662
9837
|
if (!input2.baseline) return unresolved(input2.changeSequence);
|
|
9663
9838
|
const lookup = createBaselineLookup(input2.baseline.functions);
|
|
9664
9839
|
const previousByCurrent = matchCurrentFunctions(input2.baseline.functions, currentFunctions);
|
|
9665
9840
|
const added = currentFunctions.flatMap((current) => {
|
|
9666
9841
|
const previous = previousByCurrent.get(locationIdentity(current));
|
|
9667
|
-
|
|
9842
|
+
const recheck = input2.recheckFunctions?.has(identity(current)) || previous !== void 0 && input2.recheckFunctions?.has(identity(previous));
|
|
9843
|
+
return !previous || current.tokenCount >= previous.tokenCount * 1.5 || recheck ? [{ current, previous }] : [];
|
|
9668
9844
|
});
|
|
9669
9845
|
if (!added.length) return void 0;
|
|
9670
9846
|
const matches = [];
|
|
@@ -9678,6 +9854,7 @@ async function auditChangedFunctions(input2) {
|
|
|
9678
9854
|
}
|
|
9679
9855
|
if (!best) continue;
|
|
9680
9856
|
matches.push({
|
|
9857
|
+
matchId: matchId(input2.baseline.generation, input2.changeSequence, item, best.candidate, best.similarity),
|
|
9681
9858
|
changedPath: item.path,
|
|
9682
9859
|
changedSymbol: item.symbol,
|
|
9683
9860
|
candidatePath: best.candidate.path,
|
|
@@ -9699,6 +9876,18 @@ async function auditChangedFunctions(input2) {
|
|
|
9699
9876
|
rationale: bounded.length ? `${bounded.length} deterministic duplicate candidate${bounded.length === 1 ? "" : "s"} found; review for reuse.` : "No deterministic duplicate candidate exceeded the warning threshold."
|
|
9700
9877
|
};
|
|
9701
9878
|
}
|
|
9879
|
+
function clear(baselineGeneration, changeSequence, skippedSmallFunctions) {
|
|
9880
|
+
return {
|
|
9881
|
+
baselineGeneration,
|
|
9882
|
+
changeSequence,
|
|
9883
|
+
status: "clear",
|
|
9884
|
+
warningOnly: true,
|
|
9885
|
+
checkedFunctions: 0,
|
|
9886
|
+
skippedSmallFunctions,
|
|
9887
|
+
matches: [],
|
|
9888
|
+
rationale: "No active deterministic duplicate candidate remains on the rechecked path."
|
|
9889
|
+
};
|
|
9890
|
+
}
|
|
9702
9891
|
function withoutTokens(value) {
|
|
9703
9892
|
const { normalizedTokens: _tokens, ...fingerprint } = value;
|
|
9704
9893
|
return fingerprint;
|
|
@@ -9782,6 +9971,17 @@ function unresolved(changeSequence, generation = "unavailable") {
|
|
|
9782
9971
|
function round(value) {
|
|
9783
9972
|
return Math.round(value * 1e3) / 1e3;
|
|
9784
9973
|
}
|
|
9974
|
+
function matchId(generation, changeSequence, changed, candidate, similarity) {
|
|
9975
|
+
return createHash14("sha256").update([
|
|
9976
|
+
generation,
|
|
9977
|
+
String(changeSequence),
|
|
9978
|
+
changed.path,
|
|
9979
|
+
changed.symbol,
|
|
9980
|
+
candidate.path,
|
|
9981
|
+
candidate.symbol,
|
|
9982
|
+
similarity === 1 ? "type-1-or-2" : "type-3"
|
|
9983
|
+
].join("\0")).digest("hex").slice(0, 24);
|
|
9984
|
+
}
|
|
9785
9985
|
|
|
9786
9986
|
// src/agent/runner.ts
|
|
9787
9987
|
var AgentRunner = class {
|
|
@@ -9853,6 +10053,7 @@ var AgentRunner = class {
|
|
|
9853
10053
|
await options.onEvent?.(event);
|
|
9854
10054
|
};
|
|
9855
10055
|
const changeSequenceAtStart = this.changeSequence;
|
|
10056
|
+
const runStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9856
10057
|
const runChangedFiles = /* @__PURE__ */ new Set();
|
|
9857
10058
|
const verificationEvidence = [];
|
|
9858
10059
|
const toolRecovery = new ToolRecoveryController();
|
|
@@ -9882,7 +10083,11 @@ var AgentRunner = class {
|
|
|
9882
10083
|
this.changeSequence,
|
|
9883
10084
|
mutationTracking,
|
|
9884
10085
|
activeRunContract,
|
|
9885
|
-
this.session.audit ?? []
|
|
10086
|
+
this.session.audit ?? [],
|
|
10087
|
+
hasDuplicationActivity(this.session.audit ?? [], runStartedAt) ? buildDuplicationCompletion(
|
|
10088
|
+
this.session.audit ?? [],
|
|
10089
|
+
this.session.duplicationSuppressions ?? []
|
|
10090
|
+
) : void 0
|
|
9886
10091
|
);
|
|
9887
10092
|
if (completion.acceptance && activeRunContract && activeRunContract.state !== "draft") {
|
|
9888
10093
|
activeRunContract.state = completion.acceptance.state;
|
|
@@ -10008,7 +10213,11 @@ var AgentRunner = class {
|
|
|
10008
10213
|
this.tools,
|
|
10009
10214
|
options.askMode === true,
|
|
10010
10215
|
contractEnabled,
|
|
10011
|
-
this.hasReadableToolArtifact()
|
|
10216
|
+
this.hasReadableToolArtifact(),
|
|
10217
|
+
activeDuplicationMatchIds(
|
|
10218
|
+
this.session.audit ?? [],
|
|
10219
|
+
this.session.duplicationSuppressions ?? []
|
|
10220
|
+
).size > 0
|
|
10012
10221
|
);
|
|
10013
10222
|
const estimatedInputTokens = estimateMessages2(messages) + estimateToolDefinitions(visibleTools);
|
|
10014
10223
|
if (availableTokens <= 0 || estimatedInputTokens >= availableTokens) {
|
|
@@ -10293,7 +10502,8 @@ ${input2}`
|
|
|
10293
10502
|
contextEngine: this.contextEngine,
|
|
10294
10503
|
toolArtifactStore: this.toolArtifactStore,
|
|
10295
10504
|
emit,
|
|
10296
|
-
...options.signal ? { signal: options.signal } : {}
|
|
10505
|
+
...options.signal ? { signal: options.signal } : {},
|
|
10506
|
+
toolCallId: call.id
|
|
10297
10507
|
};
|
|
10298
10508
|
try {
|
|
10299
10509
|
let reuseReceipt;
|
|
@@ -10343,10 +10553,21 @@ ${input2}`
|
|
|
10343
10553
|
throwIfAborted(options.signal);
|
|
10344
10554
|
const execution = await tool.execute(call.arguments, toolExecutionContext);
|
|
10345
10555
|
const changedFiles = await this.acceptChangedFiles(execution.changedFiles ?? []);
|
|
10556
|
+
const activeDuplicateFunctions = new Set(
|
|
10557
|
+
buildDuplicationCompletion(
|
|
10558
|
+
this.session.audit ?? [],
|
|
10559
|
+
[]
|
|
10560
|
+
)?.matches.map((match) => `${match.changedPath}\0${match.changedSymbol}`) ?? []
|
|
10561
|
+
);
|
|
10562
|
+
const activeDuplicatePaths = new Set(
|
|
10563
|
+
buildDuplicationCompletion(this.session.audit ?? [], [])?.matches.map((match) => match.changedPath) ?? []
|
|
10564
|
+
);
|
|
10346
10565
|
const duplicationAudit = duplicationAuditEnabled ? await auditChangedFunctions({
|
|
10347
10566
|
...duplicationBaseline ? { baseline: duplicationBaseline } : {},
|
|
10348
10567
|
changedFiles,
|
|
10349
|
-
changeSequence: this.changeSequence
|
|
10568
|
+
changeSequence: this.changeSequence,
|
|
10569
|
+
recheckFunctions: activeDuplicateFunctions,
|
|
10570
|
+
recheckPaths: activeDuplicatePaths
|
|
10350
10571
|
}) : void 0;
|
|
10351
10572
|
const tasksBefore = JSON.stringify(this.session.tasks);
|
|
10352
10573
|
let afterHookError;
|
|
@@ -10826,9 +11047,9 @@ ${content}` : content,
|
|
|
10826
11047
|
...failure ? { metadata: { failure } } : {}
|
|
10827
11048
|
};
|
|
10828
11049
|
}
|
|
10829
|
-
function visibleToolDefinitions(tools, askMode, contractEnabled, artifactReadAvailable) {
|
|
11050
|
+
function visibleToolDefinitions(tools, askMode, contractEnabled, artifactReadAvailable, duplicationAvailable) {
|
|
10830
11051
|
return tools.definitions().filter(
|
|
10831
|
-
(tool) => (!askMode || tool.category === "read") && (contractEnabled || tool.name !== "task_contract") && (artifactReadAvailable || tool.name !== "read_tool_artifact")
|
|
11052
|
+
(tool) => (!askMode || tool.category === "read") && (contractEnabled || tool.name !== "task_contract") && (artifactReadAvailable || tool.name !== "read_tool_artifact") && (duplicationAvailable || tool.name !== "duplication_audit")
|
|
10832
11053
|
);
|
|
10833
11054
|
}
|
|
10834
11055
|
function formatToolError(error) {
|
|
@@ -11020,7 +11241,7 @@ function integer(value, fallback, min, max) {
|
|
|
11020
11241
|
// src/agent/delegation.ts
|
|
11021
11242
|
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
11022
11243
|
import { join as join18 } from "node:path";
|
|
11023
|
-
import { z as
|
|
11244
|
+
import { z as z19 } from "zod";
|
|
11024
11245
|
|
|
11025
11246
|
// src/agent/external-runtime.ts
|
|
11026
11247
|
async function runExternalAgent(request) {
|
|
@@ -11147,86 +11368,86 @@ function numeric(...values) {
|
|
|
11147
11368
|
}
|
|
11148
11369
|
|
|
11149
11370
|
// src/agent/team-store.ts
|
|
11150
|
-
import { createHash as
|
|
11371
|
+
import { createHash as createHash15, randomUUID as randomUUID13 } from "node:crypto";
|
|
11151
11372
|
import { lstat as lstat18, readFile as readFile17, readdir as readdir7, rm as rm3 } from "node:fs/promises";
|
|
11152
11373
|
import { join as join16, resolve as resolve16 } from "node:path";
|
|
11153
|
-
import { z as
|
|
11154
|
-
var runIdSchema =
|
|
11155
|
-
var hashSchema =
|
|
11156
|
-
var artifactSchema2 =
|
|
11374
|
+
import { z as z18 } from "zod";
|
|
11375
|
+
var runIdSchema = z18.string().uuid();
|
|
11376
|
+
var hashSchema = z18.string().regex(/^[a-f0-9]{64}$/u);
|
|
11377
|
+
var artifactSchema2 = z18.object({
|
|
11157
11378
|
sha256: hashSchema,
|
|
11158
|
-
bytes:
|
|
11379
|
+
bytes: z18.number().int().nonnegative().max(5e5)
|
|
11159
11380
|
}).strict();
|
|
11160
|
-
var phaseSchema =
|
|
11161
|
-
var agentRecordSchema =
|
|
11162
|
-
id:
|
|
11163
|
-
profile:
|
|
11164
|
-
provider:
|
|
11165
|
-
model:
|
|
11381
|
+
var phaseSchema = z18.enum(["work", "review", "revision", "write"]);
|
|
11382
|
+
var agentRecordSchema = z18.object({
|
|
11383
|
+
id: z18.string().uuid(),
|
|
11384
|
+
profile: z18.string(),
|
|
11385
|
+
provider: z18.string(),
|
|
11386
|
+
model: z18.string(),
|
|
11166
11387
|
phase: phaseSchema,
|
|
11167
|
-
ok:
|
|
11168
|
-
createdAt:
|
|
11169
|
-
startedAt:
|
|
11170
|
-
endedAt:
|
|
11171
|
-
durationMs:
|
|
11172
|
-
toolCalls:
|
|
11173
|
-
usage:
|
|
11174
|
-
inputTokens:
|
|
11175
|
-
outputTokens:
|
|
11388
|
+
ok: z18.boolean(),
|
|
11389
|
+
createdAt: z18.string(),
|
|
11390
|
+
startedAt: z18.string().optional(),
|
|
11391
|
+
endedAt: z18.string().optional(),
|
|
11392
|
+
durationMs: z18.number().int().nonnegative().optional(),
|
|
11393
|
+
toolCalls: z18.number().int().nonnegative().optional(),
|
|
11394
|
+
usage: z18.object({
|
|
11395
|
+
inputTokens: z18.number().int().nonnegative(),
|
|
11396
|
+
outputTokens: z18.number().int().nonnegative()
|
|
11176
11397
|
}).strict().optional(),
|
|
11177
11398
|
report: artifactSchema2
|
|
11178
11399
|
}).strict();
|
|
11179
|
-
var messageRecordSchema =
|
|
11180
|
-
id:
|
|
11181
|
-
from:
|
|
11182
|
-
to:
|
|
11183
|
-
createdAt:
|
|
11400
|
+
var messageRecordSchema = z18.object({
|
|
11401
|
+
id: z18.string().uuid(),
|
|
11402
|
+
from: z18.string(),
|
|
11403
|
+
to: z18.string(),
|
|
11404
|
+
createdAt: z18.string(),
|
|
11184
11405
|
content: artifactSchema2
|
|
11185
11406
|
}).strict();
|
|
11186
|
-
var writerIntegrationSchema =
|
|
11187
|
-
status:
|
|
11188
|
-
checkedAt:
|
|
11189
|
-
detail:
|
|
11190
|
-
checkpoint:
|
|
11191
|
-
sessionId:
|
|
11192
|
-
checkpointId:
|
|
11407
|
+
var writerIntegrationSchema = z18.object({
|
|
11408
|
+
status: z18.enum(["ready", "conflict", "integrated"]),
|
|
11409
|
+
checkedAt: z18.string(),
|
|
11410
|
+
detail: z18.string().max(2e4),
|
|
11411
|
+
checkpoint: z18.object({
|
|
11412
|
+
sessionId: z18.string(),
|
|
11413
|
+
checkpointId: z18.string()
|
|
11193
11414
|
}).strict().optional(),
|
|
11194
|
-
integratedAt:
|
|
11415
|
+
integratedAt: z18.string().optional()
|
|
11195
11416
|
}).strict();
|
|
11196
|
-
var writerLaneSchema =
|
|
11197
|
-
profile:
|
|
11198
|
-
reviewer:
|
|
11199
|
-
baseCommit:
|
|
11200
|
-
outcome:
|
|
11417
|
+
var writerLaneSchema = z18.object({
|
|
11418
|
+
profile: z18.string(),
|
|
11419
|
+
reviewer: z18.string(),
|
|
11420
|
+
baseCommit: z18.string().regex(/^[a-f0-9]{40,64}$/u),
|
|
11421
|
+
outcome: z18.enum(["accepted", "rejected", "failed", "cancelled"]),
|
|
11201
11422
|
patch: artifactSchema2,
|
|
11202
|
-
files:
|
|
11203
|
-
worktreeCleaned:
|
|
11423
|
+
files: z18.array(z18.string().min(1).max(4e3)).max(2e3),
|
|
11424
|
+
worktreeCleaned: z18.boolean(),
|
|
11204
11425
|
review: artifactSchema2.optional(),
|
|
11205
11426
|
integration: writerIntegrationSchema.optional()
|
|
11206
11427
|
}).strict();
|
|
11207
11428
|
var manifestFields = {
|
|
11208
11429
|
id: runIdSchema,
|
|
11209
|
-
workspace:
|
|
11210
|
-
objective:
|
|
11211
|
-
reviewer:
|
|
11212
|
-
createdAt:
|
|
11213
|
-
updatedAt:
|
|
11214
|
-
status:
|
|
11215
|
-
maxReviewRounds:
|
|
11216
|
-
reviewRounds:
|
|
11217
|
-
agents:
|
|
11218
|
-
messages:
|
|
11430
|
+
workspace: z18.string(),
|
|
11431
|
+
objective: z18.string().max(3e4),
|
|
11432
|
+
reviewer: z18.string(),
|
|
11433
|
+
createdAt: z18.string(),
|
|
11434
|
+
updatedAt: z18.string(),
|
|
11435
|
+
status: z18.enum(["running", "accepted", "rejected", "failed"]),
|
|
11436
|
+
maxReviewRounds: z18.number().int().min(0).max(3),
|
|
11437
|
+
reviewRounds: z18.number().int().min(0).max(3),
|
|
11438
|
+
agents: z18.array(agentRecordSchema).max(256),
|
|
11439
|
+
messages: z18.array(messageRecordSchema).max(512)
|
|
11219
11440
|
};
|
|
11220
|
-
var manifestV1Schema =
|
|
11221
|
-
version:
|
|
11441
|
+
var manifestV1Schema = z18.object({
|
|
11442
|
+
version: z18.literal(1),
|
|
11222
11443
|
...manifestFields
|
|
11223
11444
|
}).strict();
|
|
11224
|
-
var manifestV2Schema =
|
|
11225
|
-
version:
|
|
11445
|
+
var manifestV2Schema = z18.object({
|
|
11446
|
+
version: z18.literal(2),
|
|
11226
11447
|
...manifestFields,
|
|
11227
11448
|
writer: writerLaneSchema.optional()
|
|
11228
11449
|
}).strict();
|
|
11229
|
-
var manifestSchema2 =
|
|
11450
|
+
var manifestSchema2 = z18.discriminatedUnion("version", [manifestV1Schema, manifestV2Schema]);
|
|
11230
11451
|
var TeamRunStore = class {
|
|
11231
11452
|
workspace;
|
|
11232
11453
|
directory;
|
|
@@ -11405,7 +11626,7 @@ var TeamRunStore = class {
|
|
|
11405
11626
|
async writeArtifact(runId, content, truncate = true) {
|
|
11406
11627
|
const data = boundedArtifactText(content, 5e5, truncate);
|
|
11407
11628
|
const bytes = Buffer.byteLength(data);
|
|
11408
|
-
const sha256 =
|
|
11629
|
+
const sha256 = createHash15("sha256").update(data).digest("hex");
|
|
11409
11630
|
const directory = join16(this.runDirectory(runId), "blobs");
|
|
11410
11631
|
await ensureWorkspaceStorageDirectory(this.workspace, directory, {
|
|
11411
11632
|
requireActiveNamespace: this.managedDirectory
|
|
@@ -11414,7 +11635,7 @@ var TeamRunStore = class {
|
|
|
11414
11635
|
try {
|
|
11415
11636
|
await this.assertRegularFile(path);
|
|
11416
11637
|
const existing = await readFile17(path);
|
|
11417
|
-
if (
|
|
11638
|
+
if (createHash15("sha256").update(existing).digest("hex") !== sha256) {
|
|
11418
11639
|
throw new Error(`Team artifact hash collision or corruption: ${sha256}`);
|
|
11419
11640
|
}
|
|
11420
11641
|
} catch (error) {
|
|
@@ -11435,7 +11656,7 @@ var TeamRunStore = class {
|
|
|
11435
11656
|
const path = this.artifactPath(runId, artifact.sha256);
|
|
11436
11657
|
await this.assertRegularFile(path);
|
|
11437
11658
|
const data = await readFile17(path);
|
|
11438
|
-
const hash4 =
|
|
11659
|
+
const hash4 = createHash15("sha256").update(data).digest("hex");
|
|
11439
11660
|
if (hash4 !== artifact.sha256 || data.byteLength !== artifact.bytes) {
|
|
11440
11661
|
throw new Error(`Team artifact integrity check failed: ${artifact.sha256}`);
|
|
11441
11662
|
}
|
|
@@ -11498,7 +11719,7 @@ function resolveAgentModelRoute(team, parent, profile) {
|
|
|
11498
11719
|
}
|
|
11499
11720
|
|
|
11500
11721
|
// src/agent/writer-lane.ts
|
|
11501
|
-
import { createHash as
|
|
11722
|
+
import { createHash as createHash16 } from "node:crypto";
|
|
11502
11723
|
import { lstat as lstat19, mkdtemp, realpath as realpath7, rm as rm4 } from "node:fs/promises";
|
|
11503
11724
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
11504
11725
|
import { isAbsolute as isAbsolute6, join as join17, resolve as resolve17 } from "node:path";
|
|
@@ -11596,7 +11817,7 @@ var WriterLane = class {
|
|
|
11596
11817
|
return {
|
|
11597
11818
|
baseCommit,
|
|
11598
11819
|
patch,
|
|
11599
|
-
patchSha256:
|
|
11820
|
+
patchSha256: createHash16("sha256").update(patch).digest("hex"),
|
|
11600
11821
|
files,
|
|
11601
11822
|
worktreeCleaned,
|
|
11602
11823
|
value
|
|
@@ -11826,14 +12047,14 @@ async function pathExists2(path) {
|
|
|
11826
12047
|
}
|
|
11827
12048
|
|
|
11828
12049
|
// src/agent/delegation.ts
|
|
11829
|
-
var writerRunInputSchema =
|
|
11830
|
-
task:
|
|
11831
|
-
profile:
|
|
11832
|
-
reviewer:
|
|
12050
|
+
var writerRunInputSchema = z19.object({
|
|
12051
|
+
task: z19.string().min(1).max(2e4),
|
|
12052
|
+
profile: z19.string().max(64).optional(),
|
|
12053
|
+
reviewer: z19.string().max(64).optional()
|
|
11833
12054
|
}).strict();
|
|
11834
|
-
var writerIntegrateInputSchema =
|
|
11835
|
-
run_id:
|
|
11836
|
-
patch_sha256:
|
|
12055
|
+
var writerIntegrateInputSchema = z19.object({
|
|
12056
|
+
run_id: z19.string().uuid(),
|
|
12057
|
+
patch_sha256: z19.string().regex(/^[a-f0-9]{64}$/u)
|
|
11837
12058
|
}).strict();
|
|
11838
12059
|
var DelegationManager = class {
|
|
11839
12060
|
constructor(options) {
|
|
@@ -11894,10 +12115,10 @@ var DelegationManager = class {
|
|
|
11894
12115
|
},
|
|
11895
12116
|
async execute(arguments_, context) {
|
|
11896
12117
|
if (!manager.team.enabled) return { ok: false, content: "Multi-agent delegation is disabled." };
|
|
11897
|
-
const input2 =
|
|
11898
|
-
tasks:
|
|
11899
|
-
profile:
|
|
11900
|
-
task:
|
|
12118
|
+
const input2 = z19.object({
|
|
12119
|
+
tasks: z19.array(z19.object({
|
|
12120
|
+
profile: z19.string().max(64).optional(),
|
|
12121
|
+
task: z19.string().min(1).max(2e4)
|
|
11901
12122
|
})).min(1).max(manager.team.maxDelegations)
|
|
11902
12123
|
}).parse(arguments_);
|
|
11903
12124
|
const tasks = input2.tasks.map((task) => ({
|
|
@@ -11943,13 +12164,13 @@ var DelegationManager = class {
|
|
|
11943
12164
|
},
|
|
11944
12165
|
async execute(arguments_, context) {
|
|
11945
12166
|
if (!manager.team.enabled) return { ok: false, content: "Multi-agent teams are disabled." };
|
|
11946
|
-
const input2 =
|
|
11947
|
-
objective:
|
|
11948
|
-
tasks:
|
|
11949
|
-
profile:
|
|
11950
|
-
task:
|
|
12167
|
+
const input2 = z19.object({
|
|
12168
|
+
objective: z19.string().min(1).max(3e4),
|
|
12169
|
+
tasks: z19.array(z19.object({
|
|
12170
|
+
profile: z19.string().max(64).optional(),
|
|
12171
|
+
task: z19.string().min(1).max(2e4)
|
|
11951
12172
|
})).min(1).max(manager.team.maxDelegations),
|
|
11952
|
-
reviewer:
|
|
12173
|
+
reviewer: z19.string().max(64).optional()
|
|
11953
12174
|
}).parse(arguments_);
|
|
11954
12175
|
const tasks = input2.tasks.map((task) => ({
|
|
11955
12176
|
profile: task.profile ?? manager.team.defaultProfile,
|
|
@@ -13597,22 +13818,24 @@ ${this.glyphs.meta} ${session.changedFiles.length} changed files ${this.glyphs.s
|
|
|
13597
13818
|
if (!completion || completion.status === "no_changes") return;
|
|
13598
13819
|
const checks = completion.checks.map((check) => check.command).join(", ");
|
|
13599
13820
|
const suffix = checks ? ` ${this.glyphs.separator} ${checks}` : "";
|
|
13821
|
+
const duplication = completion.duplication;
|
|
13822
|
+
const duplicateSuffix = duplication ? ` ${this.glyphs.separator} duplication ${duplication.status} (${duplication.warningCount} warning, ${duplication.unresolvedCount} incomplete, ${duplication.suppressedCount} suppressed)` : "";
|
|
13600
13823
|
if (completion.status === "verified") {
|
|
13601
13824
|
process.stderr.write(this.paint.green(
|
|
13602
|
-
`${this.glyphs.success} verified ${this.glyphs.separator} ${completion.detail}${suffix}
|
|
13825
|
+
`${this.glyphs.success} verified ${this.glyphs.separator} ${completion.detail}${suffix}${duplicateSuffix}
|
|
13603
13826
|
`
|
|
13604
13827
|
));
|
|
13605
13828
|
return;
|
|
13606
13829
|
}
|
|
13607
13830
|
if (completion.status === "verification_failed") {
|
|
13608
13831
|
process.stderr.write(this.paint.red(
|
|
13609
|
-
`${this.glyphs.error} verification failed ${this.glyphs.separator} ${completion.detail}${suffix}
|
|
13832
|
+
`${this.glyphs.error} verification failed ${this.glyphs.separator} ${completion.detail}${suffix}${duplicateSuffix}
|
|
13610
13833
|
`
|
|
13611
13834
|
));
|
|
13612
13835
|
return;
|
|
13613
13836
|
}
|
|
13614
13837
|
process.stderr.write(this.paint.yellow(
|
|
13615
|
-
`${this.glyphs.warning} unverified ${this.glyphs.separator} ${completion.detail}
|
|
13838
|
+
`${this.glyphs.warning} unverified ${this.glyphs.separator} ${completion.detail}${duplicateSuffix}
|
|
13616
13839
|
`
|
|
13617
13840
|
));
|
|
13618
13841
|
}
|
|
@@ -16231,6 +16454,11 @@ function toolMetaSummary(metadata) {
|
|
|
16231
16454
|
if (status === "warning") parts.push(`duplicates ${matches} (warning)`);
|
|
16232
16455
|
else if (status === "unresolved") parts.push("duplicates incomplete");
|
|
16233
16456
|
}
|
|
16457
|
+
const suppression = metadata.duplicationSuppression;
|
|
16458
|
+
if (suppression && typeof suppression === "object") {
|
|
16459
|
+
const matchId2 = suppression.matchId;
|
|
16460
|
+
if (typeof matchId2 === "string") parts.push(`duplicate ${matchId2.slice(0, 8)} suppressed`);
|
|
16461
|
+
}
|
|
16234
16462
|
const hooks = metadata.hooks;
|
|
16235
16463
|
if (hooks && typeof hooks === "object") {
|
|
16236
16464
|
const before = Number(hooks.before ?? 0);
|
|
@@ -16690,12 +16918,14 @@ function SkeinApp({ runner, config, extensions, initialPrompt, askMode = false,
|
|
|
16690
16918
|
refreshSession();
|
|
16691
16919
|
if (event.completion && event.completion.status !== "no_changes") {
|
|
16692
16920
|
const checks = event.completion.checks.map((check) => check.command).join(` ${separator} `);
|
|
16921
|
+
const duplication = event.completion.duplication;
|
|
16922
|
+
const duplicateDetail = duplication ? `${separator} duplication ${duplication.status} (${duplication.warningCount} warning, ${duplication.unresolvedCount} incomplete, ${duplication.suppressedCount} suppressed)` : "";
|
|
16693
16923
|
append({
|
|
16694
16924
|
id: nextId(),
|
|
16695
16925
|
kind: "notice",
|
|
16696
16926
|
wrapWidth: contentWidth,
|
|
16697
16927
|
tone: event.completion.status === "verified" ? "success" : event.completion.status === "unverified" ? "warning" : "error",
|
|
16698
|
-
text: event.completion.status === "verified" ? `Verified${separator}${event.completion.detail}${checks ? `${separator}${checks}` : ""}` : event.completion.status === "verification_failed" ? `Verification failed${separator}${event.completion.detail}${checks ? `${separator}${checks}` : ""}` : `Unverified${separator}${event.completion.detail}`
|
|
16928
|
+
text: event.completion.status === "verified" ? `Verified${separator}${event.completion.detail}${checks ? `${separator}${checks}` : ""}${duplicateDetail}` : event.completion.status === "verification_failed" ? `Verification failed${separator}${event.completion.detail}${checks ? `${separator}${checks}` : ""}${duplicateDetail}` : `Unverified${separator}${event.completion.detail}${duplicateDetail}`
|
|
16699
16929
|
});
|
|
16700
16930
|
}
|
|
16701
16931
|
if (event.reason !== "completed" && event.reason !== "unverified" && event.reason !== "verification_failed") {
|
|
@@ -18717,7 +18947,7 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/
|
|
|
18717
18947
|
import stripAnsi5 from "strip-ansi";
|
|
18718
18948
|
|
|
18719
18949
|
// src/mcp/tool.ts
|
|
18720
|
-
import { createHash as
|
|
18950
|
+
import { createHash as createHash17 } from "node:crypto";
|
|
18721
18951
|
import stripAnsi4 from "strip-ansi";
|
|
18722
18952
|
var MAX_ARGUMENT_BYTES = 256e3;
|
|
18723
18953
|
var MAX_DESCRIPTION_LENGTH = 4e3;
|
|
@@ -18725,7 +18955,7 @@ var MAX_RESULT_BYTES = 5 * 1024 * 1024;
|
|
|
18725
18955
|
var MAX_SCHEMA_BYTES = 1e5;
|
|
18726
18956
|
function createMcpToolAdapter(options) {
|
|
18727
18957
|
const { remoteTool } = options;
|
|
18728
|
-
const
|
|
18958
|
+
const inputSchema13 = copyInputSchema(remoteTool.inputSchema);
|
|
18729
18959
|
return {
|
|
18730
18960
|
definition: {
|
|
18731
18961
|
name: options.exposedName,
|
|
@@ -18733,7 +18963,7 @@ function createMcpToolAdapter(options) {
|
|
|
18733
18963
|
// MCP servers are an external trust boundary. Read-only annotations are
|
|
18734
18964
|
// hints from that server and must not lower the local permission level.
|
|
18735
18965
|
category: "network",
|
|
18736
|
-
inputSchema:
|
|
18966
|
+
inputSchema: inputSchema13
|
|
18737
18967
|
},
|
|
18738
18968
|
permissionCategories: () => ["network"],
|
|
18739
18969
|
async execute(arguments_, context) {
|
|
@@ -18887,7 +19117,7 @@ function fitToolName(name, identity2) {
|
|
|
18887
19117
|
return `${name.slice(0, 64 - suffix.length).replace(/_+$/g, "")}${suffix}`;
|
|
18888
19118
|
}
|
|
18889
19119
|
function shortHash(value) {
|
|
18890
|
-
return
|
|
19120
|
+
return createHash17("sha256").update(value).digest("hex").slice(0, 8);
|
|
18891
19121
|
}
|
|
18892
19122
|
function sanitizeOutputText(value) {
|
|
18893
19123
|
return stripAnsi4(value).replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/g, "");
|
|
@@ -19517,9 +19747,9 @@ async function closeTransportQuietly(transport) {
|
|
|
19517
19747
|
}
|
|
19518
19748
|
|
|
19519
19749
|
// src/memory/tools.ts
|
|
19520
|
-
import { z as
|
|
19521
|
-
var scopeSchema =
|
|
19522
|
-
var kindSchema =
|
|
19750
|
+
import { z as z20 } from "zod";
|
|
19751
|
+
var scopeSchema = z20.enum(["user", "workspace", "session", "agent"]);
|
|
19752
|
+
var kindSchema = z20.enum(["semantic", "episodic", "procedural"]);
|
|
19523
19753
|
function createMemoryTools(store) {
|
|
19524
19754
|
return [
|
|
19525
19755
|
{
|
|
@@ -19534,10 +19764,10 @@ function createMemoryTools(store) {
|
|
|
19534
19764
|
}, ["query"])
|
|
19535
19765
|
},
|
|
19536
19766
|
async execute(arguments_, context) {
|
|
19537
|
-
const input2 =
|
|
19538
|
-
query:
|
|
19767
|
+
const input2 = z20.object({
|
|
19768
|
+
query: z20.string().max(4e3),
|
|
19539
19769
|
scope: scopeSchema.optional(),
|
|
19540
|
-
limit:
|
|
19770
|
+
limit: z20.number().int().min(1).max(20).optional()
|
|
19541
19771
|
}).parse(arguments_);
|
|
19542
19772
|
const scopes = input2.scope ? [{ scope: input2.scope, scopeKey: scopeKey(input2.scope, context) }] : availableScopes(context);
|
|
19543
19773
|
const records = store.search(input2.query, { scopes, limit: input2.limit ?? 8 });
|
|
@@ -19569,17 +19799,17 @@ ${record.content}`
|
|
|
19569
19799
|
}, ["content", "rationale"])
|
|
19570
19800
|
},
|
|
19571
19801
|
async execute(arguments_, context) {
|
|
19572
|
-
const input2 =
|
|
19573
|
-
content:
|
|
19574
|
-
rationale:
|
|
19802
|
+
const input2 = z20.object({
|
|
19803
|
+
content: z20.string().min(1).max(12e3),
|
|
19804
|
+
rationale: z20.string().min(1).max(1e3),
|
|
19575
19805
|
scope: scopeSchema.optional(),
|
|
19576
19806
|
kind: kindSchema.optional(),
|
|
19577
|
-
tags:
|
|
19578
|
-
importance:
|
|
19579
|
-
confidence:
|
|
19580
|
-
agent:
|
|
19581
|
-
revision:
|
|
19582
|
-
conflictKey:
|
|
19807
|
+
tags: z20.array(z20.string()).max(24).optional(),
|
|
19808
|
+
importance: z20.number().min(0).max(1).optional(),
|
|
19809
|
+
confidence: z20.number().min(0).max(1).optional(),
|
|
19810
|
+
agent: z20.string().max(64).optional(),
|
|
19811
|
+
revision: z20.string().max(240).optional(),
|
|
19812
|
+
conflictKey: z20.string().max(240).optional()
|
|
19583
19813
|
}).strict().parse(arguments_);
|
|
19584
19814
|
const scope = input2.scope ?? "workspace";
|
|
19585
19815
|
const candidate = store.propose({
|
|
@@ -19617,9 +19847,9 @@ ${record.content}`
|
|
|
19617
19847
|
}, ["id"])
|
|
19618
19848
|
},
|
|
19619
19849
|
async execute(arguments_) {
|
|
19620
|
-
const input2 =
|
|
19621
|
-
id:
|
|
19622
|
-
permanent:
|
|
19850
|
+
const input2 = z20.object({
|
|
19851
|
+
id: z20.string().uuid(),
|
|
19852
|
+
permanent: z20.boolean().optional()
|
|
19623
19853
|
}).parse(arguments_);
|
|
19624
19854
|
const changed = input2.permanent ? store.remove(input2.id) : store.archive(input2.id);
|
|
19625
19855
|
return {
|
|
@@ -19823,7 +20053,7 @@ function escapeAttribute6(value) {
|
|
|
19823
20053
|
}
|
|
19824
20054
|
|
|
19825
20055
|
// src/workflows/catalog.ts
|
|
19826
|
-
import { z as
|
|
20056
|
+
import { z as z21 } from "zod";
|
|
19827
20057
|
var builtInWorkflows = [
|
|
19828
20058
|
{
|
|
19829
20059
|
name: "implement",
|
|
@@ -19914,7 +20144,7 @@ function createWorkflowTool(catalog) {
|
|
|
19914
20144
|
}, ["name", "task"])
|
|
19915
20145
|
},
|
|
19916
20146
|
async execute(arguments_) {
|
|
19917
|
-
const input2 =
|
|
20147
|
+
const input2 = z21.object({ name: z21.string(), task: z21.string().min(1).max(2e4) }).parse(arguments_);
|
|
19918
20148
|
const workflow = catalog.get(input2.name);
|
|
19919
20149
|
if (!workflow) return { ok: false, content: `Unknown workflow: ${input2.name}` };
|
|
19920
20150
|
return {
|