@caplets/core 0.18.2 → 0.18.3

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 { Ct as resolveProjectConfigPath, Mt as __exportAll, Ot as CapletsError, St as resolveProjectCapletsRoot, bt as resolveCapletsRoot, gt as loadConfigWithSources, vt as DEFAULT_AUTH_DIR, xt as resolveConfigPath, yt as DEFAULT_COMPLETION_CACHE_DIR } from "./options-bnsSREid.js";
1
+ import { Ct as resolveProjectConfigPath, Mt as __exportAll, Ot as CapletsError, St as resolveProjectCapletsRoot, bt as resolveCapletsRoot, gt as loadConfigWithSources, vt as DEFAULT_AUTH_DIR, xt as resolveConfigPath, yt as DEFAULT_COMPLETION_CACHE_DIR } from "./options-j9p3L3r1.js";
2
2
  import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
4
  import { createHash } from "node:crypto";
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- import { $ as assertCompleteRequestPrompt, A as CreateMessageResultSchema, At as toSafeError, B as JSONRPCMessageSchema, C as AjvJsonSchemaValidator, D as CallToolRequestSchema, Dt as CAPLETS_ERROR_CODES, E as toJsonSchemaCompat, Et as SERVER_ID_PATTERN, F as EmptyResultSchema, G as ListRootsResultSchema, H as ListPromptsRequestSchema, I as ErrorCode, J as McpError, K as ListToolsRequestSchema, L as GetPromptRequestSchema, M as CreateTaskResultSchema, Nt as __require, O as CallToolResultSchema, Ot as CapletsError, P as ElicitResultSchema, Pt as __toESM, R as InitializeRequestSchema, S as assertToolsCallTaskCapability, St as resolveProjectCapletsRoot, T as mergeCapabilities, Tt as validateCapletFile, U as ListResourceTemplatesRequestSchema, V as LATEST_PROTOCOL_VERSION, W as ListResourcesRequestSchema, X as SUPPORTED_PROTOCOL_VERSIONS, Y as ReadResourceRequestSchema, Z as SetLevelRequestSchema, _t as parseConfig, a as resolveCapletsServer, at as getLiteralValue, bt as resolveCapletsRoot, c as ServerRegistry, ct as getSchemaDescription, d as runOAuthFlow, dt as normalizeObjectSchema, et as assertCompleteRequestResourceTemplate, f as startGenericOAuthFlow, ft as objectFromShape, g as readTokenBundle, gt as loadConfigWithSources, h as isTokenBundleExpired, ht as loadConfig, i as resolveCapletsMode, it as isJSONRPCResultResponse, j as CreateMessageResultWithToolsSchema, jt as __commonJSMin, k as CompleteRequestSchema, kt as redactSecrets, l as capabilityDescription, lt as isSchemaOptional, m as deleteTokenBundle, mt as safeParseAsync, nt as isJSONRPCErrorResponse, o as CapletsEngine, ot as getObjectShape, p as startOAuthFlow, pt as safeParse, q as LoggingLevelSchema, r as parseServerBaseUrl, rt as isJSONRPCRequest, s as handleServerTool, st as getParseErrorMessage, t as controlUrlForBase, tt as isInitializeRequest, u as runGenericOAuthFlow, ut as isZ4Schema, v as ReadBuffer, w as Protocol, wt as discoverCapletFiles, x as assertClientRequestTaskCapability, xt as resolveConfigPath, y as serializeMessage, z as InitializedNotificationSchema } from "./options-bnsSREid.js";
1
+ import { $ as assertCompleteRequestPrompt, A as CreateMessageResultSchema, At as toSafeError, B as JSONRPCMessageSchema, C as AjvJsonSchemaValidator, D as CallToolRequestSchema, Dt as CAPLETS_ERROR_CODES, E as toJsonSchemaCompat, Et as SERVER_ID_PATTERN, F as EmptyResultSchema, G as ListRootsResultSchema, H as ListPromptsRequestSchema, I as ErrorCode, J as McpError, K as ListToolsRequestSchema, L as GetPromptRequestSchema, M as CreateTaskResultSchema, Nt as __require, O as CallToolResultSchema, Ot as CapletsError, P as ElicitResultSchema, Pt as __toESM, R as InitializeRequestSchema, S as assertToolsCallTaskCapability, St as resolveProjectCapletsRoot, T as mergeCapabilities, Tt as validateCapletFile, U as ListResourceTemplatesRequestSchema, V as LATEST_PROTOCOL_VERSION, W as ListResourcesRequestSchema, X as SUPPORTED_PROTOCOL_VERSIONS, Y as ReadResourceRequestSchema, Z as SetLevelRequestSchema, _t as parseConfig, a as resolveCapletsServer, at as getLiteralValue, bt as resolveCapletsRoot, c as ServerRegistry, ct as getSchemaDescription, d as runOAuthFlow, dt as normalizeObjectSchema, et as assertCompleteRequestResourceTemplate, f as startGenericOAuthFlow, ft as objectFromShape, g as readTokenBundle, gt as loadConfigWithSources, h as isTokenBundleExpired, ht as loadConfig, i as resolveCapletsMode, it as isJSONRPCResultResponse, j as CreateMessageResultWithToolsSchema, jt as __commonJSMin, k as CompleteRequestSchema, kt as redactSecrets, l as capabilityDescription, lt as isSchemaOptional, m as deleteTokenBundle, mt as safeParseAsync, nt as isJSONRPCErrorResponse, o as CapletsEngine, ot as getObjectShape, p as startOAuthFlow, pt as safeParse, q as LoggingLevelSchema, r as parseServerBaseUrl, rt as isJSONRPCRequest, s as handleServerTool, st as getParseErrorMessage, t as controlUrlForBase, tt as isInitializeRequest, u as runGenericOAuthFlow, ut as isZ4Schema, v as ReadBuffer, w as Protocol, wt as discoverCapletFiles, x as assertClientRequestTaskCapability, xt as resolveConfigPath, y as serializeMessage, z as InitializedNotificationSchema } from "./options-j9p3L3r1.js";
2
2
  import { A as url, C as object, D as string, b as literal, d as ZodOptional, o as generatedToolInputSchema, s as generatedToolInputSchemaForCaplet } from "./generated-tool-input-schema-BYoyY-l-.js";
