@llmindset/hf-mcp 0.2.39 → 0.2.40

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 (41) hide show
  1. package/dist/docs-search/docs-semantic-search.test.js +20 -44
  2. package/dist/docs-search/docs-semantic-search.test.js.map +1 -1
  3. package/dist/hf-api-call.d.ts.map +1 -1
  4. package/dist/hf-api-call.js +21 -7
  5. package/dist/hf-api-call.js.map +1 -1
  6. package/dist/jobs/commands/inspect.js +1 -1
  7. package/dist/jobs/commands/inspect.js.map +1 -1
  8. package/dist/jobs/commands/logs.js +3 -3
  9. package/dist/jobs/commands/logs.js.map +1 -1
  10. package/dist/jobs/commands/ps.js +1 -1
  11. package/dist/jobs/commands/ps.js.map +1 -1
  12. package/dist/jobs/commands/run.js +6 -6
  13. package/dist/jobs/commands/run.js.map +1 -1
  14. package/dist/jobs/commands/scheduled.js +5 -5
  15. package/dist/jobs/commands/scheduled.js.map +1 -1
  16. package/dist/jobs/jobs-tool.d.ts +4 -4
  17. package/dist/jobs/jobs-tool.d.ts.map +1 -1
  18. package/dist/jobs/jobs-tool.js +202 -137
  19. package/dist/jobs/jobs-tool.js.map +1 -1
  20. package/dist/jobs/schema-help.d.ts +1 -2
  21. package/dist/jobs/schema-help.d.ts.map +1 -1
  22. package/dist/jobs/sse-handler.d.ts +3 -0
  23. package/dist/jobs/sse-handler.d.ts.map +1 -1
  24. package/dist/jobs/sse-handler.js +4 -1
  25. package/dist/jobs/sse-handler.js.map +1 -1
  26. package/dist/jobs/types.d.ts +4 -4
  27. package/dist/jobs/types.d.ts.map +1 -1
  28. package/dist/jobs/types.js +8 -4
  29. package/dist/jobs/types.js.map +1 -1
  30. package/package.json +1 -1
  31. package/src/docs-search/docs-semantic-search.test.ts +22 -44
  32. package/src/hf-api-call.ts +30 -8
  33. package/src/jobs/commands/inspect.ts +1 -1
  34. package/src/jobs/commands/logs.ts +3 -3
  35. package/src/jobs/commands/ps.ts +1 -1
  36. package/src/jobs/commands/run.ts +6 -6
  37. package/src/jobs/commands/scheduled.ts +5 -5
  38. package/src/jobs/jobs-tool.ts +231 -149
  39. package/src/jobs/schema-help.ts +1 -1
  40. package/src/jobs/sse-handler.ts +16 -1
  41. package/src/jobs/types.ts +8 -4
@@ -24,7 +24,11 @@ const commonArgsSchema = z.object({
24
24
  namespace: z.string().optional().describe('Target namespace (username or organization). Defaults to current user.'),
25
25
  });
