@dmsdc-ai/aigentry-deliberation 0.0.32 → 0.0.34
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/index.js +102 -10
- package/model-router.js +14 -25
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -516,6 +516,34 @@ function dedupeSpeakers(items = []) {
|
|
|
516
516
|
return out;
|
|
517
517
|
}
|
|
518
518
|
|
|
519
|
+
function hasExplicitBrowserParticipantSelection({ speakers, participant_types } = {}) {
|
|
520
|
+
const manualSpeakers = Array.isArray(speakers) ? speakers : [];
|
|
521
|
+
const hasBrowserSpeaker = manualSpeakers.some(speaker => {
|
|
522
|
+
const normalized = normalizeSpeaker(speaker);
|
|
523
|
+
return normalized?.startsWith("web-");
|
|
524
|
+
});
|
|
525
|
+
if (hasBrowserSpeaker) return true;
|
|
526
|
+
|
|
527
|
+
const overrides = participant_types && typeof participant_types === "object"
|
|
528
|
+
? Object.entries(participant_types)
|
|
529
|
+
: [];
|
|
530
|
+
|
|
531
|
+
return overrides.some(([speaker, type]) => {
|
|
532
|
+
const normalized = normalizeSpeaker(speaker);
|
|
533
|
+
return normalized?.startsWith("web-") || type === "browser" || type === "browser_auto";
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
function resolveIncludeBrowserSpeakers({ include_browser_speakers, config, speakers, participant_types } = {}) {
|
|
538
|
+
if (include_browser_speakers !== undefined && include_browser_speakers !== null) {
|
|
539
|
+
return include_browser_speakers;
|
|
540
|
+
}
|
|
541
|
+
if (config?.include_browser_speakers !== undefined && config?.include_browser_speakers !== null) {
|
|
542
|
+
return config.include_browser_speakers;
|
|
543
|
+
}
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
|
|
519
547
|
function resolveCliCandidates() {
|
|
520
548
|
const fromEnv = (process.env.DELIBERATION_CLI_CANDIDATES || "")
|
|
521
549
|
.split(/[,\s]+/)
|
|
@@ -2473,6 +2501,10 @@ server.tool(
|
|
|
2473
2501
|
(v) => (typeof v === "string" ? v === "true" : v),
|
|
2474
2502
|
z.boolean().optional()
|
|
2475
2503
|
).describe("Whether to auto-discover speakers when omitted (defaults to config setting)"),
|
|
2504
|
+
include_browser_speakers: z.preprocess(
|
|
2505
|
+
(v) => (typeof v === "string" ? v === "true" : v),
|
|
2506
|
+
z.boolean().optional()
|
|
2507
|
+
).describe("Whether browser speakers are allowed to participate. Defaults to false unless explicitly enabled."),
|
|
2476
2508
|
participant_types: z.preprocess(
|
|
2477
2509
|
(v) => (typeof v === "string" ? JSON.parse(v) : v),
|
|
2478
2510
|
z.record(z.string(), z.enum(["cli", "browser", "browser_auto", "manual"])).optional()
|
|
@@ -2486,7 +2518,7 @@ server.tool(
|
|
|
2486
2518
|
role_preset: z.enum(["balanced", "debate", "research", "brainstorm", "review", "consensus"]).optional()
|
|
2487
2519
|
.describe("Role preset (balanced/debate/research/brainstorm/review/consensus). Ignored if speaker_roles is specified"),
|
|
2488
2520
|
},
|
|
2489
|
-
safeToolHandler("deliberation_start", async ({ topic, session_id, rounds, first_speaker, speakers, speaker_instructions, require_manual_speakers, auto_discover_speakers, participant_types, ordering_strategy, speaker_roles, role_preset }) => {
|
|
2521
|
+
safeToolHandler("deliberation_start", async ({ topic, session_id, rounds, first_speaker, speakers, speaker_instructions, require_manual_speakers, auto_discover_speakers, include_browser_speakers, participant_types, ordering_strategy, speaker_roles, role_preset }) => {
|
|
2490
2522
|
// ── First-time onboarding guard ──
|
|
2491
2523
|
const config = loadDeliberationConfig();
|
|
2492
2524
|
if (!config.setup_complete) {
|
|
@@ -2495,7 +2527,7 @@ server.tool(
|
|
|
2495
2527
|
return {
|
|
2496
2528
|
content: [{
|
|
2497
2529
|
type: "text",
|
|
2498
|
-
text: `🎉 **Welcome to Deliberation!**\n\nPlease configure basic settings before starting.\n\n**Currently detected speakers:**\n${candidateText}\n\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nYou can set all options at once:\n\n\`\`\`\ndeliberation_cli_config(\n require_speaker_selection: true/false,\n default_rounds: 3,\n default_ordering: "auto"\n)\n\`\`\`\n\n**1. Speaker participation mode** (\`require_speaker_selection\`)\n - \`true\` — Select participating speakers each time\n - \`false\` —
|
|
2530
|
+
text: `🎉 **Welcome to Deliberation!**\n\nPlease configure basic settings before starting.\n\n**Currently detected speakers:**\n${candidateText}\n\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\nYou can set all options at once:\n\n\`\`\`\ndeliberation_cli_config(\n require_speaker_selection: true/false,\n include_browser_speakers: false,\n default_rounds: 3,\n default_ordering: "auto"\n)\n\`\`\`\n\n**1. Speaker participation mode** (\`require_speaker_selection\`)\n - \`true\` — Select participating speakers each time\n - \`false\` — Auto-join detected speakers\n\n**2. Browser speakers** (\`include_browser_speakers\`)\n - \`false\` — CLI only (recommended)\n - \`true\` — Include browser LLM speakers too\n\n**3. Default rounds** (\`default_rounds\`)\n - \`1\` — Quick consensus\n - \`3\` — Default (recommended)\n - \`5\` — Deep discussion\n\n**4. Ordering strategy** (\`default_ordering\`)\n - \`"auto"\` — cyclic for 2 speakers, weighted-random for 3+ (recommended)\n - \`"cyclic"\` — Fixed order\n - \`"random"\` — Random each turn\n - \`"weighted-random"\` — Less spoken speakers first`,
|
|
2499
2531
|
}],
|
|
2500
2532
|
};
|
|
2501
2533
|
}
|
|
@@ -2507,7 +2539,26 @@ server.tool(
|
|
|
2507
2539
|
return { content: [{ type: "text", text: `❌ Session "${session_id}" is already active. Please use a different ID or reset it first.` }] };
|
|
2508
2540
|
}
|
|
2509
2541
|
}
|
|
2510
|
-
const
|
|
2542
|
+
const explicitBrowserSelection = hasExplicitBrowserParticipantSelection({ speakers, participant_types });
|
|
2543
|
+
const includeBrowserSpeakers = resolveIncludeBrowserSpeakers({
|
|
2544
|
+
include_browser_speakers,
|
|
2545
|
+
config,
|
|
2546
|
+
speakers,
|
|
2547
|
+
participant_types,
|
|
2548
|
+
});
|
|
2549
|
+
if (explicitBrowserSelection && !includeBrowserSpeakers) {
|
|
2550
|
+
return {
|
|
2551
|
+
content: [{
|
|
2552
|
+
type: "text",
|
|
2553
|
+
text: `❌ Browser speakers are currently disabled.\n\nThis deliberation server now defaults to CLI-only participation to avoid browser timeouts blocking the session.\n\nTo include browser speakers, opt in explicitly:\n\`\`\`\ndeliberation_start(\n topic: "${topic.replace(/"/g, '\\"')}",\n speakers: ${JSON.stringify(speakers || ["claude", "codex"])},\n include_browser_speakers: true,\n require_manual_speakers: true\n)\n\`\`\`\n\nOr save it in config:\n\`deliberation_cli_config(include_browser_speakers: true)\``,
|
|
2554
|
+
}],
|
|
2555
|
+
};
|
|
2556
|
+
}
|
|
2557
|
+
|
|
2558
|
+
const candidateSnapshot = await collectSpeakerCandidates({
|
|
2559
|
+
include_cli: true,
|
|
2560
|
+
include_browser: includeBrowserSpeakers,
|
|
2561
|
+
});
|
|
2511
2562
|
|
|
2512
2563
|
// Resolve effective settings from config
|
|
2513
2564
|
const effectiveRequireManual = require_manual_speakers ?? config.require_speaker_selection ?? true;
|
|
@@ -2536,7 +2587,7 @@ server.tool(
|
|
|
2536
2587
|
return {
|
|
2537
2588
|
content: [{
|
|
2538
2589
|
type: "text",
|
|
2539
|
-
text: `Speakers must be manually selected to start a deliberation.${configNote}${llmSuggested}\n\n${candidateText}\n\nExample:\n\ndeliberation_start(\n topic: "${topic.replace(/"/g, '\\"')}",\n rounds: ${rounds},\n speakers: ["
|
|
2590
|
+
text: `Speakers must be manually selected to start a deliberation.${configNote}${llmSuggested}\n\n${candidateText}\n\nExample:\n\ndeliberation_start(\n topic: "${topic.replace(/"/g, '\\"')}",\n rounds: ${rounds},\n speakers: ["claude", "codex", "gemini"],\n require_manual_speakers: true,\n first_speaker: "codex"\n)\n\nFirst call deliberation_speaker_candidates to check currently available speakers.`,
|
|
2540
2591
|
}],
|
|
2541
2592
|
};
|
|
2542
2593
|
}
|
|
@@ -2544,7 +2595,6 @@ server.tool(
|
|
|
2544
2595
|
let autoDiscoveredSpeakers = [];
|
|
2545
2596
|
let autoParticipantTypes = {};
|
|
2546
2597
|
if (!hasManualSpeakers && effectiveAutoDiscover) {
|
|
2547
|
-
// Include ALL candidates: CLI + browser
|
|
2548
2598
|
for (const c of candidateSnapshot.candidates) {
|
|
2549
2599
|
autoDiscoveredSpeakers.push(c.speaker);
|
|
2550
2600
|
if (c.type === "browser" && c.cdp_available) {
|
|
@@ -2575,12 +2625,11 @@ server.tool(
|
|
|
2575
2625
|
|
|
2576
2626
|
// Warn if only 1 speaker — deliberation requires 2+
|
|
2577
2627
|
if (speakerOrder.length < 2) {
|
|
2578
|
-
const candidateSnapshot = await collectSpeakerCandidates({ include_cli: true, include_browser: true });
|
|
2579
2628
|
const candidateText = formatSpeakerCandidatesReport(candidateSnapshot);
|
|
2580
2629
|
return {
|
|
2581
2630
|
content: [{
|
|
2582
2631
|
type: "text",
|
|
2583
|
-
text: `⚠️ Deliberation requires at least 2 speakers. Currently only ${speakerOrder.length} specified: ${speakerOrder.join(", ")}\n\nAvailable speaker candidates:\n${candidateText}\n\nExample:\ndeliberation_start(topic: "${topic.slice(0, 50)}...", speakers: ["claude", "codex", "
|
|
2632
|
+
text: `⚠️ Deliberation requires at least 2 speakers. Currently only ${speakerOrder.length} specified: ${speakerOrder.join(", ")}\n\nAvailable speaker candidates:\n${candidateText}\n\nExample:\ndeliberation_start(topic: "${topic.slice(0, 50)}...", speakers: ["claude", "codex", "gemini"])`,
|
|
2584
2633
|
}],
|
|
2585
2634
|
};
|
|
2586
2635
|
}
|
|
@@ -3324,6 +3373,41 @@ server.tool(
|
|
|
3324
3373
|
})
|
|
3325
3374
|
);
|
|
3326
3375
|
|
|
3376
|
+
server.tool(
|
|
3377
|
+
"deliberation_list_remote_sessions",
|
|
3378
|
+
"List all active deliberation sessions on a remote machine (via Tailscale/IP) to find the correct session_id for context injection.",
|
|
3379
|
+
{
|
|
3380
|
+
remote_url: z.string().describe("The Tailscale IP or Host and port (e.g., '100.100.100.5:3847') of the remote machine."),
|
|
3381
|
+
},
|
|
3382
|
+
safeToolHandler("deliberation_list_remote_sessions", async ({ remote_url }) => {
|
|
3383
|
+
try {
|
|
3384
|
+
const baseUrl = remote_url.startsWith("http") ? remote_url : `http://${remote_url}`;
|
|
3385
|
+
const cleanBaseUrl = baseUrl.replace(/\/$/, "");
|
|
3386
|
+
const response = await fetch(`${cleanBaseUrl}/api/sessions`);
|
|
3387
|
+
|
|
3388
|
+
if (!response.ok) {
|
|
3389
|
+
return { content: [{ type: "text", text: `❌ Failed to fetch remote sessions (${response.status})` }] };
|
|
3390
|
+
}
|
|
3391
|
+
|
|
3392
|
+
const sessions = await response.json();
|
|
3393
|
+
if (!Array.isArray(sessions) || sessions.length === 0) {
|
|
3394
|
+
return { content: [{ type: "text", text: `No active deliberation sessions found on ${remote_url}.` }] };
|
|
3395
|
+
}
|
|
3396
|
+
|
|
3397
|
+
let result = `### Active Sessions on ${remote_url}\n\n`;
|
|
3398
|
+
for (const s of sessions) {
|
|
3399
|
+
result += `- **ID:** \`${s.id}\`\n`;
|
|
3400
|
+
result += ` **Topic:** ${s.topic}\n`;
|
|
3401
|
+
result += ` **Status:** ${s.status} (Round ${s.current_round}/${s.max_rounds})\n\n`;
|
|
3402
|
+
}
|
|
3403
|
+
|
|
3404
|
+
return { content: [{ type: "text", text: result }] };
|
|
3405
|
+
} catch (e) {
|
|
3406
|
+
return { content: [{ type: "text", text: `❌ Error connecting to remote machine at ${remote_url}: ${e.message}` }] };
|
|
3407
|
+
}
|
|
3408
|
+
})
|
|
3409
|
+
);
|
|
3410
|
+
|
|
3327
3411
|
server.tool(
|
|
3328
3412
|
"deliberation_inject_context",
|
|
3329
3413
|
"Inject additional context or instructions into a specific active session. (Useful for local or remote context injection via Tailscale)",
|
|
@@ -3631,6 +3715,10 @@ server.tool(
|
|
|
3631
3715
|
(v) => (typeof v === "string" ? v === "true" : v),
|
|
3632
3716
|
z.boolean().optional()
|
|
3633
3717
|
).describe("true: user selects speakers before each start, false: all detected speakers auto-join"),
|
|
3718
|
+
include_browser_speakers: z.preprocess(
|
|
3719
|
+
(v) => (typeof v === "string" ? v === "true" : v),
|
|
3720
|
+
z.boolean().optional()
|
|
3721
|
+
).describe("true: browser LLM speakers may join when requested or auto-discovered, false: CLI-only mode"),
|
|
3634
3722
|
default_rounds: z.coerce.number().int().min(1).max(10).optional()
|
|
3635
3723
|
.describe("Default number of rounds (1-10, default 3)"),
|
|
3636
3724
|
default_ordering: z.enum(["auto", "cyclic", "random", "weighted-random"]).optional()
|
|
@@ -3638,7 +3726,7 @@ server.tool(
|
|
|
3638
3726
|
chrome_profile: z.string().optional()
|
|
3639
3727
|
.describe("Chrome profile directory name for CDP (e.g., \"Default\", \"Profile 1\"). Stored for auto-launch."),
|
|
3640
3728
|
},
|
|
3641
|
-
safeToolHandler("deliberation_cli_config", async ({ enabled_clis, require_speaker_selection, default_rounds, default_ordering, chrome_profile }) => {
|
|
3729
|
+
safeToolHandler("deliberation_cli_config", async ({ enabled_clis, require_speaker_selection, include_browser_speakers, default_rounds, default_ordering, chrome_profile }) => {
|
|
3642
3730
|
const config = loadDeliberationConfig();
|
|
3643
3731
|
|
|
3644
3732
|
// Handle setup config updates
|
|
@@ -3647,6 +3735,10 @@ server.tool(
|
|
|
3647
3735
|
config.require_speaker_selection = require_speaker_selection;
|
|
3648
3736
|
configChanged = true;
|
|
3649
3737
|
}
|
|
3738
|
+
if (include_browser_speakers !== undefined && include_browser_speakers !== null) {
|
|
3739
|
+
config.include_browser_speakers = include_browser_speakers;
|
|
3740
|
+
configChanged = true;
|
|
3741
|
+
}
|
|
3650
3742
|
if (default_rounds !== undefined && default_rounds !== null) {
|
|
3651
3743
|
config.default_rounds = default_rounds;
|
|
3652
3744
|
configChanged = true;
|
|
@@ -3673,7 +3765,7 @@ server.tool(
|
|
|
3673
3765
|
return {
|
|
3674
3766
|
content: [{
|
|
3675
3767
|
type: "text",
|
|
3676
|
-
text: `## Deliberation CLI Settings\n\n**Mode:** ${mode}\n**Speaker selection:** ${config.require_speaker_selection === false ? "auto (
|
|
3768
|
+
text: `## Deliberation CLI Settings\n\n**Mode:** ${mode}\n**Speaker selection:** ${config.require_speaker_selection === false ? "auto (detected speakers join)" : "manual (user selects)"}\n**Browser speakers:** ${config.include_browser_speakers === true ? "enabled" : "disabled (CLI-only default)"}\n**Default rounds:** ${config.default_rounds || 3}\n**Ordering:** ${config.default_ordering || "auto"}\n**Chrome profile:** ${config.chrome_profile || "Default"} (env: DELIBERATION_CHROME_PROFILE)\n**Configured CLIs:** ${configured.length > 0 ? configured.join(", ") : "(none — full auto-detection)"}\n**Currently detected CLIs:** ${detected.join(", ") || "(none)"}\n**All supported CLIs:** ${DEFAULT_CLI_CANDIDATES.join(", ")}\n\nTo change:\n\`deliberation_cli_config(require_speaker_selection: false, include_browser_speakers: false, default_rounds: 3, default_ordering: "auto")\`\n\nTo enable browser speakers:\n\`deliberation_cli_config(include_browser_speakers: true)\`\n\nTo set Chrome profile for CDP:\n\`deliberation_cli_config(chrome_profile: "Profile 1")\`\n\nTo revert to full auto-detection:\n\`deliberation_cli_config(enabled_clis: [])\``,
|
|
3677
3769
|
}],
|
|
3678
3770
|
};
|
|
3679
3771
|
}
|
|
@@ -4478,4 +4570,4 @@ if (__entryFile && path.resolve(__currentFile) === __entryFile) {
|
|
|
4478
4570
|
}
|
|
4479
4571
|
|
|
4480
4572
|
// ── Test exports (used by vitest) ──
|
|
4481
|
-
export { selectNextSpeaker, loadRolePrompt, inferSuggestedRole, parseVotes, ROLE_KEYWORDS, ROLE_HEADING_MARKERS, loadRolePresets, applyRolePreset, detectDegradationLevels, formatDegradationReport, DEGRADATION_TIERS, DECISION_STAGES, STAGE_TRANSITIONS, createDecisionSession, advanceStage, buildConflictMap, parseOpinionFromResponse, buildOpinionPrompt, generateConflictQuestions, buildSynthesis, buildActionPlan, loadTemplates, matchTemplate };
|
|
4573
|
+
export { selectNextSpeaker, loadRolePrompt, inferSuggestedRole, parseVotes, ROLE_KEYWORDS, ROLE_HEADING_MARKERS, loadRolePresets, applyRolePreset, detectDegradationLevels, formatDegradationReport, DEGRADATION_TIERS, DECISION_STAGES, STAGE_TRANSITIONS, createDecisionSession, advanceStage, buildConflictMap, parseOpinionFromResponse, buildOpinionPrompt, generateConflictQuestions, buildSynthesis, buildActionPlan, loadTemplates, matchTemplate, hasExplicitBrowserParticipantSelection, resolveIncludeBrowserSpeakers };
|
package/model-router.js
CHANGED
|
@@ -137,61 +137,50 @@ export function selectModelForProvider(provider, category, complexity) {
|
|
|
137
137
|
|
|
138
138
|
switch (provider) {
|
|
139
139
|
case 'chatgpt': {
|
|
140
|
-
if (isHighReasoning) return { model: '
|
|
141
|
-
|
|
142
|
-
if (isSimple) return { model: 'gpt-4o-mini', reason: 'Simple task, cost-efficient model' };
|
|
143
|
-
return { model: 'gpt-4o', reason: 'Creative or medium-complexity task' };
|
|
140
|
+
if (isHighReasoning || isCoding) return { model: 'gpt-5.4', reason: 'High-complexity or coding task' };
|
|
141
|
+
return { model: 'gpt-5.4', reason: 'General or simple task' };
|
|
144
142
|
}
|
|
145
143
|
|
|
146
144
|
case 'claude': {
|
|
147
|
-
if (
|
|
148
|
-
|
|
149
|
-
return { model: 'sonnet', reason: 'Coding or medium-complexity task' };
|
|
145
|
+
if (isSimple) return { model: 'sonnet', reason: 'Simple task' };
|
|
146
|
+
return { model: 'opus', reason: 'Medium or High-complexity task' };
|
|
150
147
|
}
|
|
151
148
|
|
|
152
149
|
case 'gemini': {
|
|
153
|
-
|
|
154
|
-
if (isSimple) return { model: '2.0 Flash', reason: 'Simple task, fast response' };
|
|
155
|
-
return { model: '2.5 Flash', reason: 'Medium-complexity task' };
|
|
150
|
+
return { model: '3.1 Pro Preview', reason: 'Always use highest-end model' };
|
|
156
151
|
}
|
|
157
152
|
|
|
158
153
|
case 'deepseek': {
|
|
159
|
-
|
|
160
|
-
return { model: 'DeepSeek-V3', reason: 'General task' };
|
|
154
|
+
return { model: 'DeepSeek-R1', reason: 'High-end reasoning model' };
|
|
161
155
|
}
|
|
162
156
|
|
|
163
157
|
case 'grok': {
|
|
164
|
-
|
|
165
|
-
return { model: 'grok-3-mini', reason: 'Simple task' };
|
|
158
|
+
return { model: 'grok-3', reason: 'Always use highest-end model' };
|
|
166
159
|
}
|
|
167
160
|
|
|
168
161
|
case 'mistral': {
|
|
169
|
-
|
|
170
|
-
return { model: 'Mistral Small', reason: 'Simple task' };
|
|
162
|
+
return { model: 'Mistral Large', reason: 'Always use highest-end model' };
|
|
171
163
|
}
|
|
172
164
|
|
|
173
165
|
case 'poe': {
|
|
174
|
-
if (
|
|
175
|
-
|
|
176
|
-
return { model: 'GPT-4o', reason: 'Medium-complexity task' };
|
|
166
|
+
if (isSimple) return { model: 'Claude-3.5-Sonnet', reason: 'Simple task' };
|
|
167
|
+
return { model: 'Claude-3.5-Opus', reason: 'Medium or High-complexity task' };
|
|
177
168
|
}
|
|
178
169
|
|
|
179
170
|
case 'qwen': {
|
|
180
|
-
|
|
181
|
-
return { model: 'Qwen-Plus', reason: 'Simple task' };
|
|
171
|
+
return { model: 'Qwen-Max', reason: 'Always use highest-end model' };
|
|
182
172
|
}
|
|
183
173
|
|
|
184
174
|
case 'huggingchat': {
|
|
185
|
-
|
|
186
|
-
return { model: 'meta-llama/Llama-3.3-70B', reason: 'Simple task' };
|
|
175
|
+
return { model: 'Qwen/QwQ-32B', reason: 'Always use highest-end model' };
|
|
187
176
|
}
|
|
188
177
|
|
|
189
178
|
case 'copilot': {
|
|
190
|
-
return { model: 'GPT-
|
|
179
|
+
return { model: 'GPT-4.5', reason: 'Copilot using latest high-end model' };
|
|
191
180
|
}
|
|
192
181
|
|
|
193
182
|
case 'perplexity': {
|
|
194
|
-
return { model: '
|
|
183
|
+
return { model: 'sonar-pro', reason: 'Perplexity high-end model' };
|
|
195
184
|
}
|
|
196
185
|
|
|
197
186
|
default: {
|
package/package.json
CHANGED