@antonbabenko/deliberation-mcp 3.6.2 → 3.7.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/index.js +41 -45
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -241,7 +241,10 @@ var require_provider = __commonJS({
|
|
|
241
241
|
var STRIP_TRAIL = /[*_`~\s]+$/;
|
|
242
242
|
var HEADING_RE = /^#{1,6}\s/;
|
|
243
243
|
function normVerdict(tok) {
|
|
244
|
-
return
|
|
244
|
+
return (
|
|
245
|
+
/** @type {any} */
|
|
246
|
+
tok.replace(/\s+/g, "_").toUpperCase()
|
|
247
|
+
);
|
|
245
248
|
}
|
|
246
249
|
function parseReview(text) {
|
|
247
250
|
const raw = safeString(text);
|
|
@@ -259,36 +262,24 @@ var require_provider = __commonJS({
|
|
|
259
262
|
function resolveVerdict(lines) {
|
|
260
263
|
for (const ln of lines) {
|
|
261
264
|
const m = ln.match(SENTINEL_RE);
|
|
262
|
-
if (m) return (
|
|
263
|
-
/** @type {any} */
|
|
264
|
-
normVerdict(m[1])
|
|
265
|
-
);
|
|
265
|
+
if (m) return normVerdict(m[1]);
|
|
266
266
|
}
|
|
267
267
|
for (const ln of lines) {
|
|
268
268
|
const m = ln.match(VERDICT_RE);
|
|
269
|
-
if (m) return (
|
|
270
|
-
/** @type {any} */
|
|
271
|
-
normVerdict(m[1])
|
|
272
|
-
);
|
|
269
|
+
if (m) return normVerdict(m[1]);
|
|
273
270
|
}
|
|
274
271
|
for (let i = 0; i < lines.length; i++) {
|
|
275
272
|
if (!VERDICT_WORD_RE.test(lines[i].trim())) continue;
|
|
276
273
|
for (let j = i + 1; j < lines.length && j <= i + 3; j++) {
|
|
277
274
|
const t = lines[j].replace(MD_EMPHASIS, "").trim();
|
|
278
275
|
if (!t) continue;
|
|
279
|
-
if (TOKEN_LINE_RE.test(t)) return (
|
|
280
|
-
/** @type {any} */
|
|
281
|
-
normVerdict(t)
|
|
282
|
-
);
|
|
276
|
+
if (TOKEN_LINE_RE.test(t)) return normVerdict(t);
|
|
283
277
|
break;
|
|
284
278
|
}
|
|
285
279
|
}
|
|
286
280
|
const nonEmpty = lines.map((l) => l.replace(MD_EMPHASIS, "").trim()).filter((t) => t !== "");
|
|
287
281
|
for (const t of [nonEmpty[0], nonEmpty[nonEmpty.length - 1]]) {
|
|
288
|
-
if (t && TOKEN_LINE_RE.test(t)) return (
|
|
289
|
-
/** @type {any} */
|
|
290
|
-
normVerdict(t)
|
|
291
|
-
);
|
|
282
|
+
if (t && TOKEN_LINE_RE.test(t)) return normVerdict(t);
|
|
292
283
|
}
|
|
293
284
|
return null;
|
|
294
285
|
}
|
|
@@ -345,6 +336,7 @@ var require_consensus_loop = __commonJS({
|
|
|
345
336
|
"use strict";
|
|
346
337
|
var MAX_ROUNDS_DEFAULT = 5;
|
|
347
338
|
var VERDICTS = Object.freeze(["APPROVE", "REQUEST_CHANGES", "REJECT"]);
|
|
339
|
+
var REVIEW_FORMAT_INSTRUCTION = "End with a line by itself in exactly this form (no markdown, token on the SAME line): VERDICT: APPROVE (or VERDICT: REQUEST_CHANGES, or VERDICT: REJECT). Then list any critical issues, one per line as: - [category] description where category is one of security, correctness, scope, ambiguity, performance, ops.";
|
|
348
340
|
function assertStatus(state, expected, op) {
|
|
349
341
|
if (state.status !== expected) {
|
|
350
342
|
throw new Error(`${op}: expected status '${expected}', got '${state.status}'`);
|
|
@@ -387,12 +379,12 @@ ${state.currentPlan}`
|
|
|
387
379
|
const peerPrompt = [
|
|
388
380
|
body,
|
|
389
381
|
"Review the plan for correctness, security, scope, ambiguity, performance, and ops gaps.",
|
|
390
|
-
|
|
382
|
+
REVIEW_FORMAT_INSTRUCTION
|
|
391
383
|
].join("\n\n");
|
|
392
384
|
const blindPrompt = [
|
|
393
385
|
body,
|
|
394
386
|
"Give your own independent verdict BEFORE seeing peer opinions.",
|
|
395
|
-
|
|
387
|
+
REVIEW_FORMAT_INSTRUCTION
|
|
396
388
|
].join("\n\n");
|
|
397
389
|
return { peerPrompt, blindPrompt };
|
|
398
390
|
}
|
|
@@ -1699,24 +1691,27 @@ var require_antigravity = __commonJS({
|
|
|
1699
1691
|
);
|
|
1700
1692
|
if (!bridge) throw new Error("makeAntigravityProvider requires opts.bridge (core is transport-agnostic; inject the gemini bridge)");
|
|
1701
1693
|
const model = opts.model || process.env.GEMINI_DEFAULT_MODEL || "auto-gemini-3";
|
|
1694
|
+
const allowImplement = opts.allowImplement === true;
|
|
1702
1695
|
return {
|
|
1703
1696
|
name: "gemini",
|
|
1704
|
-
|
|
1697
|
+
// canImplement reflects the construction lock so discovery (panel) is honest about THIS process.
|
|
1698
|
+
capabilities: { canImplement: allowImplement, fileUpload: false, multiTurn: true, walksFilesystem: true },
|
|
1705
1699
|
async health() {
|
|
1706
1700
|
return typeof bridge.runGemini === "function" ? { ok: true } : { ok: false, reason: "agy bridge unavailable" };
|
|
1707
1701
|
},
|
|
1708
1702
|
async ask(req) {
|
|
1709
1703
|
const started = Date.now();
|
|
1704
|
+
const implement = allowImplement && req.mode === "implement";
|
|
1710
1705
|
const includeDirs = (req.files || []).filter((f) => f.dir).map((f) => f.dir);
|
|
1711
1706
|
const args = bridge.buildAgyArgs({
|
|
1712
1707
|
prompt: req.prompt,
|
|
1713
1708
|
model,
|
|
1714
|
-
sandbox: "read-only",
|
|
1709
|
+
sandbox: implement ? "workspace-write" : "read-only",
|
|
1715
1710
|
developerInstructions: req.developerInstructions,
|
|
1716
1711
|
includeDirs
|
|
1717
1712
|
});
|
|
1718
1713
|
try {
|
|
1719
|
-
const out = await bridge.runGemini(args, req.cwd, req.timeoutMs, void 0, { readOnly:
|
|
1714
|
+
const out = await bridge.runGemini(args, req.cwd, req.timeoutMs, void 0, { readOnly: !implement, includeDirs });
|
|
1720
1715
|
return { provider: "gemini", model, text: out.response || "", threadId: out.threadId, isError: false, ms: Date.now() - started, reasoningEffort: null, ...out.workspaceMutated ? { workspaceMutated: true } : {} };
|
|
1721
1716
|
} catch (e) {
|
|
1722
1717
|
const err = (
|
|
@@ -1751,12 +1746,13 @@ var require_codex = __commonJS({
|
|
|
1751
1746
|
if (s.includes("rate")) return { errorKind: "rate-limit", retryable: true };
|
|
1752
1747
|
return { errorKind: "unknown", retryable: false };
|
|
1753
1748
|
}
|
|
1754
|
-
function codexExecArgs() {
|
|
1755
|
-
|
|
1749
|
+
function codexExecArgs(mode) {
|
|
1750
|
+
const sandbox = mode === "implement" ? "workspace-write" : "read-only";
|
|
1751
|
+
return ["exec", "--sandbox", sandbox, "--skip-git-repo-check"];
|
|
1756
1752
|
}
|
|
1757
|
-
function defaultRun({ prompt, cwd, timeoutMs }) {
|
|
1753
|
+
function defaultRun({ prompt, cwd, timeoutMs, mode }) {
|
|
1758
1754
|
return new Promise((resolve) => {
|
|
1759
|
-
const child = spawn("codex", codexExecArgs(), { cwd: cwd || process.cwd() });
|
|
1755
|
+
const child = spawn("codex", codexExecArgs(mode), { cwd: cwd || process.cwd() });
|
|
1760
1756
|
let stdout = "", stderr = "", settled = false;
|
|
1761
1757
|
const timer = timeoutMs ? setTimeout(() => child.kill("SIGKILL"), timeoutMs) : null;
|
|
1762
1758
|
if (timer) timer.unref();
|
|
@@ -1780,21 +1776,24 @@ var require_codex = __commonJS({
|
|
|
1780
1776
|
function makeCodexProvider(opts = {}) {
|
|
1781
1777
|
const run = opts.run || defaultRun;
|
|
1782
1778
|
const model = opts.model || "default";
|
|
1779
|
+
const allowImplement = opts.allowImplement === true;
|
|
1783
1780
|
return {
|
|
1784
1781
|
name: "codex",
|
|
1785
|
-
|
|
1786
|
-
// Option A: no threadId continuity
|
|
1782
|
+
// canImplement reflects the construction lock so discovery (panel) is honest about THIS
|
|
1783
|
+
// process. Option A: no threadId continuity (multiTurn:false).
|
|
1784
|
+
capabilities: { canImplement: allowImplement, fileUpload: false, multiTurn: false, walksFilesystem: true },
|
|
1787
1785
|
async health() {
|
|
1788
1786
|
return { ok: true };
|
|
1789
1787
|
},
|
|
1790
1788
|
async ask(req) {
|
|
1791
1789
|
const started = Date.now();
|
|
1790
|
+
const mode = allowImplement && req.mode === "implement" ? "implement" : "advisory";
|
|
1792
1791
|
const full = req.developerInstructions ? `${req.developerInstructions}
|
|
1793
1792
|
|
|
1794
1793
|
---
|
|
1795
1794
|
|
|
1796
1795
|
${req.prompt}` : req.prompt;
|
|
1797
|
-
const { code, stdout, stderr } = await run({ prompt: full, cwd: req.cwd, timeoutMs: req.timeoutMs });
|
|
1796
|
+
const { code, stdout, stderr } = await run({ prompt: full, cwd: req.cwd, timeoutMs: req.timeoutMs, mode });
|
|
1798
1797
|
if (code === 0) {
|
|
1799
1798
|
return { provider: "codex", model, text: stdout.trim(), isError: false, ms: Date.now() - started, reasoningEffort: null };
|
|
1800
1799
|
}
|
|
@@ -2225,7 +2224,7 @@ ${prompt}`;
|
|
|
2225
2224
|
args.push("-p", prompt);
|
|
2226
2225
|
return args;
|
|
2227
2226
|
}
|
|
2228
|
-
var ADVISORY_ENV_SCRUB = ["
|
|
2227
|
+
var ADVISORY_ENV_SCRUB = ["GIT_ASKPASS", "SSH_AUTH_SOCK"];
|
|
2229
2228
|
var CREDENTIAL_NAME_RE = /(?:^|_)(?:KEY|TOKEN|SECRET|SECRETS|PASSWORD|PASSWD|CREDENTIAL|CREDENTIALS)$|API_KEY|ACCESS_KEY|SESSION_TOKEN|PRIVATE_KEY/i;
|
|
2230
2229
|
function advisoryEnv(env) {
|
|
2231
2230
|
const out = { ...env };
|
|
@@ -2397,7 +2396,10 @@ ${prompt}`;
|
|
|
2397
2396
|
process.stderr.write("[deliberation] agy read-only run wrapped in sandbox-exec (workspace writes denied)\n");
|
|
2398
2397
|
}
|
|
2399
2398
|
const agyProcess = spawn(spawnPlan.cmd, spawnPlan.argv, {
|
|
2400
|
-
|
|
2399
|
+
// Scrub credentials in BOTH read-only and workspace-write runs. A write run
|
|
2400
|
+
// legitimately mutates the worktree but still has no need for the operator's
|
|
2401
|
+
// API keys / GIT_ASKPASS / SSH_AUTH_SOCK - the human commits and pushes, not agy.
|
|
2402
|
+
env: advisoryEnv(process.env),
|
|
2401
2403
|
shell: false,
|
|
2402
2404
|
cwd: effCwd,
|
|
2403
2405
|
// agy -p (print mode) waits for stdin EOF before returning; if the stdin
|
|
@@ -3045,6 +3047,12 @@ var require_glob = __commonJS({
|
|
|
3045
3047
|
for (const c of res) if (c.re.test(rel)) return true;
|
|
3046
3048
|
return false;
|
|
3047
3049
|
}
|
|
3050
|
+
function pushFile(rel, abs, size) {
|
|
3051
|
+
files.push({ rel, abs, size });
|
|
3052
|
+
totalBytes += size;
|
|
3053
|
+
if (files.length > maxFiles) throw new Error(`directory expansion exceeded maxFiles=${maxFiles}. Narrow include or raise the limit.`);
|
|
3054
|
+
if (totalBytes > maxBytes) throw new Error(`directory expansion exceeded maxBytes=${maxBytes} bytes. Narrow include or raise the limit.`);
|
|
3055
|
+
}
|
|
3048
3056
|
function descend(absDir, relDir) {
|
|
3049
3057
|
let entries;
|
|
3050
3058
|
try {
|
|
@@ -3076,10 +3084,7 @@ var require_glob = __commonJS({
|
|
|
3076
3084
|
if (!st.isFile()) continue;
|
|
3077
3085
|
if (matches(excludeRes, relPosix)) continue;
|
|
3078
3086
|
if (!matches(includeRes, relPosix)) continue;
|
|
3079
|
-
|
|
3080
|
-
totalBytes += st.size;
|
|
3081
|
-
if (files.length > maxFiles) throw new Error(`directory expansion exceeded maxFiles=${maxFiles}. Narrow include or raise the limit.`);
|
|
3082
|
-
if (totalBytes > maxBytes) throw new Error(`directory expansion exceeded maxBytes=${maxBytes} bytes. Narrow include or raise the limit.`);
|
|
3087
|
+
pushFile(relPosix, realTarget, st.size);
|
|
3083
3088
|
} else if (ent.isDirectory()) {
|
|
3084
3089
|
if (matches(excludeRes, relPosix) || matches(excludeRes, relPosix + "/**")) continue;
|
|
3085
3090
|
descend(absChild, relPosix);
|
|
@@ -3092,20 +3097,11 @@ var require_glob = __commonJS({
|
|
|
3092
3097
|
} catch (_) {
|
|
3093
3098
|
continue;
|
|
3094
3099
|
}
|
|
3095
|
-
|
|
3096
|
-
totalBytes += st.size;
|
|
3097
|
-
if (files.length > maxFiles) throw new Error(`directory expansion exceeded maxFiles=${maxFiles}. Narrow include or raise the limit.`);
|
|
3098
|
-
if (totalBytes > maxBytes) throw new Error(`directory expansion exceeded maxBytes=${maxBytes} bytes. Narrow include or raise the limit.`);
|
|
3100
|
+
pushFile(relPosix, absChild, st.size);
|
|
3099
3101
|
}
|
|
3100
3102
|
}
|
|
3101
3103
|
}
|
|
3102
3104
|
descend(rootAbs, "");
|
|
3103
|
-
if (files.length > maxFiles) {
|
|
3104
|
-
throw new Error(`directory expansion selected ${files.length} files; exceeds maxFiles=${maxFiles}. Narrow include or raise the limit.`);
|
|
3105
|
-
}
|
|
3106
|
-
if (totalBytes > maxBytes) {
|
|
3107
|
-
throw new Error(`directory expansion selected ${totalBytes} bytes; exceeds maxBytes=${maxBytes}. Narrow include or raise the limit.`);
|
|
3108
|
-
}
|
|
3109
3105
|
files.sort((a, b) => a.rel.localeCompare(b.rel, "en"));
|
|
3110
3106
|
return { files, totalBytes };
|
|
3111
3107
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antonbabenko/deliberation-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "Deliberation for Claude Code and any MCP host - GPT, Gemini, Grok, and OpenRouter expert subagents.",
|
|
5
5
|
"mcpName": "io.github.antonbabenko/deliberation",
|
|
6
6
|
"repository": { "type": "git", "url": "git+https://github.com/antonbabenko/deliberation.git", "directory": "server/mcp" },
|