@debatetalk/mcp 1.0.21 → 1.1.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/.claude-plugin/plugin.json +1 -1
- package/README.md +2 -1
- package/dist/{chunk-XVI4IIO6.js → chunk-ZE653LAA.js} +27 -7
- package/dist/chunk-ZE653LAA.js.map +1 -0
- package/dist/cli/index.js +43 -18
- package/dist/cli/index.js.map +1 -1
- package/dist/mcp/server.js +162 -39
- package/dist/mcp/server.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-XVI4IIO6.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "debatetalk",
|
|
3
3
|
"description": "Run structured multi-model AI debates from your AI assistant. Multiple models argue independently, deliberate, and converge on a 4-part synthesis: Strong Ground, Fault Lines, Blind Spots, and Your Call.",
|
|
4
|
-
"version": "1.0
|
|
4
|
+
"version": "1.1.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "DebateTalk",
|
|
7
7
|
"email": "support@debatetalk.ai"
|
package/README.md
CHANGED
|
@@ -10,7 +10,8 @@ DebateTalk makes multiple AI models argue a question independently, challenge ea
|
|
|
10
10
|
|
|
11
11
|
- **MCP server** — connect Claude Desktop, Cursor, or any MCP-compatible client to DebateTalk
|
|
12
12
|
- **CLI** — run debates and check model status from the terminal
|
|
13
|
-
- **Streaming
|
|
13
|
+
- **Streaming progress** — real-time round-by-round updates via MCP logging notifications
|
|
14
|
+
- **Cost & share links** — every debate shows cost and a shareable URL
|
|
14
15
|
- **5 tools:** `run_debate`, `get_model_status`, `recommend_models`, `estimate_cost`, `get_history`
|
|
15
16
|
|
|
16
17
|
---
|
|
@@ -102,17 +102,37 @@ var DebateTalkClient = class {
|
|
|
102
102
|
let synthesis = null;
|
|
103
103
|
for await (const event of this.streamDebate(params)) {
|
|
104
104
|
events.push(event);
|
|
105
|
+
const d = (key) => event[key] ?? event.data?.[key];
|
|
106
|
+
if (event.type === "debate_created") {
|
|
107
|
+
const did = d("debate_id");
|
|
108
|
+
if (typeof did === "string") debateId = did;
|
|
109
|
+
}
|
|
105
110
|
if (event.type === "debate_start") {
|
|
106
|
-
debateId
|
|
107
|
-
|
|
111
|
+
if (!debateId) {
|
|
112
|
+
const did = d("debate_id");
|
|
113
|
+
if (typeof did === "string") debateId = did;
|
|
114
|
+
}
|
|
115
|
+
const m = d("models");
|
|
116
|
+
models = Array.isArray(m) ? m : [];
|
|
108
117
|
}
|
|
109
118
|
if (event.type === "classification") {
|
|
110
|
-
|
|
119
|
+
const qt = d("question_type");
|
|
120
|
+
questionType = typeof qt === "string" ? qt : "";
|
|
111
121
|
}
|
|
112
122
|
if (event.type === "synthesis") {
|
|
113
|
-
const
|
|
114
|
-
|
|
115
|
-
|
|
123
|
+
const s = event.data ?? event;
|
|
124
|
+
const stringify = (v) => typeof v === "string" ? v : Array.isArray(v) ? v.join("\n") : String(v ?? "");
|
|
125
|
+
const sg = s["strong_ground"];
|
|
126
|
+
const fl = s["fault_lines"];
|
|
127
|
+
const bs = s["blind_spots"];
|
|
128
|
+
const yc = s["your_call"];
|
|
129
|
+
if (sg != null && fl != null && bs != null && yc != null) {
|
|
130
|
+
synthesis = {
|
|
131
|
+
strong_ground: stringify(sg),
|
|
132
|
+
fault_lines: stringify(fl),
|
|
133
|
+
blind_spots: stringify(bs),
|
|
134
|
+
your_call: stringify(yc)
|
|
135
|
+
};
|
|
116
136
|
}
|
|
117
137
|
}
|
|
118
138
|
}
|
|
@@ -131,4 +151,4 @@ export {
|
|
|
131
151
|
DebateTalkError,
|
|
132
152
|
DebateTalkClient
|
|
133
153
|
};
|
|
134
|
-
//# sourceMappingURL=chunk-
|
|
154
|
+
//# sourceMappingURL=chunk-ZE653LAA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { EventSourceParserStream } from \"eventsource-parser/stream\";\nimport type {\n ModelStatusResponse,\n RecommendResponse,\n EstimateCostParams,\n CostEstimate,\n HistoryResponse,\n DebateParams,\n DebateEvent,\n DebateResult,\n ApiErrorBody,\n SynthesisData,\n} from \"./types.js\";\n\nconst BASE_URL = \"https://engine.debatetalk.ai\";\n\nexport class DebateTalkError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly code?: string\n ) {\n super(message);\n this.name = \"DebateTalkError\";\n }\n}\n\nexport class DebateTalkClient {\n private readonly apiKey: string | undefined;\n\n constructor(apiKey?: string) {\n this.apiKey = apiKey ?? process.env[\"DEBATETALK_API_KEY\"];\n }\n\n private get authHeaders(): Record<string, string> {\n if (!this.apiKey) return {};\n return { Authorization: `Bearer ${this.apiKey}` };\n }\n\n private get baseHeaders(): Record<string, string> {\n return { \"Content-Type\": \"application/json\", ...this.authHeaders };\n }\n\n private requireAuth(): void {\n if (!this.apiKey) {\n throw new Error(\n \"DEBATETALK_API_KEY is required for this operation. \" +\n \"Create one at https://console.debatetalk.ai/api-keys\"\n );\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n const res = await fetch(`${BASE_URL}${path}`, {\n method,\n headers: this.baseHeaders,\n ...(body !== undefined && { body: JSON.stringify(body) }),\n });\n\n if (!res.ok) {\n const payload = await res.json().catch(() => ({\n error: { code: \"unknown\", message: res.statusText },\n })) as ApiErrorBody;\n throw new DebateTalkError(\n res.status,\n payload.error?.message ?? res.statusText,\n payload.error?.code\n );\n }\n\n return res.json() as Promise<T>;\n }\n\n // ── Public endpoints (no auth required) ──────────────────────────────────\n\n async getModelStatus(): Promise<ModelStatusResponse> {\n return this.request<ModelStatusResponse>(\"GET\", \"/v1/public/model-status\");\n }\n\n async recommendModels(question: string): Promise<RecommendResponse> {\n return this.request<RecommendResponse>(\"POST\", \"/v1/models/recommend\", {\n question,\n });\n }\n\n // ── Authenticated endpoints ───────────────────────────────────────────────\n\n async estimateCost(params: EstimateCostParams): Promise<CostEstimate> {\n this.requireAuth();\n return this.request<CostEstimate>(\"POST\", \"/v1/user/estimate-cost\", params);\n }\n\n async getHistory(limit = 20): Promise<HistoryResponse> {\n this.requireAuth();\n return this.request<HistoryResponse>(\n \"GET\",\n `/v1/user/history?limit=${limit}`\n );\n }\n\n async *streamDebate(params: DebateParams): AsyncGenerator<DebateEvent> {\n this.requireAuth();\n\n const res = await fetch(`${BASE_URL}/debate`, {\n method: \"POST\",\n headers: { ...this.baseHeaders, Accept: \"text/event-stream\" },\n body: JSON.stringify(params),\n });\n\n if (!res.ok) {\n const payload = await res.json().catch(() => ({\n error: { code: \"unknown\", message: res.statusText },\n })) as ApiErrorBody;\n throw new DebateTalkError(\n res.status,\n payload.error?.message ?? res.statusText,\n payload.error?.code\n );\n }\n\n if (!res.body) throw new DebateTalkError(0, \"No response body\");\n\n const stream = res.body\n .pipeThrough(new TextDecoderStream())\n .pipeThrough(new EventSourceParserStream());\n\n for await (const event of stream) {\n if (!event.data || event.data === \"[DONE]\") continue;\n try {\n yield JSON.parse(event.data) as DebateEvent;\n } catch {\n // skip malformed events\n }\n }\n }\n\n async runDebate(params: DebateParams): Promise<DebateResult> {\n const events: DebateEvent[] = [];\n let debateId = \"\";\n let questionType = \"\";\n let models: string[] = [];\n let synthesis: SynthesisData | null = null;\n\n for await (const event of this.streamDebate(params)) {\n events.push(event);\n\n // Helper: events may be flat or nest payload under `data`.\n const d = (key: string) => event[key] ?? event.data?.[key];\n\n if (event.type === \"debate_created\") {\n const did = d(\"debate_id\");\n if (typeof did === \"string\") debateId = did;\n }\n if (event.type === \"debate_start\") {\n if (!debateId) {\n const did = d(\"debate_id\");\n if (typeof did === \"string\") debateId = did;\n }\n const m = d(\"models\");\n models = Array.isArray(m) ? (m as string[]) : [];\n }\n if (event.type === \"classification\") {\n const qt = d(\"question_type\");\n questionType = typeof qt === \"string\" ? qt : \"\";\n }\n if (event.type === \"synthesis\") {\n // Synthesis nests under event.data; fields may be strings or arrays\n const s = (event.data ?? event) as Record<string, unknown>;\n const stringify = (v: unknown): string =>\n typeof v === \"string\" ? v : Array.isArray(v) ? v.join(\"\\n\") : String(v ?? \"\");\n const sg = s[\"strong_ground\"];\n const fl = s[\"fault_lines\"];\n const bs = s[\"blind_spots\"];\n const yc = s[\"your_call\"];\n if (sg != null && fl != null && bs != null && yc != null) {\n synthesis = {\n strong_ground: stringify(sg),\n fault_lines: stringify(fl),\n blind_spots: stringify(bs),\n your_call: stringify(yc),\n };\n }\n }\n }\n\n return {\n debate_id: debateId,\n question: params.question,\n question_type: questionType,\n models,\n synthesis,\n events,\n };\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
DebateTalkClient,
|
|
4
4
|
DebateTalkError
|
|
5
|
-
} from "../chunk-
|
|
5
|
+
} from "../chunk-ZE653LAA.js";
|
|
6
6
|
|
|
7
7
|
// src/cli/index.ts
|
|
8
8
|
import { Command as Command6 } from "commander";
|
|
@@ -38,6 +38,14 @@ function handleError(err) {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
// src/cli/commands/debate.ts
|
|
41
|
+
function d(event, key) {
|
|
42
|
+
return event[key] ?? event.data?.[key];
|
|
43
|
+
}
|
|
44
|
+
function stringify(v) {
|
|
45
|
+
if (typeof v === "string") return v;
|
|
46
|
+
if (Array.isArray(v)) return v.map((item, i) => `${i + 1}. ${item}`).join("\n");
|
|
47
|
+
return String(v ?? "");
|
|
48
|
+
}
|
|
41
49
|
function debateCommand() {
|
|
42
50
|
return new Command("debate").description("Run a structured multi-model AI debate").argument("<question>", "The question or topic to debate").option(
|
|
43
51
|
"--models <ids>",
|
|
@@ -53,6 +61,9 @@ function debateCommand() {
|
|
|
53
61
|
const spinner = ora("Starting debate\u2026").start();
|
|
54
62
|
try {
|
|
55
63
|
let currentPhase = "";
|
|
64
|
+
let costUsd = null;
|
|
65
|
+
let shareUrl = null;
|
|
66
|
+
let synthesisEvent = null;
|
|
56
67
|
for await (const event of client.streamDebate(params)) {
|
|
57
68
|
const phase = getPhaseLabel(event);
|
|
58
69
|
if (phase && phase !== currentPhase) {
|
|
@@ -60,12 +71,21 @@ function debateCommand() {
|
|
|
60
71
|
spinner.text = phase;
|
|
61
72
|
}
|
|
62
73
|
if (event.type === "synthesis") {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
74
|
+
synthesisEvent = event;
|
|
75
|
+
}
|
|
76
|
+
if (event.type === "debate_complete") {
|
|
77
|
+
const cost = d(event, "cost_usd");
|
|
78
|
+
if (typeof cost === "number") costUsd = cost;
|
|
79
|
+
const url = d(event, "share_url");
|
|
80
|
+
if (typeof url === "string") shareUrl = url;
|
|
66
81
|
}
|
|
67
82
|
}
|
|
68
|
-
|
|
83
|
+
if (synthesisEvent) {
|
|
84
|
+
spinner.succeed("Debate complete");
|
|
85
|
+
printSynthesis(question, synthesisEvent, costUsd, shareUrl);
|
|
86
|
+
} else {
|
|
87
|
+
spinner.fail("Debate ended without synthesis");
|
|
88
|
+
}
|
|
69
89
|
} catch (err) {
|
|
70
90
|
spinner.fail("Debate failed");
|
|
71
91
|
handleError(err);
|
|
@@ -78,33 +98,38 @@ function getPhaseLabel(event) {
|
|
|
78
98
|
case "debate_start":
|
|
79
99
|
return "Debate starting\u2026";
|
|
80
100
|
case "classification":
|
|
81
|
-
return `Classifying question (${event
|
|
101
|
+
return `Classifying question (${d(event, "question_type") ?? "\u2026"})`;
|
|
82
102
|
case "round_start":
|
|
83
|
-
return `Round ${event
|
|
103
|
+
return `Round ${d(event, "round") ?? "?"} \u2014 models deliberating\u2026`;
|
|
84
104
|
case "consensus":
|
|
85
105
|
return "Checking consensus\u2026";
|
|
86
|
-
case "
|
|
106
|
+
case "synthesis_start":
|
|
87
107
|
return "Generating synthesis\u2026";
|
|
88
108
|
default:
|
|
89
109
|
return null;
|
|
90
110
|
}
|
|
91
111
|
}
|
|
92
|
-
function printSynthesis(question, event) {
|
|
93
|
-
const
|
|
112
|
+
function printSynthesis(question, event, costUsd, shareUrl) {
|
|
113
|
+
const s = event.data ?? event;
|
|
94
114
|
console.log();
|
|
95
115
|
console.log(chalk2.bold(`"${question}"`));
|
|
116
|
+
if (costUsd != null) console.log(chalk2.dim(`Cost: $${costUsd.toFixed(4)}`));
|
|
96
117
|
console.log();
|
|
97
118
|
console.log(chalk2.bold.green("\u2501\u2501\u2501 STRONG GROUND \u2501\u2501\u2501"));
|
|
98
|
-
console.log(
|
|
119
|
+
console.log(stringify(s["strong_ground"]));
|
|
99
120
|
console.log();
|
|
100
121
|
console.log(chalk2.bold.yellow("\u2501\u2501\u2501 FAULT LINES \u2501\u2501\u2501"));
|
|
101
|
-
console.log(
|
|
122
|
+
console.log(stringify(s["fault_lines"]));
|
|
102
123
|
console.log();
|
|
103
124
|
console.log(chalk2.bold.magenta("\u2501\u2501\u2501 BLIND SPOTS \u2501\u2501\u2501"));
|
|
104
|
-
console.log(
|
|
125
|
+
console.log(stringify(s["blind_spots"]));
|
|
105
126
|
console.log();
|
|
106
127
|
console.log(chalk2.bold.cyan("\u2501\u2501\u2501 YOUR CALL \u2501\u2501\u2501"));
|
|
107
|
-
console.log(
|
|
128
|
+
console.log(stringify(s["your_call"]));
|
|
129
|
+
if (shareUrl) {
|
|
130
|
+
console.log();
|
|
131
|
+
console.log(chalk2.dim(`\u{1F517} ${shareUrl}`));
|
|
132
|
+
}
|
|
108
133
|
console.log();
|
|
109
134
|
}
|
|
110
135
|
|
|
@@ -202,15 +227,15 @@ function historyCommand() {
|
|
|
202
227
|
chalk6.bold(`Debate history`) + chalk6.dim(` \u2014 showing ${debates.length} of ${total}`)
|
|
203
228
|
);
|
|
204
229
|
console.log();
|
|
205
|
-
for (const
|
|
206
|
-
const date = new Date(
|
|
230
|
+
for (const d2 of debates) {
|
|
231
|
+
const date = new Date(d2.created_at).toLocaleDateString("en-US", {
|
|
207
232
|
year: "numeric",
|
|
208
233
|
month: "short",
|
|
209
234
|
day: "numeric"
|
|
210
235
|
});
|
|
211
|
-
const share =
|
|
236
|
+
const share = d2.share_token ? chalk6.dim(` \u2192 https://console.debatetalk.ai/share/${d2.share_token}`) : "";
|
|
212
237
|
console.log(
|
|
213
|
-
` ${chalk6.dim(date)} ${
|
|
238
|
+
` ${chalk6.dim(date)} ${d2.title}` + chalk6.dim(` (${d2.model_count} models, ${d2.status})`) + share
|
|
214
239
|
);
|
|
215
240
|
}
|
|
216
241
|
} catch (err) {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/debate.ts","../../src/cli/utils.ts","../../src/cli/commands/models.ts","../../src/cli/commands/recommend.ts","../../src/cli/commands/cost.ts","../../src/cli/commands/history.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { debateCommand } from \"./commands/debate.js\";\nimport { modelsCommand } from \"./commands/models.js\";\nimport { recommendCommand } from \"./commands/recommend.js\";\nimport { costCommand } from \"./commands/cost.js\";\nimport { historyCommand } from \"./commands/history.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"dt\")\n .description(\n \"DebateTalk CLI — run structured multi-model AI debates from your terminal.\\n\" +\n \"Docs: https://debatetalk.ai/resources/api-reference\"\n )\n .version(\"1.0.0\");\n\nprogram.addCommand(debateCommand());\nprogram.addCommand(modelsCommand());\nprogram.addCommand(recommendCommand());\nprogram.addCommand(costCommand());\nprogram.addCommand(historyCommand());\n\nprogram.parse();\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\nimport type { DebateEvent } from \"../../types.js\";\n\nexport function debateCommand(): Command {\n return new Command(\"debate\")\n .description(\"Run a structured multi-model AI debate\")\n .argument(\"<question>\", \"The question or topic to debate\")\n .option(\n \"--models <ids>\",\n \"Comma-separated model IDs (omit for smart routing)\"\n )\n .option(\"--rounds <n>\", \"Number of deliberation rounds (default: 2)\")\n .action(\n async (\n question: string,\n opts: { models?: string; rounds?: string }\n ) => {\n const client = new DebateTalkClient();\n const params = {\n question,\n ...(opts.models && { models: opts.models.split(\",\").map((s) => s.trim()) }),\n ...(opts.rounds && { rounds: parseInt(opts.rounds, 10) }),\n };\n\n const spinner = ora(\"Starting debate…\").start();\n\n try {\n let currentPhase = \"\";\n\n for await (const event of client.streamDebate(params)) {\n const phase = getPhaseLabel(event);\n if (phase && phase !== currentPhase) {\n currentPhase = phase;\n spinner.text = phase;\n }\n\n if (event.type === \"synthesis\") {\n spinner.succeed(\"Debate complete\");\n printSynthesis(question, event);\n return;\n }\n }\n\n spinner.fail(\"Debate ended without synthesis\");\n } catch (err) {\n spinner.fail(\"Debate failed\");\n handleError(err);\n }\n }\n );\n}\n\nfunction getPhaseLabel(event: DebateEvent): string | null {\n switch (event.type) {\n case \"debate_start\":\n return \"Debate starting…\";\n case \"classification\":\n return `Classifying question (${(event.data[\"question_type\"] as string | undefined) ?? \"…\"})`;\n case \"round_start\":\n return `Round ${(event.data[\"round\"] as number | undefined) ?? \"?\"} — models deliberating…`;\n case \"consensus\":\n return \"Checking consensus…\";\n case \"synthesis\":\n return \"Generating synthesis…\";\n default:\n return null;\n }\n}\n\nfunction printSynthesis(question: string, event: DebateEvent): void {\n const d = event.data as Record<string, string>;\n console.log();\n console.log(chalk.bold(`\"${question}\"`));\n console.log();\n console.log(chalk.bold.green(\"━━━ STRONG GROUND ━━━\"));\n console.log(d[\"strong_ground\"] ?? \"\");\n console.log();\n console.log(chalk.bold.yellow(\"━━━ FAULT LINES ━━━\"));\n console.log(d[\"fault_lines\"] ?? \"\");\n console.log();\n console.log(chalk.bold.magenta(\"━━━ BLIND SPOTS ━━━\"));\n console.log(d[\"blind_spots\"] ?? \"\");\n console.log();\n console.log(chalk.bold.cyan(\"━━━ YOUR CALL ━━━\"));\n console.log(d[\"your_call\"] ?? \"\");\n console.log();\n}\n","import chalk from \"chalk\";\nimport { DebateTalkError } from \"../client.js\";\n\nexport function handleError(err: unknown): never {\n if (err instanceof DebateTalkError) {\n if (err.status === 401 || err.status === 403) {\n console.error(chalk.red(\"Authentication failed.\"));\n console.error(\n chalk.dim(\n \"Set DEBATETALK_API_KEY or create a key at https://console.debatetalk.ai/api-keys\"\n )\n );\n } else if (err.status === 429) {\n console.error(chalk.red(\"Rate limit reached.\"));\n console.error(chalk.dim(\"Free plan: 5 debates/day. Upgrade at https://debatetalk.ai\"));\n } else {\n console.error(chalk.red(`API error (${err.status}): ${err.message}`));\n }\n } else if (err instanceof Error) {\n console.error(chalk.red(err.message));\n } else {\n console.error(chalk.red(\"An unexpected error occurred.\"));\n }\n process.exit(1);\n}\n\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\n\nexport function modelsCommand(): Command {\n return new Command(\"models\")\n .description(\"Show real-time health and latency for all DebateTalk models\")\n .action(async () => {\n const client = new DebateTalkClient();\n try {\n const { models, updated_at } = await client.getModelStatus();\n const online = models.filter((m) => m.status === \"online\").length;\n console.log(\n chalk.bold(`Model Status`) +\n chalk.dim(` — ${online}/${models.length} online (updated ${updated_at})`)\n );\n console.log();\n for (const m of models) {\n const icon =\n m.status === \"online\"\n ? chalk.green(\"✓\")\n : m.status === \"degraded\"\n ? chalk.yellow(\"⚠\")\n : chalk.red(\"✗\");\n const latency =\n m.latency_ms != null ? chalk.dim(` ${m.latency_ms}ms`) : \"\";\n console.log(` ${icon} ${m.display_name}${latency}`);\n }\n } catch (err) {\n handleError(err);\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\n\nexport function recommendCommand(): Command {\n return new Command(\"recommend\")\n .description(\"Get the best model panel for a question\")\n .argument(\"<question>\", \"The question to get recommendations for\")\n .action(async (question: string) => {\n const client = new DebateTalkClient();\n try {\n const rec = await client.recommendModels(question);\n console.log(chalk.bold(`Recommended panel`) + chalk.dim(` for \"${question}\"`));\n console.log(chalk.dim(`Question type: ${rec.question_type}`));\n console.log();\n console.log(` ${chalk.cyan(\"Debaters:\")} ${rec.debaters.join(\", \")}`);\n console.log(` ${chalk.cyan(\"Synthesizer:\")} ${rec.synthesizer}`);\n console.log(` ${chalk.cyan(\"Adjudicator:\")} ${rec.adjudicator}`);\n } catch (err) {\n handleError(err);\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\n\nexport function costCommand(): Command {\n return new Command(\"cost\")\n .description(\"Estimate the credit cost of a debate before running it\")\n .argument(\"<question>\", \"The question to estimate cost for\")\n .option(\"--rounds <n>\", \"Number of deliberation rounds\")\n .action(async (question: string, opts: { rounds?: string }) => {\n const client = new DebateTalkClient();\n try {\n const est = await client.estimateCost({\n question,\n ...(opts.rounds && { rounds: parseInt(opts.rounds, 10) }),\n });\n console.log(chalk.bold(`Cost estimate`));\n console.log();\n console.log(\n ` ${chalk.cyan(\"Total:\")} ${est.estimated_credits} credits` +\n chalk.dim(` (~$${est.estimated_usd.toFixed(2)} USD)`)\n );\n console.log();\n console.log(chalk.dim(\" Breakdown:\"));\n for (const b of est.breakdown) {\n console.log(\n chalk.dim(\n ` • ${b.model} (${b.role}): ~${b.estimated_tokens.toLocaleString()} tokens = ${b.estimated_credits} credits`\n )\n );\n }\n } catch (err) {\n handleError(err);\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\n\nexport function historyCommand(): Command {\n return new Command(\"history\")\n .description(\"List your past debates\")\n .option(\"--limit <n>\", \"Number of debates to show\", \"20\")\n .action(async (opts: { limit: string }) => {\n const client = new DebateTalkClient();\n try {\n const rawLimit = parseInt(opts.limit, 10);\n const { debates, total } = await client.getHistory(\n Number.isNaN(rawLimit) ? 20 : Math.min(Math.max(1, rawLimit), 100)\n );\n if (debates.length === 0) {\n console.log(chalk.dim('No debates yet. Run: dt debate \"your question\"'));\n return;\n }\n console.log(\n chalk.bold(`Debate history`) +\n chalk.dim(` — showing ${debates.length} of ${total}`)\n );\n console.log();\n for (const d of debates) {\n const date = new Date(d.created_at).toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n const share = d.share_token\n ? chalk.dim(` → https://console.debatetalk.ai/share/${d.share_token}`)\n : \"\";\n console.log(\n ` ${chalk.dim(date)} ${d.title}` +\n chalk.dim(` (${d.model_count} models, ${d.status})`) +\n share\n );\n }\n } catch (err) {\n handleError(err);\n }\n });\n}\n"],"mappings":"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","names":["Command","chalk","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/debate.ts","../../src/cli/utils.ts","../../src/cli/commands/models.ts","../../src/cli/commands/recommend.ts","../../src/cli/commands/cost.ts","../../src/cli/commands/history.ts"],"sourcesContent":["import { Command } from \"commander\";\nimport { debateCommand } from \"./commands/debate.js\";\nimport { modelsCommand } from \"./commands/models.js\";\nimport { recommendCommand } from \"./commands/recommend.js\";\nimport { costCommand } from \"./commands/cost.js\";\nimport { historyCommand } from \"./commands/history.js\";\n\nconst program = new Command();\n\nprogram\n .name(\"dt\")\n .description(\n \"DebateTalk CLI — run structured multi-model AI debates from your terminal.\\n\" +\n \"Docs: https://debatetalk.ai/resources/api-reference\"\n )\n .version(\"1.0.0\");\n\nprogram.addCommand(debateCommand());\nprogram.addCommand(modelsCommand());\nprogram.addCommand(recommendCommand());\nprogram.addCommand(costCommand());\nprogram.addCommand(historyCommand());\n\nprogram.parse();\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport ora from \"ora\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\nimport type { DebateEvent } from \"../../types.js\";\n\n/** Access a field from a flat or nested event. */\nfunction d(event: DebateEvent, key: string): unknown {\n return event[key] ?? event.data?.[key];\n}\n\nfunction stringify(v: unknown): string {\n if (typeof v === \"string\") return v;\n if (Array.isArray(v)) return v.map((item, i) => `${i + 1}. ${item}`).join(\"\\n\");\n return String(v ?? \"\");\n}\n\nexport function debateCommand(): Command {\n return new Command(\"debate\")\n .description(\"Run a structured multi-model AI debate\")\n .argument(\"<question>\", \"The question or topic to debate\")\n .option(\n \"--models <ids>\",\n \"Comma-separated model IDs (omit for smart routing)\"\n )\n .option(\"--rounds <n>\", \"Number of deliberation rounds (default: 2)\")\n .action(\n async (\n question: string,\n opts: { models?: string; rounds?: string }\n ) => {\n const client = new DebateTalkClient();\n const params = {\n question,\n ...(opts.models && { models: opts.models.split(\",\").map((s) => s.trim()) }),\n ...(opts.rounds && { rounds: parseInt(opts.rounds, 10) }),\n };\n\n const spinner = ora(\"Starting debate…\").start();\n\n try {\n let currentPhase = \"\";\n let costUsd: number | null = null;\n let shareUrl: string | null = null;\n let synthesisEvent: DebateEvent | null = null;\n\n for await (const event of client.streamDebate(params)) {\n const phase = getPhaseLabel(event);\n if (phase && phase !== currentPhase) {\n currentPhase = phase;\n spinner.text = phase;\n }\n\n if (event.type === \"synthesis\") {\n synthesisEvent = event;\n }\n\n if (event.type === \"debate_complete\") {\n const cost = d(event, \"cost_usd\");\n if (typeof cost === \"number\") costUsd = cost;\n const url = d(event, \"share_url\");\n if (typeof url === \"string\") shareUrl = url;\n }\n }\n\n if (synthesisEvent) {\n spinner.succeed(\"Debate complete\");\n printSynthesis(question, synthesisEvent, costUsd, shareUrl);\n } else {\n spinner.fail(\"Debate ended without synthesis\");\n }\n } catch (err) {\n spinner.fail(\"Debate failed\");\n handleError(err);\n }\n }\n );\n}\n\nfunction getPhaseLabel(event: DebateEvent): string | null {\n switch (event.type) {\n case \"debate_start\":\n return \"Debate starting…\";\n case \"classification\":\n return `Classifying question (${(d(event, \"question_type\") as string | undefined) ?? \"…\"})`;\n case \"round_start\":\n return `Round ${(d(event, \"round\") as number | undefined) ?? \"?\"} — models deliberating…`;\n case \"consensus\":\n return \"Checking consensus…\";\n case \"synthesis_start\":\n return \"Generating synthesis…\";\n default:\n return null;\n }\n}\n\nfunction printSynthesis(question: string, event: DebateEvent, costUsd: number | null, shareUrl: string | null): void {\n const s = (event.data ?? event) as Record<string, unknown>;\n console.log();\n console.log(chalk.bold(`\"${question}\"`));\n if (costUsd != null) console.log(chalk.dim(`Cost: $${costUsd.toFixed(4)}`));\n console.log();\n console.log(chalk.bold.green(\"━━━ STRONG GROUND ━━━\"));\n console.log(stringify(s[\"strong_ground\"]));\n console.log();\n console.log(chalk.bold.yellow(\"━━━ FAULT LINES ━━━\"));\n console.log(stringify(s[\"fault_lines\"]));\n console.log();\n console.log(chalk.bold.magenta(\"━━━ BLIND SPOTS ━━━\"));\n console.log(stringify(s[\"blind_spots\"]));\n console.log();\n console.log(chalk.bold.cyan(\"━━━ YOUR CALL ━━━\"));\n console.log(stringify(s[\"your_call\"]));\n if (shareUrl) {\n console.log();\n console.log(chalk.dim(`🔗 ${shareUrl}`));\n }\n console.log();\n}\n","import chalk from \"chalk\";\nimport { DebateTalkError } from \"../client.js\";\n\nexport function handleError(err: unknown): never {\n if (err instanceof DebateTalkError) {\n if (err.status === 401 || err.status === 403) {\n console.error(chalk.red(\"Authentication failed.\"));\n console.error(\n chalk.dim(\n \"Set DEBATETALK_API_KEY or create a key at https://console.debatetalk.ai/api-keys\"\n )\n );\n } else if (err.status === 429) {\n console.error(chalk.red(\"Rate limit reached.\"));\n console.error(chalk.dim(\"Free plan: 5 debates/day. Upgrade at https://debatetalk.ai\"));\n } else {\n console.error(chalk.red(`API error (${err.status}): ${err.message}`));\n }\n } else if (err instanceof Error) {\n console.error(chalk.red(err.message));\n } else {\n console.error(chalk.red(\"An unexpected error occurred.\"));\n }\n process.exit(1);\n}\n\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\n\nexport function modelsCommand(): Command {\n return new Command(\"models\")\n .description(\"Show real-time health and latency for all DebateTalk models\")\n .action(async () => {\n const client = new DebateTalkClient();\n try {\n const { models, updated_at } = await client.getModelStatus();\n const online = models.filter((m) => m.status === \"online\").length;\n console.log(\n chalk.bold(`Model Status`) +\n chalk.dim(` — ${online}/${models.length} online (updated ${updated_at})`)\n );\n console.log();\n for (const m of models) {\n const icon =\n m.status === \"online\"\n ? chalk.green(\"✓\")\n : m.status === \"degraded\"\n ? chalk.yellow(\"⚠\")\n : chalk.red(\"✗\");\n const latency =\n m.latency_ms != null ? chalk.dim(` ${m.latency_ms}ms`) : \"\";\n console.log(` ${icon} ${m.display_name}${latency}`);\n }\n } catch (err) {\n handleError(err);\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\n\nexport function recommendCommand(): Command {\n return new Command(\"recommend\")\n .description(\"Get the best model panel for a question\")\n .argument(\"<question>\", \"The question to get recommendations for\")\n .action(async (question: string) => {\n const client = new DebateTalkClient();\n try {\n const rec = await client.recommendModels(question);\n console.log(chalk.bold(`Recommended panel`) + chalk.dim(` for \"${question}\"`));\n console.log(chalk.dim(`Question type: ${rec.question_type}`));\n console.log();\n console.log(` ${chalk.cyan(\"Debaters:\")} ${rec.debaters.join(\", \")}`);\n console.log(` ${chalk.cyan(\"Synthesizer:\")} ${rec.synthesizer}`);\n console.log(` ${chalk.cyan(\"Adjudicator:\")} ${rec.adjudicator}`);\n } catch (err) {\n handleError(err);\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\n\nexport function costCommand(): Command {\n return new Command(\"cost\")\n .description(\"Estimate the credit cost of a debate before running it\")\n .argument(\"<question>\", \"The question to estimate cost for\")\n .option(\"--rounds <n>\", \"Number of deliberation rounds\")\n .action(async (question: string, opts: { rounds?: string }) => {\n const client = new DebateTalkClient();\n try {\n const est = await client.estimateCost({\n question,\n ...(opts.rounds && { rounds: parseInt(opts.rounds, 10) }),\n });\n console.log(chalk.bold(`Cost estimate`));\n console.log();\n console.log(\n ` ${chalk.cyan(\"Total:\")} ${est.estimated_credits} credits` +\n chalk.dim(` (~$${est.estimated_usd.toFixed(2)} USD)`)\n );\n console.log();\n console.log(chalk.dim(\" Breakdown:\"));\n for (const b of est.breakdown) {\n console.log(\n chalk.dim(\n ` • ${b.model} (${b.role}): ~${b.estimated_tokens.toLocaleString()} tokens = ${b.estimated_credits} credits`\n )\n );\n }\n } catch (err) {\n handleError(err);\n }\n });\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { DebateTalkClient } from \"../../client.js\";\nimport { handleError } from \"../utils.js\";\n\nexport function historyCommand(): Command {\n return new Command(\"history\")\n .description(\"List your past debates\")\n .option(\"--limit <n>\", \"Number of debates to show\", \"20\")\n .action(async (opts: { limit: string }) => {\n const client = new DebateTalkClient();\n try {\n const rawLimit = parseInt(opts.limit, 10);\n const { debates, total } = await client.getHistory(\n Number.isNaN(rawLimit) ? 20 : Math.min(Math.max(1, rawLimit), 100)\n );\n if (debates.length === 0) {\n console.log(chalk.dim('No debates yet. Run: dt debate \"your question\"'));\n return;\n }\n console.log(\n chalk.bold(`Debate history`) +\n chalk.dim(` — showing ${debates.length} of ${total}`)\n );\n console.log();\n for (const d of debates) {\n const date = new Date(d.created_at).toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n const share = d.share_token\n ? chalk.dim(` → https://console.debatetalk.ai/share/${d.share_token}`)\n : \"\";\n console.log(\n ` ${chalk.dim(date)} ${d.title}` +\n chalk.dim(` (${d.model_count} models, ${d.status})`) +\n share\n );\n }\n } catch (err) {\n handleError(err);\n }\n });\n}\n"],"mappings":";;;;;;AAAA,SAAS,WAAAA,gBAAe;;;ACAxB,SAAS,eAAe;AACxB,OAAOC,YAAW;AAClB,OAAO,SAAS;;;ACFhB,OAAO,WAAW;AAGX,SAAS,YAAY,KAAqB;AAC/C,MAAI,eAAe,iBAAiB;AAClC,QAAI,IAAI,WAAW,OAAO,IAAI,WAAW,KAAK;AAC5C,cAAQ,MAAM,MAAM,IAAI,wBAAwB,CAAC;AACjD,cAAQ;AAAA,QACN,MAAM;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AAAA,IACF,WAAW,IAAI,WAAW,KAAK;AAC7B,cAAQ,MAAM,MAAM,IAAI,qBAAqB,CAAC;AAC9C,cAAQ,MAAM,MAAM,IAAI,4DAA4D,CAAC;AAAA,IACvF,OAAO;AACL,cAAQ,MAAM,MAAM,IAAI,cAAc,IAAI,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;AAAA,IACtE;AAAA,EACF,WAAW,eAAe,OAAO;AAC/B,YAAQ,MAAM,MAAM,IAAI,IAAI,OAAO,CAAC;AAAA,EACtC,OAAO;AACL,YAAQ,MAAM,MAAM,IAAI,+BAA+B,CAAC;AAAA,EAC1D;AACA,UAAQ,KAAK,CAAC;AAChB;;;ADhBA,SAAS,EAAE,OAAoB,KAAsB;AACnD,SAAO,MAAM,GAAG,KAAK,MAAM,OAAO,GAAG;AACvC;AAEA,SAAS,UAAU,GAAoB;AACrC,MAAI,OAAO,MAAM,SAAU,QAAO;AAClC,MAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,EAAE,IAAI,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,KAAK,IAAI;AAC9E,SAAO,OAAO,KAAK,EAAE;AACvB;AAEO,SAAS,gBAAyB;AACvC,SAAO,IAAI,QAAQ,QAAQ,EACxB,YAAY,wCAAwC,EACpD,SAAS,cAAc,iCAAiC,EACxD;AAAA,IACC;AAAA,IACA;AAAA,EACF,EACC,OAAO,gBAAgB,4CAA4C,EACnE;AAAA,IACC,OACE,UACA,SACG;AACH,YAAM,SAAS,IAAI,iBAAiB;AACpC,YAAM,SAAS;AAAA,QACb;AAAA,QACA,GAAI,KAAK,UAAU,EAAE,QAAQ,KAAK,OAAO,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE;AAAA,QACzE,GAAI,KAAK,UAAU,EAAE,QAAQ,SAAS,KAAK,QAAQ,EAAE,EAAE;AAAA,MACzD;AAEA,YAAM,UAAU,IAAI,uBAAkB,EAAE,MAAM;AAE9C,UAAI;AACF,YAAI,eAAe;AACnB,YAAI,UAAyB;AAC7B,YAAI,WAA0B;AAC9B,YAAI,iBAAqC;AAEzC,yBAAiB,SAAS,OAAO,aAAa,MAAM,GAAG;AACrD,gBAAM,QAAQ,cAAc,KAAK;AACjC,cAAI,SAAS,UAAU,cAAc;AACnC,2BAAe;AACf,oBAAQ,OAAO;AAAA,UACjB;AAEA,cAAI,MAAM,SAAS,aAAa;AAC9B,6BAAiB;AAAA,UACnB;AAEA,cAAI,MAAM,SAAS,mBAAmB;AACpC,kBAAM,OAAO,EAAE,OAAO,UAAU;AAChC,gBAAI,OAAO,SAAS,SAAU,WAAU;AACxC,kBAAM,MAAM,EAAE,OAAO,WAAW;AAChC,gBAAI,OAAO,QAAQ,SAAU,YAAW;AAAA,UAC1C;AAAA,QACF;AAEA,YAAI,gBAAgB;AAClB,kBAAQ,QAAQ,iBAAiB;AACjC,yBAAe,UAAU,gBAAgB,SAAS,QAAQ;AAAA,QAC5D,OAAO;AACL,kBAAQ,KAAK,gCAAgC;AAAA,QAC/C;AAAA,MACF,SAAS,KAAK;AACZ,gBAAQ,KAAK,eAAe;AAC5B,oBAAY,GAAG;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AACJ;AAEA,SAAS,cAAc,OAAmC;AACxD,UAAQ,MAAM,MAAM;AAAA,IAClB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO,yBAA0B,EAAE,OAAO,eAAe,KAA4B,QAAG;AAAA,IAC1F,KAAK;AACH,aAAO,SAAU,EAAE,OAAO,OAAO,KAA4B,GAAG;AAAA,IAClE,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,eAAe,UAAkB,OAAoB,SAAwB,UAA+B;AACnH,QAAM,IAAK,MAAM,QAAQ;AACzB,UAAQ,IAAI;AACZ,UAAQ,IAAIC,OAAM,KAAK,IAAI,QAAQ,GAAG,CAAC;AACvC,MAAI,WAAW,KAAM,SAAQ,IAAIA,OAAM,IAAI,UAAU,QAAQ,QAAQ,CAAC,CAAC,EAAE,CAAC;AAC1E,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,MAAM,qDAAuB,CAAC;AACrD,UAAQ,IAAI,UAAU,EAAE,eAAe,CAAC,CAAC;AACzC,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,OAAO,mDAAqB,CAAC;AACpD,UAAQ,IAAI,UAAU,EAAE,aAAa,CAAC,CAAC;AACvC,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,QAAQ,mDAAqB,CAAC;AACrD,UAAQ,IAAI,UAAU,EAAE,aAAa,CAAC,CAAC;AACvC,UAAQ,IAAI;AACZ,UAAQ,IAAIA,OAAM,KAAK,KAAK,iDAAmB,CAAC;AAChD,UAAQ,IAAI,UAAU,EAAE,WAAW,CAAC,CAAC;AACrC,MAAI,UAAU;AACZ,YAAQ,IAAI;AACZ,YAAQ,IAAIA,OAAM,IAAI,aAAM,QAAQ,EAAE,CAAC;AAAA,EACzC;AACA,UAAQ,IAAI;AACd;;;AEvHA,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;AAIX,SAAS,gBAAyB;AACvC,SAAO,IAAIC,SAAQ,QAAQ,EACxB,YAAY,6DAA6D,EACzE,OAAO,YAAY;AAClB,UAAM,SAAS,IAAI,iBAAiB;AACpC,QAAI;AACF,YAAM,EAAE,QAAQ,WAAW,IAAI,MAAM,OAAO,eAAe;AAC3D,YAAM,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE;AAC3D,cAAQ;AAAA,QACNC,OAAM,KAAK,cAAc,IACvBA,OAAM,IAAI,WAAM,MAAM,IAAI,OAAO,MAAM,oBAAoB,UAAU,GAAG;AAAA,MAC5E;AACA,cAAQ,IAAI;AACZ,iBAAW,KAAK,QAAQ;AACtB,cAAM,OACJ,EAAE,WAAW,WACTA,OAAM,MAAM,QAAG,IACf,EAAE,WAAW,aACXA,OAAM,OAAO,QAAG,IAChBA,OAAM,IAAI,QAAG;AACrB,cAAM,UACJ,EAAE,cAAc,OAAOA,OAAM,IAAI,IAAI,EAAE,UAAU,IAAI,IAAI;AAC3D,gBAAQ,IAAI,KAAK,IAAI,IAAI,EAAE,YAAY,GAAG,OAAO,EAAE;AAAA,MACrD;AAAA,IACF,SAAS,KAAK;AACZ,kBAAY,GAAG;AAAA,IACjB;AAAA,EACF,CAAC;AACL;;;ACjCA,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;AAIX,SAAS,mBAA4B;AAC1C,SAAO,IAAIC,SAAQ,WAAW,EAC3B,YAAY,yCAAyC,EACrD,SAAS,cAAc,yCAAyC,EAChE,OAAO,OAAO,aAAqB;AAClC,UAAM,SAAS,IAAI,iBAAiB;AACpC,QAAI;AACF,YAAM,MAAM,MAAM,OAAO,gBAAgB,QAAQ;AACjD,cAAQ,IAAIC,OAAM,KAAK,mBAAmB,IAAIA,OAAM,IAAI,SAAS,QAAQ,GAAG,CAAC;AAC7E,cAAQ,IAAIA,OAAM,IAAI,kBAAkB,IAAI,aAAa,EAAE,CAAC;AAC5D,cAAQ,IAAI;AACZ,cAAQ,IAAI,KAAKA,OAAM,KAAK,WAAW,CAAC,OAAO,IAAI,SAAS,KAAK,IAAI,CAAC,EAAE;AACxE,cAAQ,IAAI,KAAKA,OAAM,KAAK,cAAc,CAAC,IAAI,IAAI,WAAW,EAAE;AAChE,cAAQ,IAAI,KAAKA,OAAM,KAAK,cAAc,CAAC,IAAI,IAAI,WAAW,EAAE;AAAA,IAClE,SAAS,KAAK;AACZ,kBAAY,GAAG;AAAA,IACjB;AAAA,EACF,CAAC;AACL;;;ACvBA,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;AAIX,SAAS,cAAuB;AACrC,SAAO,IAAIC,SAAQ,MAAM,EACtB,YAAY,wDAAwD,EACpE,SAAS,cAAc,mCAAmC,EAC1D,OAAO,gBAAgB,+BAA+B,EACtD,OAAO,OAAO,UAAkB,SAA8B;AAC7D,UAAM,SAAS,IAAI,iBAAiB;AACpC,QAAI;AACF,YAAM,MAAM,MAAM,OAAO,aAAa;AAAA,QACpC;AAAA,QACA,GAAI,KAAK,UAAU,EAAE,QAAQ,SAAS,KAAK,QAAQ,EAAE,EAAE;AAAA,MACzD,CAAC;AACD,cAAQ,IAAIC,OAAM,KAAK,eAAe,CAAC;AACvC,cAAQ,IAAI;AACZ,cAAQ;AAAA,QACN,KAAKA,OAAM,KAAK,QAAQ,CAAC,IAAI,IAAI,iBAAiB,aAChDA,OAAM,IAAI,OAAO,IAAI,cAAc,QAAQ,CAAC,CAAC,OAAO;AAAA,MACxD;AACA,cAAQ,IAAI;AACZ,cAAQ,IAAIA,OAAM,IAAI,cAAc,CAAC;AACrC,iBAAW,KAAK,IAAI,WAAW;AAC7B,gBAAQ;AAAA,UACNA,OAAM;AAAA,YACJ,cAAS,EAAE,KAAK,KAAK,EAAE,IAAI,OAAO,EAAE,iBAAiB,eAAe,CAAC,aAAa,EAAE,iBAAiB;AAAA,UACvG;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,kBAAY,GAAG;AAAA,IACjB;AAAA,EACF,CAAC;AACL;;;ACpCA,SAAS,WAAAC,gBAAe;AACxB,OAAOC,YAAW;AAIX,SAAS,iBAA0B;AACxC,SAAO,IAAIC,SAAQ,SAAS,EACzB,YAAY,wBAAwB,EACpC,OAAO,eAAe,6BAA6B,IAAI,EACvD,OAAO,OAAO,SAA4B;AACzC,UAAM,SAAS,IAAI,iBAAiB;AACpC,QAAI;AACF,YAAM,WAAW,SAAS,KAAK,OAAO,EAAE;AACxC,YAAM,EAAE,SAAS,MAAM,IAAI,MAAM,OAAO;AAAA,QACtC,OAAO,MAAM,QAAQ,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI,GAAG,QAAQ,GAAG,GAAG;AAAA,MACnE;AACA,UAAI,QAAQ,WAAW,GAAG;AACxB,gBAAQ,IAAIC,OAAM,IAAI,gDAAgD,CAAC;AACvE;AAAA,MACF;AACA,cAAQ;AAAA,QACNA,OAAM,KAAK,gBAAgB,IACzBA,OAAM,IAAI,mBAAc,QAAQ,MAAM,OAAO,KAAK,EAAE;AAAA,MACxD;AACA,cAAQ,IAAI;AACZ,iBAAWC,MAAK,SAAS;AACvB,cAAM,OAAO,IAAI,KAAKA,GAAE,UAAU,EAAE,mBAAmB,SAAS;AAAA,UAC9D,MAAM;AAAA,UACN,OAAO;AAAA,UACP,KAAK;AAAA,QACP,CAAC;AACD,cAAM,QAAQA,GAAE,cACZD,OAAM,IAAI,+CAA0CC,GAAE,WAAW,EAAE,IACnE;AACJ,gBAAQ;AAAA,UACN,KAAKD,OAAM,IAAI,IAAI,CAAC,KAAKC,GAAE,KAAK,KAC9BD,OAAM,IAAI,KAAKC,GAAE,WAAW,YAAYA,GAAE,MAAM,GAAG,IACnD;AAAA,QACJ;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,kBAAY,GAAG;AAAA,IACjB;AAAA,EACF,CAAC;AACL;;;ANrCA,IAAM,UAAU,IAAIC,SAAQ;AAE5B,QACG,KAAK,IAAI,EACT;AAAA,EACC;AAEF,EACC,QAAQ,OAAO;AAElB,QAAQ,WAAW,cAAc,CAAC;AAClC,QAAQ,WAAW,cAAc,CAAC;AAClC,QAAQ,WAAW,iBAAiB,CAAC;AACrC,QAAQ,WAAW,YAAY,CAAC;AAChC,QAAQ,WAAW,eAAe,CAAC;AAEnC,QAAQ,MAAM;","names":["Command","chalk","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","Command","chalk","d","Command"]}
|
package/dist/mcp/server.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
DebateTalkClient
|
|
4
|
-
|
|
3
|
+
DebateTalkClient,
|
|
4
|
+
DebateTalkError
|
|
5
|
+
} from "../chunk-ZE653LAA.js";
|
|
5
6
|
|
|
6
7
|
// src/mcp/server.ts
|
|
7
8
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -35,10 +36,119 @@ var runDebateTool = {
|
|
|
35
36
|
required: ["question"]
|
|
36
37
|
}
|
|
37
38
|
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
function log(server, message) {
|
|
40
|
+
server.sendLoggingMessage({ level: "info", data: message });
|
|
41
|
+
}
|
|
42
|
+
async function handleRunDebate(client, server, args) {
|
|
43
|
+
let debateId = "";
|
|
44
|
+
let questionType = "";
|
|
45
|
+
let models = [];
|
|
46
|
+
let synthesis = null;
|
|
47
|
+
let consensusScore = null;
|
|
48
|
+
let totalRounds = 0;
|
|
49
|
+
let costUsd = null;
|
|
50
|
+
let shareUrl = null;
|
|
51
|
+
const modelResponses = /* @__PURE__ */ new Map();
|
|
52
|
+
try {
|
|
53
|
+
for await (const event of client.streamDebate(args)) {
|
|
54
|
+
const d = (key) => event[key] ?? event.data?.[key];
|
|
55
|
+
if (event.type === "debate_created") {
|
|
56
|
+
const did = d("debate_id");
|
|
57
|
+
if (typeof did === "string") debateId = did;
|
|
58
|
+
const title = d("title");
|
|
59
|
+
log(server, `\u{1F4CB} Debate created: ${title || args.question}`);
|
|
60
|
+
}
|
|
61
|
+
if (event.type === "model_routing") {
|
|
62
|
+
const m = d("models");
|
|
63
|
+
if (Array.isArray(m)) {
|
|
64
|
+
log(server, `\u{1F500} Models selected: ${m.join(", ")}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (event.type === "classification") {
|
|
68
|
+
const qt = d("question_type");
|
|
69
|
+
questionType = typeof qt === "string" ? qt : "";
|
|
70
|
+
const rationale = d("rationale");
|
|
71
|
+
log(server, `\u{1F3F7}\uFE0F Classified as ${questionType}${rationale ? ` \u2014 ${rationale}` : ""}`);
|
|
72
|
+
}
|
|
73
|
+
if (event.type === "debate_start") {
|
|
74
|
+
if (!debateId) {
|
|
75
|
+
const did = d("debate_id");
|
|
76
|
+
if (typeof did === "string") debateId = did;
|
|
77
|
+
}
|
|
78
|
+
const m = d("models");
|
|
79
|
+
models = Array.isArray(m) ? m : [];
|
|
80
|
+
}
|
|
81
|
+
if (event.type === "round_start") {
|
|
82
|
+
const round = d("round");
|
|
83
|
+
const phase = d("phase");
|
|
84
|
+
log(server, `\u{1F504} Round ${round} \u2014 ${phase}`);
|
|
85
|
+
}
|
|
86
|
+
if (event.type === "model_response") {
|
|
87
|
+
const name = d("name");
|
|
88
|
+
const data = event.data ?? event;
|
|
89
|
+
const inner = typeof data["data"] === "object" && data["data"] !== null ? data["data"] : data;
|
|
90
|
+
const answer = inner["answer"];
|
|
91
|
+
const confidence = inner["confidence"];
|
|
92
|
+
if (name) {
|
|
93
|
+
const confStr = confidence != null ? ` (confidence: ${(confidence * 100).toFixed(0)}%)` : "";
|
|
94
|
+
const preview = answer ? answer.slice(0, 200) + (answer.length > 200 ? "\u2026" : "") : "";
|
|
95
|
+
log(server, `\u{1F4AC} ${name}${confStr}: ${preview}`);
|
|
96
|
+
if (answer && !("error" in inner)) {
|
|
97
|
+
modelResponses.set(name, {
|
|
98
|
+
answer,
|
|
99
|
+
confidence: confidence ?? 0
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
if (event.type === "consensus") {
|
|
105
|
+
const data = event.data ?? event;
|
|
106
|
+
const result = typeof data["result"] === "object" && data["result"] !== null ? data["result"] : data;
|
|
107
|
+
const score = result["score"];
|
|
108
|
+
const reached = d("reached");
|
|
109
|
+
if (score != null) consensusScore = score;
|
|
110
|
+
log(server, `\u{1F91D} Consensus${score != null ? ` score: ${score}%` : ""}${reached ? " \u2014 threshold reached" : ""}`);
|
|
111
|
+
}
|
|
112
|
+
if (event.type === "final") {
|
|
113
|
+
const tr = d("total_rounds");
|
|
114
|
+
if (typeof tr === "number") totalRounds = tr;
|
|
115
|
+
}
|
|
116
|
+
if (event.type === "synthesis_start") {
|
|
117
|
+
log(server, `\u2728 Synthesizing final answer\u2026`);
|
|
118
|
+
}
|
|
119
|
+
if (event.type === "debate_complete") {
|
|
120
|
+
const cost = d("cost_usd");
|
|
121
|
+
if (typeof cost === "number") costUsd = cost;
|
|
122
|
+
const url = d("share_url");
|
|
123
|
+
if (typeof url === "string") shareUrl = url;
|
|
124
|
+
const costStr = costUsd != null ? ` \xB7 Cost: $${costUsd.toFixed(4)}` : "";
|
|
125
|
+
log(server, `\u2705 Debate complete${costStr}${shareUrl ? ` \u2014 ${shareUrl}` : ""}`);
|
|
126
|
+
}
|
|
127
|
+
if (event.type === "synthesis") {
|
|
128
|
+
const s = event.data ?? event;
|
|
129
|
+
const stringify = (v) => typeof v === "string" ? v : Array.isArray(v) ? v.map((item, i) => `${i + 1}. ${item}`).join("\n") : String(v ?? "");
|
|
130
|
+
const fa = s["final_answer"];
|
|
131
|
+
const sg = s["strong_ground"];
|
|
132
|
+
const fl = s["fault_lines"];
|
|
133
|
+
const bs = s["blind_spots"];
|
|
134
|
+
const yc = s["your_call"];
|
|
135
|
+
if (sg != null && fl != null && bs != null && yc != null) {
|
|
136
|
+
synthesis = {
|
|
137
|
+
final_answer: stringify(fa),
|
|
138
|
+
strong_ground: stringify(sg),
|
|
139
|
+
fault_lines: stringify(fl),
|
|
140
|
+
blind_spots: stringify(bs),
|
|
141
|
+
your_call: stringify(yc)
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
} catch (err) {
|
|
147
|
+
const message = err instanceof DebateTalkError ? `DebateTalk API error (${err.status}): ${err.message}` : `Debate failed: ${err instanceof Error ? err.message : String(err)}`;
|
|
148
|
+
return { content: [{ type: "text", text: message }], isError: true };
|
|
149
|
+
}
|
|
150
|
+
if (!synthesis) {
|
|
151
|
+
const id = debateId ? `Debate ${debateId}` : "Debate";
|
|
42
152
|
return {
|
|
43
153
|
content: [
|
|
44
154
|
{
|
|
@@ -48,35 +158,47 @@ async function handleRunDebate(client, args) {
|
|
|
48
158
|
]
|
|
49
159
|
};
|
|
50
160
|
}
|
|
51
|
-
const { strong_ground, fault_lines, blind_spots, your_call } =
|
|
52
|
-
const modelList =
|
|
161
|
+
const { final_answer, strong_ground, fault_lines, blind_spots, your_call } = synthesis;
|
|
162
|
+
const modelList = models.length > 0 ? models.join(", ") : "smart routing";
|
|
163
|
+
const lines = [
|
|
164
|
+
`DebateTalk \u2014 ${questionType || "Unknown"} question`,
|
|
165
|
+
`Question: "${args.question}"`,
|
|
166
|
+
`Models: ${modelList}`,
|
|
167
|
+
`Rounds: ${totalRounds}${consensusScore != null ? ` \xB7 Consensus: ${consensusScore}%` : ""}${costUsd != null ? ` \xB7 Cost: $${costUsd.toFixed(4)}` : ""}`,
|
|
168
|
+
`Debate ID: ${debateId}`
|
|
169
|
+
];
|
|
170
|
+
if (final_answer) {
|
|
171
|
+
lines.push(``, `\u2501\u2501\u2501 Final Answer \u2501\u2501\u2501`, final_answer);
|
|
172
|
+
}
|
|
173
|
+
if (modelResponses.size > 0) {
|
|
174
|
+
lines.push(``, `\u2501\u2501\u2501 Model Positions \u2501\u2501\u2501`);
|
|
175
|
+
for (const [name, resp] of modelResponses) {
|
|
176
|
+
lines.push(`**${name}** (${(resp.confidence * 100).toFixed(0)}% confidence):`);
|
|
177
|
+
lines.push(resp.answer);
|
|
178
|
+
lines.push(``);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
lines.push(
|
|
182
|
+
`\u2501\u2501\u2501 Strong Ground \u2501\u2501\u2501`,
|
|
183
|
+
`What all models agreed on:`,
|
|
184
|
+
strong_ground,
|
|
185
|
+
``,
|
|
186
|
+
`\u2501\u2501\u2501 Fault Lines \u2501\u2501\u2501`,
|
|
187
|
+
`Where models genuinely disagreed:`,
|
|
188
|
+
fault_lines,
|
|
189
|
+
``,
|
|
190
|
+
`\u2501\u2501\u2501 Blind Spots \u2501\u2501\u2501`,
|
|
191
|
+
`What all models missed:`,
|
|
192
|
+
blind_spots,
|
|
193
|
+
``,
|
|
194
|
+
`\u2501\u2501\u2501 Your Call \u2501\u2501\u2501`,
|
|
195
|
+
your_call
|
|
196
|
+
);
|
|
197
|
+
if (shareUrl) {
|
|
198
|
+
lines.push(``, `\u{1F517} ${shareUrl}`);
|
|
199
|
+
}
|
|
53
200
|
return {
|
|
54
|
-
content: [
|
|
55
|
-
{
|
|
56
|
-
type: "text",
|
|
57
|
-
text: [
|
|
58
|
-
`DebateTalk \u2014 ${result.question_type} question`,
|
|
59
|
-
`Question: "${result.question}"`,
|
|
60
|
-
`Models: ${modelList}`,
|
|
61
|
-
`Debate ID: ${result.debate_id}`,
|
|
62
|
-
``,
|
|
63
|
-
`\u2501\u2501\u2501 Strong Ground \u2501\u2501\u2501`,
|
|
64
|
-
`What all models agreed on:`,
|
|
65
|
-
strong_ground,
|
|
66
|
-
``,
|
|
67
|
-
`\u2501\u2501\u2501 Fault Lines \u2501\u2501\u2501`,
|
|
68
|
-
`Where models genuinely disagreed:`,
|
|
69
|
-
fault_lines,
|
|
70
|
-
``,
|
|
71
|
-
`\u2501\u2501\u2501 Blind Spots \u2501\u2501\u2501`,
|
|
72
|
-
`What all models missed:`,
|
|
73
|
-
blind_spots,
|
|
74
|
-
``,
|
|
75
|
-
`\u2501\u2501\u2501 Your Call \u2501\u2501\u2501`,
|
|
76
|
-
your_call
|
|
77
|
-
].join("\n")
|
|
78
|
-
}
|
|
79
|
-
]
|
|
201
|
+
content: [{ type: "text", text: lines.join("\n") }]
|
|
80
202
|
};
|
|
81
203
|
}
|
|
82
204
|
|
|
@@ -213,7 +335,7 @@ var getHistoryTool = {
|
|
|
213
335
|
async function handleGetHistory(client, args) {
|
|
214
336
|
const raw = args.limit ?? 20;
|
|
215
337
|
const limit = Number.isFinite(raw) ? Math.min(Math.max(1, raw), 100) : 20;
|
|
216
|
-
const { debates,
|
|
338
|
+
const { debates, pagination } = await client.getHistory(limit);
|
|
217
339
|
if (debates.length === 0) {
|
|
218
340
|
return {
|
|
219
341
|
content: [
|
|
@@ -230,15 +352,16 @@ async function handleGetHistory(client, args) {
|
|
|
230
352
|
month: "short",
|
|
231
353
|
day: "numeric"
|
|
232
354
|
});
|
|
233
|
-
const
|
|
234
|
-
|
|
355
|
+
const modelCount = Object.keys(d.models_config || {}).length;
|
|
356
|
+
const costStr = d.cost_usd != null ? ` \xB7 $${d.cost_usd.toFixed(4)}` : "";
|
|
357
|
+
return `\u2022 [${date}] ${d.title || d.question_preview} (${modelCount} models, ${d.status}${costStr})`;
|
|
235
358
|
});
|
|
236
359
|
return {
|
|
237
360
|
content: [
|
|
238
361
|
{
|
|
239
362
|
type: "text",
|
|
240
363
|
text: [
|
|
241
|
-
`Debate history \u2014 showing ${debates.length} of ${total}`,
|
|
364
|
+
`Debate history \u2014 showing ${debates.length} of ${pagination.total}`,
|
|
242
365
|
``,
|
|
243
366
|
...rows
|
|
244
367
|
].join("\n")
|
|
@@ -269,7 +392,7 @@ function createServer(client) {
|
|
|
269
392
|
const { name, arguments: args = {} } = request.params;
|
|
270
393
|
switch (name) {
|
|
271
394
|
case "run_debate":
|
|
272
|
-
return handleRunDebate(client, args);
|
|
395
|
+
return handleRunDebate(client, server, args);
|
|
273
396
|
case "get_model_status":
|
|
274
397
|
return handleGetModelStatus(client);
|
|
275
398
|
case "recommend_models":
|
package/dist/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/mcp/server.ts","../../src/mcp/tools/run_debate.ts","../../src/mcp/tools/get_model_status.ts","../../src/mcp/tools/recommend_models.ts","../../src/mcp/tools/estimate_cost.ts","../../src/mcp/tools/get_history.ts"],"sourcesContent":["// Server is the low-level class needed for JSON Schema tool definitions.\n// McpServer (the replacement) requires Zod schemas — not compatible with our Tool[] approach.\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { DebateTalkClient } from \"../client.js\";\nimport { runDebateTool, handleRunDebate } from \"./tools/run_debate.js\";\nimport { getModelStatusTool, handleGetModelStatus } from \"./tools/get_model_status.js\";\nimport { recommendModelsTool, handleRecommendModels } from \"./tools/recommend_models.js\";\nimport { estimateCostTool, handleEstimateCost } from \"./tools/estimate_cost.js\";\nimport { getHistoryTool, handleGetHistory } from \"./tools/get_history.js\";\n\nexport const ALL_TOOLS = [\n runDebateTool,\n getModelStatusTool,\n recommendModelsTool,\n estimateCostTool,\n getHistoryTool,\n];\n\nfunction createServer(client: DebateTalkClient): Server {\n const server = new Server(\n { name: \"debatetalk\", version: \"1.0.0\" },\n { capabilities: { tools: {} } }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: ALL_TOOLS,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args = {} } = request.params;\n\n switch (name) {\n case \"run_debate\":\n return handleRunDebate(client, args as Parameters<typeof handleRunDebate>[1]);\n case \"get_model_status\":\n return handleGetModelStatus(client);\n case \"recommend_models\":\n return handleRecommendModels(client, args as Parameters<typeof handleRecommendModels>[1]);\n case \"estimate_cost\":\n return handleEstimateCost(client, args as Parameters<typeof handleEstimateCost>[1]);\n case \"get_history\":\n return handleGetHistory(client, args as Parameters<typeof handleGetHistory>[1]);\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n });\n\n return server;\n}\n\nasync function main() {\n const client = new DebateTalkClient();\n const server = createServer(client);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\n// Start the server when run directly (not when imported in tests).\n// npx invokes the bin symlink (e.g. `.bin/mcp` → `server.js`), so\n// process.argv[1] differs from import.meta.url in both full path and\n// basename. Resolve the symlink via realpath before comparing.\nimport { fileURLToPath } from \"url\";\nimport { realpathSync } from \"fs\";\n\nconst thisFile = fileURLToPath(import.meta.url);\nlet argvFile: string;\ntry {\n argvFile = realpathSync(process.argv[1] ?? \"\");\n} catch {\n argvFile = \"\";\n}\n\nif (thisFile === argvFile) {\n main().catch((err: unknown) => {\n process.stderr.write(\n `DebateTalk MCP server error: ${err instanceof Error ? err.message : String(err)}\\n`\n );\n process.exit(1);\n });\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const runDebateTool: Tool = {\n name: \"run_debate\",\n description:\n \"Run a structured multi-model AI debate on any question. Use this tool when the user asks to 'debate', 'use DebateTalk', 'use DT', 'multi-model', 'multi model', 'get a second opinion', 'stress-test' an idea, or wants multiple AI perspectives on a decision. \" +\n \"Also use it proactively for high-stakes decisions where a single AI answer is insufficient — architecture choices, hiring decisions, strategic bets, predictions, or anything with genuine uncertainty. \" +\n \"Multiple AI models argue independently in a blind round, deliberate, and converge on a 4-part synthesis: \" +\n \"Strong Ground (what all models agree on), Fault Lines (genuine disagreements), \" +\n \"Blind Spots (what all models missed), and Your Call (actionable recommendation). \" +\n \"Requires an API key (Pro or Enterprise plan). Free tier: 5 debates/day.\",\n inputSchema: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description:\n \"The question or topic to debate. Can be a decision, prediction, factual question, or open-ended topic.\",\n },\n models: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Specific model IDs to use as debaters (e.g. [\\\"claude-opus-4-6\\\", \\\"gpt-5.4\\\"]). \" +\n \"Omit to let DebateTalk smart routing pick the best panel automatically.\",\n },\n rounds: {\n type: \"number\",\n description: \"Number of deliberation rounds (default: 2, max depends on plan)\",\n },\n },\n required: [\"question\"],\n },\n};\n\nexport async function handleRunDebate(\n client: DebateTalkClient,\n args: { question: string; models?: string[]; rounds?: number }\n) {\n const result = await client.runDebate(args);\n\n if (!result.synthesis) {\n const id = result.debate_id ? `Debate ${result.debate_id}` : \"Debate\";\n return {\n content: [\n {\n type: \"text\" as const,\n text: `${id} completed but synthesis was not produced. Check your plan limits at https://console.debatetalk.ai`,\n },\n ],\n };\n }\n\n const { strong_ground, fault_lines, blind_spots, your_call } =\n result.synthesis;\n\n const modelList =\n result.models.length > 0 ? result.models.join(\", \") : \"smart routing\";\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: [\n `DebateTalk — ${result.question_type} question`,\n `Question: \"${result.question}\"`,\n `Models: ${modelList}`,\n `Debate ID: ${result.debate_id}`,\n ``,\n `━━━ Strong Ground ━━━`,\n `What all models agreed on:`,\n strong_ground,\n ``,\n `━━━ Fault Lines ━━━`,\n `Where models genuinely disagreed:`,\n fault_lines,\n ``,\n `━━━ Blind Spots ━━━`,\n `What all models missed:`,\n blind_spots,\n ``,\n `━━━ Your Call ━━━`,\n your_call,\n ].join(\"\\n\"),\n },\n ],\n };\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const getModelStatusTool: Tool = {\n name: \"get_model_status\",\n description:\n \"Get real-time health, latency, and uptime for all DebateTalk models. \" +\n \"Use this before running a debate to check which models are currently online. \" +\n \"No API key required.\",\n inputSchema: {\n type: \"object\",\n properties: {},\n },\n};\n\nexport async function handleGetModelStatus(client: DebateTalkClient) {\n const { models, updated_at } = await client.getModelStatus();\n\n const rows = models\n .map((m) => {\n const latency = m.latency_ms != null ? `${m.latency_ms}ms` : \"—\";\n const uptime =\n m.uptime_pct != null ? `${m.uptime_pct.toFixed(1)}%` : \"—\";\n const statusIcon =\n m.status === \"online\" ? \"✓\" : m.status === \"degraded\" ? \"⚠\" : \"✗\";\n return `${statusIcon} ${m.display_name} (${m.provider}) — ${m.status}, latency: ${latency}, uptime: ${uptime}`;\n })\n .join(\"\\n\");\n\n const online = models.filter((m) => m.status === \"online\").length;\n const total = models.length;\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Model Status — ${online}/${total} online (updated ${updated_at})\\n\\n${rows}`,\n },\n ],\n };\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const recommendModelsTool: Tool = {\n name: \"recommend_models\",\n description:\n \"Get the best model panel recommended by DebateTalk smart routing for a specific question. \" +\n \"Returns the ideal debaters, synthesizer, and adjudicator based on the question type. \" +\n \"No API key required.\",\n inputSchema: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"The question or topic you want to debate\",\n },\n },\n required: [\"question\"],\n },\n};\n\nexport async function handleRecommendModels(\n client: DebateTalkClient,\n args: { question: string }\n) {\n const rec = await client.recommendModels(args.question);\n\n const debaterList = rec.debaters.join(\", \");\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: [\n `Recommended panel for \"${args.question}\"`,\n `Question type: ${rec.question_type}`,\n ``,\n `Debaters: ${debaterList}`,\n `Synthesizer: ${rec.synthesizer}`,\n `Adjudicator: ${rec.adjudicator}`,\n ``,\n `To use this panel, run a debate with models: ${rec.debaters.join(\", \")}`,\n ].join(\"\\n\"),\n },\n ],\n };\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const estimateCostTool: Tool = {\n name: \"estimate_cost\",\n description:\n \"Estimate the credit cost of a debate before running it. \" +\n \"Returns total credits, USD cost, and a per-model breakdown. \" +\n \"Requires an API key (Pro or Enterprise plan).\",\n inputSchema: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"The question to estimate cost for\",\n },\n models: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Specific model IDs to use (omit for smart routing)\",\n },\n rounds: {\n type: \"number\",\n description: \"Number of deliberation rounds (default: 2)\",\n },\n },\n required: [\"question\"],\n },\n};\n\nexport async function handleEstimateCost(\n client: DebateTalkClient,\n args: { question: string; models?: string[]; rounds?: number }\n) {\n const estimate = await client.estimateCost(args);\n\n const breakdownRows = estimate.breakdown\n .map(\n (b) =>\n ` • ${b.model} (${b.role}): ~${b.estimated_tokens.toLocaleString()} tokens = ${b.estimated_credits} credits`\n )\n .join(\"\\n\");\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: [\n `Cost estimate for \"${args.question}\"`,\n ``,\n `Total: ${estimate.estimated_credits} credits (~$${estimate.estimated_usd.toFixed(2)} USD)`,\n ``,\n `Breakdown:`,\n breakdownRows,\n ``,\n `Credits refill automatically on Pro plans. View balance at https://console.debatetalk.ai`,\n ].join(\"\\n\"),\n },\n ],\n };\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const getHistoryTool: Tool = {\n name: \"get_history\",\n description:\n \"Retrieve your past DebateTalk debates. \" +\n \"Returns debate titles, dates, model counts, and share links. \" +\n \"Requires an API key (Pro or Enterprise plan).\",\n inputSchema: {\n type: \"object\",\n properties: {\n limit: {\n type: \"number\",\n description: \"Number of debates to return (default: 20, max: 100)\",\n },\n },\n },\n};\n\nexport async function handleGetHistory(\n client: DebateTalkClient,\n args: { limit?: number }\n) {\n const raw = args.limit ?? 20;\n const limit = Number.isFinite(raw) ? Math.min(Math.max(1, raw), 100) : 20;\n const { debates, total } = await client.getHistory(limit);\n\n if (debates.length === 0) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"No debates found. Run your first debate at https://console.debatetalk.ai\",\n },\n ],\n };\n }\n\n const rows = debates.map((d) => {\n const date = new Date(d.created_at).toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n const shareLink = d.share_token\n ? ` — https://console.debatetalk.ai/share/${d.share_token}`\n : \"\";\n return `• [${date}] ${d.title} (${d.model_count} models, ${d.status})${shareLink}`;\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: [\n `Debate history — showing ${debates.length} of ${total}`,\n ``,\n ...rows,\n ].join(\"\\n\"),\n },\n ],\n };\n}\n"],"mappings":";;;;;AAGA,SAAS,cAAc;AACvB,SAAS,4BAA4B;AACrC;AAAA,EACE;AAAA,EACA;AAAA,OACK;;;ACLA,IAAM,gBAAsB;AAAA,EACjC,MAAM;AAAA,EACN,aACE;AAAA,EAMF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aACE;AAAA,MACJ;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,aACE;AAAA,MAEJ;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,UAAU,CAAC,UAAU;AAAA,EACvB;AACF;AAEA,eAAsB,gBACpB,QACA,MACA;AACA,QAAM,SAAS,MAAM,OAAO,UAAU,IAAI;AAE1C,MAAI,CAAC,OAAO,WAAW;AACrB,UAAM,KAAK,OAAO,YAAY,UAAU,OAAO,SAAS,KAAK;AAC7D,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM,GAAG,EAAE;AAAA,QACb;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,EAAE,eAAe,aAAa,aAAa,UAAU,IACzD,OAAO;AAET,QAAM,YACJ,OAAO,OAAO,SAAS,IAAI,OAAO,OAAO,KAAK,IAAI,IAAI;AAExD,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,qBAAgB,OAAO,aAAa;AAAA,UACpC,cAAc,OAAO,QAAQ;AAAA,UAC7B,WAAW,SAAS;AAAA,UACpB,cAAc,OAAO,SAAS;AAAA,UAC9B;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;;;ACrFO,IAAM,qBAA2B;AAAA,EACtC,MAAM;AAAA,EACN,aACE;AAAA,EAGF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY,CAAC;AAAA,EACf;AACF;AAEA,eAAsB,qBAAqB,QAA0B;AACnE,QAAM,EAAE,QAAQ,WAAW,IAAI,MAAM,OAAO,eAAe;AAE3D,QAAM,OAAO,OACV,IAAI,CAAC,MAAM;AACV,UAAM,UAAU,EAAE,cAAc,OAAO,GAAG,EAAE,UAAU,OAAO;AAC7D,UAAM,SACJ,EAAE,cAAc,OAAO,GAAG,EAAE,WAAW,QAAQ,CAAC,CAAC,MAAM;AACzD,UAAM,aACJ,EAAE,WAAW,WAAW,WAAM,EAAE,WAAW,aAAa,WAAM;AAChE,WAAO,GAAG,UAAU,IAAI,EAAE,YAAY,KAAK,EAAE,QAAQ,YAAO,EAAE,MAAM,cAAc,OAAO,aAAa,MAAM;AAAA,EAC9G,CAAC,EACA,KAAK,IAAI;AAEZ,QAAM,SAAS,OAAO,OAAO,CAAC,MAAM,EAAE,WAAW,QAAQ,EAAE;AAC3D,QAAM,QAAQ,OAAO;AAErB,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM,uBAAkB,MAAM,IAAI,KAAK,oBAAoB,UAAU;AAAA;AAAA,EAAQ,IAAI;AAAA,MACnF;AAAA,IACF;AAAA,EACF;AACF;;;ACrCO,IAAM,sBAA4B;AAAA,EACvC,MAAM;AAAA,EACN,aACE;AAAA,EAGF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,UAAU,CAAC,UAAU;AAAA,EACvB;AACF;AAEA,eAAsB,sBACpB,QACA,MACA;AACA,QAAM,MAAM,MAAM,OAAO,gBAAgB,KAAK,QAAQ;AAEtD,QAAM,cAAc,IAAI,SAAS,KAAK,IAAI;AAE1C,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,0BAA0B,KAAK,QAAQ;AAAA,UACvC,kBAAkB,IAAI,aAAa;AAAA,UACnC;AAAA,UACA,aAAa,WAAW;AAAA,UACxB,gBAAgB,IAAI,WAAW;AAAA,UAC/B,gBAAgB,IAAI,WAAW;AAAA,UAC/B;AAAA,UACA,gDAAgD,IAAI,SAAS,KAAK,IAAI,CAAC;AAAA,QACzE,EAAE,KAAK,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;;;AC3CO,IAAM,mBAAyB;AAAA,EACpC,MAAM;AAAA,EACN,aACE;AAAA,EAGF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,UAAU;AAAA,QACR,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO,EAAE,MAAM,SAAS;AAAA,QACxB,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,IACA,UAAU,CAAC,UAAU;AAAA,EACvB;AACF;AAEA,eAAsB,mBACpB,QACA,MACA;AACA,QAAM,WAAW,MAAM,OAAO,aAAa,IAAI;AAE/C,QAAM,gBAAgB,SAAS,UAC5B;AAAA,IACC,CAAC,MACC,YAAO,EAAE,KAAK,KAAK,EAAE,IAAI,OAAO,EAAE,iBAAiB,eAAe,CAAC,aAAa,EAAE,iBAAiB;AAAA,EACvG,EACC,KAAK,IAAI;AAEZ,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,sBAAsB,KAAK,QAAQ;AAAA,UACnC;AAAA,UACA,UAAU,SAAS,iBAAiB,eAAe,SAAS,cAAc,QAAQ,CAAC,CAAC;AAAA,UACpF;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF,EAAE,KAAK,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;;;ACzDO,IAAM,iBAAuB;AAAA,EAClC,MAAM;AAAA,EACN,aACE;AAAA,EAGF,aAAa;AAAA,IACX,MAAM;AAAA,IACN,YAAY;AAAA,MACV,OAAO;AAAA,QACL,MAAM;AAAA,QACN,aAAa;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,iBACpB,QACA,MACA;AACA,QAAM,MAAM,KAAK,SAAS;AAC1B,QAAM,QAAQ,OAAO,SAAS,GAAG,IAAI,KAAK,IAAI,KAAK,IAAI,GAAG,GAAG,GAAG,GAAG,IAAI;AACvE,QAAM,EAAE,SAAS,MAAM,IAAI,MAAM,OAAO,WAAW,KAAK;AAExD,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO;AAAA,MACL,SAAS;AAAA,QACP;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,QAAQ,IAAI,CAAC,MAAM;AAC9B,UAAM,OAAO,IAAI,KAAK,EAAE,UAAU,EAAE,mBAAmB,SAAS;AAAA,MAC9D,MAAM;AAAA,MACN,OAAO;AAAA,MACP,KAAK;AAAA,IACP,CAAC;AACD,UAAM,YAAY,EAAE,cAChB,+CAA0C,EAAE,WAAW,KACvD;AACJ,WAAO,WAAM,IAAI,KAAK,EAAE,KAAK,KAAK,EAAE,WAAW,YAAY,EAAE,MAAM,IAAI,SAAS;AAAA,EAClF,CAAC;AAED,SAAO;AAAA,IACL,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,iCAA4B,QAAQ,MAAM,OAAO,KAAK;AAAA,UACtD;AAAA,UACA,GAAG;AAAA,QACL,EAAE,KAAK,IAAI;AAAA,MACb;AAAA,IACF;AAAA,EACF;AACF;;;ALIA,SAAS,qBAAqB;AAC9B,SAAS,oBAAoB;AApDtB,IAAM,YAAY;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,aAAa,QAAkC;AACtD,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,cAAc,SAAS,QAAQ;AAAA,IACvC,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,EAAE;AAAA,EAChC;AAEA,SAAO,kBAAkB,wBAAwB,aAAa;AAAA,IAC5D,OAAO;AAAA,EACT,EAAE;AAEF,SAAO,kBAAkB,uBAAuB,OAAO,YAAY;AACjE,UAAM,EAAE,MAAM,WAAW,OAAO,CAAC,EAAE,IAAI,QAAQ;AAE/C,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,gBAAgB,QAAQ,IAA6C;AAAA,MAC9E,KAAK;AACH,eAAO,qBAAqB,MAAM;AAAA,MACpC,KAAK;AACH,eAAO,sBAAsB,QAAQ,IAAmD;AAAA,MAC1F,KAAK;AACH,eAAO,mBAAmB,QAAQ,IAAgD;AAAA,MACpF,KAAK;AACH,eAAO,iBAAiB,QAAQ,IAA8C;AAAA,MAChF;AACE,cAAM,IAAI,MAAM,iBAAiB,IAAI,EAAE;AAAA,IAC3C;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEA,eAAe,OAAO;AACpB,QAAM,SAAS,IAAI,iBAAiB;AACpC,QAAM,SAAS,aAAa,MAAM;AAClC,QAAM,YAAY,IAAI,qBAAqB;AAC3C,QAAM,OAAO,QAAQ,SAAS;AAChC;AASA,IAAM,WAAW,cAAc,YAAY,GAAG;AAC9C,IAAI;AACJ,IAAI;AACF,aAAW,aAAa,QAAQ,KAAK,CAAC,KAAK,EAAE;AAC/C,QAAQ;AACN,aAAW;AACb;AAEA,IAAI,aAAa,UAAU;AACzB,OAAK,EAAE,MAAM,CAAC,QAAiB;AAC7B,YAAQ,OAAO;AAAA,MACb,gCAAgC,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA;AAAA,IAClF;AACA,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACH;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/mcp/server.ts","../../src/mcp/tools/run_debate.ts","../../src/mcp/tools/get_model_status.ts","../../src/mcp/tools/recommend_models.ts","../../src/mcp/tools/estimate_cost.ts","../../src/mcp/tools/get_history.ts"],"sourcesContent":["// Server is the low-level class needed for JSON Schema tool definitions.\n// McpServer (the replacement) requires Zod schemas — not compatible with our Tool[] approach.\n// eslint-disable-next-line @typescript-eslint/no-deprecated\nimport { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ListToolsRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { DebateTalkClient } from \"../client.js\";\nimport { runDebateTool, handleRunDebate } from \"./tools/run_debate.js\";\nimport { getModelStatusTool, handleGetModelStatus } from \"./tools/get_model_status.js\";\nimport { recommendModelsTool, handleRecommendModels } from \"./tools/recommend_models.js\";\nimport { estimateCostTool, handleEstimateCost } from \"./tools/estimate_cost.js\";\nimport { getHistoryTool, handleGetHistory } from \"./tools/get_history.js\";\n\nexport const ALL_TOOLS = [\n runDebateTool,\n getModelStatusTool,\n recommendModelsTool,\n estimateCostTool,\n getHistoryTool,\n];\n\nfunction createServer(client: DebateTalkClient): Server {\n const server = new Server(\n { name: \"debatetalk\", version: \"1.0.0\" },\n { capabilities: { tools: {} } }\n );\n\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: ALL_TOOLS,\n }));\n\n server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args = {} } = request.params;\n\n switch (name) {\n case \"run_debate\":\n return handleRunDebate(client, server, args as { question: string; models?: string[]; rounds?: number });\n case \"get_model_status\":\n return handleGetModelStatus(client);\n case \"recommend_models\":\n return handleRecommendModels(client, args as Parameters<typeof handleRecommendModels>[1]);\n case \"estimate_cost\":\n return handleEstimateCost(client, args as Parameters<typeof handleEstimateCost>[1]);\n case \"get_history\":\n return handleGetHistory(client, args as Parameters<typeof handleGetHistory>[1]);\n default:\n throw new Error(`Unknown tool: ${name}`);\n }\n });\n\n return server;\n}\n\nasync function main() {\n const client = new DebateTalkClient();\n const server = createServer(client);\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\n// Start the server when run directly (not when imported in tests).\n// npx invokes the bin symlink (e.g. `.bin/mcp` → `server.js`), so\n// process.argv[1] differs from import.meta.url in both full path and\n// basename. Resolve the symlink via realpath before comparing.\nimport { fileURLToPath } from \"url\";\nimport { realpathSync } from \"fs\";\n\nconst thisFile = fileURLToPath(import.meta.url);\nlet argvFile: string;\ntry {\n argvFile = realpathSync(process.argv[1] ?? \"\");\n} catch {\n argvFile = \"\";\n}\n\nif (thisFile === argvFile) {\n main().catch((err: unknown) => {\n process.stderr.write(\n `DebateTalk MCP server error: ${err instanceof Error ? err.message : String(err)}\\n`\n );\n process.exit(1);\n });\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { DebateTalkError, type DebateTalkClient } from \"../../client.js\";\nimport type { SynthesisData } from \"../../types.js\";\n\nexport const runDebateTool: Tool = {\n name: \"run_debate\",\n description:\n \"Run a structured multi-model AI debate on any question. Use this tool when the user asks to 'debate', 'use DebateTalk', 'use DT', 'multi-model', 'multi model', 'get a second opinion', 'stress-test' an idea, or wants multiple AI perspectives on a decision. \" +\n \"Also use it proactively for high-stakes decisions where a single AI answer is insufficient — architecture choices, hiring decisions, strategic bets, predictions, or anything with genuine uncertainty. \" +\n \"Multiple AI models argue independently in a blind round, deliberate, and converge on a 4-part synthesis: \" +\n \"Strong Ground (what all models agree on), Fault Lines (genuine disagreements), \" +\n \"Blind Spots (what all models missed), and Your Call (actionable recommendation). \" +\n \"Requires an API key (Pro or Enterprise plan). Free tier: 5 debates/day.\",\n inputSchema: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description:\n \"The question or topic to debate. Can be a decision, prediction, factual question, or open-ended topic.\",\n },\n models: {\n type: \"array\",\n items: { type: \"string\" },\n description:\n \"Specific model IDs to use as debaters (e.g. [\\\"claude-opus-4-6\\\", \\\"gpt-5.4\\\"]). \" +\n \"Omit to let DebateTalk smart routing pick the best panel automatically.\",\n },\n rounds: {\n type: \"number\",\n description: \"Number of deliberation rounds (default: 2, max depends on plan)\",\n },\n },\n required: [\"question\"],\n },\n};\n\nfunction log(server: Server, message: string) {\n server.sendLoggingMessage({ level: \"info\", data: message });\n}\n\nexport async function handleRunDebate(\n client: DebateTalkClient,\n server: Server,\n args: { question: string; models?: string[]; rounds?: number }\n) {\n let debateId = \"\";\n let questionType = \"\";\n let models: string[] = [];\n let synthesis: SynthesisData | null = null;\n let consensusScore: number | null = null;\n let totalRounds = 0;\n let costUsd: number | null = null;\n let shareUrl: string | null = null;\n // Track last response per model (overwritten each round to show final position)\n const modelResponses: Map<string, { answer: string; confidence: number }> = new Map();\n\n try {\n for await (const event of client.streamDebate(args)) {\n const d = (key: string) => event[key] ?? event.data?.[key];\n\n if (event.type === \"debate_created\") {\n const did = d(\"debate_id\");\n if (typeof did === \"string\") debateId = did;\n const title = d(\"title\");\n log(server, `📋 Debate created: ${title || args.question}`);\n }\n\n if (event.type === \"model_routing\") {\n const m = d(\"models\");\n if (Array.isArray(m)) {\n log(server, `🔀 Models selected: ${m.join(\", \")}`);\n }\n }\n\n if (event.type === \"classification\") {\n const qt = d(\"question_type\");\n questionType = typeof qt === \"string\" ? qt : \"\";\n const rationale = d(\"rationale\");\n log(server, `🏷️ Classified as ${questionType}${rationale ? ` — ${rationale}` : \"\"}`);\n }\n\n if (event.type === \"debate_start\") {\n if (!debateId) {\n const did = d(\"debate_id\");\n if (typeof did === \"string\") debateId = did;\n }\n const m = d(\"models\");\n models = Array.isArray(m) ? (m as string[]) : [];\n }\n\n if (event.type === \"round_start\") {\n const round = d(\"round\");\n const phase = d(\"phase\");\n log(server, `🔄 Round ${round} — ${phase}`);\n }\n\n if (event.type === \"model_response\") {\n const name = d(\"name\") as string | undefined;\n const data = (event.data ?? event) as Record<string, unknown>;\n const inner = (typeof data[\"data\"] === \"object\" && data[\"data\"] !== null)\n ? data[\"data\"] as Record<string, unknown>\n : data;\n const answer = inner[\"answer\"] as string | undefined;\n const confidence = inner[\"confidence\"] as number | undefined;\n if (name) {\n const confStr = confidence != null ? ` (confidence: ${(confidence * 100).toFixed(0)}%)` : \"\";\n const preview = answer ? answer.slice(0, 200) + (answer.length > 200 ? \"…\" : \"\") : \"\";\n log(server, `💬 ${name}${confStr}: ${preview}`);\n if (answer && !(\"error\" in inner)) {\n modelResponses.set(name, {\n answer: answer,\n confidence: confidence ?? 0,\n });\n }\n }\n }\n\n if (event.type === \"consensus\") {\n const data = (event.data ?? event) as Record<string, unknown>;\n const result = (typeof data[\"result\"] === \"object\" && data[\"result\"] !== null)\n ? data[\"result\"] as Record<string, unknown>\n : data;\n const score = result[\"score\"] as number | undefined;\n const reached = d(\"reached\");\n if (score != null) consensusScore = score;\n log(server, `🤝 Consensus${score != null ? ` score: ${score}%` : \"\"}${reached ? \" — threshold reached\" : \"\"}`);\n }\n\n if (event.type === \"final\") {\n const tr = d(\"total_rounds\");\n if (typeof tr === \"number\") totalRounds = tr;\n }\n\n if (event.type === \"synthesis_start\") {\n log(server, `✨ Synthesizing final answer…`);\n }\n\n if (event.type === \"debate_complete\") {\n const cost = d(\"cost_usd\");\n if (typeof cost === \"number\") costUsd = cost;\n const url = d(\"share_url\");\n if (typeof url === \"string\") shareUrl = url;\n const costStr = costUsd != null ? ` · Cost: $${costUsd.toFixed(4)}` : \"\";\n log(server, `✅ Debate complete${costStr}${shareUrl ? ` — ${shareUrl}` : \"\"}`);\n }\n\n if (event.type === \"synthesis\") {\n const s = (event.data ?? event) as Record<string, unknown>;\n const stringify = (v: unknown): string =>\n typeof v === \"string\" ? v : Array.isArray(v) ? v.map((item, i) => `${i + 1}. ${item}`).join(\"\\n\") : String(v ?? \"\");\n const fa = s[\"final_answer\"];\n const sg = s[\"strong_ground\"];\n const fl = s[\"fault_lines\"];\n const bs = s[\"blind_spots\"];\n const yc = s[\"your_call\"];\n if (sg != null && fl != null && bs != null && yc != null) {\n synthesis = {\n final_answer: stringify(fa),\n strong_ground: stringify(sg),\n fault_lines: stringify(fl),\n blind_spots: stringify(bs),\n your_call: stringify(yc),\n };\n }\n }\n }\n } catch (err) {\n const message =\n err instanceof DebateTalkError\n ? `DebateTalk API error (${err.status}): ${err.message}`\n : `Debate failed: ${err instanceof Error ? err.message : String(err)}`;\n return { content: [{ type: \"text\" as const, text: message }], isError: true };\n }\n\n if (!synthesis) {\n const id = debateId ? `Debate ${debateId}` : \"Debate\";\n return {\n content: [\n {\n type: \"text\" as const,\n text: `${id} completed but synthesis was not produced. Check your plan limits at https://console.debatetalk.ai`,\n },\n ],\n };\n }\n\n const { final_answer, strong_ground, fault_lines, blind_spots, your_call } = synthesis;\n const modelList = models.length > 0 ? models.join(\", \") : \"smart routing\";\n\n const lines: string[] = [\n `DebateTalk — ${questionType || \"Unknown\"} question`,\n `Question: \"${args.question}\"`,\n `Models: ${modelList}`,\n `Rounds: ${totalRounds}${consensusScore != null ? ` · Consensus: ${consensusScore}%` : \"\"}${costUsd != null ? ` · Cost: $${costUsd.toFixed(4)}` : \"\"}`,\n `Debate ID: ${debateId}`,\n ];\n\n // Final answer — the main conclusion\n if (final_answer) {\n lines.push(``, `━━━ Final Answer ━━━`, final_answer);\n }\n\n // Individual model positions (final round)\n if (modelResponses.size > 0) {\n lines.push(``, `━━━ Model Positions ━━━`);\n for (const [name, resp] of modelResponses) {\n lines.push(`**${name}** (${(resp.confidence * 100).toFixed(0)}% confidence):`);\n lines.push(resp.answer);\n lines.push(``);\n }\n }\n\n // Synthesis sections\n lines.push(\n `━━━ Strong Ground ━━━`,\n `What all models agreed on:`,\n strong_ground,\n ``,\n `━━━ Fault Lines ━━━`,\n `Where models genuinely disagreed:`,\n fault_lines,\n ``,\n `━━━ Blind Spots ━━━`,\n `What all models missed:`,\n blind_spots,\n ``,\n `━━━ Your Call ━━━`,\n your_call,\n );\n\n if (shareUrl) {\n lines.push(``, `🔗 ${shareUrl}`);\n }\n\n return {\n content: [{ type: \"text\" as const, text: lines.join(\"\\n\") }],\n };\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const getModelStatusTool: Tool = {\n name: \"get_model_status\",\n description:\n \"Get real-time health, latency, and uptime for all DebateTalk models. \" +\n \"Use this before running a debate to check which models are currently online. \" +\n \"No API key required.\",\n inputSchema: {\n type: \"object\",\n properties: {},\n },\n};\n\nexport async function handleGetModelStatus(client: DebateTalkClient) {\n const { models, updated_at } = await client.getModelStatus();\n\n const rows = models\n .map((m) => {\n const latency = m.latency_ms != null ? `${m.latency_ms}ms` : \"—\";\n const uptime =\n m.uptime_pct != null ? `${m.uptime_pct.toFixed(1)}%` : \"—\";\n const statusIcon =\n m.status === \"online\" ? \"✓\" : m.status === \"degraded\" ? \"⚠\" : \"✗\";\n return `${statusIcon} ${m.display_name} (${m.provider}) — ${m.status}, latency: ${latency}, uptime: ${uptime}`;\n })\n .join(\"\\n\");\n\n const online = models.filter((m) => m.status === \"online\").length;\n const total = models.length;\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: `Model Status — ${online}/${total} online (updated ${updated_at})\\n\\n${rows}`,\n },\n ],\n };\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const recommendModelsTool: Tool = {\n name: \"recommend_models\",\n description:\n \"Get the best model panel recommended by DebateTalk smart routing for a specific question. \" +\n \"Returns the ideal debaters, synthesizer, and adjudicator based on the question type. \" +\n \"No API key required.\",\n inputSchema: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"The question or topic you want to debate\",\n },\n },\n required: [\"question\"],\n },\n};\n\nexport async function handleRecommendModels(\n client: DebateTalkClient,\n args: { question: string }\n) {\n const rec = await client.recommendModels(args.question);\n\n const debaterList = rec.debaters.join(\", \");\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: [\n `Recommended panel for \"${args.question}\"`,\n `Question type: ${rec.question_type}`,\n ``,\n `Debaters: ${debaterList}`,\n `Synthesizer: ${rec.synthesizer}`,\n `Adjudicator: ${rec.adjudicator}`,\n ``,\n `To use this panel, run a debate with models: ${rec.debaters.join(\", \")}`,\n ].join(\"\\n\"),\n },\n ],\n };\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const estimateCostTool: Tool = {\n name: \"estimate_cost\",\n description:\n \"Estimate the credit cost of a debate before running it. \" +\n \"Returns total credits, USD cost, and a per-model breakdown. \" +\n \"Requires an API key (Pro or Enterprise plan).\",\n inputSchema: {\n type: \"object\",\n properties: {\n question: {\n type: \"string\",\n description: \"The question to estimate cost for\",\n },\n models: {\n type: \"array\",\n items: { type: \"string\" },\n description: \"Specific model IDs to use (omit for smart routing)\",\n },\n rounds: {\n type: \"number\",\n description: \"Number of deliberation rounds (default: 2)\",\n },\n },\n required: [\"question\"],\n },\n};\n\nexport async function handleEstimateCost(\n client: DebateTalkClient,\n args: { question: string; models?: string[]; rounds?: number }\n) {\n const estimate = await client.estimateCost(args);\n\n const breakdownRows = estimate.breakdown\n .map(\n (b) =>\n ` • ${b.model} (${b.role}): ~${b.estimated_tokens.toLocaleString()} tokens = ${b.estimated_credits} credits`\n )\n .join(\"\\n\");\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: [\n `Cost estimate for \"${args.question}\"`,\n ``,\n `Total: ${estimate.estimated_credits} credits (~$${estimate.estimated_usd.toFixed(2)} USD)`,\n ``,\n `Breakdown:`,\n breakdownRows,\n ``,\n `Credits refill automatically on Pro plans. View balance at https://console.debatetalk.ai`,\n ].join(\"\\n\"),\n },\n ],\n };\n}\n","import type { Tool } from \"@modelcontextprotocol/sdk/types.js\";\nimport type { DebateTalkClient } from \"../../client.js\";\n\nexport const getHistoryTool: Tool = {\n name: \"get_history\",\n description:\n \"Retrieve your past DebateTalk debates. \" +\n \"Returns debate titles, dates, model counts, and share links. \" +\n \"Requires an API key (Pro or Enterprise plan).\",\n inputSchema: {\n type: \"object\",\n properties: {\n limit: {\n type: \"number\",\n description: \"Number of debates to return (default: 20, max: 100)\",\n },\n },\n },\n};\n\nexport async function handleGetHistory(\n client: DebateTalkClient,\n args: { limit?: number }\n) {\n const raw = args.limit ?? 20;\n const limit = Number.isFinite(raw) ? Math.min(Math.max(1, raw), 100) : 20;\n const { debates, pagination } = await client.getHistory(limit);\n\n if (debates.length === 0) {\n return {\n content: [\n {\n type: \"text\" as const,\n text: \"No debates found. Run your first debate at https://console.debatetalk.ai\",\n },\n ],\n };\n }\n\n const rows = debates.map((d) => {\n const date = new Date(d.created_at).toLocaleDateString(\"en-US\", {\n year: \"numeric\",\n month: \"short\",\n day: \"numeric\",\n });\n const modelCount = Object.keys(d.models_config || {}).length;\n const costStr = d.cost_usd != null ? ` · $${d.cost_usd.toFixed(4)}` : \"\";\n return `• [${date}] ${d.title || d.question_preview} (${modelCount} models, ${d.status}${costStr})`;\n });\n\n return {\n content: [\n {\n type: \"text\" as const,\n text: [\n `Debate history — showing ${debates.length} of ${pagination.total}`,\n ``,\n ...rows,\n ].join(\"\\n\"),\n },\n ],\n };\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { EventSourceParserStream } from \"eventsource-parser/stream\";\nimport type {\n ModelStatusResponse,\n RecommendResponse,\n EstimateCostParams,\n CostEstimate,\n HistoryResponse,\n DebateParams,\n DebateEvent,\n DebateResult,\n ApiErrorBody,\n SynthesisData,\n} from \"./types.js\";\n\nconst BASE_URL = \"https://engine.debatetalk.ai\";\n\nexport class DebateTalkError extends Error {\n constructor(\n public readonly status: number,\n message: string,\n public readonly code?: string\n ) {\n super(message);\n this.name = \"DebateTalkError\";\n }\n}\n\nexport class DebateTalkClient {\n private readonly apiKey: string | undefined;\n\n constructor(apiKey?: string) {\n this.apiKey = apiKey ?? process.env[\"DEBATETALK_API_KEY\"];\n }\n\n private get authHeaders(): Record<string, string> {\n if (!this.apiKey) return {};\n return { Authorization: `Bearer ${this.apiKey}` };\n }\n\n private get baseHeaders(): Record<string, string> {\n return { \"Content-Type\": \"application/json\", ...this.authHeaders };\n }\n\n private requireAuth(): void {\n if (!this.apiKey) {\n throw new Error(\n \"DEBATETALK_API_KEY is required for this operation. \" +\n \"Create one at https://console.debatetalk.ai/api-keys\"\n );\n }\n }\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown\n ): Promise<T> {\n const res = await fetch(`${BASE_URL}${path}`, {\n method,\n headers: this.baseHeaders,\n ...(body !== undefined && { body: JSON.stringify(body) }),\n });\n\n if (!res.ok) {\n const payload = await res.json().catch(() => ({\n error: { code: \"unknown\", message: res.statusText },\n })) as ApiErrorBody;\n throw new DebateTalkError(\n res.status,\n payload.error?.message ?? res.statusText,\n payload.error?.code\n );\n }\n\n return res.json() as Promise<T>;\n }\n\n // ── Public endpoints (no auth required) ──────────────────────────────────\n\n async getModelStatus(): Promise<ModelStatusResponse> {\n return this.request<ModelStatusResponse>(\"GET\", \"/v1/public/model-status\");\n }\n\n async recommendModels(question: string): Promise<RecommendResponse> {\n return this.request<RecommendResponse>(\"POST\", \"/v1/models/recommend\", {\n question,\n });\n }\n\n // ── Authenticated endpoints ───────────────────────────────────────────────\n\n async estimateCost(params: EstimateCostParams): Promise<CostEstimate> {\n this.requireAuth();\n return this.request<CostEstimate>(\"POST\", \"/v1/user/estimate-cost\", params);\n }\n\n async getHistory(limit = 20): Promise<HistoryResponse> {\n this.requireAuth();\n return this.request<HistoryResponse>(\n \"GET\",\n `/v1/user/history?limit=${limit}`\n );\n }\n\n async *streamDebate(params: DebateParams): AsyncGenerator<DebateEvent> {\n this.requireAuth();\n\n const res = await fetch(`${BASE_URL}/debate`, {\n method: \"POST\",\n headers: { ...this.baseHeaders, Accept: \"text/event-stream\" },\n body: JSON.stringify(params),\n });\n\n if (!res.ok) {\n const payload = await res.json().catch(() => ({\n error: { code: \"unknown\", message: res.statusText },\n })) as ApiErrorBody;\n throw new DebateTalkError(\n res.status,\n payload.error?.message ?? res.statusText,\n payload.error?.code\n );\n }\n\n if (!res.body) throw new DebateTalkError(0, \"No response body\");\n\n const stream = res.body\n .pipeThrough(new TextDecoderStream())\n .pipeThrough(new EventSourceParserStream());\n\n for await (const event of stream) {\n if (!event.data || event.data === \"[DONE]\") continue;\n try {\n yield JSON.parse(event.data) as DebateEvent;\n } catch {\n // skip malformed events\n }\n }\n }\n\n async runDebate(params: DebateParams): Promise<DebateResult> {\n const events: DebateEvent[] = [];\n let debateId = \"\";\n let questionType = \"\";\n let models: string[] = [];\n let synthesis: SynthesisData | null = null;\n\n for await (const event of this.streamDebate(params)) {\n events.push(event);\n\n if (event.type === \"debate_start\") {\n debateId = typeof event.data[\"debate_id\"] === \"string\" ? event.data[\"debate_id\"] : \"\";\n models = Array.isArray(event.data[\"models\"]) ? (event.data[\"models\"] as string[]) : [];\n }\n if (event.type === \"classification\") {\n questionType = typeof event.data[\"question_type\"] === \"string\" ? event.data[\"question_type\"] : \"\";\n }\n if (event.type === \"synthesis\") {\n const d = event.data;\n if (\n typeof d[\"strong_ground\"] === \"string\" &&\n typeof d[\"fault_lines\"] === \"string\" &&\n typeof d[\"blind_spots\"] === \"string\" &&\n typeof d[\"your_call\"] === \"string\"\n ) {\n synthesis = d as unknown as SynthesisData;\n }\n }\n }\n\n return {\n debate_id: debateId,\n question: params.question,\n question_type: questionType,\n models,\n synthesis,\n events,\n };\n }\n}\n"],"mappings":"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","names":[]}
|