@caplets/core 0.18.2 → 0.18.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/caplet-files.d.ts +8 -0
- package/dist/cli/auth.d.ts +26 -2
- package/dist/cli/inspection.d.ts +2 -2
- package/dist/{completion-L23s2FGB.js → completion-DRPTunQd.js} +6 -5
- package/dist/config.d.ts +11 -0
- package/dist/engine.d.ts +2 -0
- package/dist/index.js +429 -139
- package/dist/native/service.d.ts +6 -0
- package/dist/native.js +129 -12
- package/dist/{options-bnsSREid.js → options-BlNyqF_E.js} +320 -19
- package/package.json +7 -5
|
@@ -8380,6 +8380,82 @@ function loadCapletFilesWithPaths(root) {
|
|
|
8380
8380
|
paths
|
|
8381
8381
|
} : void 0;
|
|
8382
8382
|
}
|
|
8383
|
+
function loadCapletFilesWithPathsBestEffort(root) {
|
|
8384
|
+
if (!existsSync(root)) return;
|
|
8385
|
+
const warnings = [];
|
|
8386
|
+
return buildCapletFileLoadResult(root, discoverCapletFilesBestEffort(root, warnings), warnings);
|
|
8387
|
+
}
|
|
8388
|
+
function buildCapletFileLoadResult(root, candidates, warnings) {
|
|
8389
|
+
const servers = {};
|
|
8390
|
+
const openapiEndpoints = {};
|
|
8391
|
+
const graphqlEndpoints = {};
|
|
8392
|
+
const httpApis = {};
|
|
8393
|
+
const cliTools = {};
|
|
8394
|
+
const capletSets = {};
|
|
8395
|
+
const paths = {};
|
|
8396
|
+
function hasId(id) {
|
|
8397
|
+
return Boolean(servers[id] || openapiEndpoints[id] || graphqlEndpoints[id] || httpApis[id] || cliTools[id] || capletSets[id]);
|
|
8398
|
+
}
|
|
8399
|
+
for (const candidate of candidates) {
|
|
8400
|
+
if (hasId(candidate.id)) {
|
|
8401
|
+
const message = `Duplicate Caplet ID ${candidate.id} under ${root}`;
|
|
8402
|
+
if (!warnings) throw new CapletsError("CONFIG_INVALID", message);
|
|
8403
|
+
warnings.push({
|
|
8404
|
+
path: candidate.path,
|
|
8405
|
+
message: `${message}; skipping duplicate at ${candidate.path}`
|
|
8406
|
+
});
|
|
8407
|
+
continue;
|
|
8408
|
+
}
|
|
8409
|
+
let config;
|
|
8410
|
+
try {
|
|
8411
|
+
config = readCapletFile(candidate.path);
|
|
8412
|
+
} catch (error) {
|
|
8413
|
+
if (!warnings) throw error;
|
|
8414
|
+
warnings.push({
|
|
8415
|
+
path: candidate.path,
|
|
8416
|
+
message: `Skipping invalid Caplet file at ${candidate.path}: ${errorMessage$1(error)}`
|
|
8417
|
+
});
|
|
8418
|
+
continue;
|
|
8419
|
+
}
|
|
8420
|
+
paths[candidate.id] = candidate.path;
|
|
8421
|
+
if (isPlainObject$5(config) && config.backend === "openapi") {
|
|
8422
|
+
const { backend: _backend, ...endpoint } = config;
|
|
8423
|
+
openapiEndpoints[candidate.id] = endpoint;
|
|
8424
|
+
} else if (isPlainObject$5(config) && config.backend === "graphql") {
|
|
8425
|
+
const { backend: _backend, ...endpoint } = config;
|
|
8426
|
+
graphqlEndpoints[candidate.id] = endpoint;
|
|
8427
|
+
} else if (isPlainObject$5(config) && config.backend === "http") {
|
|
8428
|
+
const { backend: _backend, ...endpoint } = config;
|
|
8429
|
+
httpApis[candidate.id] = endpoint;
|
|
8430
|
+
} else if (isPlainObject$5(config) && config.backend === "cli") {
|
|
8431
|
+
const { backend: _backend, ...endpoint } = config;
|
|
8432
|
+
cliTools[candidate.id] = endpoint;
|
|
8433
|
+
} else if (isPlainObject$5(config) && config.backend === "caplets") {
|
|
8434
|
+
const { backend: _backend, ...endpoint } = config;
|
|
8435
|
+
capletSets[candidate.id] = endpoint;
|
|
8436
|
+
} else servers[candidate.id] = config;
|
|
8437
|
+
}
|
|
8438
|
+
const hasServers = Object.keys(servers).length > 0;
|
|
8439
|
+
const hasOpenApi = Object.keys(openapiEndpoints).length > 0;
|
|
8440
|
+
const hasGraphQl = Object.keys(graphqlEndpoints).length > 0;
|
|
8441
|
+
const hasHttpApis = Object.keys(httpApis).length > 0;
|
|
8442
|
+
const hasCliTools = Object.keys(cliTools).length > 0;
|
|
8443
|
+
const hasCapletSets = Object.keys(capletSets).length > 0;
|
|
8444
|
+
const config = {
|
|
8445
|
+
...hasServers ? { mcpServers: servers } : {},
|
|
8446
|
+
...hasOpenApi ? { openapiEndpoints } : {},
|
|
8447
|
+
...hasGraphQl ? { graphqlEndpoints } : {},
|
|
8448
|
+
...hasHttpApis ? { httpApis } : {},
|
|
8449
|
+
...hasCliTools ? { cliTools } : {},
|
|
8450
|
+
...hasCapletSets ? { capletSets } : {}
|
|
8451
|
+
};
|
|
8452
|
+
if (!(Object.keys(config).length > 0) && warnings?.length === 0) return;
|
|
8453
|
+
return {
|
|
8454
|
+
config,
|
|
8455
|
+
paths,
|
|
8456
|
+
warnings: warnings ?? []
|
|
8457
|
+
};
|
|
8458
|
+
}
|
|
8383
8459
|
function discoverCapletFiles(root) {
|
|
8384
8460
|
const entries = readdirSync(root, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
8385
8461
|
const candidates = [];
|
|
@@ -8404,6 +8480,82 @@ function discoverCapletFiles(root) {
|
|
|
8404
8480
|
}
|
|
8405
8481
|
return candidates;
|
|
8406
8482
|
}
|
|
8483
|
+
function discoverCapletFilesBestEffort(root, warnings) {
|
|
8484
|
+
const entries = readdirSync(root, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
|
|
8485
|
+
const byId = /* @__PURE__ */ new Map();
|
|
8486
|
+
const duplicateIds = /* @__PURE__ */ new Set();
|
|
8487
|
+
function addCandidate(id, path, isDirectoryCaplet) {
|
|
8488
|
+
try {
|
|
8489
|
+
validateCapletId(id, path);
|
|
8490
|
+
} catch (error) {
|
|
8491
|
+
warnings.push({
|
|
8492
|
+
path,
|
|
8493
|
+
message: `Skipping invalid Caplet file at ${path}: ${errorMessage$1(error)}`
|
|
8494
|
+
});
|
|
8495
|
+
return;
|
|
8496
|
+
}
|
|
8497
|
+
if (duplicateIds.has(id)) {
|
|
8498
|
+
warnings.push({
|
|
8499
|
+
path,
|
|
8500
|
+
message: `Duplicate Caplet ID ${id} under ${root}; skipping duplicate at ${path}`
|
|
8501
|
+
});
|
|
8502
|
+
return;
|
|
8503
|
+
}
|
|
8504
|
+
const existing = byId.get(id);
|
|
8505
|
+
if (!existing) {
|
|
8506
|
+
byId.set(id, {
|
|
8507
|
+
id,
|
|
8508
|
+
path,
|
|
8509
|
+
isDirectoryCaplet
|
|
8510
|
+
});
|
|
8511
|
+
return;
|
|
8512
|
+
}
|
|
8513
|
+
if (isDirectoryCaplet && !existing.isDirectoryCaplet) {
|
|
8514
|
+
warnings.push({
|
|
8515
|
+
path: existing.path,
|
|
8516
|
+
message: `Caplet file at ${existing.path} was shadowed by ${path}`
|
|
8517
|
+
});
|
|
8518
|
+
byId.set(id, {
|
|
8519
|
+
id,
|
|
8520
|
+
path,
|
|
8521
|
+
isDirectoryCaplet
|
|
8522
|
+
});
|
|
8523
|
+
return;
|
|
8524
|
+
}
|
|
8525
|
+
if (!isDirectoryCaplet && existing.isDirectoryCaplet) {
|
|
8526
|
+
warnings.push({
|
|
8527
|
+
path,
|
|
8528
|
+
message: `Caplet file at ${path} was shadowed by ${existing.path}`
|
|
8529
|
+
});
|
|
8530
|
+
return;
|
|
8531
|
+
}
|
|
8532
|
+
warnings.push({
|
|
8533
|
+
path,
|
|
8534
|
+
message: `Duplicate Caplet ID ${id} under ${root}; skipping ${existing.path} and ${path}`
|
|
8535
|
+
});
|
|
8536
|
+
byId.delete(id);
|
|
8537
|
+
duplicateIds.add(id);
|
|
8538
|
+
}
|
|
8539
|
+
for (const entry of entries) {
|
|
8540
|
+
if (entry.name === "auth" || entry.name === "config.json") continue;
|
|
8541
|
+
const path = join(root, entry.name);
|
|
8542
|
+
if (entry.isFile() && extname(entry.name).toLowerCase() === ".md") {
|
|
8543
|
+
addCandidate(basename(entry.name, extname(entry.name)), path, false);
|
|
8544
|
+
continue;
|
|
8545
|
+
}
|
|
8546
|
+
if (entry.isDirectory()) {
|
|
8547
|
+
const capletPath = join(path, "CAPLET.md");
|
|
8548
|
+
if (existsSync(capletPath) && statSync(capletPath).isFile()) addCandidate(entry.name, capletPath, true);
|
|
8549
|
+
}
|
|
8550
|
+
}
|
|
8551
|
+
return Array.from(byId.values()).map(({ id, path }) => ({
|
|
8552
|
+
id,
|
|
8553
|
+
path
|
|
8554
|
+
}));
|
|
8555
|
+
}
|
|
8556
|
+
function errorMessage$1(error) {
|
|
8557
|
+
return error instanceof Error ? error.message : String(error);
|
|
8558
|
+
}
|
|
8407
8559
|
function readCapletFile(path) {
|
|
8408
8560
|
if (statSync(path).size > MAX_CAPLET_FILE_BYTES) throw new CapletsError("CONFIG_INVALID", `Caplet file at ${path} exceeds the ${MAX_CAPLET_FILE_BYTES} byte limit`);
|
|
8409
8561
|
const { frontmatter, body } = parseFrontmatter(readFileSync(path, "utf8"), path);
|
|
@@ -9084,35 +9236,78 @@ function loadConfigWithSources(path = resolveConfigPath(), projectPath = resolve
|
|
|
9084
9236
|
const projectConfig = hasProjectConfig ? rejectProjectConfigExecutableBackendMaps(readPublicConfigInput(projectPath), projectPath) : void 0;
|
|
9085
9237
|
const projectCapletsRoot = resolveProjectCapletsRootForConfigPath(projectPath);
|
|
9086
9238
|
const projectCaplets = projectCapletsRoot ? loadCapletFilesWithPaths(projectCapletsRoot) : void 0;
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
const { input, sources, shadows } = mergeConfigInputsWithSources({
|
|
9239
|
+
return buildConfigWithSources([
|
|
9240
|
+
{
|
|
9090
9241
|
input: userConfig,
|
|
9091
9242
|
source: {
|
|
9092
9243
|
kind: "global-config",
|
|
9093
9244
|
path
|
|
9094
9245
|
}
|
|
9095
|
-
},
|
|
9246
|
+
},
|
|
9247
|
+
userCaplets ? {
|
|
9096
9248
|
input: userCaplets.config,
|
|
9097
9249
|
source: {
|
|
9098
9250
|
kind: "global-file",
|
|
9099
9251
|
path: userCaplets.paths
|
|
9100
9252
|
}
|
|
9101
|
-
} : void 0,
|
|
9253
|
+
} : void 0,
|
|
9254
|
+
{
|
|
9102
9255
|
input: projectConfig,
|
|
9103
9256
|
source: {
|
|
9104
9257
|
kind: "project-config",
|
|
9105
9258
|
path: projectPath
|
|
9106
9259
|
}
|
|
9107
|
-
},
|
|
9260
|
+
},
|
|
9261
|
+
projectCaplets ? {
|
|
9108
9262
|
input: projectCaplets.config,
|
|
9109
9263
|
source: {
|
|
9110
9264
|
kind: "project-file",
|
|
9111
9265
|
path: projectCaplets.paths
|
|
9112
9266
|
}
|
|
9113
|
-
} : void 0
|
|
9267
|
+
} : void 0
|
|
9268
|
+
], `Caplets config not found at ${path} or ${projectPath}`, "Caplets config must define at least one MCP server, OpenAPI endpoint, GraphQL endpoint, HTTP API, CLI tools backend, or Caplet set");
|
|
9269
|
+
}
|
|
9270
|
+
function loadGlobalConfig(path = resolveConfigPath()) {
|
|
9271
|
+
const userConfig = existsSync(path) ? readPublicConfigInput(path) : void 0;
|
|
9272
|
+
const userCaplets = loadCapletFilesWithPaths(resolveCapletsRoot(path));
|
|
9273
|
+
return buildConfigWithSources([{
|
|
9274
|
+
input: userConfig,
|
|
9275
|
+
source: {
|
|
9276
|
+
kind: "global-config",
|
|
9277
|
+
path
|
|
9278
|
+
}
|
|
9279
|
+
}, userCaplets ? {
|
|
9280
|
+
input: userCaplets.config,
|
|
9281
|
+
source: {
|
|
9282
|
+
kind: "global-file",
|
|
9283
|
+
path: userCaplets.paths
|
|
9284
|
+
}
|
|
9285
|
+
} : void 0], `Caplets user config not found at ${path}`, void 0).config;
|
|
9286
|
+
}
|
|
9287
|
+
function loadProjectConfig(projectPath = resolveProjectConfigPath()) {
|
|
9288
|
+
const projectConfig = existsSync(projectPath) ? rejectProjectConfigExecutableBackendMaps(readPublicConfigInput(projectPath), projectPath) : void 0;
|
|
9289
|
+
const projectCapletsRoot = resolveProjectCapletsRootForConfigPath(projectPath);
|
|
9290
|
+
const projectCaplets = projectCapletsRoot ? loadCapletFilesWithPaths(projectCapletsRoot) : void 0;
|
|
9291
|
+
return buildConfigWithSources([{
|
|
9292
|
+
input: projectConfig,
|
|
9293
|
+
source: {
|
|
9294
|
+
kind: "project-config",
|
|
9295
|
+
path: projectPath
|
|
9296
|
+
}
|
|
9297
|
+
}, projectCaplets ? {
|
|
9298
|
+
input: projectCaplets.config,
|
|
9299
|
+
source: {
|
|
9300
|
+
kind: "project-file",
|
|
9301
|
+
path: projectCaplets.paths
|
|
9302
|
+
}
|
|
9303
|
+
} : void 0], `Caplets project config not found at ${projectPath}`, void 0).config;
|
|
9304
|
+
}
|
|
9305
|
+
function buildConfigWithSources(inputs, notFoundMessage, emptyMessage) {
|
|
9306
|
+
if (!inputs.some((entry) => entry?.input !== void 0)) throw new CapletsError("CONFIG_NOT_FOUND", notFoundMessage);
|
|
9307
|
+
try {
|
|
9308
|
+
const { input, sources, shadows } = mergeConfigInputsWithSources(...inputs);
|
|
9114
9309
|
const config = parseConfig(input);
|
|
9115
|
-
if (Object.keys(config.mcpServers).length === 0 && Object.keys(config.openapiEndpoints).length === 0 && Object.keys(config.graphqlEndpoints).length === 0 && Object.keys(config.httpApis).length === 0 && Object.keys(config.cliTools).length === 0 && Object.keys(config.capletSets).length === 0) throw new CapletsError("CONFIG_INVALID",
|
|
9310
|
+
if (emptyMessage && Object.keys(config.mcpServers).length === 0 && Object.keys(config.openapiEndpoints).length === 0 && Object.keys(config.graphqlEndpoints).length === 0 && Object.keys(config.httpApis).length === 0 && Object.keys(config.cliTools).length === 0 && Object.keys(config.capletSets).length === 0) throw new CapletsError("CONFIG_INVALID", emptyMessage);
|
|
9116
9311
|
return {
|
|
9117
9312
|
config,
|
|
9118
9313
|
sources,
|
|
@@ -9123,6 +9318,74 @@ function loadConfigWithSources(path = resolveConfigPath(), projectPath = resolve
|
|
|
9123
9318
|
throw new CapletsError("CONFIG_INVALID", "Caplets config is not valid JSON", redactSecrets(error));
|
|
9124
9319
|
}
|
|
9125
9320
|
}
|
|
9321
|
+
function loadLocalOverlayConfigWithSources(path = resolveConfigPath(), projectPath = resolveProjectConfigPath()) {
|
|
9322
|
+
const warnings = [];
|
|
9323
|
+
const userConfig = existsSync(path) ? readBestEffortConfigInput(path, "global-config", warnings) : void 0;
|
|
9324
|
+
const userCaplets = loadBestEffortCapletFiles(resolveCapletsRoot(path), "global-file", warnings);
|
|
9325
|
+
const projectConfig = existsSync(projectPath) ? readBestEffortConfigInput(projectPath, "project-config", warnings, (input) => rejectProjectConfigExecutableBackendMaps(input, projectPath)) : void 0;
|
|
9326
|
+
const projectCapletsRoot = resolveProjectCapletsRootForConfigPath(projectPath);
|
|
9327
|
+
const projectCaplets = projectCapletsRoot ? loadBestEffortCapletFiles(projectCapletsRoot, "project-file", warnings) : void 0;
|
|
9328
|
+
const { input, sources, shadows } = mergeConfigInputsWithSources({
|
|
9329
|
+
input: userConfig,
|
|
9330
|
+
source: {
|
|
9331
|
+
kind: "global-config",
|
|
9332
|
+
path
|
|
9333
|
+
}
|
|
9334
|
+
}, userCaplets ? {
|
|
9335
|
+
input: userCaplets.config,
|
|
9336
|
+
source: {
|
|
9337
|
+
kind: "global-file",
|
|
9338
|
+
path: userCaplets.paths
|
|
9339
|
+
}
|
|
9340
|
+
} : void 0, {
|
|
9341
|
+
input: projectConfig,
|
|
9342
|
+
source: {
|
|
9343
|
+
kind: "project-config",
|
|
9344
|
+
path: projectPath
|
|
9345
|
+
}
|
|
9346
|
+
}, projectCaplets ? {
|
|
9347
|
+
input: projectCaplets.config,
|
|
9348
|
+
source: {
|
|
9349
|
+
kind: "project-file",
|
|
9350
|
+
path: projectCaplets.paths
|
|
9351
|
+
}
|
|
9352
|
+
} : void 0);
|
|
9353
|
+
return {
|
|
9354
|
+
config: parseConfig(input),
|
|
9355
|
+
sources,
|
|
9356
|
+
shadows,
|
|
9357
|
+
warnings
|
|
9358
|
+
};
|
|
9359
|
+
}
|
|
9360
|
+
function readBestEffortConfigInput(path, kind, warnings, transform) {
|
|
9361
|
+
try {
|
|
9362
|
+
const input = readPublicConfigInput(path);
|
|
9363
|
+
return transform ? transform(input) : input;
|
|
9364
|
+
} catch (error) {
|
|
9365
|
+
warnings.push({
|
|
9366
|
+
kind,
|
|
9367
|
+
path,
|
|
9368
|
+
message: errorMessage(error)
|
|
9369
|
+
});
|
|
9370
|
+
return;
|
|
9371
|
+
}
|
|
9372
|
+
}
|
|
9373
|
+
function loadBestEffortCapletFiles(root, kind, warnings) {
|
|
9374
|
+
const result = loadCapletFilesWithPathsBestEffort(root);
|
|
9375
|
+
if (!result) return;
|
|
9376
|
+
for (const warning of result.warnings) warnings.push({
|
|
9377
|
+
kind,
|
|
9378
|
+
path: warning.path ?? root,
|
|
9379
|
+
message: warning.message
|
|
9380
|
+
});
|
|
9381
|
+
return {
|
|
9382
|
+
config: result.config,
|
|
9383
|
+
paths: result.paths
|
|
9384
|
+
};
|
|
9385
|
+
}
|
|
9386
|
+
function errorMessage(error) {
|
|
9387
|
+
return error instanceof Error ? error.message : String(error);
|
|
9388
|
+
}
|
|
9126
9389
|
function loadIsolatedConfig(options) {
|
|
9127
9390
|
if (!options.configPath && !options.capletsRoot) throw new CapletsError("CONFIG_INVALID", "Nested Caplet set must define at least one source: configPath or capletsRoot");
|
|
9128
9391
|
const configInput = options.configPath ? readPublicConfigInput(options.configPath) : void 0;
|
|
@@ -52655,8 +52918,21 @@ async function loadOpenApiSource(endpoint, authDir) {
|
|
|
52655
52918
|
if (endpoint.specPath) return endpoint.specPath;
|
|
52656
52919
|
if (!endpoint.specUrl) throw new CapletsError("CONFIG_INVALID", `${endpoint.server} is missing OpenAPI spec source`);
|
|
52657
52920
|
if (!endpoint.baseUrl) throw new CapletsError("CONFIG_INVALID", `${endpoint.server} must configure baseUrl when using remote specUrl`);
|
|
52658
|
-
|
|
52659
|
-
|
|
52921
|
+
return parseOpenApiSourceText(await fetchWithLimit(endpoint.specUrl, endpoint.requestTimeoutMs, shouldSendSpecAuth(endpoint) ? authHeaders(endpoint, authDir) : {}));
|
|
52922
|
+
}
|
|
52923
|
+
function parseOpenApiSourceText(source) {
|
|
52924
|
+
let parsed;
|
|
52925
|
+
try {
|
|
52926
|
+
parsed = JSON.parse(source);
|
|
52927
|
+
} catch (jsonError) {
|
|
52928
|
+
try {
|
|
52929
|
+
parsed = (0, import_dist$1.parse)(source);
|
|
52930
|
+
} catch {
|
|
52931
|
+
throw jsonError instanceof Error ? jsonError : new Error(String(jsonError));
|
|
52932
|
+
}
|
|
52933
|
+
}
|
|
52934
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("OpenAPI source must parse to an object");
|
|
52935
|
+
return parsed;
|
|
52660
52936
|
}
|
|
52661
52937
|
function extractOperations(endpoint, document) {
|
|
52662
52938
|
const operations = [];
|
|
@@ -52674,6 +52950,7 @@ function extractOperations(endpoint, document) {
|
|
|
52674
52950
|
const requestBody = requestBodyFor(operation);
|
|
52675
52951
|
const outputSchema = outputSchemaFor(operation);
|
|
52676
52952
|
const baseUrl = endpoint.baseUrl ?? firstServerUrl(document);
|
|
52953
|
+
const staticHeaders = staticHeaderDefaultsFor(endpoint, parameters);
|
|
52677
52954
|
validateOperationBaseUrl(endpoint, baseUrl);
|
|
52678
52955
|
operations.push({
|
|
52679
52956
|
name,
|
|
@@ -52681,15 +52958,32 @@ function extractOperations(endpoint, document) {
|
|
|
52681
52958
|
path,
|
|
52682
52959
|
...typeof operation.summary === "string" ? { summary: operation.summary } : {},
|
|
52683
52960
|
...typeof operation.description === "string" ? { description: operation.description } : {},
|
|
52684
|
-
inputSchema: inputSchemaFor(parameters, requestBody),
|
|
52961
|
+
inputSchema: inputSchemaFor(parameters, requestBody, staticHeaders),
|
|
52685
52962
|
...outputSchema ? { outputSchema } : {},
|
|
52686
52963
|
...requestBody?.contentType ? { requestBodyContentType: requestBody.contentType } : {},
|
|
52687
|
-
...baseUrl ? { baseUrl } : {}
|
|
52964
|
+
...baseUrl ? { baseUrl } : {},
|
|
52965
|
+
...Object.keys(staticHeaders).length ? { staticHeaders } : {}
|
|
52688
52966
|
});
|
|
52689
52967
|
}
|
|
52690
52968
|
}
|
|
52691
52969
|
return operations.sort((left, right) => left.name.localeCompare(right.name));
|
|
52692
52970
|
}
|
|
52971
|
+
function staticHeaderDefaultsFor(endpoint, parameters) {
|
|
52972
|
+
const configuredHeaderNames = configuredAuthHeaderNames(endpoint);
|
|
52973
|
+
const headers = {};
|
|
52974
|
+
for (const parameter of parameters) {
|
|
52975
|
+
if (parameter?.in !== "header" || typeof parameter.name !== "string") continue;
|
|
52976
|
+
const normalized = parameter.name.toLowerCase();
|
|
52977
|
+
if (configuredHeaderNames.has(normalized) || FORBIDDEN_ARGUMENT_HEADERS.has(normalized) && normalized !== "accept") continue;
|
|
52978
|
+
const defaultValue = parameter.schema?.default;
|
|
52979
|
+
if ([
|
|
52980
|
+
"string",
|
|
52981
|
+
"number",
|
|
52982
|
+
"boolean"
|
|
52983
|
+
].includes(typeof defaultValue)) headers[parameter.name] = String(defaultValue);
|
|
52984
|
+
}
|
|
52985
|
+
return headers;
|
|
52986
|
+
}
|
|
52693
52987
|
function requestBodyFor(operation) {
|
|
52694
52988
|
const requestBody = operation.requestBody;
|
|
52695
52989
|
if (!requestBody || typeof requestBody !== "object") return;
|
|
@@ -52750,19 +53044,20 @@ function structuredOutputSchema(bodySchema) {
|
|
|
52750
53044
|
}
|
|
52751
53045
|
};
|
|
52752
53046
|
}
|
|
52753
|
-
function inputSchemaFor(parameters, requestBody) {
|
|
53047
|
+
function inputSchemaFor(parameters, requestBody, staticHeaders = {}) {
|
|
52754
53048
|
const schema = {
|
|
52755
53049
|
type: "object",
|
|
52756
53050
|
additionalProperties: false,
|
|
52757
53051
|
properties: {}
|
|
52758
53052
|
};
|
|
52759
53053
|
const required = [];
|
|
53054
|
+
const protectedStaticHeaders = new Set(Object.keys(staticHeaders).map((key) => key.toLowerCase()).filter((key) => FORBIDDEN_ARGUMENT_HEADERS.has(key)));
|
|
52760
53055
|
for (const location of [
|
|
52761
53056
|
"path",
|
|
52762
53057
|
"query",
|
|
52763
53058
|
"header"
|
|
52764
53059
|
]) {
|
|
52765
|
-
const locationParameters = parameters.filter((parameter) => parameter?.in === location);
|
|
53060
|
+
const locationParameters = parameters.filter((parameter) => parameter?.in === location && !(location === "header" && protectedStaticHeaders.has(parameter.name?.toLowerCase())));
|
|
52766
53061
|
if (locationParameters.length === 0) continue;
|
|
52767
53062
|
const nestedRequired = locationParameters.filter((parameter) => parameter.required === true || location === "path").map((parameter) => parameter.name);
|
|
52768
53063
|
schema.properties[location] = {
|
|
@@ -52801,7 +53096,8 @@ function buildRequest(endpoint, operation, args, authDir) {
|
|
|
52801
53096
|
for (const [key, value] of Object.entries(asRecord(args.query))) if (value !== void 0 && value !== null) url.searchParams.append(key, serializeHttpValue("query", key, value));
|
|
52802
53097
|
const headers = new Headers();
|
|
52803
53098
|
applyAuth(headers, endpoint, authDir);
|
|
52804
|
-
const configuredHeaderNames =
|
|
53099
|
+
const configuredHeaderNames = configuredAuthHeaderNames(endpoint);
|
|
53100
|
+
for (const [key, value] of Object.entries(operation.staticHeaders ?? {})) if (!headers.has(key) && !configuredHeaderNames.has(key.toLowerCase())) headers.set(key, value);
|
|
52805
53101
|
for (const [key, value] of Object.entries(asRecord(args.header))) if (value !== void 0 && value !== null) {
|
|
52806
53102
|
const normalized = key.toLowerCase();
|
|
52807
53103
|
if (FORBIDDEN_ARGUMENT_HEADERS.has(normalized) || configuredHeaderNames.has(normalized)) throw new CapletsError("REQUEST_INVALID", `Header ${key} cannot be supplied by arguments`);
|
|
@@ -52847,6 +53143,9 @@ function asRecord(value) {
|
|
|
52847
53143
|
function applyAuth(headers, endpoint, authDir) {
|
|
52848
53144
|
for (const [key, value] of Object.entries(authHeaders(endpoint, authDir))) headers.set(key, value);
|
|
52849
53145
|
}
|
|
53146
|
+
function configuredAuthHeaderNames(endpoint) {
|
|
53147
|
+
return endpoint.auth.type === "headers" ? new Set(Object.keys(endpoint.auth.headers).map((key) => key.toLowerCase())) : /* @__PURE__ */ new Set();
|
|
53148
|
+
}
|
|
52850
53149
|
function authHeaders(endpoint, authDir) {
|
|
52851
53150
|
switch (endpoint.auth.type) {
|
|
52852
53151
|
case "none": return {};
|
|
@@ -53786,6 +54085,7 @@ var CapletsEngine = class {
|
|
|
53786
54085
|
watchDebounceMs;
|
|
53787
54086
|
watchEnabled;
|
|
53788
54087
|
writeErr;
|
|
54088
|
+
configLoader;
|
|
53789
54089
|
reloadListeners = /* @__PURE__ */ new Set();
|
|
53790
54090
|
watchers = [];
|
|
53791
54091
|
reloadTimer;
|
|
@@ -53798,7 +54098,8 @@ var CapletsEngine = class {
|
|
|
53798
54098
|
configPath: resolveConfigPath(options.configPath),
|
|
53799
54099
|
projectConfigPath: options.projectConfigPath ?? resolveProjectConfigPath()
|
|
53800
54100
|
};
|
|
53801
|
-
|
|
54101
|
+
this.configLoader = options.configLoader ?? loadConfig;
|
|
54102
|
+
const config = this.configLoader(this.paths.configPath, this.paths.projectConfigPath);
|
|
53802
54103
|
this.registry = new ServerRegistry(config);
|
|
53803
54104
|
this.downstream = new DownstreamManager(this.registry, selectAuthOptions(options.authDir));
|
|
53804
54105
|
this.openapi = new OpenApiManager(this.registry, selectAuthOptions(options.authDir));
|
|
@@ -53853,7 +54154,7 @@ var CapletsEngine = class {
|
|
|
53853
54154
|
}
|
|
53854
54155
|
}
|
|
53855
54156
|
async completeCliWords(words) {
|
|
53856
|
-
const { completeCliWords } = await import("./completion-
|
|
54157
|
+
const { completeCliWords } = await import("./completion-DRPTunQd.js").then((n) => n.r);
|
|
53857
54158
|
return await completeCliWords(words, {
|
|
53858
54159
|
config: this.registry.config,
|
|
53859
54160
|
managers: {
|
|
@@ -53913,7 +54214,7 @@ var CapletsEngine = class {
|
|
|
53913
54214
|
if (this.closed) return false;
|
|
53914
54215
|
let nextConfig;
|
|
53915
54216
|
try {
|
|
53916
|
-
nextConfig =
|
|
54217
|
+
nextConfig = this.configLoader(this.paths.configPath, this.paths.projectConfigPath);
|
|
53917
54218
|
} catch (error) {
|
|
53918
54219
|
this.writeErr(`Caplets config reload failed; keeping last known-good config.\n`);
|
|
53919
54220
|
this.writeErr(`${JSON.stringify(toSafeError(error, "CONFIG_INVALID"), null, 2)}\n`);
|
|
@@ -54193,4 +54494,4 @@ function hasEnv(value) {
|
|
|
54193
54494
|
return value !== void 0 && value.trim() !== "";
|
|
54194
54495
|
}
|
|
54195
54496
|
//#endregion
|
|
54196
|
-
export { assertCompleteRequestPrompt as $, CreateMessageResultSchema as A,
|
|
54497
|
+
export { assertCompleteRequestPrompt as $, CreateMessageResultSchema as A, CAPLETS_ERROR_CODES as At, JSONRPCMessageSchema as B, AjvJsonSchemaValidator as C, resolveCapletsRoot as Ct, CallToolRequestSchema as D, discoverCapletFiles as Dt, toJsonSchemaCompat as E, resolveProjectConfigPath as Et, EmptyResultSchema as F, __exportAll as Ft, ListRootsResultSchema as G, ListPromptsRequestSchema as H, ErrorCode as I, __require as It, McpError as J, ListToolsRequestSchema as K, GetPromptRequestSchema as L, __toESM as Lt, CreateTaskResultSchema as M, redactSecrets as Mt, DEFAULT_NEGOTIATED_PROTOCOL_VERSION as N, toSafeError as Nt, CallToolResultSchema as O, validateCapletFile as Ot, ElicitResultSchema as P, __commonJSMin as Pt, ToolListChangedNotificationSchema as Q, InitializeRequestSchema as R, assertToolsCallTaskCapability as S, DEFAULT_COMPLETION_CACHE_DIR as St, mergeCapabilities as T, resolveProjectCapletsRoot as Tt, ListResourceTemplatesRequestSchema as U, LATEST_PROTOCOL_VERSION as V, ListResourcesRequestSchema as W, SUPPORTED_PROTOCOL_VERSIONS as X, ReadResourceRequestSchema as Y, SetLevelRequestSchema as Z, StreamableHTTPClientTransport as _, loadGlobalConfig as _t, resolveCapletsServer as a, getLiteralValue as at, Client as b, parseConfig as bt, ServerRegistry as c, getSchemaDescription as ct, runOAuthFlow as d, normalizeObjectSchema as dt, assertCompleteRequestResourceTemplate as et, startGenericOAuthFlow as f, objectFromShape as ft, readTokenBundle as g, loadConfigWithSources as gt, isTokenBundleExpired as h, loadConfig as ht, resolveCapletsMode as i, isJSONRPCResultResponse as it, CreateMessageResultWithToolsSchema as j, CapletsError as jt, CompleteRequestSchema as k, SERVER_ID_PATTERN as kt, capabilityDescription as l, isSchemaOptional as lt, deleteTokenBundle as m, safeParseAsync as mt, mcpUrlForBase as n, isJSONRPCErrorResponse as nt, CapletsEngine as o, getObjectShape as ot, startOAuthFlow as p, safeParse as pt, LoggingLevelSchema as q, parseServerBaseUrl as r, isJSONRPCRequest as rt, handleServerTool as s, getParseErrorMessage as st, controlUrlForBase as t, isInitializeRequest as tt, runGenericOAuthFlow as u, isZ4Schema as ut, ReadBuffer as v, loadLocalOverlayConfigWithSources as vt, Protocol as w, resolveConfigPath as wt, assertClientRequestTaskCapability as x, DEFAULT_AUTH_DIR as xt, serializeMessage as y, loadProjectConfig as yt, InitializedNotificationSchema as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@caplets/core",
|
|
3
|
-
"version": "0.18.
|
|
3
|
+
"version": "0.18.4",
|
|
4
4
|
"description": "Core runtime library for Caplets progressive disclosure gateways.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"caplets",
|
|
@@ -50,14 +50,15 @@
|
|
|
50
50
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
51
51
|
"commander": "^14.0.3",
|
|
52
52
|
"graphql": "^16.14.0",
|
|
53
|
-
"hono": "^4.12.
|
|
53
|
+
"hono": "^4.12.22",
|
|
54
54
|
"vfile": "^6.0.3",
|
|
55
55
|
"vfile-matter": "^5.0.1",
|
|
56
|
+
"yaml": "^2.9.0",
|
|
56
57
|
"zod": "^4.4.3"
|
|
57
58
|
},
|
|
58
59
|
"devDependencies": {
|
|
59
60
|
"@types/node": "^25.9.1",
|
|
60
|
-
"@typescript/native-preview": "7.0.0-dev.
|
|
61
|
+
"@typescript/native-preview": "7.0.0-dev.20260523.1",
|
|
61
62
|
"rolldown": "^1.0.2",
|
|
62
63
|
"typescript": "^6.0.3",
|
|
63
64
|
"vitest": "^4.1.7"
|
|
@@ -66,8 +67,9 @@
|
|
|
66
67
|
"node": ">=22"
|
|
67
68
|
},
|
|
68
69
|
"scripts": {
|
|
69
|
-
"
|
|
70
|
-
"build
|
|
70
|
+
"clean": "rm -rf dist",
|
|
71
|
+
"build": "pnpm run clean && rolldown -c && tsc -p tsconfig.build.json",
|
|
72
|
+
"build:watch": "pnpm run clean && rolldown -c --watch",
|
|
71
73
|
"typecheck": "tsgo --noEmit",
|
|
72
74
|
"test": "vitest run"
|
|
73
75
|
}
|