@j0hanz/superfetch 2.4.5 → 2.4.6
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 +195 -138
- package/dist/http-native.js +2 -2
- package/dist/instructions.md +30 -38
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +270 -98
- package/dist/observability.js +2 -1
- package/dist/tasks.d.ts +24 -5
- package/dist/tasks.js +125 -8
- package/dist/tools.js +46 -4
- package/dist/transform.js +40 -14
- package/package.json +1 -1
package/dist/mcp.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readFile } from 'node:fs/promises';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { McpServer, ResourceTemplate, } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
4
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
5
|
-
import { CallToolRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
+
import { CallToolRequestSchema, ErrorCode, McpError, } from '@modelcontextprotocol/sdk/types.js';
|
|
6
6
|
import { registerCachedContentResource } from './cache.js';
|
|
7
7
|
import { config } from './config.js';
|
|
8
8
|
import { destroyAgents } from './fetch.js';
|
|
@@ -12,10 +12,10 @@ import { taskManager } from './tasks.js';
|
|
|
12
12
|
import { FETCH_URL_TOOL_NAME, fetchUrlToolHandler, registerTools, } from './tools.js';
|
|
13
13
|
import { shutdownTransformWorkerPool } from './transform.js';
|
|
14
14
|
import { isObject } from './type-guards.js';
|
|
15
|
-
function getLocalIcons() {
|
|
15
|
+
async function getLocalIcons() {
|
|
16
16
|
try {
|
|
17
17
|
const iconPath = new URL('../assets/logo.svg', import.meta.url);
|
|
18
|
-
const buffer =
|
|
18
|
+
const buffer = await readFile(iconPath);
|
|
19
19
|
return [
|
|
20
20
|
{
|
|
21
21
|
src: `data:image/svg+xml;base64,${buffer.toString('base64')}`,
|
|
@@ -28,8 +28,8 @@ function getLocalIcons() {
|
|
|
28
28
|
return undefined;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
|
-
function createServerInfo() {
|
|
32
|
-
const localIcons = getLocalIcons();
|
|
31
|
+
async function createServerInfo() {
|
|
32
|
+
const localIcons = await getLocalIcons();
|
|
33
33
|
return {
|
|
34
34
|
name: config.server.name,
|
|
35
35
|
version: config.server.version,
|
|
@@ -40,6 +40,7 @@ function createServerCapabilities() {
|
|
|
40
40
|
return {
|
|
41
41
|
tools: { listChanged: true },
|
|
42
42
|
resources: { listChanged: true, subscribe: true },
|
|
43
|
+
prompts: {},
|
|
43
44
|
logging: {},
|
|
44
45
|
tasks: {
|
|
45
46
|
list: {},
|
|
@@ -52,9 +53,9 @@ function createServerCapabilities() {
|
|
|
52
53
|
},
|
|
53
54
|
};
|
|
54
55
|
}
|
|
55
|
-
function createServerInstructions(serverVersion) {
|
|
56
|
+
async function createServerInstructions(serverVersion) {
|
|
56
57
|
try {
|
|
57
|
-
const raw =
|
|
58
|
+
const raw = await readFile(new URL('./instructions.md', import.meta.url), 'utf8');
|
|
58
59
|
return raw.replaceAll('{{SERVER_VERSION}}', serverVersion).trim();
|
|
59
60
|
}
|
|
60
61
|
catch {
|
|
@@ -77,83 +78,233 @@ function registerInstructionsResource(server, instructions) {
|
|
|
77
78
|
}));
|
|
78
79
|
}
|
|
79
80
|
// Schemas based on methods strings
|
|
80
|
-
const TaskGetSchema = z.object({
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
81
|
+
const TaskGetSchema = z.object({
|
|
82
|
+
method: z.literal('tasks/get'),
|
|
83
|
+
params: z.object({ taskId: z.string() }),
|
|
84
|
+
});
|
|
85
|
+
const TaskListSchema = z.object({
|
|
86
|
+
method: z.literal('tasks/list'),
|
|
87
|
+
params: z
|
|
88
|
+
.object({
|
|
89
|
+
cursor: z.string().optional(),
|
|
90
|
+
})
|
|
91
|
+
.optional(),
|
|
92
|
+
});
|
|
93
|
+
const TaskCancelSchema = z.object({
|
|
94
|
+
method: z.literal('tasks/cancel'),
|
|
95
|
+
params: z.object({ taskId: z.string() }),
|
|
96
|
+
});
|
|
97
|
+
const TaskResultSchema = z.object({
|
|
98
|
+
method: z.literal('tasks/result'),
|
|
99
|
+
params: z.object({ taskId: z.string() }),
|
|
100
|
+
});
|
|
101
|
+
function isNonEmptyString(value) {
|
|
102
|
+
return typeof value === 'string' && value.length > 0;
|
|
103
|
+
}
|
|
104
|
+
function isRecord(value) {
|
|
105
|
+
return isObject(value);
|
|
106
|
+
}
|
|
107
|
+
function isValidTask(task) {
|
|
108
|
+
if (task === undefined)
|
|
109
|
+
return true;
|
|
110
|
+
if (!isRecord(task))
|
|
111
|
+
return false;
|
|
112
|
+
const { ttl } = task;
|
|
113
|
+
return ttl === undefined || typeof ttl === 'number';
|
|
114
|
+
}
|
|
115
|
+
function isValidMeta(meta) {
|
|
116
|
+
if (meta === undefined)
|
|
117
|
+
return true;
|
|
118
|
+
if (!isRecord(meta))
|
|
119
|
+
return false;
|
|
120
|
+
const { progressToken } = meta;
|
|
121
|
+
if (progressToken !== undefined &&
|
|
122
|
+
typeof progressToken !== 'string' &&
|
|
123
|
+
typeof progressToken !== 'number') {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
const related = meta['io.modelcontextprotocol/related-task'];
|
|
127
|
+
if (related === undefined)
|
|
128
|
+
return true;
|
|
129
|
+
if (!isRecord(related))
|
|
130
|
+
return false;
|
|
131
|
+
const { taskId } = related;
|
|
132
|
+
return typeof taskId === 'string';
|
|
133
|
+
}
|
|
134
|
+
function isExtendedCallToolRequest(request) {
|
|
135
|
+
if (!isRecord(request))
|
|
136
|
+
return false;
|
|
137
|
+
const { method, params } = request;
|
|
138
|
+
if (method !== 'tools/call')
|
|
139
|
+
return false;
|
|
140
|
+
if (!isRecord(params))
|
|
141
|
+
return false;
|
|
142
|
+
const { name, arguments: args, task, _meta, } = params;
|
|
143
|
+
return (isNonEmptyString(name) &&
|
|
144
|
+
(args === undefined || isRecord(args)) &&
|
|
145
|
+
isValidTask(task) &&
|
|
146
|
+
isValidMeta(_meta));
|
|
147
|
+
}
|
|
148
|
+
function resolveTaskOwnerKey(extra) {
|
|
149
|
+
if (extra?.sessionId)
|
|
150
|
+
return `session:${extra.sessionId}`;
|
|
151
|
+
if (extra?.authInfo?.clientId)
|
|
152
|
+
return `client:${extra.authInfo.clientId}`;
|
|
153
|
+
if (extra?.authInfo?.token)
|
|
154
|
+
return `token:${extra.authInfo.token}`;
|
|
155
|
+
return 'default';
|
|
156
|
+
}
|
|
157
|
+
function resolveToolCallContext(extra) {
|
|
158
|
+
const context = {
|
|
159
|
+
ownerKey: resolveTaskOwnerKey(extra),
|
|
160
|
+
};
|
|
161
|
+
if (extra?.signal)
|
|
162
|
+
context.signal = extra.signal;
|
|
163
|
+
if (extra?.requestId !== undefined)
|
|
164
|
+
context.requestId = extra.requestId;
|
|
165
|
+
if (extra?.sendNotification)
|
|
166
|
+
context.sendNotification = extra.sendNotification;
|
|
167
|
+
return context;
|
|
168
|
+
}
|
|
169
|
+
function requireFetchUrlArgs(args) {
|
|
170
|
+
if (!isObject(args) || typeof args.url !== 'string') {
|
|
171
|
+
throw new McpError(ErrorCode.InvalidParams, 'Invalid arguments for fetch-url');
|
|
172
|
+
}
|
|
173
|
+
return { url: args.url };
|
|
174
|
+
}
|
|
175
|
+
function throwTaskNotFound() {
|
|
176
|
+
throw new McpError(ErrorCode.InvalidParams, 'Failed to retrieve task: Task not found');
|
|
177
|
+
}
|
|
178
|
+
function requireFetchUrlToolName(name) {
|
|
179
|
+
if (name === FETCH_URL_TOOL_NAME)
|
|
180
|
+
return;
|
|
181
|
+
throw new McpError(ErrorCode.MethodNotFound, `Tool '${name}' does not support task execution`);
|
|
182
|
+
}
|
|
183
|
+
function buildRelatedTaskMeta(taskId, meta) {
|
|
184
|
+
return {
|
|
185
|
+
...(meta ?? {}),
|
|
186
|
+
'io.modelcontextprotocol/related-task': { taskId },
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function buildCreateTaskResult(task) {
|
|
190
|
+
return {
|
|
191
|
+
task,
|
|
192
|
+
_meta: {
|
|
193
|
+
'io.modelcontextprotocol/related-task': {
|
|
194
|
+
taskId: task.taskId,
|
|
195
|
+
status: task.status,
|
|
196
|
+
...(task.statusMessage ? { statusMessage: task.statusMessage } : {}),
|
|
197
|
+
createdAt: task.createdAt,
|
|
198
|
+
lastUpdatedAt: task.lastUpdatedAt,
|
|
199
|
+
ttl: task.ttl,
|
|
200
|
+
pollInterval: task.pollInterval,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
async function runFetchTaskExecution(params) {
|
|
206
|
+
const { taskId, args, meta, sendNotification } = params;
|
|
207
|
+
try {
|
|
208
|
+
const controller = new AbortController();
|
|
209
|
+
const relatedMeta = buildRelatedTaskMeta(taskId, meta);
|
|
210
|
+
const result = await fetchUrlToolHandler(args, {
|
|
211
|
+
signal: controller.signal,
|
|
212
|
+
requestId: taskId, // Correlation
|
|
213
|
+
_meta: relatedMeta,
|
|
214
|
+
...(sendNotification ? { sendNotification } : {}),
|
|
215
|
+
});
|
|
216
|
+
const isToolError = typeof result.isError === 'boolean'
|
|
217
|
+
? result.isError
|
|
218
|
+
: false;
|
|
219
|
+
taskManager.updateTask(taskId, {
|
|
220
|
+
status: isToolError ? 'failed' : 'completed',
|
|
221
|
+
...(isToolError
|
|
222
|
+
? {
|
|
223
|
+
statusMessage: result
|
|
224
|
+
.structuredContent?.error ?? 'Tool execution failed',
|
|
124
225
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
return response;
|
|
139
|
-
}
|
|
140
|
-
if (extendedParams.name === FETCH_URL_TOOL_NAME) {
|
|
141
|
-
const args = extendedParams.arguments;
|
|
142
|
-
if (!isObject(args) ||
|
|
143
|
-
typeof args.url !== 'string') {
|
|
144
|
-
throw new Error('Invalid arguments for fetch-url');
|
|
226
|
+
: {}),
|
|
227
|
+
result,
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
232
|
+
const errorPayload = error instanceof McpError
|
|
233
|
+
? {
|
|
234
|
+
code: error.code,
|
|
235
|
+
message: errorMessage,
|
|
236
|
+
data: error.data,
|
|
145
237
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
238
|
+
: {
|
|
239
|
+
code: ErrorCode.InternalError,
|
|
240
|
+
message: errorMessage,
|
|
241
|
+
};
|
|
242
|
+
taskManager.updateTask(taskId, {
|
|
243
|
+
status: 'failed',
|
|
244
|
+
statusMessage: errorMessage,
|
|
245
|
+
error: errorPayload,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function handleTaskToolCall(params, context) {
|
|
250
|
+
requireFetchUrlToolName(params.name);
|
|
251
|
+
const validArgs = requireFetchUrlArgs(params.arguments);
|
|
252
|
+
const task = taskManager.createTask(params.task?.ttl !== undefined ? { ttl: params.task.ttl } : undefined, 'Task started', context.ownerKey);
|
|
253
|
+
const executionParams = {
|
|
254
|
+
taskId: task.taskId,
|
|
255
|
+
args: validArgs,
|
|
256
|
+
...(params._meta ? { meta: params._meta } : {}),
|
|
257
|
+
...(context.sendNotification
|
|
258
|
+
? { sendNotification: context.sendNotification }
|
|
259
|
+
: {}),
|
|
260
|
+
};
|
|
261
|
+
void runFetchTaskExecution(executionParams);
|
|
262
|
+
return buildCreateTaskResult({
|
|
263
|
+
taskId: task.taskId,
|
|
264
|
+
status: task.status,
|
|
265
|
+
...(task.statusMessage ? { statusMessage: task.statusMessage } : {}),
|
|
266
|
+
createdAt: task.createdAt,
|
|
267
|
+
lastUpdatedAt: task.lastUpdatedAt,
|
|
268
|
+
ttl: task.ttl,
|
|
269
|
+
pollInterval: task.pollInterval,
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
async function handleDirectToolCall(params, context) {
|
|
273
|
+
const args = requireFetchUrlArgs(params.arguments);
|
|
274
|
+
return fetchUrlToolHandler({ url: args.url }, {
|
|
275
|
+
...(context.signal ? { signal: context.signal } : {}),
|
|
276
|
+
...(context.requestId ? { requestId: context.requestId } : {}),
|
|
277
|
+
...(context.sendNotification
|
|
278
|
+
? { sendNotification: context.sendNotification }
|
|
279
|
+
: {}),
|
|
280
|
+
...(params._meta ? { _meta: params._meta } : {}),
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
async function handleToolCallRequest(request, context) {
|
|
284
|
+
const { params } = request;
|
|
285
|
+
if (params.task) {
|
|
286
|
+
return handleTaskToolCall(params, context);
|
|
287
|
+
}
|
|
288
|
+
if (params.name === FETCH_URL_TOOL_NAME) {
|
|
289
|
+
return handleDirectToolCall(params, context);
|
|
290
|
+
}
|
|
291
|
+
throw new McpError(ErrorCode.MethodNotFound, `Unknown tool: ${params.name}`);
|
|
292
|
+
}
|
|
293
|
+
function registerTaskHandlers(server) {
|
|
294
|
+
server.server.setRequestHandler(CallToolRequestSchema, async (request, extra) => {
|
|
295
|
+
const context = resolveToolCallContext(extra);
|
|
296
|
+
if (!isExtendedCallToolRequest(request)) {
|
|
297
|
+
throw new McpError(ErrorCode.InvalidParams, 'Invalid tool request');
|
|
149
298
|
}
|
|
150
|
-
|
|
299
|
+
const result = await handleToolCallRequest(request, context);
|
|
300
|
+
return result;
|
|
151
301
|
});
|
|
152
|
-
server.server.setRequestHandler(TaskGetSchema, async (request) => {
|
|
302
|
+
server.server.setRequestHandler(TaskGetSchema, async (request, extra) => {
|
|
153
303
|
const { taskId } = request.params;
|
|
154
|
-
const
|
|
304
|
+
const ownerKey = resolveTaskOwnerKey(extra);
|
|
305
|
+
const task = taskManager.getTask(taskId, ownerKey);
|
|
155
306
|
if (!task) {
|
|
156
|
-
|
|
307
|
+
throwTaskNotFound();
|
|
157
308
|
}
|
|
158
309
|
return Promise.resolve({
|
|
159
310
|
taskId: task.taskId,
|
|
@@ -165,20 +316,37 @@ function registerTaskHandlers(server) {
|
|
|
165
316
|
pollInterval: task.pollInterval,
|
|
166
317
|
});
|
|
167
318
|
});
|
|
168
|
-
server.server.setRequestHandler(TaskResultSchema, async (request) => {
|
|
319
|
+
server.server.setRequestHandler(TaskResultSchema, async (request, extra) => {
|
|
169
320
|
const { taskId } = request.params;
|
|
170
|
-
const
|
|
321
|
+
const ownerKey = resolveTaskOwnerKey(extra);
|
|
322
|
+
const task = await taskManager.waitForTerminalTask(taskId, ownerKey, extra?.signal);
|
|
171
323
|
if (!task) {
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
if (task.status === 'working' || task.status === 'input_required') {
|
|
175
|
-
throw new Error('Task execution in progress');
|
|
324
|
+
throwTaskNotFound();
|
|
176
325
|
}
|
|
177
326
|
if (task.status === 'failed') {
|
|
178
|
-
|
|
327
|
+
if (task.error) {
|
|
328
|
+
throw new McpError(task.error.code, task.error.message, task.error.data);
|
|
329
|
+
}
|
|
330
|
+
const failedResult = (task.result ?? null);
|
|
331
|
+
const fallback = failedResult ?? {
|
|
332
|
+
content: [
|
|
333
|
+
{
|
|
334
|
+
type: 'text',
|
|
335
|
+
text: task.statusMessage ?? 'Task execution failed',
|
|
336
|
+
},
|
|
337
|
+
],
|
|
338
|
+
isError: true,
|
|
339
|
+
};
|
|
340
|
+
return Promise.resolve({
|
|
341
|
+
...fallback,
|
|
342
|
+
_meta: {
|
|
343
|
+
...fallback._meta,
|
|
344
|
+
'io.modelcontextprotocol/related-task': { taskId: task.taskId },
|
|
345
|
+
},
|
|
346
|
+
});
|
|
179
347
|
}
|
|
180
348
|
if (task.status === 'cancelled') {
|
|
181
|
-
throw new
|
|
349
|
+
throw new McpError(ErrorCode.InvalidRequest, 'Task was cancelled');
|
|
182
350
|
}
|
|
183
351
|
const result = (task.result ?? { content: [] });
|
|
184
352
|
return Promise.resolve({
|
|
@@ -189,8 +357,10 @@ function registerTaskHandlers(server) {
|
|
|
189
357
|
},
|
|
190
358
|
});
|
|
191
359
|
});
|
|
192
|
-
server.server.setRequestHandler(TaskListSchema, async () => {
|
|
193
|
-
const
|
|
360
|
+
server.server.setRequestHandler(TaskListSchema, async (request, extra) => {
|
|
361
|
+
const ownerKey = resolveTaskOwnerKey(extra);
|
|
362
|
+
const cursor = request.params?.cursor;
|
|
363
|
+
const { tasks, nextCursor } = taskManager.listTasks(cursor === undefined ? { ownerKey } : { ownerKey, cursor });
|
|
194
364
|
return Promise.resolve({
|
|
195
365
|
tasks: tasks.map((t) => ({
|
|
196
366
|
taskId: t.taskId,
|
|
@@ -200,14 +370,15 @@ function registerTaskHandlers(server) {
|
|
|
200
370
|
ttl: t.ttl,
|
|
201
371
|
pollInterval: t.pollInterval,
|
|
202
372
|
})),
|
|
203
|
-
nextCursor
|
|
373
|
+
nextCursor,
|
|
204
374
|
});
|
|
205
375
|
});
|
|
206
|
-
server.server.setRequestHandler(TaskCancelSchema, async (request) => {
|
|
376
|
+
server.server.setRequestHandler(TaskCancelSchema, async (request, extra) => {
|
|
207
377
|
const { taskId } = request.params;
|
|
208
|
-
const
|
|
378
|
+
const ownerKey = resolveTaskOwnerKey(extra);
|
|
379
|
+
const task = taskManager.cancelTask(taskId, ownerKey);
|
|
209
380
|
if (!task) {
|
|
210
|
-
|
|
381
|
+
throwTaskNotFound();
|
|
211
382
|
}
|
|
212
383
|
return Promise.resolve({
|
|
213
384
|
taskId: task.taskId,
|
|
@@ -240,14 +411,15 @@ function registerPrompts(server) {
|
|
|
240
411
|
}));
|
|
241
412
|
}
|
|
242
413
|
}
|
|
243
|
-
export function createMcpServer() {
|
|
244
|
-
const instructions = createServerInstructions(config.server.version);
|
|
245
|
-
const
|
|
414
|
+
export async function createMcpServer() {
|
|
415
|
+
const instructions = await createServerInstructions(config.server.version);
|
|
416
|
+
const serverInfo = await createServerInfo();
|
|
417
|
+
const server = new McpServer(serverInfo, {
|
|
246
418
|
capabilities: createServerCapabilities(),
|
|
247
419
|
instructions,
|
|
248
420
|
});
|
|
249
421
|
setMcpServer(server);
|
|
250
|
-
const localIcons = getLocalIcons();
|
|
422
|
+
const localIcons = await getLocalIcons();
|
|
251
423
|
registerTools(server);
|
|
252
424
|
registerCachedContentResource(server, localIcons);
|
|
253
425
|
registerInstructionsResource(server, instructions);
|
|
@@ -311,7 +483,7 @@ async function connectStdioServer(server, transport) {
|
|
|
311
483
|
}
|
|
312
484
|
}
|
|
313
485
|
export async function startStdioServer() {
|
|
314
|
-
const server = createMcpServer();
|
|
486
|
+
const server = await createMcpServer();
|
|
315
487
|
const transport = new StdioServerTransport();
|
|
316
488
|
attachServerErrorHandler(server);
|
|
317
489
|
registerSignalHandlers(createShutdownHandler(server));
|
package/dist/observability.js
CHANGED
|
@@ -65,11 +65,12 @@ function writeLog(level, message, meta) {
|
|
|
65
65
|
return;
|
|
66
66
|
process.stderr.write(`${formatLogEntry(level, message, meta)}\n`);
|
|
67
67
|
if (mcpServer) {
|
|
68
|
+
const sessionId = getSessionId();
|
|
68
69
|
mcpServer.server
|
|
69
70
|
.sendLoggingMessage({
|
|
70
71
|
level: mapToMcpLevel(level),
|
|
71
72
|
data: meta ? { message, ...meta } : message,
|
|
72
|
-
})
|
|
73
|
+
}, sessionId)
|
|
73
74
|
.catch(() => { });
|
|
74
75
|
}
|
|
75
76
|
}
|
package/dist/tasks.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export type TaskStatus = 'working' | 'input_required' | 'completed' | 'failed' | 'cancelled';
|
|
2
|
+
export interface TaskError {
|
|
3
|
+
code: number;
|
|
4
|
+
message: string;
|
|
5
|
+
data?: unknown;
|
|
6
|
+
}
|
|
2
7
|
export interface TaskState {
|
|
3
8
|
taskId: string;
|
|
9
|
+
ownerKey: string;
|
|
4
10
|
status: TaskStatus;
|
|
5
11
|
statusMessage?: string;
|
|
6
12
|
createdAt: string;
|
|
@@ -8,7 +14,7 @@ export interface TaskState {
|
|
|
8
14
|
ttl: number;
|
|
9
15
|
pollInterval: number;
|
|
10
16
|
result?: unknown;
|
|
11
|
-
error?:
|
|
17
|
+
error?: TaskError;
|
|
12
18
|
}
|
|
13
19
|
export interface CreateTaskOptions {
|
|
14
20
|
ttl?: number;
|
|
@@ -27,11 +33,24 @@ export interface CreateTaskResult {
|
|
|
27
33
|
}
|
|
28
34
|
export declare class TaskManager {
|
|
29
35
|
private tasks;
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
private waiters;
|
|
37
|
+
createTask(options?: CreateTaskOptions, statusMessage?: string, ownerKey?: string): TaskState;
|
|
38
|
+
getTask(taskId: string, ownerKey?: string): TaskState | undefined;
|
|
32
39
|
updateTask(taskId: string, updates: Partial<Omit<TaskState, 'taskId' | 'createdAt'>>): void;
|
|
33
|
-
cancelTask(taskId: string): TaskState | undefined;
|
|
34
|
-
listTasks(
|
|
40
|
+
cancelTask(taskId: string, ownerKey?: string): TaskState | undefined;
|
|
41
|
+
listTasks(options: {
|
|
42
|
+
ownerKey: string;
|
|
43
|
+
cursor?: string;
|
|
44
|
+
limit?: number;
|
|
45
|
+
}): {
|
|
46
|
+
tasks: TaskState[];
|
|
47
|
+
nextCursor?: string;
|
|
48
|
+
};
|
|
35
49
|
cleanupExpiredTasks(): number;
|
|
50
|
+
waitForTerminalTask(taskId: string, ownerKey: string, signal?: AbortSignal): Promise<TaskState | undefined>;
|
|
51
|
+
private notifyWaiters;
|
|
52
|
+
private isExpired;
|
|
53
|
+
private encodeCursor;
|
|
54
|
+
private decodeCursor;
|
|
36
55
|
}
|
|
37
56
|
export declare const taskManager: TaskManager;
|