converse-mcp-server 2.3.1 → 2.4.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/README.md +771 -738
- package/docs/API.md +10 -1
- package/docs/PROVIDERS.md +8 -4
- package/package.json +12 -12
- package/src/async/asyncJobStore.js +82 -52
- package/src/async/eventBus.js +25 -20
- package/src/async/fileCache.js +121 -40
- package/src/async/jobRunner.js +65 -39
- package/src/async/providerStreamNormalizer.js +203 -117
- package/src/config.js +374 -102
- package/src/continuationStore.js +32 -24
- package/src/index.js +45 -25
- package/src/prompts/helpPrompt.js +328 -305
- package/src/providers/anthropic.js +303 -119
- package/src/providers/codex.js +103 -45
- package/src/providers/deepseek.js +24 -8
- package/src/providers/google.js +337 -93
- package/src/providers/index.js +1 -1
- package/src/providers/interface.js +16 -11
- package/src/providers/mistral.js +179 -69
- package/src/providers/openai-compatible.js +231 -94
- package/src/providers/openai.js +1094 -914
- package/src/providers/openrouter-endpoints-client.js +220 -216
- package/src/providers/openrouter.js +426 -381
- package/src/providers/xai.js +153 -56
- package/src/resources/helpResource.js +70 -67
- package/src/router.js +95 -67
- package/src/services/summarizationService.js +51 -24
- package/src/systemPrompts.js +89 -89
- package/src/tools/cancelJob.js +31 -19
- package/src/tools/chat.js +997 -883
- package/src/tools/checkStatus.js +86 -65
- package/src/tools/consensus.js +400 -234
- package/src/tools/index.js +39 -16
- package/src/transport/httpTransport.js +82 -55
- package/src/utils/contextProcessor.js +54 -37
- package/src/utils/errorHandler.js +95 -45
- package/src/utils/fileValidator.js +107 -98
- package/src/utils/formatStatus.js +122 -64
- package/src/utils/logger.js +459 -449
- package/src/utils/pathUtils.js +2 -2
- package/src/utils/tokenLimiter.js +216 -216
|
@@ -21,11 +21,16 @@ export async function formatJobListHumanReadable(jobsList, dependencies = {}) {
|
|
|
21
21
|
|
|
22
22
|
// Summary line - include cancelled jobs if any
|
|
23
23
|
const summaryParts = [];
|
|
24
|
-
if (jobsList.summary.active_jobs > 0)
|
|
25
|
-
|
|
26
|
-
if (jobsList.summary.
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
if (jobsList.summary.active_jobs > 0)
|
|
25
|
+
summaryParts.push(`${jobsList.summary.active_jobs} active`);
|
|
26
|
+
if (jobsList.summary.completed_jobs > 0)
|
|
27
|
+
summaryParts.push(`${jobsList.summary.completed_jobs} completed`);
|
|
28
|
+
if (jobsList.summary.failed_jobs > 0)
|
|
29
|
+
summaryParts.push(`${jobsList.summary.failed_jobs} failed`);
|
|
30
|
+
if (jobsList.summary.cancelled_jobs > 0)
|
|
31
|
+
summaryParts.push(`${jobsList.summary.cancelled_jobs} cancelled`);
|
|
32
|
+
const summaryStr =
|
|
33
|
+
summaryParts.length > 0 ? summaryParts.join(', ') : '0 jobs';
|
|
29
34
|
parts.push(`📊 Jobs Summary: ${summaryStr}`);
|
|
30
35
|
|
|
31
36
|
if (jobsList.jobs.length === 0) {
|
|
@@ -37,23 +42,28 @@ export async function formatJobListHumanReadable(jobsList, dependencies = {}) {
|
|
|
37
42
|
|
|
38
43
|
// List each job
|
|
39
44
|
for (const job of jobsList.jobs) {
|
|
40
|
-
const timeStr =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
45
|
+
const timeStr =
|
|
46
|
+
job.elapsed_seconds >= 60
|
|
47
|
+
? `${Math.floor(job.elapsed_seconds / 60)}m${Math.round(job.elapsed_seconds % 60)}s`
|
|
48
|
+
: `${job.elapsed_seconds.toFixed(1)}s`;
|
|
49
|
+
|
|
50
|
+
const statusEmoji =
|
|
51
|
+
{
|
|
52
|
+
queued: '⏳',
|
|
53
|
+
running: '🔄',
|
|
54
|
+
completed: '✅',
|
|
55
|
+
failed: '❌',
|
|
56
|
+
cancelled: '⛔',
|
|
57
|
+
completed_with_errors: '⚠️',
|
|
58
|
+
}[job.status] || '❓';
|
|
59
|
+
|
|
60
|
+
const provider =
|
|
61
|
+
job.provider || (job.tool === 'consensus' ? 'multiple' : 'unknown');
|
|
54
62
|
|
|
55
63
|
// Format start time as readable date/time
|
|
56
|
-
const startTime = job.created_at
|
|
64
|
+
const startTime = job.created_at
|
|
65
|
+
? new Date(job.created_at).toLocaleString()
|
|
66
|
+
: 'unknown';
|
|
57
67
|
|
|
58
68
|
// Format: emoji STATUS | TOOL | id | sequence | started | time | [progress for consensus only] | provider
|
|
59
69
|
const sequenceStr = '1/1';
|
|
@@ -78,9 +88,10 @@ export async function formatJobListHumanReadable(jobsList, dependencies = {}) {
|
|
|
78
88
|
// Add final summary snippet for completed jobs
|
|
79
89
|
if (job.status === 'completed' && job.final_summary) {
|
|
80
90
|
// Indent and truncate summary for list view
|
|
81
|
-
const summarySnippet =
|
|
82
|
-
|
|
83
|
-
|
|
91
|
+
const summarySnippet =
|
|
92
|
+
job.final_summary.length > 100
|
|
93
|
+
? job.final_summary.substring(0, 100) + '...'
|
|
94
|
+
: job.final_summary;
|
|
84
95
|
parts.push(` └─ ${summarySnippet}`);
|
|
85
96
|
}
|
|
86
97
|
}
|
|
@@ -97,7 +108,11 @@ export async function formatJobListHumanReadable(jobsList, dependencies = {}) {
|
|
|
97
108
|
* @param {object} dependencies - Dependencies object with config and providers
|
|
98
109
|
* @returns {Promise<string>} Human-readable status text
|
|
99
110
|
*/
|
|
100
|
-
export async function formatHumanReadableStatus(
|
|
111
|
+
export async function formatHumanReadableStatus(
|
|
112
|
+
jobStatus,
|
|
113
|
+
options = {},
|
|
114
|
+
dependencies = {},
|
|
115
|
+
) {
|
|
101
116
|
const parts = [];
|
|
102
117
|
|
|
103
118
|
// Format elapsed time
|
|
@@ -111,17 +126,20 @@ export async function formatHumanReadableStatus(jobStatus, options = {}, depende
|
|
|
111
126
|
}
|
|
112
127
|
|
|
113
128
|
// Build status line based on status
|
|
114
|
-
const statusEmoji =
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
129
|
+
const statusEmoji =
|
|
130
|
+
{
|
|
131
|
+
queued: '⏳',
|
|
132
|
+
running: '🔄',
|
|
133
|
+
completed: '✅',
|
|
134
|
+
failed: '❌',
|
|
135
|
+
cancelled: '⛔',
|
|
136
|
+
completed_with_errors: '⚠️',
|
|
137
|
+
}[jobStatus.status] || '❓';
|
|
122
138
|
|
|
123
139
|
// Format start time as readable date/time
|
|
124
|
-
const startTime = jobStatus.created_at
|
|
140
|
+
const startTime = jobStatus.created_at
|
|
141
|
+
? new Date(jobStatus.created_at).toLocaleString()
|
|
142
|
+
: 'unknown';
|
|
125
143
|
|
|
126
144
|
// Add sequence info if provided
|
|
127
145
|
const sequenceStr = options.sequence ? ` | ${options.sequence}` : '';
|
|
@@ -141,8 +159,9 @@ export async function formatHumanReadableStatus(jobStatus, options = {}, depende
|
|
|
141
159
|
} else if (jobStatus.providers) {
|
|
142
160
|
// Calculate progress from provider states
|
|
143
161
|
const providerEntries = Object.entries(jobStatus.providers);
|
|
144
|
-
const completed = providerEntries.filter(
|
|
145
|
-
|
|
162
|
+
const completed = providerEntries.filter(
|
|
163
|
+
([_, state]) =>
|
|
164
|
+
state.status === 'completed' || state.status === 'refined',
|
|
146
165
|
).length;
|
|
147
166
|
const total = providerEntries.length;
|
|
148
167
|
statusLine += ` | ${completed}/${total} responded`;
|
|
@@ -163,56 +182,83 @@ export async function formatHumanReadableStatus(jobStatus, options = {}, depende
|
|
|
163
182
|
parts.push(statusLine);
|
|
164
183
|
|
|
165
184
|
// Show reasoning summary for running jobs from OpenAI reasoning models
|
|
166
|
-
if (
|
|
167
|
-
|
|
185
|
+
if (
|
|
186
|
+
jobStatus.status === 'running' &&
|
|
187
|
+
!jobStatus.accumulated_content &&
|
|
188
|
+
jobStatus.reasoning_summary
|
|
189
|
+
) {
|
|
190
|
+
debugLog(
|
|
191
|
+
`[FormatStatus] *** SHOWING REASONING SUMMARY: "${jobStatus.reasoning_summary.substring(0, 100)}..."`,
|
|
192
|
+
);
|
|
168
193
|
parts.push(`Thinking: ${jobStatus.reasoning_summary}`);
|
|
169
|
-
} else if (
|
|
194
|
+
} else if (
|
|
195
|
+
jobStatus.status === 'running' &&
|
|
196
|
+
!jobStatus.accumulated_content &&
|
|
197
|
+
jobStatus.elapsed_seconds > 5
|
|
198
|
+
) {
|
|
170
199
|
// Fallback thinking status for jobs without reasoning summaries
|
|
171
200
|
const thinkingTime = Math.floor(jobStatus.elapsed_seconds);
|
|
172
|
-
debugLog(
|
|
173
|
-
|
|
201
|
+
debugLog(
|
|
202
|
+
'[FormatStatus] *** FALLBACK THINKING (no reasoning_summary available)',
|
|
203
|
+
);
|
|
204
|
+
parts.push(
|
|
205
|
+
'Thinking: Model is processing your request (' +
|
|
206
|
+
thinkingTime +
|
|
207
|
+
's elapsed)',
|
|
208
|
+
);
|
|
174
209
|
}
|
|
175
210
|
|
|
176
211
|
// Generate streaming summary for running jobs if accumulated content available
|
|
177
212
|
if (jobStatus.status === 'running' && jobStatus.accumulated_content) {
|
|
178
213
|
try {
|
|
179
214
|
if (dependencies.config && dependencies.providers) {
|
|
180
|
-
const summarizationService = new SummarizationService(
|
|
215
|
+
const summarizationService = new SummarizationService(
|
|
216
|
+
dependencies.providers,
|
|
217
|
+
dependencies.config,
|
|
218
|
+
);
|
|
181
219
|
|
|
182
220
|
// Extract the last 500 characters as the current focus area
|
|
183
221
|
const contentLength = jobStatus.accumulated_content.length;
|
|
184
|
-
const currentFocus =
|
|
185
|
-
|
|
186
|
-
|
|
222
|
+
const currentFocus =
|
|
223
|
+
contentLength > 500
|
|
224
|
+
? jobStatus.accumulated_content.substring(contentLength - 500)
|
|
225
|
+
: jobStatus.accumulated_content;
|
|
187
226
|
|
|
188
227
|
// Generate streaming summary
|
|
189
|
-
const streamingSummary =
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
228
|
+
const streamingSummary =
|
|
229
|
+
await summarizationService.generateStreamingSummary(
|
|
230
|
+
jobStatus.accumulated_content,
|
|
231
|
+
currentFocus,
|
|
232
|
+
);
|
|
193
233
|
|
|
194
234
|
if (streamingSummary) {
|
|
195
235
|
parts.push(`Status: ${streamingSummary}`);
|
|
196
236
|
} else {
|
|
197
237
|
// Fallback: show truncated accumulated content as streaming preview
|
|
198
|
-
const preview =
|
|
199
|
-
|
|
200
|
-
|
|
238
|
+
const preview =
|
|
239
|
+
jobStatus.accumulated_content.length > 200
|
|
240
|
+
? jobStatus.accumulated_content.substring(0, 200) + '...'
|
|
241
|
+
: jobStatus.accumulated_content;
|
|
201
242
|
parts.push(`Streaming: "${preview}"`);
|
|
202
243
|
}
|
|
203
244
|
} else {
|
|
204
245
|
// Fallback when summarization unavailable: show truncated accumulated content
|
|
205
|
-
const preview =
|
|
206
|
-
|
|
207
|
-
|
|
246
|
+
const preview =
|
|
247
|
+
jobStatus.accumulated_content.length > 200
|
|
248
|
+
? jobStatus.accumulated_content.substring(0, 200) + '...'
|
|
249
|
+
: jobStatus.accumulated_content;
|
|
208
250
|
parts.push(`Streaming: "${preview}"`);
|
|
209
251
|
}
|
|
210
252
|
} catch (error) {
|
|
211
|
-
debugError(
|
|
253
|
+
debugError(
|
|
254
|
+
'formatHumanReadableStatus: Failed to generate streaming summary',
|
|
255
|
+
error,
|
|
256
|
+
);
|
|
212
257
|
// Fall back to showing truncated accumulated content
|
|
213
|
-
const preview =
|
|
214
|
-
|
|
215
|
-
|
|
258
|
+
const preview =
|
|
259
|
+
jobStatus.accumulated_content.length > 200
|
|
260
|
+
? jobStatus.accumulated_content.substring(0, 200) + '...'
|
|
261
|
+
: jobStatus.accumulated_content;
|
|
216
262
|
parts.push(`Streaming: "${preview}"`);
|
|
217
263
|
}
|
|
218
264
|
}
|
|
@@ -225,7 +271,10 @@ export async function formatHumanReadableStatus(jobStatus, options = {}, depende
|
|
|
225
271
|
// Optionally show first provider's preview
|
|
226
272
|
const firstPreview = Object.values(jobStatus.provider_previews)[0];
|
|
227
273
|
if (firstPreview) {
|
|
228
|
-
const truncated =
|
|
274
|
+
const truncated =
|
|
275
|
+
firstPreview.length > 80
|
|
276
|
+
? firstPreview.substring(0, 80) + '...'
|
|
277
|
+
: firstPreview;
|
|
229
278
|
parts.push(`Preview: "${truncated}"`);
|
|
230
279
|
}
|
|
231
280
|
}
|
|
@@ -293,13 +342,14 @@ export function formatJobStatus(job, options = {}) {
|
|
|
293
342
|
accumulated_content: job.accumulated_content || null,
|
|
294
343
|
title: job.title || null,
|
|
295
344
|
final_summary: job.final_summary || null,
|
|
296
|
-
reasoning_summary: job.reasoning_summary || null
|
|
345
|
+
reasoning_summary: job.reasoning_summary || null,
|
|
297
346
|
};
|
|
298
347
|
|
|
299
348
|
// For consensus, gather provider previews
|
|
300
349
|
if (job.tool === 'consensus') {
|
|
301
350
|
const providerPreviews = {};
|
|
302
|
-
for (let i = 0; i < 10; i++) {
|
|
351
|
+
for (let i = 0; i < 10; i++) {
|
|
352
|
+
// Check up to 10 providers
|
|
303
353
|
if (job[`provider_${i}_preview`]) {
|
|
304
354
|
providerPreviews[`provider_${i}`] = job[`provider_${i}_preview`];
|
|
305
355
|
}
|
|
@@ -321,7 +371,7 @@ export function formatJobStatus(job, options = {}) {
|
|
|
321
371
|
formatted.providers[providerId] = {
|
|
322
372
|
status: providerState.status || 'unknown',
|
|
323
373
|
progress: providerState.progress || 0,
|
|
324
|
-
updated_at: providerState.updatedAt || null
|
|
374
|
+
updated_at: providerState.updatedAt || null,
|
|
325
375
|
};
|
|
326
376
|
}
|
|
327
377
|
}
|
|
@@ -346,7 +396,11 @@ export function formatJobStatus(job, options = {}) {
|
|
|
346
396
|
* @param {object} dependencies - Dependencies object with config and providers
|
|
347
397
|
* @returns {Promise<string>} Human-readable conversation history
|
|
348
398
|
*/
|
|
349
|
-
export async function formatConversationHistory(
|
|
399
|
+
export async function formatConversationHistory(
|
|
400
|
+
jobStatus,
|
|
401
|
+
continuationId,
|
|
402
|
+
dependencies = {},
|
|
403
|
+
) {
|
|
350
404
|
const parts = [];
|
|
351
405
|
|
|
352
406
|
parts.push(`📊 Conversation History for ${continuationId}:`);
|
|
@@ -355,7 +409,11 @@ export async function formatConversationHistory(jobStatus, continuationId, depen
|
|
|
355
409
|
|
|
356
410
|
// For now, show the single job with sequence 1/1
|
|
357
411
|
// TODO: Implement proper conversation tracking when multi-job conversations are supported
|
|
358
|
-
const statusLine = await formatHumanReadableStatus(
|
|
412
|
+
const statusLine = await formatHumanReadableStatus(
|
|
413
|
+
jobStatus,
|
|
414
|
+
{ sequence: '1/1', skipContent: false },
|
|
415
|
+
dependencies,
|
|
416
|
+
);
|
|
359
417
|
parts.push(statusLine);
|
|
360
418
|
|
|
361
419
|
return parts.join('\n');
|