@llmindset/hf-mcp 0.3.2 → 0.3.4

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 (137) hide show
  1. package/dist/docs-search/doc-fetch.d.ts +1 -0
  2. package/dist/docs-search/doc-fetch.d.ts.map +1 -1
  3. package/dist/docs-search/doc-fetch.js +9 -12
  4. package/dist/docs-search/doc-fetch.js.map +1 -1
  5. package/dist/docs-search/doc-fetch.test.js +56 -11
  6. package/dist/docs-search/doc-fetch.test.js.map +1 -1
  7. package/dist/file-icons.d.ts +3 -0
  8. package/dist/file-icons.d.ts.map +1 -0
  9. package/dist/file-icons.js +38 -0
  10. package/dist/file-icons.js.map +1 -0
  11. package/dist/gradio-files.d.ts +0 -1
  12. package/dist/gradio-files.d.ts.map +1 -1
  13. package/dist/gradio-files.js +2 -35
  14. package/dist/gradio-files.js.map +1 -1
  15. package/dist/hf-api-call.d.ts.map +1 -1
  16. package/dist/hf-api-call.js +7 -7
  17. package/dist/hf-api-call.js.map +1 -1
  18. package/dist/index.browser.d.ts +48 -0
  19. package/dist/index.browser.d.ts.map +1 -0
  20. package/dist/index.browser.js +153 -0
  21. package/dist/index.browser.js.map +1 -0
  22. package/dist/index.d.ts +1 -0
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -0
  25. package/dist/index.js.map +1 -1
  26. package/dist/jobs/commands/uv-utils.d.ts +0 -3
  27. package/dist/jobs/commands/uv-utils.d.ts.map +1 -1
  28. package/dist/jobs/commands/uv-utils.js +2 -2
  29. package/dist/jobs/commands/uv-utils.js.map +1 -1
  30. package/dist/jobs/jobs-tool.d.ts.map +1 -1
  31. package/dist/jobs/jobs-tool.js +11 -12
  32. package/dist/jobs/jobs-tool.js.map +1 -1
  33. package/dist/jobs/schema-help.d.ts +2 -9
  34. package/dist/jobs/schema-help.d.ts.map +1 -1
  35. package/dist/jobs/schema-help.js +3 -3
  36. package/dist/jobs/schema-help.js.map +1 -1
  37. package/dist/jobs/sse-handler.d.ts +3 -2
  38. package/dist/jobs/sse-handler.d.ts.map +1 -1
  39. package/dist/jobs/sse-handler.js +8 -4
  40. package/dist/jobs/sse-handler.js.map +1 -1
  41. package/dist/jobs/types.d.ts +1 -1
  42. package/dist/logger.d.ts +2 -2
  43. package/dist/logger.d.ts.map +1 -1
  44. package/dist/network/fetch-profile.d.ts +24 -0
  45. package/dist/network/fetch-profile.d.ts.map +1 -0
  46. package/dist/network/fetch-profile.js +80 -0
  47. package/dist/network/fetch-profile.js.map +1 -0
  48. package/dist/network/index.d.ts +5 -0
  49. package/dist/network/index.d.ts.map +1 -0
  50. package/dist/network/index.js +5 -0
  51. package/dist/network/index.js.map +1 -0
  52. package/dist/network/ip-policy.d.ts +6 -0
  53. package/dist/network/ip-policy.d.ts.map +1 -0
  54. package/dist/network/ip-policy.js +202 -0
  55. package/dist/network/ip-policy.js.map +1 -0
  56. package/dist/network/ip-policy.test.d.ts +2 -0
  57. package/dist/network/ip-policy.test.d.ts.map +1 -0
  58. package/dist/network/ip-policy.test.js +46 -0
  59. package/dist/network/ip-policy.test.js.map +1 -0
  60. package/dist/network/safe-fetch.d.ts +16 -0
  61. package/dist/network/safe-fetch.d.ts.map +1 -0
  62. package/dist/network/safe-fetch.js +124 -0
  63. package/dist/network/safe-fetch.js.map +1 -0
  64. package/dist/network/safe-fetch.test.d.ts +2 -0
  65. package/dist/network/safe-fetch.test.d.ts.map +1 -0
  66. package/dist/network/safe-fetch.test.js +136 -0
  67. package/dist/network/safe-fetch.test.js.map +1 -0
  68. package/dist/network/url-policy.d.ts +32 -0
  69. package/dist/network/url-policy.d.ts.map +1 -0
  70. package/dist/network/url-policy.js +230 -0
  71. package/dist/network/url-policy.js.map +1 -0
  72. package/dist/network/url-policy.test.d.ts +2 -0
  73. package/dist/network/url-policy.test.d.ts.map +1 -0
  74. package/dist/network/url-policy.test.js +57 -0
  75. package/dist/network/url-policy.test.js.map +1 -0
  76. package/dist/readme-utils.d.ts.map +1 -1
  77. package/dist/readme-utils.js +3 -4
  78. package/dist/readme-utils.js.map +1 -1
  79. package/dist/space/commands/discover.d.ts +0 -5
  80. package/dist/space/commands/discover.d.ts.map +1 -1
  81. package/dist/space/commands/discover.js +9 -2
  82. package/dist/space/commands/discover.js.map +1 -1
  83. package/dist/space/commands/invoke.js +1 -59
  84. package/dist/space/commands/invoke.js.map +1 -1
  85. package/dist/space/commands/view-parameters.d.ts.map +1 -1
  86. package/dist/space/commands/view-parameters.js +3 -98
  87. package/dist/space/commands/view-parameters.js.map +1 -1
  88. package/dist/space/dynamic-space-tool.d.ts.map +1 -1
  89. package/dist/space/dynamic-space-tool.js +5 -2
  90. package/dist/space/dynamic-space-tool.js.map +1 -1
  91. package/dist/space/utils/gradio-caller.d.ts.map +1 -1
  92. package/dist/space/utils/gradio-caller.js +13 -6
  93. package/dist/space/utils/gradio-caller.js.map +1 -1
  94. package/dist/space/utils/space-http.d.ts +8 -0
  95. package/dist/space/utils/space-http.d.ts.map +1 -0
  96. package/dist/space/utils/space-http.js +49 -0
  97. package/dist/space/utils/space-http.js.map +1 -0
  98. package/dist/space-files.d.ts +0 -1
  99. package/dist/space-files.d.ts.map +1 -1
  100. package/dist/space-files.js +3 -36
  101. package/dist/space-files.js.map +1 -1
  102. package/package.json +6 -2
  103. package/src/docs-search/doc-fetch.test.ts +98 -28
  104. package/src/docs-search/doc-fetch.ts +9 -16
  105. package/src/file-icons.ts +39 -0
  106. package/src/gradio-files.ts +2 -40
  107. package/src/hf-api-call.ts +8 -10
  108. package/src/index.browser.ts +183 -0
  109. package/src/index.ts +1 -0
  110. package/src/jobs/commands/uv-utils.ts +2 -2
  111. package/src/jobs/jobs-tool.ts +13 -12
  112. package/src/jobs/schema-help.ts +4 -4
  113. package/src/jobs/sse-handler.ts +12 -7
  114. package/src/logger.ts +2 -2
  115. package/src/network/fetch-profile.ts +112 -0
  116. package/src/network/index.ts +4 -0
  117. package/src/network/ip-policy.test.ts +58 -0
  118. package/src/network/ip-policy.ts +252 -0
  119. package/src/network/safe-fetch.test.ts +181 -0
  120. package/src/network/safe-fetch.ts +174 -0
  121. package/src/network/url-policy.test.ts +100 -0
  122. package/src/network/url-policy.ts +304 -0
  123. package/src/readme-utils.ts +11 -10
  124. package/src/space/commands/discover.ts +10 -2
  125. package/src/space/commands/invoke.ts +1 -88
  126. package/src/space/commands/view-parameters.ts +3 -136
  127. package/src/space/dynamic-space-tool.ts +6 -2
  128. package/src/space/utils/gradio-caller.ts +25 -12
  129. package/src/space/utils/space-http.ts +75 -0
  130. package/src/space-files.ts +3 -41
  131. package/test/fetch-guard.spec.ts +70 -0
  132. package/test/jobs/sse-handler.spec.ts +60 -0
  133. package/dist/space/utils/result-formatter.d.ts +0 -4
  134. package/dist/space/utils/result-formatter.d.ts.map +0 -1
  135. package/dist/space/utils/result-formatter.js +0 -146
  136. package/dist/space/utils/result-formatter.js.map +0 -1
  137. package/src/space/utils/result-formatter.ts +0 -226
