@caplets/core 0.12.1 → 0.13.0

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.
@@ -1,4 +1,4 @@
1
- import { generatedToolInputDescriptions, operations } from "./generated-tool-input-schema.js";
1
+ import { generatedToolInputDescriptions, generatedToolInputJsonSchema, operations } from "./generated-tool-input-schema.js";
2
2
  import { createRequire } from "node:module";
3
3
  import { accessSync, chmodSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
4
4
  import minpath, { basename, delimiter, dirname, extname, isAbsolute, join, parse, posix, relative, resolve, win32 } from "node:path";
@@ -26433,6 +26433,24 @@ const capletCliToolsSchema = object({
26433
26433
  maxOutputBytes: number$1().int().positive().optional(),
26434
26434
  disabled: boolean().optional().describe("When true, omit this Caplet from discovery.")
26435
26435
  }).strict();
26436
+ const capletSetSchema = object({
26437
+ configPath: string().min(1).optional().describe("Child Caplets config.json path."),
26438
+ capletsRoot: string().min(1).optional().describe("Child Markdown Caplets root directory."),
26439
+ defaultSearchLimit: number$1().int().positive().optional(),
26440
+ maxSearchLimit: number$1().int().positive().max(50).optional(),
26441
+ toolCacheTtlMs: number$1().int().nonnegative().optional(),
26442
+ disabled: boolean().optional().describe("When true, omit this Caplet from discovery.")
26443
+ }).strict().superRefine((set, ctx) => {
26444
+ if (!set.configPath && !set.capletsRoot) ctx.addIssue({
26445
+ code: "custom",
26446
+ message: "capletSet must define at least one source: configPath or capletsRoot"
26447
+ });
26448
+ if (set.defaultSearchLimit !== void 0 && set.maxSearchLimit !== void 0 && set.defaultSearchLimit > set.maxSearchLimit) ctx.addIssue({
26449
+ code: "custom",
26450
+ path: ["defaultSearchLimit"],
26451
+ message: "defaultSearchLimit must be <= maxSearchLimit"
26452
+ });
26453
+ });
26436
26454
  const capletFileSchema = object({
26437
26455
  $schema: string().url().optional().describe("Optional JSON Schema URL for editor validation."),
26438
26456
  name: string().trim().min(1).max(80).describe("Human-readable Caplet display name."),
@@ -26442,13 +26460,17 @@ const capletFileSchema = object({
26442
26460
  openapiEndpoint: capletOpenApiEndpointSchema.describe("OpenAPI endpoint backend configuration for this Caplet.").optional(),
26443
26461
  graphqlEndpoint: capletGraphQlEndpointSchema.describe("GraphQL endpoint backend configuration for this Caplet.").optional(),
26444
26462
  httpApi: capletHttpApiSchema.describe("HTTP API backend configuration for this Caplet.").optional(),
26445
- cliTools: capletCliToolsSchema.describe("CLI tools backend configuration for this Caplet.").optional()
26463
+ cliTools: capletCliToolsSchema.describe("CLI tools backend configuration for this Caplet.").optional(),
26464
+ capletSet: capletSetSchema.describe("Nested Caplet collection backend configuration for this Caplet.").optional()
26446
26465
  }).strict().superRefine((frontmatter, ctx) => {
26447
- if (Number(Boolean(frontmatter.mcpServer)) + Number(Boolean(frontmatter.openapiEndpoint)) + Number(Boolean(frontmatter.graphqlEndpoint)) + Number(Boolean(frontmatter.httpApi)) + Number(Boolean(frontmatter.cliTools)) !== 1) ctx.addIssue({
26466
+ if (Number(Boolean(frontmatter.mcpServer)) + Number(Boolean(frontmatter.openapiEndpoint)) + Number(Boolean(frontmatter.graphqlEndpoint)) + Number(Boolean(frontmatter.httpApi)) + Number(Boolean(frontmatter.cliTools)) + Number(Boolean(frontmatter.capletSet)) !== 1) ctx.addIssue({
26448
26467
  code: "custom",
26449
- message: "Caplet file must define exactly one backend: mcpServer, openapiEndpoint, graphqlEndpoint, httpApi, or cliTools"
26468
+ message: "Caplet file must define exactly one backend: mcpServer, openapiEndpoint, graphqlEndpoint, httpApi, cliTools, or capletSet"
26450
26469
  });
26451
26470
  });
26471
+ function loadCapletFiles(root) {
26472
+ return loadCapletFilesWithPaths(root)?.config;
26473
+ }
26452
26474
  function loadCapletFilesWithPaths(root) {
26453
26475
  if (!existsSync(root)) return;
26454
26476
  const servers = {};
@@ -26456,9 +26478,10 @@ function loadCapletFilesWithPaths(root) {
26456
26478
  const graphqlEndpoints = {};
26457
26479
  const httpApis = {};
26458
26480
  const cliTools = {};
26481
+ const capletSets = {};
26459
26482
  const paths = {};
26460
26483
  for (const candidate of discoverCapletFiles(root)) {
26461
- if (servers[candidate.id] || openapiEndpoints[candidate.id] || graphqlEndpoints[candidate.id] || httpApis[candidate.id] || cliTools[candidate.id]) throw new CapletsError("CONFIG_INVALID", `Duplicate Caplet ID ${candidate.id} under ${root}`);
26484
+ if (servers[candidate.id] || openapiEndpoints[candidate.id] || graphqlEndpoints[candidate.id] || httpApis[candidate.id] || cliTools[candidate.id] || capletSets[candidate.id]) throw new CapletsError("CONFIG_INVALID", `Duplicate Caplet ID ${candidate.id} under ${root}`);
26462
26485
  paths[candidate.id] = candidate.path;
26463
26486
  const config = readCapletFile(candidate.path);
26464
26487
  if (isPlainObject$5(config) && config.backend === "openapi") {
@@ -26473,6 +26496,9 @@ function loadCapletFilesWithPaths(root) {
26473
26496
  } else if (isPlainObject$5(config) && config.backend === "cli") {
26474
26497
  const { backend: _backend, ...endpoint } = config;
26475
26498
  cliTools[candidate.id] = endpoint;
26499
+ } else if (isPlainObject$5(config) && config.backend === "caplets") {
26500
+ const { backend: _backend, ...endpoint } = config;
26501
+ capletSets[candidate.id] = endpoint;
26476
26502
  } else servers[candidate.id] = config;
26477
26503
  }
26478
26504
  const hasServers = Object.keys(servers).length > 0;
@@ -26480,13 +26506,15 @@ function loadCapletFilesWithPaths(root) {
26480
26506
  const hasGraphQl = Object.keys(graphqlEndpoints).length > 0;
26481
26507
  const hasHttpApis = Object.keys(httpApis).length > 0;
26482
26508
  const hasCliTools = Object.keys(cliTools).length > 0;
26483
- return hasServers || hasOpenApi || hasGraphQl || hasHttpApis || hasCliTools ? {
26509
+ const hasCapletSets = Object.keys(capletSets).length > 0;
26510
+ return hasServers || hasOpenApi || hasGraphQl || hasHttpApis || hasCliTools || hasCapletSets ? {
26484
26511
  config: {
26485
26512
  ...hasServers ? { mcpServers: servers } : {},
26486
26513
  ...hasOpenApi ? { openapiEndpoints } : {},
26487
26514
  ...hasGraphQl ? { graphqlEndpoints } : {},
26488
26515
  ...hasHttpApis ? { httpApis } : {},
26489
- ...hasCliTools ? { cliTools } : {}
26516
+ ...hasCliTools ? { cliTools } : {},
26517
+ ...hasCapletSets ? { capletSets } : {}
26490
26518
  },
26491
26519
  paths
26492
26520
  } : void 0;
@@ -26564,6 +26592,16 @@ function capletToServerConfig(frontmatter, body, baseDir) {
26564
26592
  ...frontmatter.tags ? { tags: frontmatter.tags } : {},
26565
26593
  body
26566
26594
  };
26595
+ if (frontmatter.capletSet) return {
26596
+ ...frontmatter.capletSet,
26597
+ configPath: normalizeLocalPath$1(frontmatter.capletSet.configPath, baseDir),
26598
+ capletsRoot: normalizeLocalPath$1(frontmatter.capletSet.capletsRoot, baseDir),
26599
+ backend: "caplets",
26600
+ name: frontmatter.name,
26601
+ description: frontmatter.description,
26602
+ ...frontmatter.tags ? { tags: frontmatter.tags } : {},
26603
+ body
26604
+ };
26567
26605
  return {
26568
26606
  ...frontmatter.mcpServer,
26569
26607
  name: frontmatter.name,
@@ -26884,7 +26922,29 @@ const publicCliToolsSchema = object({
26884
26922
  disabled: boolean().default(false).describe("When true, omit this CLI tools Caplet.")
26885
26923
  }).strict();
26886
26924
  const normalizedCliToolsSchema = publicCliToolsSchema.extend({ body: string().optional() });
26887
- function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlEndpointValueSchema, httpApiValueSchema, cliToolsValueSchema) {
26925
+ const publicCapletSetSchema = object({
26926
+ name: string().trim().min(1).max(80).describe("Human-readable Caplet set display name."),
26927
+ 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"),
26928
+ configPath: string().min(1).optional().describe("Child Caplets config.json path."),
26929
+ capletsRoot: string().min(1).optional().describe("Child Markdown Caplets root directory."),
26930
+ defaultSearchLimit: number$1().int().positive().default(20).describe("Default maximum number of child Caplet search results."),
26931
+ maxSearchLimit: number$1().int().positive().max(50).default(50).describe("Maximum accepted child Caplet search result limit."),
26932
+ toolCacheTtlMs: number$1().int().nonnegative().default(3e4).describe("Milliseconds child Caplet metadata stays fresh. Set 0 to refresh every time."),
26933
+ tags: array(string().trim().min(1).max(80)).optional(),
26934
+ disabled: boolean().default(false).describe("When true, omit this Caplet set.")
26935
+ }).strict().superRefine((set, ctx) => {
26936
+ if (!set.configPath && !set.capletsRoot) ctx.addIssue({
26937
+ code: "custom",
26938
+ message: "Caplet set must define at least one source: configPath or capletsRoot"
26939
+ });
26940
+ if (set.defaultSearchLimit > set.maxSearchLimit) ctx.addIssue({
26941
+ code: "custom",
26942
+ path: ["defaultSearchLimit"],
26943
+ message: "defaultSearchLimit must be <= maxSearchLimit"
26944
+ });
26945
+ });
26946
+ const normalizedCapletSetSchema = publicCapletSetSchema.extend({ body: string().optional() });
26947
+ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlEndpointValueSchema, httpApiValueSchema, cliToolsValueSchema, capletSetValueSchema) {
26888
26948
  return object({
26889
26949
  $schema: string().url().optional().describe("Optional JSON Schema URL for editor validation."),
26890
26950
  version: literal(1).default(1).describe("Caplets config schema version."),
@@ -26894,7 +26954,8 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
26894
26954
  openapiEndpoints: record(string().regex(SERVER_ID_PATTERN), openApiEndpointValueSchema).default({}).describe("OpenAPI endpoints keyed by stable Caplet ID."),
26895
26955
  graphqlEndpoints: record(string().regex(SERVER_ID_PATTERN), graphQlEndpointValueSchema).default({}).describe("GraphQL endpoints keyed by stable Caplet ID."),
26896
26956
  httpApis: record(string().regex(SERVER_ID_PATTERN), httpApiValueSchema).default({}).describe("HTTP APIs keyed by stable Caplet ID."),
26897
- cliTools: record(string().regex(SERVER_ID_PATTERN), cliToolsValueSchema).default({}).describe("CLI tools keyed by stable Caplet ID.")
26957
+ cliTools: record(string().regex(SERVER_ID_PATTERN), cliToolsValueSchema).default({}).describe("CLI tools keyed by stable Caplet ID."),
26958
+ capletSets: record(string().regex(SERVER_ID_PATTERN), capletSetValueSchema).default({}).describe("Nested Caplet collections keyed by stable Caplet ID.")
26898
26959
  }).strict().superRefine((config, ctx) => {
26899
26960
  if (config.defaultSearchLimit > config.maxSearchLimit) ctx.addIssue({
26900
26961
  code: "custom",
@@ -27107,10 +27168,29 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
27107
27168
  message: "CLI action ID must match ^[a-zA-Z0-9_-]{1,64}$"
27108
27169
  });
27109
27170
  }
27171
+ for (const [server, rawValue] of Object.entries(config.capletSets)) {
27172
+ const raw = rawValue;
27173
+ const duplicateBackend = config.mcpServers[server] ? "mcpServers" : config.openapiEndpoints[server] ? "openapiEndpoints" : config.graphqlEndpoints[server] ? "graphqlEndpoints" : config.httpApis[server] ? "httpApis" : config.cliTools[server] ? "cliTools" : void 0;
27174
+ if (duplicateBackend) ctx.addIssue({
27175
+ code: "custom",
27176
+ path: ["capletSets", server],
27177
+ message: `Caplet ID ${server} is already used by ${duplicateBackend}`
27178
+ });
27179
+ if (!SERVER_ID_PATTERN.test(server)) ctx.addIssue({
27180
+ code: "custom",
27181
+ path: ["capletSets", server],
27182
+ message: "Caplet set ID must match ^[a-zA-Z0-9_-]{1,64}$"
27183
+ });
27184
+ if (!raw.configPath && !raw.capletsRoot) ctx.addIssue({
27185
+ code: "custom",
27186
+ path: ["capletSets", server],
27187
+ message: "Caplet set must define at least one source: configPath or capletsRoot"
27188
+ });
27189
+ }
27110
27190
  });
27111
27191
  }
27112
- const configFileSchema = configSchemaFor(publicServerSchema, publicOpenApiEndpointSchema, publicGraphQlEndpointSchema, publicHttpApiSchema, publicCliToolsSchema);
27113
- const normalizedConfigFileSchema = configSchemaFor(normalizedServerSchema, normalizedOpenApiEndpointSchema, normalizedGraphQlEndpointSchema, normalizedHttpApiSchema, normalizedCliToolsSchema);
27192
+ const configFileSchema = configSchemaFor(publicServerSchema, publicOpenApiEndpointSchema, publicGraphQlEndpointSchema, publicHttpApiSchema, publicCliToolsSchema, publicCapletSetSchema);
27193
+ const normalizedConfigFileSchema = configSchemaFor(normalizedServerSchema, normalizedOpenApiEndpointSchema, normalizedGraphQlEndpointSchema, normalizedHttpApiSchema, normalizedCliToolsSchema, normalizedCapletSetSchema);
27114
27194
  function loadConfig(path = resolveConfigPath(), projectPath = resolveProjectConfigPath()) {
27115
27195
  return loadConfigWithSources(path, projectPath).config;
27116
27196
  }
@@ -27150,7 +27230,7 @@ function loadConfigWithSources(path = resolveConfigPath(), projectPath = resolve
27150
27230
  }
27151
27231
  } : void 0);
27152
27232
  const config = parseConfig(input);
27153
- 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) throw new CapletsError("CONFIG_INVALID", "Caplets config must define at least one MCP server, OpenAPI endpoint, GraphQL endpoint, HTTP API, or CLI tools backend");
27233
+ 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", "Caplets config must define at least one MCP server, OpenAPI endpoint, GraphQL endpoint, HTTP API, CLI tools backend, or Caplet set");
27154
27234
  return {
27155
27235
  config,
27156
27236
  sources,
@@ -27161,6 +27241,19 @@ function loadConfigWithSources(path = resolveConfigPath(), projectPath = resolve
27161
27241
  throw new CapletsError("CONFIG_INVALID", "Caplets config is not valid JSON", redactSecrets(error));
27162
27242
  }
27163
27243
  }
27244
+ function loadIsolatedConfig(options) {
27245
+ if (!options.configPath && !options.capletsRoot) throw new CapletsError("CONFIG_INVALID", "Nested Caplet set must define at least one source: configPath or capletsRoot");
27246
+ const configInput = options.configPath ? readPublicConfigInput(options.configPath) : void 0;
27247
+ const capletInput = options.capletsRoot ? loadCapletFiles(options.capletsRoot) : void 0;
27248
+ if (!configInput && !capletInput) throw new CapletsError("CONFIG_NOT_FOUND", `Nested Caplet set sources not found: ${[options.configPath, options.capletsRoot].filter(Boolean).join(", ")}`);
27249
+ const config = parseConfig(mergeConfigInputs(configInput, capletInput, {
27250
+ version: 1,
27251
+ defaultSearchLimit: options.defaultSearchLimit,
27252
+ maxSearchLimit: options.maxSearchLimit
27253
+ }));
27254
+ 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", "Nested Caplet set must define at least one Caplet");
27255
+ return config;
27256
+ }
27164
27257
  function resolveProjectCapletsRootForConfigPath(projectPath) {
27165
27258
  const root = dirname(projectPath);
27166
27259
  return basename(root) === ".caplets" && basename(projectPath) === "config.json" ? root : void 0;
@@ -27181,7 +27274,8 @@ function normalizeLocalPaths(input, baseDir) {
27181
27274
  ...input,
27182
27275
  openapiEndpoints: normalizeEndpointPaths(input.openapiEndpoints, baseDir, normalizeOpenApiPath),
27183
27276
  graphqlEndpoints: normalizeEndpointPaths(input.graphqlEndpoints, baseDir, normalizeGraphQlPath),
27184
- cliTools: normalizeEndpointPaths(input.cliTools, baseDir, normalizeCliToolsPaths)
27277
+ cliTools: normalizeEndpointPaths(input.cliTools, baseDir, normalizeCliToolsPaths),
27278
+ capletSets: normalizeEndpointPaths(input.capletSets, baseDir, normalizeCapletSetPaths)
27185
27279
  });
27186
27280
  }
27187
27281
  function normalizeEndpointPaths(endpoints, baseDir, normalize) {
@@ -27216,6 +27310,13 @@ function normalizeCliToolsPaths(endpoint, baseDir) {
27216
27310
  actions
27217
27311
  };
27218
27312
  }
27313
+ function normalizeCapletSetPaths(endpoint, baseDir) {
27314
+ return {
27315
+ ...endpoint,
27316
+ configPath: normalizeLocalPath(endpoint.configPath, baseDir),
27317
+ capletsRoot: normalizeLocalPath(endpoint.capletsRoot, baseDir)
27318
+ };
27319
+ }
27219
27320
  function normalizeLocalPath(value, baseDir) {
27220
27321
  if (typeof value !== "string" || !value || isAbsolute(value) || hasEnvReference(value)) return value;
27221
27322
  return join(baseDir, value);
@@ -27225,6 +27326,7 @@ function rejectProjectConfigExecutableBackendMaps(input, path) {
27225
27326
  if (input.graphqlEndpoints && Object.keys(input.graphqlEndpoints).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map graphqlEndpoints; use project Markdown Caplet files or user config instead`);
27226
27327
  if (input.httpApis && Object.keys(input.httpApis).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map httpApis; use project Markdown Caplet files or user config instead`);
27227
27328
  if (input.cliTools && Object.keys(input.cliTools).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map cliTools; use project Markdown Caplet files or user config instead`);
27329
+ if (input.capletSets && Object.keys(input.capletSets).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map capletSets; use project Markdown Caplet files or user config instead`);
27228
27330
  return input;
27229
27331
  }
27230
27332
  function mergeConfigInputs(...inputs) {
@@ -27253,6 +27355,10 @@ function mergeConfigInputs(...inputs) {
27253
27355
  cliTools: {
27254
27356
  ...merged?.cliTools,
27255
27357
  ...input.cliTools
27358
+ },
27359
+ capletSets: {
27360
+ ...merged?.capletSets,
27361
+ ...input.capletSets
27256
27362
  }
27257
27363
  };
27258
27364
  }
@@ -27284,13 +27390,15 @@ function removeCapletId(input, id) {
27284
27390
  const { [id]: _graphqlEndpoint, ...graphqlEndpoints } = input.graphqlEndpoints ?? {};
27285
27391
  const { [id]: _httpApi, ...httpApis } = input.httpApis ?? {};
27286
27392
  const { [id]: _cliTools, ...cliTools } = input.cliTools ?? {};
27393
+ const { [id]: _capletSet, ...capletSets } = input.capletSets ?? {};
27287
27394
  return {
27288
27395
  ...input,
27289
27396
  mcpServers,
27290
27397
  openapiEndpoints,
27291
27398
  graphqlEndpoints,
27292
27399
  httpApis,
27293
- cliTools
27400
+ cliTools,
27401
+ capletSets
27294
27402
  };
27295
27403
  }
27296
27404
  function capletIds(input) {
@@ -27299,7 +27407,8 @@ function capletIds(input) {
27299
27407
  ...Object.keys(input.openapiEndpoints ?? {}),
27300
27408
  ...Object.keys(input.graphqlEndpoints ?? {}),
27301
27409
  ...Object.keys(input.httpApis ?? {}),
27302
- ...Object.keys(input.cliTools ?? {})
27410
+ ...Object.keys(input.cliTools ?? {}),
27411
+ ...Object.keys(input.capletSets ?? {})
27303
27412
  ];
27304
27413
  }
27305
27414
  function sourceForId(source, id) {
@@ -27345,6 +27454,12 @@ function parseConfig(input) {
27345
27454
  server,
27346
27455
  backend: "cli"
27347
27456
  });
27457
+ const capletSets = {};
27458
+ for (const [server, raw] of Object.entries(parsed.data.capletSets)) capletSets[server] = stripUndefined$1({
27459
+ ...raw,
27460
+ server,
27461
+ backend: "caplets"
27462
+ });
27348
27463
  return {
27349
27464
  version: parsed.data.version,
27350
27465
  options: {
@@ -27355,7 +27470,8 @@ function parseConfig(input) {
27355
27470
  openapiEndpoints,
27356
27471
  graphqlEndpoints,
27357
27472
  httpApis,
27358
- cliTools
27473
+ cliTools,
27474
+ capletSets
27359
27475
  };
27360
27476
  }
27361
27477
  function validateEndpointAuthHeaders(auth, ctx, path) {
@@ -27384,7 +27500,7 @@ function interpolateConfig(value, path = []) {
27384
27500
  return value;
27385
27501
  }
27386
27502
  function isPublicMetadataPath(path) {
27387
- if (path.length < 3 || path[0] !== "mcpServers" && path[0] !== "openapiEndpoints" && path[0] !== "graphqlEndpoints" && path[0] !== "httpApis" && path[0] !== "cliTools") return false;
27503
+ if (path.length < 3 || path[0] !== "mcpServers" && path[0] !== "openapiEndpoints" && path[0] !== "graphqlEndpoints" && path[0] !== "httpApis" && path[0] !== "cliTools" && path[0] !== "capletSets") return false;
27388
27504
  return NON_INTERPOLATED_SERVER_FIELDS.has(path[2] ?? "");
27389
27505
  }
27390
27506
  function isPlainObject$4(value) {
@@ -56973,7 +57089,7 @@ function openApiCacheKey(endpoint) {
56973
57089
  //#endregion
56974
57090
  //#region src/capability-description.mjs
56975
57091
  function capabilityDescription(server) {
56976
- const backendName = server.backend === "mcp" ? "MCP server" : server.backend === "openapi" ? "OpenAPI endpoint" : server.backend === "graphql" ? "GraphQL endpoint" : server.backend === "http" ? "HTTP API" : "CLI tools";
57092
+ const backendName = server.backend === "mcp" ? "MCP server" : server.backend === "openapi" ? "OpenAPI endpoint" : server.backend === "graphql" ? "GraphQL endpoint" : server.backend === "http" ? "HTTP API" : server.backend === "cli" ? "CLI tools" : server.backend === "caplets" ? "nested Caplets" : "backend";
56977
57093
  const checkOperation = server.backend === "mcp" ? "check_mcp_server" : "check_backend";
56978
57094
  const hint = [
56979
57095
  `Use this Caplet to inspect and call tools from its ${backendName} backend.`,
@@ -57003,7 +57119,7 @@ var ServerRegistry = class {
57003
57119
  return this.allCaplets().filter((server) => !server.disabled);
57004
57120
  }
57005
57121
  get(serverId) {
57006
- const server = this.config.mcpServers[serverId] ?? this.config.openapiEndpoints[serverId] ?? this.config.graphqlEndpoints[serverId] ?? this.config.httpApis[serverId] ?? this.config.cliTools[serverId];
57122
+ const server = this.config.mcpServers[serverId] ?? this.config.openapiEndpoints[serverId] ?? this.config.graphqlEndpoints[serverId] ?? this.config.httpApis[serverId] ?? this.config.cliTools[serverId] ?? this.config.capletSets[serverId];
57007
57123
  return server?.disabled ? void 0 : server;
57008
57124
  }
57009
57125
  require(serverId) {
@@ -57055,7 +57171,8 @@ var ServerRegistry = class {
57055
57171
  ...Object.values(this.config.openapiEndpoints),
57056
57172
  ...Object.values(this.config.graphqlEndpoints),
57057
57173
  ...Object.values(this.config.httpApis),
57058
- ...Object.values(this.config.cliTools)
57174
+ ...Object.values(this.config.cliTools),
57175
+ ...Object.values(this.config.capletSets)
57059
57176
  ];
57060
57177
  }
57061
57178
  };
@@ -57088,6 +57205,12 @@ function backendDetail(server) {
57088
57205
  maxOutputBytes: server.maxOutputBytes,
57089
57206
  configuredActions: Object.keys(server.actions).length
57090
57207
  };
57208
+ if (server.backend === "caplets") return {
57209
+ type: "caplets",
57210
+ disabled: server.disabled,
57211
+ source: capletSetSource(server),
57212
+ toolCacheTtlMs: server.toolCacheTtlMs
57213
+ };
57091
57214
  return {
57092
57215
  type: "mcp",
57093
57216
  transport: server.transport,
@@ -57097,6 +57220,9 @@ function backendDetail(server) {
57097
57220
  toolCacheTtlMs: server.toolCacheTtlMs
57098
57221
  };
57099
57222
  }
57223
+ function capletSetSource(server) {
57224
+ return server.configPath && server.capletsRoot ? "both" : server.configPath ? "configPath" : "capletsRoot";
57225
+ }
57100
57226
  function graphQlSource(server) {
57101
57227
  if (server.schemaPath) return "schemaPath";
57102
57228
  if (server.schemaUrl) return "schemaUrl";
@@ -57213,16 +57339,16 @@ const generatedToolInputSchema = object({
57213
57339
  arguments: record(string(), unknown()).optional().describe(generatedToolInputDescriptions.arguments),
57214
57340
  fields: array(string().min(1)).min(1).optional().describe(generatedToolInputDescriptions.fields)
57215
57341
  }).strict();
57216
- async function handleServerTool(server, request, registry, downstream, openapi, graphql, http, cli) {
57342
+ async function handleServerTool(server, request, registry, downstream, openapi, graphql, http, cli, caplets) {
57217
57343
  const parsed = validateOperationRequest(request, registry.config.options.maxSearchLimit);
57218
57344
  switch (parsed.operation) {
57219
57345
  case "get_caplet": return jsonResult(registry.detail(server));
57220
- case "check_backend": return jsonResult(await backendFor(server, downstream, openapi, graphql, http, cli).check(server));
57346
+ case "check_backend": return jsonResult(await backendFor(server, downstream, openapi, graphql, http, cli, caplets).check(server));
57221
57347
  case "check_mcp_server":
57222
57348
  if (server.backend !== "mcp") throw new CapletsError("REQUEST_INVALID", "check_mcp_server is only valid for MCP-backed Caplets; use check_backend");
57223
57349
  return jsonResult(await downstream.checkServer(server));
57224
57350
  case "list_tools": {
57225
- const backend = backendFor(server, downstream, openapi, graphql, http, cli);
57351
+ const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets);
57226
57352
  const tools = await backend.listTools(server);
57227
57353
  return jsonResult({
57228
57354
  server: server.server,
@@ -57230,7 +57356,7 @@ async function handleServerTool(server, request, registry, downstream, openapi,
57230
57356
  });
57231
57357
  }
57232
57358
  case "search_tools": {
57233
- const backend = backendFor(server, downstream, openapi, graphql, http, cli);
57359
+ const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets);
57234
57360
  const tools = await backend.listTools(server);
57235
57361
  const limit = parsed.limit ?? registry.config.options.defaultSearchLimit;
57236
57362
  return jsonResult({
@@ -57240,14 +57366,14 @@ async function handleServerTool(server, request, registry, downstream, openapi,
57240
57366
  });
57241
57367
  }
57242
57368
  case "get_tool": {
57243
- const tool = await backendFor(server, downstream, openapi, graphql, http, cli).getTool(server, parsed.tool);
57369
+ const tool = await backendFor(server, downstream, openapi, graphql, http, cli, caplets).getTool(server, parsed.tool);
57244
57370
  return jsonResult({
57245
57371
  server: server.server,
57246
57372
  tool
57247
57373
  });
57248
57374
  }
57249
57375
  case "call_tool": {
57250
- const backend = backendFor(server, downstream, openapi, graphql, http, cli);
57376
+ const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets);
57251
57377
  if (parsed.fields === void 0) return backend.callTool(server, parsed.tool, parsed.arguments);
57252
57378
  if (server.backend === "graphql") throw new CapletsError("REQUEST_INVALID", "call_tool.fields is not supported for GraphQL-backed Caplets; select fields in the GraphQL operation document instead");
57253
57379
  const tool = await backend.getTool(server, parsed.tool);
@@ -57340,7 +57466,7 @@ function projectCallToolResult(result, outputSchema, fields) {
57340
57466
  function isPlainObject(value) {
57341
57467
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
57342
57468
  }
57343
- function backendFor(server, downstream, openapi, graphql, http, cli) {
57469
+ function backendFor(server, downstream, openapi, graphql, http, cli, caplets) {
57344
57470
  if (server.backend === "mcp") return {
57345
57471
  check: (...args) => downstream.checkServer(...args),
57346
57472
  listTools: (...args) => downstream.listTools(...args),
@@ -57382,6 +57508,17 @@ function backendFor(server, downstream, openapi, graphql, http, cli) {
57382
57508
  search: (...args) => cli.search(...args)
57383
57509
  };
57384
57510
  }
57511
+ if (server.backend === "caplets") {
57512
+ if (!caplets) throw new CapletsError("INTERNAL_ERROR", "Caplet set manager is not configured");
57513
+ return {
57514
+ check: (...args) => caplets.checkSet(...args),
57515
+ listTools: (...args) => caplets.listTools(...args),
57516
+ getTool: (...args) => caplets.getTool(...args),
57517
+ callTool: (...args) => caplets.callTool(...args),
57518
+ compact: (...args) => caplets.compact(...args),
57519
+ search: (...args) => caplets.search(...args)
57520
+ };
57521
+ }
57385
57522
  if (!openapi) throw new CapletsError("INTERNAL_ERROR", "OpenAPI manager is not configured");
57386
57523
  return {
57387
57524
  check: (...args) => openapi.checkEndpoint(...args),
@@ -57393,6 +57530,174 @@ function backendFor(server, downstream, openapi, graphql, http, cli) {
57393
57530
  };
57394
57531
  }
57395
57532
  //#endregion
57533
+ //#region src/caplet-sets.ts
57534
+ var CapletSetManager = class CapletSetManager {
57535
+ registry;
57536
+ options;
57537
+ children = /* @__PURE__ */ new Map();
57538
+ childRefreshLocks = /* @__PURE__ */ new Map();
57539
+ constructor(registry, options = {}) {
57540
+ this.registry = registry;
57541
+ this.options = options;
57542
+ }
57543
+ updateRegistry(registry) {
57544
+ this.registry = registry;
57545
+ }
57546
+ invalidate(serverId) {
57547
+ const pending = this.childRefreshLocks.get(serverId);
57548
+ if (pending) {
57549
+ pending.then(() => this.closeChild(serverId), () => this.closeChild(serverId));
57550
+ return;
57551
+ }
57552
+ this.closeChild(serverId);
57553
+ }
57554
+ async close() {
57555
+ await Promise.allSettled(this.childRefreshLocks.values());
57556
+ await Promise.allSettled([...this.children.keys()].map((serverId) => this.closeChild(serverId)));
57557
+ }
57558
+ async checkSet(config) {
57559
+ const startedAt = Date.now();
57560
+ try {
57561
+ const childCaplets = (await this.childRuntime(config, true)).registry.enabledServers();
57562
+ this.registry.setStatus(config.server, "available");
57563
+ return {
57564
+ server: config.server,
57565
+ status: "available",
57566
+ toolCount: childCaplets.length,
57567
+ elapsedMs: Date.now() - startedAt
57568
+ };
57569
+ } catch (error) {
57570
+ const safe = toSafeError(error, "SERVER_UNAVAILABLE");
57571
+ this.registry.setStatus(config.server, "unavailable", safe);
57572
+ return {
57573
+ server: config.server,
57574
+ status: "unavailable",
57575
+ elapsedMs: Date.now() - startedAt,
57576
+ error: safe
57577
+ };
57578
+ }
57579
+ }
57580
+ async listTools(config) {
57581
+ return (await this.childRuntime(config, false)).registry.enabledServers().map((caplet) => this.toTool(caplet));
57582
+ }
57583
+ async getTool(config, toolName) {
57584
+ const child = await this.childRuntime(config, false);
57585
+ const caplet = child.registry.get(toolName);
57586
+ if (!caplet) throw new CapletsError("TOOL_NOT_FOUND", `Tool ${toolName} was not found on ${config.server}`, {
57587
+ server: config.server,
57588
+ tool: toolName,
57589
+ suggestions: nearbyCapletNames(child.registry.enabledServers(), toolName)
57590
+ });
57591
+ return this.toTool(caplet);
57592
+ }
57593
+ async callTool(config, toolName, args) {
57594
+ const child = await this.childRuntime(config, false);
57595
+ const caplet = child.registry.get(toolName);
57596
+ if (!caplet) throw new CapletsError("TOOL_NOT_FOUND", `Tool ${toolName} was not found on ${config.server}`, {
57597
+ server: config.server,
57598
+ tool: toolName,
57599
+ suggestions: nearbyCapletNames(child.registry.enabledServers(), toolName)
57600
+ });
57601
+ try {
57602
+ return await handleServerTool(caplet, args, child.registry, child.downstream, child.openapi, child.graphql, child.http, child.cli, child.capletSets);
57603
+ } catch (error) {
57604
+ return errorResult(error);
57605
+ }
57606
+ }
57607
+ compact(config, tool) {
57608
+ return {
57609
+ server: config.server,
57610
+ tool: tool.name,
57611
+ ...tool.description ? { description: tool.description } : {},
57612
+ ...tool.annotations ? { annotations: tool.annotations } : {},
57613
+ hasInputSchema: Boolean(tool.inputSchema),
57614
+ hasOutputSchema: Boolean(tool.outputSchema)
57615
+ };
57616
+ }
57617
+ search(config, tools, query, limit) {
57618
+ const needle = query.toLocaleLowerCase();
57619
+ return tools.filter((tool) => `${tool.name}\n${tool.description ?? ""}`.toLocaleLowerCase().includes(needle)).sort((left, right) => left.name.localeCompare(right.name)).slice(0, limit).map((tool) => this.compact(config, tool));
57620
+ }
57621
+ async childRuntime(config, force) {
57622
+ const pending = this.childRefreshLocks.get(config.server);
57623
+ if (pending) return pending;
57624
+ const refresh = this.loadChildRuntime(config, force).finally(() => {
57625
+ this.childRefreshLocks.delete(config.server);
57626
+ });
57627
+ this.childRefreshLocks.set(config.server, refresh);
57628
+ return await refresh;
57629
+ }
57630
+ async loadChildRuntime(config, force) {
57631
+ const cacheKey = sourceKey(config);
57632
+ const existing = this.children.get(config.server);
57633
+ const now = Date.now();
57634
+ const isFresh = existing && existing.cacheKey === cacheKey && existing.configFingerprint === JSON.stringify(config) && config.toolCacheTtlMs > 0 && now - existing.loadedAt <= config.toolCacheTtlMs;
57635
+ if (existing && !force && isFresh) return existing;
57636
+ const ancestry = this.options.ancestry ?? /* @__PURE__ */ new Set();
57637
+ if (ancestry.has(cacheKey)) throw new CapletsError("CONFIG_INVALID", "Nested Caplet set cycle detected", {
57638
+ server: config.server,
57639
+ source: cacheKey,
57640
+ ancestry: [...ancestry]
57641
+ });
57642
+ let child;
57643
+ try {
57644
+ const registry = new ServerRegistry(loadIsolatedConfig({
57645
+ ...config.configPath ? { configPath: config.configPath } : {},
57646
+ ...config.capletsRoot ? { capletsRoot: config.capletsRoot } : {},
57647
+ defaultSearchLimit: config.defaultSearchLimit,
57648
+ maxSearchLimit: config.maxSearchLimit
57649
+ }));
57650
+ const authOptions = this.options.authDir ? { authDir: this.options.authDir } : {};
57651
+ const childAncestry = new Set([...ancestry, cacheKey]);
57652
+ child = {
57653
+ registry,
57654
+ downstream: new DownstreamManager(registry, authOptions),
57655
+ openapi: new OpenApiManager(registry, authOptions),
57656
+ graphql: new GraphQLManager(registry, authOptions),
57657
+ http: new HttpActionManager(registry, authOptions),
57658
+ cli: new CliToolsManager(registry),
57659
+ capletSets: new CapletSetManager(registry, {
57660
+ ...authOptions,
57661
+ ancestry: childAncestry
57662
+ }),
57663
+ cacheKey,
57664
+ configFingerprint: JSON.stringify(config),
57665
+ loadedAt: now
57666
+ };
57667
+ } catch (error) {
57668
+ if (existing) return existing;
57669
+ throw error;
57670
+ }
57671
+ if (existing) await this.closeChild(config.server);
57672
+ this.children.set(config.server, child);
57673
+ this.registry.setStatus(config.server, "available");
57674
+ return child;
57675
+ }
57676
+ async closeChild(serverId) {
57677
+ const child = this.children.get(serverId);
57678
+ this.children.delete(serverId);
57679
+ if (!child) return;
57680
+ await Promise.allSettled([child.downstream.close(), child.capletSets.close()]);
57681
+ }
57682
+ toTool(caplet) {
57683
+ return {
57684
+ name: caplet.server,
57685
+ description: capabilityDescription(caplet),
57686
+ inputSchema: generatedToolInputJsonSchema()
57687
+ };
57688
+ }
57689
+ };
57690
+ function sourceKey(config) {
57691
+ return JSON.stringify({
57692
+ configPath: config.configPath ? resolve(config.configPath) : void 0,
57693
+ capletsRoot: config.capletsRoot ? resolve(config.capletsRoot) : void 0
57694
+ });
57695
+ }
57696
+ function nearbyCapletNames(caplets, needle) {
57697
+ const lower = needle.toLocaleLowerCase();
57698
+ return caplets.map((caplet) => caplet.server).filter((name) => name.toLocaleLowerCase().includes(lower[0] ?? "")).sort().slice(0, 5);
57699
+ }
57700
+ //#endregion
57396
57701
  //#region src/engine.ts
57397
57702
  var CapletsEngine = class {
57398
57703
  registry;
@@ -57401,6 +57706,7 @@ var CapletsEngine = class {
57401
57706
  graphql;
57402
57707
  http;
57403
57708
  cli;
57709
+ capletSets;
57404
57710
  paths;
57405
57711
  watchDebounceMs;
57406
57712
  watchEnabled;
@@ -57424,6 +57730,7 @@ var CapletsEngine = class {
57424
57730
  this.graphql = new GraphQLManager(this.registry, selectAuthOptions(options.authDir));
57425
57731
  this.http = new HttpActionManager(this.registry, selectAuthOptions(options.authDir));
57426
57732
  this.cli = new CliToolsManager(this.registry);
57733
+ this.capletSets = new CapletSetManager(this.registry, selectAuthOptions(options.authDir));
57427
57734
  this.watchDebounceMs = options.watchDebounceMs ?? 250;
57428
57735
  this.watchEnabled = options.watch ?? true;
57429
57736
  this.writeErr = options.writeErr ?? ((value) => process.stderr.write(value));
@@ -57465,7 +57772,7 @@ var CapletsEngine = class {
57465
57772
  }
57466
57773
  async execute(serverId, request) {
57467
57774
  try {
57468
- return await handleServerTool(this.registry.require(serverId), request, this.registry, this.downstream, this.openapi, this.graphql, this.http, this.cli);
57775
+ return await handleServerTool(this.registry.require(serverId), request, this.registry, this.downstream, this.openapi, this.graphql, this.http, this.cli, this.capletSets);
57469
57776
  } catch (error) {
57470
57777
  return errorResult(error);
57471
57778
  }
@@ -57485,6 +57792,7 @@ var CapletsEngine = class {
57485
57792
  } finally {
57486
57793
  this.closeWatchers();
57487
57794
  await this.downstream.close();
57795
+ await this.capletSets.close();
57488
57796
  this.reloadListeners.clear();
57489
57797
  }
57490
57798
  }
@@ -57507,6 +57815,7 @@ var CapletsEngine = class {
57507
57815
  this.graphql.updateRegistry(nextRegistry);
57508
57816
  this.http.updateRegistry(nextRegistry);
57509
57817
  this.cli.updateRegistry(nextRegistry);
57818
+ this.capletSets.updateRegistry(nextRegistry);
57510
57819
  let invalidated = true;
57511
57820
  try {
57512
57821
  await this.invalidateChangedBackends(previousConfig, nextConfig);
@@ -57559,6 +57868,7 @@ var CapletsEngine = class {
57559
57868
  if (before?.backend === "graphql" || after?.backend === "graphql" || !after) this.graphql.invalidate(serverId);
57560
57869
  if (before?.backend === "http" || after?.backend === "http" || !after) this.http.invalidate(serverId);
57561
57870
  if (before?.backend === "cli" || after?.backend === "cli" || !after) this.cli.invalidate(serverId);
57871
+ if (before?.backend === "caplets" || after?.backend === "caplets" || !after) this.capletSets.invalidate(serverId);
57562
57872
  }
57563
57873
  }
57564
57874
  resetWatchers() {
@@ -57651,7 +57961,8 @@ function allCaplets(config) {
57651
57961
  ...Object.values(config.openapiEndpoints),
57652
57962
  ...Object.values(config.graphqlEndpoints),
57653
57963
  ...Object.values(config.httpApis),
57654
- ...Object.values(config.cliTools)
57964
+ ...Object.values(config.cliTools),
57965
+ ...Object.values(config.capletSets)
57655
57966
  ];
57656
57967
  }
57657
57968
  function nextEnabledServers(config) {
@@ -11,7 +11,7 @@ const operations = [
11
11
  const generatedToolInputDescriptions = {
12
12
  operation: [
13
13
  "Caplets wrapper operation to perform for this configured Caplet backend.",
14
- "Use get_caplet to read the full Caplet card, check_backend to check any backend, check_mcp_server to check an MCP backend, list_tools or search_tools to discover downstream tools, get_tool to read a downstream input schema, and call_tool to run one downstream tool, operation, action, or CLI command.",
14
+ "Use get_caplet to read the full Caplet card, check_backend to check any backend, check_mcp_server to check an MCP backend, list_tools or search_tools to discover downstream tools, get_tool to read a downstream input schema, and call_tool to run one downstream tool, operation, action, CLI command, or child Caplet.",
15
15
  "For call_tool, pass downstream inputs only inside the top-level \"arguments\" object."
16
16
  ].join(" "),
17
17
  query: "Required only for search_tools. Example: {\"operation\":\"search_tools\",\"query\":\"web search\",\"limit\":5}. Do not use query for call_tool; put downstream query values under arguments.query.",
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as assertCompleteRequestPrompt, A as CallToolRequestSchema, B as InitializeRequestSchema, C as SERVER_ID_PATTERN, D as Protocol, E as AjvJsonSchemaValidator, F as CreateTaskResultSchema, G as ListResourcesRequestSchema, H as LATEST_PROTOCOL_VERSION, I as ElicitResultSchema, J as LoggingLevelSchema, K as ListRootsResultSchema, L as EmptyResultSchema, M as CompleteRequestSchema, N as CreateMessageResultSchema, O as mergeCapabilities, P as CreateMessageResultWithToolsSchema, Q as SetLevelRequestSchema, R as ErrorCode, S as toSafeError, T as assertToolsCallTaskCapability, U as ListPromptsRequestSchema, V as InitializedNotificationSchema, W as ListResourceTemplatesRequestSchema, X as ReadResourceRequestSchema, Y as McpError, Z as SUPPORTED_PROTOCOL_VERSIONS, _ as resolveProjectCapletsRoot, a as capabilityDescription, at as getSchemaDescription, b as validateCapletFile, c as deleteTokenBundle, ct as normalizeObjectSchema, d as loadConfig, dt as safeParseAsync, et as assertCompleteRequestResourceTemplate, f as loadConfigWithSources, ft as __commonJSMin, g as resolveConfigPath, h as resolveCapletsRoot, i as ServerRegistry, it as getParseErrorMessage, j as CallToolResultSchema, k as toJsonSchemaCompat, l as isTokenBundleExpired, lt as objectFromShape, m as DEFAULT_AUTH_DIR, mt as __toESM, n as generatedToolInputSchema, nt as getLiteralValue, o as runGenericOAuthFlow, ot as isSchemaOptional, p as parseConfig, pt as __require, q as ListToolsRequestSchema, r as handleServerTool, rt as getObjectShape, s as runOAuthFlow, st as isZ4Schema, t as CapletsEngine, tt as ZodOptional, u as readTokenBundle, ut as safeParse, v as resolveProjectConfigPath, w as assertClientRequestTaskCapability, x as CapletsError, y as discoverCapletFiles, z as GetPromptRequestSchema } from "./engine-BzekyZ5r.js";
1
+ import { $ as assertCompleteRequestPrompt, A as CallToolRequestSchema, B as InitializeRequestSchema, C as SERVER_ID_PATTERN, D as Protocol, E as AjvJsonSchemaValidator, F as CreateTaskResultSchema, G as ListResourcesRequestSchema, H as LATEST_PROTOCOL_VERSION, I as ElicitResultSchema, J as LoggingLevelSchema, K as ListRootsResultSchema, L as EmptyResultSchema, M as CompleteRequestSchema, N as CreateMessageResultSchema, O as mergeCapabilities, P as CreateMessageResultWithToolsSchema, Q as SetLevelRequestSchema, R as ErrorCode, S as toSafeError, T as assertToolsCallTaskCapability, U as ListPromptsRequestSchema, V as InitializedNotificationSchema, W as ListResourceTemplatesRequestSchema, X as ReadResourceRequestSchema, Y as McpError, Z as SUPPORTED_PROTOCOL_VERSIONS, _ as resolveProjectCapletsRoot, a as capabilityDescription, at as getSchemaDescription, b as validateCapletFile, c as deleteTokenBundle, ct as normalizeObjectSchema, d as loadConfig, dt as safeParseAsync, et as assertCompleteRequestResourceTemplate, f as loadConfigWithSources, ft as __commonJSMin, g as resolveConfigPath, h as resolveCapletsRoot, i as ServerRegistry, it as getParseErrorMessage, j as CallToolResultSchema, k as toJsonSchemaCompat, l as isTokenBundleExpired, lt as objectFromShape, m as DEFAULT_AUTH_DIR, mt as __toESM, n as generatedToolInputSchema, nt as getLiteralValue, o as runGenericOAuthFlow, ot as isSchemaOptional, p as parseConfig, pt as __require, q as ListToolsRequestSchema, r as handleServerTool, rt as getObjectShape, s as runOAuthFlow, st as isZ4Schema, t as CapletsEngine, tt as ZodOptional, u as readTokenBundle, ut as safeParse, v as resolveProjectConfigPath, w as assertClientRequestTaskCapability, x as CapletsError, y as discoverCapletFiles, z as GetPromptRequestSchema } from "./engine-D_zyCvXx.js";
2
2
  import { accessSync, chmodSync, closeSync, constants, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
3
3
  import { basename, dirname, join, parse, relative, resolve } from "node:path";
4
4
  import { stdin, stdout } from "node:process";
@@ -1314,7 +1314,7 @@ const EMPTY_COMPLETION_RESULT = { completion: {
1314
1314
  } };
1315
1315
  //#endregion
1316
1316
  //#region package.json
1317
- var version = "0.12.1";
1317
+ var version = "0.13.0";
1318
1318
  //#endregion
1319
1319
  //#region src/runtime.ts
1320
1320
  var CapletsRuntime = class {
@@ -1396,11 +1396,12 @@ function nextEnabledServers(config) {
1396
1396
  ...Object.values(config.openapiEndpoints),
1397
1397
  ...Object.values(config.graphqlEndpoints),
1398
1398
  ...Object.values(config.httpApis),
1399
- ...Object.values(config.cliTools)
1399
+ ...Object.values(config.cliTools),
1400
+ ...Object.values(config.capletSets)
1400
1401
  ].filter((server) => !server.disabled);
1401
1402
  }
1402
1403
  function capletById(config, serverId) {
1403
- return config.mcpServers[serverId] ?? config.openapiEndpoints[serverId] ?? config.graphqlEndpoints[serverId] ?? config.httpApis[serverId] ?? config.cliTools[serverId];
1404
+ return config.mcpServers[serverId] ?? config.openapiEndpoints[serverId] ?? config.graphqlEndpoints[serverId] ?? config.httpApis[serverId] ?? config.cliTools[serverId] ?? config.capletSets[serverId];
1404
1405
  }
1405
1406
  function serializeCaplet(caplet) {
1406
1407
  return JSON.stringify(caplet ?? null);
@@ -5323,7 +5324,7 @@ function createProgram(io = {}) {
5323
5324
  const writeOut = io.writeOut ?? ((value) => process.stdout.write(value));
5324
5325
  const writeErr = io.writeErr ?? ((value) => process.stderr.write(value));
5325
5326
  const program = new Command();
5326
- program.name("caplets").description("Progressive-disclosure gateway for MCP servers.").version(version).exitOverride().configureOutput({
5327
+ program.name("caplets").description("Progressive-disclosure gateway for MCP servers.").version(io.version ?? version).exitOverride().configureOutput({
5327
5328
  writeOut,
5328
5329
  writeErr,
5329
5330
  outputError: (value, write) => write(value)
package/dist/native.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as capabilityDescription, n as generatedToolInputSchema, t as CapletsEngine } from "./engine-BzekyZ5r.js";
1
+ import { a as capabilityDescription, n as generatedToolInputSchema, t as CapletsEngine } from "./engine-D_zyCvXx.js";
2
2
  import { generatedToolInputJsonSchema } from "./generated-tool-input-schema.js";
3
3
  //#region src/native/tools.ts
4
4
  function nativeCapletToolName(capletId) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caplets/core",
3
- "version": "0.12.1",
3
+ "version": "0.13.0",
4
4
  "description": "Core runtime library for Caplets progressive disclosure gateways.",
5
5
  "keywords": [
6
6
  "caplets",