converse-mcp-server 2.22.7 → 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.
- package/LICENSE +18 -18
- package/docs/ALTERNATIVE_PROVIDERS.md +449 -449
- package/docs/API.md +164 -4
- package/docs/ARCHITECTURE.md +551 -551
- package/docs/EXAMPLES.md +98 -0
- package/package.json +13 -13
- package/src/async/asyncJobStore.js +2 -2
- package/src/providers/anthropic.js +35 -4
- package/src/providers/claude.js +1 -1
- package/src/providers/gemini-cli.js +33 -2
- package/src/providers/google.js +26 -0
- package/src/systemPrompts.js +33 -0
- package/src/tools/conversation.js +1217 -0
- package/src/tools/index.js +4 -2
- package/src/utils/formatStatus.js +9 -0
- package/src/utils/modelRouting.js +200 -0
package/src/tools/index.js
CHANGED
|
@@ -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
|
|
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
|
+
}
|