@mrciphersmith/keryx 0.3.26 → 0.3.27
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.js +128 -50
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -12991,7 +12991,7 @@ var package_default;
|
|
|
12991
12991
|
var init_package = __esm(() => {
|
|
12992
12992
|
package_default = {
|
|
12993
12993
|
name: "@mrciphersmith/keryx",
|
|
12994
|
-
version: "0.3.
|
|
12994
|
+
version: "0.3.27",
|
|
12995
12995
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
12996
12996
|
private: false,
|
|
12997
12997
|
publishConfig: {
|
|
@@ -71063,7 +71063,7 @@ ${shown.join(`
|
|
|
71063
71063
|
result = precomputedResult;
|
|
71064
71064
|
} else {
|
|
71065
71065
|
try {
|
|
71066
|
-
result = await executeCall(call, toolByName, io.requestApproval, io.permissionMode, io.readOnly, io.onAutoApproved, hasInvocationCapacity, reserveInvocation, invocationBudget.maxCalls, signal, deps.busLeases, deps.hardDeny === undefined ? undefined : { check: deps.hardDeny, onDenied: io.onUnattendedDenial }, deps.hooks, untrustedOrigin);
|
|
71066
|
+
result = await executeCall(call, toolByName, io.requestApproval, io.permissionMode, io.readOnly, io.onAutoApproved, hasInvocationCapacity, reserveInvocation, invocationBudget.maxCalls, signal, deps.busLeases, deps.hardDeny === undefined ? undefined : { check: deps.hardDeny, onDenied: io.onUnattendedDenial }, deps.hooks, untrustedOrigin, io.trustedMcpTools, io.mcpToolFingerprint);
|
|
71067
71067
|
} catch (err) {
|
|
71068
71068
|
const message = err instanceof Error ? err.message : String(err);
|
|
71069
71069
|
result = { output: `${call.name} failed: ${message}`, isError: true };
|
|
@@ -71633,7 +71633,7 @@ function composeWithHook(toolName, rawDecision, hookResult, interactive) {
|
|
|
71633
71633
|
}
|
|
71634
71634
|
return { decision, hookTightened: true, hookAsked, ...denyMessage !== undefined ? { denyMessage } : {} };
|
|
71635
71635
|
}
|
|
71636
|
-
async function executeCall(call, toolByName, requestApproval, permissionMode, readOnly, onAutoApproved, hasInvocationCapacity, reserveInvocation, maxToolCalls, signal, busLeases, hardDeny, hooks, untrustedOrigin = false) {
|
|
71636
|
+
async function executeCall(call, toolByName, requestApproval, permissionMode, readOnly, onAutoApproved, hasInvocationCapacity, reserveInvocation, maxToolCalls, signal, busLeases, hardDeny, hooks, untrustedOrigin = false, trustedMcpTools, mcpToolFingerprint) {
|
|
71637
71637
|
const tool = toolByName.get(call.name);
|
|
71638
71638
|
if (tool === undefined) {
|
|
71639
71639
|
return { output: `unknown tool: ${call.name}`, isError: true };
|
|
@@ -71694,13 +71694,20 @@ async function executeCall(call, toolByName, requestApproval, permissionMode, re
|
|
|
71694
71694
|
publishLease
|
|
71695
71695
|
});
|
|
71696
71696
|
const gated = composeWithHook(call.name, rawDecision, hookResult, hookInteractive);
|
|
71697
|
+
const mcpFqn = call.name === "use_tool" && typeof input.tool_name === "string" ? input.tool_name : undefined;
|
|
71698
|
+
const currentMcpFingerprint = mcpFqn !== undefined ? mcpToolFingerprint?.(mcpFqn) : undefined;
|
|
71699
|
+
if (mcpFqn !== undefined && trustedMcpTools?.has(mcpFqn) === true && trustedMcpTools.get(mcpFqn) !== currentMcpFingerprint) {
|
|
71700
|
+
trustedMcpTools.delete(mcpFqn);
|
|
71701
|
+
}
|
|
71702
|
+
const trustedMcp = mode === "trust" && mcpFqn !== undefined && trustedMcpTools?.has(mcpFqn) === true;
|
|
71703
|
+
const mcpTrustEligible = mcpFqn !== undefined && mode === "trust" && !gated.hookAsked && currentMcpFingerprint !== undefined;
|
|
71697
71704
|
if (gated.decision === "deny") {
|
|
71698
71705
|
return {
|
|
71699
71706
|
output: gated.hookTightened ? gated.denyMessage : `tool "${call.name}" is not permitted while read-only mode (/plan) is on`,
|
|
71700
71707
|
isError: true
|
|
71701
71708
|
};
|
|
71702
71709
|
}
|
|
71703
|
-
if (gated.decision === "auto" && !untrustedOrigin) {
|
|
71710
|
+
if (gated.decision === "auto" && !untrustedOrigin || trustedMcp && !untrustedOrigin && !gated.hookAsked && !isReadOnly) {
|
|
71704
71711
|
onAutoApproved?.(call.name, call.input, { destructive, credentials });
|
|
71705
71712
|
} else {
|
|
71706
71713
|
const fingerprint = toolCallHash(call.name, call.input);
|
|
@@ -71711,11 +71718,15 @@ async function executeCall(call, toolByName, requestApproval, permissionMode, re
|
|
|
71711
71718
|
...publishLease ? { publishLease } : {},
|
|
71712
71719
|
...publishLease && publishLeaseHolder !== undefined ? { publishLeaseDetail: `held by @${publishLeaseHolder.name} \u2014 "${publishLeaseHolder.reason}"` } : {},
|
|
71713
71720
|
...gated.hookAsked ? { hookAsk: true } : {},
|
|
71714
|
-
...untrustedOrigin ? { untrustedOrigin: true } : {}
|
|
71721
|
+
...untrustedOrigin ? { untrustedOrigin: true } : {},
|
|
71722
|
+
...mcpTrustEligible ? untrustedOrigin ? { mcpTrustWithheld: true } : { mcpTrustAvailable: true } : {}
|
|
71715
71723
|
});
|
|
71716
71724
|
if (!isApprovalFor(response, fingerprint)) {
|
|
71717
71725
|
return { output: untrustedOrigin ? untrustedDenial : "command not approved by the user; not executed", isError: true };
|
|
71718
71726
|
}
|
|
71727
|
+
if (mcpFqn !== undefined && currentMcpFingerprint !== undefined && typeof response === "object" && response.trustMcpTool === true && mcpTrustEligible && !untrustedOrigin) {
|
|
71728
|
+
trustedMcpTools?.set(mcpFqn, currentMcpFingerprint);
|
|
71729
|
+
}
|
|
71719
71730
|
}
|
|
71720
71731
|
} else if (risk === "delegate") {
|
|
71721
71732
|
const rawDecision = resolveApprovalDecision({
|
|
@@ -77704,6 +77715,26 @@ var init_workspace_lifecycle_tool = __esm(() => {
|
|
|
77704
77715
|
});
|
|
77705
77716
|
|
|
77706
77717
|
// src/mcp-servers/catalog.ts
|
|
77718
|
+
import { createHash as createHash54 } from "crypto";
|
|
77719
|
+
function canonicalJson3(value) {
|
|
77720
|
+
if (value === undefined)
|
|
77721
|
+
return "null";
|
|
77722
|
+
if (value === null || typeof value !== "object")
|
|
77723
|
+
return JSON.stringify(value);
|
|
77724
|
+
if (Array.isArray(value))
|
|
77725
|
+
return `[${value.map(canonicalJson3).join(",")}]`;
|
|
77726
|
+
const record = value;
|
|
77727
|
+
const keys = Object.keys(record).filter((key) => record[key] !== undefined).sort();
|
|
77728
|
+
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalJson3(record[key])}`).join(",")}}`;
|
|
77729
|
+
}
|
|
77730
|
+
function toolDefinitionFingerprint(entry) {
|
|
77731
|
+
const canonical = canonicalJson3({
|
|
77732
|
+
name: entry.fqn,
|
|
77733
|
+
description: entry.description ?? null,
|
|
77734
|
+
inputSchema: entry.inputSchema ?? null
|
|
77735
|
+
});
|
|
77736
|
+
return createHash54("sha256").update(canonical).digest("hex");
|
|
77737
|
+
}
|
|
77707
77738
|
function buildFqn(server, rawName) {
|
|
77708
77739
|
return `${server}${FQN_DELIMITER}${rawName}`;
|
|
77709
77740
|
}
|
|
@@ -79640,7 +79671,7 @@ var init_shell_events = __esm(() => {
|
|
|
79640
79671
|
// src/lib/shell-permissions.ts
|
|
79641
79672
|
import { existsSync as existsSync32 } from "fs";
|
|
79642
79673
|
import path192 from "path";
|
|
79643
|
-
import { createHash as
|
|
79674
|
+
import { createHash as createHash55 } from "crypto";
|
|
79644
79675
|
function validateShellPattern(pattern) {
|
|
79645
79676
|
const trimmed = pattern.trim();
|
|
79646
79677
|
if (trimmed.length === 0) {
|
|
@@ -79847,7 +79878,7 @@ function shellPermissionsFingerprint(dir) {
|
|
|
79847
79878
|
if (!read.ok) {
|
|
79848
79879
|
return "";
|
|
79849
79880
|
}
|
|
79850
|
-
return
|
|
79881
|
+
return createHash55("sha256").update(read.text, "utf8").digest("hex");
|
|
79851
79882
|
} catch {
|
|
79852
79883
|
return "";
|
|
79853
79884
|
}
|
|
@@ -80716,11 +80747,23 @@ function renderUseToolApprovalLines(description, meta) {
|
|
|
80716
80747
|
if (meta?.destructive === true) {
|
|
80717
80748
|
lines.push(" this tool is treated as destructive \u2014 it is a third party's code");
|
|
80718
80749
|
}
|
|
80719
|
-
|
|
80720
|
-
lines.push(
|
|
80750
|
+
for (const notice of untrustedOriginNotices(meta)) {
|
|
80751
|
+
lines.push(` ${notice}`);
|
|
80721
80752
|
}
|
|
80722
80753
|
return lines;
|
|
80723
80754
|
}
|
|
80755
|
+
function untrustedOriginNotices(meta) {
|
|
80756
|
+
if (meta?.untrustedOrigin !== true)
|
|
80757
|
+
return [];
|
|
80758
|
+
const notices = ["\u26A0 follows untrusted external content \u2014 that content cannot authorize this call"];
|
|
80759
|
+
if (meta.mcpTrustWithheld === true) {
|
|
80760
|
+
notices.push("trust for this session is not offered: this turn contains external content");
|
|
80761
|
+
}
|
|
80762
|
+
return notices;
|
|
80763
|
+
}
|
|
80764
|
+
function mcpTrustOffered(meta, resolvable) {
|
|
80765
|
+
return meta?.mcpTrustAvailable === true && meta.untrustedOrigin !== true && meta.fingerprint !== undefined && resolvable;
|
|
80766
|
+
}
|
|
80724
80767
|
function summariseUseToolApproval(description) {
|
|
80725
80768
|
return `${description.tool} on ${description.server}`;
|
|
80726
80769
|
}
|
|
@@ -80733,6 +80776,7 @@ function isApprovalYes(answer) {
|
|
|
80733
80776
|
async function promptUseToolApproval(io, input, meta, resolve, style, gutter = "") {
|
|
80734
80777
|
const paint = style ?? { yellow: (t) => t, dim: (t) => t, green: (t) => t, red: (t) => t };
|
|
80735
80778
|
const described = describeUseToolApproval(input, resolve);
|
|
80779
|
+
const canTrust = mcpTrustOffered(meta, resolve?.(described.fqn) !== undefined);
|
|
80736
80780
|
const lines = renderUseToolApprovalLines(described, meta);
|
|
80737
80781
|
io.out(`
|
|
80738
80782
|
`);
|
|
@@ -80741,19 +80785,29 @@ async function promptUseToolApproval(io, input, meta, resolve, style, gutter = "
|
|
|
80741
80785
|
`);
|
|
80742
80786
|
}
|
|
80743
80787
|
io.out(`
|
|
80744
|
-
${gutter}${paint.dim("[y/N] ")}`);
|
|
80788
|
+
${gutter}${paint.dim(canTrust ? "[y/N/T=trust this tool for session] " : "[y/N] ")}`);
|
|
80745
80789
|
const answer = await io.readLine() ?? "";
|
|
80746
|
-
const
|
|
80747
|
-
|
|
80790
|
+
const trust = canTrust && /^t(rust)?$/i.test(answer.trim());
|
|
80791
|
+
const approved = trust || isApprovalYes(answer);
|
|
80792
|
+
io.out(approved ? paint.green(trust ? `approved \xB7 trusted for this session
|
|
80793
|
+
` : `approved
|
|
80748
80794
|
`) : paint.red(`denied
|
|
80749
80795
|
`));
|
|
80750
80796
|
if (!approved)
|
|
80751
80797
|
return false;
|
|
80752
|
-
return meta?.fingerprint !== undefined ? { approved: true, fingerprint: meta.fingerprint } : true;
|
|
80798
|
+
return meta?.fingerprint !== undefined ? { approved: true, fingerprint: meta.fingerprint, ...trust ? { trustMcpTool: true } : {} } : true;
|
|
80753
80799
|
}
|
|
80754
80800
|
function isDockApproval(id) {
|
|
80755
80801
|
return id === APPROVAL_ALLOW_ID;
|
|
80756
80802
|
}
|
|
80803
|
+
function mcpDockVerdict(id, canTrust, fingerprint) {
|
|
80804
|
+
if (isDockApproval(id))
|
|
80805
|
+
return true;
|
|
80806
|
+
if (id === "trust-mcp" && canTrust && fingerprint !== undefined) {
|
|
80807
|
+
return { approved: true, fingerprint, trustMcpTool: true };
|
|
80808
|
+
}
|
|
80809
|
+
return false;
|
|
80810
|
+
}
|
|
80757
80811
|
function catalogResolver(catalog) {
|
|
80758
80812
|
return (fqn) => {
|
|
80759
80813
|
if (catalog === undefined)
|
|
@@ -80762,8 +80816,15 @@ function catalogResolver(catalog) {
|
|
|
80762
80816
|
return entry === undefined ? undefined : { server: entry.server, tool: entry.rawName };
|
|
80763
80817
|
};
|
|
80764
80818
|
}
|
|
80819
|
+
function catalogFingerprintResolver(catalog) {
|
|
80820
|
+
return (fqn) => {
|
|
80821
|
+
const entry = catalog?.entries.find((candidate) => candidate.fqn === fqn);
|
|
80822
|
+
return entry === undefined ? undefined : toolDefinitionFingerprint(entry);
|
|
80823
|
+
};
|
|
80824
|
+
}
|
|
80765
80825
|
var FQN_SEPARATOR = "__", MAX_ARGUMENT_CHARS = 400, MAX_ARGUMENT_KEYS = 40, MAX_IDENTIFIER_CHARS = 80, APPROVAL_ALLOW_ID = "allow";
|
|
80766
80826
|
var init_approval_render = __esm(() => {
|
|
80827
|
+
init_catalog4();
|
|
80767
80828
|
init_config9();
|
|
80768
80829
|
init_tools2();
|
|
80769
80830
|
});
|
|
@@ -81793,7 +81854,7 @@ var init_child_model_request = __esm(() => {
|
|
|
81793
81854
|
});
|
|
81794
81855
|
|
|
81795
81856
|
// src/harness/tool/builtin/spawn-subagent-tool.ts
|
|
81796
|
-
import { createHash as
|
|
81857
|
+
import { createHash as createHash56, randomUUID as randomUUID24 } from "crypto";
|
|
81797
81858
|
import { execFile as execFile7 } from "child_process";
|
|
81798
81859
|
import { lstat as lstat13, mkdtemp as mkdtemp2, readFile as readFile91, realpath as realpath14, rm as rm13 } from "fs/promises";
|
|
81799
81860
|
import { tmpdir as tmpdir6 } from "os";
|
|
@@ -81871,7 +81932,7 @@ function readExternalRuntimeRequest(input) {
|
|
|
81871
81932
|
return raw.kind === "external" ? raw : undefined;
|
|
81872
81933
|
}
|
|
81873
81934
|
function sha2568(text) {
|
|
81874
|
-
return
|
|
81935
|
+
return createHash56("sha256").update(text).digest("hex");
|
|
81875
81936
|
}
|
|
81876
81937
|
async function resolveSubagentCwd(rawCwd, parentCwd) {
|
|
81877
81938
|
if (rawCwd === undefined) {
|
|
@@ -87253,7 +87314,7 @@ var init_http_headers = __esm(() => {
|
|
|
87253
87314
|
});
|
|
87254
87315
|
|
|
87255
87316
|
// src/mcp-servers/trust.ts
|
|
87256
|
-
import { createHash as
|
|
87317
|
+
import { createHash as createHash57 } from "crypto";
|
|
87257
87318
|
import path203 from "path";
|
|
87258
87319
|
function trustFile(configDir) {
|
|
87259
87320
|
return path203.join(configDir ?? ensureKeryxConfigDir(), "mcp-servers-trust.json");
|
|
@@ -87276,7 +87337,7 @@ function serverFingerprint(server) {
|
|
|
87276
87337
|
}
|
|
87277
87338
|
}
|
|
87278
87339
|
});
|
|
87279
|
-
return
|
|
87340
|
+
return createHash57("sha256").update(material).digest("hex").slice(0, 32);
|
|
87280
87341
|
}
|
|
87281
87342
|
function sortedKeys(values) {
|
|
87282
87343
|
return Object.entries(values ?? {}).sort(([a], [b]) => a.localeCompare(b));
|
|
@@ -114162,12 +114223,12 @@ var init_config11 = __esm(() => {
|
|
|
114162
114223
|
});
|
|
114163
114224
|
|
|
114164
114225
|
// src/wiki/deep-enrich.ts
|
|
114165
|
-
import { randomUUID as randomUUID31, createHash as
|
|
114226
|
+
import { randomUUID as randomUUID31, createHash as createHash58 } from "crypto";
|
|
114166
114227
|
function errorMessage2(cause) {
|
|
114167
114228
|
return cause instanceof Error ? cause.message : String(cause);
|
|
114168
114229
|
}
|
|
114169
114230
|
function sha256Hex7(text) {
|
|
114170
|
-
return
|
|
114231
|
+
return createHash58("sha256").update(text).digest("hex");
|
|
114171
114232
|
}
|
|
114172
114233
|
function buildDeepEnrichTools(port) {
|
|
114173
114234
|
const deepOps = METAPROJECT_OPERATIONS.filter((op) => DEEP_ENRICH_OPS.includes(op.name));
|
|
@@ -115768,7 +115829,10 @@ function createForegroundAgentIoFacade(owner, token, io) {
|
|
|
115768
115829
|
if (accepts())
|
|
115769
115830
|
io.onAutoApproved?.(tool, input, meta);
|
|
115770
115831
|
},
|
|
115771
|
-
permissionMode: () => accepts() ? io.permissionMode?.() ?? "ask" : "ask"
|
|
115832
|
+
permissionMode: () => accepts() ? io.permissionMode?.() ?? "ask" : "ask",
|
|
115833
|
+
...io.trustedMcpTools === undefined ? {} : { trustedMcpTools: io.trustedMcpTools },
|
|
115834
|
+
...io.mcpToolFingerprint === undefined ? {} : { mcpToolFingerprint: io.mcpToolFingerprint },
|
|
115835
|
+
readOnly: () => !accepts() || (io.readOnly?.() ?? false)
|
|
115772
115836
|
};
|
|
115773
115837
|
}
|
|
115774
115838
|
|
|
@@ -126594,6 +126658,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
126594
126658
|
}
|
|
126595
126659
|
if (isMcpToolCall(tool)) {
|
|
126596
126660
|
const described = describeUseToolApproval(inputJson, catalogResolver(deps.mcpRuntime?.()?.catalog()));
|
|
126661
|
+
const canTrustMcp = mcpTrustOffered(meta, catalogResolver(deps.mcpRuntime?.()?.catalog())(described.fqn) !== undefined);
|
|
126597
126662
|
transcript.add(new otui.TextRenderable(r, {
|
|
126598
126663
|
id: `ap${uid++}`,
|
|
126599
126664
|
content: otui.t`${roleChunk(otui, "attention", `\u2699 ${described.server} wants to run ${described.tool}`)}`
|
|
@@ -126607,6 +126672,9 @@ async function launchTuiAgentShell(opts) {
|
|
|
126607
126672
|
content: otui.t`${dimChunk(otui, ` \u2026 arguments truncated at ${MAX_ARGUMENT_CHARS} characters`)}`
|
|
126608
126673
|
}));
|
|
126609
126674
|
}
|
|
126675
|
+
for (const notice of untrustedOriginNotices(meta)) {
|
|
126676
|
+
transcript.add(new otui.TextRenderable(r, { id: `ap${uid++}`, content: otui.t`${dimChunk(otui, ` ${notice}`)}` }));
|
|
126677
|
+
}
|
|
126610
126678
|
chrome.hideMenu();
|
|
126611
126679
|
setMainAgent("blocked", "approval");
|
|
126612
126680
|
const id = await chrome.withOverlay(() => showComposerChoice(otui, r, chrome.dock, {
|
|
@@ -126617,17 +126685,19 @@ async function launchTuiAgentShell(opts) {
|
|
|
126617
126685
|
signal: foregroundOperation.signal,
|
|
126618
126686
|
options: [
|
|
126619
126687
|
{ id: APPROVAL_ALLOW_ID, label: "Approve", description: `run ${described.tool} on ${described.server}` },
|
|
126688
|
+
...canTrustMcp ? [{ id: "trust-mcp", label: "Trust this tool (this session)", description: `Skip future approvals for ${described.fqn} in trust mode` }] : [],
|
|
126620
126689
|
{ id: "deny", label: "Deny", description: "the tool call is refused", recommended: true }
|
|
126621
126690
|
]
|
|
126622
126691
|
}));
|
|
126623
126692
|
input.focus();
|
|
126624
|
-
const
|
|
126693
|
+
const verdict = mcpDockVerdict(id, canTrustMcp, meta?.fingerprint);
|
|
126694
|
+
const allowed = verdict !== false;
|
|
126625
126695
|
setMainAgent("running", allowed ? "write" : "denied");
|
|
126626
126696
|
transcript.add(new otui.TextRenderable(r, {
|
|
126627
126697
|
id: `ap${uid++}`,
|
|
126628
126698
|
content: allowed ? otui.t`${roleChunk(otui, "ok", `\u25C7 ${described.fqn} approved`)}` : otui.t`${roleChunk(otui, "error", `\u25C7 ${described.fqn} denied`)}`
|
|
126629
126699
|
}));
|
|
126630
|
-
return
|
|
126700
|
+
return verdict;
|
|
126631
126701
|
}
|
|
126632
126702
|
if (tool.startsWith(MCP_ELICITATION_TOOL_PREFIX)) {
|
|
126633
126703
|
const described = describeElicitationPrompt(tool, inputJson) ?? { message: inputJson, command: undefined };
|
|
@@ -126826,6 +126896,8 @@ async function launchTuiAgentShell(opts) {
|
|
|
126826
126896
|
const sessionCwd = opts.session?.cwd ?? process.cwd();
|
|
126827
126897
|
let permissionMode = opts.initialPermissionMode ?? getProjectPermissionMode(sessionCwd) ?? DEFAULT_PERMISSION_MODE;
|
|
126828
126898
|
io.permissionMode = () => permissionMode;
|
|
126899
|
+
io.trustedMcpTools = new Map;
|
|
126900
|
+
io.mcpToolFingerprint = (fqn) => catalogFingerprintResolver(deps.mcpRuntime?.()?.catalog())(fqn);
|
|
126829
126901
|
let readOnly = false;
|
|
126830
126902
|
io.readOnly = () => readOnly;
|
|
126831
126903
|
const paintModeRow = () => {
|
|
@@ -126872,6 +126944,7 @@ async function launchTuiAgentShell(opts) {
|
|
|
126872
126944
|
splash?.removeIfShown();
|
|
126873
126945
|
}
|
|
126874
126946
|
liveSession = opened.handle;
|
|
126947
|
+
io.trustedMcpTools?.clear();
|
|
126875
126948
|
history = previewHistory === true ? opened.history.slice(-SESSION_PREVIEW_MESSAGE_COUNT) : opened.history;
|
|
126876
126949
|
archive = opened.archive.length > 0 ? [...opened.archive] : [...opened.history];
|
|
126877
126950
|
nextArchiveIndex = history.length;
|
|
@@ -131492,6 +131565,8 @@ ${text.trim()}`;
|
|
|
131492
131565
|
const sessionsOn = sessionOpts !== undefined && sessionOpts.enabled !== false;
|
|
131493
131566
|
let permissionMode = initialPermissionMode ?? getProjectPermissionMode(sessionCwd) ?? DEFAULT_PERMISSION_MODE;
|
|
131494
131567
|
agentIo.permissionMode = () => permissionMode;
|
|
131568
|
+
agentIo.trustedMcpTools = new Map;
|
|
131569
|
+
agentIo.mcpToolFingerprint = (fqn) => catalogFingerprintResolver(deps.mcpRuntime?.()?.catalog())(fqn);
|
|
131495
131570
|
let reasoningSessionOverride;
|
|
131496
131571
|
let readOnly = false;
|
|
131497
131572
|
agentIo.readOnly = () => readOnly;
|
|
@@ -131549,6 +131624,7 @@ ${text.trim()}`;
|
|
|
131549
131624
|
try {
|
|
131550
131625
|
const next = switchLeasedSession(lease, () => openLeased({ cwd: sessionCwd, provider: deps.providerId, model: deps.modelId }));
|
|
131551
131626
|
holdLease(next.lease);
|
|
131627
|
+
agentIo.trustedMcpTools?.clear();
|
|
131552
131628
|
return next.handle;
|
|
131553
131629
|
} catch (cause) {
|
|
131554
131630
|
agentIo.onSystem?.(`${cause instanceof Error ? cause.message : String(cause)}
|
|
@@ -131893,6 +131969,7 @@ ${GUTTER}${turnSeparator()}
|
|
|
131893
131969
|
} else {
|
|
131894
131970
|
history = [];
|
|
131895
131971
|
archive = [];
|
|
131972
|
+
agentIo.trustedMcpTools?.clear();
|
|
131896
131973
|
agentIo.onSystem?.(`Conversation cleared.
|
|
131897
131974
|
`);
|
|
131898
131975
|
}
|
|
@@ -132822,6 +132899,7 @@ Example: keryx shell --provider ollama --model llama3.1:latest`);
|
|
|
132822
132899
|
}),
|
|
132823
132900
|
idSeq: () => randomUUID34(),
|
|
132824
132901
|
askUser: invokeAskUserHost,
|
|
132902
|
+
mcpRuntime: () => mcpRuntime,
|
|
132825
132903
|
sweepBackgroundJobs: () => jobRegistry.sweepAll(),
|
|
132826
132904
|
...resetSubagentBudget !== undefined ? { resetSubagentBudget } : {},
|
|
132827
132905
|
...Object.keys(initialModelParams).length > 0 ? { modelParams: initialModelParams } : {},
|
|
@@ -133361,7 +133439,7 @@ var init_retired_rules = __esm(() => {
|
|
|
133361
133439
|
// src/gdskills/guarded-fs-ops.ts
|
|
133362
133440
|
import { cp, lstat as lstat14, readFile as readFile129, readdir as readdir44, realpath as realpath15, unlink as unlink2 } from "fs/promises";
|
|
133363
133441
|
import { existsSync as existsSync42 } from "fs";
|
|
133364
|
-
import { createHash as
|
|
133442
|
+
import { createHash as createHash59 } from "crypto";
|
|
133365
133443
|
import path258 from "path";
|
|
133366
133444
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
133367
133445
|
function isErrnoException(error) {
|
|
@@ -133555,7 +133633,7 @@ async function removeUnmodifiedRetiredRules(rulesTarget, fsOps = { unlink: unlin
|
|
|
133555
133633
|
}
|
|
133556
133634
|
stage = "read";
|
|
133557
133635
|
const content = await readFile129(installedPath);
|
|
133558
|
-
const hash =
|
|
133636
|
+
const hash = createHash59("sha256").update(normalizeRetiredRuleContent(content)).digest("hex");
|
|
133559
133637
|
if (retired.shippedSha256.includes(hash)) {
|
|
133560
133638
|
stage = "unlink";
|
|
133561
133639
|
await fsOps.unlink(installedPath);
|
|
@@ -144007,7 +144085,7 @@ var init_authoring_lint = __esm(() => {
|
|
|
144007
144085
|
});
|
|
144008
144086
|
|
|
144009
144087
|
// src/gdskills/governance/stocktake.ts
|
|
144010
|
-
import { createHash as
|
|
144088
|
+
import { createHash as createHash60 } from "crypto";
|
|
144011
144089
|
import { existsSync as existsSync46, readdirSync as readdirSync11, readFileSync as readFileSync22, statSync as statSync16 } from "fs";
|
|
144012
144090
|
import path279 from "path";
|
|
144013
144091
|
function cacheKeyMatches(cached, inputs, quick) {
|
|
@@ -144015,7 +144093,7 @@ function cacheKeyMatches(cached, inputs, quick) {
|
|
|
144015
144093
|
}
|
|
144016
144094
|
function catalogFingerprint(catalog) {
|
|
144017
144095
|
const parts = [...catalog].map((entry) => `${entry.id}:${entry.sha256}`).sort();
|
|
144018
|
-
return
|
|
144096
|
+
return createHash60("sha256").update(parts.join(`
|
|
144019
144097
|
`)).digest("hex");
|
|
144020
144098
|
}
|
|
144021
144099
|
function verificationReportHash(root, entry) {
|
|
@@ -144023,7 +144101,7 @@ function verificationReportHash(root, entry) {
|
|
|
144023
144101
|
if (!existsSync46(reportPath))
|
|
144024
144102
|
return null;
|
|
144025
144103
|
try {
|
|
144026
|
-
return
|
|
144104
|
+
return createHash60("sha256").update(readFileSync22(reportPath, "utf8")).digest("hex");
|
|
144027
144105
|
} catch {
|
|
144028
144106
|
return null;
|
|
144029
144107
|
}
|
|
@@ -144045,7 +144123,7 @@ function referencesHash(entry) {
|
|
|
144045
144123
|
}
|
|
144046
144124
|
};
|
|
144047
144125
|
walk(referencesDir, "");
|
|
144048
|
-
const hash =
|
|
144126
|
+
const hash = createHash60("sha256");
|
|
144049
144127
|
for (const rel of files) {
|
|
144050
144128
|
hash.update(rel);
|
|
144051
144129
|
hash.update("\x00");
|
|
@@ -145492,7 +145570,7 @@ var init_glob = __esm(() => {
|
|
|
145492
145570
|
});
|
|
145493
145571
|
|
|
145494
145572
|
// src/gdskills/manifest/plan.ts
|
|
145495
|
-
import { createHash as
|
|
145573
|
+
import { createHash as createHash61 } from "crypto";
|
|
145496
145574
|
import path283 from "path";
|
|
145497
145575
|
function destinationRootsForTarget(target) {
|
|
145498
145576
|
if (target === "claude")
|
|
@@ -145504,7 +145582,7 @@ function destinationRootsForTarget(target) {
|
|
|
145504
145582
|
}
|
|
145505
145583
|
function stackInputsSha256(stack) {
|
|
145506
145584
|
const { detectedAt: _detectedAt, ...rest } = stack;
|
|
145507
|
-
return
|
|
145585
|
+
return createHash61("sha256").update(stableStringify3(rest)).digest("hex");
|
|
145508
145586
|
}
|
|
145509
145587
|
function stableStringify3(value) {
|
|
145510
145588
|
if (Array.isArray(value)) {
|
|
@@ -163952,7 +164030,7 @@ var init_detect3 = __esm(() => {
|
|
|
163952
164030
|
});
|
|
163953
164031
|
|
|
163954
164032
|
// src/stack/service.ts
|
|
163955
|
-
import { createHash as
|
|
164033
|
+
import { createHash as createHash62 } from "crypto";
|
|
163956
164034
|
import { readFile as readFile162 } from "fs/promises";
|
|
163957
164035
|
import path316 from "path";
|
|
163958
164036
|
function stackJsonPath(root) {
|
|
@@ -163978,7 +164056,7 @@ function serializeStackDetection(doc) {
|
|
|
163978
164056
|
}
|
|
163979
164057
|
function fingerprintOf(core) {
|
|
163980
164058
|
const canonical = JSON.stringify(canonicalize2(core));
|
|
163981
|
-
return
|
|
164059
|
+
return createHash62("sha256").update(canonical, "utf8").digest("hex");
|
|
163982
164060
|
}
|
|
163983
164061
|
async function readStackDetection(root) {
|
|
163984
164062
|
try {
|
|
@@ -164252,9 +164330,9 @@ function evaluateCompletion(input, deps) {
|
|
|
164252
164330
|
var SCHEMA_VERSION3 = 1;
|
|
164253
164331
|
|
|
164254
164332
|
// src/harness/evidence/redaction.ts
|
|
164255
|
-
import { createHash as
|
|
164333
|
+
import { createHash as createHash63 } from "crypto";
|
|
164256
164334
|
function hashContent(content) {
|
|
164257
|
-
return
|
|
164335
|
+
return createHash63("sha256").update(content, "utf8").digest("hex");
|
|
164258
164336
|
}
|
|
164259
164337
|
function redactForPersistence(content, deps) {
|
|
164260
164338
|
const scan = deps.scan(content);
|
|
@@ -164304,7 +164382,7 @@ async function metaprojectBlastRadius(port, target) {
|
|
|
164304
164382
|
}
|
|
164305
164383
|
|
|
164306
164384
|
// src/harness/session/session.ts
|
|
164307
|
-
import { createHash as
|
|
164385
|
+
import { createHash as createHash64 } from "crypto";
|
|
164308
164386
|
function canonicalStringify(value) {
|
|
164309
164387
|
if (Array.isArray(value)) {
|
|
164310
164388
|
return `[${value.map(canonicalStringify).join(",")}]`;
|
|
@@ -164317,7 +164395,7 @@ function canonicalStringify(value) {
|
|
|
164317
164395
|
return JSON.stringify(value) ?? "null";
|
|
164318
164396
|
}
|
|
164319
164397
|
function sha2569(input) {
|
|
164320
|
-
return
|
|
164398
|
+
return createHash64("sha256").update(input, "utf8").digest("hex");
|
|
164321
164399
|
}
|
|
164322
164400
|
function deepFreeze(value) {
|
|
164323
164401
|
if (value !== null && typeof value === "object") {
|
|
@@ -164461,7 +164539,7 @@ var init_startup = __esm(() => {
|
|
|
164461
164539
|
});
|
|
164462
164540
|
|
|
164463
164541
|
// src/harness/run/run.ts
|
|
164464
|
-
import { createHash as
|
|
164542
|
+
import { createHash as createHash65 } from "crypto";
|
|
164465
164543
|
function aliasRunHookToolName(keryxToolName) {
|
|
164466
164544
|
return RUN_HOOK_TOOL_NAME_ALIASES[keryxToolName] ?? keryxToolName;
|
|
164467
164545
|
}
|
|
@@ -164477,7 +164555,7 @@ function canonicalize3(value) {
|
|
|
164477
164555
|
return `{${keys.map((key) => `${JSON.stringify(key)}:${canonicalize3(record[key])}`).join(",")}}`;
|
|
164478
164556
|
}
|
|
164479
164557
|
function sha25610(input) {
|
|
164480
|
-
return
|
|
164558
|
+
return createHash65("sha256").update(input, "utf8").digest("hex");
|
|
164481
164559
|
}
|
|
164482
164560
|
function uniqueInOrder2(values) {
|
|
164483
164561
|
const seen = new Set;
|
|
@@ -165052,7 +165130,7 @@ var init_replay = __esm(() => {
|
|
|
165052
165130
|
});
|
|
165053
165131
|
|
|
165054
165132
|
// src/harness/tool/registry.ts
|
|
165055
|
-
import { createHash as
|
|
165133
|
+
import { createHash as createHash66 } from "crypto";
|
|
165056
165134
|
function canonicalize4(value) {
|
|
165057
165135
|
if (value === null || typeof value !== "object") {
|
|
165058
165136
|
return JSON.stringify(value) ?? "null";
|
|
@@ -165066,7 +165144,7 @@ function canonicalize4(value) {
|
|
|
165066
165144
|
return `{${entries.join(",")}}`;
|
|
165067
165145
|
}
|
|
165068
165146
|
function sha25611(input) {
|
|
165069
|
-
return
|
|
165147
|
+
return createHash66("sha256").update(input, "utf8").digest("hex");
|
|
165070
165148
|
}
|
|
165071
165149
|
function definitionHash(definition) {
|
|
165072
165150
|
return sha25611(canonicalize4(definition));
|
|
@@ -165219,9 +165297,9 @@ var init_executor = __esm(() => {
|
|
|
165219
165297
|
|
|
165220
165298
|
// src/harness/process/real-process-adapter.ts
|
|
165221
165299
|
import { spawnSync as spawnSync8 } from "child_process";
|
|
165222
|
-
import { createHash as
|
|
165300
|
+
import { createHash as createHash67 } from "crypto";
|
|
165223
165301
|
function sha256Hex8(input) {
|
|
165224
|
-
return
|
|
165302
|
+
return createHash67("sha256").update(input, "utf8").digest("hex");
|
|
165225
165303
|
}
|
|
165226
165304
|
function byteLength2(chunk) {
|
|
165227
165305
|
if (chunk === null || chunk === undefined)
|
|
@@ -166979,7 +167057,7 @@ var init_session3 = __esm(() => {
|
|
|
166979
167057
|
});
|
|
166980
167058
|
|
|
166981
167059
|
// src/acp/session-mcp.ts
|
|
166982
|
-
import { createHash as
|
|
167060
|
+
import { createHash as createHash68 } from "crypto";
|
|
166983
167061
|
function isRecord6(value) {
|
|
166984
167062
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
166985
167063
|
}
|
|
@@ -167106,7 +167184,7 @@ function acpMcpSetKey(parsed) {
|
|
|
167106
167184
|
})),
|
|
167107
167185
|
refused: parsed.refused
|
|
167108
167186
|
};
|
|
167109
|
-
return
|
|
167187
|
+
return createHash68("sha256").update(JSON.stringify(canonical)).digest("hex");
|
|
167110
167188
|
}
|
|
167111
167189
|
function startAcpSessionMcp(parsed, options = {}) {
|
|
167112
167190
|
const refused = parsed.refused.map((problem) => ({ name: problem.name, reason: scrub(problem.reason, parsed.secrets) }));
|
|
@@ -168985,7 +169063,7 @@ var init_modules = __esm(() => {
|
|
|
168985
169063
|
});
|
|
168986
169064
|
|
|
168987
169065
|
// src/lib/serve-credential.ts
|
|
168988
|
-
import { createHash as
|
|
169066
|
+
import { createHash as createHash69, randomBytes as randomBytes11, randomUUID as randomUUID43 } from "crypto";
|
|
168989
169067
|
import {
|
|
168990
169068
|
chmodSync as chmodSync5,
|
|
168991
169069
|
closeSync as closeSync7,
|
|
@@ -169012,10 +169090,10 @@ function constantTimeEqual(a, b) {
|
|
|
169012
169090
|
return difference === 0;
|
|
169013
169091
|
}
|
|
169014
169092
|
function hashToken(salt, token) {
|
|
169015
|
-
return
|
|
169093
|
+
return createHash69("sha256").update(Buffer.from(salt, "hex")).update(Buffer.from(token, "utf8")).digest("hex");
|
|
169016
169094
|
}
|
|
169017
169095
|
function credentialFingerprint(record) {
|
|
169018
|
-
return
|
|
169096
|
+
return createHash69("sha256").update(`keryx-serve-fingerprint:${record.hash}`).digest("hex").slice(0, 8);
|
|
169019
169097
|
}
|
|
169020
169098
|
function isValidRecord(value) {
|
|
169021
169099
|
if (typeof value !== "object" || value === null) {
|
|
@@ -169229,7 +169307,7 @@ var init_serve_throttle = __esm(() => {
|
|
|
169229
169307
|
});
|
|
169230
169308
|
|
|
169231
169309
|
// src/lib/serve-turn-store.ts
|
|
169232
|
-
import { createHash as
|
|
169310
|
+
import { createHash as createHash70 } from "crypto";
|
|
169233
169311
|
import { existsSync as existsSync50, readdirSync as readdirSync12, rmSync as rmSync4 } from "fs";
|
|
169234
169312
|
import path321 from "path";
|
|
169235
169313
|
function turnsRoot(dir) {
|
|
@@ -169240,11 +169318,11 @@ function turnDir(turnId, dir) {
|
|
|
169240
169318
|
}
|
|
169241
169319
|
function keyPath(project, idempotencyKey, dir) {
|
|
169242
169320
|
const projectBytes = Buffer.byteLength(project, "utf8");
|
|
169243
|
-
const digest =
|
|
169321
|
+
const digest = createHash70("sha256").update(`${projectBytes}:${project}\x00${idempotencyKey}`, "utf8").digest("hex");
|
|
169244
169322
|
return path321.join(turnsRoot(dir), "keys", `${digest}.json`);
|
|
169245
169323
|
}
|
|
169246
169324
|
function legacyKeyPath(idempotencyKey, dir) {
|
|
169247
|
-
const digest =
|
|
169325
|
+
const digest = createHash70("sha256").update(idempotencyKey, "utf8").digest("hex");
|
|
169248
169326
|
return path321.join(turnsRoot(dir), "keys", `${digest}.json`);
|
|
169249
169327
|
}
|
|
169250
169328
|
function adoptLegacyClaim(project, idempotencyKey, dir) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.27",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|