@@ -3,10 +3,17 @@ import {
3
3
  StreamableHTTPClientTransport,
4
4
  type StreamableHTTPClientTransportOptions,
5
5
  } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
6
- import { CallToolResultSchema, type CallToolResult, type ServerNotification, type ServerRequest } from '@modelcontextprotocol/sdk/types.js';
6
+ import {
7
+ CallToolResultSchema,
8
+ type CallToolResult,
9
+ type ServerNotification,
10
+ type ServerRequest,
11
+ } from '@modelcontextprotocol/sdk/types.js';
7
12
  import { Protocol, type RequestHandlerExtra, type RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
8
13
  import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
9
14
  import { logger } from '../../logger.js';
15
+ import { fetchWithProfile, NETWORK_FETCH_PROFILES } from '../../network/fetch-profile.js';
16
+ import { createGradioMcpPolicy, parseAndValidateUrl } from '../../network/url-policy.js';
10
17
 
11
18
  class GradioClient extends Client {
12
19
  override async connect(transport: Transport, _options?: RequestOptions): Promise<void> {
@@ -102,6 +109,10 @@ export async function callGradioToolWithHeaders(
102
109
  extra: RequestHandlerExtra<ServerRequest, ServerNotification> | undefined,
103
110
  options: GradioCallOptions = {}
104
111
  ): Promise<GradioCallResult> {
112
+ const validatedMcpUrl = parseAndValidateUrl(mcpUrl, createGradioMcpPolicy());
113
+ const protocol = validatedMcpUrl.protocol === 'http:' ? 'http:' : 'https:';
114
+ const mcpRequestProfile = NETWORK_FETCH_PROFILES.gradioMcpHost(validatedMcpUrl.hostname, protocol);
115
+
105
116
  const capturedHeaders: Record<string, string> = {};
106
117
  let loggedHeader = false;
107
118
 
@@ -154,7 +165,9 @@ export async function callGradioToolWithHeaders(
154
165
  hasBody: Boolean(init?.body),
155
166
  requestSummary,
156
167
  });
157
- const response = await fetch(url, init);
168
+ const { response } = await fetchWithProfile(url.toString(), mcpRequestProfile, {
169
+ requestInit: init,
170
+ });
158
171
  logger.trace('[gradio] upstream response', {
159
172
  method,
160
173
  url: url.toString(),
@@ -196,22 +209,22 @@ export async function callGradioToolWithHeaders(
196
209
  }
197
210
 
198
211
  logger.trace('[gradio] connecting streamable client', {
199
- mcpUrl,
212
+ mcpUrl: validatedMcpUrl.toString(),
200
213
  hasToken: Boolean(hfToken),
201
214
  skipInitialize,
202
215
  });
203
- const transport = new StreamableHTTPClientTransport(new URL(mcpUrl), transportOptions);
216
+ const transport = new StreamableHTTPClientTransport(validatedMcpUrl, transportOptions);
204
217
  let isClosing = false;
205
218
  transport.onmessage = (message) => {
206
219
  const messageInfo =
207
220
  message && typeof message === 'object'
208
221
  ? {
209
- hasId: 'id' in message,
210
- id: (message as { id?: unknown }).id ?? null,
211
- method: 'method' in message ? (message as { method?: unknown }).method : null,
212
- isResult: 'result' in message,
213
- isError: 'error' in message,
214
- }
222
+ hasId: 'id' in message,
223
+ id: (message as { id?: unknown }).id ?? null,
224
+ method: 'method' in message ? (message as { method?: unknown }).method : null,
225
+ isResult: 'result' in message,
226
+ isError: 'error' in message,
227
+ }
215
228
  : { messageType: typeof message };
216
229
  logger.trace('[gradio] transport message', messageInfo);
217
230
  };
@@ -228,13 +241,13 @@ export async function callGradioToolWithHeaders(
228
241
  let connectCompleted = false;
229
242
  const connectWatchdog = setTimeout(() => {
230
243
  if (!connectCompleted) {
231
- logger.trace('[gradio] connect still pending', { mcpUrl });
244
+ logger.trace('[gradio] connect still pending', { mcpUrl: validatedMcpUrl.toString() });
232
245
  }
233
246
  }, 15000);
234
247
  await remoteClient.connect(transport);
235
248
  connectCompleted = true;
236
249
  clearTimeout(connectWatchdog);
237
- logger.trace('[gradio] connected streamable client', { mcpUrl });
250
+ logger.trace('[gradio] connected streamable client', { mcpUrl: validatedMcpUrl.toString() });
238
251
 
239
252
  try {
240
253
  // Check if the client is requesting progress notifications
@@ -0,0 +1,75 @@
1
+ import type { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import { fetchWithProfile, NETWORK_FETCH_PROFILES } from '../../network/fetch-profile.js';
3
+ import { normalizeParsedTools, parseGradioSchemaResponse } from './gradio-schema.js';
4
+
5
+ const SPACE_HTTP_TIMEOUT_MS = 10_000;
6
+
7
+ export interface SpaceMetadata {
8
+ subdomain: string;
9
+ private: boolean;
10
+ }
11
+
12
+ export async function fetchSpaceMetadata(spaceName: string, hfToken?: string): Promise<SpaceMetadata> {
13
+ const url = `https://huggingface.co/api/spaces/${spaceName}`;
14
+ const headers: Record<string, string> = {};
15
+
16
+ if (hfToken) {
17
+ headers['Authorization'] = `Bearer ${hfToken}`;
18
+ }
19
+
20
+ const { response } = await fetchWithProfile(url, NETWORK_FETCH_PROFILES.hfHub(), {
21
+ timeoutMs: SPACE_HTTP_TIMEOUT_MS,
22
+ requestInit: {
23
+ headers,
24
+ },
25
+ });
26
+
27
+ if (!response.ok) {
28
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
29
+ }
30
+
31
+ const info = (await response.json()) as {
32
+ subdomain?: string;
33
+ private?: boolean;
34
+ };
35
+
36
+ if (!info.subdomain) {
37
+ throw new Error('Space does not have a subdomain');
38
+ }
39
+
40
+ return {
41
+ subdomain: info.subdomain,
42
+ private: info.private || false,
43
+ };
44
+ }
45
+
46
+ export async function fetchGradioSchema(subdomain: string, isPrivate: boolean, hfToken?: string): Promise<Tool[]> {
47
+ const schemaUrl = `https://${subdomain}.hf.space/gradio_api/mcp/schema`;
48
+
49
+ const headers: Record<string, string> = {
50
+ 'Content-Type': 'application/json',
51
+ };
52
+
53
+ if (isPrivate && hfToken) {
54
+ headers['X-HF-Authorization'] = `Bearer ${hfToken}`;
55
+ }
56
+
57
+ const { response } = await fetchWithProfile(
58
+ schemaUrl,
59
+ NETWORK_FETCH_PROFILES.gradioSchemaHost(`${subdomain}.hf.space`),
60
+ {
61
+ timeoutMs: SPACE_HTTP_TIMEOUT_MS,
62
+ requestInit: {
63
+ method: 'GET',
64
+ headers,
65
+ },
66
+ }
67
+ );
68
+
69
+ if (!response.ok) {
70
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
71
+ }
72
+
73
+ const schemaResponse = (await response.json()) as unknown;
74
+ return normalizeParsedTools(parseGradioSchemaResponse(schemaResponse));
75
+ }
@@ -3,6 +3,7 @@ import { listFiles, spaceInfo } from '@huggingface/hub';
3
3
  import { formatBytes, escapeMarkdown } from './utilities.js';
4
4
  import { HfApiError } from './hf-api-call.js';
5
5
  import { explain } from './error-messages.js';
6
+ import { getFileIcon } from './file-icons.js';
6
7
 
7
8
  // Define the FileWithUrl interface
8
9
  export interface FileWithUrl {
@@ -226,7 +227,7 @@ export class SpaceFilesTool {
226
227
  for (const file of dirFiles) {
227
228
  const fileName = file.path.split('/').pop() || file.path;
228
229
  const indent = dir === '/' ? '' : '&nbsp;&nbsp;&nbsp;&nbsp;';
229
- const icon = this.getFileIcon(fileName);
230
+ const icon = getFileIcon(fileName);
230
231
  const lastMod = file.lastModified ? new Date(file.lastModified).toLocaleDateString() : '-';
231
232
 
232
233
  markdown += `| ${indent}${icon} ${escapeMarkdown(fileName)} | ${file.sizeFormatted} | ${file.lfs ? 'LFS' : 'Regular'} | ${lastMod} | ${file.url} |\n`;
@@ -265,7 +266,7 @@ export class SpaceFilesTool {
265
266
 
266
267
  for (const file of files) {
267
268
  const fileName = file.path.split('/').pop() || file.path;
268
- const icon = this.getFileIcon(fileName);
269
+ const icon = getFileIcon(fileName);
269
270
  markdown += `| ${icon} ${escapeMarkdown(fileName)} | ${escapeMarkdown(file.path)} | ${file.sizeFormatted} | [Link](${file.url}) |\n`;
270
271
  }
271
272
 
@@ -283,43 +284,4 @@ export class SpaceFilesTool {
283
284
 
284
285
  return this.generateDetailedMarkdown(spaceName, fileType);
285
286
  }
286
-
287
- /**
288
- * Get file icon based on extension
289
- */
290
- private getFileIcon(filename: string): string {
291
- const ext = filename.split('.').pop()?.toLowerCase();
292
- const iconMap: Record<string, string> = {
293
- py: '🐍',
294
- js: '📜',
295
- ts: '📘',
296
- md: '📝',
297
- txt: '📄',
298
- json: '📊',
299
- yaml: '⚙️',
300
- yml: '⚙️',
301
- png: '🖼️',
302
- jpg: '🖼️',
303
- jpeg: '🖼️',
304
- gif: '🖼️',
305
- svg: '🎨',
306
- mp4: '🎬',
307
- mp3: '🎵',
308
- pdf: '📕',
309
- zip: '📦',
310
- tar: '📦',
311
- gz: '📦',
312
- html: '🌐',
313
- css: '🎨',
314
- ipynb: '📓',
315
- csv: '📊',
316
- parquet: '🗄️',
317
- safetensors: '🤖',
318
- bin: '💾',
319
- pkl: '🥒',
320
- h5: '🗃️',
321
- };
322
-
323
- return iconMap[ext || ''] || '📄';
324
- }
325
287
  }
@@ -0,0 +1,70 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import { readdirSync, readFileSync, statSync } from 'node:fs';
3
+ import { join } from 'node:path';
4
+
5
+ const SRC_ROOT = join(process.cwd(), 'src');
6
+
7
+ function collectTsFiles(root: string): string[] {
8
+ const entries = readdirSync(root);
9
+ const files: string[] = [];
10
+
11
+ for (const entry of entries) {
12
+ const fullPath = join(root, entry);
13
+ const stat = statSync(fullPath);
14
+ if (stat.isDirectory()) {
15
+ files.push(...collectTsFiles(fullPath));
16
+ continue;
17
+ }
18
+
19
+ if (fullPath.endsWith('.ts')) {
20
+ files.push(fullPath);
21
+ }
22
+ }
23
+
24
+ return files;
25
+ }
26
+
27
+ function hasDirectFetchCall(content: string): boolean {
28
+ const regex = /fetch\s*\(/g;
29
+ let match: RegExpExecArray | null;
30
+
31
+ while ((match = regex.exec(content)) !== null) {
32
+ const index = match.index;
33
+ const previousChar = index > 0 ? content[index - 1] : '';
34
+
35
+ if (/[\w$.]/.test(previousChar)) {
36
+ continue;
37
+ }
38
+
39
+ const prefix = content.slice(Math.max(0, index - 20), index);
40
+ if (/\basync\s+$/.test(prefix) || /\bfunction\s+$/.test(prefix)) {
41
+ continue;
42
+ }
43
+
44
+ return true;
45
+ }
46
+
47
+ return false;
48
+ }
49
+
50
+ describe('fetch usage guard', () => {
51
+ it('only allows direct fetch calls in network/safe-fetch.ts', () => {
52
+ const allowedSuffixes = new Set(['/network/safe-fetch.ts']);
53
+ const offenders: string[] = [];
54
+ const files = collectTsFiles(SRC_ROOT);
55
+
56
+ for (const file of files) {
57
+ const content = readFileSync(file, 'utf8');
58
+ if (!hasDirectFetchCall(content)) {
59
+ continue;
60
+ }
61
+
62
+ const normalized = file.replace(SRC_ROOT, '').replace(/\\/g, '/');
63
+ if (!allowedSuffixes.has(normalized)) {
64
+ offenders.push(normalized);
65
+ }
66
+ }
67
+
68
+ expect(offenders).toEqual([]);
69
+ });
70
+ });
@@ -0,0 +1,60 @@
1
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
2
+ import { fetchJobLogs } from '../../src/jobs/sse-handler.js';
3
+ import { safeFetch } from '../../src/network/safe-fetch.js';
4
+
5
+ vi.mock('../../src/network/safe-fetch.js', () => ({
6
+ safeFetch: vi.fn(),
7
+ }));
8
+
9
+ function createSseResponse(read: () => Promise<ReadableStreamReadResult<Uint8Array>>): Response {
10
+ return {
11
+ ok: true,
12
+ body: {
13
+ getReader: () => ({
14
+ read,
15
+ cancel: vi.fn().mockResolvedValue(undefined),
16
+ }),
17
+ },
18
+ } as unknown as Response;
19
+ }
20
+
21
+ describe('fetchJobLogs', () => {
22
+ beforeEach(() => {
23
+ vi.clearAllMocks();
24
+ });
25
+
26
+ it('treats timeout-aborted SSE reads as expected truncation', async () => {
27
+ const abortedRead = async (): Promise<ReadableStreamReadResult<Uint8Array>> => {
28
+ await new Promise((resolve) => setTimeout(resolve, 20));
29
+ throw new DOMException('The operation was aborted.', 'AbortError');
30
+ };
31
+
32
+ vi.mocked(safeFetch).mockResolvedValue({
33
+ response: createSseResponse(abortedRead),
34
+ finalUrl: new URL('https://example.com/logs'),
35
+ redirectsFollowed: 0,
36
+ });
37
+
38
+ const result = await fetchJobLogs('https://example.com/logs', { maxDuration: 1, maxLines: 5 });
39
+
40
+ expect(result).toEqual({
41
+ logs: [],
42
+ finished: false,
43
+ truncated: true,
44
+ });
45
+ });
46
+
47
+ it('throws non-timeout stream errors', async () => {
48
+ const failingRead = async (): Promise<ReadableStreamReadResult<Uint8Array>> => {
49
+ throw new Error('stream read failed');
50
+ };
51
+
52
+ vi.mocked(safeFetch).mockResolvedValue({
53
+ response: createSseResponse(failingRead),
54
+ finalUrl: new URL('https://example.com/logs'),
55
+ redirectsFollowed: 0,
56
+ });
57
+
58
+ await expect(fetchJobLogs('https://example.com/logs', { maxDuration: 100 })).rejects.toThrow('stream read failed');
59
+ });
60
+ });
@@ -1,4 +0,0 @@
1
- import type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
2
- export declare function formatToolResult(result: CallToolResult): string;
3
- export declare function formatWarnings(warnings: string[]): string;
4
- //# sourceMappingURL=result-formatter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"result-formatter.d.ts","sourceRoot":"","sources":["../../../src/space/utils/result-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAUzE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAa/D;AAmMD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAOzD"}
@@ -1,146 +0,0 @@
1
- export function formatToolResult(result) {
2
- if (result.isError) {
3
- return formatErrorResult(result);
4
- }
5
- if (Array.isArray(result.content) && result.content.length > 0) {
6
- return formatContentArray(result.content);
7
- }
8
- return 'Tool executed successfully (no content returned).';
9
- }
10
- function formatErrorResult(result) {
11
- if (!Array.isArray(result.content) || result.content.length === 0) {
12
- return 'Error: Tool execution failed (no error details provided).';
13
- }
14
- const errorMessages = [];
15
- for (const item of result.content) {
16
- if (typeof item === 'string') {
17
- errorMessages.push(item);
18
- }
19
- else if (item && typeof item === 'object') {
20
- const obj = item;
21
- if (typeof obj.text === 'string') {
22
- errorMessages.push(obj.text);
23
- }
24
- else if (typeof obj.message === 'string') {
25
- errorMessages.push(obj.message);
26
- }
27
- else if (typeof obj.error === 'string') {
28
- errorMessages.push(obj.error);
29
- }
30
- }
31
- }
32
- if (errorMessages.length > 0) {
33
- return `Error: ${errorMessages.join('\n')}`;
34
- }
35
- return 'Error: Tool execution failed.';
36
- }
37
- function formatContentArray(content) {
38
- const formattedItems = [];
39
- for (const item of content) {
40
- const formatted = formatContentItem(item);
41
- if (formatted) {
42
- formattedItems.push(formatted);
43
- }
44
- }
45
- if (formattedItems.length === 0) {
46
- return 'Tool executed successfully (no displayable content).';
47
- }
48
- return formattedItems.join('\n\n');
49
- }
50
- function formatContentItem(item) {
51
- if (!item) {
52
- return null;
53
- }
54
- if (typeof item === 'string') {
55
- return item;
56
- }
57
- if (typeof item !== 'object') {
58
- if (typeof item === 'number' || typeof item === 'boolean') {
59
- return String(item);
60
- }
61
- return JSON.stringify(item);
62
- }
63
- const obj = item;
64
- const type = typeof obj.type === 'string' ? obj.type.toLowerCase() : undefined;
65
- switch (type) {
66
- case 'text':
67
- return formatTextContent(obj);
68
- case 'image':
69
- return formatImageContent(obj);
70
- case 'resource':
71
- return formatResourceContent(obj);
72
- case 'embedded_resource':
73
- return formatEmbeddedResourceContent(obj);
74
- default:
75
- if (typeof obj.text === 'string') {
76
- return obj.text;
77
- }
78
- try {
79
- return JSON.stringify(item, null, 2);
80
- }
81
- catch {
82
- return '[complex object]';
83
- }
84
- }
85
- }
86
- function formatTextContent(obj) {
87
- if (typeof obj.text === 'string') {
88
- return obj.text;
89
- }
90
- return null;
91
- }
92
- function formatImageContent(obj) {
93
- const parts = ['[Image Content]'];
94
- if (typeof obj.mimeType === 'string') {
95
- parts.push(`Type: ${obj.mimeType}`);
96
- }
97
- if (typeof obj.url === 'string') {
98
- parts.push(`URL: ${obj.url}`);
99
- }
100
- if (typeof obj.data === 'string') {
101
- const dataLength = obj.data.length;
102
- parts.push(`Data: ${dataLength} characters (base64)`);
103
- }
104
- return parts.join('\n');
105
- }
106
- function formatResourceContent(obj) {
107
- const parts = ['[Resource]'];
108
- const resource = obj.resource;
109
- if (resource) {
110
- if (typeof resource.uri === 'string') {
111
- parts.push(`URI: ${resource.uri}`);
112
- }
113
- if (typeof resource.name === 'string') {
114
- parts.push(`Name: ${resource.name}`);
115
- }
116
- if (typeof resource.mimeType === 'string') {
117
- parts.push(`Type: ${resource.mimeType}`);
118
- }
119
- if (typeof resource.description === 'string') {
120
- parts.push(`Description: ${resource.description}`);
121
- }
122
- }
123
- return parts.join('\n');
124
- }
125
- function formatEmbeddedResourceContent(obj) {
126
- const parts = ['[Embedded Resource]'];
127
- if (typeof obj.uri === 'string') {
128
- parts.push(`URI: ${obj.uri}`);
129
- }
130
- if (typeof obj.mimeType === 'string') {
131
- parts.push(`Type: ${obj.mimeType}`);
132
- }
133
- if (typeof obj.blob === 'string') {
134
- const blobLength = obj.blob.length;
135
- parts.push(`Data: ${blobLength} characters`);
136
- }
137
- return parts.join('\n');
138
- }
139
- export function formatWarnings(warnings) {
140
- if (warnings.length === 0) {
141
- return '';
142
- }
143
- const header = warnings.length === 1 ? 'Warning:' : 'Warnings:';
144
- return `${header}\n${warnings.map((w) => `- ${w}`).join('\n')}\n\n`;
145
- }
146
- //# sourceMappingURL=result-formatter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"result-formatter.js","sourceRoot":"","sources":["../../../src/space/utils/result-formatter.ts"],"names":[],"mappings":"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"}