@vybestack/llxprt-code-core 0.1.17 → 0.1.18
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 +0 -1
- package/dist/src/config/config.d.ts +3 -0
- package/dist/src/config/config.js +10 -2
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/core/client.d.ts +9 -2
- package/dist/src/core/client.js +41 -7
- package/dist/src/core/client.js.map +1 -1
- package/dist/src/core/client.test.js +1 -1
- package/dist/src/core/client.test.js.map +1 -1
- package/dist/src/core/coreToolScheduler.d.ts +2 -0
- package/dist/src/core/coreToolScheduler.js +3 -1
- package/dist/src/core/coreToolScheduler.js.map +1 -1
- package/dist/src/core/coreToolScheduler.test.js +6 -0
- package/dist/src/core/coreToolScheduler.test.js.map +1 -1
- package/dist/src/core/geminiChat.d.ts +1 -0
- package/dist/src/core/geminiChat.js +33 -0
- package/dist/src/core/geminiChat.js.map +1 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/index.js +1 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/mcp/oauth-provider.d.ts +1 -0
- package/dist/src/mcp/oauth-provider.js +14 -1
- package/dist/src/mcp/oauth-provider.js.map +1 -1
- package/dist/src/mcp/oauth-provider.test.js +87 -6
- package/dist/src/mcp/oauth-provider.test.js.map +1 -1
- package/dist/src/prompts/prompt-registry.d.ts +8 -0
- package/dist/src/prompts/prompt-registry.js +16 -0
- package/dist/src/prompts/prompt-registry.js.map +1 -1
- package/dist/src/providers/openai/OpenAIProvider.integration.test.js +1 -1
- package/dist/src/providers/openai/OpenAIProvider.integration.test.js.map +1 -1
- package/dist/src/services/loopDetectionService.js +2 -4
- package/dist/src/services/loopDetectionService.js.map +1 -1
- package/dist/src/tools/glob.d.ts +4 -0
- package/dist/src/tools/glob.js +31 -5
- package/dist/src/tools/glob.js.map +1 -1
- package/dist/src/tools/grep.d.ts +4 -0
- package/dist/src/tools/grep.js +22 -5
- package/dist/src/tools/grep.js.map +1 -1
- package/dist/src/tools/ls.d.ts +4 -0
- package/dist/src/tools/ls.js +30 -5
- package/dist/src/tools/ls.js.map +1 -1
- package/dist/src/tools/mcp-tool.js +104 -45
- package/dist/src/tools/mcp-tool.js.map +1 -1
- package/dist/src/tools/mcp-tool.test.js +280 -2
- package/dist/src/tools/mcp-tool.test.js.map +1 -1
- package/dist/src/tools/modifiable-tool.d.ts +1 -1
- package/dist/src/tools/modifiable-tool.js +2 -2
- package/dist/src/tools/modifiable-tool.js.map +1 -1
- package/dist/src/tools/modifiable-tool.test.js +9 -9
- package/dist/src/tools/modifiable-tool.test.js.map +1 -1
- package/dist/src/tools/shell.js +14 -2
- package/dist/src/tools/shell.js.map +1 -1
- package/dist/src/tools/tool-registry.d.ts +1 -0
- package/dist/src/tools/tool-registry.js +12 -10
- package/dist/src/tools/tool-registry.js.map +1 -1
- package/dist/src/tools/tool-registry.test.js +6 -2
- package/dist/src/tools/tool-registry.test.js.map +1 -1
- package/dist/src/tools/tools.d.ts +6 -0
- package/dist/src/tools/tools.js +65 -0
- package/dist/src/tools/tools.js.map +1 -1
- package/dist/src/tools/tools.test.d.ts +6 -0
- package/dist/src/tools/tools.test.js +117 -0
- package/dist/src/tools/tools.test.js.map +1 -0
- package/dist/src/utils/editor.d.ts +1 -1
- package/dist/src/utils/editor.js +13 -5
- package/dist/src/utils/editor.js.map +1 -1
- package/dist/src/utils/editor.test.js +38 -6
- package/dist/src/utils/editor.test.js.map +1 -1
- package/dist/src/utils/fileUtils.js +5 -4
- package/dist/src/utils/fileUtils.js.map +1 -1
- package/dist/src/utils/fileUtils.test.js +18 -1
- package/dist/src/utils/fileUtils.test.js.map +1 -1
- package/dist/src/utils/filesearch/crawlCache.d.ts +25 -0
- package/dist/src/utils/filesearch/crawlCache.js +57 -0
- package/dist/src/utils/filesearch/crawlCache.js.map +1 -0
- package/dist/src/utils/filesearch/crawlCache.test.d.ts +6 -0
- package/dist/src/utils/filesearch/crawlCache.test.js +103 -0
- package/dist/src/utils/filesearch/crawlCache.test.js.map +1 -0
- package/dist/src/utils/filesearch/fileSearch.d.ts +80 -0
- package/dist/src/utils/filesearch/fileSearch.js +219 -0
- package/dist/src/utils/filesearch/fileSearch.js.map +1 -0
- package/dist/src/utils/filesearch/fileSearch.test.d.ts +6 -0
- package/dist/src/utils/filesearch/fileSearch.test.js +634 -0
- package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -0
- package/dist/src/utils/filesearch/ignore.d.ts +35 -0
- package/dist/src/utils/filesearch/ignore.js +81 -0
- package/dist/src/utils/filesearch/ignore.js.map +1 -0
- package/dist/src/utils/filesearch/ignore.test.d.ts +6 -0
- package/dist/src/utils/filesearch/ignore.test.js +57 -0
- package/dist/src/utils/filesearch/ignore.test.js.map +1 -0
- package/dist/src/utils/filesearch/result-cache.d.ts +34 -0
- package/dist/src/utils/filesearch/result-cache.js +61 -0
- package/dist/src/utils/filesearch/result-cache.js.map +1 -0
- package/dist/src/utils/filesearch/result-cache.test.d.ts +6 -0
- package/dist/src/utils/filesearch/result-cache.test.js +47 -0
- package/dist/src/utils/filesearch/result-cache.test.js.map +1 -0
- package/dist/src/utils/memoryDiscovery.d.ts +1 -1
- package/dist/src/utils/memoryDiscovery.js +18 -6
- package/dist/src/utils/memoryDiscovery.js.map +1 -1
- package/dist/src/utils/memoryDiscovery.test.js +30 -71
- package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
- package/dist/src/utils/toolOutputLimiter.js +5 -1
- package/dist/src/utils/toolOutputLimiter.js.map +1 -1
- package/dist/src/utils/workspaceContext.d.ts +4 -0
- package/dist/src/utils/workspaceContext.js +33 -0
- package/dist/src/utils/workspaceContext.js.map +1 -1
- package/package.json +5 -1
package/dist/src/tools/ls.d.ts
CHANGED
|
@@ -24,6 +24,10 @@ export interface LSToolParams {
|
|
|
24
24
|
respect_git_ignore?: boolean;
|
|
25
25
|
respect_llxprt_ignore?: boolean;
|
|
26
26
|
};
|
|
27
|
+
/**
|
|
28
|
+
* Maximum number of entries to return (optional, helps prevent overwhelming output)
|
|
29
|
+
*/
|
|
30
|
+
max_entries?: number;
|
|
27
31
|
}
|
|
28
32
|
/**
|
|
29
33
|
* File entry returned by LS tool
|
package/dist/src/tools/ls.js
CHANGED
|
@@ -10,7 +10,7 @@ import { SchemaValidator } from '../utils/schemaValidator.js';
|
|
|
10
10
|
import { makeRelative, shortenPath } from '../utils/paths.js';
|
|
11
11
|
import { DEFAULT_FILE_FILTERING_OPTIONS } from '../config/config.js';
|
|
12
12
|
import { Type } from '@google/genai';
|
|
13
|
-
import { limitOutputTokens, formatLimitedOutput, } from '../utils/toolOutputLimiter.js';
|
|
13
|
+
import { limitOutputTokens, formatLimitedOutput, getOutputLimits, } from '../utils/toolOutputLimiter.js';
|
|
14
14
|
/**
|
|
15
15
|
* Implementation of the LS tool logic
|
|
16
16
|
*/
|
|
@@ -45,6 +45,10 @@ export class LSTool extends BaseTool {
|
|
|
45
45
|
},
|
|
46
46
|
},
|
|
47
47
|
},
|
|
48
|
+
max_entries: {
|
|
49
|
+
description: 'Optional: Maximum number of entries to return. If omitted, returns all entries in the directory. Set a lower number for large directories to avoid overwhelming output.',
|
|
50
|
+
type: Type.NUMBER,
|
|
51
|
+
},
|
|
48
52
|
},
|
|
49
53
|
required: ['path'],
|
|
50
54
|
type: Type.OBJECT,
|
|
@@ -192,11 +196,19 @@ export class LSTool extends BaseTool {
|
|
|
192
196
|
return 1;
|
|
193
197
|
return a.name.localeCompare(b.name);
|
|
194
198
|
});
|
|
199
|
+
// Apply max_entries limit if specified
|
|
200
|
+
let displayEntries = entries;
|
|
201
|
+
let limitMessage = '';
|
|
202
|
+
const totalEntries = entries.length;
|
|
203
|
+
if (params.max_entries && entries.length > params.max_entries) {
|
|
204
|
+
displayEntries = entries.slice(0, params.max_entries);
|
|
205
|
+
limitMessage = ` (showing first ${params.max_entries} of ${totalEntries} total)`;
|
|
206
|
+
}
|
|
195
207
|
// Create formatted content for LLM
|
|
196
|
-
const directoryContent =
|
|
208
|
+
const directoryContent = displayEntries
|
|
197
209
|
.map((entry) => `${entry.isDirectory ? '[DIR] ' : ''}${entry.name}`)
|
|
198
210
|
.join('\n');
|
|
199
|
-
let resultMessage = `Directory listing for ${params.path}:\n${directoryContent}`;
|
|
211
|
+
let resultMessage = `Directory listing for ${params.path}${limitMessage}:\n${directoryContent}`;
|
|
200
212
|
const ignoredMessages = [];
|
|
201
213
|
if (gitIgnoredCount > 0) {
|
|
202
214
|
ignoredMessages.push(`${gitIgnoredCount} git-ignored`);
|
|
@@ -207,14 +219,27 @@ export class LSTool extends BaseTool {
|
|
|
207
219
|
if (ignoredMessages.length > 0) {
|
|
208
220
|
resultMessage += `\n\n(${ignoredMessages.join(', ')})`;
|
|
209
221
|
}
|
|
210
|
-
let displayMessage = `Listed ${
|
|
222
|
+
let displayMessage = `Listed ${displayEntries.length} item(s)${limitMessage}.`;
|
|
211
223
|
if (ignoredMessages.length > 0) {
|
|
212
224
|
displayMessage += ` (${ignoredMessages.join(', ')})`;
|
|
213
225
|
}
|
|
214
226
|
// Apply token-based limiting (NOT item limiting - ls just lists entries)
|
|
215
227
|
const limitedResult = limitOutputTokens(resultMessage, this.config, 'list_directory');
|
|
228
|
+
// If we hit token limits with warn mode, provide better guidance
|
|
229
|
+
if (limitedResult.wasTruncated &&
|
|
230
|
+
!limitedResult.content &&
|
|
231
|
+
!params.max_entries) {
|
|
232
|
+
const improvedMessage = `ls output exceeded token limit (${limitedResult.originalTokens} > ${getOutputLimits(this.config).maxTokens}). The directory contains too many files to list. Please:
|
|
233
|
+
1. Use the max_entries parameter to limit results (e.g., max_entries: 100)
|
|
234
|
+
2. Use glob with a specific pattern to find files (e.g., "*.ts", "src/**/*.js")
|
|
235
|
+
3. List subdirectories individually instead of the parent directory
|
|
236
|
+
4. Use grep to search for specific file contents if looking for code`;
|
|
237
|
+
return {
|
|
238
|
+
llmContent: improvedMessage,
|
|
239
|
+
returnDisplay: `## Directory Listing Too Large\n\n${improvedMessage}`,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
216
242
|
const formatted = formatLimitedOutput(limitedResult);
|
|
217
|
-
// If we hit token limits, override the display to be more informative
|
|
218
243
|
if (limitedResult.wasTruncated && !limitedResult.content) {
|
|
219
244
|
return formatted;
|
|
220
245
|
}
|
package/dist/src/tools/ls.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/tools/ls.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,QAAQ,EAAc,IAAI,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAU,8BAA8B,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EACL,iBAAiB,EACjB,mBAAmB,
|
|
1
|
+
{"version":3,"file":"ls.js","sourceRoot":"","sources":["../../../src/tools/ls.ts"],"names":[],"mappings":"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"}
|
|
@@ -72,61 +72,120 @@ export class DiscoveredMCPTool extends BaseTool {
|
|
|
72
72
|
args: params,
|
|
73
73
|
},
|
|
74
74
|
];
|
|
75
|
-
const
|
|
75
|
+
const rawResponseParts = await this.mcpTool.callTool(functionCalls);
|
|
76
|
+
const transformedParts = transformMcpContentToParts(rawResponseParts);
|
|
76
77
|
return {
|
|
77
|
-
llmContent:
|
|
78
|
-
returnDisplay: getStringifiedResultForDisplay(
|
|
78
|
+
llmContent: transformedParts,
|
|
79
|
+
returnDisplay: getStringifiedResultForDisplay(rawResponseParts),
|
|
79
80
|
};
|
|
80
81
|
}
|
|
81
82
|
}
|
|
83
|
+
function transformTextBlock(block) {
|
|
84
|
+
return { text: block.text };
|
|
85
|
+
}
|
|
86
|
+
function transformImageAudioBlock(block, toolName) {
|
|
87
|
+
return [
|
|
88
|
+
{
|
|
89
|
+
text: `[Tool '${toolName}' provided the following ${block.type} data with mime-type: ${block.mimeType}]`,
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
inlineData: {
|
|
93
|
+
mimeType: block.mimeType,
|
|
94
|
+
data: block.data,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
function transformResourceBlock(block, toolName) {
|
|
100
|
+
const resource = block.resource;
|
|
101
|
+
if (resource?.text) {
|
|
102
|
+
return { text: resource.text };
|
|
103
|
+
}
|
|
104
|
+
if (resource?.blob) {
|
|
105
|
+
const mimeType = resource.mimeType || 'application/octet-stream';
|
|
106
|
+
return [
|
|
107
|
+
{
|
|
108
|
+
text: `[Tool '${toolName}' provided the following embedded resource with mime-type: ${mimeType}]`,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
inlineData: {
|
|
112
|
+
mimeType,
|
|
113
|
+
data: resource.blob,
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
];
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
function transformResourceLinkBlock(block) {
|
|
121
|
+
return {
|
|
122
|
+
text: `Resource Link: ${block.title || block.name} at ${block.uri}`,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
82
125
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
126
|
+
* Transforms the raw MCP content blocks from the SDK response into a
|
|
127
|
+
* standard GenAI Part array.
|
|
128
|
+
* @param sdkResponse The raw Part[] array from `mcpTool.callTool()`.
|
|
129
|
+
* @returns A clean Part[] array ready for the scheduler.
|
|
130
|
+
*/
|
|
131
|
+
function transformMcpContentToParts(sdkResponse) {
|
|
132
|
+
const funcResponse = sdkResponse?.[0]?.functionResponse;
|
|
133
|
+
const mcpContent = funcResponse?.response?.content;
|
|
134
|
+
const toolName = funcResponse?.name || 'unknown tool';
|
|
135
|
+
if (!Array.isArray(mcpContent)) {
|
|
136
|
+
return [{ text: '[Error: Could not parse tool response]' }];
|
|
137
|
+
}
|
|
138
|
+
const transformed = mcpContent.flatMap((block) => {
|
|
139
|
+
switch (block.type) {
|
|
140
|
+
case 'text':
|
|
141
|
+
return transformTextBlock(block);
|
|
142
|
+
case 'image':
|
|
143
|
+
case 'audio':
|
|
144
|
+
return transformImageAudioBlock(block, toolName);
|
|
145
|
+
case 'resource':
|
|
146
|
+
return transformResourceBlock(block, toolName);
|
|
147
|
+
case 'resource_link':
|
|
148
|
+
return transformResourceLinkBlock(block);
|
|
149
|
+
default:
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
return transformed.filter((part) => part !== null);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Processes the raw response from the MCP tool to generate a clean,
|
|
157
|
+
* human-readable string for display in the CLI. It summarizes non-text
|
|
158
|
+
* content and presents text directly.
|
|
98
159
|
*
|
|
99
|
-
*
|
|
100
|
-
*
|
|
160
|
+
* @param rawResponse The raw Part[] array from the GenAI SDK.
|
|
161
|
+
* @returns A formatted string representing the tool's output.
|
|
101
162
|
*/
|
|
102
|
-
function getStringifiedResultForDisplay(
|
|
103
|
-
|
|
104
|
-
|
|
163
|
+
function getStringifiedResultForDisplay(rawResponse) {
|
|
164
|
+
const mcpContent = rawResponse?.[0]?.functionResponse?.response
|
|
165
|
+
?.content;
|
|
166
|
+
if (!Array.isArray(mcpContent)) {
|
|
167
|
+
return '```json\n' + JSON.stringify(rawResponse, null, 2) + '\n```';
|
|
105
168
|
}
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
169
|
+
const displayParts = mcpContent.map((block) => {
|
|
170
|
+
switch (block.type) {
|
|
171
|
+
case 'text':
|
|
172
|
+
return block.text;
|
|
173
|
+
case 'image':
|
|
174
|
+
return `[Image: ${block.mimeType}]`;
|
|
175
|
+
case 'audio':
|
|
176
|
+
return `[Audio: ${block.mimeType}]`;
|
|
177
|
+
case 'resource_link':
|
|
178
|
+
return `[Link to ${block.title || block.name}: ${block.uri}]`;
|
|
179
|
+
case 'resource':
|
|
180
|
+
if (block.resource?.text) {
|
|
181
|
+
return block.resource.text;
|
|
114
182
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
// If no content, or not an array, or not a functionResponse, stringify the whole functionResponse part for inspection
|
|
119
|
-
return part.functionResponse;
|
|
183
|
+
return `[Embedded Resource: ${block.resource?.mimeType || 'unknown type'}]`;
|
|
184
|
+
default:
|
|
185
|
+
return `[Unknown content type: ${block.type}]`;
|
|
120
186
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const processedResults = result.length === 1
|
|
124
|
-
? processFunctionResponse(result[0])
|
|
125
|
-
: result.map(processFunctionResponse);
|
|
126
|
-
if (typeof processedResults === 'string') {
|
|
127
|
-
return processedResults;
|
|
128
|
-
}
|
|
129
|
-
return '```json\n' + JSON.stringify(processedResults, null, 2) + '\n```';
|
|
187
|
+
});
|
|
188
|
+
return displayParts.join('\n');
|
|
130
189
|
}
|
|
131
190
|
/** Visible for testing */
|
|
132
191
|
export function generateValidName(name) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-tool.js","sourceRoot":"","sources":["../../../src/tools/mcp-tool.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,QAAQ,EAGR,uBAAuB,EAEvB,IAAI,GACL,MAAM,YAAY,CAAC;AACpB,OAAO,EAKL,IAAI,GACL,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"mcp-tool.js","sourceRoot":"","sources":["../../../src/tools/mcp-tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -83,7 +83,10 @@ describe('DiscoveredMCPTool', () => {
|
|
|
83
83
|
details: 'executed',
|
|
84
84
|
};
|
|
85
85
|
const mockFunctionResponseContent = [
|
|
86
|
-
{
|
|
86
|
+
{
|
|
87
|
+
type: 'text',
|
|
88
|
+
text: JSON.stringify(mockToolSuccessResultObject),
|
|
89
|
+
},
|
|
87
90
|
];
|
|
88
91
|
const mockMcpToolResponseParts = [
|
|
89
92
|
{
|
|
@@ -98,8 +101,10 @@ describe('DiscoveredMCPTool', () => {
|
|
|
98
101
|
expect(mockCallTool).toHaveBeenCalledWith([
|
|
99
102
|
{ name: serverToolName, args: params },
|
|
100
103
|
]);
|
|
101
|
-
expect(toolResult.llmContent).toEqual(mockMcpToolResponseParts);
|
|
102
104
|
const stringifiedResponseContent = JSON.stringify(mockToolSuccessResultObject);
|
|
105
|
+
expect(toolResult.llmContent).toEqual([
|
|
106
|
+
{ text: stringifiedResponseContent },
|
|
107
|
+
]);
|
|
103
108
|
expect(toolResult.returnDisplay).toBe(stringifiedResponseContent);
|
|
104
109
|
});
|
|
105
110
|
it('should handle empty result from getStringifiedResultForDisplay', async () => {
|
|
@@ -109,6 +114,9 @@ describe('DiscoveredMCPTool', () => {
|
|
|
109
114
|
mockCallTool.mockResolvedValue(mockMcpToolResponsePartsEmpty);
|
|
110
115
|
const toolResult = await tool.execute(params);
|
|
111
116
|
expect(toolResult.returnDisplay).toBe('```json\n[]\n```');
|
|
117
|
+
expect(toolResult.llmContent).toEqual([
|
|
118
|
+
{ text: '[Error: Could not parse tool response]' },
|
|
119
|
+
]);
|
|
112
120
|
});
|
|
113
121
|
it('should propagate rejection if mcpTool.callTool rejects', async () => {
|
|
114
122
|
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
@@ -117,6 +125,276 @@ describe('DiscoveredMCPTool', () => {
|
|
|
117
125
|
mockCallTool.mockRejectedValue(expectedError);
|
|
118
126
|
await expect(tool.execute(params)).rejects.toThrow(expectedError);
|
|
119
127
|
});
|
|
128
|
+
it('should handle a simple text response correctly', async () => {
|
|
129
|
+
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
130
|
+
const params = { query: 'test' };
|
|
131
|
+
const successMessage = 'This is a success message.';
|
|
132
|
+
// Simulate the response from the GenAI SDK, which wraps the MCP
|
|
133
|
+
// response in a functionResponse Part.
|
|
134
|
+
const sdkResponse = [
|
|
135
|
+
{
|
|
136
|
+
functionResponse: {
|
|
137
|
+
name: serverToolName,
|
|
138
|
+
response: {
|
|
139
|
+
// The `content` array contains MCP ContentBlocks.
|
|
140
|
+
content: [{ type: 'text', text: successMessage }],
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
},
|
|
144
|
+
];
|
|
145
|
+
mockCallTool.mockResolvedValue(sdkResponse);
|
|
146
|
+
const toolResult = await tool.execute(params);
|
|
147
|
+
// 1. Assert that the llmContent sent to the scheduler is a clean Part array.
|
|
148
|
+
expect(toolResult.llmContent).toEqual([{ text: successMessage }]);
|
|
149
|
+
// 2. Assert that the display output is the simple text message.
|
|
150
|
+
expect(toolResult.returnDisplay).toBe(successMessage);
|
|
151
|
+
// 3. Verify that the underlying callTool was made correctly.
|
|
152
|
+
expect(mockCallTool).toHaveBeenCalledWith([
|
|
153
|
+
{ name: serverToolName, args: params },
|
|
154
|
+
]);
|
|
155
|
+
});
|
|
156
|
+
it('should handle an AudioBlock response', async () => {
|
|
157
|
+
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
158
|
+
const params = { action: 'play' };
|
|
159
|
+
const sdkResponse = [
|
|
160
|
+
{
|
|
161
|
+
functionResponse: {
|
|
162
|
+
name: serverToolName,
|
|
163
|
+
response: {
|
|
164
|
+
content: [
|
|
165
|
+
{
|
|
166
|
+
type: 'audio',
|
|
167
|
+
data: 'BASE64_AUDIO_DATA',
|
|
168
|
+
mimeType: 'audio/mp3',
|
|
169
|
+
},
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
];
|
|
175
|
+
mockCallTool.mockResolvedValue(sdkResponse);
|
|
176
|
+
const toolResult = await tool.execute(params);
|
|
177
|
+
expect(toolResult.llmContent).toEqual([
|
|
178
|
+
{
|
|
179
|
+
text: `[Tool '${serverToolName}' provided the following audio data with mime-type: audio/mp3]`,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
inlineData: {
|
|
183
|
+
mimeType: 'audio/mp3',
|
|
184
|
+
data: 'BASE64_AUDIO_DATA',
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
]);
|
|
188
|
+
expect(toolResult.returnDisplay).toBe('[Audio: audio/mp3]');
|
|
189
|
+
});
|
|
190
|
+
it('should handle a ResourceLinkBlock response', async () => {
|
|
191
|
+
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
192
|
+
const params = { resource: 'get' };
|
|
193
|
+
const sdkResponse = [
|
|
194
|
+
{
|
|
195
|
+
functionResponse: {
|
|
196
|
+
name: serverToolName,
|
|
197
|
+
response: {
|
|
198
|
+
content: [
|
|
199
|
+
{
|
|
200
|
+
type: 'resource_link',
|
|
201
|
+
uri: 'file:///path/to/thing',
|
|
202
|
+
name: 'resource-name',
|
|
203
|
+
title: 'My Resource',
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
];
|
|
210
|
+
mockCallTool.mockResolvedValue(sdkResponse);
|
|
211
|
+
const toolResult = await tool.execute(params);
|
|
212
|
+
expect(toolResult.llmContent).toEqual([
|
|
213
|
+
{
|
|
214
|
+
text: 'Resource Link: My Resource at file:///path/to/thing',
|
|
215
|
+
},
|
|
216
|
+
]);
|
|
217
|
+
expect(toolResult.returnDisplay).toBe('[Link to My Resource: file:///path/to/thing]');
|
|
218
|
+
});
|
|
219
|
+
it('should handle an embedded text ResourceBlock response', async () => {
|
|
220
|
+
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
221
|
+
const params = { resource: 'get' };
|
|
222
|
+
const sdkResponse = [
|
|
223
|
+
{
|
|
224
|
+
functionResponse: {
|
|
225
|
+
name: serverToolName,
|
|
226
|
+
response: {
|
|
227
|
+
content: [
|
|
228
|
+
{
|
|
229
|
+
type: 'resource',
|
|
230
|
+
resource: {
|
|
231
|
+
uri: 'file:///path/to/text.txt',
|
|
232
|
+
text: 'This is the text content.',
|
|
233
|
+
mimeType: 'text/plain',
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
},
|
|
240
|
+
];
|
|
241
|
+
mockCallTool.mockResolvedValue(sdkResponse);
|
|
242
|
+
const toolResult = await tool.execute(params);
|
|
243
|
+
expect(toolResult.llmContent).toEqual([
|
|
244
|
+
{ text: 'This is the text content.' },
|
|
245
|
+
]);
|
|
246
|
+
expect(toolResult.returnDisplay).toBe('This is the text content.');
|
|
247
|
+
});
|
|
248
|
+
it('should handle an embedded binary ResourceBlock response', async () => {
|
|
249
|
+
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
250
|
+
const params = { resource: 'get' };
|
|
251
|
+
const sdkResponse = [
|
|
252
|
+
{
|
|
253
|
+
functionResponse: {
|
|
254
|
+
name: serverToolName,
|
|
255
|
+
response: {
|
|
256
|
+
content: [
|
|
257
|
+
{
|
|
258
|
+
type: 'resource',
|
|
259
|
+
resource: {
|
|
260
|
+
uri: 'file:///path/to/data.bin',
|
|
261
|
+
blob: 'BASE64_BINARY_DATA',
|
|
262
|
+
mimeType: 'application/octet-stream',
|
|
263
|
+
},
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
},
|
|
267
|
+
},
|
|
268
|
+
},
|
|
269
|
+
];
|
|
270
|
+
mockCallTool.mockResolvedValue(sdkResponse);
|
|
271
|
+
const toolResult = await tool.execute(params);
|
|
272
|
+
expect(toolResult.llmContent).toEqual([
|
|
273
|
+
{
|
|
274
|
+
text: `[Tool '${serverToolName}' provided the following embedded resource with mime-type: application/octet-stream]`,
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
inlineData: {
|
|
278
|
+
mimeType: 'application/octet-stream',
|
|
279
|
+
data: 'BASE64_BINARY_DATA',
|
|
280
|
+
},
|
|
281
|
+
},
|
|
282
|
+
]);
|
|
283
|
+
expect(toolResult.returnDisplay).toBe('[Embedded Resource: application/octet-stream]');
|
|
284
|
+
});
|
|
285
|
+
it('should handle a mix of content block types', async () => {
|
|
286
|
+
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
287
|
+
const params = { action: 'complex' };
|
|
288
|
+
const sdkResponse = [
|
|
289
|
+
{
|
|
290
|
+
functionResponse: {
|
|
291
|
+
name: serverToolName,
|
|
292
|
+
response: {
|
|
293
|
+
content: [
|
|
294
|
+
{ type: 'text', text: 'First part.' },
|
|
295
|
+
{
|
|
296
|
+
type: 'image',
|
|
297
|
+
data: 'BASE64_IMAGE_DATA',
|
|
298
|
+
mimeType: 'image/jpeg',
|
|
299
|
+
},
|
|
300
|
+
{ type: 'text', text: 'Second part.' },
|
|
301
|
+
],
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
];
|
|
306
|
+
mockCallTool.mockResolvedValue(sdkResponse);
|
|
307
|
+
const toolResult = await tool.execute(params);
|
|
308
|
+
expect(toolResult.llmContent).toEqual([
|
|
309
|
+
{ text: 'First part.' },
|
|
310
|
+
{
|
|
311
|
+
text: `[Tool '${serverToolName}' provided the following image data with mime-type: image/jpeg]`,
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
inlineData: {
|
|
315
|
+
mimeType: 'image/jpeg',
|
|
316
|
+
data: 'BASE64_IMAGE_DATA',
|
|
317
|
+
},
|
|
318
|
+
},
|
|
319
|
+
{ text: 'Second part.' },
|
|
320
|
+
]);
|
|
321
|
+
expect(toolResult.returnDisplay).toBe('First part.\n[Image: image/jpeg]\nSecond part.');
|
|
322
|
+
});
|
|
323
|
+
it('should ignore unknown content block types', async () => {
|
|
324
|
+
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
325
|
+
const params = { action: 'test' };
|
|
326
|
+
const sdkResponse = [
|
|
327
|
+
{
|
|
328
|
+
functionResponse: {
|
|
329
|
+
name: serverToolName,
|
|
330
|
+
response: {
|
|
331
|
+
content: [
|
|
332
|
+
{ type: 'text', text: 'Valid part.' },
|
|
333
|
+
{ type: 'future_block', data: 'some-data' },
|
|
334
|
+
],
|
|
335
|
+
},
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
];
|
|
339
|
+
mockCallTool.mockResolvedValue(sdkResponse);
|
|
340
|
+
const toolResult = await tool.execute(params);
|
|
341
|
+
expect(toolResult.llmContent).toEqual([{ text: 'Valid part.' }]);
|
|
342
|
+
expect(toolResult.returnDisplay).toBe('Valid part.\n[Unknown content type: future_block]');
|
|
343
|
+
});
|
|
344
|
+
it('should handle a complex mix of content block types', async () => {
|
|
345
|
+
const tool = new DiscoveredMCPTool(mockCallableToolInstance, serverName, serverToolName, baseDescription, inputSchema);
|
|
346
|
+
const params = { action: 'super-complex' };
|
|
347
|
+
const sdkResponse = [
|
|
348
|
+
{
|
|
349
|
+
functionResponse: {
|
|
350
|
+
name: serverToolName,
|
|
351
|
+
response: {
|
|
352
|
+
content: [
|
|
353
|
+
{ type: 'text', text: 'Here is a resource.' },
|
|
354
|
+
{
|
|
355
|
+
type: 'resource_link',
|
|
356
|
+
uri: 'file:///path/to/resource',
|
|
357
|
+
name: 'resource-name',
|
|
358
|
+
title: 'My Resource',
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
type: 'resource',
|
|
362
|
+
resource: {
|
|
363
|
+
uri: 'file:///path/to/text.txt',
|
|
364
|
+
text: 'Embedded text content.',
|
|
365
|
+
mimeType: 'text/plain',
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
type: 'image',
|
|
370
|
+
data: 'BASE64_IMAGE_DATA',
|
|
371
|
+
mimeType: 'image/jpeg',
|
|
372
|
+
},
|
|
373
|
+
],
|
|
374
|
+
},
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
];
|
|
378
|
+
mockCallTool.mockResolvedValue(sdkResponse);
|
|
379
|
+
const toolResult = await tool.execute(params);
|
|
380
|
+
expect(toolResult.llmContent).toEqual([
|
|
381
|
+
{ text: 'Here is a resource.' },
|
|
382
|
+
{
|
|
383
|
+
text: 'Resource Link: My Resource at file:///path/to/resource',
|
|
384
|
+
},
|
|
385
|
+
{ text: 'Embedded text content.' },
|
|
386
|
+
{
|
|
387
|
+
text: `[Tool '${serverToolName}' provided the following image data with mime-type: image/jpeg]`,
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
inlineData: {
|
|
391
|
+
mimeType: 'image/jpeg',
|
|
392
|
+
data: 'BASE64_IMAGE_DATA',
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
]);
|
|
396
|
+
expect(toolResult.returnDisplay).toBe('Here is a resource.\n[Link to My Resource: file:///path/to/resource]\nEmbedded text content.\n[Image: image/jpeg]');
|
|
397
|
+
});
|
|
120
398
|
});
|
|
121
399
|
describe('shouldConfirmExecute', () => {
|
|
122
400
|
// beforeEach is already clearing allowlist
|