@antonbabenko/deliberation-mcp 3.5.4 → 3.6.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 +78 -21
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -520,7 +520,14 @@ var require_orchestrate = __commonJS({
|
|
|
520
520
|
} catch {
|
|
521
521
|
}
|
|
522
522
|
}
|
|
523
|
-
|
|
523
|
+
function withOrientation(provider, req, orientationFiles) {
|
|
524
|
+
if (Array.isArray(orientationFiles) && orientationFiles.length && !(Array.isArray(req.files) && req.files.length) && provider.capabilities && provider.capabilities.walksFilesystem === false) {
|
|
525
|
+
return { ...req, files: orientationFiles };
|
|
526
|
+
}
|
|
527
|
+
return req;
|
|
528
|
+
}
|
|
529
|
+
async function callProvider(provider, req, logger, tool, cache, orientationFiles) {
|
|
530
|
+
req = withOrientation(provider, req, orientationFiles);
|
|
524
531
|
const useCache = cache && !(Array.isArray(req.files) && req.files.length);
|
|
525
532
|
if (useCache) {
|
|
526
533
|
const hit = cache.get(provider.name, req);
|
|
@@ -553,7 +560,7 @@ var require_orchestrate = __commonJS({
|
|
|
553
560
|
const logger = opts.logger || NULL_LOGGER;
|
|
554
561
|
const tool = opts.tool || "ask-all";
|
|
555
562
|
const settled = await Promise.allSettled(
|
|
556
|
-
providers.map((p) => callProvider(p, req, logger, tool, opts.cache))
|
|
563
|
+
providers.map((p) => callProvider(p, req, logger, tool, opts.cache, opts.orientationFiles))
|
|
557
564
|
);
|
|
558
565
|
return settled.map(
|
|
559
566
|
(s, i) => s.status === "fulfilled" ? s.value : {
|
|
@@ -568,7 +575,7 @@ var require_orchestrate = __commonJS({
|
|
|
568
575
|
);
|
|
569
576
|
}
|
|
570
577
|
async function askOne2(provider, req, opts = {}) {
|
|
571
|
-
return callProvider(provider, req, opts.logger || NULL_LOGGER, opts.tool || "ask-one", opts.cache);
|
|
578
|
+
return callProvider(provider, req, opts.logger || NULL_LOGGER, opts.tool || "ask-one", opts.cache, opts.orientationFiles);
|
|
572
579
|
}
|
|
573
580
|
function buildArbiterPrompt(question, opinions) {
|
|
574
581
|
const blocks = opinions.map((o, i) => `### Opinion ${i + 1}
|
|
@@ -593,17 +600,17 @@ ${blocks}`,
|
|
|
593
600
|
// Promise.resolve().then(...) so even a SYNCHRONOUS throw in ask() is caught
|
|
594
601
|
// by the rejection handler (a bare arbiter.ask() could throw before awaiting).
|
|
595
602
|
Promise.resolve().then(
|
|
596
|
-
() => arbiter.ask({
|
|
603
|
+
() => arbiter.ask(withOrientation(arbiter, {
|
|
597
604
|
...req,
|
|
598
605
|
files: req.files ? req.files.map((f) => ({ ...f })) : void 0,
|
|
599
606
|
developerInstructions: opts.arbiterInstructions || req.developerInstructions
|
|
600
|
-
})
|
|
607
|
+
}, opts.orientationFiles))
|
|
601
608
|
).then((v) => v, () => null)
|
|
602
609
|
) : Promise.resolve(
|
|
603
610
|
/** @type {DelegationResult|null} */
|
|
604
611
|
null
|
|
605
612
|
);
|
|
606
|
-
const [opinions, blindVerdict] = await Promise.all([askAll2(providers, req, { logger: opts.logger, tool: "consensus" }), blindPromise]);
|
|
613
|
+
const [opinions, blindVerdict] = await Promise.all([askAll2(providers, req, { logger: opts.logger, tool: "consensus", orientationFiles: opts.orientationFiles }), blindPromise]);
|
|
607
614
|
const ok = (
|
|
608
615
|
/** @type {DelegationSuccess[]} */
|
|
609
616
|
opinions.filter((o) => !o.isError)
|
|
@@ -666,8 +673,8 @@ ${feedback || "(reviewers gave no specific issues; tighten the weakest part)"}`
|
|
|
666
673
|
const { peerPrompt, blindPrompt } = loop.prepareRound(state);
|
|
667
674
|
const roundNo = state.round;
|
|
668
675
|
const [blindRes, peerResults] = await Promise.all([
|
|
669
|
-
Promise.resolve().then(() => arbiter.ask({ ...req, prompt: blindPrompt })).then((r) => r, () => null),
|
|
670
|
-
askAll2(providers, { ...req, prompt: peerPrompt }, { logger, tool: "consensus" })
|
|
676
|
+
Promise.resolve().then(() => arbiter.ask(withOrientation(arbiter, { ...req, prompt: blindPrompt }, opts.orientationFiles))).then((r) => r, () => null),
|
|
677
|
+
askAll2(providers, { ...req, prompt: peerPrompt }, { logger, tool: "consensus", orientationFiles: opts.orientationFiles })
|
|
671
678
|
]);
|
|
672
679
|
state = loop.recordBlindVerdict(state, okText(blindRes) || "(blind pass unavailable)");
|
|
673
680
|
lastResults = peerResults.map(
|
|
@@ -732,6 +739,52 @@ ${feedback || "(reviewers gave no specific issues; tighten the weakest part)"}`
|
|
|
732
739
|
}
|
|
733
740
|
});
|
|
734
741
|
|
|
742
|
+
// ../../core/orientation.js
|
|
743
|
+
var require_orientation = __commonJS({
|
|
744
|
+
"../../core/orientation.js"(exports2, module2) {
|
|
745
|
+
"use strict";
|
|
746
|
+
var fs = require("node:fs");
|
|
747
|
+
var path = require("node:path");
|
|
748
|
+
var ORIENTATION_CANDIDATES = [
|
|
749
|
+
"CLAUDE.md",
|
|
750
|
+
"AGENTS.md",
|
|
751
|
+
"README.md",
|
|
752
|
+
"package.json",
|
|
753
|
+
"pyproject.toml",
|
|
754
|
+
"Cargo.toml",
|
|
755
|
+
"go.mod",
|
|
756
|
+
"tsconfig.json",
|
|
757
|
+
"main.tf"
|
|
758
|
+
];
|
|
759
|
+
var DEFAULT_MAX_FILES = 6;
|
|
760
|
+
function resolveOrientationFiles(cwd, opts = {}) {
|
|
761
|
+
const base = cwd || process.cwd();
|
|
762
|
+
const max = Number.isInteger(opts.maxFiles) && /** @type {number} */
|
|
763
|
+
opts.maxFiles > 0 ? (
|
|
764
|
+
/** @type {number} */
|
|
765
|
+
opts.maxFiles
|
|
766
|
+
) : DEFAULT_MAX_FILES;
|
|
767
|
+
const candidates = opts.candidates || ORIENTATION_CANDIDATES;
|
|
768
|
+
const out = [];
|
|
769
|
+
for (const name of candidates) {
|
|
770
|
+
if (out.length >= max) break;
|
|
771
|
+
const abs = path.join(base, name);
|
|
772
|
+
try {
|
|
773
|
+
if (fs.statSync(abs).isFile()) out.push({ path: abs });
|
|
774
|
+
} catch {
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
return out;
|
|
778
|
+
}
|
|
779
|
+
function orientationFilesFor2(config, cwd) {
|
|
780
|
+
const o = config && config.orientation;
|
|
781
|
+
if (!o || o.enabled !== true) return void 0;
|
|
782
|
+
return resolveOrientationFiles(cwd, { maxFiles: o.maxFiles });
|
|
783
|
+
}
|
|
784
|
+
module2.exports = { resolveOrientationFiles, orientationFilesFor: orientationFilesFor2, ORIENTATION_CANDIDATES, DEFAULT_MAX_FILES };
|
|
785
|
+
}
|
|
786
|
+
});
|
|
787
|
+
|
|
735
788
|
// ../../core/prompts/index.js
|
|
736
789
|
var require_prompts = __commonJS({
|
|
737
790
|
"../../core/prompts/index.js"(exports2, module2) {
|
|
@@ -1443,7 +1496,7 @@ var require_openai_compatible = __commonJS({
|
|
|
1443
1496
|
/** @type {any} */
|
|
1444
1497
|
{
|
|
1445
1498
|
name,
|
|
1446
|
-
capabilities: { canImplement: false, fileUpload: false, multiTurn: true },
|
|
1499
|
+
capabilities: { canImplement: false, fileUpload: false, multiTurn: true, walksFilesystem: false },
|
|
1447
1500
|
/** Test-only: current number of cached sessions. */
|
|
1448
1501
|
get __sessionCount() {
|
|
1449
1502
|
return sessions.size;
|
|
@@ -1525,7 +1578,7 @@ var require_grok = __commonJS({
|
|
|
1525
1578
|
name: "grok",
|
|
1526
1579
|
// multiTurn is not wired through Core (runGrok/runWithFiles return no threadId),
|
|
1527
1580
|
// so report false to match reality.
|
|
1528
|
-
capabilities: { canImplement: false, fileUpload: true, multiTurn: false },
|
|
1581
|
+
capabilities: { canImplement: false, fileUpload: true, multiTurn: false, walksFilesystem: false },
|
|
1529
1582
|
async health() {
|
|
1530
1583
|
return process.env.XAI_API_KEY ? { ok: true } : { ok: false, reason: "XAI_API_KEY unset" };
|
|
1531
1584
|
},
|
|
@@ -1585,7 +1638,7 @@ var require_antigravity = __commonJS({
|
|
|
1585
1638
|
const model = opts.model || process.env.GEMINI_DEFAULT_MODEL || "auto-gemini-3";
|
|
1586
1639
|
return {
|
|
1587
1640
|
name: "gemini",
|
|
1588
|
-
capabilities: { canImplement: true, fileUpload: false, multiTurn: true },
|
|
1641
|
+
capabilities: { canImplement: true, fileUpload: false, multiTurn: true, walksFilesystem: true },
|
|
1589
1642
|
async health() {
|
|
1590
1643
|
return typeof bridge.runGemini === "function" ? { ok: true } : { ok: false, reason: "agy bridge unavailable" };
|
|
1591
1644
|
},
|
|
@@ -1666,7 +1719,7 @@ var require_codex = __commonJS({
|
|
|
1666
1719
|
const model = opts.model || "default";
|
|
1667
1720
|
return {
|
|
1668
1721
|
name: "codex",
|
|
1669
|
-
capabilities: { canImplement: true, fileUpload: false, multiTurn: false },
|
|
1722
|
+
capabilities: { canImplement: true, fileUpload: false, multiTurn: false, walksFilesystem: true },
|
|
1670
1723
|
// Option A: no threadId continuity
|
|
1671
1724
|
async health() {
|
|
1672
1725
|
return { ok: true };
|
|
@@ -4525,6 +4578,7 @@ var require_openrouter = __commonJS({
|
|
|
4525
4578
|
// index.js
|
|
4526
4579
|
var { makeRegistry, pinAlias } = require_registry();
|
|
4527
4580
|
var { askAll, askOne, consensus, runToConvergence } = require_orchestrate();
|
|
4581
|
+
var { orientationFilesFor } = require_orientation();
|
|
4528
4582
|
var { PROMPTS } = require_prompts();
|
|
4529
4583
|
var analyzeCore = require_analyze();
|
|
4530
4584
|
var ADVISORY = { readOnlyHint: true };
|
|
@@ -4801,6 +4855,9 @@ function buildServer({ providers, getConfig, getConfigError, sessionsDir, notify
|
|
|
4801
4855
|
if (!persona) return request;
|
|
4802
4856
|
return { ...request, developerInstructions: persona };
|
|
4803
4857
|
}
|
|
4858
|
+
function orient(req) {
|
|
4859
|
+
return orientationFilesFor(getConfig(), req && req.cwd);
|
|
4860
|
+
}
|
|
4804
4861
|
function sessionsCfg() {
|
|
4805
4862
|
const c = getConfig() || {};
|
|
4806
4863
|
const s = c.sessions || {};
|
|
@@ -4898,7 +4955,7 @@ function buildServer({ providers, getConfig, getConfigError, sessionsDir, notify
|
|
|
4898
4955
|
lg.logEvent({ event: "dispatch_start", at: Date.now(), tool: "ask-all", voices: selected.length });
|
|
4899
4956
|
} catch {
|
|
4900
4957
|
}
|
|
4901
|
-
const results = await askAll(selected, withPersona(req, expert), { logger: lg, tool: "ask-all", cache: opts.noCache ? void 0 : resultCache });
|
|
4958
|
+
const results = await askAll(selected, withPersona(req, expert), { logger: lg, tool: "ask-all", cache: opts.noCache ? void 0 : resultCache, orientationFiles: orient(req) });
|
|
4902
4959
|
return {
|
|
4903
4960
|
payload: { results, omitted },
|
|
4904
4961
|
parts: { opinions: results, blindVerdict: null, verdict: null, arbiter: null, warnings: [] }
|
|
@@ -4916,13 +4973,13 @@ function buildServer({ providers, getConfig, getConfigError, sessionsDir, notify
|
|
|
4916
4973
|
const resolved = await resolveArbiter(arbiterSpec, selected, registry, getConfig);
|
|
4917
4974
|
if (resolved.warning) warnings.push(resolved.warning);
|
|
4918
4975
|
if (resolved.mode === "host") {
|
|
4919
|
-
const opinions = await askAll(selected, withPersona(req, expert), { logger: currentLogger(), tool: "consensus" });
|
|
4976
|
+
const opinions = await askAll(selected, withPersona(req, expert), { logger: currentLogger(), tool: "consensus", orientationFiles: orient(req) });
|
|
4920
4977
|
const arbiter2 = { mode: "host" };
|
|
4921
4978
|
const body = { opinions, blindVerdict: null, verdict: null, arbiter: arbiter2, warnings };
|
|
4922
4979
|
return { payload: body, parts: body };
|
|
4923
4980
|
}
|
|
4924
4981
|
if (!resolved.provider) {
|
|
4925
|
-
const out2 = await consensus(selected, withPersona(req, expert), { arbiterInstructions: PROMPTS.arbiter, logger: currentLogger() });
|
|
4982
|
+
const out2 = await consensus(selected, withPersona(req, expert), { arbiterInstructions: PROMPTS.arbiter, logger: currentLogger(), orientationFiles: orient(req) });
|
|
4926
4983
|
const arbiter2 = { mode: "server", provider: null };
|
|
4927
4984
|
return {
|
|
4928
4985
|
payload: { opinions: out2.opinions, blindVerdict: out2.blindVerdict, verdict: out2.verdict, error: out2.error, arbiter: arbiter2, warnings },
|
|
@@ -4935,7 +4992,7 @@ function buildServer({ providers, getConfig, getConfigError, sessionsDir, notify
|
|
|
4935
4992
|
peers = selected;
|
|
4936
4993
|
warnings.push(`panel too small to exclude arbiter '${arbiterP.name}'; kept it in the peer panel (floor of 2)`);
|
|
4937
4994
|
}
|
|
4938
|
-
const out = await consensus(peers, withPersona(req, expert), { arbiter: arbiterP, arbiterInstructions: PROMPTS.arbiter, blindVote, logger: currentLogger() });
|
|
4995
|
+
const out = await consensus(peers, withPersona(req, expert), { arbiter: arbiterP, arbiterInstructions: PROMPTS.arbiter, blindVote, logger: currentLogger(), orientationFiles: orient(req) });
|
|
4939
4996
|
const arbiter = { mode: "server", provider: arbiterP.name };
|
|
4940
4997
|
return {
|
|
4941
4998
|
payload: { opinions: out.opinions, blindVerdict: out.blindVerdict, verdict: out.verdict, error: out.error, arbiter, warnings },
|
|
@@ -4965,7 +5022,7 @@ function buildServer({ providers, getConfig, getConfigError, sessionsDir, notify
|
|
|
4965
5022
|
}
|
|
4966
5023
|
const maxRounds = Number.isInteger(maxRoundsOverride) && /** @type {number} */
|
|
4967
5024
|
maxRoundsOverride > 0 ? maxRoundsOverride : Number.isInteger(cc.maxRounds) && cc.maxRounds > 0 ? cc.maxRounds : void 0;
|
|
4968
|
-
const out = await runToConvergence(peers, withPersona(req, expert), { arbiter: arbiterP, maxRounds, logger: currentLogger() });
|
|
5025
|
+
const out = await runToConvergence(peers, withPersona(req, expert), { arbiter: arbiterP, maxRounds, logger: currentLogger(), orientationFiles: orient(req) });
|
|
4969
5026
|
const allWarnings = out.error ? warnings.concat([`loop: ${out.error}`]) : warnings;
|
|
4970
5027
|
const rounds = Array.isArray(out.rounds) ? out.rounds.length : 0;
|
|
4971
5028
|
const arbiter = { mode: "server", provider: arbiterP.name };
|
|
@@ -5106,7 +5163,7 @@ function buildServer({ providers, getConfig, getConfigError, sessionsDir, notify
|
|
|
5106
5163
|
lg.logEvent({ event: "dispatch_start", at: Date.now(), tool: "consensus", round: cur.round, voices: selected.length });
|
|
5107
5164
|
} catch {
|
|
5108
5165
|
}
|
|
5109
|
-
const peerResults = await askAll(selected, withPersona(peerReq, ex), { logger: lg, tool: "consensus" });
|
|
5166
|
+
const peerResults = await askAll(selected, withPersona(peerReq, ex), { logger: lg, tool: "consensus", orientationFiles: orient(peerReq) });
|
|
5110
5167
|
const results = peerResults.map(
|
|
5111
5168
|
(r) => r.isError ? { source: r.provider, isError: true, errorKind: r.errorKind, verdict: null, criticalIssues: [], model: r.model, reasoningEffort: r.reasoningEffort ?? null, ms: r.ms } : { ...parseReview(typeof r.text === "string" ? r.text : ""), source: r.provider, isError: false, model: r.model, reasoningEffort: r.reasoningEffort ?? null, ms: r.ms }
|
|
5112
5169
|
);
|
|
@@ -5230,7 +5287,7 @@ function buildServer({ providers, getConfig, getConfigError, sessionsDir, notify
|
|
|
5230
5287
|
if (!p) {
|
|
5231
5288
|
return jsonResult({ error: `provider "${want}" is not in the active panel`, panel: selected.map((x) => x.name) });
|
|
5232
5289
|
}
|
|
5233
|
-
const result = await askOne(p, withPersona(req, expert), { logger: currentLogger(), tool: "ask-one", cache: resultCache });
|
|
5290
|
+
const result = await askOne(p, withPersona(req, expert), { logger: currentLogger(), tool: "ask-one", cache: resultCache, orientationFiles: orient(req) });
|
|
5234
5291
|
return jsonResult({ result });
|
|
5235
5292
|
}
|
|
5236
5293
|
if (name === "analyze") {
|
|
@@ -5299,12 +5356,12 @@ function buildServer({ providers, getConfig, getConfigError, sessionsDir, notify
|
|
|
5299
5356
|
if (Object.prototype.hasOwnProperty.call(ASK_PROVIDER, name)) {
|
|
5300
5357
|
const p = registry.get(ASK_PROVIDER[name]);
|
|
5301
5358
|
if (!p) return { content: [{ type: "text", text: JSON.stringify({ error: `provider ${ASK_PROVIDER[name]} not registered` }) }] };
|
|
5302
|
-
const result = await askOne(p, withPersona(req, expert), { logger: currentLogger(), tool: "ask-one", cache: resultCache });
|
|
5359
|
+
const result = await askOne(p, withPersona(req, expert), { logger: currentLogger(), tool: "ask-one", cache: resultCache, orientationFiles: orient(req) });
|
|
5303
5360
|
return { content: [{ type: "text", text: JSON.stringify({ result }) }] };
|
|
5304
5361
|
}
|
|
5305
5362
|
if (EXPERTS.includes(name)) {
|
|
5306
5363
|
const { providers: selected } = registry.selectForAskAll({ config: getConfig(), expert: name });
|
|
5307
|
-
const results = await askAll(selected, withPersona({ ...req, expert: name }, expert), { logger: currentLogger(), tool: name, cache: resultCache });
|
|
5364
|
+
const results = await askAll(selected, withPersona({ ...req, expert: name }, expert), { logger: currentLogger(), tool: name, cache: resultCache, orientationFiles: orient(req) });
|
|
5308
5365
|
return { content: [{ type: "text", text: JSON.stringify({ results }) }] };
|
|
5309
5366
|
}
|
|
5310
5367
|
throw new Error(`unknown tool: ${name}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@antonbabenko/deliberation-mcp",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.6.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" },
|