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.
Files changed (42) hide show
  1. package/README.md +771 -738
  2. package/docs/API.md +10 -1
  3. package/docs/PROVIDERS.md +8 -4
  4. package/package.json +12 -12
  5. package/src/async/asyncJobStore.js +82 -52
  6. package/src/async/eventBus.js +25 -20
  7. package/src/async/fileCache.js +121 -40
  8. package/src/async/jobRunner.js +65 -39
  9. package/src/async/providerStreamNormalizer.js +203 -117
  10. package/src/config.js +374 -102
  11. package/src/continuationStore.js +32 -24
  12. package/src/index.js +45 -25
  13. package/src/prompts/helpPrompt.js +328 -305
  14. package/src/providers/anthropic.js +303 -119
  15. package/src/providers/codex.js +103 -45
  16. package/src/providers/deepseek.js +24 -8
  17. package/src/providers/google.js +337 -93
  18. package/src/providers/index.js +1 -1
  19. package/src/providers/interface.js +16 -11
  20. package/src/providers/mistral.js +179 -69
  21. package/src/providers/openai-compatible.js +231 -94
  22. package/src/providers/openai.js +1094 -914
  23. package/src/providers/openrouter-endpoints-client.js +220 -216
  24. package/src/providers/openrouter.js +426 -381
  25. package/src/providers/xai.js +153 -56
  26. package/src/resources/helpResource.js +70 -67
  27. package/src/router.js +95 -67
  28. package/src/services/summarizationService.js +51 -24
  29. package/src/systemPrompts.js +89 -89
  30. package/src/tools/cancelJob.js +31 -19
  31. package/src/tools/chat.js +997 -883
  32. package/src/tools/checkStatus.js +86 -65
  33. package/src/tools/consensus.js +400 -234
  34. package/src/tools/index.js +39 -16
  35. package/src/transport/httpTransport.js +82 -55
  36. package/src/utils/contextProcessor.js +54 -37
  37. package/src/utils/errorHandler.js +95 -45
  38. package/src/utils/fileValidator.js +107 -98
  39. package/src/utils/formatStatus.js +122 -64
  40. package/src/utils/logger.js +459 -449
  41. package/src/utils/pathUtils.js +2 -2
  42. package/src/utils/tokenLimiter.js +216 -216
@@ -15,7 +15,7 @@ import {
15
15
  formatJobStatus,
16
16
  formatHumanReadableStatus,
17
17
  formatJobListHumanReadable,
18
- formatConversationHistory
18
+ formatConversationHistory,
19
19
  } from '../utils/formatStatus.js';
20
20
 
21
21
  const logger = createLogger('check-status');
@@ -33,10 +33,7 @@ export async function checkStatusTool(args, dependencies) {
33
33
  const { config, providers } = dependencies;
34
34
 
35
35
  // Extract and validate arguments
36
- const {
37
- continuation_id,
38
- full_history = false
39
- } = args;
36
+ const { continuation_id, full_history = false } = args;
40
37
 
41
38
  // Validate arguments
42
39
  if (continuation_id && typeof continuation_id !== 'string') {
@@ -48,7 +45,7 @@ export async function checkStatusTool(args, dependencies) {
48
45
 
49
46
  debugLog('checkStatus', 'Processing status query', {
50
47
  continuation_id,
51
- full_history
48
+ full_history,
52
49
  });
53
50
 
54
51
  if (continuation_id) {
@@ -58,52 +55,58 @@ export async function checkStatusTool(args, dependencies) {
58
55
  asyncJobStore,
59
56
  fileCache,
60
57
  {
61
- include_output: true, // Always include output
62
- full_history
63
- }
58
+ include_output: true, // Always include output
59
+ full_history,
60
+ },
64
61
  );
65
62
 
66
63
  if (!jobStatus) {
67
- return createToolError(`Job not found or access denied: ${continuation_id}`);
64
+ return createToolError(
65
+ `Job not found or access denied: ${continuation_id}`,
66
+ );
68
67
  }
69
68
 
70
69
  // Format content as human-readable status (now async)
71
70
  const content = full_history
72
- ? await formatConversationHistory(jobStatus, continuation_id, { config, providers })
73
- : await formatHumanReadableStatus(jobStatus, { sequence: '1/1' }, { config, providers });
71
+ ? await formatConversationHistory(jobStatus, continuation_id, {
72
+ config,
73
+ providers,
74
+ })
75
+ : await formatHumanReadableStatus(
76
+ jobStatus,
77
+ { sequence: '1/1' },
78
+ { config, providers },
79
+ );
74
80
 
75
81
  return createToolResponse({
76
82
  content,
77
83
  metadata: {
78
84
  continuation_id,
79
85
  execution_time: (Date.now() - startTime) / 1000,
80
- full_history
81
- }
86
+ full_history,
87
+ },
82
88
  });
83
-
84
89
  } else {
85
90
  // List all active/recent jobs (hardcoded to 10 latest)
86
- const jobsList = await listAllJobs(
87
- asyncJobStore,
88
- fileCache,
89
- {
90
- include_output: true, // Always include output
91
- max_results: 10
92
- }
93
- );
91
+ const jobsList = await listAllJobs(asyncJobStore, fileCache, {
92
+ include_output: true, // Always include output
93
+ max_results: 10,
94
+ });
94
95
 
95
96
  // Format content as human-readable jobs list (now async)
96
- const content = await formatJobListHumanReadable(jobsList, { config, providers });
97
+ const content = await formatJobListHumanReadable(jobsList, {
98
+ config,
99
+ providers,
100
+ });
97
101
 
98
102
  return createToolResponse({
99
103
  content,
100
104
  metadata: {
101
105
  execution_time: (Date.now() - startTime) / 1000,
102
- total_jobs: jobsList.jobs.length
103
- }
106
+ total_jobs: jobsList.jobs.length,
107
+ },
104
108
  });
105
109
  }
