caplets 0.16.0 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +87 -0
- package/dist/index.js +2480 -824
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -6,464 +6,25 @@ import { execFileSync, spawn } from "node:child_process";
|
|
|
6
6
|
import process$1, { stdin, stdout } from "node:process";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { homedir, tmpdir } from "node:os";
|
|
9
|
-
import { PassThrough } from "node:stream";
|
|
10
|
-
import { createServer } from "node:http";
|
|
9
|
+
import { PassThrough, Readable } from "node:stream";
|
|
10
|
+
import { STATUS_CODES, createServer } from "node:http";
|
|
11
11
|
import { createHash, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
12
12
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
13
13
|
import { createInterface } from "node:readline/promises";
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
"call_tool"
|
|
26
|
-
];
|
|
27
|
-
const generatedToolInputDescriptions = {
|
|
28
|
-
operation: "Wrapper operation: get_caplet, check_backend, list_tools, search_tools, get_tool, or call_tool.",
|
|
29
|
-
query: "Required for search_tools only.",
|
|
30
|
-
limit: "Optional search_tools result limit.",
|
|
31
|
-
tool: "Exact downstream tool name for get_tool or call_tool.",
|
|
32
|
-
arguments: "Required JSON object for call_tool arguments/downstream inputs.",
|
|
33
|
-
fields: "Optional call_tool structured output paths when outputSchema allows it."
|
|
14
|
+
import { Http2ServerRequest, constants as constants$1 } from "node:http2";
|
|
15
|
+
//#region \0rolldown/runtime.js
|
|
16
|
+
var __defProp$1 = Object.defineProperty;
|
|
17
|
+
var __exportAll$1 = (all, no_symbols) => {
|
|
18
|
+
let target = {};
|
|
19
|
+
for (var name in all) __defProp$1(target, name, {
|
|
20
|
+
get: all[name],
|
|
21
|
+
enumerable: true
|
|
22
|
+
});
|
|
23
|
+
if (!no_symbols) __defProp$1(target, Symbol.toStringTag, { value: "Module" });
|
|
24
|
+
return target;
|
|
34
25
|
};
|
|
35
|
-
function generatedToolInputJsonSchema() {
|
|
36
|
-
return {
|
|
37
|
-
type: "object",
|
|
38
|
-
properties: {
|
|
39
|
-
operation: {
|
|
40
|
-
type: "string",
|
|
41
|
-
enum: operations,
|
|
42
|
-
description: generatedToolInputDescriptions.operation
|
|
43
|
-
},
|
|
44
|
-
query: {
|
|
45
|
-
type: "string",
|
|
46
|
-
description: generatedToolInputDescriptions.query
|
|
47
|
-
},
|
|
48
|
-
limit: {
|
|
49
|
-
type: "integer",
|
|
50
|
-
minimum: 1,
|
|
51
|
-
description: generatedToolInputDescriptions.limit
|
|
52
|
-
},
|
|
53
|
-
tool: {
|
|
54
|
-
type: "string",
|
|
55
|
-
description: generatedToolInputDescriptions.tool
|
|
56
|
-
},
|
|
57
|
-
arguments: {
|
|
58
|
-
type: "object",
|
|
59
|
-
description: generatedToolInputDescriptions.arguments
|
|
60
|
-
},
|
|
61
|
-
fields: {
|
|
62
|
-
type: "array",
|
|
63
|
-
items: {
|
|
64
|
-
type: "string",
|
|
65
|
-
minLength: 1
|
|
66
|
-
},
|
|
67
|
-
minItems: 1,
|
|
68
|
-
description: generatedToolInputDescriptions.fields
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
required: ["operation"],
|
|
72
|
-
additionalProperties: false
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
26
|
//#endregion
|
|
76
|
-
//#region ../core/dist/
|
|
77
|
-
var __create = Object.create;
|
|
78
|
-
var __defProp = Object.defineProperty;
|
|
79
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
80
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
81
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
82
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
83
|
-
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
84
|
-
var __copyProps = (to, from, except, desc) => {
|
|
85
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
86
|
-
key = keys[i];
|
|
87
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
88
|
-
get: ((k) => from[k]).bind(null, key),
|
|
89
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
return to;
|
|
93
|
-
};
|
|
94
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
95
|
-
value: mod,
|
|
96
|
-
enumerable: true
|
|
97
|
-
}) : target, mod));
|
|
98
|
-
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
99
|
-
const CAPLETS_ERROR_CODES = [
|
|
100
|
-
"CONFIG_NOT_FOUND",
|
|
101
|
-
"CONFIG_EXISTS",
|
|
102
|
-
"CONFIG_INVALID",
|
|
103
|
-
"REQUEST_INVALID",
|
|
104
|
-
"SERVER_NOT_FOUND",
|
|
105
|
-
"SERVER_UNAVAILABLE",
|
|
106
|
-
"SERVER_START_TIMEOUT",
|
|
107
|
-
"UNKNOWN_OPERATION",
|
|
108
|
-
"TOOL_NOT_FOUND",
|
|
109
|
-
"TOOL_CALL_TIMEOUT",
|
|
110
|
-
"AUTH_REQUIRED",
|
|
111
|
-
"AUTH_FAILED",
|
|
112
|
-
"AUTH_REFRESH_FAILED",
|
|
113
|
-
"DOWNSTREAM_PROTOCOL_ERROR",
|
|
114
|
-
"DOWNSTREAM_TOOL_ERROR",
|
|
115
|
-
"UNSUPPORTED_TRANSPORT",
|
|
116
|
-
"INTERNAL_ERROR"
|
|
117
|
-
];
|
|
118
|
-
var CapletsError = class extends Error {
|
|
119
|
-
code;
|
|
120
|
-
details;
|
|
121
|
-
constructor(code, message, details) {
|
|
122
|
-
super(message);
|
|
123
|
-
this.name = "CapletsError";
|
|
124
|
-
this.code = code;
|
|
125
|
-
this.details = details;
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
const SECRET_KEY_PATTERN = /(token|secret|authorization|auth|api[-_]?key|password|credential|clientsecret|client_secret|code|refresh)/i;
|
|
129
|
-
const SECRET_VALUE_PATTERN = /(bearer\s+)[a-z0-9._~+/=-]+|([?&](?:access_token|refresh_token|token|code)=)[^&\s]+/gi;
|
|
130
|
-
function redactSecrets(value) {
|
|
131
|
-
if (typeof value === "string") return value.replace(SECRET_VALUE_PATTERN, "$1$2[REDACTED]");
|
|
132
|
-
if (Array.isArray(value)) return value.map((item) => redactSecrets(item));
|
|
133
|
-
if (value && typeof value === "object") {
|
|
134
|
-
const redacted = {};
|
|
135
|
-
for (const [key, nested] of Object.entries(value)) redacted[key] = SECRET_KEY_PATTERN.test(key) ? "[REDACTED]" : redactSecrets(nested);
|
|
136
|
-
return redacted;
|
|
137
|
-
}
|
|
138
|
-
return value;
|
|
139
|
-
}
|
|
140
|
-
function toSafeError(error, fallback = "INTERNAL_ERROR") {
|
|
141
|
-
if (error instanceof CapletsError) return {
|
|
142
|
-
code: error.code,
|
|
143
|
-
message: String(redactSecrets(error.message)),
|
|
144
|
-
...error.details === void 0 ? {} : { details: redactSecrets(error.details) }
|
|
145
|
-
};
|
|
146
|
-
if (error instanceof Error) return {
|
|
147
|
-
code: fallback,
|
|
148
|
-
message: String(redactSecrets(error.message))
|
|
149
|
-
};
|
|
150
|
-
return {
|
|
151
|
-
code: fallback,
|
|
152
|
-
message: String(redactSecrets(error))
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
function errorResult(error, fallback) {
|
|
156
|
-
const safe = toSafeError(error, fallback);
|
|
157
|
-
return {
|
|
158
|
-
isError: true,
|
|
159
|
-
content: [{
|
|
160
|
-
type: "text",
|
|
161
|
-
text: `${safe.code}: ${safe.message}`
|
|
162
|
-
}],
|
|
163
|
-
structuredContent: { error: safe }
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
function textContent(text) {
|
|
167
|
-
return text ? [{
|
|
168
|
-
type: "text",
|
|
169
|
-
text
|
|
170
|
-
}] : [];
|
|
171
|
-
}
|
|
172
|
-
function compactJsonText(value, maxLength = 600) {
|
|
173
|
-
return compactText(JSON.stringify(value) ?? String(value), maxLength);
|
|
174
|
-
}
|
|
175
|
-
function compactText(value, maxLength = 600) {
|
|
176
|
-
const collapsed = value.replace(/\s+/gu, " ").trim();
|
|
177
|
-
return collapsed.length > maxLength ? `${collapsed.slice(0, maxLength - 1).trimEnd()}…` : collapsed;
|
|
178
|
-
}
|
|
179
|
-
function resultKeys(value) {
|
|
180
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return "scalar result";
|
|
181
|
-
const keys = Object.keys(value).filter((key) => key !== "elapsedMs");
|
|
182
|
-
return keys.length > 0 ? `structured keys: ${keys.join(", ")}` : "empty structured result";
|
|
183
|
-
}
|
|
184
|
-
function statusSummary(value) {
|
|
185
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return compactJsonText(value);
|
|
186
|
-
const record = value;
|
|
187
|
-
return [
|
|
188
|
-
typeof record.status === "number" ? `status ${record.status}` : void 0,
|
|
189
|
-
typeof record.statusText === "string" && record.statusText ? record.statusText : void 0,
|
|
190
|
-
typeof record.exitCode === "number" ? `exit ${record.exitCode}` : void 0,
|
|
191
|
-
"body" in record ? "body" : void 0,
|
|
192
|
-
"json" in record ? "json" : void 0,
|
|
193
|
-
typeof record.stdout === "string" && record.stdout ? "stdout" : void 0,
|
|
194
|
-
typeof record.stderr === "string" && record.stderr ? "stderr" : void 0
|
|
195
|
-
].filter((part) => Boolean(part)).join("; ") || resultKeys(record);
|
|
196
|
-
}
|
|
197
|
-
function compactStructuredContent(value) {
|
|
198
|
-
return textContent(statusSummary(value));
|
|
199
|
-
}
|
|
200
|
-
function searchToolList(tools, query, limit, compact) {
|
|
201
|
-
const tokens = query.toLocaleLowerCase().split(/\s+/).filter(Boolean);
|
|
202
|
-
return tools.filter((tool) => {
|
|
203
|
-
const haystack = `${tool.name}\n${tool.description ?? ""}`.toLocaleLowerCase();
|
|
204
|
-
return tokens.some((token) => haystack.includes(token));
|
|
205
|
-
}).sort((left, right) => left.name.localeCompare(right.name)).slice(0, limit).map(compact);
|
|
206
|
-
}
|
|
207
|
-
const DEFAULT_INPUT_SCHEMA$1 = {
|
|
208
|
-
type: "object",
|
|
209
|
-
additionalProperties: true
|
|
210
|
-
};
|
|
211
|
-
var CliToolsManager = class {
|
|
212
|
-
registry;
|
|
213
|
-
constructor(registry) {
|
|
214
|
-
this.registry = registry;
|
|
215
|
-
}
|
|
216
|
-
updateRegistry(registry) {
|
|
217
|
-
this.registry = registry;
|
|
218
|
-
}
|
|
219
|
-
invalidate(_serverId) {}
|
|
220
|
-
async checkTools(config) {
|
|
221
|
-
const startedAt = Date.now();
|
|
222
|
-
try {
|
|
223
|
-
for (const action of actionsFor(config)) {
|
|
224
|
-
const cwdTemplate = action.cwd ?? config.cwd;
|
|
225
|
-
if (cwdTemplate && !cwdTemplate.includes("$input")) {
|
|
226
|
-
if (!existsSync(interpolateRequiredString(cwdTemplate, {}, "cwd"))) throw new CapletsError("CONFIG_INVALID", `CLI cwd does not exist for ${config.server}/${action.name}`);
|
|
227
|
-
}
|
|
228
|
-
if (!action.command.includes("$input")) resolveCommandPath(action.command);
|
|
229
|
-
}
|
|
230
|
-
this.registry.setStatus(config.server, "available");
|
|
231
|
-
return {
|
|
232
|
-
id: config.server,
|
|
233
|
-
status: "available",
|
|
234
|
-
toolCount: Object.keys(config.actions).length,
|
|
235
|
-
elapsedMs: Date.now() - startedAt
|
|
236
|
-
};
|
|
237
|
-
} catch (error) {
|
|
238
|
-
const safe = toSafeError(error, "SERVER_UNAVAILABLE");
|
|
239
|
-
this.registry.setStatus(config.server, "unavailable", safe);
|
|
240
|
-
return {
|
|
241
|
-
id: config.server,
|
|
242
|
-
status: "unavailable",
|
|
243
|
-
elapsedMs: Date.now() - startedAt,
|
|
244
|
-
error: safe
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
async listTools(config) {
|
|
249
|
-
return actionsFor(config).map((action) => this.toTool(action));
|
|
250
|
-
}
|
|
251
|
-
async getTool(config, toolName) {
|
|
252
|
-
return this.toTool(getAction(config, toolName));
|
|
253
|
-
}
|
|
254
|
-
async callTool(config, toolName, args) {
|
|
255
|
-
const action = getAction(config, toolName);
|
|
256
|
-
validateInput(action, args);
|
|
257
|
-
const execution = resolveExecution(config, action, args);
|
|
258
|
-
const startedAt = Date.now();
|
|
259
|
-
const controller = new AbortController();
|
|
260
|
-
const timeout = setTimeout(() => controller.abort(), execution.timeoutMs);
|
|
261
|
-
try {
|
|
262
|
-
const result = await spawnCommand(execution, controller.signal, () => Date.now() - startedAt);
|
|
263
|
-
const structured = parseStructuredResult(action, result, result.exitCode !== 0);
|
|
264
|
-
return {
|
|
265
|
-
content: compactStructuredContent(structured),
|
|
266
|
-
structuredContent: structured,
|
|
267
|
-
isError: result.exitCode !== 0
|
|
268
|
-
};
|
|
269
|
-
} catch (error) {
|
|
270
|
-
if (isAbortError$1(error)) throw new CapletsError("TOOL_CALL_TIMEOUT", `CLI tool timed out for ${config.server}/${toolName}`);
|
|
271
|
-
if (error instanceof CapletsError) throw error;
|
|
272
|
-
throw new CapletsError("DOWNSTREAM_TOOL_ERROR", `CLI tool failed for ${config.server}/${toolName}`, toSafeError(error));
|
|
273
|
-
} finally {
|
|
274
|
-
clearTimeout(timeout);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
compact(config, tool) {
|
|
278
|
-
return {
|
|
279
|
-
id: config.server,
|
|
280
|
-
tool: tool.name,
|
|
281
|
-
...tool.description ? { description: tool.description } : {},
|
|
282
|
-
hasInputSchema: Boolean(tool.inputSchema),
|
|
283
|
-
hasOutputSchema: Boolean(tool.outputSchema)
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
search(config, tools, query, limit) {
|
|
287
|
-
return searchToolList(tools, query, limit, (tool) => this.compact(config, tool));
|
|
288
|
-
}
|
|
289
|
-
toTool(action) {
|
|
290
|
-
return {
|
|
291
|
-
name: action.name,
|
|
292
|
-
...action.description ? { description: action.description } : {},
|
|
293
|
-
inputSchema: action.inputSchema ?? DEFAULT_INPUT_SCHEMA$1,
|
|
294
|
-
...action.outputSchema ? { outputSchema: action.outputSchema } : {},
|
|
295
|
-
...action.annotations ? { annotations: action.annotations } : {}
|
|
296
|
-
};
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
function actionsFor(config) {
|
|
300
|
-
return Object.entries(config.actions).map(([name, action]) => ({
|
|
301
|
-
name,
|
|
302
|
-
...action
|
|
303
|
-
})).sort((left, right) => left.name.localeCompare(right.name));
|
|
304
|
-
}
|
|
305
|
-
function getAction(config, toolName) {
|
|
306
|
-
const actions = actionsFor(config);
|
|
307
|
-
const action = actions.find((candidate) => candidate.name === toolName);
|
|
308
|
-
if (!action) throw new CapletsError("TOOL_NOT_FOUND", `Tool ${toolName} was not found on ${config.server}`, {
|
|
309
|
-
server: config.server,
|
|
310
|
-
tool: toolName,
|
|
311
|
-
suggestions: actions.map((candidate) => candidate.name).filter((name) => name.toLocaleLowerCase().includes(toolName.toLocaleLowerCase()[0] ?? "")).slice(0, 5)
|
|
312
|
-
});
|
|
313
|
-
return action;
|
|
314
|
-
}
|
|
315
|
-
function resolveExecution(config, action, input) {
|
|
316
|
-
const cwd = interpolateString(action.cwd ?? config.cwd, input, "cwd");
|
|
317
|
-
if (cwd && !existsSync(cwd)) throw new CapletsError("CONFIG_INVALID", `CLI cwd does not exist for ${config.server}/${action.name}`);
|
|
318
|
-
const env = {
|
|
319
|
-
...process.env,
|
|
320
|
-
...resolveEnv(config.env, input),
|
|
321
|
-
...resolveEnv(action.env, input)
|
|
322
|
-
};
|
|
323
|
-
return {
|
|
324
|
-
command: interpolateString(action.command, input, "command") ?? action.command,
|
|
325
|
-
args: (action.args ?? []).map((arg, index) => interpolateRequiredString(arg, input, `args.${index}`)),
|
|
326
|
-
...cwd ? { cwd } : {},
|
|
327
|
-
env,
|
|
328
|
-
timeoutMs: action.timeoutMs ?? config.timeoutMs,
|
|
329
|
-
maxOutputBytes: action.maxOutputBytes ?? config.maxOutputBytes
|
|
330
|
-
};
|
|
331
|
-
}
|
|
332
|
-
function resolveEnv(env, input) {
|
|
333
|
-
if (!env) return {};
|
|
334
|
-
return Object.fromEntries(Object.entries(env).map(([key, value]) => [key, interpolateRequiredString(value, input, `env.${key}`)]));
|
|
335
|
-
}
|
|
336
|
-
function interpolateString(value, input, field) {
|
|
337
|
-
return value === void 0 ? void 0 : interpolateRequiredString(value, input, field);
|
|
338
|
-
}
|
|
339
|
-
function interpolateRequiredString(value, input, field) {
|
|
340
|
-
return value.replace(/\$input(?:\.([A-Za-z0-9_.-]+))?/g, (_match, path) => {
|
|
341
|
-
if (!path) throw new CapletsError("REQUEST_INVALID", `CLI ${field} cannot interpolate $input directly`);
|
|
342
|
-
const selected = valueAtPath$1(input, path);
|
|
343
|
-
if (selected === void 0 || selected === null) throw new CapletsError("REQUEST_INVALID", `CLI ${field} references missing input ${path}`);
|
|
344
|
-
if (typeof selected !== "string" && typeof selected !== "number" && typeof selected !== "boolean") throw new CapletsError("REQUEST_INVALID", `CLI ${field} input ${path} must be a string, number, or boolean`);
|
|
345
|
-
return String(selected);
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
function valueAtPath$1(input, path) {
|
|
349
|
-
let current = input;
|
|
350
|
-
for (const segment of path.split(".")) {
|
|
351
|
-
if (!current || typeof current !== "object" || Array.isArray(current)) return;
|
|
352
|
-
current = current[segment];
|
|
353
|
-
}
|
|
354
|
-
return current;
|
|
355
|
-
}
|
|
356
|
-
function validateInput(action, input) {
|
|
357
|
-
const schema = action.inputSchema;
|
|
358
|
-
if (!schema) return;
|
|
359
|
-
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
360
|
-
for (const key of required) if (typeof key === "string" && (input[key] === void 0 || input[key] === null)) throw new CapletsError("REQUEST_INVALID", `CLI tool ${action.name} requires input ${key}`);
|
|
361
|
-
const properties = isPlainObject$7(schema.properties) ? schema.properties : {};
|
|
362
|
-
for (const [key, property] of Object.entries(properties)) {
|
|
363
|
-
if (input[key] === void 0 || !isPlainObject$7(property) || typeof property.type !== "string") continue;
|
|
364
|
-
if (!matchesJsonType(input[key], property.type)) throw new CapletsError("REQUEST_INVALID", `CLI tool ${action.name} input ${key} must be ${property.type}`);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
function matchesJsonType(value, type) {
|
|
368
|
-
switch (type) {
|
|
369
|
-
case "string": return typeof value === "string";
|
|
370
|
-
case "number":
|
|
371
|
-
case "integer": return typeof value === "number" && (type === "number" || Number.isInteger(value));
|
|
372
|
-
case "boolean": return typeof value === "boolean";
|
|
373
|
-
case "object": return isPlainObject$7(value);
|
|
374
|
-
case "array": return Array.isArray(value);
|
|
375
|
-
case "null": return value === null;
|
|
376
|
-
default: return true;
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
function spawnCommand(execution, signal, elapsedMs) {
|
|
380
|
-
return new Promise((resolve, reject) => {
|
|
381
|
-
let stdout = "";
|
|
382
|
-
let stderr = "";
|
|
383
|
-
let outputBytes = 0;
|
|
384
|
-
const child = spawn(execution.command, execution.args, {
|
|
385
|
-
cwd: execution.cwd,
|
|
386
|
-
env: execution.env,
|
|
387
|
-
shell: false,
|
|
388
|
-
signal,
|
|
389
|
-
windowsHide: true
|
|
390
|
-
});
|
|
391
|
-
child.on("error", reject);
|
|
392
|
-
const append = (stream, chunk) => {
|
|
393
|
-
outputBytes += chunk.byteLength;
|
|
394
|
-
if (outputBytes > execution.maxOutputBytes) {
|
|
395
|
-
child.kill();
|
|
396
|
-
reject(new CapletsError("DOWNSTREAM_TOOL_ERROR", "CLI tool output exceeded byte limit"));
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
if (stream === "stdout") stdout += chunk.toString("utf8");
|
|
400
|
-
else stderr += chunk.toString("utf8");
|
|
401
|
-
};
|
|
402
|
-
child.stdout?.on("data", (chunk) => append("stdout", chunk));
|
|
403
|
-
child.stderr?.on("data", (chunk) => append("stderr", chunk));
|
|
404
|
-
child.on("close", (exitCode, childSignal) => {
|
|
405
|
-
resolve({
|
|
406
|
-
exitCode,
|
|
407
|
-
signal: childSignal,
|
|
408
|
-
stdout,
|
|
409
|
-
stderr,
|
|
410
|
-
elapsedMs: elapsedMs()
|
|
411
|
-
});
|
|
412
|
-
});
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
function parseStructuredResult(action, result, tolerateInvalidJson = false) {
|
|
416
|
-
const structured = {
|
|
417
|
-
exitCode: result.exitCode,
|
|
418
|
-
stdout: result.stdout,
|
|
419
|
-
stderr: result.stderr,
|
|
420
|
-
elapsedMs: result.elapsedMs,
|
|
421
|
-
...result.signal ? { signal: result.signal } : {}
|
|
422
|
-
};
|
|
423
|
-
if (action.output?.type === "json" && result.stdout.trim()) try {
|
|
424
|
-
structured.json = JSON.parse(result.stdout);
|
|
425
|
-
} catch (error) {
|
|
426
|
-
if (tolerateInvalidJson) {
|
|
427
|
-
structured.jsonParseError = toSafeError(error);
|
|
428
|
-
return structured;
|
|
429
|
-
}
|
|
430
|
-
throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", `CLI tool ${action.name} stdout was not valid JSON`, toSafeError(error));
|
|
431
|
-
}
|
|
432
|
-
return structured;
|
|
433
|
-
}
|
|
434
|
-
function resolveCommandPath(command) {
|
|
435
|
-
if (isAbsolute(command) || /[\\/]/.test(command)) {
|
|
436
|
-
assertExecutable(command);
|
|
437
|
-
return command;
|
|
438
|
-
}
|
|
439
|
-
for (const directory of (process.env.PATH ?? "").split(delimiter)) {
|
|
440
|
-
if (!directory) continue;
|
|
441
|
-
const candidate = join(directory, command);
|
|
442
|
-
if (isExecutable(candidate)) return candidate;
|
|
443
|
-
if (process.platform === "win32") for (const ext of (process.env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";")) {
|
|
444
|
-
const windowsCandidate = join(directory, `${command}${ext.toLowerCase()}`);
|
|
445
|
-
if (isExecutable(windowsCandidate)) return windowsCandidate;
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
throw new CapletsError("SERVER_UNAVAILABLE", `CLI command ${command} was not found on PATH`);
|
|
449
|
-
}
|
|
450
|
-
function assertExecutable(path) {
|
|
451
|
-
if (!isExecutable(path)) throw new CapletsError("SERVER_UNAVAILABLE", `CLI command ${path} is not executable`);
|
|
452
|
-
}
|
|
453
|
-
function isExecutable(path) {
|
|
454
|
-
try {
|
|
455
|
-
accessSync(path, constants.X_OK);
|
|
456
|
-
return true;
|
|
457
|
-
} catch {
|
|
458
|
-
return false;
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
function isAbortError$1(error) {
|
|
462
|
-
return error instanceof Error && error.name === "AbortError";
|
|
463
|
-
}
|
|
464
|
-
function isPlainObject$7(value) {
|
|
465
|
-
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
466
|
-
}
|
|
27
|
+
//#region ../core/dist/generated-tool-input-schema-BYoyY-l-.js
|
|
467
28
|
var _a$1;
|
|
468
29
|
/** A special constant with type `never` */
|
|
469
30
|
const NEVER = /* @__PURE__ */ Object.freeze({ status: "aborted" });
|
|
@@ -607,7 +168,7 @@ const allowsEval = /* @__PURE__ */ cached(() => {
|
|
|
607
168
|
return false;
|
|
608
169
|
}
|
|
609
170
|
});
|
|
610
|
-
function isPlainObject$
|
|
171
|
+
function isPlainObject$8(o) {
|
|
611
172
|
if (isObject(o) === false) return false;
|
|
612
173
|
const ctor = o.constructor;
|
|
613
174
|
if (ctor === void 0) return true;
|
|
@@ -618,7 +179,7 @@ function isPlainObject$6(o) {
|
|
|
618
179
|
return true;
|
|
619
180
|
}
|
|
620
181
|
function shallowClone(o) {
|
|
621
|
-
if (isPlainObject$
|
|
182
|
+
if (isPlainObject$8(o)) return { ...o };
|
|
622
183
|
if (Array.isArray(o)) return [...o];
|
|
623
184
|
if (o instanceof Map) return new Map(o);
|
|
624
185
|
if (o instanceof Set) return new Set(o);
|
|
@@ -701,7 +262,7 @@ function omit(schema, mask) {
|
|
|
701
262
|
}));
|
|
702
263
|
}
|
|
703
264
|
function extend(schema, shape) {
|
|
704
|
-
if (!isPlainObject$
|
|
265
|
+
if (!isPlainObject$8(shape)) throw new Error("Invalid input to extend: expected a plain object");
|
|
705
266
|
const checks = schema._zod.def.checks;
|
|
706
267
|
if (checks && checks.length > 0) {
|
|
707
268
|
const existingShape = schema._zod.def.shape;
|
|
@@ -717,7 +278,7 @@ function extend(schema, shape) {
|
|
|
717
278
|
} }));
|
|
718
279
|
}
|
|
719
280
|
function safeExtend(schema, shape) {
|
|
720
|
-
if (!isPlainObject$
|
|
281
|
+
if (!isPlainObject$8(shape)) throw new Error("Invalid input to safeExtend: expected a plain object");
|
|
721
282
|
return clone(schema, mergeDefs(schema._zod.def, { get shape() {
|
|
722
283
|
const _shape = {
|
|
723
284
|
...schema._zod.def.shape,
|
|
@@ -908,7 +469,7 @@ const _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
|
908
469
|
}
|
|
909
470
|
return result.value;
|
|
910
471
|
};
|
|
911
|
-
const parse$
|
|
472
|
+
const parse$1 = /* @__PURE__ */ _parse($ZodRealError);
|
|
912
473
|
const _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
913
474
|
const ctx = _ctx ? {
|
|
914
475
|
..._ctx,
|
|
@@ -945,7 +506,7 @@ const _safeParse = (_Err) => (schema, value, _ctx) => {
|
|
|
945
506
|
data: result.value
|
|
946
507
|
};
|
|
947
508
|
};
|
|
948
|
-
const safeParse$
|
|
509
|
+
const safeParse$1 = /* @__PURE__ */ _safeParse($ZodRealError);
|
|
949
510
|
const _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
950
511
|
const ctx = _ctx ? {
|
|
951
512
|
..._ctx,
|
|
@@ -964,7 +525,7 @@ const _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
|
964
525
|
data: result.value
|
|
965
526
|
};
|
|
966
527
|
};
|
|
967
|
-
const safeParseAsync$
|
|
528
|
+
const safeParseAsync$1 = /* @__PURE__ */ _safeParseAsync($ZodRealError);
|
|
968
529
|
const _encode = (_Err) => (schema, value, _ctx) => {
|
|
969
530
|
const ctx = _ctx ? {
|
|
970
531
|
..._ctx,
|
|
@@ -1063,7 +624,7 @@ const string$1 = (params) => {
|
|
|
1063
624
|
return new RegExp(`^${regex}$`);
|
|
1064
625
|
};
|
|
1065
626
|
const integer = /^-?\d+$/;
|
|
1066
|
-
const number$
|
|
627
|
+
const number$1 = /^-?\d+(?:\.\d+)?$/;
|
|
1067
628
|
const boolean$1 = /^(?:true|false)$/i;
|
|
1068
629
|
const _null$2 = /^null$/i;
|
|
1069
630
|
const lowercase = /^[^A-Z]*$/;
|
|
@@ -1537,10 +1098,10 @@ const $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
|
1537
1098
|
defineLazy(inst, "~standard", () => ({
|
|
1538
1099
|
validate: (value) => {
|
|
1539
1100
|
try {
|
|
1540
|
-
const r = safeParse$
|
|
1101
|
+
const r = safeParse$1(inst, value);
|
|
1541
1102
|
return r.success ? { value: r.data } : { issues: r.error?.issues };
|
|
1542
1103
|
} catch (_) {
|
|
1543
|
-
return safeParseAsync$
|
|
1104
|
+
return safeParseAsync$1(inst, value).then((r) => r.success ? { value: r.data } : { issues: r.error?.issues });
|
|
1544
1105
|
}
|
|
1545
1106
|
},
|
|
1546
1107
|
vendor: "zod",
|
|
@@ -1830,7 +1391,7 @@ const $ZodJWT = /* @__PURE__ */ $constructor("$ZodJWT", (inst, def) => {
|
|
|
1830
1391
|
});
|
|
1831
1392
|
const $ZodNumber = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
|
|
1832
1393
|
$ZodType.init(inst, def);
|
|
1833
|
-
inst._zod.pattern = inst._zod.bag.pattern ?? number$
|
|
1394
|
+
inst._zod.pattern = inst._zod.bag.pattern ?? number$1;
|
|
1834
1395
|
inst._zod.parse = (payload, _ctx) => {
|
|
1835
1396
|
if (def.coerce) try {
|
|
1836
1397
|
payload.value = Number(payload.value);
|
|
@@ -2317,7 +1878,7 @@ function mergeValues$1(a, b) {
|
|
|
2317
1878
|
valid: true,
|
|
2318
1879
|
data: a
|
|
2319
1880
|
};
|
|
2320
|
-
if (isPlainObject$
|
|
1881
|
+
if (isPlainObject$8(a) && isPlainObject$8(b)) {
|
|
2321
1882
|
const bKeys = Object.keys(b);
|
|
2322
1883
|
const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);
|
|
2323
1884
|
const newObj = {
|
|
@@ -2393,7 +1954,7 @@ const $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
2393
1954
|
$ZodType.init(inst, def);
|
|
2394
1955
|
inst._zod.parse = (payload, ctx) => {
|
|
2395
1956
|
const input = payload.value;
|
|
2396
|
-
if (!isPlainObject$
|
|
1957
|
+
if (!isPlainObject$8(input)) {
|
|
2397
1958
|
payload.issues.push({
|
|
2398
1959
|
expected: "record",
|
|
2399
1960
|
code: "invalid_type",
|
|
@@ -2460,7 +2021,7 @@ const $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
|
2460
2021
|
issues: []
|
|
2461
2022
|
}, ctx);
|
|
2462
2023
|
if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
2463
|
-
if (typeof key === "string" && number$
|
|
2024
|
+
if (typeof key === "string" && number$1.test(key) && keyResult.issues.length) {
|
|
2464
2025
|
const retryResult = def.keyType._zod.run({
|
|
2465
2026
|
value: Number(key),
|
|
2466
2027
|
issues: []
|
|
@@ -4135,8 +3696,8 @@ const initializer = (inst, issues) => {
|
|
|
4135
3696
|
const ZodRealError = /* @__PURE__ */ $constructor("ZodError", initializer, { Parent: Error });
|
|
4136
3697
|
const parse$2 = /* @__PURE__ */ _parse(ZodRealError);
|
|
4137
3698
|
const parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);
|
|
4138
|
-
const safeParse$
|
|
4139
|
-
const safeParseAsync$
|
|
3699
|
+
const safeParse$2 = /* @__PURE__ */ _safeParse(ZodRealError);
|
|
3700
|
+
const safeParseAsync$2 = /* @__PURE__ */ _safeParseAsync(ZodRealError);
|
|
4140
3701
|
const encode = /* @__PURE__ */ _encode(ZodRealError);
|
|
4141
3702
|
const decode = /* @__PURE__ */ _decode(ZodRealError);
|
|
4142
3703
|
const encodeAsync = /* @__PURE__ */ _encodeAsync(ZodRealError);
|
|
@@ -4192,9 +3753,9 @@ const ZodType$1 = /* @__PURE__ */ $constructor("ZodType", (inst, def) => {
|
|
|
4192
3753
|
inst.type = def.type;
|
|
4193
3754
|
Object.defineProperty(inst, "_def", { value: def });
|
|
4194
3755
|
inst.parse = (data, params) => parse$2(inst, data, params, { callee: inst.parse });
|
|
4195
|
-
inst.safeParse = (data, params) => safeParse$
|
|
3756
|
+
inst.safeParse = (data, params) => safeParse$2(inst, data, params);
|
|
4196
3757
|
inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
|
|
4197
|
-
inst.safeParseAsync = async (data, params) => safeParseAsync$
|
|
3758
|
+
inst.safeParseAsync = async (data, params) => safeParseAsync$2(inst, data, params);
|
|
4198
3759
|
inst.spa = inst.safeParseAsync;
|
|
4199
3760
|
inst.encode = (data, params) => encode(inst, data, params);
|
|
4200
3761
|
inst.decode = (data, params) => decode(inst, data, params);
|
|
@@ -4543,7 +4104,7 @@ const ZodNumber$1 = /* @__PURE__ */ $constructor("ZodNumber", (inst, def) => {
|
|
|
4543
4104
|
inst.isFinite = true;
|
|
4544
4105
|
inst.format = bag.format ?? null;
|
|
4545
4106
|
});
|
|
4546
|
-
function number$
|
|
4107
|
+
function number$2(params) {
|
|
4547
4108
|
return /* @__PURE__ */ _number(ZodNumber$1, params);
|
|
4548
4109
|
}
|
|
4549
4110
|
const ZodNumberFormat = /* @__PURE__ */ $constructor("ZodNumberFormat", (inst, def) => {
|
|
@@ -4989,6 +4550,571 @@ function preprocess(fn, schema) {
|
|
|
4989
4550
|
out: schema
|
|
4990
4551
|
});
|
|
4991
4552
|
}
|
|
4553
|
+
const operations = [
|
|
4554
|
+
"get_caplet",
|
|
4555
|
+
"check_backend",
|
|
4556
|
+
"list_tools",
|
|
4557
|
+
"search_tools",
|
|
4558
|
+
"get_tool",
|
|
4559
|
+
"call_tool"
|
|
4560
|
+
];
|
|
4561
|
+
const mcpOperations = [
|
|
4562
|
+
...operations,
|
|
4563
|
+
"list_resources",
|
|
4564
|
+
"search_resources",
|
|
4565
|
+
"list_resource_templates",
|
|
4566
|
+
"read_resource",
|
|
4567
|
+
"list_prompts",
|
|
4568
|
+
"search_prompts",
|
|
4569
|
+
"get_prompt",
|
|
4570
|
+
"complete"
|
|
4571
|
+
];
|
|
4572
|
+
const generatedToolInputDescriptions = {
|
|
4573
|
+
operation: "Wrapper operation: get_caplet, check_backend, list_tools, search_tools, get_tool, call_tool. MCP Caplets also expose resources, prompts, and completions.",
|
|
4574
|
+
query: "Required for search operations only.",
|
|
4575
|
+
limit: "Optional list/search result limit.",
|
|
4576
|
+
tool: "Exact downstream tool name for get_tool or call_tool.",
|
|
4577
|
+
arguments: "JSON object for call_tool arguments/downstream inputs or get_prompt arguments.",
|
|
4578
|
+
fields: "Optional call_tool structured output paths when outputSchema allows it.",
|
|
4579
|
+
uri: "Exact downstream resource URI for read_resource.",
|
|
4580
|
+
prompt: "Exact downstream prompt name for get_prompt.",
|
|
4581
|
+
ref: "Completion target reference for complete.",
|
|
4582
|
+
argument: "Completion argument object for complete."
|
|
4583
|
+
};
|
|
4584
|
+
const completionRefSchema = union([object$1({
|
|
4585
|
+
type: literal("prompt"),
|
|
4586
|
+
name: string().min(1)
|
|
4587
|
+
}).strict(), object$1({
|
|
4588
|
+
type: literal("resourceTemplate"),
|
|
4589
|
+
uri: string().min(1)
|
|
4590
|
+
}).strict()]);
|
|
4591
|
+
const completionArgumentSchema = object$1({
|
|
4592
|
+
name: string().min(1),
|
|
4593
|
+
value: string()
|
|
4594
|
+
}).strict();
|
|
4595
|
+
const baseShape = {
|
|
4596
|
+
query: string().optional().describe(generatedToolInputDescriptions.query),
|
|
4597
|
+
limit: number$2().int().positive().optional().describe(generatedToolInputDescriptions.limit),
|
|
4598
|
+
tool: string().optional().describe(generatedToolInputDescriptions.tool),
|
|
4599
|
+
arguments: object$1({}).catchall(any()).optional().describe(generatedToolInputDescriptions.arguments),
|
|
4600
|
+
fields: array(string().min(1)).min(1).optional().describe(generatedToolInputDescriptions.fields)
|
|
4601
|
+
};
|
|
4602
|
+
function generatedToolInputSchemaForCaplet(caplet) {
|
|
4603
|
+
return object$1({
|
|
4604
|
+
operation: (caplet.backend === "mcp" ? _enum(mcpOperations) : _enum(operations)).describe(generatedToolInputDescriptions.operation),
|
|
4605
|
+
...baseShape,
|
|
4606
|
+
...caplet.backend === "mcp" ? {
|
|
4607
|
+
uri: string().optional().describe(generatedToolInputDescriptions.uri),
|
|
4608
|
+
prompt: string().optional().describe(generatedToolInputDescriptions.prompt),
|
|
4609
|
+
ref: completionRefSchema.optional().describe(generatedToolInputDescriptions.ref),
|
|
4610
|
+
argument: completionArgumentSchema.optional().describe(generatedToolInputDescriptions.argument)
|
|
4611
|
+
} : {}
|
|
4612
|
+
}).strict();
|
|
4613
|
+
}
|
|
4614
|
+
object$1({
|
|
4615
|
+
operation: _enum(operations).describe(generatedToolInputDescriptions.operation),
|
|
4616
|
+
...baseShape
|
|
4617
|
+
}).strict();
|
|
4618
|
+
function generatedToolInputJsonSchemaForCaplet(caplet) {
|
|
4619
|
+
const mcp = caplet.backend === "mcp";
|
|
4620
|
+
return {
|
|
4621
|
+
type: "object",
|
|
4622
|
+
properties: {
|
|
4623
|
+
operation: {
|
|
4624
|
+
type: "string",
|
|
4625
|
+
enum: mcp ? mcpOperations : operations,
|
|
4626
|
+
description: generatedToolInputDescriptions.operation
|
|
4627
|
+
},
|
|
4628
|
+
query: {
|
|
4629
|
+
type: "string",
|
|
4630
|
+
description: generatedToolInputDescriptions.query
|
|
4631
|
+
},
|
|
4632
|
+
limit: {
|
|
4633
|
+
type: "integer",
|
|
4634
|
+
minimum: 1,
|
|
4635
|
+
description: generatedToolInputDescriptions.limit
|
|
4636
|
+
},
|
|
4637
|
+
tool: {
|
|
4638
|
+
type: "string",
|
|
4639
|
+
description: generatedToolInputDescriptions.tool
|
|
4640
|
+
},
|
|
4641
|
+
arguments: {
|
|
4642
|
+
type: "object",
|
|
4643
|
+
description: generatedToolInputDescriptions.arguments
|
|
4644
|
+
},
|
|
4645
|
+
fields: {
|
|
4646
|
+
type: "array",
|
|
4647
|
+
items: {
|
|
4648
|
+
type: "string",
|
|
4649
|
+
minLength: 1
|
|
4650
|
+
},
|
|
4651
|
+
minItems: 1,
|
|
4652
|
+
description: generatedToolInputDescriptions.fields
|
|
4653
|
+
},
|
|
4654
|
+
...mcp ? {
|
|
4655
|
+
uri: {
|
|
4656
|
+
type: "string",
|
|
4657
|
+
description: generatedToolInputDescriptions.uri
|
|
4658
|
+
},
|
|
4659
|
+
prompt: {
|
|
4660
|
+
type: "string",
|
|
4661
|
+
description: generatedToolInputDescriptions.prompt
|
|
4662
|
+
},
|
|
4663
|
+
ref: {
|
|
4664
|
+
oneOf: [{
|
|
4665
|
+
type: "object",
|
|
4666
|
+
properties: {
|
|
4667
|
+
type: { const: "prompt" },
|
|
4668
|
+
name: {
|
|
4669
|
+
type: "string",
|
|
4670
|
+
minLength: 1
|
|
4671
|
+
}
|
|
4672
|
+
},
|
|
4673
|
+
required: ["type", "name"],
|
|
4674
|
+
additionalProperties: false
|
|
4675
|
+
}, {
|
|
4676
|
+
type: "object",
|
|
4677
|
+
properties: {
|
|
4678
|
+
type: { const: "resourceTemplate" },
|
|
4679
|
+
uri: {
|
|
4680
|
+
type: "string",
|
|
4681
|
+
minLength: 1
|
|
4682
|
+
}
|
|
4683
|
+
},
|
|
4684
|
+
required: ["type", "uri"],
|
|
4685
|
+
additionalProperties: false
|
|
4686
|
+
}],
|
|
4687
|
+
description: generatedToolInputDescriptions.ref
|
|
4688
|
+
},
|
|
4689
|
+
argument: {
|
|
4690
|
+
type: "object",
|
|
4691
|
+
properties: {
|
|
4692
|
+
name: {
|
|
4693
|
+
type: "string",
|
|
4694
|
+
minLength: 1
|
|
4695
|
+
},
|
|
4696
|
+
value: { type: "string" }
|
|
4697
|
+
},
|
|
4698
|
+
required: ["name", "value"],
|
|
4699
|
+
additionalProperties: false,
|
|
4700
|
+
description: generatedToolInputDescriptions.argument
|
|
4701
|
+
}
|
|
4702
|
+
} : {}
|
|
4703
|
+
},
|
|
4704
|
+
required: ["operation"],
|
|
4705
|
+
additionalProperties: false
|
|
4706
|
+
};
|
|
4707
|
+
}
|
|
4708
|
+
function generatedToolInputJsonSchema() {
|
|
4709
|
+
return generatedToolInputJsonSchemaForCaplet({ backend: "tool" });
|
|
4710
|
+
}
|
|
4711
|
+
//#endregion
|
|
4712
|
+
//#region ../core/dist/options-BqibJVxq.js
|
|
4713
|
+
var __create = Object.create;
|
|
4714
|
+
var __defProp = Object.defineProperty;
|
|
4715
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4716
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4717
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
4718
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4719
|
+
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
|
|
4720
|
+
var __exportAll = (all, no_symbols) => {
|
|
4721
|
+
let target = {};
|
|
4722
|
+
for (var name in all) __defProp(target, name, {
|
|
4723
|
+
get: all[name],
|
|
4724
|
+
enumerable: true
|
|
4725
|
+
});
|
|
4726
|
+
if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
|
|
4727
|
+
return target;
|
|
4728
|
+
};
|
|
4729
|
+
var __copyProps = (to, from, except, desc) => {
|
|
4730
|
+
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
4731
|
+
key = keys[i];
|
|
4732
|
+
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
4733
|
+
get: ((k) => from[k]).bind(null, key),
|
|
4734
|
+
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
4735
|
+
});
|
|
4736
|
+
}
|
|
4737
|
+
return to;
|
|
4738
|
+
};
|
|
4739
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
4740
|
+
value: mod,
|
|
4741
|
+
enumerable: true
|
|
4742
|
+
}) : target, mod));
|
|
4743
|
+
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
4744
|
+
const CAPLETS_ERROR_CODES = [
|
|
4745
|
+
"CONFIG_NOT_FOUND",
|
|
4746
|
+
"CONFIG_EXISTS",
|
|
4747
|
+
"CONFIG_INVALID",
|
|
4748
|
+
"REQUEST_INVALID",
|
|
4749
|
+
"SERVER_NOT_FOUND",
|
|
4750
|
+
"SERVER_UNAVAILABLE",
|
|
4751
|
+
"SERVER_START_TIMEOUT",
|
|
4752
|
+
"UNKNOWN_OPERATION",
|
|
4753
|
+
"TOOL_NOT_FOUND",
|
|
4754
|
+
"TOOL_CALL_TIMEOUT",
|
|
4755
|
+
"AUTH_REQUIRED",
|
|
4756
|
+
"AUTH_FAILED",
|
|
4757
|
+
"AUTH_REFRESH_FAILED",
|
|
4758
|
+
"DOWNSTREAM_PROTOCOL_ERROR",
|
|
4759
|
+
"DOWNSTREAM_TOOL_ERROR",
|
|
4760
|
+
"UNSUPPORTED_OPERATION",
|
|
4761
|
+
"UNSUPPORTED_CAPABILITY",
|
|
4762
|
+
"PROMPT_NOT_FOUND",
|
|
4763
|
+
"DOWNSTREAM_RESOURCE_ERROR",
|
|
4764
|
+
"DOWNSTREAM_PROMPT_ERROR",
|
|
4765
|
+
"DOWNSTREAM_COMPLETION_ERROR",
|
|
4766
|
+
"UNSUPPORTED_TRANSPORT",
|
|
4767
|
+
"INTERNAL_ERROR"
|
|
4768
|
+
];
|
|
4769
|
+
var CapletsError = class extends Error {
|
|
4770
|
+
code;
|
|
4771
|
+
details;
|
|
4772
|
+
constructor(code, message, details) {
|
|
4773
|
+
super(message);
|
|
4774
|
+
this.name = "CapletsError";
|
|
4775
|
+
this.code = code;
|
|
4776
|
+
this.details = details;
|
|
4777
|
+
}
|
|
4778
|
+
};
|
|
4779
|
+
const SECRET_KEY_PATTERN = /(token|secret|authorization|auth|api[-_]?key|password|credential|clientsecret|client_secret|code|refresh)/i;
|
|
4780
|
+
const SECRET_VALUE_PATTERN = /(bearer\s+)[a-z0-9._~+/=-]+|([?&](?:access_token|refresh_token|token|code)=)[^&\s]+/gi;
|
|
4781
|
+
function redactSecrets(value) {
|
|
4782
|
+
if (typeof value === "string") return value.replace(SECRET_VALUE_PATTERN, "$1$2[REDACTED]");
|
|
4783
|
+
if (Array.isArray(value)) return value.map((item) => redactSecrets(item));
|
|
4784
|
+
if (value && typeof value === "object") {
|
|
4785
|
+
const redacted = {};
|
|
4786
|
+
for (const [key, nested] of Object.entries(value)) redacted[key] = SECRET_KEY_PATTERN.test(key) ? "[REDACTED]" : redactSecrets(nested);
|
|
4787
|
+
return redacted;
|
|
4788
|
+
}
|
|
4789
|
+
return value;
|
|
4790
|
+
}
|
|
4791
|
+
function toSafeError(error, fallback = "INTERNAL_ERROR") {
|
|
4792
|
+
if (error instanceof CapletsError) return {
|
|
4793
|
+
code: error.code,
|
|
4794
|
+
message: String(redactSecrets(error.message)),
|
|
4795
|
+
...error.details === void 0 ? {} : { details: redactSecrets(error.details) }
|
|
4796
|
+
};
|
|
4797
|
+
if (error instanceof Error) return {
|
|
4798
|
+
code: fallback,
|
|
4799
|
+
message: String(redactSecrets(error.message))
|
|
4800
|
+
};
|
|
4801
|
+
return {
|
|
4802
|
+
code: fallback,
|
|
4803
|
+
message: String(redactSecrets(error))
|
|
4804
|
+
};
|
|
4805
|
+
}
|
|
4806
|
+
function errorResult(error, fallback) {
|
|
4807
|
+
const safe = toSafeError(error, fallback);
|
|
4808
|
+
return {
|
|
4809
|
+
isError: true,
|
|
4810
|
+
content: [{
|
|
4811
|
+
type: "text",
|
|
4812
|
+
text: `${safe.code}: ${safe.message}`
|
|
4813
|
+
}],
|
|
4814
|
+
structuredContent: { error: safe }
|
|
4815
|
+
};
|
|
4816
|
+
}
|
|
4817
|
+
function textContent(text) {
|
|
4818
|
+
return text ? [{
|
|
4819
|
+
type: "text",
|
|
4820
|
+
text
|
|
4821
|
+
}] : [];
|
|
4822
|
+
}
|
|
4823
|
+
function compactJsonText(value, maxLength = 600) {
|
|
4824
|
+
return compactText(JSON.stringify(value) ?? String(value), maxLength);
|
|
4825
|
+
}
|
|
4826
|
+
function compactText(value, maxLength = 600) {
|
|
4827
|
+
const collapsed = value.replace(/\s+/gu, " ").trim();
|
|
4828
|
+
return collapsed.length > maxLength ? `${collapsed.slice(0, maxLength - 1).trimEnd()}…` : collapsed;
|
|
4829
|
+
}
|
|
4830
|
+
function resultKeys(value) {
|
|
4831
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return "scalar result";
|
|
4832
|
+
const keys = Object.keys(value).filter((key) => key !== "elapsedMs");
|
|
4833
|
+
return keys.length > 0 ? `structured keys: ${keys.join(", ")}` : "empty structured result";
|
|
4834
|
+
}
|
|
4835
|
+
function statusSummary(value) {
|
|
4836
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return compactJsonText(value);
|
|
4837
|
+
const record = value;
|
|
4838
|
+
return [
|
|
4839
|
+
typeof record.status === "number" ? `status ${record.status}` : void 0,
|
|
4840
|
+
typeof record.statusText === "string" && record.statusText ? record.statusText : void 0,
|
|
4841
|
+
typeof record.exitCode === "number" ? `exit ${record.exitCode}` : void 0,
|
|
4842
|
+
"body" in record ? "body" : void 0,
|
|
4843
|
+
"json" in record ? "json" : void 0,
|
|
4844
|
+
typeof record.stdout === "string" && record.stdout ? "stdout" : void 0,
|
|
4845
|
+
typeof record.stderr === "string" && record.stderr ? "stderr" : void 0
|
|
4846
|
+
].filter((part) => Boolean(part)).join("; ") || resultKeys(record);
|
|
4847
|
+
}
|
|
4848
|
+
function compactStructuredContent(value) {
|
|
4849
|
+
return textContent(statusSummary(value));
|
|
4850
|
+
}
|
|
4851
|
+
function searchToolList(tools, query, limit, compact) {
|
|
4852
|
+
const tokens = query.toLocaleLowerCase().split(/\s+/).filter(Boolean);
|
|
4853
|
+
return tools.filter((tool) => {
|
|
4854
|
+
const haystack = `${tool.name}\n${tool.description ?? ""}`.toLocaleLowerCase();
|
|
4855
|
+
return tokens.some((token) => haystack.includes(token));
|
|
4856
|
+
}).sort((left, right) => left.name.localeCompare(right.name)).slice(0, limit).map(compact);
|
|
4857
|
+
}
|
|
4858
|
+
const DEFAULT_INPUT_SCHEMA$1 = {
|
|
4859
|
+
type: "object",
|
|
4860
|
+
additionalProperties: true
|
|
4861
|
+
};
|
|
4862
|
+
var CliToolsManager = class {
|
|
4863
|
+
registry;
|
|
4864
|
+
constructor(registry) {
|
|
4865
|
+
this.registry = registry;
|
|
4866
|
+
}
|
|
4867
|
+
updateRegistry(registry) {
|
|
4868
|
+
this.registry = registry;
|
|
4869
|
+
}
|
|
4870
|
+
invalidate(_serverId) {}
|
|
4871
|
+
async checkTools(config) {
|
|
4872
|
+
const startedAt = Date.now();
|
|
4873
|
+
try {
|
|
4874
|
+
for (const action of actionsFor(config)) {
|
|
4875
|
+
const cwdTemplate = action.cwd ?? config.cwd;
|
|
4876
|
+
if (cwdTemplate && !cwdTemplate.includes("$input")) {
|
|
4877
|
+
if (!existsSync(interpolateRequiredString(cwdTemplate, {}, "cwd"))) throw new CapletsError("CONFIG_INVALID", `CLI cwd does not exist for ${config.server}/${action.name}`);
|
|
4878
|
+
}
|
|
4879
|
+
if (!action.command.includes("$input")) resolveCommandPath(action.command);
|
|
4880
|
+
}
|
|
4881
|
+
this.registry.setStatus(config.server, "available");
|
|
4882
|
+
return {
|
|
4883
|
+
id: config.server,
|
|
4884
|
+
status: "available",
|
|
4885
|
+
toolCount: Object.keys(config.actions).length,
|
|
4886
|
+
elapsedMs: Date.now() - startedAt
|
|
4887
|
+
};
|
|
4888
|
+
} catch (error) {
|
|
4889
|
+
const safe = toSafeError(error, "SERVER_UNAVAILABLE");
|
|
4890
|
+
this.registry.setStatus(config.server, "unavailable", safe);
|
|
4891
|
+
return {
|
|
4892
|
+
id: config.server,
|
|
4893
|
+
status: "unavailable",
|
|
4894
|
+
elapsedMs: Date.now() - startedAt,
|
|
4895
|
+
error: safe
|
|
4896
|
+
};
|
|
4897
|
+
}
|
|
4898
|
+
}
|
|
4899
|
+
async listTools(config) {
|
|
4900
|
+
return actionsFor(config).map((action) => this.toTool(action));
|
|
4901
|
+
}
|
|
4902
|
+
async getTool(config, toolName) {
|
|
4903
|
+
return this.toTool(getAction(config, toolName));
|
|
4904
|
+
}
|
|
4905
|
+
async callTool(config, toolName, args) {
|
|
4906
|
+
const action = getAction(config, toolName);
|
|
4907
|
+
validateInput(action, args);
|
|
4908
|
+
const execution = resolveExecution(config, action, args);
|
|
4909
|
+
const startedAt = Date.now();
|
|
4910
|
+
const controller = new AbortController();
|
|
4911
|
+
const timeout = setTimeout(() => controller.abort(), execution.timeoutMs);
|
|
4912
|
+
try {
|
|
4913
|
+
const result = await spawnCommand(execution, controller.signal, () => Date.now() - startedAt);
|
|
4914
|
+
const structured = parseStructuredResult(action, result, result.exitCode !== 0);
|
|
4915
|
+
return {
|
|
4916
|
+
content: compactStructuredContent(structured),
|
|
4917
|
+
structuredContent: structured,
|
|
4918
|
+
isError: result.exitCode !== 0
|
|
4919
|
+
};
|
|
4920
|
+
} catch (error) {
|
|
4921
|
+
if (isAbortError$1(error)) throw new CapletsError("TOOL_CALL_TIMEOUT", `CLI tool timed out for ${config.server}/${toolName}`);
|
|
4922
|
+
if (error instanceof CapletsError) throw error;
|
|
4923
|
+
throw new CapletsError("DOWNSTREAM_TOOL_ERROR", `CLI tool failed for ${config.server}/${toolName}`, toSafeError(error));
|
|
4924
|
+
} finally {
|
|
4925
|
+
clearTimeout(timeout);
|
|
4926
|
+
}
|
|
4927
|
+
}
|
|
4928
|
+
compact(config, tool) {
|
|
4929
|
+
return {
|
|
4930
|
+
id: config.server,
|
|
4931
|
+
tool: tool.name,
|
|
4932
|
+
...tool.description ? { description: tool.description } : {},
|
|
4933
|
+
hasInputSchema: Boolean(tool.inputSchema),
|
|
4934
|
+
hasOutputSchema: Boolean(tool.outputSchema)
|
|
4935
|
+
};
|
|
4936
|
+
}
|
|
4937
|
+
search(config, tools, query, limit) {
|
|
4938
|
+
return searchToolList(tools, query, limit, (tool) => this.compact(config, tool));
|
|
4939
|
+
}
|
|
4940
|
+
toTool(action) {
|
|
4941
|
+
return {
|
|
4942
|
+
name: action.name,
|
|
4943
|
+
...action.description ? { description: action.description } : {},
|
|
4944
|
+
inputSchema: action.inputSchema ?? DEFAULT_INPUT_SCHEMA$1,
|
|
4945
|
+
...action.outputSchema ? { outputSchema: action.outputSchema } : {},
|
|
4946
|
+
...action.annotations ? { annotations: action.annotations } : {}
|
|
4947
|
+
};
|
|
4948
|
+
}
|
|
4949
|
+
};
|
|
4950
|
+
function actionsFor(config) {
|
|
4951
|
+
return Object.entries(config.actions).map(([name, action]) => ({
|
|
4952
|
+
name,
|
|
4953
|
+
...action
|
|
4954
|
+
})).sort((left, right) => left.name.localeCompare(right.name));
|
|
4955
|
+
}
|
|
4956
|
+
function getAction(config, toolName) {
|
|
4957
|
+
const actions = actionsFor(config);
|
|
4958
|
+
const action = actions.find((candidate) => candidate.name === toolName);
|
|
4959
|
+
if (!action) throw new CapletsError("TOOL_NOT_FOUND", `Tool ${toolName} was not found on ${config.server}`, {
|
|
4960
|
+
server: config.server,
|
|
4961
|
+
tool: toolName,
|
|
4962
|
+
suggestions: actions.map((candidate) => candidate.name).filter((name) => name.toLocaleLowerCase().includes(toolName.toLocaleLowerCase()[0] ?? "")).slice(0, 5)
|
|
4963
|
+
});
|
|
4964
|
+
return action;
|
|
4965
|
+
}
|
|
4966
|
+
function resolveExecution(config, action, input) {
|
|
4967
|
+
const cwd = interpolateString(action.cwd ?? config.cwd, input, "cwd");
|
|
4968
|
+
if (cwd && !existsSync(cwd)) throw new CapletsError("CONFIG_INVALID", `CLI cwd does not exist for ${config.server}/${action.name}`);
|
|
4969
|
+
const env = {
|
|
4970
|
+
...process.env,
|
|
4971
|
+
...resolveEnv(config.env, input),
|
|
4972
|
+
...resolveEnv(action.env, input)
|
|
4973
|
+
};
|
|
4974
|
+
return {
|
|
4975
|
+
command: interpolateString(action.command, input, "command") ?? action.command,
|
|
4976
|
+
args: (action.args ?? []).map((arg, index) => interpolateRequiredString(arg, input, `args.${index}`)),
|
|
4977
|
+
...cwd ? { cwd } : {},
|
|
4978
|
+
env,
|
|
4979
|
+
timeoutMs: action.timeoutMs ?? config.timeoutMs,
|
|
4980
|
+
maxOutputBytes: action.maxOutputBytes ?? config.maxOutputBytes
|
|
4981
|
+
};
|
|
4982
|
+
}
|
|
4983
|
+
function resolveEnv(env, input) {
|
|
4984
|
+
if (!env) return {};
|
|
4985
|
+
return Object.fromEntries(Object.entries(env).map(([key, value]) => [key, interpolateRequiredString(value, input, `env.${key}`)]));
|
|
4986
|
+
}
|
|
4987
|
+
function interpolateString(value, input, field) {
|
|
4988
|
+
return value === void 0 ? void 0 : interpolateRequiredString(value, input, field);
|
|
4989
|
+
}
|
|
4990
|
+
function interpolateRequiredString(value, input, field) {
|
|
4991
|
+
return value.replace(/\$input(?:\.([A-Za-z0-9_.-]+))?/g, (_match, path) => {
|
|
4992
|
+
if (!path) throw new CapletsError("REQUEST_INVALID", `CLI ${field} cannot interpolate $input directly`);
|
|
4993
|
+
const selected = valueAtPath$1(input, path);
|
|
4994
|
+
if (selected === void 0 || selected === null) throw new CapletsError("REQUEST_INVALID", `CLI ${field} references missing input ${path}`);
|
|
4995
|
+
if (typeof selected !== "string" && typeof selected !== "number" && typeof selected !== "boolean") throw new CapletsError("REQUEST_INVALID", `CLI ${field} input ${path} must be a string, number, or boolean`);
|
|
4996
|
+
return String(selected);
|
|
4997
|
+
});
|
|
4998
|
+
}
|
|
4999
|
+
function valueAtPath$1(input, path) {
|
|
5000
|
+
let current = input;
|
|
5001
|
+
for (const segment of path.split(".")) {
|
|
5002
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) return;
|
|
5003
|
+
current = current[segment];
|
|
5004
|
+
}
|
|
5005
|
+
return current;
|
|
5006
|
+
}
|
|
5007
|
+
function validateInput(action, input) {
|
|
5008
|
+
const schema = action.inputSchema;
|
|
5009
|
+
if (!schema) return;
|
|
5010
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
5011
|
+
for (const key of required) if (typeof key === "string" && (input[key] === void 0 || input[key] === null)) throw new CapletsError("REQUEST_INVALID", `CLI tool ${action.name} requires input ${key}`);
|
|
5012
|
+
const properties = isPlainObject$6(schema.properties) ? schema.properties : {};
|
|
5013
|
+
for (const [key, property] of Object.entries(properties)) {
|
|
5014
|
+
if (input[key] === void 0 || !isPlainObject$6(property) || typeof property.type !== "string") continue;
|
|
5015
|
+
if (!matchesJsonType(input[key], property.type)) throw new CapletsError("REQUEST_INVALID", `CLI tool ${action.name} input ${key} must be ${property.type}`);
|
|
5016
|
+
}
|
|
5017
|
+
}
|
|
5018
|
+
function matchesJsonType(value, type) {
|
|
5019
|
+
switch (type) {
|
|
5020
|
+
case "string": return typeof value === "string";
|
|
5021
|
+
case "number":
|
|
5022
|
+
case "integer": return typeof value === "number" && (type === "number" || Number.isInteger(value));
|
|
5023
|
+
case "boolean": return typeof value === "boolean";
|
|
5024
|
+
case "object": return isPlainObject$6(value);
|
|
5025
|
+
case "array": return Array.isArray(value);
|
|
5026
|
+
case "null": return value === null;
|
|
5027
|
+
default: return true;
|
|
5028
|
+
}
|
|
5029
|
+
}
|
|
5030
|
+
function spawnCommand(execution, signal, elapsedMs) {
|
|
5031
|
+
return new Promise((resolve, reject) => {
|
|
5032
|
+
let stdout = "";
|
|
5033
|
+
let stderr = "";
|
|
5034
|
+
let outputBytes = 0;
|
|
5035
|
+
const child = spawn(execution.command, execution.args, {
|
|
5036
|
+
cwd: execution.cwd,
|
|
5037
|
+
env: execution.env,
|
|
5038
|
+
shell: false,
|
|
5039
|
+
signal,
|
|
5040
|
+
windowsHide: true
|
|
5041
|
+
});
|
|
5042
|
+
child.on("error", reject);
|
|
5043
|
+
const append = (stream, chunk) => {
|
|
5044
|
+
outputBytes += chunk.byteLength;
|
|
5045
|
+
if (outputBytes > execution.maxOutputBytes) {
|
|
5046
|
+
child.kill();
|
|
5047
|
+
reject(new CapletsError("DOWNSTREAM_TOOL_ERROR", "CLI tool output exceeded byte limit"));
|
|
5048
|
+
return;
|
|
5049
|
+
}
|
|
5050
|
+
if (stream === "stdout") stdout += chunk.toString("utf8");
|
|
5051
|
+
else stderr += chunk.toString("utf8");
|
|
5052
|
+
};
|
|
5053
|
+
child.stdout?.on("data", (chunk) => append("stdout", chunk));
|
|
5054
|
+
child.stderr?.on("data", (chunk) => append("stderr", chunk));
|
|
5055
|
+
child.on("close", (exitCode, childSignal) => {
|
|
5056
|
+
resolve({
|
|
5057
|
+
exitCode,
|
|
5058
|
+
signal: childSignal,
|
|
5059
|
+
stdout,
|
|
5060
|
+
stderr,
|
|
5061
|
+
elapsedMs: elapsedMs()
|
|
5062
|
+
});
|
|
5063
|
+
});
|
|
5064
|
+
});
|
|
5065
|
+
}
|
|
5066
|
+
function parseStructuredResult(action, result, tolerateInvalidJson = false) {
|
|
5067
|
+
const structured = {
|
|
5068
|
+
exitCode: result.exitCode,
|
|
5069
|
+
stdout: result.stdout,
|
|
5070
|
+
stderr: result.stderr,
|
|
5071
|
+
elapsedMs: result.elapsedMs,
|
|
5072
|
+
...result.signal ? { signal: result.signal } : {}
|
|
5073
|
+
};
|
|
5074
|
+
if (action.output?.type === "json" && result.stdout.trim()) try {
|
|
5075
|
+
structured.json = JSON.parse(result.stdout);
|
|
5076
|
+
} catch (error) {
|
|
5077
|
+
if (tolerateInvalidJson) {
|
|
5078
|
+
structured.jsonParseError = toSafeError(error);
|
|
5079
|
+
return structured;
|
|
5080
|
+
}
|
|
5081
|
+
throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", `CLI tool ${action.name} stdout was not valid JSON`, toSafeError(error));
|
|
5082
|
+
}
|
|
5083
|
+
return structured;
|
|
5084
|
+
}
|
|
5085
|
+
function resolveCommandPath(command) {
|
|
5086
|
+
if (isAbsolute(command) || /[\\/]/.test(command)) {
|
|
5087
|
+
assertExecutable(command);
|
|
5088
|
+
return command;
|
|
5089
|
+
}
|
|
5090
|
+
for (const directory of (process.env.PATH ?? "").split(delimiter)) {
|
|
5091
|
+
if (!directory) continue;
|
|
5092
|
+
const candidate = join(directory, command);
|
|
5093
|
+
if (isExecutable(candidate)) return candidate;
|
|
5094
|
+
if (process.platform === "win32") for (const ext of (process.env.PATHEXT ?? ".EXE;.CMD;.BAT").split(";")) {
|
|
5095
|
+
const windowsCandidate = join(directory, `${command}${ext.toLowerCase()}`);
|
|
5096
|
+
if (isExecutable(windowsCandidate)) return windowsCandidate;
|
|
5097
|
+
}
|
|
5098
|
+
}
|
|
5099
|
+
throw new CapletsError("SERVER_UNAVAILABLE", `CLI command ${command} was not found on PATH`);
|
|
5100
|
+
}
|
|
5101
|
+
function assertExecutable(path) {
|
|
5102
|
+
if (!isExecutable(path)) throw new CapletsError("SERVER_UNAVAILABLE", `CLI command ${path} is not executable`);
|
|
5103
|
+
}
|
|
5104
|
+
function isExecutable(path) {
|
|
5105
|
+
try {
|
|
5106
|
+
accessSync(path, constants.X_OK);
|
|
5107
|
+
return true;
|
|
5108
|
+
} catch {
|
|
5109
|
+
return false;
|
|
5110
|
+
}
|
|
5111
|
+
}
|
|
5112
|
+
function isAbortError$1(error) {
|
|
5113
|
+
return error instanceof Error && error.name === "AbortError";
|
|
5114
|
+
}
|
|
5115
|
+
function isPlainObject$6(value) {
|
|
5116
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
5117
|
+
}
|
|
4992
5118
|
/** @deprecated Use the raw string literal codes instead, e.g. "invalid_type". */
|
|
4993
5119
|
const ZodIssueCode$1 = {
|
|
4994
5120
|
invalid_type: "invalid_type",
|
|
@@ -12509,9 +12635,9 @@ const capletMcpServerSchema = object$1({
|
|
|
12509
12635
|
cwd: string().min(1).optional().describe("Working directory for stdio servers."),
|
|
12510
12636
|
url: string().min(1).optional().describe("Remote MCP server URL for http or sse transport."),
|
|
12511
12637
|
auth: capletRemoteAuthSchema.optional(),
|
|
12512
|
-
startupTimeoutMs: number$
|
|
12513
|
-
callTimeoutMs: number$
|
|
12514
|
-
toolCacheTtlMs: number$
|
|
12638
|
+
startupTimeoutMs: number$2().int().positive().optional().describe("Timeout in milliseconds for starting or checking a downstream server."),
|
|
12639
|
+
callTimeoutMs: number$2().int().positive().optional().describe("Timeout in milliseconds for downstream tool calls."),
|
|
12640
|
+
toolCacheTtlMs: number$2().int().nonnegative().optional().describe("Milliseconds downstream tool metadata stays fresh. Set 0 to refresh every time."),
|
|
12515
12641
|
disabled: boolean().optional().describe("When true, omit this Caplet from discovery and do not start its MCP server.")
|
|
12516
12642
|
}).strict().superRefine((server, ctx) => {
|
|
12517
12643
|
const effectiveTransport = server.transport ?? (server.command ? "stdio" : void 0);
|
|
@@ -12566,8 +12692,8 @@ const capletOpenApiEndpointSchema = object$1({
|
|
|
12566
12692
|
specUrl: string().min(1).optional().describe("Remote OpenAPI specification URL."),
|
|
12567
12693
|
baseUrl: string().min(1).optional().describe("Override base URL for OpenAPI requests."),
|
|
12568
12694
|
auth: capletEndpointAuthSchema.describe("Explicit OpenAPI request auth config. Use {\"type\":\"none\"} for public APIs."),
|
|
12569
|
-
requestTimeoutMs: number$
|
|
12570
|
-
operationCacheTtlMs: number$
|
|
12695
|
+
requestTimeoutMs: number$2().int().positive().optional().describe("Timeout in milliseconds for OpenAPI HTTP requests."),
|
|
12696
|
+
operationCacheTtlMs: number$2().int().nonnegative().optional().describe("Milliseconds OpenAPI operation metadata stays fresh. Set 0 to refresh every time."),
|
|
12571
12697
|
disabled: boolean().optional().describe("When true, omit this Caplet from discovery.")
|
|
12572
12698
|
}).strict().superRefine((endpoint, ctx) => {
|
|
12573
12699
|
if (Boolean(endpoint.specPath) === Boolean(endpoint.specUrl)) ctx.addIssue({
|
|
@@ -12604,9 +12730,9 @@ const capletGraphQlEndpointSchema = object$1({
|
|
|
12604
12730
|
introspection: literal(true).optional().describe("Load schema through endpoint introspection."),
|
|
12605
12731
|
operations: record(string().regex(SERVER_ID_PATTERN), capletGraphQlOperationSchema).optional().describe("Configured GraphQL operations keyed by stable tool name."),
|
|
12606
12732
|
auth: capletEndpointAuthSchema.describe("Explicit GraphQL request auth config. Use {\"type\":\"none\"} for public APIs."),
|
|
12607
|
-
requestTimeoutMs: number$
|
|
12608
|
-
operationCacheTtlMs: number$
|
|
12609
|
-
selectionDepth: number$
|
|
12733
|
+
requestTimeoutMs: number$2().int().positive().optional().describe("Timeout in milliseconds for GraphQL HTTP requests."),
|
|
12734
|
+
operationCacheTtlMs: number$2().int().nonnegative().optional().describe("Milliseconds GraphQL operation metadata stays fresh. Set 0 to refresh every time."),
|
|
12735
|
+
selectionDepth: number$2().int().positive().max(5).optional().describe("Maximum depth for auto-generated GraphQL selection sets."),
|
|
12610
12736
|
disabled: boolean().optional().describe("When true, omit this Caplet from discovery.")
|
|
12611
12737
|
}).strict().superRefine((endpoint, ctx) => {
|
|
12612
12738
|
if (Number(Boolean(endpoint.schemaPath)) + Number(Boolean(endpoint.schemaUrl)) + Number(endpoint.introspection === true) !== 1) ctx.addIssue({
|
|
@@ -12627,7 +12753,7 @@ const capletGraphQlEndpointSchema = object$1({
|
|
|
12627
12753
|
});
|
|
12628
12754
|
const httpScalarMappingSchema$1 = record(string(), union([
|
|
12629
12755
|
string(),
|
|
12630
|
-
number$
|
|
12756
|
+
number$2(),
|
|
12631
12757
|
boolean()
|
|
12632
12758
|
]));
|
|
12633
12759
|
const capletHttpActionSchema = object$1({
|
|
@@ -12655,8 +12781,8 @@ const capletHttpApiSchema = object$1({
|
|
|
12655
12781
|
baseUrl: string().min(1).regex(HTTP_BASE_URL_PATTERN, "HTTP API baseUrl must not include credentials, query, or fragment").describe("Base URL for HTTP action requests."),
|
|
12656
12782
|
auth: capletEndpointAuthSchema.describe("Explicit HTTP API request auth config. Use {\"type\":\"none\"} for public APIs."),
|
|
12657
12783
|
actions: record(string().regex(SERVER_ID_PATTERN), capletHttpActionSchema).refine((actions) => Object.keys(actions).length > 0, "HTTP API must define at least one action").describe("Configured HTTP actions keyed by stable tool name."),
|
|
12658
|
-
requestTimeoutMs: number$
|
|
12659
|
-
maxResponseBytes: number$
|
|
12784
|
+
requestTimeoutMs: number$2().int().positive().optional().describe("Timeout in milliseconds for HTTP action requests."),
|
|
12785
|
+
maxResponseBytes: number$2().int().positive().optional().describe("Maximum HTTP action response body bytes to read."),
|
|
12660
12786
|
disabled: boolean().optional().describe("When true, omit this Caplet from discovery.")
|
|
12661
12787
|
}).strict().superRefine((api, ctx) => {
|
|
12662
12788
|
if (api.baseUrl && !hasEnvReference$1(api.baseUrl) && !isAllowedHttpBaseUrl(api.baseUrl)) ctx.addIssue({
|
|
@@ -12686,8 +12812,8 @@ const capletCliToolActionSchema = object$1({
|
|
|
12686
12812
|
args: array(string()).optional().describe("Arguments passed to the command."),
|
|
12687
12813
|
env: record(string(), string()).optional().describe("Additional environment variables."),
|
|
12688
12814
|
cwd: string().min(1).optional().describe("Working directory for this action."),
|
|
12689
|
-
timeoutMs: number$
|
|
12690
|
-
maxOutputBytes: number$
|
|
12815
|
+
timeoutMs: number$2().int().positive().optional(),
|
|
12816
|
+
maxOutputBytes: number$2().int().positive().optional(),
|
|
12691
12817
|
output: capletCliToolOutputSchema.optional(),
|
|
12692
12818
|
annotations: capletCliToolAnnotationsSchema.optional()
|
|
12693
12819
|
}).strict();
|
|
@@ -12695,16 +12821,16 @@ const capletCliToolsSchema = object$1({
|
|
|
12695
12821
|
actions: record(string().regex(SERVER_ID_PATTERN), capletCliToolActionSchema).refine((actions) => Object.keys(actions).length > 0, "CLI tools backend must define at least one action").describe("Configured CLI actions keyed by stable tool name."),
|
|
12696
12822
|
cwd: string().min(1).optional().describe("Default working directory for CLI actions."),
|
|
12697
12823
|
env: record(string(), string()).optional().describe("Default environment variables."),
|
|
12698
|
-
timeoutMs: number$
|
|
12699
|
-
maxOutputBytes: number$
|
|
12824
|
+
timeoutMs: number$2().int().positive().optional(),
|
|
12825
|
+
maxOutputBytes: number$2().int().positive().optional(),
|
|
12700
12826
|
disabled: boolean().optional().describe("When true, omit this Caplet from discovery.")
|
|
12701
12827
|
}).strict();
|
|
12702
12828
|
const capletSetSchema = object$1({
|
|
12703
12829
|
configPath: string().min(1).optional().describe("Child Caplets config.json path."),
|
|
12704
12830
|
capletsRoot: string().min(1).optional().describe("Child Markdown Caplets root directory."),
|
|
12705
|
-
defaultSearchLimit: number$
|
|
12706
|
-
maxSearchLimit: number$
|
|
12707
|
-
toolCacheTtlMs: number$
|
|
12831
|
+
defaultSearchLimit: number$2().int().positive().optional(),
|
|
12832
|
+
maxSearchLimit: number$2().int().positive().max(50).optional(),
|
|
12833
|
+
toolCacheTtlMs: number$2().int().nonnegative().optional(),
|
|
12708
12834
|
disabled: boolean().optional().describe("When true, omit this Caplet from discovery.")
|
|
12709
12835
|
}).strict().superRefine((set, ctx) => {
|
|
12710
12836
|
if (!set.configPath && !set.capletsRoot) ctx.addIssue({
|
|
@@ -12942,14 +13068,24 @@ function defaultStateBaseDir(env = process.env, home = homedir(), platform = pro
|
|
|
12942
13068
|
if (platform === "win32") return env.LOCALAPPDATA && win32.isAbsolute(env.LOCALAPPDATA) ? env.LOCALAPPDATA : win32.join(home, "AppData", "Local");
|
|
12943
13069
|
return env.XDG_STATE_HOME && posix.isAbsolute(env.XDG_STATE_HOME) ? env.XDG_STATE_HOME : posix.join(home, ".local", "state");
|
|
12944
13070
|
}
|
|
13071
|
+
function defaultCacheBaseDir(env = process.env, home = homedir(), platform = process.platform) {
|
|
13072
|
+
if (platform === "win32") return env.LOCALAPPDATA && win32.isAbsolute(env.LOCALAPPDATA) ? env.LOCALAPPDATA : win32.join(home, "AppData", "Local");
|
|
13073
|
+
if (platform === "darwin") return posix.join(home, "Library", "Caches");
|
|
13074
|
+
return env.XDG_CACHE_HOME && posix.isAbsolute(env.XDG_CACHE_HOME) ? env.XDG_CACHE_HOME : posix.join(home, ".cache");
|
|
13075
|
+
}
|
|
12945
13076
|
function defaultConfigPath(env = process.env, home = homedir(), platform = process.platform) {
|
|
12946
13077
|
return (platform === "win32" ? win32.join : posix.join)(defaultConfigBaseDir(env, home, platform), "caplets", "config.json");
|
|
12947
13078
|
}
|
|
12948
13079
|
function defaultAuthDir(env = process.env, home = homedir(), platform = process.platform) {
|
|
12949
13080
|
return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "auth");
|
|
12950
13081
|
}
|
|
13082
|
+
function defaultCompletionCacheDir(env = process.env, home = homedir(), platform = process.platform) {
|
|
13083
|
+
const pathJoin = platform === "win32" ? win32.join : posix.join;
|
|
13084
|
+
return platform === "win32" ? pathJoin(defaultCacheBaseDir(env, home, platform), "caplets", "cache", "completions") : pathJoin(defaultCacheBaseDir(env, home, platform), "caplets", "completions");
|
|
13085
|
+
}
|
|
12951
13086
|
const DEFAULT_CONFIG_PATH = defaultConfigPath();
|
|
12952
13087
|
const DEFAULT_AUTH_DIR = defaultAuthDir();
|
|
13088
|
+
const DEFAULT_COMPLETION_CACHE_DIR = defaultCompletionCacheDir();
|
|
12953
13089
|
const PROJECT_CONFIG_FILE = join(".caplets", "config.json");
|
|
12954
13090
|
function resolveConfigPath(path) {
|
|
12955
13091
|
return path ?? DEFAULT_CONFIG_PATH;
|
|
@@ -13062,9 +13198,9 @@ const publicServerSchema = object$1({
|
|
|
13062
13198
|
url: string().url().optional().describe("Remote MCP server URL for http or sse transport."),
|
|
13063
13199
|
auth: remoteAuthSchema.optional(),
|
|
13064
13200
|
tags: array(string().trim().min(1).max(80)).optional(),
|
|
13065
|
-
startupTimeoutMs: number$
|
|
13066
|
-
callTimeoutMs: number$
|
|
13067
|
-
toolCacheTtlMs: number$
|
|
13201
|
+
startupTimeoutMs: number$2().int().positive().default(1e4).describe("Timeout in milliseconds for starting or checking a downstream server."),
|
|
13202
|
+
callTimeoutMs: number$2().int().positive().default(6e4).describe("Timeout in milliseconds for downstream tool calls."),
|
|
13203
|
+
toolCacheTtlMs: number$2().int().nonnegative().default(3e4).describe("Milliseconds downstream tool metadata stays fresh. Set 0 to refresh every time."),
|
|
13068
13204
|
disabled: boolean().default(false).describe("When true, omit this server from Caplets discovery and do not start it.")
|
|
13069
13205
|
}).strict();
|
|
13070
13206
|
const normalizedServerSchema = publicServerSchema.extend({ body: string().optional() });
|
|
@@ -13076,8 +13212,8 @@ const publicOpenApiEndpointSchema = object$1({
|
|
|
13076
13212
|
baseUrl: string().url().optional().describe("Override base URL for OpenAPI requests."),
|
|
13077
13213
|
auth: openApiAuthSchema.describe("Explicit OpenAPI request auth config. Use {\"type\":\"none\"} for public APIs."),
|
|
13078
13214
|
tags: array(string().trim().min(1).max(80)).optional(),
|
|
13079
|
-
requestTimeoutMs: number$
|
|
13080
|
-
operationCacheTtlMs: number$
|
|
13215
|
+
requestTimeoutMs: number$2().int().positive().default(6e4).describe("Timeout in milliseconds for OpenAPI HTTP requests."),
|
|
13216
|
+
operationCacheTtlMs: number$2().int().nonnegative().default(3e4).describe("Milliseconds OpenAPI operation metadata stays fresh. Set 0 to refresh every time."),
|
|
13081
13217
|
disabled: boolean().default(false).describe("When true, omit this OpenAPI Caplet from discovery.")
|
|
13082
13218
|
}).strict();
|
|
13083
13219
|
const normalizedOpenApiEndpointSchema = publicOpenApiEndpointSchema.extend({ body: string().optional() });
|
|
@@ -13102,9 +13238,9 @@ const publicGraphQlEndpointSchema = object$1({
|
|
|
13102
13238
|
operations: record(string().regex(SERVER_ID_PATTERN), graphQlOperationSchema).optional().describe("Configured GraphQL operations keyed by stable tool name."),
|
|
13103
13239
|
auth: openApiAuthSchema.describe("Explicit GraphQL request auth config. Use {\"type\":\"none\"} for public APIs."),
|
|
13104
13240
|
tags: array(string().trim().min(1).max(80)).optional(),
|
|
13105
|
-
requestTimeoutMs: number$
|
|
13106
|
-
operationCacheTtlMs: number$
|
|
13107
|
-
selectionDepth: number$
|
|
13241
|
+
requestTimeoutMs: number$2().int().positive().default(6e4).describe("Timeout in milliseconds for GraphQL HTTP requests."),
|
|
13242
|
+
operationCacheTtlMs: number$2().int().nonnegative().default(3e4).describe("Milliseconds GraphQL operation metadata stays fresh. Set 0 to refresh every time."),
|
|
13243
|
+
selectionDepth: number$2().int().positive().max(5).default(2).describe("Maximum depth for auto-generated GraphQL selection sets."),
|
|
13108
13244
|
disabled: boolean().default(false).describe("When true, omit this GraphQL Caplet.")
|
|
13109
13245
|
}).strict().superRefine((endpoint, ctx) => {
|
|
13110
13246
|
if (Number(Boolean(endpoint.schemaPath)) + Number(Boolean(endpoint.schemaUrl)) + Number(endpoint.introspection === true) !== 1) ctx.addIssue({
|
|
@@ -13115,7 +13251,7 @@ const publicGraphQlEndpointSchema = object$1({
|
|
|
13115
13251
|
const normalizedGraphQlEndpointSchema = publicGraphQlEndpointSchema.extend({ body: string().optional() });
|
|
13116
13252
|
const httpScalarMappingSchema = record(string(), union([
|
|
13117
13253
|
string(),
|
|
13118
|
-
number$
|
|
13254
|
+
number$2(),
|
|
13119
13255
|
boolean()
|
|
13120
13256
|
]));
|
|
13121
13257
|
const httpActionSchema = object$1({
|
|
@@ -13147,8 +13283,8 @@ const publicHttpApiSchema = object$1({
|
|
|
13147
13283
|
auth: openApiAuthSchema.describe("Explicit HTTP API request auth config. Use {\"type\":\"none\"} for public APIs."),
|
|
13148
13284
|
actions: record(string().regex(SERVER_ID_PATTERN), httpActionSchema).refine((actions) => Object.keys(actions).length > 0, "HTTP API must define at least one action").describe("Configured HTTP actions keyed by stable tool name."),
|
|
13149
13285
|
tags: array(string().trim().min(1).max(80)).optional(),
|
|
13150
|
-
requestTimeoutMs: number$
|
|
13151
|
-
maxResponseBytes: number$
|
|
13286
|
+
requestTimeoutMs: number$2().int().positive().default(6e4).describe("Timeout in milliseconds for HTTP action requests."),
|
|
13287
|
+
maxResponseBytes: number$2().int().positive().default(2e5).describe("Maximum HTTP action response body bytes to read."),
|
|
13152
13288
|
disabled: boolean().default(false).describe("When true, omit this HTTP API Caplet.")
|
|
13153
13289
|
}).strict();
|
|
13154
13290
|
const normalizedHttpApiSchema = publicHttpApiSchema.extend({ body: string().optional() });
|
|
@@ -13167,8 +13303,8 @@ const cliToolActionSchema = object$1({
|
|
|
13167
13303
|
args: array(string()).optional().describe("Arguments passed to the command."),
|
|
13168
13304
|
env: record(string(), string()).optional().describe("Additional environment variables for the command."),
|
|
13169
13305
|
cwd: string().min(1).optional().describe("Working directory for this action."),
|
|
13170
|
-
timeoutMs: number$
|
|
13171
|
-
maxOutputBytes: number$
|
|
13306
|
+
timeoutMs: number$2().int().positive().optional().describe("Command timeout in milliseconds."),
|
|
13307
|
+
maxOutputBytes: number$2().int().positive().optional().describe("Maximum combined stdout and stderr bytes to keep."),
|
|
13172
13308
|
output: cliToolOutputSchema.optional(),
|
|
13173
13309
|
annotations: cliToolAnnotationsSchema.optional()
|
|
13174
13310
|
}).strict();
|
|
@@ -13179,8 +13315,8 @@ const publicCliToolsSchema = object$1({
|
|
|
13179
13315
|
cwd: string().min(1).optional().describe("Default working directory for CLI actions."),
|
|
13180
13316
|
env: record(string(), string()).optional().describe("Default environment variables for CLI actions."),
|
|
13181
13317
|
tags: array(string().trim().min(1).max(80)).optional(),
|
|
13182
|
-
timeoutMs: number$
|
|
13183
|
-
maxOutputBytes: number$
|
|
13318
|
+
timeoutMs: number$2().int().positive().default(6e4).describe("Default timeout in milliseconds for CLI actions."),
|
|
13319
|
+
maxOutputBytes: number$2().int().positive().default(2e5).describe("Default maximum combined stdout and stderr bytes to keep."),
|
|
13184
13320
|
disabled: boolean().default(false).describe("When true, omit this CLI tools Caplet.")
|
|
13185
13321
|
}).strict();
|
|
13186
13322
|
const normalizedCliToolsSchema = publicCliToolsSchema.extend({ body: string().optional() });
|
|
@@ -13189,9 +13325,9 @@ const publicCapletSetSchema = object$1({
|
|
|
13189
13325
|
description: string().describe("Capability description shown before child Caplets are disclosed.").refine((value) => value.trim().length >= 10, "description must contain at least 10 non-whitespace characters").refine((value) => value.length <= 1500, "description must be at most 1500 characters"),
|
|
13190
13326
|
configPath: string().min(1).optional().describe("Child Caplets config.json path."),
|
|
13191
13327
|
capletsRoot: string().min(1).optional().describe("Child Markdown Caplets root directory."),
|
|
13192
|
-
defaultSearchLimit: number$
|
|
13193
|
-
maxSearchLimit: number$
|
|
13194
|
-
toolCacheTtlMs: number$
|
|
13328
|
+
defaultSearchLimit: number$2().int().positive().default(20).describe("Default maximum number of child Caplet search results."),
|
|
13329
|
+
maxSearchLimit: number$2().int().positive().max(50).default(50).describe("Maximum accepted child Caplet search result limit."),
|
|
13330
|
+
toolCacheTtlMs: number$2().int().nonnegative().default(3e4).describe("Milliseconds child Caplet metadata stays fresh. Set 0 to refresh every time."),
|
|
13195
13331
|
tags: array(string().trim().min(1).max(80)).optional(),
|
|
13196
13332
|
disabled: boolean().default(false).describe("When true, omit this Caplet set.")
|
|
13197
13333
|
}).strict().superRefine((set, ctx) => {
|
|
@@ -13210,8 +13346,19 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
|
|
|
13210
13346
|
return object$1({
|
|
13211
13347
|
$schema: string().url().optional().describe("Optional JSON Schema URL for editor validation."),
|
|
13212
13348
|
version: literal(1).default(1).describe("Caplets config schema version."),
|
|
13213
|
-
defaultSearchLimit: number$
|
|
13214
|
-
maxSearchLimit: number$
|
|
13349
|
+
defaultSearchLimit: number$2().int().positive().default(20).describe("Default maximum number of same-server search results."),
|
|
13350
|
+
maxSearchLimit: number$2().int().positive().max(50).default(50).describe("Maximum accepted search_tools limit."),
|
|
13351
|
+
completion: object$1({
|
|
13352
|
+
discoveryTimeoutMs: number$2().int().positive().default(750),
|
|
13353
|
+
overallTimeoutMs: number$2().int().positive().default(1500),
|
|
13354
|
+
cacheTtlMs: number$2().int().nonnegative().default(3e5),
|
|
13355
|
+
negativeCacheTtlMs: number$2().int().nonnegative().default(3e4)
|
|
13356
|
+
}).strict().default({
|
|
13357
|
+
discoveryTimeoutMs: 750,
|
|
13358
|
+
overallTimeoutMs: 1500,
|
|
13359
|
+
cacheTtlMs: 3e5,
|
|
13360
|
+
negativeCacheTtlMs: 3e4
|
|
13361
|
+
}).describe("Shell completion discovery timeout and cache settings."),
|
|
13215
13362
|
mcpServers: record(string().regex(SERVER_ID_PATTERN), serverValueSchema).default({}).describe("Downstream MCP servers keyed by stable server ID."),
|
|
13216
13363
|
openapiEndpoints: record(string().regex(SERVER_ID_PATTERN), openApiEndpointValueSchema).default({}).describe("OpenAPI endpoints keyed by stable Caplet ID."),
|
|
13217
13364
|
graphqlEndpoints: record(string().regex(SERVER_ID_PATTERN), graphQlEndpointValueSchema).default({}).describe("GraphQL endpoints keyed by stable Caplet ID."),
|
|
@@ -13726,7 +13873,8 @@ function parseConfig(input) {
|
|
|
13726
13873
|
version: parsed.data.version,
|
|
13727
13874
|
options: {
|
|
13728
13875
|
defaultSearchLimit: parsed.data.defaultSearchLimit,
|
|
13729
|
-
maxSearchLimit: parsed.data.maxSearchLimit
|
|
13876
|
+
maxSearchLimit: parsed.data.maxSearchLimit,
|
|
13877
|
+
completion: parsed.data.completion
|
|
13730
13878
|
},
|
|
13731
13879
|
mcpServers: servers,
|
|
13732
13880
|
openapiEndpoints,
|
|
@@ -17306,10 +17454,10 @@ const ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
|
|
|
17306
17454
|
$ZodType.init(inst, def);
|
|
17307
17455
|
inst.def = def;
|
|
17308
17456
|
inst.type = def.type;
|
|
17309
|
-
inst.parse = (data, params) => parse$
|
|
17310
|
-
inst.safeParse = (data, params) => safeParse$
|
|
17457
|
+
inst.parse = (data, params) => parse$1(inst, data, params, { callee: inst.parse });
|
|
17458
|
+
inst.safeParse = (data, params) => safeParse$1(inst, data, params);
|
|
17311
17459
|
inst.parseAsync = async (data, params) => parseAsync$1(inst, data, params, { callee: inst.parseAsync });
|
|
17312
|
-
inst.safeParseAsync = async (data, params) => safeParseAsync$
|
|
17460
|
+
inst.safeParseAsync = async (data, params) => safeParseAsync$1(inst, data, params);
|
|
17313
17461
|
inst.check = (...checks) => {
|
|
17314
17462
|
return inst.clone({
|
|
17315
17463
|
...def,
|
|
@@ -17355,11 +17503,11 @@ function objectFromShape(shape) {
|
|
|
17355
17503
|
throw new Error("Mixed Zod versions detected in object shape.");
|
|
17356
17504
|
}
|
|
17357
17505
|
function safeParse(schema, data) {
|
|
17358
|
-
if (isZ4Schema(schema)) return safeParse$
|
|
17506
|
+
if (isZ4Schema(schema)) return safeParse$1(schema, data);
|
|
17359
17507
|
return schema.safeParse(data);
|
|
17360
17508
|
}
|
|
17361
17509
|
async function safeParseAsync(schema, data) {
|
|
17362
|
-
if (isZ4Schema(schema)) return await safeParseAsync$
|
|
17510
|
+
if (isZ4Schema(schema)) return await safeParseAsync$1(schema, data);
|
|
17363
17511
|
return await schema.safeParseAsync(data);
|
|
17364
17512
|
}
|
|
17365
17513
|
function getObjectShape(schema) {
|
|
@@ -17473,7 +17621,7 @@ const AssertObjectSchema = custom((v) => v !== null && (typeof v === "object" ||
|
|
|
17473
17621
|
/**
|
|
17474
17622
|
* A progress token, used to associate progress notifications with the original request.
|
|
17475
17623
|
*/
|
|
17476
|
-
const ProgressTokenSchema = union([string(), number$
|
|
17624
|
+
const ProgressTokenSchema = union([string(), number$2().int()]);
|
|
17477
17625
|
/**
|
|
17478
17626
|
* An opaque token used to represent a cursor for pagination.
|
|
17479
17627
|
*/
|
|
@@ -17482,13 +17630,13 @@ looseObject({
|
|
|
17482
17630
|
/**
|
|
17483
17631
|
* Requested duration in milliseconds to retain task from creation.
|
|
17484
17632
|
*/
|
|
17485
|
-
ttl: number$
|
|
17633
|
+
ttl: number$2().optional(),
|
|
17486
17634
|
/**
|
|
17487
17635
|
* Time in milliseconds to wait between task status requests.
|
|
17488
17636
|
*/
|
|
17489
|
-
pollInterval: number$
|
|
17637
|
+
pollInterval: number$2().optional()
|
|
17490
17638
|
});
|
|
17491
|
-
const TaskMetadataSchema = object$1({ ttl: number$
|
|
17639
|
+
const TaskMetadataSchema = object$1({ ttl: number$2().optional() });
|
|
17492
17640
|
/**
|
|
17493
17641
|
* Metadata for associating messages with a task.
|
|
17494
17642
|
* Include this in the `_meta` field under the key `io.modelcontextprotocol/related-task`.
|
|
@@ -17555,7 +17703,7 @@ _meta: RequestMetaSchema.optional() });
|
|
|
17555
17703
|
/**
|
|
17556
17704
|
* A uniquely identifying ID for a request in JSON-RPC.
|
|
17557
17705
|
*/
|
|
17558
|
-
const RequestIdSchema = union([string(), number$
|
|
17706
|
+
const RequestIdSchema = union([string(), number$2().int()]);
|
|
17559
17707
|
/**
|
|
17560
17708
|
* A request that expects a response.
|
|
17561
17709
|
*/
|
|
@@ -17612,7 +17760,7 @@ const JSONRPCErrorResponseSchema = object$1({
|
|
|
17612
17760
|
/**
|
|
17613
17761
|
* The error type that occurred.
|
|
17614
17762
|
*/
|
|
17615
|
-
code: number$
|
|
17763
|
+
code: number$2().int(),
|
|
17616
17764
|
/**
|
|
17617
17765
|
* A short description of the error. The message SHOULD be limited to a concise single sentence.
|
|
17618
17766
|
*/
|
|
@@ -17948,11 +18096,11 @@ const ProgressSchema = object$1({
|
|
|
17948
18096
|
/**
|
|
17949
18097
|
* The progress thus far. This should increase every time progress is made, even if the total is unknown.
|
|
17950
18098
|
*/
|
|
17951
|
-
progress: number$
|
|
18099
|
+
progress: number$2(),
|
|
17952
18100
|
/**
|
|
17953
18101
|
* Total number of items to process (or total progress required), if known.
|
|
17954
18102
|
*/
|
|
17955
|
-
total: optional(number$
|
|
18103
|
+
total: optional(number$2()),
|
|
17956
18104
|
/**
|
|
17957
18105
|
* An optional message describing the current progress.
|
|
17958
18106
|
*/
|
|
@@ -18008,7 +18156,7 @@ const TaskSchema = object$1({
|
|
|
18008
18156
|
* Time in milliseconds to keep task results available after completion.
|
|
18009
18157
|
* If null, the task has unlimited lifetime until manually cleaned up.
|
|
18010
18158
|
*/
|
|
18011
|
-
ttl: union([number$
|
|
18159
|
+
ttl: union([number$2(), _null()]),
|
|
18012
18160
|
/**
|
|
18013
18161
|
* ISO 8601 timestamp when the task was created.
|
|
18014
18162
|
*/
|
|
@@ -18017,7 +18165,7 @@ const TaskSchema = object$1({
|
|
|
18017
18165
|
* ISO 8601 timestamp when the task was last updated.
|
|
18018
18166
|
*/
|
|
18019
18167
|
lastUpdatedAt: string(),
|
|
18020
|
-
pollInterval: optional(number$
|
|
18168
|
+
pollInterval: optional(number$2()),
|
|
18021
18169
|
/**
|
|
18022
18170
|
* Optional diagnostic message for failed tasks or other status information.
|
|
18023
18171
|
*/
|
|
@@ -18132,7 +18280,7 @@ const AnnotationsSchema = object$1({
|
|
|
18132
18280
|
/**
|
|
18133
18281
|
* Importance hint for the resource, from 0 (least) to 1 (most).
|
|
18134
18282
|
*/
|
|
18135
|
-
priority: number$
|
|
18283
|
+
priority: number$2().min(0).max(1).optional(),
|
|
18136
18284
|
/**
|
|
18137
18285
|
* ISO 8601 timestamp for the most recent modification.
|
|
18138
18286
|
*/
|
|
@@ -18163,7 +18311,7 @@ const ResourceSchema = object$1({
|
|
|
18163
18311
|
*
|
|
18164
18312
|
* This can be used by Hosts to display file sizes and estimate context window usage.
|
|
18165
18313
|
*/
|
|
18166
|
-
size: optional(number$
|
|
18314
|
+
size: optional(number$2()),
|
|
18167
18315
|
/**
|
|
18168
18316
|
* Optional annotations for the client.
|
|
18169
18317
|
*/
|
|
@@ -18690,7 +18838,7 @@ const ListChangedOptionsBaseSchema = object$1({
|
|
|
18690
18838
|
*
|
|
18691
18839
|
* @default 300
|
|
18692
18840
|
*/
|
|
18693
|
-
debounceMs: number$
|
|
18841
|
+
debounceMs: number$2().int().nonnegative().default(300)
|
|
18694
18842
|
});
|
|
18695
18843
|
/**
|
|
18696
18844
|
* The severity of a log message.
|
|
@@ -18759,15 +18907,15 @@ name: string().optional() })).optional(),
|
|
|
18759
18907
|
/**
|
|
18760
18908
|
* How much to prioritize cost when selecting a model.
|
|
18761
18909
|
*/
|
|
18762
|
-
costPriority: number$
|
|
18910
|
+
costPriority: number$2().min(0).max(1).optional(),
|
|
18763
18911
|
/**
|
|
18764
18912
|
* How much to prioritize sampling speed (latency) when selecting a model.
|
|
18765
18913
|
*/
|
|
18766
|
-
speedPriority: number$
|
|
18914
|
+
speedPriority: number$2().min(0).max(1).optional(),
|
|
18767
18915
|
/**
|
|
18768
18916
|
* How much to prioritize intelligence and capabilities when selecting a model.
|
|
18769
18917
|
*/
|
|
18770
|
-
intelligencePriority: number$
|
|
18918
|
+
intelligencePriority: number$2().min(0).max(1).optional()
|
|
18771
18919
|
});
|
|
18772
18920
|
/**
|
|
18773
18921
|
* Controls tool usage behavior in sampling requests.
|
|
@@ -18857,13 +19005,13 @@ const CreateMessageRequestParamsSchema = TaskAugmentedRequestParamsSchema.extend
|
|
|
18857
19005
|
"thisServer",
|
|
18858
19006
|
"allServers"
|
|
18859
19007
|
]).optional(),
|
|
18860
|
-
temperature: number$
|
|
19008
|
+
temperature: number$2().optional(),
|
|
18861
19009
|
/**
|
|
18862
19010
|
* The requested maximum number of tokens to sample (to prevent runaway completions).
|
|
18863
19011
|
*
|
|
18864
19012
|
* The client MAY choose to sample fewer tokens than the requested maximum.
|
|
18865
19013
|
*/
|
|
18866
|
-
maxTokens: number$
|
|
19014
|
+
maxTokens: number$2().int(),
|
|
18867
19015
|
stopSequences: array(string()).optional(),
|
|
18868
19016
|
/**
|
|
18869
19017
|
* Optional metadata to pass through to the LLM provider. The format of this metadata is provider-specific.
|
|
@@ -18967,8 +19115,8 @@ const StringSchemaSchema = object$1({
|
|
|
18967
19115
|
type: literal("string"),
|
|
18968
19116
|
title: string().optional(),
|
|
18969
19117
|
description: string().optional(),
|
|
18970
|
-
minLength: number$
|
|
18971
|
-
maxLength: number$
|
|
19118
|
+
minLength: number$2().optional(),
|
|
19119
|
+
maxLength: number$2().optional(),
|
|
18972
19120
|
format: _enum([
|
|
18973
19121
|
"email",
|
|
18974
19122
|
"uri",
|
|
@@ -18984,9 +19132,9 @@ const NumberSchemaSchema = object$1({
|
|
|
18984
19132
|
type: _enum(["number", "integer"]),
|
|
18985
19133
|
title: string().optional(),
|
|
18986
19134
|
description: string().optional(),
|
|
18987
|
-
minimum: number$
|
|
18988
|
-
maximum: number$
|
|
18989
|
-
default: number$
|
|
19135
|
+
minimum: number$2().optional(),
|
|
19136
|
+
maximum: number$2().optional(),
|
|
19137
|
+
default: number$2().optional()
|
|
18990
19138
|
});
|
|
18991
19139
|
/**
|
|
18992
19140
|
* Schema for single-selection enumeration without display titles for options.
|
|
@@ -19029,8 +19177,8 @@ const PrimitiveSchemaDefinitionSchema = union([
|
|
|
19029
19177
|
type: literal("array"),
|
|
19030
19178
|
title: string().optional(),
|
|
19031
19179
|
description: string().optional(),
|
|
19032
|
-
minItems: number$
|
|
19033
|
-
maxItems: number$
|
|
19180
|
+
minItems: number$2().optional(),
|
|
19181
|
+
maxItems: number$2().optional(),
|
|
19034
19182
|
items: object$1({
|
|
19035
19183
|
type: literal("string"),
|
|
19036
19184
|
enum: array(string())
|
|
@@ -19040,8 +19188,8 @@ const PrimitiveSchemaDefinitionSchema = union([
|
|
|
19040
19188
|
type: literal("array"),
|
|
19041
19189
|
title: string().optional(),
|
|
19042
19190
|
description: string().optional(),
|
|
19043
|
-
minItems: number$
|
|
19044
|
-
maxItems: number$
|
|
19191
|
+
minItems: number$2().optional(),
|
|
19192
|
+
maxItems: number$2().optional(),
|
|
19045
19193
|
items: object$1({ anyOf: array(object$1({
|
|
19046
19194
|
const: string(),
|
|
19047
19195
|
title: string()
|
|
@@ -19146,7 +19294,7 @@ const ElicitResultSchema = ResultSchema.extend({
|
|
|
19146
19294
|
*/
|
|
19147
19295
|
content: preprocess((val) => val === null ? void 0 : val, record(string(), union([
|
|
19148
19296
|
string(),
|
|
19149
|
-
number$
|
|
19297
|
+
number$2(),
|
|
19150
19298
|
boolean(),
|
|
19151
19299
|
array(string())
|
|
19152
19300
|
])).optional())
|
|
@@ -19219,7 +19367,7 @@ const CompleteResultSchema = ResultSchema.extend({ completion: looseObject({
|
|
|
19219
19367
|
/**
|
|
19220
19368
|
* The total number of completion options available. This can exceed the number of values actually sent in the response.
|
|
19221
19369
|
*/
|
|
19222
|
-
total: optional(number$
|
|
19370
|
+
total: optional(number$2().int()),
|
|
19223
19371
|
/**
|
|
19224
19372
|
* Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.
|
|
19225
19373
|
*/
|
|
@@ -28684,15 +28832,15 @@ function createFetchWithInit(baseFetch = fetch, baseInit) {
|
|
|
28684
28832
|
});
|
|
28685
28833
|
};
|
|
28686
28834
|
}
|
|
28687
|
-
let crypto$
|
|
28688
|
-
crypto$
|
|
28835
|
+
let crypto$1;
|
|
28836
|
+
crypto$1 = globalThis.crypto?.webcrypto ?? globalThis.crypto ?? import("node:crypto").then((m) => m.webcrypto);
|
|
28689
28837
|
/**
|
|
28690
28838
|
* Creates an array of length `size` of random bytes
|
|
28691
28839
|
* @param size
|
|
28692
28840
|
* @returns Array of random ints (0 to 255)
|
|
28693
28841
|
*/
|
|
28694
28842
|
async function getRandomValues(size) {
|
|
28695
|
-
return (await crypto$
|
|
28843
|
+
return (await crypto$1).getRandomValues(new Uint8Array(size));
|
|
28696
28844
|
}
|
|
28697
28845
|
/** Generate cryptographically strong random string
|
|
28698
28846
|
* @param size The desired length of the string
|
|
@@ -28720,7 +28868,7 @@ async function generateVerifier(length) {
|
|
|
28720
28868
|
* @returns The base64 url encoded code challenge
|
|
28721
28869
|
*/
|
|
28722
28870
|
async function generateChallenge(code_verifier) {
|
|
28723
|
-
const buffer = await (await crypto$
|
|
28871
|
+
const buffer = await (await crypto$1).subtle.digest("SHA-256", new TextEncoder().encode(code_verifier));
|
|
28724
28872
|
return btoa(String.fromCharCode(...new Uint8Array(buffer))).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
|
|
28725
28873
|
}
|
|
28726
28874
|
/** Generate a PKCE challenge pair
|
|
@@ -28891,8 +29039,8 @@ const OAuthClientMetadataSchema = object$1({
|
|
|
28891
29039
|
const OAuthClientInformationSchema = object$1({
|
|
28892
29040
|
client_id: string(),
|
|
28893
29041
|
client_secret: string().optional(),
|
|
28894
|
-
client_id_issued_at: number$
|
|
28895
|
-
client_secret_expires_at: number$
|
|
29042
|
+
client_id_issued_at: number$2().optional(),
|
|
29043
|
+
client_secret_expires_at: number$2().optional()
|
|
28896
29044
|
}).strip();
|
|
28897
29045
|
/**
|
|
28898
29046
|
* RFC 7591 OAuth 2.0 Dynamic Client Registration full response (client information plus metadata)
|
|
@@ -31267,14 +31415,28 @@ var DownstreamManager = class {
|
|
|
31267
31415
|
async checkServer(server) {
|
|
31268
31416
|
const startedAt = Date.now();
|
|
31269
31417
|
try {
|
|
31418
|
+
const capabilities = (await this.connect(server)).client.getServerCapabilities() ?? {};
|
|
31270
31419
|
const tools = await this.refreshTools(server, true);
|
|
31271
31420
|
this.registry.setStatus(server.server, "available");
|
|
31272
|
-
|
|
31421
|
+
const result = {
|
|
31273
31422
|
id: server.server,
|
|
31274
31423
|
status: "available",
|
|
31424
|
+
capabilities: {
|
|
31425
|
+
tools: Boolean(capabilities.tools),
|
|
31426
|
+
resources: Boolean(capabilities.resources),
|
|
31427
|
+
resourceTemplates: Boolean(capabilities.resources),
|
|
31428
|
+
prompts: Boolean(capabilities.prompts),
|
|
31429
|
+
completions: Boolean(capabilities.completions)
|
|
31430
|
+
},
|
|
31275
31431
|
toolCount: tools.length,
|
|
31276
31432
|
elapsedMs: Date.now() - startedAt
|
|
31277
31433
|
};
|
|
31434
|
+
if (capabilities.resources) Object.assign(result, {
|
|
31435
|
+
resourceCount: (await this.listResources(server, true)).length,
|
|
31436
|
+
resourceTemplateCount: (await this.listResourceTemplates(server, true)).length
|
|
31437
|
+
});
|
|
31438
|
+
if (capabilities.prompts) Object.assign(result, { promptCount: (await this.listPrompts(server, true)).length });
|
|
31439
|
+
return result;
|
|
31278
31440
|
} catch (error) {
|
|
31279
31441
|
const safe = toSafeError(error, "SERVER_UNAVAILABLE");
|
|
31280
31442
|
this.registry.setStatus(server.server, "unavailable", safe);
|
|
@@ -31316,6 +31478,86 @@ var DownstreamManager = class {
|
|
|
31316
31478
|
throw new CapletsError("DOWNSTREAM_TOOL_ERROR", `Downstream tool failed for ${server.server}/${toolName}`, toSafeError(error));
|
|
31317
31479
|
}
|
|
31318
31480
|
}
|
|
31481
|
+
async listResources(server, force = false) {
|
|
31482
|
+
const connection = await this.assertCapability(server, "resources");
|
|
31483
|
+
if (!force && connection.resources && this.isCacheFresh(connection.resourcesFetchedAt, server.toolCacheTtlMs)) return connection.resources;
|
|
31484
|
+
const resources = [];
|
|
31485
|
+
let cursor;
|
|
31486
|
+
do {
|
|
31487
|
+
const result = await connection.client.listResources(cursor ? { cursor } : void 0, { timeout: server.startupTimeoutMs });
|
|
31488
|
+
resources.push(...result.resources ?? []);
|
|
31489
|
+
cursor = result.nextCursor;
|
|
31490
|
+
} while (cursor);
|
|
31491
|
+
connection.resources = resources;
|
|
31492
|
+
connection.resourcesFetchedAt = Date.now();
|
|
31493
|
+
return resources;
|
|
31494
|
+
}
|
|
31495
|
+
async listResourceTemplates(server, force = false) {
|
|
31496
|
+
const connection = await this.assertCapability(server, "resources");
|
|
31497
|
+
if (!force && connection.resourceTemplates && this.isCacheFresh(connection.resourceTemplatesFetchedAt, server.toolCacheTtlMs)) return connection.resourceTemplates;
|
|
31498
|
+
const resourceTemplates = [];
|
|
31499
|
+
let cursor;
|
|
31500
|
+
do {
|
|
31501
|
+
const result = await connection.client.listResourceTemplates(cursor ? { cursor } : void 0, { timeout: server.startupTimeoutMs });
|
|
31502
|
+
resourceTemplates.push(...result.resourceTemplates ?? []);
|
|
31503
|
+
cursor = result.nextCursor;
|
|
31504
|
+
} while (cursor);
|
|
31505
|
+
connection.resourceTemplates = resourceTemplates;
|
|
31506
|
+
connection.resourceTemplatesFetchedAt = Date.now();
|
|
31507
|
+
return resourceTemplates;
|
|
31508
|
+
}
|
|
31509
|
+
async readResource(server, uri) {
|
|
31510
|
+
const connection = await this.assertCapability(server, "resources");
|
|
31511
|
+
try {
|
|
31512
|
+
return await connection.client.readResource({ uri }, { timeout: server.callTimeoutMs });
|
|
31513
|
+
} catch (error) {
|
|
31514
|
+
throw new CapletsError("DOWNSTREAM_RESOURCE_ERROR", `Downstream resource read failed for ${server.server}/${uri}`, toSafeError(error));
|
|
31515
|
+
}
|
|
31516
|
+
}
|
|
31517
|
+
async listPrompts(server, force = false) {
|
|
31518
|
+
const connection = await this.assertCapability(server, "prompts");
|
|
31519
|
+
if (!force && connection.prompts && this.isCacheFresh(connection.promptsFetchedAt, server.toolCacheTtlMs)) return connection.prompts;
|
|
31520
|
+
const prompts = [];
|
|
31521
|
+
let cursor;
|
|
31522
|
+
do {
|
|
31523
|
+
const result = await connection.client.listPrompts(cursor ? { cursor } : void 0, { timeout: server.startupTimeoutMs });
|
|
31524
|
+
prompts.push(...result.prompts ?? []);
|
|
31525
|
+
cursor = result.nextCursor;
|
|
31526
|
+
} while (cursor);
|
|
31527
|
+
connection.prompts = prompts;
|
|
31528
|
+
connection.promptsFetchedAt = Date.now();
|
|
31529
|
+
return prompts;
|
|
31530
|
+
}
|
|
31531
|
+
async getPrompt(server, promptName, args) {
|
|
31532
|
+
if (!(await this.listPrompts(server)).some((prompt) => prompt.name === promptName)) throw new CapletsError("PROMPT_NOT_FOUND", `Prompt ${promptName} was not found on ${server.server}`);
|
|
31533
|
+
const connection = await this.connect(server);
|
|
31534
|
+
try {
|
|
31535
|
+
return await connection.client.getPrompt({
|
|
31536
|
+
name: promptName,
|
|
31537
|
+
arguments: stringifyPromptArgs(args)
|
|
31538
|
+
}, { timeout: server.callTimeoutMs });
|
|
31539
|
+
} catch (error) {
|
|
31540
|
+
throw new CapletsError("DOWNSTREAM_PROMPT_ERROR", `Downstream prompt failed for ${server.server}/${promptName}`, toSafeError(error));
|
|
31541
|
+
}
|
|
31542
|
+
}
|
|
31543
|
+
async complete(server, request) {
|
|
31544
|
+
const connection = await this.assertCapability(server, "completions");
|
|
31545
|
+
const params = {
|
|
31546
|
+
ref: request.ref.type === "prompt" ? {
|
|
31547
|
+
type: "ref/prompt",
|
|
31548
|
+
name: request.ref.name
|
|
31549
|
+
} : {
|
|
31550
|
+
type: "ref/resource",
|
|
31551
|
+
uri: request.ref.uri
|
|
31552
|
+
},
|
|
31553
|
+
argument: request.argument
|
|
31554
|
+
};
|
|
31555
|
+
try {
|
|
31556
|
+
return await connection.client.complete(params, { timeout: server.callTimeoutMs });
|
|
31557
|
+
} catch (error) {
|
|
31558
|
+
throw new CapletsError("DOWNSTREAM_COMPLETION_ERROR", `Downstream completion failed for ${server.server}`, toSafeError(error));
|
|
31559
|
+
}
|
|
31560
|
+
}
|
|
31319
31561
|
compact(server, tool) {
|
|
31320
31562
|
return {
|
|
31321
31563
|
id: server.server,
|
|
@@ -31325,9 +31567,75 @@ var DownstreamManager = class {
|
|
|
31325
31567
|
hasOutputSchema: Boolean(tool.outputSchema)
|
|
31326
31568
|
};
|
|
31327
31569
|
}
|
|
31570
|
+
compactResource(server, resource) {
|
|
31571
|
+
return {
|
|
31572
|
+
id: server.server,
|
|
31573
|
+
kind: "resource",
|
|
31574
|
+
uri: resource.uri,
|
|
31575
|
+
...resource.name ? { name: resource.name } : {},
|
|
31576
|
+
...resource.description ? { description: resource.description } : {},
|
|
31577
|
+
...resource.mimeType ? { mimeType: resource.mimeType } : {},
|
|
31578
|
+
...typeof resource.size === "number" ? { size: resource.size } : {}
|
|
31579
|
+
};
|
|
31580
|
+
}
|
|
31581
|
+
compactResourceTemplate(server, template) {
|
|
31582
|
+
return {
|
|
31583
|
+
id: server.server,
|
|
31584
|
+
kind: "resourceTemplate",
|
|
31585
|
+
uriTemplate: template.uriTemplate,
|
|
31586
|
+
...template.name ? { name: template.name } : {},
|
|
31587
|
+
...template.description ? { description: template.description } : {},
|
|
31588
|
+
...template.mimeType ? { mimeType: template.mimeType } : {}
|
|
31589
|
+
};
|
|
31590
|
+
}
|
|
31591
|
+
compactPrompt(server, prompt) {
|
|
31592
|
+
return {
|
|
31593
|
+
id: server.server,
|
|
31594
|
+
prompt: prompt.name,
|
|
31595
|
+
...prompt.description ? { description: prompt.description } : {},
|
|
31596
|
+
...prompt.arguments ? { arguments: prompt.arguments } : {}
|
|
31597
|
+
};
|
|
31598
|
+
}
|
|
31599
|
+
searchResources(server, resources, query, limit) {
|
|
31600
|
+
const lower = query.toLocaleLowerCase();
|
|
31601
|
+
return resources.map((resource) => this.compactResource(server, resource)).filter((resource) => [
|
|
31602
|
+
resource.uri,
|
|
31603
|
+
resource.name,
|
|
31604
|
+
resource.description,
|
|
31605
|
+
resource.mimeType
|
|
31606
|
+
].some((value) => value?.toLocaleLowerCase().includes(lower))).slice(0, limit);
|
|
31607
|
+
}
|
|
31608
|
+
searchResourceTemplates(server, templates, query, limit) {
|
|
31609
|
+
const lower = query.toLocaleLowerCase();
|
|
31610
|
+
return templates.map((template) => this.compactResourceTemplate(server, template)).filter((template) => [
|
|
31611
|
+
template.uriTemplate,
|
|
31612
|
+
template.name,
|
|
31613
|
+
template.description,
|
|
31614
|
+
template.mimeType
|
|
31615
|
+
].some((value) => value?.toLocaleLowerCase().includes(lower))).slice(0, limit);
|
|
31616
|
+
}
|
|
31617
|
+
searchPrompts(server, prompts, query, limit) {
|
|
31618
|
+
const lower = query.toLocaleLowerCase();
|
|
31619
|
+
return prompts.map((prompt) => this.compactPrompt(server, prompt)).filter((prompt) => [
|
|
31620
|
+
prompt.prompt,
|
|
31621
|
+
prompt.description,
|
|
31622
|
+
...(prompt.arguments ?? []).flatMap((arg) => [arg.name, arg.description])
|
|
31623
|
+
].some((value) => value?.toLocaleLowerCase().includes(lower))).slice(0, limit);
|
|
31624
|
+
}
|
|
31328
31625
|
search(server, tools, query, limit) {
|
|
31329
31626
|
return searchToolList(tools, query, limit, (tool) => this.compact(server, tool));
|
|
31330
31627
|
}
|
|
31628
|
+
async assertCapability(server, capability) {
|
|
31629
|
+
const connection = await this.connect(server);
|
|
31630
|
+
if (!connection.client.getServerCapabilities()?.[capability]) throw new CapletsError("UNSUPPORTED_CAPABILITY", `${server.server} does not advertise MCP ${capability}`, {
|
|
31631
|
+
server: server.server,
|
|
31632
|
+
capability
|
|
31633
|
+
});
|
|
31634
|
+
return connection;
|
|
31635
|
+
}
|
|
31636
|
+
isCacheFresh(fetchedAt, ttlMs) {
|
|
31637
|
+
return fetchedAt !== void 0 && ttlMs > 0 && Date.now() - fetchedAt <= ttlMs;
|
|
31638
|
+
}
|
|
31331
31639
|
async refreshTools(server, force) {
|
|
31332
31640
|
const connection = await this.connect(server);
|
|
31333
31641
|
const now = Date.now();
|
|
@@ -31371,6 +31679,20 @@ var DownstreamManager = class {
|
|
|
31371
31679
|
transport,
|
|
31372
31680
|
configFingerprint: expectedFingerprint
|
|
31373
31681
|
};
|
|
31682
|
+
client.setNotificationHandler(ToolListChangedNotificationSchema, () => {
|
|
31683
|
+
connection.tools = void 0;
|
|
31684
|
+
connection.toolsFetchedAt = void 0;
|
|
31685
|
+
});
|
|
31686
|
+
client.setNotificationHandler(ResourceListChangedNotificationSchema, () => {
|
|
31687
|
+
connection.resources = void 0;
|
|
31688
|
+
connection.resourcesFetchedAt = void 0;
|
|
31689
|
+
connection.resourceTemplates = void 0;
|
|
31690
|
+
connection.resourceTemplatesFetchedAt = void 0;
|
|
31691
|
+
});
|
|
31692
|
+
client.setNotificationHandler(PromptListChangedNotificationSchema, () => {
|
|
31693
|
+
connection.prompts = void 0;
|
|
31694
|
+
connection.promptsFetchedAt = void 0;
|
|
31695
|
+
});
|
|
31374
31696
|
pendingConnection = connection;
|
|
31375
31697
|
this.connecting.set(server.server, connection);
|
|
31376
31698
|
transport.onclose = () => {
|
|
@@ -31501,6 +31823,18 @@ function nearbyToolNames(tools, needle) {
|
|
|
31501
31823
|
function isTimeoutLike(error) {
|
|
31502
31824
|
return error instanceof Error && /timeout|timed out|aborted/i.test(error.message);
|
|
31503
31825
|
}
|
|
31826
|
+
function stringifyPromptArgs(args) {
|
|
31827
|
+
const stringified = {};
|
|
31828
|
+
for (const [key, value] of Object.entries(args)) {
|
|
31829
|
+
if (typeof value === "string") {
|
|
31830
|
+
stringified[key] = value;
|
|
31831
|
+
continue;
|
|
31832
|
+
}
|
|
31833
|
+
const serialized = JSON.stringify(value);
|
|
31834
|
+
if (typeof serialized === "string") stringified[key] = serialized;
|
|
31835
|
+
}
|
|
31836
|
+
return stringified;
|
|
31837
|
+
}
|
|
31504
31838
|
function isAuthRemediationError(error) {
|
|
31505
31839
|
return error instanceof CapletsError && (error.code === "AUTH_REQUIRED" || error.code === "AUTH_FAILED");
|
|
31506
31840
|
}
|
|
@@ -56362,7 +56696,7 @@ function capabilityDescription(server) {
|
|
|
56362
56696
|
return [
|
|
56363
56697
|
`${server.name} Caplet.`,
|
|
56364
56698
|
server.description,
|
|
56365
|
-
"Use get_caplet for details when needed; use search_tools or list_tools to discover downstream operations."
|
|
56699
|
+
server.backend === "mcp" ? "Use get_caplet for details when needed; use tools for actions, resources for readable context, prompts for reusable workflows, and complete for prompt/resource-template arguments." : "Use get_caplet for details when needed; use search_tools or list_tools to discover downstream operations."
|
|
56366
56700
|
].filter(Boolean).join(" ");
|
|
56367
56701
|
}
|
|
56368
56702
|
var ServerRegistry = class {
|
|
@@ -56578,17 +56912,9 @@ function cloneJsonValue(value) {
|
|
|
56578
56912
|
function throwInvalid(message) {
|
|
56579
56913
|
throw new CapletsError("REQUEST_INVALID", message);
|
|
56580
56914
|
}
|
|
56581
|
-
const generatedToolInputSchema = object$1({
|
|
56582
|
-
operation: _enum(operations).describe(generatedToolInputDescriptions.operation),
|
|
56583
|
-
query: string().optional().describe(generatedToolInputDescriptions.query),
|
|
56584
|
-
limit: number$1().int().positive().optional().describe(generatedToolInputDescriptions.limit),
|
|
56585
|
-
tool: string().optional().describe(generatedToolInputDescriptions.tool),
|
|
56586
|
-
arguments: record(string(), unknown()).optional().describe(generatedToolInputDescriptions.arguments),
|
|
56587
|
-
fields: array(string().min(1)).min(1).optional().describe(generatedToolInputDescriptions.fields)
|
|
56588
|
-
}).strict();
|
|
56589
56915
|
async function handleServerTool(server, request, registry, downstream, openapi, graphql, http, cli, caplets) {
|
|
56590
56916
|
const startedAt = Date.now();
|
|
56591
|
-
const parsed = validateOperationRequest(request, registry.config.options.maxSearchLimit);
|
|
56917
|
+
const parsed = validateOperationRequest(request, registry.config.options.maxSearchLimit, server.backend);
|
|
56592
56918
|
switch (parsed.operation) {
|
|
56593
56919
|
case "get_caplet": return jsonResult(registry.detail(server), metadataFor(server, "get_caplet", void 0, startedAt));
|
|
56594
56920
|
case "check_backend": return jsonResult(await backendFor(server, downstream, openapi, graphql, http, cli, caplets).check(server), metadataFor(server, "check_backend", void 0, startedAt));
|
|
@@ -56629,11 +56955,75 @@ async function handleServerTool(server, request, registry, downstream, openapi,
|
|
|
56629
56955
|
validateFieldSelection(tool.outputSchema, parsed.fields);
|
|
56630
56956
|
return annotateCallToolResult(projectCallToolResult(await backend.callTool(server, parsed.tool, parsed.arguments), tool.outputSchema, parsed.fields), metadataFor(server, "call_tool", parsed.tool, startedAt));
|
|
56631
56957
|
}
|
|
56958
|
+
case "list_resources": {
|
|
56959
|
+
const backend = mcpBackendFor(server, downstream);
|
|
56960
|
+
const resources = await backend.listResources(server);
|
|
56961
|
+
const templates = await backend.listResourceTemplates(server);
|
|
56962
|
+
const limit = parsed.limit ?? resources.length + templates.length;
|
|
56963
|
+
return jsonResult({
|
|
56964
|
+
id: server.server,
|
|
56965
|
+
name: server.name,
|
|
56966
|
+
resources: resources.slice(0, limit).map((resource) => backend.compactResource(server, resource)),
|
|
56967
|
+
resourceTemplates: templates.slice(0, Math.max(0, limit - resources.length)).map((template) => backend.compactResourceTemplate(server, template))
|
|
56968
|
+
}, metadataFor(server, "list_resources", void 0, startedAt));
|
|
56969
|
+
}
|
|
56970
|
+
case "search_resources": {
|
|
56971
|
+
const backend = mcpBackendFor(server, downstream);
|
|
56972
|
+
const resources = await backend.listResources(server);
|
|
56973
|
+
const templates = await backend.listResourceTemplates(server);
|
|
56974
|
+
const limit = parsed.limit ?? registry.config.options.defaultSearchLimit;
|
|
56975
|
+
const resourceMatches = backend.searchResources(server, resources, parsed.query, limit);
|
|
56976
|
+
const templateMatches = backend.searchResourceTemplates(server, templates, parsed.query, Math.max(0, limit - resourceMatches.length));
|
|
56977
|
+
return jsonResult({
|
|
56978
|
+
id: server.server,
|
|
56979
|
+
name: server.name,
|
|
56980
|
+
query: parsed.query,
|
|
56981
|
+
matches: [...resourceMatches, ...templateMatches]
|
|
56982
|
+
}, metadataFor(server, "search_resources", void 0, startedAt));
|
|
56983
|
+
}
|
|
56984
|
+
case "list_resource_templates": {
|
|
56985
|
+
const backend = mcpBackendFor(server, downstream);
|
|
56986
|
+
const templates = await backend.listResourceTemplates(server);
|
|
56987
|
+
const limit = parsed.limit ?? templates.length;
|
|
56988
|
+
return jsonResult({
|
|
56989
|
+
id: server.server,
|
|
56990
|
+
name: server.name,
|
|
56991
|
+
resourceTemplates: templates.slice(0, limit).map((template) => backend.compactResourceTemplate(server, template))
|
|
56992
|
+
}, metadataFor(server, "list_resource_templates", void 0, startedAt));
|
|
56993
|
+
}
|
|
56994
|
+
case "read_resource": return annotateMcpResult(await mcpBackendFor(server, downstream).readResource(server, parsed.uri), metadataFor(server, "read_resource", { uri: parsed.uri }, startedAt));
|
|
56995
|
+
case "list_prompts": {
|
|
56996
|
+
const backend = mcpBackendFor(server, downstream);
|
|
56997
|
+
const prompts = await backend.listPrompts(server);
|
|
56998
|
+
const limit = parsed.limit ?? prompts.length;
|
|
56999
|
+
return jsonResult({
|
|
57000
|
+
id: server.server,
|
|
57001
|
+
name: server.name,
|
|
57002
|
+
prompts: prompts.slice(0, limit).map((prompt) => backend.compactPrompt(server, prompt))
|
|
57003
|
+
}, metadataFor(server, "list_prompts", void 0, startedAt));
|
|
57004
|
+
}
|
|
57005
|
+
case "search_prompts": {
|
|
57006
|
+
const backend = mcpBackendFor(server, downstream);
|
|
57007
|
+
const prompts = await backend.listPrompts(server);
|
|
57008
|
+
const limit = parsed.limit ?? registry.config.options.defaultSearchLimit;
|
|
57009
|
+
return jsonResult({
|
|
57010
|
+
id: server.server,
|
|
57011
|
+
name: server.name,
|
|
57012
|
+
query: parsed.query,
|
|
57013
|
+
prompts: backend.searchPrompts(server, prompts, parsed.query, limit)
|
|
57014
|
+
}, metadataFor(server, "search_prompts", void 0, startedAt));
|
|
57015
|
+
}
|
|
57016
|
+
case "get_prompt": return annotateMcpResult(await mcpBackendFor(server, downstream).getPrompt(server, parsed.prompt, parsed.arguments), metadataFor(server, "get_prompt", { prompt: parsed.prompt }, startedAt));
|
|
57017
|
+
case "complete": return annotateMcpResult(await mcpBackendFor(server, downstream).complete(server, {
|
|
57018
|
+
ref: parsed.ref,
|
|
57019
|
+
argument: parsed.argument
|
|
57020
|
+
}), metadataFor(server, "complete", void 0, startedAt));
|
|
56632
57021
|
}
|
|
56633
57022
|
}
|
|
56634
|
-
function validateOperationRequest(request, maxSearchLimit) {
|
|
56635
|
-
|
|
56636
|
-
|
|
57023
|
+
function validateOperationRequest(request, maxSearchLimit, backend = "tool") {
|
|
57024
|
+
const result = generatedToolInputSchemaForCaplet({ backend }).safeParse(request);
|
|
57025
|
+
if (request && typeof request === "object" && "operation" in request && typeof request.operation === "string" && !mcpOperations.includes(request.operation)) throw new CapletsError("UNKNOWN_OPERATION", `Unknown operation: ${request.operation}`);
|
|
57026
|
+
if (request && typeof request === "object" && "operation" in request && typeof request.operation === "string" && backend !== "mcp" && mcpOperations.includes(request.operation) && !operations.includes(request.operation)) throw new CapletsError("UNSUPPORTED_OPERATION", `${request.operation} is only available for MCP-backed Caplets`);
|
|
56637
57027
|
if (!result.success) throw new CapletsError("REQUEST_INVALID", "Generated server tool request is invalid", result.error.issues);
|
|
56638
57028
|
const value = result.data;
|
|
56639
57029
|
const keys = Object.keys(value).sort();
|
|
@@ -56680,7 +57070,7 @@ function validateOperationRequest(request, maxSearchLimit) {
|
|
|
56680
57070
|
"fields"
|
|
56681
57071
|
]);
|
|
56682
57072
|
if (!value.tool) throw new CapletsError("REQUEST_INVALID", "call_tool requires tool");
|
|
56683
|
-
if (!isPlainObject$
|
|
57073
|
+
if (!isPlainObject$7(value.arguments)) throw new CapletsError("REQUEST_INVALID", "call_tool.arguments must be a JSON object");
|
|
56684
57074
|
return value.fields === void 0 ? {
|
|
56685
57075
|
operation: "call_tool",
|
|
56686
57076
|
tool: value.tool,
|
|
@@ -56691,23 +57081,82 @@ function validateOperationRequest(request, maxSearchLimit) {
|
|
|
56691
57081
|
arguments: value.arguments,
|
|
56692
57082
|
fields: value.fields
|
|
56693
57083
|
};
|
|
57084
|
+
case "list_resources":
|
|
57085
|
+
case "list_resource_templates":
|
|
57086
|
+
case "list_prompts":
|
|
57087
|
+
allowed(["limit"]);
|
|
57088
|
+
if (value.limit !== void 0 && value.limit > maxSearchLimit) throw new CapletsError("REQUEST_INVALID", `${value.operation} limit must be <= ${maxSearchLimit}`);
|
|
57089
|
+
return value.limit === void 0 ? { operation: value.operation } : {
|
|
57090
|
+
operation: value.operation,
|
|
57091
|
+
limit: value.limit
|
|
57092
|
+
};
|
|
57093
|
+
case "search_resources":
|
|
57094
|
+
case "search_prompts":
|
|
57095
|
+
allowed(["query", "limit"]);
|
|
57096
|
+
if (!value.query) throw new CapletsError("REQUEST_INVALID", `${value.operation} requires query`);
|
|
57097
|
+
if (value.limit !== void 0 && value.limit > maxSearchLimit) throw new CapletsError("REQUEST_INVALID", `${value.operation} limit must be <= ${maxSearchLimit}`);
|
|
57098
|
+
return value.limit === void 0 ? {
|
|
57099
|
+
operation: value.operation,
|
|
57100
|
+
query: value.query
|
|
57101
|
+
} : {
|
|
57102
|
+
operation: value.operation,
|
|
57103
|
+
query: value.query,
|
|
57104
|
+
limit: value.limit
|
|
57105
|
+
};
|
|
57106
|
+
case "read_resource":
|
|
57107
|
+
allowed(["uri"]);
|
|
57108
|
+
if (!value.uri) throw new CapletsError("REQUEST_INVALID", "read_resource requires uri");
|
|
57109
|
+
return {
|
|
57110
|
+
operation: "read_resource",
|
|
57111
|
+
uri: value.uri
|
|
57112
|
+
};
|
|
57113
|
+
case "get_prompt":
|
|
57114
|
+
allowed(["prompt", "arguments"]);
|
|
57115
|
+
if (!value.prompt) throw new CapletsError("REQUEST_INVALID", "get_prompt requires prompt");
|
|
57116
|
+
if (value.arguments !== void 0 && !isPlainObject$7(value.arguments)) throw new CapletsError("REQUEST_INVALID", "get_prompt.arguments must be a JSON object");
|
|
57117
|
+
return {
|
|
57118
|
+
operation: "get_prompt",
|
|
57119
|
+
prompt: value.prompt,
|
|
57120
|
+
arguments: value.arguments ?? {}
|
|
57121
|
+
};
|
|
57122
|
+
case "complete":
|
|
57123
|
+
allowed(["ref", "argument"]);
|
|
57124
|
+
if (!value.ref) throw new CapletsError("REQUEST_INVALID", "complete requires ref");
|
|
57125
|
+
if (!value.argument) throw new CapletsError("REQUEST_INVALID", "complete requires argument");
|
|
57126
|
+
return {
|
|
57127
|
+
operation: "complete",
|
|
57128
|
+
ref: value.ref,
|
|
57129
|
+
argument: value.argument
|
|
57130
|
+
};
|
|
56694
57131
|
}
|
|
56695
|
-
|
|
57132
|
+
throw new CapletsError("INTERNAL_ERROR", "Unhandled operation");
|
|
56696
57133
|
}
|
|
56697
|
-
function
|
|
56698
|
-
throw new CapletsError("
|
|
57134
|
+
function mcpBackendFor(server, downstream) {
|
|
57135
|
+
if (server.backend !== "mcp") throw new CapletsError("UNSUPPORTED_OPERATION", "MCP resource, prompt, and completion operations require an MCP-backed Caplet");
|
|
57136
|
+
return downstream;
|
|
56699
57137
|
}
|
|
56700
|
-
function metadataFor(server, operation,
|
|
57138
|
+
function metadataFor(server, operation, target, startedAt) {
|
|
57139
|
+
const targetFields = typeof target === "string" ? { tool: target } : target ?? {};
|
|
56701
57140
|
return {
|
|
56702
57141
|
id: server.server,
|
|
56703
57142
|
name: server.name,
|
|
56704
57143
|
backend: server.backend,
|
|
56705
57144
|
operation,
|
|
56706
|
-
...
|
|
57145
|
+
...targetFields,
|
|
56707
57146
|
status: "ok",
|
|
56708
57147
|
...startedAt === void 0 ? {} : { elapsedMs: Date.now() - startedAt }
|
|
56709
57148
|
};
|
|
56710
57149
|
}
|
|
57150
|
+
function annotateMcpResult(result, metadata) {
|
|
57151
|
+
const existingMeta = result._meta;
|
|
57152
|
+
return {
|
|
57153
|
+
...result,
|
|
57154
|
+
_meta: {
|
|
57155
|
+
...isPlainObject$7(existingMeta) ? existingMeta : {},
|
|
57156
|
+
caplets: metadata
|
|
57157
|
+
}
|
|
57158
|
+
};
|
|
57159
|
+
}
|
|
56711
57160
|
function jsonResult(value, metadata) {
|
|
56712
57161
|
return {
|
|
56713
57162
|
content: [{
|
|
@@ -56731,7 +57180,7 @@ function annotateCallToolResult(result, metadata) {
|
|
|
56731
57180
|
return {
|
|
56732
57181
|
...result,
|
|
56733
57182
|
_meta: {
|
|
56734
|
-
...isPlainObject$
|
|
57183
|
+
...isPlainObject$7(existingMeta) ? existingMeta : {},
|
|
56735
57184
|
caplets: annotatedMetadata
|
|
56736
57185
|
}
|
|
56737
57186
|
};
|
|
@@ -56739,7 +57188,7 @@ function annotateCallToolResult(result, metadata) {
|
|
|
56739
57188
|
function projectCallToolResult(result, outputSchema, fields) {
|
|
56740
57189
|
if (result.isError === true) return result;
|
|
56741
57190
|
const structuredContent = result.structuredContent;
|
|
56742
|
-
if (!isPlainObject$
|
|
57191
|
+
if (!isPlainObject$7(structuredContent)) throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Field selection requires the downstream tool to return object structuredContent");
|
|
56743
57192
|
const projected = projectStructuredContent(structuredContent, outputSchema, fields);
|
|
56744
57193
|
return {
|
|
56745
57194
|
...result,
|
|
@@ -56748,11 +57197,11 @@ function projectCallToolResult(result, outputSchema, fields) {
|
|
|
56748
57197
|
};
|
|
56749
57198
|
}
|
|
56750
57199
|
function extractArtifacts(result) {
|
|
56751
|
-
if (!isPlainObject$
|
|
57200
|
+
if (!isPlainObject$7(result) || !Array.isArray(result.content)) return [];
|
|
56752
57201
|
const artifacts = [];
|
|
56753
57202
|
const seen = /* @__PURE__ */ new Set();
|
|
56754
57203
|
for (const item of result.content) {
|
|
56755
|
-
if (!isPlainObject$
|
|
57204
|
+
if (!isPlainObject$7(item) || item.type !== "text" || typeof item.text !== "string") continue;
|
|
56756
57205
|
const text = item.text;
|
|
56757
57206
|
for (const link of parseMarkdownLinks(text)) {
|
|
56758
57207
|
const label = link.label;
|
|
@@ -56867,7 +57316,7 @@ function artifactKindFromText(text) {
|
|
|
56867
57316
|
if (/network[-_ ]?(?:log)?|har\b/.test(text)) return "network-log";
|
|
56868
57317
|
return "file";
|
|
56869
57318
|
}
|
|
56870
|
-
function isPlainObject$
|
|
57319
|
+
function isPlainObject$7(value) {
|
|
56871
57320
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
56872
57321
|
}
|
|
56873
57322
|
function backendFor(server, downstream, openapi, graphql, http, cli, caplets) {
|
|
@@ -57175,6 +57624,38 @@ var CapletsEngine = class {
|
|
|
57175
57624
|
return errorResult(error);
|
|
57176
57625
|
}
|
|
57177
57626
|
}
|
|
57627
|
+
async completeCliWords(words) {
|
|
57628
|
+
const { completeCliWords } = await Promise.resolve().then(() => completion_dbB1hc97_exports).then((n) => n.r);
|
|
57629
|
+
return await completeCliWords(words, {
|
|
57630
|
+
config: this.registry.config,
|
|
57631
|
+
managers: {
|
|
57632
|
+
listTools: async (server) => this.listCompletionTools(server),
|
|
57633
|
+
listPrompts: async (server) => {
|
|
57634
|
+
if (server.backend !== "mcp") return [];
|
|
57635
|
+
return (await this.downstream.listPrompts(server)).map((prompt) => ({
|
|
57636
|
+
name: prompt.name,
|
|
57637
|
+
...prompt.description ? { description: prompt.description } : {}
|
|
57638
|
+
}));
|
|
57639
|
+
},
|
|
57640
|
+
listResources: async (server) => {
|
|
57641
|
+
if (server.backend !== "mcp") return [];
|
|
57642
|
+
return (await this.downstream.listResources(server)).map((resource) => ({
|
|
57643
|
+
uri: resource.uri,
|
|
57644
|
+
...resource.name ? { name: resource.name } : {},
|
|
57645
|
+
...resource.description ? { description: resource.description } : {}
|
|
57646
|
+
}));
|
|
57647
|
+
},
|
|
57648
|
+
listResourceTemplates: async (server) => {
|
|
57649
|
+
if (server.backend !== "mcp") return [];
|
|
57650
|
+
return (await this.downstream.listResourceTemplates(server)).map((template) => ({
|
|
57651
|
+
uriTemplate: template.uriTemplate,
|
|
57652
|
+
...template.name ? { name: template.name } : {},
|
|
57653
|
+
...template.description ? { description: template.description } : {}
|
|
57654
|
+
}));
|
|
57655
|
+
}
|
|
57656
|
+
}
|
|
57657
|
+
});
|
|
57658
|
+
}
|
|
57178
57659
|
async close() {
|
|
57179
57660
|
this.closed = true;
|
|
57180
57661
|
try {
|
|
@@ -57194,6 +57675,12 @@ var CapletsEngine = class {
|
|
|
57194
57675
|
this.reloadListeners.clear();
|
|
57195
57676
|
}
|
|
57196
57677
|
}
|
|
57678
|
+
async listCompletionTools(server) {
|
|
57679
|
+
return (server.backend === "mcp" ? await this.downstream.listTools(server) : server.backend === "openapi" ? await this.openapi.listTools(server) : server.backend === "graphql" ? await this.graphql.listTools(server) : server.backend === "http" ? await this.http.listTools(server) : server.backend === "cli" ? await this.cli.listTools(server) : await this.capletSets.listTools(server)).map((tool) => ({
|
|
57680
|
+
name: tool.name,
|
|
57681
|
+
...tool.description ? { description: tool.description } : {}
|
|
57682
|
+
}));
|
|
57683
|
+
}
|
|
57197
57684
|
async reloadOnce() {
|
|
57198
57685
|
if (this.closed) return false;
|
|
57199
57686
|
let nextConfig;
|
|
@@ -57476,6 +57963,565 @@ function hasEnv$1(value) {
|
|
|
57476
57963
|
return value !== void 0 && value.trim() !== "";
|
|
57477
57964
|
}
|
|
57478
57965
|
//#endregion
|
|
57966
|
+
//#region ../core/dist/completion-dbB1hc97.js
|
|
57967
|
+
var completion_dbB1hc97_exports = /* @__PURE__ */ __exportAll$1({
|
|
57968
|
+
a: () => formatCapletList,
|
|
57969
|
+
c: () => resolveCliConfigPaths,
|
|
57970
|
+
i: () => trailingSpaceCompletionToken,
|
|
57971
|
+
l: () => cliCommands,
|
|
57972
|
+
n: () => completionScript,
|
|
57973
|
+
o: () => formatConfigPaths,
|
|
57974
|
+
r: () => completion_exports,
|
|
57975
|
+
s: () => listCaplets,
|
|
57976
|
+
t: () => completeCliWords,
|
|
57977
|
+
u: () => completionShells
|
|
57978
|
+
});
|
|
57979
|
+
const completionShells = [
|
|
57980
|
+
"bash",
|
|
57981
|
+
"zsh",
|
|
57982
|
+
"fish",
|
|
57983
|
+
"powershell",
|
|
57984
|
+
"cmd"
|
|
57985
|
+
];
|
|
57986
|
+
const cliCommands = {
|
|
57987
|
+
completion: "completion",
|
|
57988
|
+
completeHidden: "__complete",
|
|
57989
|
+
serve: "serve",
|
|
57990
|
+
init: "init",
|
|
57991
|
+
list: "list",
|
|
57992
|
+
install: "install",
|
|
57993
|
+
add: "add",
|
|
57994
|
+
getCaplet: "get-caplet",
|
|
57995
|
+
checkBackend: "check-backend",
|
|
57996
|
+
listTools: "list-tools",
|
|
57997
|
+
searchTools: "search-tools",
|
|
57998
|
+
getTool: "get-tool",
|
|
57999
|
+
callTool: "call-tool",
|
|
58000
|
+
listResources: "list-resources",
|
|
58001
|
+
searchResources: "search-resources",
|
|
58002
|
+
listResourceTemplates: "list-resource-templates",
|
|
58003
|
+
readResource: "read-resource",
|
|
58004
|
+
listPrompts: "list-prompts",
|
|
58005
|
+
searchPrompts: "search-prompts",
|
|
58006
|
+
getPrompt: "get-prompt",
|
|
58007
|
+
complete: "complete",
|
|
58008
|
+
config: "config",
|
|
58009
|
+
auth: "auth"
|
|
58010
|
+
};
|
|
58011
|
+
const topLevelCommandNames = [
|
|
58012
|
+
cliCommands.serve,
|
|
58013
|
+
cliCommands.init,
|
|
58014
|
+
cliCommands.list,
|
|
58015
|
+
cliCommands.install,
|
|
58016
|
+
cliCommands.add,
|
|
58017
|
+
cliCommands.getCaplet,
|
|
58018
|
+
cliCommands.checkBackend,
|
|
58019
|
+
cliCommands.listTools,
|
|
58020
|
+
cliCommands.searchTools,
|
|
58021
|
+
cliCommands.getTool,
|
|
58022
|
+
cliCommands.callTool,
|
|
58023
|
+
cliCommands.listResources,
|
|
58024
|
+
cliCommands.searchResources,
|
|
58025
|
+
cliCommands.listResourceTemplates,
|
|
58026
|
+
cliCommands.readResource,
|
|
58027
|
+
cliCommands.listPrompts,
|
|
58028
|
+
cliCommands.searchPrompts,
|
|
58029
|
+
cliCommands.getPrompt,
|
|
58030
|
+
cliCommands.complete,
|
|
58031
|
+
cliCommands.config,
|
|
58032
|
+
cliCommands.auth,
|
|
58033
|
+
cliCommands.completion
|
|
58034
|
+
];
|
|
58035
|
+
const cliSubcommands = {
|
|
58036
|
+
[cliCommands.add]: [
|
|
58037
|
+
"cli",
|
|
58038
|
+
"mcp",
|
|
58039
|
+
"openapi",
|
|
58040
|
+
"graphql",
|
|
58041
|
+
"http"
|
|
58042
|
+
],
|
|
58043
|
+
[cliCommands.auth]: [
|
|
58044
|
+
"login",
|
|
58045
|
+
"logout",
|
|
58046
|
+
"list"
|
|
58047
|
+
],
|
|
58048
|
+
[cliCommands.completion]: [...completionShells],
|
|
58049
|
+
[cliCommands.config]: ["path", "paths"]
|
|
58050
|
+
};
|
|
58051
|
+
const capletIdCommands = new Set([
|
|
58052
|
+
cliCommands.getCaplet,
|
|
58053
|
+
cliCommands.checkBackend,
|
|
58054
|
+
cliCommands.listTools,
|
|
58055
|
+
cliCommands.searchTools,
|
|
58056
|
+
cliCommands.listResources,
|
|
58057
|
+
cliCommands.searchResources,
|
|
58058
|
+
cliCommands.listResourceTemplates,
|
|
58059
|
+
cliCommands.readResource,
|
|
58060
|
+
cliCommands.listPrompts,
|
|
58061
|
+
cliCommands.searchPrompts,
|
|
58062
|
+
cliCommands.complete
|
|
58063
|
+
]);
|
|
58064
|
+
const qualifiedToolCommands = new Set([cliCommands.getTool, cliCommands.callTool]);
|
|
58065
|
+
const qualifiedPromptCommands = new Set([cliCommands.getPrompt]);
|
|
58066
|
+
function listCaplets(configWithSources, options) {
|
|
58067
|
+
const { config, sources, shadows } = configWithSources;
|
|
58068
|
+
return allCaplets(config).filter((server) => options.includeDisabled || !server.disabled).map((server) => ({
|
|
58069
|
+
server: server.server,
|
|
58070
|
+
backend: server.backend,
|
|
58071
|
+
name: server.name,
|
|
58072
|
+
description: server.description,
|
|
58073
|
+
disabled: server.disabled,
|
|
58074
|
+
status: initialServerStatus(server),
|
|
58075
|
+
source: sources[server.server]?.kind ?? "unknown",
|
|
58076
|
+
path: sources[server.server]?.path ?? null,
|
|
58077
|
+
shadows: shadows[server.server] ?? []
|
|
58078
|
+
})).sort((left, right) => left.server.localeCompare(right.server));
|
|
58079
|
+
}
|
|
58080
|
+
function initialServerStatus(server) {
|
|
58081
|
+
return server.disabled ? "disabled" : "not_started";
|
|
58082
|
+
}
|
|
58083
|
+
function allCaplets(config) {
|
|
58084
|
+
return [
|
|
58085
|
+
...Object.values(config.mcpServers),
|
|
58086
|
+
...Object.values(config.openapiEndpoints),
|
|
58087
|
+
...Object.values(config.graphqlEndpoints),
|
|
58088
|
+
...Object.values(config.httpApis),
|
|
58089
|
+
...Object.values(config.cliTools)
|
|
58090
|
+
];
|
|
58091
|
+
}
|
|
58092
|
+
function formatCapletList(rows, format = "plain") {
|
|
58093
|
+
return format === "markdown" ? formatCapletListMarkdown(rows) : formatCapletListPlain(rows);
|
|
58094
|
+
}
|
|
58095
|
+
function formatCapletListMarkdown(rows) {
|
|
58096
|
+
if (rows.length === 0) return "## Configured Caplets\n\nNo configured Caplets found.\n";
|
|
58097
|
+
const heading = [
|
|
58098
|
+
"## Configured Caplets",
|
|
58099
|
+
"",
|
|
58100
|
+
`${rows.length} ${rows.length === 1 ? "Caplet" : "Caplets"} shown.`,
|
|
58101
|
+
""
|
|
58102
|
+
];
|
|
58103
|
+
const entries = rows.flatMap((row) => [
|
|
58104
|
+
`- \`${row.server}\` — ${row.name}`,
|
|
58105
|
+
` - Backend: ${row.backend}`,
|
|
58106
|
+
` - Status: ${row.status}`,
|
|
58107
|
+
` - Source: ${row.source}`,
|
|
58108
|
+
...row.disabled ? [" - Disabled: true"] : [],
|
|
58109
|
+
...row.path ? [` - Path: ${row.path}`] : []
|
|
58110
|
+
]);
|
|
58111
|
+
const warnings = rows.flatMap((row) => row.shadows.map((shadow) => `Warning: ${formatSourceKind(row.source)} Caplet ${row.server} shadows ${formatSourceKind(shadow.kind)} Caplet at ${shadow.path}`));
|
|
58112
|
+
if (warnings.length === 0) return `${[...heading, ...entries].join("\n")}\n`;
|
|
58113
|
+
return `${[
|
|
58114
|
+
...heading,
|
|
58115
|
+
...entries,
|
|
58116
|
+
"",
|
|
58117
|
+
"Warnings:",
|
|
58118
|
+
...warnings.map((warning) => `- ${warning}`)
|
|
58119
|
+
].join("\n")}\n`;
|
|
58120
|
+
}
|
|
58121
|
+
function formatCapletListPlain(rows) {
|
|
58122
|
+
if (rows.length === 0) return "No configured Caplets found.\n";
|
|
58123
|
+
const entries = rows.map((row) => [
|
|
58124
|
+
row.server,
|
|
58125
|
+
` Name: ${row.name}`,
|
|
58126
|
+
` Backend: ${row.backend}`,
|
|
58127
|
+
` Status: ${row.status}`,
|
|
58128
|
+
` Source: ${row.source}`,
|
|
58129
|
+
...row.disabled ? [" Disabled: true"] : [],
|
|
58130
|
+
...row.path ? [` Path: ${row.path}`] : []
|
|
58131
|
+
].join("\n")).join("\n\n");
|
|
58132
|
+
const warnings = rows.flatMap((row) => row.shadows.map((shadow) => `Warning: ${formatSourceKind(row.source)} Caplet ${row.server} shadows ${formatSourceKind(shadow.kind)} Caplet at ${shadow.path}`));
|
|
58133
|
+
if (warnings.length === 0) return `Configured Caplets (${rows.length})\n\n${entries}\n`;
|
|
58134
|
+
return `Configured Caplets (${rows.length})\n\n${entries}\n\n${warnings.join("\n")}\n`;
|
|
58135
|
+
}
|
|
58136
|
+
function formatSourceKind(kind) {
|
|
58137
|
+
if (kind.startsWith("project")) return "project";
|
|
58138
|
+
if (kind.startsWith("global")) return "global";
|
|
58139
|
+
return kind;
|
|
58140
|
+
}
|
|
58141
|
+
function resolveCliConfigPaths(envConfigPath, authDir) {
|
|
58142
|
+
const configPath = resolveConfigPath(envConfigPath);
|
|
58143
|
+
const effectiveAuthDir = authDir ?? DEFAULT_AUTH_DIR;
|
|
58144
|
+
return {
|
|
58145
|
+
userConfig: configPath,
|
|
58146
|
+
projectConfig: resolveProjectConfigPath(),
|
|
58147
|
+
userRoot: resolveCapletsRoot(configPath),
|
|
58148
|
+
stateRoot: dirname(effectiveAuthDir),
|
|
58149
|
+
projectRoot: resolveProjectCapletsRoot(),
|
|
58150
|
+
authDir: effectiveAuthDir,
|
|
58151
|
+
envConfig: envConfigPath ?? null
|
|
58152
|
+
};
|
|
58153
|
+
}
|
|
58154
|
+
function formatConfigPaths(paths, format = "plain") {
|
|
58155
|
+
if (format === "markdown") return formatConfigPathsMarkdown(paths);
|
|
58156
|
+
return formatConfigPathsPlain(paths);
|
|
58157
|
+
}
|
|
58158
|
+
function formatConfigPathsMarkdown(paths) {
|
|
58159
|
+
return [
|
|
58160
|
+
"## Caplets paths",
|
|
58161
|
+
"",
|
|
58162
|
+
`- User config: ${paths.userConfig}`,
|
|
58163
|
+
`- Project config: ${paths.projectConfig}`,
|
|
58164
|
+
`- User Caplets root: ${paths.userRoot}`,
|
|
58165
|
+
`- State root: ${paths.stateRoot}`,
|
|
58166
|
+
`- Project Caplets root: ${paths.projectRoot}`,
|
|
58167
|
+
`- Auth directory: ${paths.authDir}`,
|
|
58168
|
+
`- CAPLETS_CONFIG: ${paths.envConfig ?? "unset"}`
|
|
58169
|
+
].join("\n") + "\n";
|
|
58170
|
+
}
|
|
58171
|
+
function formatConfigPathsPlain(paths) {
|
|
58172
|
+
return [
|
|
58173
|
+
"Caplets paths",
|
|
58174
|
+
"",
|
|
58175
|
+
`User config: ${paths.userConfig}`,
|
|
58176
|
+
`Project config: ${paths.projectConfig}`,
|
|
58177
|
+
`User root: ${paths.userRoot}`,
|
|
58178
|
+
`State root: ${paths.stateRoot}`,
|
|
58179
|
+
`Project root: ${paths.projectRoot}`,
|
|
58180
|
+
`Auth directory: ${paths.authDir}`,
|
|
58181
|
+
`CAPLETS_CONFIG: ${paths.envConfig ?? "unset"}`
|
|
58182
|
+
].join("\n") + "\n";
|
|
58183
|
+
}
|
|
58184
|
+
function completionCacheKey(input) {
|
|
58185
|
+
return createHash("sha256").update(JSON.stringify(input)).digest("hex");
|
|
58186
|
+
}
|
|
58187
|
+
function readCompletionCacheEntry(cacheDir, key, now = Date.now()) {
|
|
58188
|
+
try {
|
|
58189
|
+
const parsed = JSON.parse(readFileSync(cachePath(cacheDir, key), "utf8"));
|
|
58190
|
+
if (parsed.status === "positive" && Array.isArray(parsed.candidates)) return {
|
|
58191
|
+
...parsed,
|
|
58192
|
+
fresh: now <= parsed.expiresAt
|
|
58193
|
+
};
|
|
58194
|
+
if (parsed.status === "negative" && typeof parsed.reason === "string") return {
|
|
58195
|
+
...parsed,
|
|
58196
|
+
fresh: now <= parsed.expiresAt
|
|
58197
|
+
};
|
|
58198
|
+
} catch {
|
|
58199
|
+
return;
|
|
58200
|
+
}
|
|
58201
|
+
}
|
|
58202
|
+
function writeCompletionCacheEntry(cacheDir, key, entry) {
|
|
58203
|
+
mkdirSync(cacheDir, { recursive: true });
|
|
58204
|
+
const path = cachePath(cacheDir, key);
|
|
58205
|
+
const tempPath = `${path}.${process.pid}.tmp`;
|
|
58206
|
+
writeFileSync(tempPath, JSON.stringify(entry), { mode: 384 });
|
|
58207
|
+
renameSync(tempPath, path);
|
|
58208
|
+
}
|
|
58209
|
+
function cachePath(cacheDir, key) {
|
|
58210
|
+
return join(cacheDir, `${key}.json`);
|
|
58211
|
+
}
|
|
58212
|
+
async function discoverCompletionCandidates(serverId, kind, options) {
|
|
58213
|
+
const server = enabledServer(serverId, options.config);
|
|
58214
|
+
if (!server) return [];
|
|
58215
|
+
const completion = options.completion ?? options.config.options.completion;
|
|
58216
|
+
const now = options.now ?? Date.now();
|
|
58217
|
+
const configCandidates = configDefinedCandidates(serverId, kind, options.config);
|
|
58218
|
+
const cacheDir = options.cacheDir ?? DEFAULT_COMPLETION_CACHE_DIR;
|
|
58219
|
+
const key = completionCacheKey({
|
|
58220
|
+
server: server.server,
|
|
58221
|
+
backend: server.backend,
|
|
58222
|
+
kind,
|
|
58223
|
+
fingerprint: completionFingerprint(server, kind, completion)
|
|
58224
|
+
});
|
|
58225
|
+
const cached = readCompletionCacheEntry(cacheDir, key, now);
|
|
58226
|
+
if (cached?.status === "positive" && cached.fresh) return cached.candidates;
|
|
58227
|
+
if (cached?.status === "negative" && cached.fresh) return cached.candidates ?? configCandidates;
|
|
58228
|
+
try {
|
|
58229
|
+
const live = await withTimeout(liveCandidates(server, kind, options.managers), Math.min(completion.discoveryTimeoutMs, completion.overallTimeoutMs));
|
|
58230
|
+
const candidates = dedupeCandidates([...configCandidates, ...live]);
|
|
58231
|
+
writeCompletionCacheEntry(cacheDir, key, {
|
|
58232
|
+
status: "positive",
|
|
58233
|
+
fetchedAt: now,
|
|
58234
|
+
expiresAt: now + completion.cacheTtlMs,
|
|
58235
|
+
candidates
|
|
58236
|
+
});
|
|
58237
|
+
return candidates;
|
|
58238
|
+
} catch (error) {
|
|
58239
|
+
writeCompletionCacheEntry(cacheDir, key, {
|
|
58240
|
+
status: "negative",
|
|
58241
|
+
fetchedAt: now,
|
|
58242
|
+
expiresAt: now + completion.negativeCacheTtlMs,
|
|
58243
|
+
reason: negativeReason(error),
|
|
58244
|
+
...cached?.status === "positive" ? { candidates: cached.candidates } : {}
|
|
58245
|
+
});
|
|
58246
|
+
if (cached?.status === "positive") return cached.candidates;
|
|
58247
|
+
return configCandidates;
|
|
58248
|
+
}
|
|
58249
|
+
}
|
|
58250
|
+
function configDefinedCandidates(serverId, kind, config) {
|
|
58251
|
+
if (kind !== "tools") return [];
|
|
58252
|
+
const cli = config.cliTools[serverId];
|
|
58253
|
+
if (cli && !cli.disabled) return Object.keys(cli.actions).map((name) => ({ value: `${serverId}.${name}` }));
|
|
58254
|
+
const http = config.httpApis[serverId];
|
|
58255
|
+
if (http && !http.disabled) return Object.keys(http.actions).map((name) => ({ value: `${serverId}.${name}` }));
|
|
58256
|
+
const graphql = config.graphqlEndpoints[serverId];
|
|
58257
|
+
if (graphql && !graphql.disabled && graphql.operations) return Object.keys(graphql.operations).map((name) => ({ value: `${serverId}.${name}` }));
|
|
58258
|
+
return [];
|
|
58259
|
+
}
|
|
58260
|
+
async function liveCandidates(server, kind, managers) {
|
|
58261
|
+
if (kind === "tools" && managers?.listTools) return (await managers.listTools(server)).map((tool) => ({
|
|
58262
|
+
value: `${server.server}.${tool.name}`,
|
|
58263
|
+
description: tool.description
|
|
58264
|
+
}));
|
|
58265
|
+
if (kind === "tools") return [];
|
|
58266
|
+
if (server.backend !== "mcp") return [];
|
|
58267
|
+
if (kind === "prompts" && managers?.listPrompts) return (await managers.listPrompts(server)).map((prompt) => ({
|
|
58268
|
+
value: `${server.server}.${prompt.name}`,
|
|
58269
|
+
description: prompt.description
|
|
58270
|
+
}));
|
|
58271
|
+
if (kind === "resources" && managers?.listResources) return (await managers.listResources(server)).map((resource) => ({
|
|
58272
|
+
value: resource.uri,
|
|
58273
|
+
label: resource.name,
|
|
58274
|
+
description: resource.description
|
|
58275
|
+
}));
|
|
58276
|
+
if (kind === "resourceTemplates" && managers?.listResourceTemplates) return (await managers.listResourceTemplates(server)).map((template) => ({
|
|
58277
|
+
value: template.uriTemplate,
|
|
58278
|
+
label: template.name,
|
|
58279
|
+
description: template.description
|
|
58280
|
+
}));
|
|
58281
|
+
throw new CapletsError("UNSUPPORTED_CAPABILITY", `Completion discovery is unsupported for ${kind}`);
|
|
58282
|
+
}
|
|
58283
|
+
function completionFingerprint(server, kind, completion) {
|
|
58284
|
+
return JSON.stringify({
|
|
58285
|
+
kind,
|
|
58286
|
+
completion: {
|
|
58287
|
+
discoveryTimeoutMs: completion.discoveryTimeoutMs,
|
|
58288
|
+
cacheTtlMs: completion.cacheTtlMs,
|
|
58289
|
+
negativeCacheTtlMs: completion.negativeCacheTtlMs
|
|
58290
|
+
},
|
|
58291
|
+
server: secretFreeServerShape(server)
|
|
58292
|
+
});
|
|
58293
|
+
}
|
|
58294
|
+
function secretFreeServerShape(server) {
|
|
58295
|
+
const base = {
|
|
58296
|
+
server: server.server,
|
|
58297
|
+
backend: server.backend,
|
|
58298
|
+
name: server.name,
|
|
58299
|
+
description: server.description,
|
|
58300
|
+
tags: server.tags,
|
|
58301
|
+
disabled: server.disabled
|
|
58302
|
+
};
|
|
58303
|
+
switch (server.backend) {
|
|
58304
|
+
case "mcp": return {
|
|
58305
|
+
...base,
|
|
58306
|
+
transport: server.transport,
|
|
58307
|
+
command: server.command,
|
|
58308
|
+
args: server.args,
|
|
58309
|
+
cwd: server.cwd,
|
|
58310
|
+
url: server.url,
|
|
58311
|
+
authType: server.auth?.type,
|
|
58312
|
+
startupTimeoutMs: server.startupTimeoutMs,
|
|
58313
|
+
callTimeoutMs: server.callTimeoutMs
|
|
58314
|
+
};
|
|
58315
|
+
case "openapi": return {
|
|
58316
|
+
...base,
|
|
58317
|
+
specPath: server.specPath,
|
|
58318
|
+
specUrl: server.specUrl,
|
|
58319
|
+
baseUrl: server.baseUrl,
|
|
58320
|
+
authType: server.auth.type,
|
|
58321
|
+
requestTimeoutMs: server.requestTimeoutMs
|
|
58322
|
+
};
|
|
58323
|
+
case "graphql": return {
|
|
58324
|
+
...base,
|
|
58325
|
+
endpointUrl: server.endpointUrl,
|
|
58326
|
+
schemaPath: server.schemaPath,
|
|
58327
|
+
schemaUrl: server.schemaUrl,
|
|
58328
|
+
authType: server.auth.type,
|
|
58329
|
+
operationNames: server.operations ? Object.keys(server.operations) : void 0
|
|
58330
|
+
};
|
|
58331
|
+
case "http": return {
|
|
58332
|
+
...base,
|
|
58333
|
+
baseUrl: server.baseUrl,
|
|
58334
|
+
authType: server.auth.type,
|
|
58335
|
+
actions: Object.fromEntries(Object.entries(server.actions).map(([name, action]) => [name, {
|
|
58336
|
+
method: action.method,
|
|
58337
|
+
path: action.path
|
|
58338
|
+
}])),
|
|
58339
|
+
requestTimeoutMs: server.requestTimeoutMs
|
|
58340
|
+
};
|
|
58341
|
+
case "cli": return {
|
|
58342
|
+
...base,
|
|
58343
|
+
cwd: server.cwd,
|
|
58344
|
+
actions: Object.fromEntries(Object.entries(server.actions).map(([name, action]) => [name, {
|
|
58345
|
+
command: action.command,
|
|
58346
|
+
args: action.args,
|
|
58347
|
+
cwd: action.cwd
|
|
58348
|
+
}])),
|
|
58349
|
+
timeoutMs: server.timeoutMs,
|
|
58350
|
+
maxOutputBytes: server.maxOutputBytes
|
|
58351
|
+
};
|
|
58352
|
+
case "caplets": return {
|
|
58353
|
+
...base,
|
|
58354
|
+
configPath: server.configPath,
|
|
58355
|
+
capletsRoot: server.capletsRoot,
|
|
58356
|
+
defaultSearchLimit: server.defaultSearchLimit,
|
|
58357
|
+
maxSearchLimit: server.maxSearchLimit
|
|
58358
|
+
};
|
|
58359
|
+
}
|
|
58360
|
+
}
|
|
58361
|
+
function negativeReason(error) {
|
|
58362
|
+
if (error instanceof CapletsError) {
|
|
58363
|
+
if (error.code === "AUTH_REQUIRED" || error.code === "AUTH_FAILED" || error.code === "AUTH_REFRESH_FAILED") return "auth_required";
|
|
58364
|
+
if (error.code === "SERVER_UNAVAILABLE" || error.code === "SERVER_START_TIMEOUT") return "unavailable";
|
|
58365
|
+
if (error.code === "UNSUPPORTED_CAPABILITY" || error.code === "UNSUPPORTED_OPERATION") return "unsupported";
|
|
58366
|
+
if (error.code === "TOOL_CALL_TIMEOUT" || error.code === "DOWNSTREAM_COMPLETION_ERROR") return "timeout";
|
|
58367
|
+
}
|
|
58368
|
+
return error instanceof Error && error.message.includes("timeout") ? "timeout" : "error";
|
|
58369
|
+
}
|
|
58370
|
+
async function withTimeout(promise, timeoutMs) {
|
|
58371
|
+
let timeout;
|
|
58372
|
+
try {
|
|
58373
|
+
return await Promise.race([promise, new Promise((_, reject) => {
|
|
58374
|
+
timeout = setTimeout(() => reject(/* @__PURE__ */ new Error("completion discovery timeout")), timeoutMs);
|
|
58375
|
+
})]);
|
|
58376
|
+
} finally {
|
|
58377
|
+
if (timeout) clearTimeout(timeout);
|
|
58378
|
+
}
|
|
58379
|
+
}
|
|
58380
|
+
function enabledServer(serverId, config) {
|
|
58381
|
+
const server = config.mcpServers[serverId] ?? config.openapiEndpoints[serverId] ?? config.graphqlEndpoints[serverId] ?? config.httpApis[serverId] ?? config.cliTools[serverId] ?? config.capletSets[serverId];
|
|
58382
|
+
return server && !server.disabled ? server : void 0;
|
|
58383
|
+
}
|
|
58384
|
+
function dedupeCandidates(candidates) {
|
|
58385
|
+
const seen = /* @__PURE__ */ new Set();
|
|
58386
|
+
return candidates.filter((candidate) => {
|
|
58387
|
+
if (seen.has(candidate.value)) return false;
|
|
58388
|
+
seen.add(candidate.value);
|
|
58389
|
+
return true;
|
|
58390
|
+
});
|
|
58391
|
+
}
|
|
58392
|
+
var completion_exports = /* @__PURE__ */ __exportAll({
|
|
58393
|
+
completeCliWords: () => completeCliWords,
|
|
58394
|
+
completionScript: () => completionScript,
|
|
58395
|
+
trailingSpaceCompletionToken: () => trailingSpaceCompletionToken
|
|
58396
|
+
});
|
|
58397
|
+
const trailingSpaceCompletionToken = "__CAPLETS_TRAILING_SPACE__";
|
|
58398
|
+
const optionValueSuggestions = {
|
|
58399
|
+
"*": { "--format": [
|
|
58400
|
+
"markdown",
|
|
58401
|
+
"md",
|
|
58402
|
+
"plain",
|
|
58403
|
+
"json"
|
|
58404
|
+
] },
|
|
58405
|
+
serve: { "--transport": ["stdio", "http"] },
|
|
58406
|
+
"add:mcp": { "--transport": ["http", "sse"] },
|
|
58407
|
+
"add:cli": { "--include": [
|
|
58408
|
+
"git",
|
|
58409
|
+
"gh",
|
|
58410
|
+
"package"
|
|
58411
|
+
] }
|
|
58412
|
+
};
|
|
58413
|
+
function completionScript(shell) {
|
|
58414
|
+
switch (shell) {
|
|
58415
|
+
case "bash": return bashCompletionScript();
|
|
58416
|
+
case "zsh": return zshCompletionScript();
|
|
58417
|
+
case "fish": return fishCompletionScript();
|
|
58418
|
+
case "powershell": return powershellCompletionScript();
|
|
58419
|
+
case "cmd": return cmdCompletionScript();
|
|
58420
|
+
default: throw new CapletsError("REQUEST_INVALID", "completion shell must be bash, zsh, fish, powershell, or cmd");
|
|
58421
|
+
}
|
|
58422
|
+
}
|
|
58423
|
+
async function completeCliWords(words, options = {}) {
|
|
58424
|
+
try {
|
|
58425
|
+
const normalized = words.length === 0 ? [""] : words;
|
|
58426
|
+
const current = normalized.at(-1) ?? "";
|
|
58427
|
+
const previous = normalized.at(-2);
|
|
58428
|
+
const command = normalized[0] ?? "";
|
|
58429
|
+
const subcommand = normalized[1] ?? "";
|
|
58430
|
+
if (command === cliCommands.complete && previous === "--prompt" && subcommand) return prefixFilter((await discoverCompletionCandidates(subcommand, "prompts", discoveryOptions(options))).map((candidate) => candidate.value.replace(`${subcommand}.`, "")), current);
|
|
58431
|
+
if (command === cliCommands.complete && previous === "--resource-template" && subcommand) return prefixFilter((await discoverCompletionCandidates(subcommand, "resourceTemplates", discoveryOptions(options))).map((candidate) => candidate.value), current);
|
|
58432
|
+
const optionValues = suggestionsForOptionValue(command, subcommand, previous);
|
|
58433
|
+
if (optionValues) return prefixFilter(optionValues, current);
|
|
58434
|
+
if (normalized.length === 1) return prefixFilter([...topLevelCommandNames], current);
|
|
58435
|
+
if (normalized.length === 2 && command in cliSubcommands) return prefixFilter(cliSubcommands[command], current);
|
|
58436
|
+
if (normalized.length === 2 && capletIdCommands.has(command)) return prefixFilter(promptResourceCommands.has(command) ? configuredCapletIds(options, { backend: "mcp" }) : configuredCapletIds(options), current);
|
|
58437
|
+
if (normalized.length === 2 && (qualifiedToolCommands.has(command) || qualifiedPromptCommands.has(command))) {
|
|
58438
|
+
if (current.includes(".")) return prefixFilter((await discoverCompletionCandidates(current.slice(0, current.indexOf(".")), qualifiedToolCommands.has(command) ? "tools" : "prompts", discoveryOptions(options))).map((candidate) => candidate.value), current);
|
|
58439
|
+
return prefixFilter(configuredCapletIds(options, qualifiedPromptCommands.has(command) ? { backend: "mcp" } : void 0).map((id) => `${id}.`), current);
|
|
58440
|
+
}
|
|
58441
|
+
if (command === cliCommands.readResource && normalized.length === 3) return prefixFilter((await discoverCompletionCandidates(subcommand, "resources", discoveryOptions(options))).map((candidate) => candidate.value), current);
|
|
58442
|
+
if (command === cliCommands.auth && ["login", "logout"].includes(subcommand) && normalized.length === 3) return prefixFilter(configuredCapletIds(options), current);
|
|
58443
|
+
return [];
|
|
58444
|
+
} catch {
|
|
58445
|
+
return [];
|
|
58446
|
+
}
|
|
58447
|
+
}
|
|
58448
|
+
function suggestionsForOptionValue(command, subcommand, previous) {
|
|
58449
|
+
if (!previous) return void 0;
|
|
58450
|
+
return optionValueSuggestions[`${command}:${subcommand}`]?.[previous] ?? optionValueSuggestions[command]?.[previous] ?? optionValueSuggestions["*"]?.[previous];
|
|
58451
|
+
}
|
|
58452
|
+
const promptResourceCommands = new Set([
|
|
58453
|
+
cliCommands.getPrompt,
|
|
58454
|
+
cliCommands.readResource,
|
|
58455
|
+
cliCommands.complete
|
|
58456
|
+
]);
|
|
58457
|
+
function configuredCapletIds(options, filter = {}) {
|
|
58458
|
+
return listCaplets(options.config ? {
|
|
58459
|
+
config: options.config,
|
|
58460
|
+
sources: {},
|
|
58461
|
+
shadows: {}
|
|
58462
|
+
} : loadConfigWithSources(options.configPath, options.projectConfigPath), { includeDisabled: false }).filter((row) => !filter.backend || row.backend === filter.backend).map((row) => row.server);
|
|
58463
|
+
}
|
|
58464
|
+
function discoveryOptions(options) {
|
|
58465
|
+
return {
|
|
58466
|
+
config: options.config ?? loadConfigWithSources(options.configPath, options.projectConfigPath).config,
|
|
58467
|
+
completion: options.completion,
|
|
58468
|
+
cacheDir: options.cacheDir,
|
|
58469
|
+
managers: options.managers
|
|
58470
|
+
};
|
|
58471
|
+
}
|
|
58472
|
+
function prefixFilter(values, prefix) {
|
|
58473
|
+
return values.filter((value) => value.startsWith(prefix));
|
|
58474
|
+
}
|
|
58475
|
+
function bashCompletionScript() {
|
|
58476
|
+
return `# caplets bash completion
|
|
58477
|
+
_caplets_completions() {
|
|
58478
|
+
local IFS=$'\n'
|
|
58479
|
+
COMPREPLY=( $(caplets __complete --shell bash -- "\${COMP_WORDS[@]:1}" 2>/dev/null) )
|
|
58480
|
+
}
|
|
58481
|
+
complete -o default -F _caplets_completions caplets
|
|
58482
|
+
`;
|
|
58483
|
+
}
|
|
58484
|
+
function zshCompletionScript() {
|
|
58485
|
+
return `#compdef caplets
|
|
58486
|
+
_caplets() {
|
|
58487
|
+
local -a suggestions
|
|
58488
|
+
suggestions=("\${(@f)$(caplets __complete --shell zsh -- "\${words[@]:1}" 2>/dev/null)}")
|
|
58489
|
+
compadd -- $suggestions
|
|
58490
|
+
}
|
|
58491
|
+
_caplets "$@"
|
|
58492
|
+
`;
|
|
58493
|
+
}
|
|
58494
|
+
function fishCompletionScript() {
|
|
58495
|
+
return `# caplets fish completion
|
|
58496
|
+
function __caplets_complete
|
|
58497
|
+
set -l tokens (commandline -opc)
|
|
58498
|
+
set -l current (commandline -ct)
|
|
58499
|
+
caplets __complete --shell fish -- $tokens[2..-1] $current 2>/dev/null
|
|
58500
|
+
end
|
|
58501
|
+
complete -c caplets -f -a '(__caplets_complete)'
|
|
58502
|
+
`;
|
|
58503
|
+
}
|
|
58504
|
+
function powershellCompletionScript() {
|
|
58505
|
+
return `# caplets PowerShell completion
|
|
58506
|
+
Register-ArgumentCompleter -Native -CommandName caplets -ScriptBlock {
|
|
58507
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
58508
|
+
$tokens = @($commandAst.CommandElements | Select-Object -Skip 1 | ForEach-Object { $_.ToString() })
|
|
58509
|
+
if ($tokens.Count -eq 0 -or $commandAst.Extent.Text.EndsWith(' ')) { $tokens += '${trailingSpaceCompletionToken}' }
|
|
58510
|
+
caplets __complete --shell powershell -- @tokens 2>$null | ForEach-Object {
|
|
58511
|
+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
|
|
58512
|
+
}
|
|
58513
|
+
}
|
|
58514
|
+
`;
|
|
58515
|
+
}
|
|
58516
|
+
function cmdCompletionScript() {
|
|
58517
|
+
return `@echo off
|
|
58518
|
+
REM caplets cmd completion helper
|
|
58519
|
+
REM cmd.exe has no native programmable completion API. This doskey macro prints suggestions for the current words.
|
|
58520
|
+
doskey caplets-complete=caplets __complete --shell cmd -- $* 2^>nul
|
|
58521
|
+
REM Usage: caplets-complete get-caplet
|
|
58522
|
+
`;
|
|
58523
|
+
}
|
|
58524
|
+
//#endregion
|
|
57479
58525
|
//#region ../core/dist/index.js
|
|
57480
58526
|
/**
|
|
57481
58527
|
* Experimental server task features for MCP SDK.
|
|
@@ -58773,7 +59819,7 @@ const EMPTY_COMPLETION_RESULT = { completion: {
|
|
|
58773
59819
|
values: [],
|
|
58774
59820
|
hasMore: false
|
|
58775
59821
|
} };
|
|
58776
|
-
var version$1 = "0.
|
|
59822
|
+
var version$1 = "0.18.1";
|
|
58777
59823
|
var CapletsMcpSession = class {
|
|
58778
59824
|
engine;
|
|
58779
59825
|
server;
|
|
@@ -58815,6 +59861,7 @@ var CapletsMcpSession = class {
|
|
|
58815
59861
|
if (!previousCaplet || serializeCaplet(previousCaplet) !== serializeCaplet(caplet)) tool.update({
|
|
58816
59862
|
title: caplet.name,
|
|
58817
59863
|
description: capabilityDescription(caplet),
|
|
59864
|
+
paramsSchema: generatedToolInputSchemaForCaplet(caplet).shape,
|
|
58818
59865
|
callback: async (request) => this.handleTool(serverId, request),
|
|
58819
59866
|
enabled: true
|
|
58820
59867
|
});
|
|
@@ -58828,7 +59875,7 @@ var CapletsMcpSession = class {
|
|
|
58828
59875
|
return this.server.registerTool(caplet.server, {
|
|
58829
59876
|
title: caplet.name,
|
|
58830
59877
|
description: capabilityDescription(caplet),
|
|
58831
|
-
inputSchema:
|
|
59878
|
+
inputSchema: generatedToolInputSchemaForCaplet(caplet).shape
|
|
58832
59879
|
}, async (request) => this.handleTool(caplet.server, request));
|
|
58833
59880
|
}
|
|
58834
59881
|
async handleTool(serverId, request) {
|
|
@@ -62424,124 +63471,6 @@ function starterConfig() {
|
|
|
62424
63471
|
} }
|
|
62425
63472
|
}, null, 2);
|
|
62426
63473
|
}
|
|
62427
|
-
function listCaplets(configWithSources, options) {
|
|
62428
|
-
const { config, sources, shadows } = configWithSources;
|
|
62429
|
-
return allCaplets(config).filter((server) => options.includeDisabled || !server.disabled).map((server) => ({
|
|
62430
|
-
server: server.server,
|
|
62431
|
-
backend: server.backend,
|
|
62432
|
-
name: server.name,
|
|
62433
|
-
description: server.description,
|
|
62434
|
-
disabled: server.disabled,
|
|
62435
|
-
status: initialServerStatus(server),
|
|
62436
|
-
source: sources[server.server]?.kind ?? "unknown",
|
|
62437
|
-
path: sources[server.server]?.path ?? null,
|
|
62438
|
-
shadows: shadows[server.server] ?? []
|
|
62439
|
-
})).sort((left, right) => left.server.localeCompare(right.server));
|
|
62440
|
-
}
|
|
62441
|
-
function initialServerStatus(server) {
|
|
62442
|
-
return server.disabled ? "disabled" : "not_started";
|
|
62443
|
-
}
|
|
62444
|
-
function allCaplets(config) {
|
|
62445
|
-
return [
|
|
62446
|
-
...Object.values(config.mcpServers),
|
|
62447
|
-
...Object.values(config.openapiEndpoints),
|
|
62448
|
-
...Object.values(config.graphqlEndpoints),
|
|
62449
|
-
...Object.values(config.httpApis),
|
|
62450
|
-
...Object.values(config.cliTools)
|
|
62451
|
-
];
|
|
62452
|
-
}
|
|
62453
|
-
function formatCapletList(rows, format = "plain") {
|
|
62454
|
-
return format === "markdown" ? formatCapletListMarkdown(rows) : formatCapletListPlain(rows);
|
|
62455
|
-
}
|
|
62456
|
-
function formatCapletListMarkdown(rows) {
|
|
62457
|
-
if (rows.length === 0) return "## Configured Caplets\n\nNo configured Caplets found.\n";
|
|
62458
|
-
const heading = [
|
|
62459
|
-
"## Configured Caplets",
|
|
62460
|
-
"",
|
|
62461
|
-
`${rows.length} ${rows.length === 1 ? "Caplet" : "Caplets"} shown.`,
|
|
62462
|
-
""
|
|
62463
|
-
];
|
|
62464
|
-
const entries = rows.flatMap((row) => [
|
|
62465
|
-
`- \`${row.server}\` — ${row.name}`,
|
|
62466
|
-
` - Backend: ${row.backend}`,
|
|
62467
|
-
` - Status: ${row.status}`,
|
|
62468
|
-
` - Source: ${row.source}`,
|
|
62469
|
-
...row.disabled ? [" - Disabled: true"] : [],
|
|
62470
|
-
...row.path ? [` - Path: ${row.path}`] : []
|
|
62471
|
-
]);
|
|
62472
|
-
const warnings = rows.flatMap((row) => row.shadows.map((shadow) => `Warning: ${formatSourceKind(row.source)} Caplet ${row.server} shadows ${formatSourceKind(shadow.kind)} Caplet at ${shadow.path}`));
|
|
62473
|
-
if (warnings.length === 0) return `${[...heading, ...entries].join("\n")}\n`;
|
|
62474
|
-
return `${[
|
|
62475
|
-
...heading,
|
|
62476
|
-
...entries,
|
|
62477
|
-
"",
|
|
62478
|
-
"Warnings:",
|
|
62479
|
-
...warnings.map((warning) => `- ${warning}`)
|
|
62480
|
-
].join("\n")}\n`;
|
|
62481
|
-
}
|
|
62482
|
-
function formatCapletListPlain(rows) {
|
|
62483
|
-
if (rows.length === 0) return "No configured Caplets found.\n";
|
|
62484
|
-
const entries = rows.map((row) => [
|
|
62485
|
-
row.server,
|
|
62486
|
-
` Name: ${row.name}`,
|
|
62487
|
-
` Backend: ${row.backend}`,
|
|
62488
|
-
` Status: ${row.status}`,
|
|
62489
|
-
` Source: ${row.source}`,
|
|
62490
|
-
...row.disabled ? [" Disabled: true"] : [],
|
|
62491
|
-
...row.path ? [` Path: ${row.path}`] : []
|
|
62492
|
-
].join("\n")).join("\n\n");
|
|
62493
|
-
const warnings = rows.flatMap((row) => row.shadows.map((shadow) => `Warning: ${formatSourceKind(row.source)} Caplet ${row.server} shadows ${formatSourceKind(shadow.kind)} Caplet at ${shadow.path}`));
|
|
62494
|
-
if (warnings.length === 0) return `Configured Caplets (${rows.length})\n\n${entries}\n`;
|
|
62495
|
-
return `Configured Caplets (${rows.length})\n\n${entries}\n\n${warnings.join("\n")}\n`;
|
|
62496
|
-
}
|
|
62497
|
-
function formatSourceKind(kind) {
|
|
62498
|
-
if (kind.startsWith("project")) return "project";
|
|
62499
|
-
if (kind.startsWith("global")) return "global";
|
|
62500
|
-
return kind;
|
|
62501
|
-
}
|
|
62502
|
-
function resolveCliConfigPaths(envConfigPath, authDir) {
|
|
62503
|
-
const configPath = resolveConfigPath(envConfigPath);
|
|
62504
|
-
const effectiveAuthDir = authDir ?? DEFAULT_AUTH_DIR;
|
|
62505
|
-
return {
|
|
62506
|
-
userConfig: configPath,
|
|
62507
|
-
projectConfig: resolveProjectConfigPath(),
|
|
62508
|
-
userRoot: resolveCapletsRoot(configPath),
|
|
62509
|
-
stateRoot: dirname(effectiveAuthDir),
|
|
62510
|
-
projectRoot: resolveProjectCapletsRoot(),
|
|
62511
|
-
authDir: effectiveAuthDir,
|
|
62512
|
-
envConfig: envConfigPath ?? null
|
|
62513
|
-
};
|
|
62514
|
-
}
|
|
62515
|
-
function formatConfigPaths(paths, format = "plain") {
|
|
62516
|
-
if (format === "markdown") return formatConfigPathsMarkdown(paths);
|
|
62517
|
-
return formatConfigPathsPlain(paths);
|
|
62518
|
-
}
|
|
62519
|
-
function formatConfigPathsMarkdown(paths) {
|
|
62520
|
-
return [
|
|
62521
|
-
"## Caplets paths",
|
|
62522
|
-
"",
|
|
62523
|
-
`- User config: ${paths.userConfig}`,
|
|
62524
|
-
`- Project config: ${paths.projectConfig}`,
|
|
62525
|
-
`- User Caplets root: ${paths.userRoot}`,
|
|
62526
|
-
`- State root: ${paths.stateRoot}`,
|
|
62527
|
-
`- Project Caplets root: ${paths.projectRoot}`,
|
|
62528
|
-
`- Auth directory: ${paths.authDir}`,
|
|
62529
|
-
`- CAPLETS_CONFIG: ${paths.envConfig ?? "unset"}`
|
|
62530
|
-
].join("\n") + "\n";
|
|
62531
|
-
}
|
|
62532
|
-
function formatConfigPathsPlain(paths) {
|
|
62533
|
-
return [
|
|
62534
|
-
"Caplets paths",
|
|
62535
|
-
"",
|
|
62536
|
-
`User config: ${paths.userConfig}`,
|
|
62537
|
-
`Project config: ${paths.projectConfig}`,
|
|
62538
|
-
`User root: ${paths.userRoot}`,
|
|
62539
|
-
`State root: ${paths.stateRoot}`,
|
|
62540
|
-
`Project root: ${paths.projectRoot}`,
|
|
62541
|
-
`Auth directory: ${paths.authDir}`,
|
|
62542
|
-
`CAPLETS_CONFIG: ${paths.envConfig ?? "unset"}`
|
|
62543
|
-
].join("\n") + "\n";
|
|
62544
|
-
}
|
|
62545
63474
|
function installCaplets(repo, options = {}) {
|
|
62546
63475
|
const source = resolveInstallSource(repo);
|
|
62547
63476
|
try {
|
|
@@ -63895,7 +64824,7 @@ var Hono$1 = class _Hono {
|
|
|
63895
64824
|
handler = async (c, next) => (await compose([], app.errorHandler)(c, () => r.handler(c, next))).res;
|
|
63896
64825
|
handler[COMPOSED_HANDLER] = r.handler;
|
|
63897
64826
|
}
|
|
63898
|
-
subApp.#addRoute(r.method, r.path, handler);
|
|
64827
|
+
subApp.#addRoute(r.method, r.path, handler, r.basePath);
|
|
63899
64828
|
});
|
|
63900
64829
|
return this;
|
|
63901
64830
|
}
|
|
@@ -64012,7 +64941,7 @@ var Hono$1 = class _Hono {
|
|
|
64012
64941
|
const pathPrefixLength = mergedPath === "/" ? 0 : mergedPath.length;
|
|
64013
64942
|
return (request) => {
|
|
64014
64943
|
const url = new URL(request.url);
|
|
64015
|
-
url.pathname =
|
|
64944
|
+
url.pathname = this.getPath(request).slice(pathPrefixLength) || "/";
|
|
64016
64945
|
return new Request(url, request);
|
|
64017
64946
|
};
|
|
64018
64947
|
})();
|
|
@@ -64024,11 +64953,11 @@ var Hono$1 = class _Hono {
|
|
|
64024
64953
|
this.#addRoute("ALL", mergePath(path, "*"), handler);
|
|
64025
64954
|
return this;
|
|
64026
64955
|
}
|
|
64027
|
-
#addRoute(method, path, handler) {
|
|
64956
|
+
#addRoute(method, path, handler, baseRoutePath) {
|
|
64028
64957
|
method = method.toUpperCase();
|
|
64029
64958
|
path = mergePath(this._basePath, path);
|
|
64030
64959
|
const r = {
|
|
64031
|
-
basePath: this._basePath,
|
|
64960
|
+
basePath: baseRoutePath !== void 0 ? mergePath(this._basePath, baseRoutePath) : this._basePath,
|
|
64032
64961
|
path,
|
|
64033
64962
|
method,
|
|
64034
64963
|
handler
|
|
@@ -65195,29 +66124,49 @@ var RequestError = class extends Error {
|
|
|
65195
66124
|
this.name = "RequestError";
|
|
65196
66125
|
}
|
|
65197
66126
|
};
|
|
65198
|
-
|
|
66127
|
+
const reValidRequestUrl = /^\/[!#$&-;=?-\[\]_a-z~]*$/;
|
|
66128
|
+
const reDotSegment = /\/\.\.?(?:[/?#]|$)/;
|
|
66129
|
+
const reValidHost = /^[a-z0-9._-]+(?::(?:[1-5]\d{3,4}|[6-9]\d{3}))?$/;
|
|
66130
|
+
const buildUrl = (scheme, host, incomingUrl) => {
|
|
66131
|
+
const url = `${scheme}://${host}${incomingUrl}`;
|
|
66132
|
+
if (!reValidHost.test(host)) {
|
|
66133
|
+
const urlObj = new URL(url);
|
|
66134
|
+
if (urlObj.hostname.length !== host.length && urlObj.hostname !== (host.includes(":") ? host.replace(/:\d+$/, "") : host).toLowerCase()) throw new RequestError("Invalid host header");
|
|
66135
|
+
return urlObj.href;
|
|
66136
|
+
} else if (incomingUrl.length === 0) return url + "/";
|
|
66137
|
+
else {
|
|
66138
|
+
if (incomingUrl.charCodeAt(0) !== 47) throw new RequestError("Invalid URL");
|
|
66139
|
+
if (!reValidRequestUrl.test(incomingUrl) || reDotSegment.test(incomingUrl)) return new URL(url).href;
|
|
66140
|
+
return url;
|
|
66141
|
+
}
|
|
66142
|
+
};
|
|
66143
|
+
const toRequestError = (e) => {
|
|
65199
66144
|
if (e instanceof RequestError) return e;
|
|
65200
66145
|
return new RequestError(e.message, { cause: e });
|
|
65201
66146
|
};
|
|
65202
|
-
|
|
66147
|
+
const GlobalRequest = global.Request;
|
|
65203
66148
|
var Request$1 = class extends GlobalRequest {
|
|
65204
66149
|
constructor(input, options) {
|
|
65205
|
-
if (typeof input === "object" && getRequestCache in input)
|
|
65206
|
-
|
|
66150
|
+
if (typeof input === "object" && getRequestCache in input) {
|
|
66151
|
+
const hasReplacementBody = options !== void 0 && "body" in options && options.body != null;
|
|
66152
|
+
if (input[bodyConsumedDirectlyKey] && !hasReplacementBody) throw new TypeError("Cannot construct a Request with a Request object that has already been used.");
|
|
66153
|
+
input = input[getRequestCache]();
|
|
66154
|
+
}
|
|
66155
|
+
if (typeof (options?.body)?.getReader !== "undefined") options.duplex ??= "half";
|
|
65207
66156
|
super(input, options);
|
|
65208
66157
|
}
|
|
65209
66158
|
};
|
|
65210
|
-
|
|
66159
|
+
const newHeadersFromIncoming = (incoming) => {
|
|
65211
66160
|
const headerRecord = [];
|
|
65212
66161
|
const rawHeaders = incoming.rawHeaders;
|
|
65213
|
-
for (let i = 0
|
|
65214
|
-
const
|
|
65215
|
-
if (key.charCodeAt(0) !== 58) headerRecord.push([key,
|
|
66162
|
+
for (let i = 0, len = rawHeaders.length; i < len; i += 2) {
|
|
66163
|
+
const key = rawHeaders[i];
|
|
66164
|
+
if (key.charCodeAt(0) !== 58) headerRecord.push([key, rawHeaders[i + 1]]);
|
|
65216
66165
|
}
|
|
65217
66166
|
return new Headers(headerRecord);
|
|
65218
66167
|
};
|
|
65219
|
-
|
|
65220
|
-
|
|
66168
|
+
const wrapBodyStream = Symbol("wrapBodyStream");
|
|
66169
|
+
const newRequestFromIncoming = (method, url, headers, incoming, abortController) => {
|
|
65221
66170
|
const init = {
|
|
65222
66171
|
method,
|
|
65223
66172
|
headers,
|
|
@@ -65250,15 +66199,162 @@ var newRequestFromIncoming = (method, url, headers, incoming, abortController) =
|
|
|
65250
66199
|
} else init.body = Readable.toWeb(incoming);
|
|
65251
66200
|
return new Request$1(url, init);
|
|
65252
66201
|
};
|
|
65253
|
-
|
|
65254
|
-
|
|
65255
|
-
|
|
65256
|
-
|
|
65257
|
-
|
|
65258
|
-
|
|
65259
|
-
|
|
66202
|
+
const getRequestCache = Symbol("getRequestCache");
|
|
66203
|
+
const requestCache = Symbol("requestCache");
|
|
66204
|
+
const incomingKey = Symbol("incomingKey");
|
|
66205
|
+
const urlKey = Symbol("urlKey");
|
|
66206
|
+
const methodKey = Symbol("methodKey");
|
|
66207
|
+
const headersKey = Symbol("headersKey");
|
|
66208
|
+
const abortControllerKey = Symbol("abortControllerKey");
|
|
66209
|
+
const getAbortController = Symbol("getAbortController");
|
|
66210
|
+
const abortRequest = Symbol("abortRequest");
|
|
66211
|
+
const bodyBufferKey = Symbol("bodyBuffer");
|
|
66212
|
+
const bodyReadPromiseKey = Symbol("bodyReadPromise");
|
|
66213
|
+
const bodyConsumedDirectlyKey = Symbol("bodyConsumedDirectly");
|
|
66214
|
+
const bodyLockReaderKey = Symbol("bodyLockReader");
|
|
66215
|
+
const abortReasonKey = Symbol("abortReason");
|
|
66216
|
+
const newBodyUnusableError = () => {
|
|
66217
|
+
return /* @__PURE__ */ new TypeError("Body is unusable");
|
|
66218
|
+
};
|
|
66219
|
+
const rejectBodyUnusable = () => {
|
|
66220
|
+
return Promise.reject(newBodyUnusableError());
|
|
66221
|
+
};
|
|
66222
|
+
const textDecoder = new TextDecoder();
|
|
66223
|
+
const consumeBodyDirectOnce = (request) => {
|
|
66224
|
+
if (request[bodyConsumedDirectlyKey]) return rejectBodyUnusable();
|
|
66225
|
+
request[bodyConsumedDirectlyKey] = true;
|
|
66226
|
+
};
|
|
66227
|
+
const toArrayBuffer = (buf) => {
|
|
66228
|
+
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
|
|
66229
|
+
};
|
|
66230
|
+
const contentType = (request) => {
|
|
66231
|
+
return (request[headersKey] ||= newHeadersFromIncoming(request[incomingKey])).get("content-type") || "";
|
|
66232
|
+
};
|
|
66233
|
+
const methodTokenRegExp = /^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/;
|
|
66234
|
+
const normalizeIncomingMethod = (method) => {
|
|
66235
|
+
if (typeof method !== "string" || method.length === 0) return "GET";
|
|
66236
|
+
switch (method) {
|
|
66237
|
+
case "DELETE":
|
|
66238
|
+
case "GET":
|
|
66239
|
+
case "HEAD":
|
|
66240
|
+
case "OPTIONS":
|
|
66241
|
+
case "POST":
|
|
66242
|
+
case "PUT": return method;
|
|
66243
|
+
}
|
|
66244
|
+
const upper = method.toUpperCase();
|
|
66245
|
+
switch (upper) {
|
|
66246
|
+
case "DELETE":
|
|
66247
|
+
case "GET":
|
|
66248
|
+
case "HEAD":
|
|
66249
|
+
case "OPTIONS":
|
|
66250
|
+
case "POST":
|
|
66251
|
+
case "PUT": return upper;
|
|
66252
|
+
default: return method;
|
|
66253
|
+
}
|
|
66254
|
+
};
|
|
66255
|
+
const validateDirectReadMethod = (method) => {
|
|
66256
|
+
if (!methodTokenRegExp.test(method)) return /* @__PURE__ */ new TypeError(`'${method}' is not a valid HTTP method.`);
|
|
66257
|
+
const normalized = method.toUpperCase();
|
|
66258
|
+
if (normalized === "CONNECT" || normalized === "TRACK" || normalized === "TRACE" && method !== "TRACE") return /* @__PURE__ */ new TypeError(`'${method}' HTTP method is unsupported.`);
|
|
66259
|
+
};
|
|
66260
|
+
const readBodyWithFastPath = (request, method, fromBuffer) => {
|
|
66261
|
+
if (request[bodyConsumedDirectlyKey]) return rejectBodyUnusable();
|
|
66262
|
+
const methodName = request.method;
|
|
66263
|
+
if (methodName === "GET" || methodName === "HEAD") return request[getRequestCache]()[method]();
|
|
66264
|
+
const methodValidationError = validateDirectReadMethod(methodName);
|
|
66265
|
+
if (methodValidationError) return Promise.reject(methodValidationError);
|
|
66266
|
+
if (request[requestCache]) {
|
|
66267
|
+
if (methodName !== "TRACE") return request[requestCache][method]();
|
|
66268
|
+
}
|
|
66269
|
+
const alreadyUsedError = consumeBodyDirectOnce(request);
|
|
66270
|
+
if (alreadyUsedError) return alreadyUsedError;
|
|
66271
|
+
const raw = readRawBodyIfAvailable(request);
|
|
66272
|
+
if (raw) {
|
|
66273
|
+
const result = Promise.resolve(fromBuffer(raw, request));
|
|
66274
|
+
request[bodyBufferKey] = void 0;
|
|
66275
|
+
return result;
|
|
66276
|
+
}
|
|
66277
|
+
return readBodyDirect(request).then((buf) => {
|
|
66278
|
+
const result = fromBuffer(buf, request);
|
|
66279
|
+
request[bodyBufferKey] = void 0;
|
|
66280
|
+
return result;
|
|
66281
|
+
});
|
|
66282
|
+
};
|
|
66283
|
+
const readRawBodyIfAvailable = (request) => {
|
|
66284
|
+
const incoming = request[incomingKey];
|
|
66285
|
+
if ("rawBody" in incoming && incoming.rawBody instanceof Buffer) return incoming.rawBody;
|
|
66286
|
+
};
|
|
66287
|
+
const readBodyDirect = (request) => {
|
|
66288
|
+
if (request[bodyBufferKey]) return Promise.resolve(request[bodyBufferKey]);
|
|
66289
|
+
if (request[bodyReadPromiseKey]) return request[bodyReadPromiseKey];
|
|
66290
|
+
const incoming = request[incomingKey];
|
|
66291
|
+
if (Readable.isDisturbed(incoming)) return rejectBodyUnusable();
|
|
66292
|
+
const promise = new Promise((resolve, reject) => {
|
|
66293
|
+
const chunks = [];
|
|
66294
|
+
let settled = false;
|
|
66295
|
+
const finish = (callback) => {
|
|
66296
|
+
if (settled) return;
|
|
66297
|
+
settled = true;
|
|
66298
|
+
cleanup();
|
|
66299
|
+
callback();
|
|
66300
|
+
};
|
|
66301
|
+
const onData = (chunk) => {
|
|
66302
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
66303
|
+
};
|
|
66304
|
+
const onEnd = () => {
|
|
66305
|
+
finish(() => {
|
|
66306
|
+
const buffer = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks);
|
|
66307
|
+
request[bodyBufferKey] = buffer;
|
|
66308
|
+
resolve(buffer);
|
|
66309
|
+
});
|
|
66310
|
+
};
|
|
66311
|
+
const onError = (error) => {
|
|
66312
|
+
finish(() => {
|
|
66313
|
+
reject(error);
|
|
66314
|
+
});
|
|
66315
|
+
};
|
|
66316
|
+
const onClose = () => {
|
|
66317
|
+
if (incoming.readableEnded) {
|
|
66318
|
+
onEnd();
|
|
66319
|
+
return;
|
|
66320
|
+
}
|
|
66321
|
+
finish(() => {
|
|
66322
|
+
if (incoming.errored) {
|
|
66323
|
+
reject(incoming.errored);
|
|
66324
|
+
return;
|
|
66325
|
+
}
|
|
66326
|
+
const reason = request[abortReasonKey];
|
|
66327
|
+
if (reason !== void 0) {
|
|
66328
|
+
reject(reason instanceof Error ? reason : new Error(String(reason)));
|
|
66329
|
+
return;
|
|
66330
|
+
}
|
|
66331
|
+
reject(/* @__PURE__ */ new Error("Client connection prematurely closed."));
|
|
66332
|
+
});
|
|
66333
|
+
};
|
|
66334
|
+
const cleanup = () => {
|
|
66335
|
+
incoming.off("data", onData);
|
|
66336
|
+
incoming.off("end", onEnd);
|
|
66337
|
+
incoming.off("error", onError);
|
|
66338
|
+
incoming.off("close", onClose);
|
|
66339
|
+
request[bodyReadPromiseKey] = void 0;
|
|
66340
|
+
};
|
|
66341
|
+
incoming.on("data", onData);
|
|
66342
|
+
incoming.on("end", onEnd);
|
|
66343
|
+
incoming.on("error", onError);
|
|
66344
|
+
incoming.on("close", onClose);
|
|
66345
|
+
queueMicrotask(() => {
|
|
66346
|
+
if (settled) return;
|
|
66347
|
+
if (incoming.readableEnded) onEnd();
|
|
66348
|
+
else if (incoming.errored) onError(incoming.errored);
|
|
66349
|
+
else if (incoming.destroyed) onClose();
|
|
66350
|
+
});
|
|
66351
|
+
});
|
|
66352
|
+
request[bodyReadPromiseKey] = promise;
|
|
66353
|
+
return promise;
|
|
66354
|
+
};
|
|
66355
|
+
const requestPrototype = {
|
|
65260
66356
|
get method() {
|
|
65261
|
-
return this[
|
|
66357
|
+
return this[methodKey];
|
|
65262
66358
|
},
|
|
65263
66359
|
get url() {
|
|
65264
66360
|
return this[urlKey];
|
|
@@ -65266,18 +66362,57 @@ var requestPrototype = {
|
|
|
65266
66362
|
get headers() {
|
|
65267
66363
|
return this[headersKey] ||= newHeadersFromIncoming(this[incomingKey]);
|
|
65268
66364
|
},
|
|
65269
|
-
[
|
|
65270
|
-
this[
|
|
66365
|
+
[abortRequest](reason) {
|
|
66366
|
+
if (this[abortReasonKey] === void 0) this[abortReasonKey] = reason;
|
|
66367
|
+
const abortController = this[abortControllerKey];
|
|
66368
|
+
if (abortController && !abortController.signal.aborted) abortController.abort(reason);
|
|
66369
|
+
},
|
|
66370
|
+
[getAbortController]() {
|
|
66371
|
+
this[abortControllerKey] ||= new AbortController();
|
|
66372
|
+
if (this[abortReasonKey] !== void 0 && !this[abortControllerKey].signal.aborted) this[abortControllerKey].abort(this[abortReasonKey]);
|
|
65271
66373
|
return this[abortControllerKey];
|
|
65272
66374
|
},
|
|
65273
66375
|
[getRequestCache]() {
|
|
65274
|
-
this[
|
|
65275
|
-
|
|
66376
|
+
const abortController = this[getAbortController]();
|
|
66377
|
+
if (this[requestCache]) return this[requestCache];
|
|
66378
|
+
const method = this.method;
|
|
66379
|
+
if (this[bodyConsumedDirectlyKey] && !(method === "GET" || method === "HEAD")) {
|
|
66380
|
+
this[bodyBufferKey] = void 0;
|
|
66381
|
+
const init = {
|
|
66382
|
+
method: method === "TRACE" ? "GET" : method,
|
|
66383
|
+
headers: this.headers,
|
|
66384
|
+
signal: abortController.signal
|
|
66385
|
+
};
|
|
66386
|
+
if (method !== "TRACE") {
|
|
66387
|
+
init.body = new ReadableStream({ start(c) {
|
|
66388
|
+
c.close();
|
|
66389
|
+
} });
|
|
66390
|
+
init.duplex = "half";
|
|
66391
|
+
}
|
|
66392
|
+
const req = new Request$1(this[urlKey], init);
|
|
66393
|
+
if (method === "TRACE") Object.defineProperty(req, "method", { get() {
|
|
66394
|
+
return "TRACE";
|
|
66395
|
+
} });
|
|
66396
|
+
return this[requestCache] = req;
|
|
66397
|
+
}
|
|
66398
|
+
return this[requestCache] = newRequestFromIncoming(this.method, this[urlKey], this.headers, this[incomingKey], abortController);
|
|
66399
|
+
},
|
|
66400
|
+
get body() {
|
|
66401
|
+
if (!this[bodyConsumedDirectlyKey]) return this[getRequestCache]().body;
|
|
66402
|
+
const request = this[getRequestCache]();
|
|
66403
|
+
if (!this[bodyLockReaderKey] && request.body) this[bodyLockReaderKey] = request.body.getReader();
|
|
66404
|
+
return request.body;
|
|
66405
|
+
},
|
|
66406
|
+
get bodyUsed() {
|
|
66407
|
+
if (this[bodyConsumedDirectlyKey]) return true;
|
|
66408
|
+
if (this[requestCache]) return this[requestCache].bodyUsed;
|
|
66409
|
+
return false;
|
|
65276
66410
|
}
|
|
65277
66411
|
};
|
|
66412
|
+
Object.defineProperty(requestPrototype, "signal", { get() {
|
|
66413
|
+
return this[getAbortController]().signal;
|
|
66414
|
+
} });
|
|
65278
66415
|
[
|
|
65279
|
-
"body",
|
|
65280
|
-
"bodyUsed",
|
|
65281
66416
|
"cache",
|
|
65282
66417
|
"credentials",
|
|
65283
66418
|
"destination",
|
|
@@ -65286,25 +66421,37 @@ var requestPrototype = {
|
|
|
65286
66421
|
"redirect",
|
|
65287
66422
|
"referrer",
|
|
65288
66423
|
"referrerPolicy",
|
|
65289
|
-
"signal",
|
|
65290
66424
|
"keepalive"
|
|
65291
66425
|
].forEach((k) => {
|
|
65292
66426
|
Object.defineProperty(requestPrototype, k, { get() {
|
|
65293
66427
|
return this[getRequestCache]()[k];
|
|
65294
66428
|
} });
|
|
65295
66429
|
});
|
|
65296
|
-
[
|
|
65297
|
-
"arrayBuffer",
|
|
65298
|
-
"blob",
|
|
65299
|
-
"clone",
|
|
65300
|
-
"formData",
|
|
65301
|
-
"json",
|
|
65302
|
-
"text"
|
|
65303
|
-
].forEach((k) => {
|
|
66430
|
+
["clone", "formData"].forEach((k) => {
|
|
65304
66431
|
Object.defineProperty(requestPrototype, k, { value: function() {
|
|
66432
|
+
if (this[bodyConsumedDirectlyKey]) {
|
|
66433
|
+
if (k === "clone") throw newBodyUnusableError();
|
|
66434
|
+
return rejectBodyUnusable();
|
|
66435
|
+
}
|
|
65305
66436
|
return this[getRequestCache]()[k]();
|
|
65306
66437
|
} });
|
|
65307
66438
|
});
|
|
66439
|
+
Object.defineProperty(requestPrototype, "text", { value: function() {
|
|
66440
|
+
return readBodyWithFastPath(this, "text", (buf) => textDecoder.decode(buf));
|
|
66441
|
+
} });
|
|
66442
|
+
Object.defineProperty(requestPrototype, "arrayBuffer", { value: function() {
|
|
66443
|
+
return readBodyWithFastPath(this, "arrayBuffer", (buf) => toArrayBuffer(buf));
|
|
66444
|
+
} });
|
|
66445
|
+
Object.defineProperty(requestPrototype, "blob", { value: function() {
|
|
66446
|
+
return readBodyWithFastPath(this, "blob", (buf, request) => {
|
|
66447
|
+
const type = contentType(request);
|
|
66448
|
+
return new Response(buf, type ? { headers: { "content-type": type } } : void 0).blob();
|
|
66449
|
+
});
|
|
66450
|
+
} });
|
|
66451
|
+
Object.defineProperty(requestPrototype, "json", { value: function() {
|
|
66452
|
+
if (this[bodyConsumedDirectlyKey]) return rejectBodyUnusable();
|
|
66453
|
+
return this.text().then(JSON.parse);
|
|
66454
|
+
} });
|
|
65308
66455
|
Object.defineProperty(requestPrototype, Symbol.for("nodejs.util.inspect.custom"), { value: function(depth, options, inspectFn) {
|
|
65309
66456
|
return `Request (lightweight) ${inspectFn({
|
|
65310
66457
|
method: this.method,
|
|
@@ -65317,9 +66464,10 @@ Object.defineProperty(requestPrototype, Symbol.for("nodejs.util.inspect.custom")
|
|
|
65317
66464
|
})}`;
|
|
65318
66465
|
} });
|
|
65319
66466
|
Object.setPrototypeOf(requestPrototype, Request$1.prototype);
|
|
65320
|
-
|
|
66467
|
+
const newRequest = (incoming, defaultHostname) => {
|
|
65321
66468
|
const req = Object.create(requestPrototype);
|
|
65322
66469
|
req[incomingKey] = incoming;
|
|
66470
|
+
req[methodKey] = normalizeIncomingMethod(incoming.method);
|
|
65323
66471
|
const incomingUrl = incoming.url || "";
|
|
65324
66472
|
if (incomingUrl[0] !== "/" && (incomingUrl.startsWith("http://") || incomingUrl.startsWith("https://"))) {
|
|
65325
66473
|
if (incoming instanceof Http2ServerRequest) throw new RequestError("Absolute URL for :path is not allowed in HTTP/2");
|
|
@@ -65337,26 +66485,35 @@ var newRequest = (incoming, defaultHostname) => {
|
|
|
65337
66485
|
scheme = incoming.scheme;
|
|
65338
66486
|
if (!(scheme === "http" || scheme === "https")) throw new RequestError("Unsupported scheme");
|
|
65339
66487
|
} else scheme = incoming.socket && incoming.socket.encrypted ? "https" : "http";
|
|
65340
|
-
|
|
65341
|
-
|
|
65342
|
-
|
|
66488
|
+
try {
|
|
66489
|
+
req[urlKey] = buildUrl(scheme, host, incomingUrl);
|
|
66490
|
+
} catch (e) {
|
|
66491
|
+
if (e instanceof RequestError) throw e;
|
|
66492
|
+
else throw new RequestError("Invalid URL", { cause: e });
|
|
66493
|
+
}
|
|
65343
66494
|
return req;
|
|
65344
66495
|
};
|
|
65345
|
-
|
|
65346
|
-
|
|
65347
|
-
|
|
65348
|
-
|
|
65349
|
-
|
|
66496
|
+
const defaultContentType = "text/plain; charset=UTF-8";
|
|
66497
|
+
const responseCache = Symbol("responseCache");
|
|
66498
|
+
const getResponseCache = Symbol("getResponseCache");
|
|
66499
|
+
const cacheKey = Symbol("cache");
|
|
66500
|
+
const GlobalResponse = global.Response;
|
|
66501
|
+
var Response$1 = class Response$1 {
|
|
65350
66502
|
#body;
|
|
65351
66503
|
#init;
|
|
65352
66504
|
[getResponseCache]() {
|
|
66505
|
+
const cache = this[cacheKey];
|
|
66506
|
+
const liveHeaders = cache && cache[2] instanceof Headers ? cache[2] : void 0;
|
|
65353
66507
|
delete this[cacheKey];
|
|
65354
|
-
return this[responseCache] ||= new GlobalResponse(this.#body,
|
|
66508
|
+
return this[responseCache] ||= new GlobalResponse(this.#body, liveHeaders ? {
|
|
66509
|
+
...this.#init,
|
|
66510
|
+
headers: liveHeaders
|
|
66511
|
+
} : this.#init);
|
|
65355
66512
|
}
|
|
65356
66513
|
constructor(body, init) {
|
|
65357
66514
|
let headers;
|
|
65358
66515
|
this.#body = body;
|
|
65359
|
-
if (init instanceof
|
|
66516
|
+
if (init instanceof Response$1) {
|
|
65360
66517
|
const cachedGlobalResponse = init[responseCache];
|
|
65361
66518
|
if (cachedGlobalResponse) {
|
|
65362
66519
|
this.#init = cachedGlobalResponse;
|
|
@@ -65364,19 +66521,19 @@ var Response2 = class _Response {
|
|
|
65364
66521
|
return;
|
|
65365
66522
|
} else {
|
|
65366
66523
|
this.#init = init.#init;
|
|
65367
|
-
headers = new Headers(init
|
|
66524
|
+
headers = new Headers(init.headers);
|
|
65368
66525
|
}
|
|
65369
66526
|
} else this.#init = init;
|
|
65370
|
-
if (typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) this[cacheKey] = [
|
|
66527
|
+
if (body == null || typeof body === "string" || typeof body?.getReader !== "undefined" || body instanceof Blob || body instanceof Uint8Array) this[cacheKey] = [
|
|
65371
66528
|
init?.status || 200,
|
|
65372
|
-
body,
|
|
66529
|
+
body ?? null,
|
|
65373
66530
|
headers || init?.headers
|
|
65374
66531
|
];
|
|
65375
66532
|
}
|
|
65376
66533
|
get headers() {
|
|
65377
66534
|
const cache = this[cacheKey];
|
|
65378
66535
|
if (cache) {
|
|
65379
|
-
if (!(cache[2] instanceof Headers)) cache[2] = new Headers(cache[2] || { "content-type":
|
|
66536
|
+
if (!(cache[2] instanceof Headers)) cache[2] = new Headers(cache[2] || (cache[1] === null ? void 0 : { "content-type": defaultContentType }));
|
|
65380
66537
|
return cache[2];
|
|
65381
66538
|
}
|
|
65382
66539
|
return this[getResponseCache]().headers;
|
|
@@ -65398,7 +66555,7 @@ var Response2 = class _Response {
|
|
|
65398
66555
|
"type",
|
|
65399
66556
|
"url"
|
|
65400
66557
|
].forEach((k) => {
|
|
65401
|
-
Object.defineProperty(
|
|
66558
|
+
Object.defineProperty(Response$1.prototype, k, { get() {
|
|
65402
66559
|
return this[getResponseCache]()[k];
|
|
65403
66560
|
} });
|
|
65404
66561
|
});
|
|
@@ -65410,11 +66567,11 @@ var Response2 = class _Response {
|
|
|
65410
66567
|
"json",
|
|
65411
66568
|
"text"
|
|
65412
66569
|
].forEach((k) => {
|
|
65413
|
-
Object.defineProperty(
|
|
66570
|
+
Object.defineProperty(Response$1.prototype, k, { value: function() {
|
|
65414
66571
|
return this[getResponseCache]()[k]();
|
|
65415
66572
|
} });
|
|
65416
66573
|
});
|
|
65417
|
-
Object.defineProperty(
|
|
66574
|
+
Object.defineProperty(Response$1.prototype, Symbol.for("nodejs.util.inspect.custom"), { value: function(depth, options, inspectFn) {
|
|
65418
66575
|
return `Response (lightweight) ${inspectFn({
|
|
65419
66576
|
status: this.status,
|
|
65420
66577
|
headers: this.headers,
|
|
@@ -65425,8 +66582,51 @@ Object.defineProperty(Response2.prototype, Symbol.for("nodejs.util.inspect.custo
|
|
|
65425
66582
|
depth: depth == null ? null : depth - 1
|
|
65426
66583
|
})}`;
|
|
65427
66584
|
} });
|
|
65428
|
-
Object.setPrototypeOf(
|
|
65429
|
-
Object.setPrototypeOf(
|
|
66585
|
+
Object.setPrototypeOf(Response$1, GlobalResponse);
|
|
66586
|
+
Object.setPrototypeOf(Response$1.prototype, GlobalResponse.prototype);
|
|
66587
|
+
const validRedirectUrl = /^https?:\/\/[!#-;=?-[\]_a-z~A-Z]+$/;
|
|
66588
|
+
const parseRedirectUrl = (url) => {
|
|
66589
|
+
if (url instanceof URL) return url.href;
|
|
66590
|
+
if (validRedirectUrl.test(url)) return url;
|
|
66591
|
+
return new URL(url).href;
|
|
66592
|
+
};
|
|
66593
|
+
const validRedirectStatuses = new Set([
|
|
66594
|
+
301,
|
|
66595
|
+
302,
|
|
66596
|
+
303,
|
|
66597
|
+
307,
|
|
66598
|
+
308
|
|
66599
|
+
]);
|
|
66600
|
+
Object.defineProperty(Response$1, "redirect", {
|
|
66601
|
+
value: function redirect(url, status = 302) {
|
|
66602
|
+
if (!validRedirectStatuses.has(status)) throw new RangeError("Invalid status code");
|
|
66603
|
+
return new Response$1(null, {
|
|
66604
|
+
status,
|
|
66605
|
+
headers: { location: parseRedirectUrl(url) }
|
|
66606
|
+
});
|
|
66607
|
+
},
|
|
66608
|
+
writable: true,
|
|
66609
|
+
configurable: true
|
|
66610
|
+
});
|
|
66611
|
+
Object.defineProperty(Response$1, "json", {
|
|
66612
|
+
value: function json(data, init) {
|
|
66613
|
+
const body = JSON.stringify(data);
|
|
66614
|
+
if (body === void 0) throw new TypeError("The data is not JSON serializable");
|
|
66615
|
+
const initHeaders = init?.headers;
|
|
66616
|
+
let headers;
|
|
66617
|
+
if (initHeaders) {
|
|
66618
|
+
headers = new Headers(initHeaders);
|
|
66619
|
+
if (!headers.has("content-type")) headers.set("content-type", "application/json");
|
|
66620
|
+
} else headers = { "content-type": "application/json" };
|
|
66621
|
+
return new Response$1(body, {
|
|
66622
|
+
status: init?.status ?? 200,
|
|
66623
|
+
statusText: init?.statusText,
|
|
66624
|
+
headers
|
|
66625
|
+
});
|
|
66626
|
+
},
|
|
66627
|
+
writable: true,
|
|
66628
|
+
configurable: true
|
|
66629
|
+
});
|
|
65430
66630
|
async function readWithoutBlocking(readPromise) {
|
|
65431
66631
|
return Promise.race([readPromise, Promise.resolve().then(() => Promise.resolve(void 0))]);
|
|
65432
66632
|
}
|
|
@@ -65462,23 +66662,23 @@ function writeFromReadableStream(stream, writable) {
|
|
|
65462
66662
|
else if (writable.destroyed) return;
|
|
65463
66663
|
return writeFromReadableStreamDefaultReader(stream.getReader(), writable);
|
|
65464
66664
|
}
|
|
65465
|
-
|
|
66665
|
+
const buildOutgoingHttpHeaders = (headers, defaultContentType) => {
|
|
65466
66666
|
const res = {};
|
|
65467
66667
|
if (!(headers instanceof Headers)) headers = new Headers(headers ?? void 0);
|
|
65468
|
-
|
|
65469
|
-
|
|
65470
|
-
|
|
65471
|
-
|
|
65472
|
-
|
|
66668
|
+
if (headers.has("set-cookie")) {
|
|
66669
|
+
const cookies = [];
|
|
66670
|
+
for (const [k, v] of headers) if (k === "set-cookie") cookies.push(v);
|
|
66671
|
+
else res[k] = v;
|
|
66672
|
+
if (cookies.length > 0) res["set-cookie"] = cookies;
|
|
66673
|
+
} else for (const [k, v] of headers) res[k] = v;
|
|
66674
|
+
if (defaultContentType) res["content-type"] ??= defaultContentType;
|
|
65473
66675
|
return res;
|
|
65474
66676
|
};
|
|
65475
|
-
|
|
65476
|
-
|
|
65477
|
-
|
|
65478
|
-
|
|
65479
|
-
|
|
65480
|
-
var MAX_DRAIN_BYTES = 64 * 1024 * 1024;
|
|
65481
|
-
var drainIncoming = (incoming) => {
|
|
66677
|
+
const outgoingEnded = Symbol("outgoingEnded");
|
|
66678
|
+
const incomingDraining = Symbol("incomingDraining");
|
|
66679
|
+
const DRAIN_TIMEOUT_MS = 500;
|
|
66680
|
+
const MAX_DRAIN_BYTES = 64 * 1024 * 1024;
|
|
66681
|
+
const drainIncoming = (incoming) => {
|
|
65482
66682
|
const incomingWithDrainState = incoming;
|
|
65483
66683
|
if (incoming.destroyed || incomingWithDrainState[incomingDraining]) return;
|
|
65484
66684
|
incomingWithDrainState[incomingDraining] = true;
|
|
@@ -65511,9 +66711,23 @@ var drainIncoming = (incoming) => {
|
|
|
65511
66711
|
incoming.on("error", cleanup);
|
|
65512
66712
|
incoming.resume();
|
|
65513
66713
|
};
|
|
65514
|
-
|
|
65515
|
-
|
|
65516
|
-
|
|
66714
|
+
const makeCloseHandler = (req, incoming, outgoing, needsBodyCleanup) => () => {
|
|
66715
|
+
if (incoming.errored) req[abortRequest](incoming.errored.toString());
|
|
66716
|
+
else if (!outgoing.writableFinished) req[abortRequest]("Client connection prematurely closed.");
|
|
66717
|
+
if (needsBodyCleanup && !incoming.readableEnded) setTimeout(() => {
|
|
66718
|
+
if (!incoming.readableEnded) setTimeout(() => {
|
|
66719
|
+
drainIncoming(incoming);
|
|
66720
|
+
});
|
|
66721
|
+
});
|
|
66722
|
+
};
|
|
66723
|
+
const isImmediateCacheableResponse = (res) => {
|
|
66724
|
+
if (!(cacheKey in res)) return false;
|
|
66725
|
+
const body = res[cacheKey][1];
|
|
66726
|
+
return body === null || typeof body === "string" || body instanceof Uint8Array;
|
|
66727
|
+
};
|
|
66728
|
+
const handleRequestError = () => new Response(null, { status: 400 });
|
|
66729
|
+
const handleFetchError = (e) => new Response(null, { status: e instanceof Error && (e.name === "TimeoutError" || e.constructor.name === "TimeoutError") ? 504 : 500 });
|
|
66730
|
+
const handleResponseError = (e, outgoing) => {
|
|
65517
66731
|
const err = e instanceof Error ? e : new Error("unknown error", { cause: e });
|
|
65518
66732
|
if (err.code === "ERR_STREAM_PREMATURE_CLOSE") console.info("The user aborted a request.");
|
|
65519
66733
|
else {
|
|
@@ -65523,20 +66737,49 @@ var handleResponseError = (e, outgoing) => {
|
|
|
65523
66737
|
outgoing.destroy(err);
|
|
65524
66738
|
}
|
|
65525
66739
|
};
|
|
65526
|
-
|
|
66740
|
+
const flushHeaders = (outgoing) => {
|
|
65527
66741
|
if ("flushHeaders" in outgoing && outgoing.writable) outgoing.flushHeaders();
|
|
65528
66742
|
};
|
|
65529
|
-
|
|
66743
|
+
const responseViaCache = async (res, outgoing) => {
|
|
65530
66744
|
let [status, body, header] = res[cacheKey];
|
|
66745
|
+
if (!header) {
|
|
66746
|
+
if (body === null) {
|
|
66747
|
+
outgoing.writeHead(status);
|
|
66748
|
+
outgoing.end();
|
|
66749
|
+
} else if (typeof body === "string") {
|
|
66750
|
+
outgoing.writeHead(status, {
|
|
66751
|
+
"Content-Type": defaultContentType,
|
|
66752
|
+
"Content-Length": Buffer.byteLength(body)
|
|
66753
|
+
});
|
|
66754
|
+
outgoing.end(body);
|
|
66755
|
+
} else if (body instanceof Uint8Array) {
|
|
66756
|
+
outgoing.writeHead(status, {
|
|
66757
|
+
"Content-Type": defaultContentType,
|
|
66758
|
+
"Content-Length": body.byteLength
|
|
66759
|
+
});
|
|
66760
|
+
outgoing.end(body);
|
|
66761
|
+
} else if (body instanceof Blob) {
|
|
66762
|
+
outgoing.writeHead(status, {
|
|
66763
|
+
"Content-Type": defaultContentType,
|
|
66764
|
+
"Content-Length": body.size
|
|
66765
|
+
});
|
|
66766
|
+
outgoing.end(new Uint8Array(await body.arrayBuffer()));
|
|
66767
|
+
} else {
|
|
66768
|
+
outgoing.writeHead(status, { "Content-Type": defaultContentType });
|
|
66769
|
+
flushHeaders(outgoing);
|
|
66770
|
+
await writeFromReadableStream(body, outgoing)?.catch((e) => handleResponseError(e, outgoing));
|
|
66771
|
+
}
|
|
66772
|
+
outgoing[outgoingEnded]?.();
|
|
66773
|
+
return;
|
|
66774
|
+
}
|
|
65531
66775
|
let hasContentLength = false;
|
|
65532
|
-
if (
|
|
65533
|
-
else if (header instanceof Headers) {
|
|
66776
|
+
if (header instanceof Headers) {
|
|
65534
66777
|
hasContentLength = header.has("content-length");
|
|
65535
|
-
header = buildOutgoingHttpHeaders(header);
|
|
66778
|
+
header = buildOutgoingHttpHeaders(header, body === null ? void 0 : defaultContentType);
|
|
65536
66779
|
} else if (Array.isArray(header)) {
|
|
65537
66780
|
const headerObj = new Headers(header);
|
|
65538
66781
|
hasContentLength = headerObj.has("content-length");
|
|
65539
|
-
header = buildOutgoingHttpHeaders(headerObj);
|
|
66782
|
+
header = buildOutgoingHttpHeaders(headerObj, body === null ? void 0 : defaultContentType);
|
|
65540
66783
|
} else for (const key in header) if (key.length === 14 && key.toLowerCase() === "content-length") {
|
|
65541
66784
|
hasContentLength = true;
|
|
65542
66785
|
break;
|
|
@@ -65547,7 +66790,8 @@ var responseViaCache = async (res, outgoing) => {
|
|
|
65547
66790
|
else if (body instanceof Blob) header["Content-Length"] = body.size;
|
|
65548
66791
|
}
|
|
65549
66792
|
outgoing.writeHead(status, header);
|
|
65550
|
-
if (
|
|
66793
|
+
if (body == null) outgoing.end();
|
|
66794
|
+
else if (typeof body === "string" || body instanceof Uint8Array) outgoing.end(body);
|
|
65551
66795
|
else if (body instanceof Blob) outgoing.end(new Uint8Array(await body.arrayBuffer()));
|
|
65552
66796
|
else {
|
|
65553
66797
|
flushHeaders(outgoing);
|
|
@@ -65555,8 +66799,8 @@ var responseViaCache = async (res, outgoing) => {
|
|
|
65555
66799
|
}
|
|
65556
66800
|
outgoing[outgoingEnded]?.();
|
|
65557
66801
|
};
|
|
65558
|
-
|
|
65559
|
-
|
|
66802
|
+
const isPromise = (res) => typeof res.then === "function";
|
|
66803
|
+
const responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
65560
66804
|
if (isPromise(res)) if (options.errorHandler) try {
|
|
65561
66805
|
res = await res;
|
|
65562
66806
|
} catch (err) {
|
|
@@ -65566,7 +66810,7 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
65566
66810
|
}
|
|
65567
66811
|
else res = await res.catch(handleFetchError);
|
|
65568
66812
|
if (cacheKey in res) return responseViaCache(res, outgoing);
|
|
65569
|
-
const resHeaderRecord = buildOutgoingHttpHeaders(res.headers);
|
|
66813
|
+
const resHeaderRecord = buildOutgoingHttpHeaders(res.headers, res.body === null ? void 0 : defaultContentType);
|
|
65570
66814
|
if (res.body) {
|
|
65571
66815
|
const reader = res.body.getReader();
|
|
65572
66816
|
const values = [];
|
|
@@ -65606,57 +66850,55 @@ var responseViaResponseObject = async (res, outgoing, options = {}) => {
|
|
|
65606
66850
|
if (values.length === 0) flushHeaders(outgoing);
|
|
65607
66851
|
await writeFromReadableStreamDefaultReader(reader, outgoing, currentReadPromise);
|
|
65608
66852
|
}
|
|
65609
|
-
} else if (resHeaderRecord[
|
|
66853
|
+
} else if (resHeaderRecord["x-hono-already-sent"]) {} else {
|
|
65610
66854
|
outgoing.writeHead(res.status, resHeaderRecord);
|
|
65611
66855
|
outgoing.end();
|
|
65612
66856
|
}
|
|
65613
66857
|
outgoing[outgoingEnded]?.();
|
|
65614
66858
|
};
|
|
65615
|
-
|
|
66859
|
+
const getRequestListener = (fetchCallback, options = {}) => {
|
|
65616
66860
|
const autoCleanupIncoming = options.autoCleanupIncoming ?? true;
|
|
65617
66861
|
if (options.overrideGlobalObjects !== false && global.Request !== Request$1) {
|
|
65618
66862
|
Object.defineProperty(global, "Request", { value: Request$1 });
|
|
65619
|
-
Object.defineProperty(global, "Response", { value:
|
|
66863
|
+
Object.defineProperty(global, "Response", { value: Response$1 });
|
|
65620
66864
|
}
|
|
65621
66865
|
return async (incoming, outgoing) => {
|
|
65622
66866
|
let res, req;
|
|
66867
|
+
let needsBodyCleanup = false;
|
|
66868
|
+
let closeHandlerAttached = false;
|
|
66869
|
+
const ensureCloseHandler = () => {
|
|
66870
|
+
if (!req || closeHandlerAttached) return;
|
|
66871
|
+
closeHandlerAttached = true;
|
|
66872
|
+
outgoing.on("close", makeCloseHandler(req, incoming, outgoing, needsBodyCleanup));
|
|
66873
|
+
};
|
|
65623
66874
|
try {
|
|
65624
66875
|
req = newRequest(incoming, options.hostname);
|
|
65625
|
-
|
|
65626
|
-
if (
|
|
66876
|
+
needsBodyCleanup = autoCleanupIncoming && !(incoming.method === "GET" || incoming.method === "HEAD");
|
|
66877
|
+
if (needsBodyCleanup) {
|
|
65627
66878
|
incoming[wrapBodyStream] = true;
|
|
65628
|
-
incoming.on("end", () => {
|
|
65629
|
-
incomingEnded = true;
|
|
65630
|
-
});
|
|
65631
66879
|
if (incoming instanceof Http2ServerRequest) outgoing[outgoingEnded] = () => {
|
|
65632
|
-
if (!
|
|
65633
|
-
if (!
|
|
65634
|
-
|
|
66880
|
+
if (!incoming.readableEnded) setTimeout(() => {
|
|
66881
|
+
if (!incoming.readableEnded) setTimeout(() => {
|
|
66882
|
+
incoming.destroy();
|
|
66883
|
+
outgoing.destroy();
|
|
65635
66884
|
});
|
|
65636
66885
|
});
|
|
65637
66886
|
};
|
|
65638
|
-
outgoing.on("finish", () => {
|
|
65639
|
-
if (!incomingEnded) drainIncoming(incoming);
|
|
65640
|
-
});
|
|
65641
66887
|
}
|
|
65642
|
-
outgoing.on("close", () => {
|
|
65643
|
-
if (req[abortControllerKey]) {
|
|
65644
|
-
if (incoming.errored) req[abortControllerKey].abort(incoming.errored.toString());
|
|
65645
|
-
else if (!outgoing.writableFinished) req[abortControllerKey].abort("Client connection prematurely closed.");
|
|
65646
|
-
}
|
|
65647
|
-
if (!incomingEnded) setTimeout(() => {
|
|
65648
|
-
if (!incomingEnded) setTimeout(() => {
|
|
65649
|
-
drainIncoming(incoming);
|
|
65650
|
-
});
|
|
65651
|
-
});
|
|
65652
|
-
});
|
|
65653
66888
|
res = fetchCallback(req, {
|
|
65654
66889
|
incoming,
|
|
65655
66890
|
outgoing
|
|
65656
66891
|
});
|
|
65657
|
-
if (
|
|
66892
|
+
if (!isPromise(res) && isImmediateCacheableResponse(res)) {
|
|
66893
|
+
if (needsBodyCleanup && !incoming.readableEnded) outgoing.once("finish", () => {
|
|
66894
|
+
if (!incoming.readableEnded) drainIncoming(incoming);
|
|
66895
|
+
});
|
|
66896
|
+
return responseViaCache(res, outgoing);
|
|
66897
|
+
}
|
|
66898
|
+
ensureCloseHandler();
|
|
65658
66899
|
} catch (e) {
|
|
65659
66900
|
if (!res) if (options.errorHandler) {
|
|
66901
|
+
ensureCloseHandler();
|
|
65660
66902
|
res = await options.errorHandler(req ? e : toRequestError(e));
|
|
65661
66903
|
if (!res) return;
|
|
65662
66904
|
} else if (!req) res = handleRequestError();
|
|
@@ -65670,16 +66912,126 @@ var getRequestListener = (fetchCallback, options = {}) => {
|
|
|
65670
66912
|
}
|
|
65671
66913
|
};
|
|
65672
66914
|
};
|
|
65673
|
-
|
|
66915
|
+
globalThis.CloseEvent;
|
|
66916
|
+
const CONNECTION_SYMBOL_KEY = Symbol("CONNECTION_SYMBOL_KEY");
|
|
66917
|
+
const WAIT_FOR_WEBSOCKET_SYMBOL = Symbol("WAIT_FOR_WEBSOCKET_SYMBOL");
|
|
66918
|
+
const responseHeadersToSkip = new Set([
|
|
66919
|
+
"connection",
|
|
66920
|
+
"content-length",
|
|
66921
|
+
"keep-alive",
|
|
66922
|
+
"proxy-authenticate",
|
|
66923
|
+
"proxy-authorization",
|
|
66924
|
+
"te",
|
|
66925
|
+
"trailer",
|
|
66926
|
+
"transfer-encoding",
|
|
66927
|
+
"upgrade",
|
|
66928
|
+
"sec-websocket-accept",
|
|
66929
|
+
"sec-websocket-extensions",
|
|
66930
|
+
"sec-websocket-protocol"
|
|
66931
|
+
]);
|
|
66932
|
+
const appendResponseHeaders = (headers, responseHeaders) => {
|
|
66933
|
+
if (!responseHeaders) return;
|
|
66934
|
+
responseHeaders.forEach((value, key) => {
|
|
66935
|
+
if (responseHeadersToSkip.has(key.toLowerCase())) return;
|
|
66936
|
+
headers.push(`${key}: ${value}`);
|
|
66937
|
+
});
|
|
66938
|
+
};
|
|
66939
|
+
const rejectUpgradeRequest = (socket, status, responseHeaders) => {
|
|
66940
|
+
const responseLines = ["Connection: close", "Content-Length: 0"];
|
|
66941
|
+
appendResponseHeaders(responseLines, responseHeaders);
|
|
66942
|
+
socket.end(`HTTP/1.1 ${status.toString()} ${STATUS_CODES[status] ?? ""}\r\n${responseLines.join("\r\n")}\r\n\r
|
|
66943
|
+
`);
|
|
66944
|
+
};
|
|
66945
|
+
const createUpgradeRequest = (request) => {
|
|
66946
|
+
const protocol = request.socket.encrypted ? "https" : "http";
|
|
66947
|
+
const url = new URL(request.url ?? "/", `${protocol}://${request.headers.host ?? "localhost"}`);
|
|
66948
|
+
const headers = new Headers();
|
|
66949
|
+
for (const key in request.headers) {
|
|
66950
|
+
const value = request.headers[key];
|
|
66951
|
+
if (!value) continue;
|
|
66952
|
+
headers.append(key, Array.isArray(value) ? value[0] : value);
|
|
66953
|
+
}
|
|
66954
|
+
return new Request(url, { headers });
|
|
66955
|
+
};
|
|
66956
|
+
const setupWebSocket = (options) => {
|
|
66957
|
+
const { server, fetchCallback, wss } = options;
|
|
66958
|
+
const waiterMap = /* @__PURE__ */ new Map();
|
|
66959
|
+
wss.on("connection", (ws, request) => {
|
|
66960
|
+
const waiter = waiterMap.get(request);
|
|
66961
|
+
if (waiter) {
|
|
66962
|
+
waiter.resolve(ws);
|
|
66963
|
+
waiterMap.delete(request);
|
|
66964
|
+
}
|
|
66965
|
+
});
|
|
66966
|
+
const waitForWebSocket = (request, connectionSymbol) => {
|
|
66967
|
+
return new Promise((resolve) => {
|
|
66968
|
+
waiterMap.set(request, {
|
|
66969
|
+
resolve,
|
|
66970
|
+
connectionSymbol
|
|
66971
|
+
});
|
|
66972
|
+
});
|
|
66973
|
+
};
|
|
66974
|
+
server.on("upgrade", async (request, socket, head) => {
|
|
66975
|
+
if (request.headers.upgrade?.toLowerCase() !== "websocket") return;
|
|
66976
|
+
const env = {
|
|
66977
|
+
incoming: request,
|
|
66978
|
+
outgoing: void 0,
|
|
66979
|
+
wss,
|
|
66980
|
+
[WAIT_FOR_WEBSOCKET_SYMBOL]: waitForWebSocket
|
|
66981
|
+
};
|
|
66982
|
+
let status = 400;
|
|
66983
|
+
let responseHeaders;
|
|
66984
|
+
try {
|
|
66985
|
+
const response = await fetchCallback(createUpgradeRequest(request), env);
|
|
66986
|
+
if (response instanceof Response) {
|
|
66987
|
+
status = response.status;
|
|
66988
|
+
responseHeaders = response.headers;
|
|
66989
|
+
}
|
|
66990
|
+
} catch {
|
|
66991
|
+
if (server.listenerCount("upgrade") === 1) rejectUpgradeRequest(socket, 500);
|
|
66992
|
+
return;
|
|
66993
|
+
}
|
|
66994
|
+
const waiter = waiterMap.get(request);
|
|
66995
|
+
if (!waiter || waiter.connectionSymbol !== env[CONNECTION_SYMBOL_KEY]) {
|
|
66996
|
+
waiterMap.delete(request);
|
|
66997
|
+
if (server.listenerCount("upgrade") === 1) rejectUpgradeRequest(socket, status, responseHeaders);
|
|
66998
|
+
return;
|
|
66999
|
+
}
|
|
67000
|
+
const addResponseHeaders = (headers) => {
|
|
67001
|
+
appendResponseHeaders(headers, responseHeaders);
|
|
67002
|
+
};
|
|
67003
|
+
wss.on("headers", addResponseHeaders);
|
|
67004
|
+
try {
|
|
67005
|
+
wss.handleUpgrade(request, socket, head, (ws) => {
|
|
67006
|
+
wss.emit("connection", ws, request);
|
|
67007
|
+
});
|
|
67008
|
+
} finally {
|
|
67009
|
+
wss.off("headers", addResponseHeaders);
|
|
67010
|
+
}
|
|
67011
|
+
});
|
|
67012
|
+
server.on("close", () => {
|
|
67013
|
+
wss.close();
|
|
67014
|
+
});
|
|
67015
|
+
};
|
|
67016
|
+
const createAdaptorServer = (options) => {
|
|
65674
67017
|
const fetchCallback = options.fetch;
|
|
65675
67018
|
const requestListener = getRequestListener(fetchCallback, {
|
|
65676
67019
|
hostname: options.hostname,
|
|
65677
67020
|
overrideGlobalObjects: options.overrideGlobalObjects,
|
|
65678
67021
|
autoCleanupIncoming: options.autoCleanupIncoming
|
|
65679
67022
|
});
|
|
65680
|
-
|
|
67023
|
+
const server = (options.createServer || createServer)(options.serverOptions || {}, requestListener);
|
|
67024
|
+
if (options.websocket && options.websocket.server) {
|
|
67025
|
+
if (options.websocket.server.options.noServer !== true) throw new Error("WebSocket server must be created with { noServer: true } option");
|
|
67026
|
+
setupWebSocket({
|
|
67027
|
+
server,
|
|
67028
|
+
fetchCallback,
|
|
67029
|
+
wss: options.websocket.server
|
|
67030
|
+
});
|
|
67031
|
+
}
|
|
67032
|
+
return server;
|
|
65681
67033
|
};
|
|
65682
|
-
|
|
67034
|
+
const serve = (options, listeningListener) => {
|
|
65683
67035
|
const server = createAdaptorServer(options);
|
|
65684
67036
|
server.listen(options?.port ?? 3e3, options.hostname, () => {
|
|
65685
67037
|
const serverInfo = server.address();
|
|
@@ -65738,7 +67090,15 @@ const ENGINE_COMMANDS = new Set([
|
|
|
65738
67090
|
"list_tools",
|
|
65739
67091
|
"search_tools",
|
|
65740
67092
|
"get_tool",
|
|
65741
|
-
"call_tool"
|
|
67093
|
+
"call_tool",
|
|
67094
|
+
"list_resources",
|
|
67095
|
+
"search_resources",
|
|
67096
|
+
"list_resource_templates",
|
|
67097
|
+
"read_resource",
|
|
67098
|
+
"list_prompts",
|
|
67099
|
+
"search_prompts",
|
|
67100
|
+
"get_prompt",
|
|
67101
|
+
"complete"
|
|
65742
67102
|
]);
|
|
65743
67103
|
async function dispatchRemoteCliRequest(request, context) {
|
|
65744
67104
|
try {
|
|
@@ -65789,6 +67149,16 @@ async function dispatch(request, context) {
|
|
|
65789
67149
|
...optionalProp("force", optionalBoolean(request.arguments, "force"))
|
|
65790
67150
|
})
|
|
65791
67151
|
};
|
|
67152
|
+
if (request.command === "complete_cli") {
|
|
67153
|
+
const shell = optionalString(request.arguments, "shell") ?? "bash";
|
|
67154
|
+
if (!completionShells.includes(shell)) return [];
|
|
67155
|
+
const engine = new CapletsEngine(context);
|
|
67156
|
+
try {
|
|
67157
|
+
return await engine.completeCliWords(optionalStringArray(request.arguments, "words") ?? [""]);
|
|
67158
|
+
} finally {
|
|
67159
|
+
await engine.close();
|
|
67160
|
+
}
|
|
67161
|
+
}
|
|
65792
67162
|
if (request.command === "auth_list") return listAuthRows({
|
|
65793
67163
|
...optionalProp("configPath", context.configPath),
|
|
65794
67164
|
...optionalProp("authDir", context.authDir)
|
|
@@ -65905,6 +67275,12 @@ function requiredString(args, key) {
|
|
|
65905
67275
|
if (typeof value !== "string" || value.length === 0) throw new CapletsError("REQUEST_INVALID", `${key} must be a non-empty string`);
|
|
65906
67276
|
return value;
|
|
65907
67277
|
}
|
|
67278
|
+
function optionalString(args, key) {
|
|
67279
|
+
const value = args[key];
|
|
67280
|
+
if (value === void 0) return;
|
|
67281
|
+
if (typeof value !== "string") throw new CapletsError("REQUEST_INVALID", `${key} must be a string`);
|
|
67282
|
+
return value;
|
|
67283
|
+
}
|
|
65908
67284
|
function optionalObject(args, key) {
|
|
65909
67285
|
const value = args[key];
|
|
65910
67286
|
if (value === void 0) return {};
|
|
@@ -66467,6 +67843,9 @@ async function runCli(args, io = {}) {
|
|
|
66467
67843
|
throw error;
|
|
66468
67844
|
}
|
|
66469
67845
|
}
|
|
67846
|
+
function normalizeCompletionWords(words) {
|
|
67847
|
+
return words.map((word) => word === "__CAPLETS_TRAILING_SPACE__" ? "" : word);
|
|
67848
|
+
}
|
|
66470
67849
|
function createProgram(io = {}) {
|
|
66471
67850
|
const writeOut = io.writeOut ?? ((value) => process.stdout.write(value));
|
|
66472
67851
|
const writeErr = io.writeErr ?? ((value) => process.stderr.write(value));
|
|
@@ -66481,7 +67860,27 @@ function createProgram(io = {}) {
|
|
|
66481
67860
|
writeErr,
|
|
66482
67861
|
outputError: (value, write) => write(value)
|
|
66483
67862
|
});
|
|
66484
|
-
program.command(
|
|
67863
|
+
program.command(cliCommands.completion).description("Print a shell completion script.").argument("<shell>", "completion shell: bash, zsh, fish, powershell, or cmd").action((shell) => {
|
|
67864
|
+
if (!completionShells.includes(shell)) throw new CapletsError("REQUEST_INVALID", "completion shell must be bash, zsh, fish, powershell, or cmd");
|
|
67865
|
+
writeOut(completionScript(shell));
|
|
67866
|
+
});
|
|
67867
|
+
program.command(cliCommands.completeHidden, { hidden: true }).description("Internal shell completion endpoint.").option("--shell <shell>", "completion shell").allowUnknownOption(true).argument("[words...]", "words to complete").action(async (words, options) => {
|
|
67868
|
+
const shell = completionShells.includes(options.shell) ? options.shell : "bash";
|
|
67869
|
+
const remote = remoteClientForCli(io);
|
|
67870
|
+
const configPath = currentConfigPath();
|
|
67871
|
+
const completionWords = normalizeCompletionWords(words);
|
|
67872
|
+
let suggestions = [];
|
|
67873
|
+
try {
|
|
67874
|
+
suggestions = remote ? await remote.request("complete_cli", {
|
|
67875
|
+
shell,
|
|
67876
|
+
words: completionWords
|
|
67877
|
+
}) : await completeCliWords(completionWords, configPath ? { configPath } : {});
|
|
67878
|
+
} catch {
|
|
67879
|
+
suggestions = [];
|
|
67880
|
+
}
|
|
67881
|
+
if (suggestions.length > 0) writeOut(`${suggestions.join("\n")}\n`);
|
|
67882
|
+
});
|
|
67883
|
+
program.command(cliCommands.serve).description("Serve configured Caplets as an MCP server.").option("--transport <transport>", "server transport: stdio or http").option("--host <host>", "HTTP bind host").option("--port <port>", "HTTP bind port").option("--path <path>", "HTTP service base path").option("--user <user>", "HTTP Basic Auth username").option("--password <password>", "HTTP Basic Auth password").option("--allow-unauthenticated-http", "allow unauthenticated HTTP serving on non-loopback hosts").option("--trust-proxy", "trust X-Forwarded-* headers from a reverse proxy").action(async (options) => {
|
|
66485
67884
|
const resolved = resolveServeOptions(options);
|
|
66486
67885
|
const configPath = currentConfigPath();
|
|
66487
67886
|
await (io.serve ?? ((serveOptions) => serveResolvedCaplets(serveOptions, {
|
|
@@ -66489,7 +67888,7 @@ function createProgram(io = {}) {
|
|
|
66489
67888
|
...io.authDir ? { authDir: io.authDir } : {}
|
|
66490
67889
|
}, writeErr)))(resolved);
|
|
66491
67890
|
});
|
|
66492
|
-
program.command(
|
|
67891
|
+
program.command(cliCommands.init).description("Create a starter Caplets config file.").option("--force", "overwrite an existing config file").action(async (options) => {
|
|
66493
67892
|
const remote = remoteClientForCli(io);
|
|
66494
67893
|
if (remote) {
|
|
66495
67894
|
writeOut(`Created remote Caplets config at ${(await remote.request("init", { force: Boolean(options.force) })).path}\n`);
|
|
@@ -66501,7 +67900,7 @@ function createProgram(io = {}) {
|
|
|
66501
67900
|
force: Boolean(options.force)
|
|
66502
67901
|
})}\n`);
|
|
66503
67902
|
});
|
|
66504
|
-
program.command(
|
|
67903
|
+
program.command(cliCommands.list).description("List configured Caplets.").option("--all", "include disabled Caplets").option("--json", "print JSON output").option("--format <format>", "output format: plain, markdown, md, or json", parseOutputFormat).action(async (options) => {
|
|
66505
67904
|
const includeDisabled = Boolean(options.all);
|
|
66506
67905
|
const remote = remoteClientForCli(io);
|
|
66507
67906
|
if (remote) {
|
|
@@ -66520,7 +67919,7 @@ function createProgram(io = {}) {
|
|
|
66520
67919
|
}
|
|
66521
67920
|
writeOut(formatCapletList(rows, options.format ?? "plain"));
|
|
66522
67921
|
});
|
|
66523
|
-
program.command(
|
|
67922
|
+
program.command(cliCommands.install).description("Install Caplets from a repo's caplets directory.").argument("<repo>", "local repo path, Git URL, or GitHub owner/repo").argument("[caplets...]", "optional Caplet IDs to install").option("-g, --global", "install to the user Caplets root").option("--force", "overwrite installed Caplets").action(async (repo, capletIds, options) => {
|
|
66524
67923
|
const remote = remoteClientForCli(io);
|
|
66525
67924
|
if (remote) {
|
|
66526
67925
|
if (options.global) writeErr("Warning: --global is not supported in remote mode; the server controls the installation destination.\n");
|
|
@@ -66539,7 +67938,7 @@ function createProgram(io = {}) {
|
|
|
66539
67938
|
});
|
|
66540
67939
|
for (const caplet of result.installed) writeOut(`Installed ${caplet.id} to ${caplet.destination}\n`);
|
|
66541
67940
|
});
|
|
66542
|
-
const add = program.command(
|
|
67941
|
+
const add = program.command(cliCommands.add).description("Add generated Caplet files.");
|
|
66543
67942
|
add.command("cli").description("Add a CLI tools Caplet.").argument("<id>", "Caplet ID/display seed").option("--repo <path>", "repository path to inspect").option("--include <items>", "comma-separated generators to include: git,gh,package").option("--command <name>", "single CLI command template to generate").option("-g, --global", "write to the user Caplets root").option("--print", "print generated Caplet text without writing a file").option("--output <path>", "output path").option("--force", "overwrite an existing destination file").action(async (id, options) => {
|
|
66544
67943
|
const remote = remoteClientForCli(io);
|
|
66545
67944
|
if (remote) {
|
|
@@ -66620,7 +68019,7 @@ function createProgram(io = {}) {
|
|
|
66620
68019
|
destinationRoot: addDestinationRoot(options, currentConfigPath())
|
|
66621
68020
|
}));
|
|
66622
68021
|
});
|
|
66623
|
-
program.command(
|
|
68022
|
+
program.command(cliCommands.getCaplet).description("Print a configured Caplet card.").argument("<caplet>", "configured Caplet ID").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => {
|
|
66624
68023
|
await executeOperation(caplet, { operation: "get_caplet" }, {
|
|
66625
68024
|
writeOut,
|
|
66626
68025
|
writeErr,
|
|
@@ -66631,7 +68030,7 @@ function createProgram(io = {}) {
|
|
|
66631
68030
|
format: options.format
|
|
66632
68031
|
});
|
|
66633
68032
|
});
|
|
66634
|
-
program.command(
|
|
68033
|
+
program.command(cliCommands.checkBackend).description("Check backend availability for a configured Caplet.").argument("<caplet>", "configured Caplet ID").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => {
|
|
66635
68034
|
await executeOperation(caplet, { operation: "check_backend" }, {
|
|
66636
68035
|
writeOut,
|
|
66637
68036
|
writeErr,
|
|
@@ -66642,7 +68041,7 @@ function createProgram(io = {}) {
|
|
|
66642
68041
|
format: options.format
|
|
66643
68042
|
});
|
|
66644
68043
|
});
|
|
66645
|
-
program.command(
|
|
68044
|
+
program.command(cliCommands.listTools).description("List downstream tools for a configured Caplet.").argument("<caplet>", "configured Caplet ID").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => {
|
|
66646
68045
|
await executeOperation(caplet, { operation: "list_tools" }, {
|
|
66647
68046
|
writeOut,
|
|
66648
68047
|
writeErr,
|
|
@@ -66653,7 +68052,7 @@ function createProgram(io = {}) {
|
|
|
66653
68052
|
format: options.format
|
|
66654
68053
|
});
|
|
66655
68054
|
});
|
|
66656
|
-
program.command(
|
|
68055
|
+
program.command(cliCommands.searchTools).description("Search downstream tools for a configured Caplet.").argument("<caplet>", "configured Caplet ID").argument("<query>", "search query").option("--limit <n>", "maximum number of tools to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, query, options) => {
|
|
66657
68056
|
await executeOperation(caplet, options.limit === void 0 ? {
|
|
66658
68057
|
operation: "search_tools",
|
|
66659
68058
|
query
|
|
@@ -66671,7 +68070,7 @@ function createProgram(io = {}) {
|
|
|
66671
68070
|
format: options.format
|
|
66672
68071
|
});
|
|
66673
68072
|
});
|
|
66674
|
-
program.command(
|
|
68073
|
+
program.command(cliCommands.getTool).description("Print one downstream tool schema.").argument("<caplet.tool>", "qualified target, split on the first dot").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (target, options) => {
|
|
66675
68074
|
const { caplet, tool } = parseQualifiedTarget(target);
|
|
66676
68075
|
await executeOperation(caplet, {
|
|
66677
68076
|
operation: "get_tool",
|
|
@@ -66686,7 +68085,7 @@ function createProgram(io = {}) {
|
|
|
66686
68085
|
format: options.format
|
|
66687
68086
|
});
|
|
66688
68087
|
});
|
|
66689
|
-
program.command(
|
|
68088
|
+
program.command(cliCommands.callTool).description("Call one downstream tool.").argument("<caplet.tool>", "qualified target, split on the first dot").option("--args <json-object>", "JSON object of downstream tool arguments").option("--field <path>", "project a field from structured output", collect, []).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (target, options) => {
|
|
66690
68089
|
const { caplet, tool } = parseQualifiedTarget(target);
|
|
66691
68090
|
await executeOperation(caplet, {
|
|
66692
68091
|
operation: "call_tool",
|
|
@@ -66703,7 +68102,119 @@ function createProgram(io = {}) {
|
|
|
66703
68102
|
format: options.format
|
|
66704
68103
|
});
|
|
66705
68104
|
});
|
|
66706
|
-
|
|
68105
|
+
program.command(cliCommands.listResources).description("List MCP resources for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of resources to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "list_resources" } : {
|
|
68106
|
+
operation: "list_resources",
|
|
68107
|
+
limit: options.limit
|
|
68108
|
+
}, {
|
|
68109
|
+
writeOut,
|
|
68110
|
+
writeErr,
|
|
68111
|
+
setExitCode,
|
|
68112
|
+
authDir: io.authDir,
|
|
68113
|
+
env,
|
|
68114
|
+
remote: remoteClientForCli(io),
|
|
68115
|
+
format: options.format
|
|
68116
|
+
}));
|
|
68117
|
+
program.command(cliCommands.searchResources).description("Search MCP resources and resource templates for a configured MCP Caplet.").argument("<caplet>").argument("<query>").option("--limit <n>", "maximum number of matches to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, query, options) => executeOperation(caplet, options.limit === void 0 ? {
|
|
68118
|
+
operation: "search_resources",
|
|
68119
|
+
query
|
|
68120
|
+
} : {
|
|
68121
|
+
operation: "search_resources",
|
|
68122
|
+
query,
|
|
68123
|
+
limit: options.limit
|
|
68124
|
+
}, {
|
|
68125
|
+
writeOut,
|
|
68126
|
+
writeErr,
|
|
68127
|
+
setExitCode,
|
|
68128
|
+
authDir: io.authDir,
|
|
68129
|
+
env,
|
|
68130
|
+
remote: remoteClientForCli(io),
|
|
68131
|
+
format: options.format
|
|
68132
|
+
}));
|
|
68133
|
+
program.command(cliCommands.listResourceTemplates).description("List MCP resource templates for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of templates to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "list_resource_templates" } : {
|
|
68134
|
+
operation: "list_resource_templates",
|
|
68135
|
+
limit: options.limit
|
|
68136
|
+
}, {
|
|
68137
|
+
writeOut,
|
|
68138
|
+
writeErr,
|
|
68139
|
+
setExitCode,
|
|
68140
|
+
authDir: io.authDir,
|
|
68141
|
+
env,
|
|
68142
|
+
remote: remoteClientForCli(io),
|
|
68143
|
+
format: options.format
|
|
68144
|
+
}));
|
|
68145
|
+
program.command(cliCommands.readResource).description("Read one MCP resource by URI.").argument("<caplet>").argument("<uri>").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, uri, options) => executeOperation(caplet, {
|
|
68146
|
+
operation: "read_resource",
|
|
68147
|
+
uri
|
|
68148
|
+
}, {
|
|
68149
|
+
writeOut,
|
|
68150
|
+
writeErr,
|
|
68151
|
+
setExitCode,
|
|
68152
|
+
authDir: io.authDir,
|
|
68153
|
+
env,
|
|
68154
|
+
remote: remoteClientForCli(io),
|
|
68155
|
+
format: options.format
|
|
68156
|
+
}));
|
|
68157
|
+
program.command(cliCommands.listPrompts).description("List MCP prompts for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of prompts to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "list_prompts" } : {
|
|
68158
|
+
operation: "list_prompts",
|
|
68159
|
+
limit: options.limit
|
|
68160
|
+
}, {
|
|
68161
|
+
writeOut,
|
|
68162
|
+
writeErr,
|
|
68163
|
+
setExitCode,
|
|
68164
|
+
authDir: io.authDir,
|
|
68165
|
+
env,
|
|
68166
|
+
remote: remoteClientForCli(io),
|
|
68167
|
+
format: options.format
|
|
68168
|
+
}));
|
|
68169
|
+
program.command(cliCommands.searchPrompts).description("Search MCP prompts for a configured MCP Caplet.").argument("<caplet>").argument("<query>").option("--limit <n>", "maximum number of prompts to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, query, options) => executeOperation(caplet, options.limit === void 0 ? {
|
|
68170
|
+
operation: "search_prompts",
|
|
68171
|
+
query
|
|
68172
|
+
} : {
|
|
68173
|
+
operation: "search_prompts",
|
|
68174
|
+
query,
|
|
68175
|
+
limit: options.limit
|
|
68176
|
+
}, {
|
|
68177
|
+
writeOut,
|
|
68178
|
+
writeErr,
|
|
68179
|
+
setExitCode,
|
|
68180
|
+
authDir: io.authDir,
|
|
68181
|
+
env,
|
|
68182
|
+
remote: remoteClientForCli(io),
|
|
68183
|
+
format: options.format
|
|
68184
|
+
}));
|
|
68185
|
+
program.command(cliCommands.getPrompt).description("Get one MCP prompt by name.").argument("<caplet.prompt>", "qualified target, split on the first dot").option("--args <json-object>", "JSON object of prompt arguments").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (target, options) => {
|
|
68186
|
+
const { caplet, tool: prompt } = parseQualifiedTarget(target);
|
|
68187
|
+
await executeOperation(caplet, {
|
|
68188
|
+
operation: "get_prompt",
|
|
68189
|
+
prompt,
|
|
68190
|
+
arguments: parseJsonObjectOption(options.args, "get-prompt --args")
|
|
68191
|
+
}, {
|
|
68192
|
+
writeOut,
|
|
68193
|
+
writeErr,
|
|
68194
|
+
setExitCode,
|
|
68195
|
+
authDir: io.authDir,
|
|
68196
|
+
env,
|
|
68197
|
+
remote: remoteClientForCli(io),
|
|
68198
|
+
format: options.format
|
|
68199
|
+
});
|
|
68200
|
+
});
|
|
68201
|
+
program.command(cliCommands.complete).description("Complete an MCP prompt or resource-template argument.").argument("<caplet>").requiredOption("--argument <name>", "argument name").option("--value <value>", "argument prefix", "").option("--prompt <name>", "prompt name to complete").option("--resource-template <uri-template>", "resource template URI to complete").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, {
|
|
68202
|
+
operation: "complete",
|
|
68203
|
+
ref: completionRefFromOptions(options),
|
|
68204
|
+
argument: {
|
|
68205
|
+
name: options.argument,
|
|
68206
|
+
value: options.value
|
|
68207
|
+
}
|
|
68208
|
+
}, {
|
|
68209
|
+
writeOut,
|
|
68210
|
+
writeErr,
|
|
68211
|
+
setExitCode,
|
|
68212
|
+
authDir: io.authDir,
|
|
68213
|
+
env,
|
|
68214
|
+
remote: remoteClientForCli(io),
|
|
68215
|
+
format: options.format
|
|
68216
|
+
}));
|
|
68217
|
+
const config = program.command(cliCommands.config).description("Inspect Caplets config locations.");
|
|
66707
68218
|
config.command("path").description("Print the effective user config path.").action(() => {
|
|
66708
68219
|
writeOut(`${resolveConfigPath(currentConfigPath())}\n`);
|
|
66709
68220
|
});
|
|
@@ -66715,7 +68226,7 @@ function createProgram(io = {}) {
|
|
|
66715
68226
|
}
|
|
66716
68227
|
writeOut(formatConfigPaths(paths, options.format ?? "plain"));
|
|
66717
68228
|
});
|
|
66718
|
-
const auth = program.command(
|
|
68229
|
+
const auth = program.command(cliCommands.auth).description("Manage OAuth credentials for remote servers.");
|
|
66719
68230
|
auth.command("login").description("Authenticate a configured remote OAuth server.").argument("<server>", "configured server ID").option("--no-open", "print the authorization URL without opening a browser").action(async (serverId, options) => {
|
|
66720
68231
|
const remote = remoteClientForCli(io);
|
|
66721
68232
|
if (remote) {
|
|
@@ -66800,7 +68311,15 @@ function remoteCommandForOperation(operation) {
|
|
|
66800
68311
|
case "list_tools":
|
|
66801
68312
|
case "search_tools":
|
|
66802
68313
|
case "get_tool":
|
|
66803
|
-
case "call_tool":
|
|
68314
|
+
case "call_tool":
|
|
68315
|
+
case "list_resources":
|
|
68316
|
+
case "search_resources":
|
|
68317
|
+
case "list_resource_templates":
|
|
68318
|
+
case "read_resource":
|
|
68319
|
+
case "list_prompts":
|
|
68320
|
+
case "search_prompts":
|
|
68321
|
+
case "get_prompt":
|
|
68322
|
+
case "complete": return operation;
|
|
66804
68323
|
default: return;
|
|
66805
68324
|
}
|
|
66806
68325
|
}
|
|
@@ -66848,6 +68367,29 @@ function parseCallToolArgs(value) {
|
|
|
66848
68367
|
if (!isPlainObject(parsed)) throw new CapletsError("REQUEST_INVALID", "call-tool --args must be a JSON object");
|
|
66849
68368
|
return parsed;
|
|
66850
68369
|
}
|
|
68370
|
+
function parseJsonObjectOption(value, label) {
|
|
68371
|
+
if (value === void 0) return {};
|
|
68372
|
+
let parsed;
|
|
68373
|
+
try {
|
|
68374
|
+
parsed = JSON.parse(value);
|
|
68375
|
+
} catch (error) {
|
|
68376
|
+
throw new CapletsError("REQUEST_INVALID", `${label} must be valid JSON`, error);
|
|
68377
|
+
}
|
|
68378
|
+
if (!isPlainObject(parsed)) throw new CapletsError("REQUEST_INVALID", `${label} must be a JSON object`);
|
|
68379
|
+
return parsed;
|
|
68380
|
+
}
|
|
68381
|
+
function completionRefFromOptions(options) {
|
|
68382
|
+
if (options.prompt && options.resourceTemplate) throw new CapletsError("REQUEST_INVALID", "complete accepts either --prompt or --resource-template, not both");
|
|
68383
|
+
if (options.prompt) return {
|
|
68384
|
+
type: "prompt",
|
|
68385
|
+
name: options.prompt
|
|
68386
|
+
};
|
|
68387
|
+
if (options.resourceTemplate) return {
|
|
68388
|
+
type: "resourceTemplate",
|
|
68389
|
+
uri: options.resourceTemplate
|
|
68390
|
+
};
|
|
68391
|
+
throw new CapletsError("REQUEST_INVALID", "complete requires --prompt or --resource-template");
|
|
68392
|
+
}
|
|
66851
68393
|
function isPlainObject(value) {
|
|
66852
68394
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
66853
68395
|
}
|
|
@@ -66978,6 +68520,55 @@ function markdownSummaryForOperation(result, request) {
|
|
|
66978
68520
|
"",
|
|
66979
68521
|
"Use `--format json` to inspect the full structured result."
|
|
66980
68522
|
].filter((line) => line !== void 0).join("\n");
|
|
68523
|
+
case "list_resources":
|
|
68524
|
+
case "search_resources": {
|
|
68525
|
+
const resources = Array.isArray(payload.resources) ? payload.resources : [];
|
|
68526
|
+
const templates = Array.isArray(payload.resourceTemplates) ? payload.resourceTemplates : [];
|
|
68527
|
+
const matches = Array.isArray(payload.matches) ? payload.matches : [...resources, ...templates];
|
|
68528
|
+
return [
|
|
68529
|
+
`## MCP resources for \`${id}\``,
|
|
68530
|
+
"",
|
|
68531
|
+
`${matches.length} item${matches.length === 1 ? "" : "s"} found.`,
|
|
68532
|
+
"",
|
|
68533
|
+
...formatResourceLines(matches, "markdown")
|
|
68534
|
+
].join("\n");
|
|
68535
|
+
}
|
|
68536
|
+
case "list_resource_templates": {
|
|
68537
|
+
const templates = Array.isArray(payload.resourceTemplates) ? payload.resourceTemplates : [];
|
|
68538
|
+
return [
|
|
68539
|
+
`## MCP resource templates for \`${id}\``,
|
|
68540
|
+
"",
|
|
68541
|
+
...formatResourceLines(templates, "markdown")
|
|
68542
|
+
].join("\n");
|
|
68543
|
+
}
|
|
68544
|
+
case "read_resource": return [
|
|
68545
|
+
`## Resource \`${String(request.uri ?? "")}\``,
|
|
68546
|
+
"",
|
|
68547
|
+
summarizeResourceRead(payload),
|
|
68548
|
+
"",
|
|
68549
|
+
"Use `--format json` to inspect all contents."
|
|
68550
|
+
].join("\n");
|
|
68551
|
+
case "list_prompts":
|
|
68552
|
+
case "search_prompts": {
|
|
68553
|
+
const prompts = Array.isArray(payload.prompts) ? payload.prompts : [];
|
|
68554
|
+
return [
|
|
68555
|
+
`## MCP prompts for \`${id}\``,
|
|
68556
|
+
"",
|
|
68557
|
+
...formatPromptLines(prompts, "markdown")
|
|
68558
|
+
].join("\n");
|
|
68559
|
+
}
|
|
68560
|
+
case "get_prompt": return [
|
|
68561
|
+
`## Prompt \`${String(request.caplet)}.${String(request.prompt)}\``,
|
|
68562
|
+
"",
|
|
68563
|
+
summarizePromptResult(payload),
|
|
68564
|
+
"",
|
|
68565
|
+
"Use `--format json` to inspect all messages."
|
|
68566
|
+
].join("\n");
|
|
68567
|
+
case "complete": return [
|
|
68568
|
+
`## Completion for \`${id}\``,
|
|
68569
|
+
"",
|
|
68570
|
+
summarizeCompletionResult(payload)
|
|
68571
|
+
].join("\n");
|
|
66981
68572
|
default: return JSON.stringify(payload, null, 2);
|
|
66982
68573
|
}
|
|
66983
68574
|
}
|
|
@@ -67034,6 +68625,33 @@ function plainSummaryForOperation(result, request) {
|
|
|
67034
68625
|
`Result: ${summarizeCallResult(payload)}`,
|
|
67035
68626
|
"Use --format json to inspect the full structured result."
|
|
67036
68627
|
].filter((line) => Boolean(line)).join("\n");
|
|
68628
|
+
case "list_resources":
|
|
68629
|
+
case "search_resources": {
|
|
68630
|
+
const resources = Array.isArray(payload.resources) ? payload.resources : [];
|
|
68631
|
+
const templates = Array.isArray(payload.resourceTemplates) ? payload.resourceTemplates : [];
|
|
68632
|
+
const matches = Array.isArray(payload.matches) ? payload.matches : [...resources, ...templates];
|
|
68633
|
+
return [`MCP resources for ${id} (${matches.length}):`, ...formatResourceLines(matches, "plain")].join("\n");
|
|
68634
|
+
}
|
|
68635
|
+
case "list_resource_templates": {
|
|
68636
|
+
const templates = Array.isArray(payload.resourceTemplates) ? payload.resourceTemplates : [];
|
|
68637
|
+
return [`MCP resource templates for ${id}:`, ...formatResourceLines(templates, "plain")].join("\n");
|
|
68638
|
+
}
|
|
68639
|
+
case "read_resource": return [
|
|
68640
|
+
`Resource ${String(request.uri ?? "")}`,
|
|
68641
|
+
summarizeResourceRead(payload),
|
|
68642
|
+
"Use --format json to inspect all contents."
|
|
68643
|
+
].join("\n");
|
|
68644
|
+
case "list_prompts":
|
|
68645
|
+
case "search_prompts": {
|
|
68646
|
+
const prompts = Array.isArray(payload.prompts) ? payload.prompts : [];
|
|
68647
|
+
return [`MCP prompts for ${id}:`, ...formatPromptLines(prompts, "plain")].join("\n");
|
|
68648
|
+
}
|
|
68649
|
+
case "get_prompt": return [
|
|
68650
|
+
`Prompt ${String(request.caplet)}.${String(request.prompt)}`,
|
|
68651
|
+
summarizePromptResult(payload),
|
|
68652
|
+
"Use --format json to inspect all messages."
|
|
68653
|
+
].join("\n");
|
|
68654
|
+
case "complete": return [`Completion for ${id}`, summarizeCompletionResult(payload)].join("\n");
|
|
67037
68655
|
default: return JSON.stringify(payload, null, 2);
|
|
67038
68656
|
}
|
|
67039
68657
|
}
|
|
@@ -67050,6 +68668,44 @@ function formatToolLines(tools, format) {
|
|
|
67050
68668
|
return `- ${displayName}${flags ? ` (${flags})` : ""}${tool.description ? ` — ${compactDescription(String(tool.description))}` : ""}`;
|
|
67051
68669
|
});
|
|
67052
68670
|
}
|
|
68671
|
+
function formatResourceLines(resources, format) {
|
|
68672
|
+
if (resources.length === 0) return ["- none"];
|
|
68673
|
+
return resources.map((resource) => {
|
|
68674
|
+
if (!isPlainObject(resource)) return `- ${String(resource)}`;
|
|
68675
|
+
const name = String(resource.uri ?? resource.uriTemplate ?? "unknown");
|
|
68676
|
+
const displayName = format === "markdown" ? `\`${name}\`` : name;
|
|
68677
|
+
const label = typeof resource.name === "string" ? ` (${resource.name})` : "";
|
|
68678
|
+
return `- ${typeof resource.kind === "string" ? `${resource.kind}: ` : ""}${displayName}${label}${resource.description ? ` — ${compactDescription(String(resource.description))}` : ""}`;
|
|
68679
|
+
});
|
|
68680
|
+
}
|
|
68681
|
+
function formatPromptLines(prompts, format) {
|
|
68682
|
+
if (prompts.length === 0) return ["- none"];
|
|
68683
|
+
return prompts.map((prompt) => {
|
|
68684
|
+
if (!isPlainObject(prompt)) return `- ${String(prompt)}`;
|
|
68685
|
+
const name = String(prompt.prompt ?? prompt.name ?? "unknown");
|
|
68686
|
+
return `- ${format === "markdown" ? `\`${name}\`` : name}${Array.isArray(prompt.arguments) ? ` (${prompt.arguments.length} args)` : ""}${prompt.description ? ` — ${compactDescription(String(prompt.description))}` : ""}`;
|
|
68687
|
+
});
|
|
68688
|
+
}
|
|
68689
|
+
function summarizeResourceRead(payload) {
|
|
68690
|
+
const contents = Array.isArray(payload.contents) ? payload.contents : [];
|
|
68691
|
+
if (contents.length === 0) return "No contents returned.";
|
|
68692
|
+
const first = contents.find(isPlainObject);
|
|
68693
|
+
if (!first) return `${contents.length} content item${contents.length === 1 ? "" : "s"} returned.`;
|
|
68694
|
+
return previewValue(typeof first.text === "string" ? first.text : first.blob) ?? `${contents.length} content item${contents.length === 1 ? "" : "s"} returned.`;
|
|
68695
|
+
}
|
|
68696
|
+
function summarizePromptResult(payload) {
|
|
68697
|
+
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
68698
|
+
if (messages.length === 0) return "No messages returned.";
|
|
68699
|
+
const first = messages.find(isPlainObject);
|
|
68700
|
+
if (!first) return `${messages.length} message${messages.length === 1 ? "" : "s"} returned.`;
|
|
68701
|
+
return previewValue((isPlainObject(first.content) ? first.content : void 0)?.text ?? first.content) ?? `${messages.length} message${messages.length === 1 ? "" : "s"} returned.`;
|
|
68702
|
+
}
|
|
68703
|
+
function summarizeCompletionResult(payload) {
|
|
68704
|
+
const completion = isPlainObject(payload.completion) ? payload.completion : void 0;
|
|
68705
|
+
const values = Array.isArray(completion?.values) ? completion.values : [];
|
|
68706
|
+
if (values.length > 0) return values.map((value) => `- ${String(value)}`).join("\n");
|
|
68707
|
+
return previewValue(payload) ?? "No completions returned.";
|
|
68708
|
+
}
|
|
67053
68709
|
function compactDescription(value) {
|
|
67054
68710
|
const firstParagraph = value.trim().split(/\n\s*\n/u)[0] ?? "";
|
|
67055
68711
|
const collapsed = (firstParagraph.match(/^.*?(?:[.!?](?=\s|$)|$)/u)?.[0] ?? firstParagraph).replace(/\s+/gu, " ").trim();
|
|
@@ -67124,7 +68780,7 @@ function writeAddResult(writeOut, label, result) {
|
|
|
67124
68780
|
}
|
|
67125
68781
|
//#endregion
|
|
67126
68782
|
//#region package.json
|
|
67127
|
-
var version = "0.
|
|
68783
|
+
var version = "0.17.1";
|
|
67128
68784
|
//#endregion
|
|
67129
68785
|
//#region src/index.ts
|
|
67130
68786
|
async function main() {
|