3
- import { a as formatCapletList, c as resolveCliConfigPaths, l as cliCommands, n as completionScript, o as formatConfigPaths, s as listCaplets, t as completeCliWords, u as completionShells } from "./completion-L23s2FGB.js";
4
- import { accessSync, chmodSync, closeSync, constants, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
5
- import { basename, dirname, join, parse, relative, resolve } from "node:path";
3
+ import { a as formatCapletList, c as resolveCliConfigPaths, l as cliCommands, n as completionScript, o as formatConfigPaths, s as listCaplets, t as completeCliWords, u as completionShells } from "./completion-Cq1z7ci2.js";
4
+ import { accessSync, chmodSync, closeSync, constants, copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, readlinkSync, realpathSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
5
+ import { basename, dirname, isAbsolute, join, parse, relative, resolve, sep } from "node:path";
6
6
  import { execFileSync } from "node:child_process";
7
7
  import process$1, { stdin, stdout } from "node:process";
8
8
  import { tmpdir } from "node:os";
@@ -1320,7 +1320,7 @@ const EMPTY_COMPLETION_RESULT = { completion: {
1320
1320
  } };
1321
1321
  //#endregion
1322
1322
  //#region package.json
1323
- var version = "0.18.2";
1323
+ var version = "0.18.3";
1324
1324
  //#endregion
1325
1325
  //#region src/serve/session.ts
1326
1326
  var CapletsMcpSession = class {
@@ -5192,12 +5192,14 @@ function rejectCrossKindDestinationCollision(plan, destinationRoot) {
5192
5192
  function installPlan(caplet, options) {
5193
5193
  const isDirectory = basename(caplet.path) === "CAPLET.md";
5194
5194
  const sourcePath = isDirectory ? dirname(caplet.path) : caplet.path;
5195
+ const sourceBoundary = dirname(sourcePath);
5195
5196
  const sourcePathRelative = relative(options.repoRoot, sourcePath);
5196
5197
  const destination = isDirectory ? join(options.destinationRoot, caplet.id) : join(options.destinationRoot, `${caplet.id}.md`);
5197
5198
  return {
5198
5199
  id: caplet.id,
5199
5200
  source: `${options.sourceId}#${sourcePathRelative}`,
5200
5201
  sourcePath,
5202
+ sourceBoundary,
5201
5203
  destination,
5202
5204
  kind: isDirectory ? "directory" : "file"
5203
5205
  };
@@ -5259,16 +5261,40 @@ function removeInstallPath(path, label, force) {
5259
5261
  }
5260
5262
  function copyInstallPath(plan) {
5261
5263
  try {
5264
+ if (plan.kind === "directory") {
5265
+ copyDirectoryCaplet(plan.sourcePath, plan.destination, realpathSync(plan.sourceBoundary));
5266
+ return;
5267
+ }
5262
5268
  cpSync(plan.sourcePath, plan.destination, {
5263
- recursive: plan.kind === "directory",
5269
+ recursive: false,
5264
5270
  force: false,
5265
5271
  errorOnExist: true
5266
5272
  });
5267
5273
  } catch (error) {
5274
+ if (error instanceof CapletsError) throw error;
5268
5275
  if (isFsError(error, "EEXIST") || isFsError(error, "EISDIR")) throw new CapletsError("CONFIG_EXISTS", `Caplet ${plan.id} already exists at ${plan.destination}; pass --force to overwrite it`, toSafeError(error));
5269
5276
  throw new CapletsError("CONFIG_INVALID", `Could not install Caplet ${plan.id} to ${plan.destination}`, toSafeError(error));
5270
5277
  }
5271
5278
  }
5279
+ function copyDirectoryCaplet(source, destination, sourceBoundary, seenDirectories = /* @__PURE__ */ new Set()) {
5280
+ const resolvedSource = lstatSync(source).isSymbolicLink() ? resolveDirectoryCapletSymlink(source, sourceBoundary) : source;
5281
+ if (statSync(resolvedSource).isDirectory()) {
5282
+ const realDirectory = realpathSync(resolvedSource);
5283
+ if (seenDirectories.has(realDirectory)) throw new CapletsError("CONFIG_INVALID", `Directory Caplet symlink ${source} creates a copy cycle`);
5284
+ const childSeenDirectories = new Set(seenDirectories);
5285
+ childSeenDirectories.add(realDirectory);
5286
+ mkdirSync(destination);
5287
+ for (const entry of readdirSync(resolvedSource)) copyDirectoryCaplet(join(resolvedSource, entry), join(destination, entry), sourceBoundary, childSeenDirectories);
5288
+ return;
5289
+ }
5290
+ copyFileSync(resolvedSource, destination);
5291
+ }
5292
+ function resolveDirectoryCapletSymlink(source, sourceBoundary) {
5293
+ const target = readlinkSync(source);
5294
+ const resolvedTarget = realpathSync(isAbsolute(target) ? target : resolve(dirname(source), target));
5295
+ if (resolvedTarget !== sourceBoundary && !resolvedTarget.startsWith(`${sourceBoundary}${sep}`)) throw new CapletsError("CONFIG_INVALID", `Directory Caplet symlink ${source} resolves outside source Caplets boundary`);
5296
+ return resolvedTarget;
5297
+ }
5272
5298
  function isFsError(error, code) {
5273
5299
  return typeof error === "object" && error !== null && "code" in error && error.code === code;
5274
5300
  }
package/dist/native.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Ot as CapletsError, Q as ToolListChangedNotificationSchema, _ as StreamableHTTPClientTransport, a as resolveCapletsServer, b as Client, i as resolveCapletsMode, l as capabilityDescription, n as mcpUrlForBase, o as CapletsEngine } from "./options-bnsSREid.js";
1
+ import { Ot as CapletsError, Q as ToolListChangedNotificationSchema, _ as StreamableHTTPClientTransport, a as resolveCapletsServer, b as Client, i as resolveCapletsMode, l as capabilityDescription, n as mcpUrlForBase, o as CapletsEngine } from "./options-j9p3L3r1.js";
2
2
  import { a as generatedToolInputJsonSchemaForCaplet, i as generatedToolInputJsonSchema, l as operations, o as generatedToolInputSchema } from "./generated-tool-input-schema-BYoyY-l-.js";
3
3
  //#region src/native/options.ts
4
4
  const DEFAULT_POLL_INTERVAL_MS = 3e4;
@@ -52655,8 +52655,21 @@ async function loadOpenApiSource(endpoint, authDir) {
52655
52655
  if (endpoint.specPath) return endpoint.specPath;
52656
52656
  if (!endpoint.specUrl) throw new CapletsError("CONFIG_INVALID", `${endpoint.server} is missing OpenAPI spec source`);
52657
52657
  if (!endpoint.baseUrl) throw new CapletsError("CONFIG_INVALID", `${endpoint.server} must configure baseUrl when using remote specUrl`);
52658
- const response = await fetchWithLimit(endpoint.specUrl, endpoint.requestTimeoutMs, shouldSendSpecAuth(endpoint) ? authHeaders(endpoint, authDir) : {});
52659
- return JSON.parse(response);
52658
+ return parseOpenApiSourceText(await fetchWithLimit(endpoint.specUrl, endpoint.requestTimeoutMs, shouldSendSpecAuth(endpoint) ? authHeaders(endpoint, authDir) : {}));
52659
+ }
52660
+ function parseOpenApiSourceText(source) {
52661
+ let parsed;
52662
+ try {
52663
+ parsed = JSON.parse(source);
52664
+ } catch (jsonError) {
52665
+ try {
52666
+ parsed = (0, import_dist$1.parse)(source);
52667
+ } catch {
52668
+ throw jsonError instanceof Error ? jsonError : new Error(String(jsonError));
52669
+ }
52670
+ }
52671
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("OpenAPI source must parse to an object");
52672
+ return parsed;
52660
52673
  }
52661
52674
  function extractOperations(endpoint, document) {
52662
52675
  const operations = [];
@@ -52674,6 +52687,7 @@ function extractOperations(endpoint, document) {
52674
52687
  const requestBody = requestBodyFor(operation);
52675
52688
  const outputSchema = outputSchemaFor(operation);
52676
52689
  const baseUrl = endpoint.baseUrl ?? firstServerUrl(document);
52690
+ const staticHeaders = staticHeaderDefaultsFor(endpoint, parameters);
52677
52691
  validateOperationBaseUrl(endpoint, baseUrl);
52678
52692
  operations.push({
52679
52693
  name,
@@ -52681,15 +52695,32 @@ function extractOperations(endpoint, document) {
52681
52695
  path,
52682
52696
  ...typeof operation.summary === "string" ? { summary: operation.summary } : {},
52683
52697
  ...typeof operation.description === "string" ? { description: operation.description } : {},
52684
- inputSchema: inputSchemaFor(parameters, requestBody),
52698
+ inputSchema: inputSchemaFor(parameters, requestBody, staticHeaders),
52685
52699
  ...outputSchema ? { outputSchema } : {},
52686
52700
  ...requestBody?.contentType ? { requestBodyContentType: requestBody.contentType } : {},
52687
- ...baseUrl ? { baseUrl } : {}
52701
+ ...baseUrl ? { baseUrl } : {},
52702
+ ...Object.keys(staticHeaders).length ? { staticHeaders } : {}
52688
52703
  });
52689
52704
  }
52690
52705
  }
52691
52706
  return operations.sort((left, right) => left.name.localeCompare(right.name));
52692
52707
  }
52708
+ function staticHeaderDefaultsFor(endpoint, parameters) {
52709
+ const configuredHeaderNames = configuredAuthHeaderNames(endpoint);
52710
+ const headers = {};
52711
+ for (const parameter of parameters) {
52712
+ if (parameter?.in !== "header" || typeof parameter.name !== "string") continue;
52713
+ const normalized = parameter.name.toLowerCase();
52714
+ if (configuredHeaderNames.has(normalized) || FORBIDDEN_ARGUMENT_HEADERS.has(normalized) && normalized !== "accept") continue;
52715
+ const defaultValue = parameter.schema?.default;
52716
+ if ([
52717
+ "string",
52718
+ "number",
52719
+ "boolean"
52720
+ ].includes(typeof defaultValue)) headers[parameter.name] = String(defaultValue);
52721
+ }
52722
+ return headers;
52723
+ }
52693
52724
  function requestBodyFor(operation) {
52694
52725
  const requestBody = operation.requestBody;
52695
52726
  if (!requestBody || typeof requestBody !== "object") return;
@@ -52750,19 +52781,20 @@ function structuredOutputSchema(bodySchema) {
52750
52781
  }
52751
52782
  };
52752
52783
  }
52753
- function inputSchemaFor(parameters, requestBody) {
52784
+ function inputSchemaFor(parameters, requestBody, staticHeaders = {}) {
52754
52785
  const schema = {
52755
52786
  type: "object",
52756
52787
  additionalProperties: false,
52757
52788
  properties: {}
52758
52789
  };
52759
52790
  const required = [];
52791
+ const protectedStaticHeaders = new Set(Object.keys(staticHeaders).map((key) => key.toLowerCase()).filter((key) => FORBIDDEN_ARGUMENT_HEADERS.has(key)));
52760
52792
  for (const location of [
52761
52793
  "path",
52762
52794
  "query",
52763
52795
  "header"
52764
52796
  ]) {
52765
- const locationParameters = parameters.filter((parameter) => parameter?.in === location);
52797
+ const locationParameters = parameters.filter((parameter) => parameter?.in === location && !(location === "header" && protectedStaticHeaders.has(parameter.name?.toLowerCase())));
52766
52798
  if (locationParameters.length === 0) continue;
52767
52799
  const nestedRequired = locationParameters.filter((parameter) => parameter.required === true || location === "path").map((parameter) => parameter.name);
52768
52800
  schema.properties[location] = {
@@ -52801,7 +52833,8 @@ function buildRequest(endpoint, operation, args, authDir) {
52801
52833
  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
52834
  const headers = new Headers();
52803
52835
  applyAuth(headers, endpoint, authDir);
52804
- const configuredHeaderNames = endpoint.auth.type === "headers" ? new Set(Object.keys(endpoint.auth.headers).map((key) => key.toLowerCase())) : /* @__PURE__ */ new Set();
52836
+ const configuredHeaderNames = configuredAuthHeaderNames(endpoint);
52837
+ for (const [key, value] of Object.entries(operation.staticHeaders ?? {})) if (!headers.has(key) && !configuredHeaderNames.has(key.toLowerCase())) headers.set(key, value);
52805
52838
  for (const [key, value] of Object.entries(asRecord(args.header))) if (value !== void 0 && value !== null) {
52806
52839
  const normalized = key.toLowerCase();
52807
52840
  if (FORBIDDEN_ARGUMENT_HEADERS.has(normalized) || configuredHeaderNames.has(normalized)) throw new CapletsError("REQUEST_INVALID", `Header ${key} cannot be supplied by arguments`);
@@ -52847,6 +52880,9 @@ function asRecord(value) {
52847
52880
  function applyAuth(headers, endpoint, authDir) {
52848
52881
  for (const [key, value] of Object.entries(authHeaders(endpoint, authDir))) headers.set(key, value);
52849
52882
  }
52883
+ function configuredAuthHeaderNames(endpoint) {
52884
+ return endpoint.auth.type === "headers" ? new Set(Object.keys(endpoint.auth.headers).map((key) => key.toLowerCase())) : /* @__PURE__ */ new Set();
52885
+ }
52850
52886
  function authHeaders(endpoint, authDir) {
52851
52887
  switch (endpoint.auth.type) {
52852
52888
  case "none": return {};
@@ -53853,7 +53889,7 @@ var CapletsEngine = class {
53853
53889
  }
53854
53890
  }
53855
53891
  async completeCliWords(words) {
53856
- const { completeCliWords } = await import("./completion-L23s2FGB.js").then((n) => n.r);
53892
+ const { completeCliWords } = await import("./completion-Cq1z7ci2.js").then((n) => n.r);
53857
53893
  return await completeCliWords(words, {
53858
53894
  config: this.registry.config,
53859
53895
  managers: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caplets/core",
3
- "version": "0.18.2",
3
+ "version": "0.18.3",
4
4
  "description": "Core runtime library for Caplets progressive disclosure gateways.",
5
5
  "keywords": [
6
6
  "caplets",
@@ -53,6 +53,7 @@
53
53
  "hono": "^4.12.21",
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": {