converse-mcp-server 2.22.8 → 2.25.1

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.
@@ -8,6 +8,7 @@
8
8
  // Import individual tools
9
9
  import { chatTool } from './chat.js';
10
10
  import { consensusTool } from './consensus.js';
11
+ import { conversationTool } from './conversation.js';
11
12
  import { checkStatusTool } from './checkStatus.js';
12
13
  import { cancelJobTool } from './cancelJob.js';
13
14
 
@@ -19,6 +20,7 @@ import { cancelJobTool } from './cancelJob.js';
19
20
  const tools = {
20
21
  chat: chatTool,
21
22
  consensus: consensusTool,
23
+ conversation: conversationTool,
22
24
  check_status: checkStatusTool,
23
25
  cancel_job: cancelJobTool,
24
26
  };
@@ -45,8 +47,8 @@ export function getTools(config = null) {
45
47
  // Clone the tool to avoid mutating the original
46
48
  const clonedTool = tool;
47
49
 
48
- // For chat and consensus tools, remove the 'async' parameter from their schemas
49
- if (name === 'chat' || name === 'consensus') {
50
+ // For chat, consensus, and conversation tools, remove the 'async' parameter from their schemas
51
+ if (name === 'chat' || name === 'consensus' || name === 'conversation') {
50
52
  // Create a modified inputSchema without the async parameter
51
53
  const modifiedSchema = {
52
54
  ...tool.inputSchema,
@@ -170,6 +170,14 @@ export async function formatHumanReadableStatus(
170
170
  if (jobStatus.models_list) {
171
171
  statusLine += ` | ${jobStatus.models_list}`;
172
172
  }
173
+ } else if (jobStatus.tool === 'conversation') {
174
+ // Add turn progress and models list for conversation (x/y turns)
175
+ if (jobStatus.conversation_progress) {
176
+ statusLine += ` | ${jobStatus.conversation_progress} turns`;
177
+ }
178
+ if (jobStatus.models_list) {
179
+ statusLine += ` | ${jobStatus.models_list}`;
180
+ }
173
181
  } else if (jobStatus.tool === 'chat') {
174
182
  // Add provider/model for chat
175
183
  if (jobStatus.provider && jobStatus.model) {
@@ -338,6 +346,7 @@ export function formatJobStatus(job, options = {}) {
338
346
  model: job.model || null,
339
347
  models_list: job.models_list || null,
340
348
  consensus_progress: job.consensus_progress || null,
349
+ conversation_progress: job.conversation_progress || null,
341
350
  // Include new metadata fields if present
342
351
  accumulated_content: job.accumulated_content || null,
343
352
  title: job.title || null,
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Model Routing Helpers
3
+ *
4
+ * Pure helpers for mapping model specifications to providers and resolving
5
+ * "auto" model names to a provider's default model. Extracted so multiple
6
+ * tools (consensus, conversation) can share the same routing logic without
7
+ * importing from another tool module (which would risk circular dependencies).
8
+ */
9
+
10
+ /**
11
+ * Get default model for a provider
12
+ * @param {string} providerName - Provider name
13
+ * @returns {string} Default model name for the provider
14
+ */
15
+ export function getDefaultModelForProvider(providerName) {
16
+ const defaults = {
17
+ codex: 'codex',
18
+ 'gemini-cli': 'gemini',
19
+ claude: 'claude',
20
+ copilot: 'copilot',
21
+ openai: 'gpt-5',
22
+ xai: 'grok-4-0709',
23
+ google: 'gemini-pro',
24
+ anthropic: 'claude-sonnet-4-20250514',
25
+ mistral: 'magistral-medium-2506',
26
+ deepseek: 'deepseek-reasoner',
27
+ openrouter: 'qwen/qwen3-coder',
28
+ };
29
+
30
+ return defaults[providerName] || 'gpt-5';
31
+ }
32
+
33
+ /**
34
+ * Resolve "auto" model to default model for the provider
35
+ * @param {string} model - Model name (may be "auto")
36
+ * @param {string} providerName - Resolved provider name
37
+ * @returns {string} Concrete model name
38
+ */
39
+ export function resolveAutoModel(model, providerName) {
40
+ if (model.toLowerCase() !== 'auto') {
41
+ return model;
42
+ }
43
+
44
+ return getDefaultModelForProvider(providerName);
45
+ }
46
+
47
+ /**
48
+ * Map model name to provider name
49
+ * @param {string} model - Model name
50
+ * @param {object} providers - Map of available provider instances keyed by name
51
+ * @returns {string} Provider name
52
+ */
53
+ export function mapModelToProvider(model, providers) {
54
+ const modelLower = model.toLowerCase();
55
+
56
+ // Handle "auto" - prioritize: codex > gemini-cli > claude > copilot > openai
57
+ if (modelLower === 'auto') {
58
+ if (providers['codex']) {
59
+ return 'codex';
60
+ }
61
+ if (providers['gemini-cli']) {
62
+ return 'gemini-cli';
63
+ }
64
+ if (providers['claude']) {
65
+ return 'claude';
66
+ }
67
+ if (providers['copilot']) {
68
+ return 'copilot';
69
+ }
70
+ return 'openai';
71
+ }
72
+
73
+ // Check Codex (exact match only - don't route "gpt-5-codex" etc to Codex provider)
74
+ if (modelLower === 'codex') {
75
+ return 'codex';
76
+ }
77
+
78
+ // Check Gemini CLI (exact match only - routes to CLI provider instead of Google API)
79
+ if (modelLower === 'gemini' || modelLower === 'gemini-cli') {
80
+ return 'gemini-cli';
81
+ }
82
+
83
+ // Check Claude SDK (exact match only - routes to SDK provider instead of Anthropic API)
84
+ if (
85
+ modelLower === 'claude' ||
86
+ modelLower === 'claude-sdk' ||
87
+ modelLower === 'claude-code'
88
+ ) {
89
+ return 'claude';
90
+ }
91
+
92
+ // Check Copilot SDK (exact match only - routes to SDK provider)
93
+ if (
94
+ modelLower === 'copilot' ||
95
+ modelLower === 'copilot-sdk' ||
96
+ modelLower === 'github-copilot'
97
+ ) {
98
+ return 'copilot';
99
+ }
100
+
101
+ // Check copilot: prefix (e.g., copilot:gpt-5.2, copilot:claude-sonnet-4.6)
102
+ // Must be before slash-format and keyword matching to prevent misrouting
103
+ if (modelLower.startsWith('copilot:')) {
104
+ return 'copilot';
105
+ }
106
+
107
+ // Check OpenRouter-specific patterns first
108
+ if (
109
+ modelLower === 'openrouter auto' ||
110
+ modelLower === 'auto router' ||
111
+ modelLower === 'auto-router' ||
112
+ modelLower === 'openrouter-auto'
113
+ ) {
114
+ return 'openrouter';
115
+ }
116
+
117
+ // If model contains "/", check if native provider supports it
118
+ if (modelLower.includes('/')) {
119
+ // Check each provider to see if they have this exact model
120
+ for (const [providerName, provider] of Object.entries(providers)) {
121
+ if (provider && provider.getModelConfig) {
122
+ const modelConfig = provider.getModelConfig(model);
123
+ if (
124
+ modelConfig &&
125
+ !modelConfig.isDynamic &&
126
+ !modelConfig.needsApiUpdate
127
+ ) {
128
+ // Model exists in this provider's static list
129
+ return providerName;
130
+ }
131
+ }
132
+ }
133
+ // No native provider has this model, route to OpenRouter
134
+ return 'openrouter';
135
+ }
136
+
137
+ // For non-slash models, use keyword matching as before
138
+
139
+ // OpenAI models
140
+ if (
141
+ modelLower.includes('gpt') ||
142
+ modelLower.includes('o1') ||
143
+ modelLower.includes('o3') ||
144
+ modelLower.includes('o4')
145
+ ) {
146
+ return 'openai';
147
+ }
148
+
149
+ // XAI models
150
+ if (modelLower.includes('grok')) {
151
+ return 'xai';
152
+ }
153
+
154
+ // Google models
155
+ if (
156
+ modelLower.includes('flash') ||
157
+ modelLower.includes('pro') ||
158
+ modelLower === 'google'
159
+ ) {
160
+ return 'google';
161
+ }
162
+
163
+ // Anthropic models
164
+ if (
165
+ modelLower.includes('claude') ||
166
+ modelLower.includes('opus') ||
167
+ modelLower.includes('sonnet') ||
168
+ modelLower.includes('haiku')
169
+ ) {
170
+ return 'anthropic';
171
+ }
172
+
173
+ // Mistral models
174
+ if (modelLower.includes('mistral') || modelLower.includes('magistral')) {
175
+ return 'mistral';
176
+ }
177
+
178
+ // DeepSeek models
179
+ if (
180
+ modelLower.includes('deepseek') ||
181
+ modelLower === 'reasoner' ||
182
+ modelLower === 'r1' ||
183
+ modelLower === 'chat'
184
+ ) {
185
+ return 'deepseek';
186
+ }
187
+
188
+ // OpenRouter models (specific model patterns)
189
+ if (
190
+ modelLower.includes('qwen') ||
191
+ modelLower.includes('kimi') ||
192
+ modelLower.includes('moonshot') ||
193
+ modelLower === 'k2'
194
+ ) {
195
+ return 'openrouter';
196
+ }
197
+
198
+ // Default fallback
199
+ return 'openai';
200
+ }