106
-
107
110
  } catch (error) {
108
111
  debugError('checkStatus', 'Tool execution failed:', error);
109
112
  return createToolError('Failed to check job status', error);
@@ -118,7 +121,12 @@ export async function checkStatusTool(args, dependencies) {
118
121
  * @param {object} options - Query options
119
122
  * @returns {object|null} Job status or null if not found
120
123
  */
121
- async function querySpecificJob(continuationId, asyncJobStore, fileCache, options = {}) {
124
+ async function querySpecificJob(
125
+ continuationId,
126
+ asyncJobStore,
127
+ fileCache,
128
+ options = {},
129
+ ) {
122
130
  try {
123
131
  // First try memory store (AsyncJobStore)
124
132
  const memoryJob = await asyncJobStore.get(continuationId);
@@ -135,7 +143,6 @@ async function querySpecificJob(continuationId, asyncJobStore, fileCache, option
135
143
  // Job not found
136
144
  debugLog('checkStatus', 'Job not found', { continuationId });
137
145
  return null;
138
-
139
146
  } catch (error) {
140
147
  debugError('checkStatus', 'Error querying specific job:', error);
141
148
  throw error;
@@ -157,7 +164,7 @@ async function listAllJobs(asyncJobStore, fileCache, options = {}) {
157
164
  completed_jobs: 0,
158
165
  failed_jobs: 0,
159
166
  cancelled_jobs: 0,
160
- total_jobs: 0
167
+ total_jobs: 0,
161
168
  };
162
169
 
163
170
  // Get stats from AsyncJobStore to understand what's in memory
@@ -192,41 +199,53 @@ async function listAllJobs(asyncJobStore, fileCache, options = {}) {
192
199
 
193
200
  // If we haven't reached 10 jobs, try to get more from FileCache
194
201
  if (jobs.length < 10 && fileCache) {
195
- debugLog('checkStatus', `Have ${jobs.length} jobs from memory, checking FileCache for additional completed jobs`);
202
+ debugLog(
203
+ 'checkStatus',
204
+ `Have ${jobs.length} jobs from memory, checking FileCache for additional completed jobs`,
205
+ );
196
206
 
197
207
  try {
198
208
  // Get recent jobs from FileCache
199
209
  const remainingLimit = 10 - jobs.length;
200
210
  const cachedJobs = await fileCache.listRecentJobs({
201
211
  limit: remainingLimit,
202
- daysBack: 3
212
+ daysBack: 3,
203
213
  });
204
214
 
205
- debugLog('checkStatus', `Found ${cachedJobs.length} additional jobs in FileCache`);
215
+ debugLog(
216
+ 'checkStatus',
217
+ `Found ${cachedJobs.length} additional jobs in FileCache`,
218
+ );
206
219
 
207
220
  // Format and add cached jobs to the list
208
221
  for (const cachedJob of cachedJobs) {
209
222
  // Check if this job is already in our list (avoid duplicates)
210
- const isDuplicate = jobs.some(j => j.continuation_id === cachedJob.jobId);
223
+ const isDuplicate = jobs.some(
224
+ (j) => j.continuation_id === cachedJob.jobId,
225
+ );
211
226
  if (!isDuplicate) {
212
227
  // Format the cached job to match our standard format
213
- const formattedJob = formatJobStatus({
214
- jobId: cachedJob.jobId,
215
- status: cachedJob.status || 'completed',
216
- tool: cachedJob.tool || 'unknown',
217
- createdAt: cachedJob.createdAt || cachedJob.startedAt,
218
- updatedAt: cachedJob.completedAt || cachedJob.updatedAt || Date.now(),
219
- overall: {
220
- result: cachedJob.result || cachedJob,
221
- progress: 100,
222
- startedAt: cachedJob.startedAt,
223
- endedAt: cachedJob.completedAt
228
+ const formattedJob = formatJobStatus(
229
+ {
230
+ jobId: cachedJob.jobId,
231
+ status: cachedJob.status || 'completed',
232
+ tool: cachedJob.tool || 'unknown',
233
+ createdAt: cachedJob.createdAt || cachedJob.startedAt,
234
+ updatedAt:
235
+ cachedJob.completedAt || cachedJob.updatedAt || Date.now(),
236
+ overall: {
237
+ result: cachedJob.result || cachedJob,
238
+ progress: 100,
239
+ startedAt: cachedJob.startedAt,
240
+ endedAt: cachedJob.completedAt,
241
+ },
242
+ provider: cachedJob.provider,
243
+ model: cachedJob.model,
244
+ title: cachedJob.title,
245
+ final_summary: cachedJob.final_summary,
224
246
  },
225
- provider: cachedJob.provider,
226
- model: cachedJob.model,
227
- title: cachedJob.title,
228
- final_summary: cachedJob.final_summary
229
- }, options);
247
+ options,
248
+ );
230
249
 
231
250
  jobs.push(formattedJob);
232
251
 
@@ -244,7 +263,11 @@ async function listAllJobs(asyncJobStore, fileCache, options = {}) {
244
263
  }
245
264
  }
246
265
  } catch (error) {
247
- debugError('checkStatus', 'Error retrieving jobs from FileCache:', error);
266
+ debugError(
267
+ 'checkStatus',
268
+ 'Error retrieving jobs from FileCache:',
269
+ error,
270
+ );
248
271
  // Continue without cached jobs if there's an error
249
272
  }
250
273
  }
@@ -253,12 +276,11 @@ async function listAllJobs(asyncJobStore, fileCache, options = {}) {
253
276
  jobs,
254
277
  summary,
255
278
  query_options: {
256
- include_output: true, // Always include output
257
- max_results: 10
279
+ include_output: true, // Always include output
280
+ max_results: 10,
258
281
  },
259
- timestamp: Date.now()
282
+ timestamp: Date.now(),
260
283
  };
261
-
262
284
  } catch (error) {
263
285
  debugError('checkStatus', 'Error listing session jobs:', error);
264
286
  throw error;
@@ -276,7 +298,7 @@ async function getAllJobsFromStore(asyncJobStore, options = {}) {
276
298
  return await asyncJobStore.getAllJobs({
277
299
  limit: 10,
278
300
  sortBy: 'updatedAt',
279
- sortOrder: 'desc'
301
+ sortOrder: 'desc',
280
302
  });
281
303
  } catch (error) {
282
304
  debugError('checkStatus', 'Error getting all jobs:', error);
@@ -284,25 +306,24 @@ async function getAllJobsFromStore(asyncJobStore, options = {}) {
284
306
  }
285
307
  }
286
308
 
287
-
288
-
289
-
290
-
291
309
  // Tool metadata and input schema
292
- checkStatusTool.description = 'Check the status and progress of async jobs. Query specific jobs by continuation_id or list the 10 most recent jobs. Returns job status with start time and progress information.';
310
+ checkStatusTool.description =
311
+ 'Check the status and progress of async jobs. Query specific jobs by continuation_id or list the 10 most recent jobs. Returns job status with start time and progress information.';
293
312
 
294
313
  checkStatusTool.inputSchema = {
295
314
  type: 'object',
296
315
  properties: {
297
316
  continuation_id: {
298
317
  type: 'string',
299
- description: 'Optional job continuation ID to query. If not provided, returns the 10 most recent jobs.'
318
+ description:
319
+ 'Optional job continuation ID to query. If not provided, returns the 10 most recent jobs.',
300
320
  },
301
321
  full_history: {
302
322
  type: 'boolean',
303
323
  default: false,
304
- description: 'When used with continuation_id, returns the full conversation history for that continuation ID. Only use when there are multiple turns and you need the full conversation.'
305
- }
324
+ description:
325
+ 'When used with continuation_id, returns the full conversation history for that continuation ID. Only use when there are multiple turns and you need the full conversation.',
326
+ },
306
327
  },
307
- additionalProperties: false
328
+ additionalProperties: false,
308
329
  };