26
26
  export const runArgsSchema = commonArgsSchema.extend({
27
- image: z.string().describe('Docker image or HF Space URL (e.g., "python:3.12" or "hf.co/spaces/user/space")'),
27
+ image: z
28
+ .string()
29
+ .describe('Docker image or HF Space URL (e.g., "python:3.12" or "hf.co/spaces/user/space")')
30
+ .optional()
31
+ .default('python:3.12'),
28
32
  command: z
29
33
  .union([z.string(), z.array(z.string())])
30
34
  .describe('Command to execute. Array format recommended (e.g., ["python", "script.py"]). ' +
@@ -44,8 +48,8 @@ export const runArgsSchema = commonArgsSchema.extend({
44
48
  detach: z
45
49
  .boolean()
46
50
  .optional()
47
- .default(true)
48
- .describe('Run in background and return after 10 seconds (default: true)'),
51
+ .default(false)
52
+ .describe('If true, return immediately with job ID. If false (default), tail logs for up to 10 seconds.'),
49
53
  });
50
54
  export const uvArgsSchema = commonArgsSchema.extend({
51
55
  script: z
@@ -61,7 +65,7 @@ export const uvArgsSchema = commonArgsSchema.extend({
61
65
  .optional()
62
66
  .describe('Secrets as key-value pairs. Use HF_TOKEN=$HF_TOKEN to include your token'),
63
67
  timeout: z.string().optional().default('30m').describe('Max duration'),
64
- detach: z.boolean().optional().default(true).describe('Run in background and return after 10 seconds'),
68
+ detach: z.boolean().optional().default(false).describe('If true, return immediately with job ID. If false (default), tail logs for up to 10 seconds.'),
65
69
  });
66
70
  export const psArgsSchema = commonArgsSchema.extend({
67
71
  all: z.boolean().optional().default(false).describe('Show all jobs (default: only running)'),
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/jobs/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/jobs/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@llmindset/hf-mcp",
3
- "version": "0.2.39",
3
+ "version": "0.2.40",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -6,6 +6,17 @@ import { DOC_FETCH_CONFIG } from './doc-fetch.js';
6
6
  const mockFetch = vi.fn();
7
7
  global.fetch = mockFetch as typeof fetch;
8
8
 
9
+ // Helper to create a proper mock Response
10
+ function createMockResponse(data: unknown) {
11
+ const jsonString = JSON.stringify(data);
12
+ return {
13
+ ok: true,
14
+ text: () => Promise.resolve(jsonString),
15
+ json: () => Promise.resolve(data),
16
+ headers: new Headers({ 'content-type': 'application/json' }),
17
+ };
18
+ }
19
+
9
20
  describe('DocSearchTool', () => {
10
21
  let docSearchTool: DocSearchTool;
11
22
 
@@ -20,10 +31,7 @@ describe('DocSearchTool', () => {
20
31
  });
21
32
 
22
33
  it('should return no results message when API returns empty array', async () => {
23
- mockFetch.mockResolvedValueOnce({
24
- ok: true,
25
- json: () => Promise.resolve([]),
26
- });
34
+ mockFetch.mockResolvedValueOnce(createMockResponse([]));
27
35
 
28
36
  const result = await docSearchTool.search({ query: 'nonexistent' });
29
37
  expect(result.formatted).toBe(`No documentation found for query 'nonexistent'`);
@@ -32,10 +40,7 @@ describe('DocSearchTool', () => {
32
40
  });
33
41
 
34
42
  it('should return no results message with product filter', async () => {
35
- mockFetch.mockResolvedValueOnce({
36
- ok: true,
37
- json: () => Promise.resolve([]),
38
- });
43
+ mockFetch.mockResolvedValueOnce(createMockResponse([]));
39
44
 
40
45
  const result = await docSearchTool.search({ query: 'nonexistent', product: 'hub' });
41
46
  expect(result.formatted).toBe(`No documentation found for query 'nonexistent' in product 'hub'`);
@@ -70,10 +75,7 @@ describe('DocSearchTool', () => {
70
75
  },
71
76
  ];
72
77
 
73
- mockFetch.mockResolvedValueOnce({
74
- ok: true,
75
- json: () => Promise.resolve(sampleResults),
76
- });
78
+ mockFetch.mockResolvedValueOnce(createMockResponse(sampleResults));
77
79
 
78
80
  const result = await docSearchTool.search({ query: 'analytics' });
79
81
 
@@ -124,10 +126,7 @@ describe('DocSearchTool', () => {
124
126
  },
125
127
  ];
126
128
 
127
- mockFetch.mockResolvedValueOnce({
128
- ok: true,
129
- json: () => Promise.resolve(sampleResults),
130
- });
129
+ mockFetch.mockResolvedValueOnce(createMockResponse(sampleResults));
131
130
 
132
131
  const result = await docSearchTool.search({ query: 'transformers' });
133
132
 
@@ -150,10 +149,7 @@ describe('DocSearchTool', () => {
150
149
  },
151
150
  ];
152
151
 
153
- mockFetch.mockResolvedValueOnce({
154
- ok: true,
155
- json: () => Promise.resolve(sampleResults),
156
- });
152
+ mockFetch.mockResolvedValueOnce(createMockResponse(sampleResults));
157
153
 
158
154
  const result = await docSearchTool.search({ query: 'special' });
159
155
 
@@ -176,10 +172,7 @@ describe('DocSearchTool', () => {
176
172
  },
177
173
  ];
178
174
 
179
- mockFetch.mockResolvedValueOnce({
180
- ok: true,
181
- json: () => Promise.resolve(sampleResults),
182
- });
175
+ mockFetch.mockResolvedValueOnce(createMockResponse(sampleResults));
183
176
 
184
177
  const result = await docSearchTool.search({ query: 'html' });
185
178
 
@@ -233,10 +226,7 @@ describe('DocSearchTool', () => {
233
226
  },
234
227
  ];
235
228
 
236
- mockFetch.mockResolvedValueOnce({
237
- ok: true,
238
- json: () => Promise.resolve(sampleResults),
239
- });
229
+ mockFetch.mockResolvedValueOnce(createMockResponse(sampleResults));
240
230
 
241
231
  const result = await docSearchTool.search({ query: 'test' });
242
232
 
@@ -263,10 +253,7 @@ describe('DocSearchTool', () => {
263
253
  });
264
254
 
265
255
  it('should include product filter in API call when provided', async () => {
266
- mockFetch.mockResolvedValueOnce({
267
- ok: true,
268
- json: () => Promise.resolve([]),
269
- });
256
+ mockFetch.mockResolvedValueOnce(createMockResponse([]));
270
257
 
271
258
  await docSearchTool.search({ query: 'test', product: 'hub' });
272
259
 
@@ -301,10 +288,7 @@ describe('DocSearchTool', () => {
301
288
  },
302
289
  ];
303
290
 
304
- mockFetch.mockResolvedValueOnce({
305
- ok: true,
306
- json: () => Promise.resolve(sampleResults),
307
- });
291
+ mockFetch.mockResolvedValueOnce(createMockResponse(sampleResults));
308
292
 
309
293
  const result = await docSearchTool.search({ query: 'analytics' });
310
294
 
@@ -357,10 +341,7 @@ describe('DocSearchTool', () => {
357
341
  });
358
342
  }
359
343
 
360
- mockFetch.mockResolvedValueOnce({
361
- ok: true,
362
- json: () => Promise.resolve(manyResults),
363
- });
344
+ mockFetch.mockResolvedValueOnce(createMockResponse(manyResults));
364
345
 
365
346
  const result = await smallBudgetTool.search({ query: 'test' });
366
347
 
@@ -423,10 +404,7 @@ describe('DocSearchTool', () => {
423
404
  },
424
405
  ];
425
406
 
426
- mockFetch.mockResolvedValueOnce({
427
- ok: true,
428
- json: () => Promise.resolve(sampleResults),
429
- });
407
+ mockFetch.mockResolvedValueOnce(createMockResponse(sampleResults));
430
408
 
431
409
  const result = await docSearchTool.search({ query: 'test' });
432
410
 
@@ -111,14 +111,11 @@ export class HfApiCall<TParams = Record<string, string | undefined>, TResponse =
111
111
 
112
112
  clearTimeout(timeoutId);
113
113
 
114
+ const responseBodyText = await response.text();
115
+
114
116
  if (!response.ok) {
115
117
  // Try to get error details from response body
116
- let responseBody: string | undefined;
117
- try {
118
- responseBody = await response.text();
119
- } catch {
120
- // Ignore if we can't read the body
121
- }
118
+ const responseBody: string | undefined = responseBodyText || undefined;
122
119
 
123
120
  // Log the error for debugging
124
121
  console.error(`[API Error] ${response.status} ${response.statusText}`);
@@ -134,7 +131,33 @@ export class HfApiCall<TParams = Record<string, string | undefined>, TResponse =
134
131
  );
135
132
  }
136
133
 
137
- return (await response.json()) as T;
134
+ const contentType = response.headers.get('content-type') ?? '';
135
+ const trimmedBody = responseBodyText.trim();
136
+ const looksLikeJson =
137
+ contentType.includes('application/json') || trimmedBody.startsWith('{') || trimmedBody.startsWith('[');
138
+
139
+ if (trimmedBody.length === 0) {
140
+ return undefined as T;
141
+ }
142
+
143
+ if (looksLikeJson) {
144
+ try {
145
+ return JSON.parse(responseBodyText) as T;
146
+ } catch (error) {
147
+ throw new Error(
148
+ `API request failed: Unable to parse JSON response (${error instanceof Error ? error.message : 'unknown error'})`
149
+ );
150
+ }
151
+ }
152
+
153
+ if (trimmedBody.toUpperCase() === 'OK') {
154
+ return undefined as T;
155
+ }
156
+
157
+ const truncatedBody = trimmedBody.length > 200 ? `${trimmedBody.slice(0, 200)}…` : trimmedBody;
158
+ throw new Error(
159
+ `API request failed: Unexpected non-JSON response${contentType ? ` (content-type: ${contentType})` : ''}: ${truncatedBody}`
160
+ );
138
161
  } catch (error) {
139
162
  // Re-throw HfApiError as-is to preserve status information
140
163
  if (error instanceof HfApiError) {
@@ -184,5 +207,4 @@ export class HfApiCall<TParams = Record<string, string | undefined>, TResponse =
184
207
  const url = this.buildUrl(params);
185
208
  return this.fetchFromApi<T>(url, options);
186
209
  }
187
-
188
210
  }
@@ -34,5 +34,5 @@ export async function cancelCommand(args: CancelArgs, client: JobsApiClient): Pr
34
34
 
35
35
  return `✓ Job ${args.job_id} has been cancelled.
36
36
 
37
- To verify: \`hf_jobs("inspect", {"job_id": "${args.job_id}"})\``;
37
+ To verify, call this tool with \`{"operation": "inspect", "args": {"job_id": "${args.job_id}"}}\``;
38
38
  }
@@ -1,6 +1,6 @@
1
1
  import type { LogsArgs } from '../types.js';
2
2
  import type { JobsApiClient } from '../api-client.js';
3
- import { fetchJobLogs } from '../sse-handler.js';
3
+ import { fetchJobLogs, DEFAULT_LOG_WAIT_MS, DEFAULT_LOG_WAIT_SECONDS } from '../sse-handler.js';
4
4
 
5
5
  /**
6
6
  * Execute the 'logs' command
@@ -14,7 +14,7 @@ export async function logsCommand(args: LogsArgs, client: JobsApiClient, token?:
14
14
  // Fetch logs with timeout and line limit
15
15
  const result = await fetchJobLogs(logsUrl, {
16
16
  token,
17
- maxDuration: 10000,
17
+ maxDuration: DEFAULT_LOG_WAIT_MS,
18
18
  maxLines: args.tail,
19
19
  });
20
20
 
@@ -29,7 +29,7 @@ export async function logsCommand(args: LogsArgs, client: JobsApiClient, token?:
29
29
  if (result.finished) {
30
30
  response += '\n\n✓ Job finished.';
31
31
  } else if (result.truncated) {
32
- response += '\n\n⚠ Log collection stopped after 10 seconds. Job may still be running.';
32
+ response += `\n\n⚠ Log collection stopped after ${DEFAULT_LOG_WAIT_SECONDS} seconds. Job may still be running.`;
33
33
  }
34
34
 
35
35
  return response;
@@ -31,7 +31,7 @@ export async function psCommand(args: PsArgs, client: JobsApiClient): Promise<st
31
31
  if (args.all) {
32
32
  return 'No jobs found.';
33
33
  }
34
- return 'No running jobs found. Use `{"all": true}` to show all jobs.';
34
+ return 'No running jobs found. Use `{"args": {"all": true}}` to show all jobs.';
35
35
  }
36
36
 
37
37
  return `**Jobs (${jobs.length} of ${allJobs.length} total):**
@@ -1,7 +1,7 @@
1
1
  import type { RunArgs, UvArgs } from '../types.js';
2
2
  import type { JobsApiClient } from '../api-client.js';
3
3
  import { createJobSpec } from './utils.js';
4
- import { fetchJobLogs } from '../sse-handler.js';
4
+ import { fetchJobLogs, DEFAULT_LOG_WAIT_MS, DEFAULT_MAX_LOG_LINES, DEFAULT_LOG_WAIT_SECONDS } from '../sse-handler.js';
5
5
  import { resolveUvCommand, UV_DEFAULT_IMAGE } from './uv-utils.js';
6
6
 
7
7
  /**
@@ -33,18 +33,18 @@ export async function runCommand(args: RunArgs, client: JobsApiClient, token?: s
33
33
  **Status:** ${job.status.stage}
34
34
  **View at:** ${jobUrl}
35
35
 
36
- To check logs: \`hf_jobs("logs", {"job_id": "${job.id}"})\`
37
- To inspect: \`hf_jobs("inspect", {"job_id": "${job.id}"})\``;
36
+ To check logs, call this tool with \`{"operation": "logs", "args": {"job_id": "${job.id}"}}\`
37
+ To inspect, call this tool with \`{"operation": "inspect", "args": {"job_id": "${job.id}"}}\``;
38
38
  }
39
39
 
40
40
  // Not detached - fetch logs
41
41
  const logsUrl = client.getLogsUrl(job.id, job.owner.name);
42
- const logResult = await fetchJobLogs(logsUrl, { token, maxDuration: 10000, maxLines: 20 });
42
+ const logResult = await fetchJobLogs(logsUrl, { token, maxDuration: DEFAULT_LOG_WAIT_MS, maxLines: DEFAULT_MAX_LOG_LINES });
43
43
 
44
44
  let response = `Job started: ${job.id}\n\n`;
45
45
 
46
46
  if (logResult.logs.length > 0) {
47
- response += '**Logs (last 20 lines):**\n```\n';
47
+ response += `**Logs (last ${DEFAULT_MAX_LOG_LINES} lines):**\n\`\`\`\n`;
48
48
  response += logResult.logs.join('\n');
49
49
  response += '\n```\n\n';
50
50
  }
@@ -52,7 +52,7 @@ To inspect: \`hf_jobs("inspect", {"job_id": "${job.id}"})\``;
52
52
  if (logResult.finished) {
53
53
  response += `Job finished. Full details: ${jobUrl}`;
54
54
  } else if (logResult.truncated) {
55
- response += `Log collection stopped after 10s. Job may still be running.\n`;
55
+ response += `Log collection stopped after ${DEFAULT_LOG_WAIT_SECONDS}s. Job may still be running.\n`;
56
56
  response += `View full logs: ${jobUrl}`;
57
57
  }
58
58
 
@@ -47,8 +47,8 @@ export async function scheduledRunCommand(
47
47
  **Suspended:** ${scheduledJob.suspend ? 'Yes' : 'No'}
48
48
  **Next Run:** ${scheduledJob.nextRun || 'N/A'}
49
49
 
50
- To inspect: \`hf_jobs("scheduled inspect", {"scheduled_job_id": "${scheduledJob.id}"})\`
51
- To list all: \`hf_jobs("scheduled ps")\``;
50
+ To inspect, call this tool with \`{"operation": "scheduled inspect", "args": {"scheduled_job_id": "${scheduledJob.id}"}}\`
51
+ To list all, call this tool with \`{"operation": "scheduled ps"}\``;
52
52
  }
53
53
 
54
54
  /**
@@ -106,7 +106,7 @@ export async function scheduledPsCommand(args: ScheduledPsArgs, client: JobsApiC
106
106
  if (args.all) {
107
107
  return 'No scheduled jobs found.';
108
108
  }
109
- return 'No active scheduled jobs found. Use `{"all": true}` to show suspended jobs.';
109
+ return 'No active scheduled jobs found. Use `{"args": {"all": true}}` to show suspended jobs.';
110
110
  }
111
111
 
112
112
  return `**Scheduled Jobs (${jobs.length} of ${allJobs.length} total):**
@@ -143,7 +143,7 @@ export async function scheduledSuspendCommand(args: ScheduledJobArgs, client: Jo
143
143
 
144
144
  return `✓ Scheduled job ${args.scheduled_job_id} has been suspended.
145
145
 
146
- To resume: \`hf_jobs("scheduled resume", {"scheduled_job_id": "${args.scheduled_job_id}"})\``;
146
+ To resume, call this tool with \`{"operation": "scheduled resume", "args": {"scheduled_job_id": "${args.scheduled_job_id}"}}\``;
147
147
  }
148
148
 
149
149
  /**
@@ -155,5 +155,5 @@ export async function scheduledResumeCommand(args: ScheduledJobArgs, client: Job
155
155
 
156
156
  return `✓ Scheduled job ${args.scheduled_job_id} has been resumed.
157
157
 
158
- To inspect: \`hf_jobs("scheduled inspect", {"scheduled_job_id": "${args.scheduled_job_id}"})\``;
158
+ To inspect, call this tool with \`{"operation": "scheduled inspect", "args": {"scheduled_job_id": "${args.scheduled_job_id}"}}\``;
159
159
  }