@caplets/core 0.26.1 → 0.28.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.
Files changed (43) hide show
  1. package/dist/attach/api.d.ts +10 -1
  2. package/dist/caplet-files-bundle.d.ts +1 -0
  3. package/dist/caplet-source.js +39 -3
  4. package/dist/cli/code-mode.d.ts +3 -2
  5. package/dist/cli/commands.d.ts +3 -1
  6. package/dist/cli/inspection.d.ts +2 -1
  7. package/dist/cli.d.ts +4 -0
  8. package/dist/code-mode/types.d.ts +2 -1
  9. package/dist/{completion-CFOJucl5.js → completion-CjE0EnbF.js} +16 -4
  10. package/dist/config/paths.d.ts +9 -0
  11. package/dist/config/validation.d.ts +2 -0
  12. package/dist/config-runtime.d.ts +6 -1
  13. package/dist/config-runtime.js +34 -3
  14. package/dist/config.d.ts +13 -2
  15. package/dist/engine.d.ts +18 -0
  16. package/dist/errors.d.ts +1 -1
  17. package/dist/esm-Db9dhnIG.js +7488 -0
  18. package/dist/exposure/namespace.d.ts +39 -0
  19. package/dist/index.js +840 -483
  20. package/dist/native/options.d.ts +1 -0
  21. package/dist/native/remote.d.ts +4 -2
  22. package/dist/native/service.d.ts +16 -2
  23. package/dist/native.js +1 -1
  24. package/dist/node-BgWIvSVP.js +17214 -0
  25. package/dist/rolldown-runtime-CE-6LUnI.js +44 -0
  26. package/dist/serve/http.d.ts +16 -1
  27. package/dist/serve/options.d.ts +2 -0
  28. package/dist/{service-aBIn4nrw.js → service-BfPCRxQ9.js} +2043 -154
  29. package/dist/src-Cd2QIUm1.js +813 -0
  30. package/dist/telemetry/context.d.ts +13 -0
  31. package/dist/telemetry/debug.d.ts +10 -0
  32. package/dist/telemetry/delivery.d.ts +1 -0
  33. package/dist/telemetry/events.d.ts +70 -0
  34. package/dist/telemetry/identity.d.ts +1 -0
  35. package/dist/telemetry/index.d.ts +8 -0
  36. package/dist/telemetry/intake.generated.d.ts +2 -0
  37. package/dist/telemetry/notice.d.ts +8 -0
  38. package/dist/telemetry/privacy.d.ts +3 -0
  39. package/dist/telemetry/providers.d.ts +21 -0
  40. package/dist/telemetry/runtime.d.ts +40 -0
  41. package/dist/telemetry/state.d.ts +53 -0
  42. package/dist/{validation-GD2x5HW1.js → validation-CWzd2gtn.js} +3 -1
  43. package/package.json +3 -1
@@ -1,53 +1,20 @@
1
+ import { i as __require, o as __toESM, t as __commonJSMin } from "./rolldown-runtime-CE-6LUnI.js";
1
2
  import { A as safeParseAsync$1, C as toJSONSchema, D as parse$3, E as $ZodType, F as NEVER, M as defineLazy, N as normalizeParams, O as parseAsync, P as $constructor, S as datetime, T as $ZodObject, _ as record, a as any, b as unknown, c as custom, d as literal, f as looseObject, g as preprocess, h as optional, i as _null, j as clone, k as safeParse$1, l as discriminatedUnion, m as object$1, o as array, p as number$1, r as _enum, s as boolean, t as ZodNumber$1, u as intersection, v as string, w as _coercedNumber, x as url, y as union } from "./schemas-BoqMu4MG.js";
2
- import { a as isAllowedHttpBaseUrl, c as validateHttpActionHeaders, d as errorResult, f as redactSecrets, i as SERVER_ID_PATTERN, n as HEADER_NAME_PATTERN, o as isAllowedRemoteUrl, p as toSafeError, r as HTTP_BASE_URL_PATTERN, s as isUrl, t as FORBIDDEN_HEADERS, u as CapletsError } from "./validation-GD2x5HW1.js";
3
+ import { a as SERVER_ID_PATTERN, c as isUrl, d as CapletsError, f as errorResult, i as NAMESPACE_ALIAS_LABEL_PATTERN, l as validateHttpActionHeaders, m as toSafeError, n as HEADER_NAME_PATTERN, o as isAllowedHttpBaseUrl, p as redactSecrets, r as HTTP_BASE_URL_PATTERN, s as isAllowedRemoteUrl, t as FORBIDDEN_HEADERS } from "./validation-CWzd2gtn.js";
3
4
  import { generatedToolInputJsonSchema, generatedToolInputJsonSchemaForCaplet, generatedToolInputSchemaForCaplet, mcpOperations, operations } from "./generated-tool-input-schema.js";
4
- import { f as observedOutputShapeKey, i as observeOutputShape, r as normalizedObservableValue, t as usefulOutputSchema, u as FileObservedOutputShapeStore } from "./observed-output-shapes-DuP7mJQf.js";
5
- import { createRequire } from "node:module";
6
- import { accessSync, chmodSync, constants, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
5
+ import { f as observedOutputShapeKey, g as stableJsonStringify, h as schemaHash, i as observeOutputShape, r as normalizedObservableValue, t as usefulOutputSchema, u as FileObservedOutputShapeStore } from "./observed-output-shapes-DuP7mJQf.js";
6
+ import { accessSync, chmodSync, constants, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
7
7
  import { basename, delimiter, dirname, extname, isAbsolute, join, parse, posix, relative, resolve, sep, win32 } from "node:path";
8
8
  import { spawn } from "node:child_process";
9
9
  import process$1 from "node:process";
10
10
  import { PassThrough } from "node:stream";
11
11
  import { createServer } from "node:http";
12
12
  import { createCipheriv, createDecipheriv, createHash, createHmac, randomBytes, randomUUID } from "node:crypto";
13
- import { homedir } from "node:os";
13
+ import { arch, homedir, platform } from "node:os";
14
14
  import { Buffer as Buffer$1 } from "node:buffer";
15
15
  import { readFile } from "node:fs/promises";
16
16
  import ts from "typescript";
17
17
  import { getQuickJS, shouldInterruptAfterDeadline } from "quickjs-emscripten";
18
- //#region \0rolldown/runtime.js
19
- var __create = Object.create;
20
- var __defProp = Object.defineProperty;
21
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
22
- var __getOwnPropNames = Object.getOwnPropertyNames;
23
- var __getProtoOf = Object.getPrototypeOf;
24
- var __hasOwnProp = Object.prototype.hasOwnProperty;
25
- var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
26
- var __exportAll = (all, no_symbols) => {
27
- let target = {};
28
- for (var name in all) __defProp(target, name, {
29
- get: all[name],
30
- enumerable: true
31
- });
32
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
33
- return target;
34
- };
35
- var __copyProps = (to, from, except, desc) => {
36
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
37
- key = keys[i];
38
- if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
39
- get: ((k) => from[k]).bind(null, key),
40
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
41
- });
42
- }
43
- return to;
44
- };
45
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
46
- value: mod,
47
- enumerable: true
48
- }) : target, mod));
49
- var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
50
- //#endregion
51
18
  //#region ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v3/helpers/util.js
52
19
  var util$1;
53
20
  (function(util) {
@@ -17242,6 +17209,18 @@ function defaultConfigPath(env = process.env, home = homedir(), platform = proce
17242
17209
  function defaultAuthDir(env = process.env, home = homedir(), platform = process.platform) {
17243
17210
  return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "auth");
17244
17211
  }
17212
+ function defaultTelemetryStateDir(env = process.env, home = homedir(), platform = process.platform) {
17213
+ return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "telemetry");
17214
+ }
17215
+ function defaultTelemetryIdentityPath(env = process.env, home = homedir(), platform = process.platform) {
17216
+ return (platform === "win32" ? win32.join : posix.join)(defaultTelemetryStateDir(env, home, platform), "identity.json");
17217
+ }
17218
+ function defaultTelemetryNoticePath(env = process.env, home = homedir(), platform = process.platform) {
17219
+ return (platform === "win32" ? win32.join : posix.join)(defaultTelemetryStateDir(env, home, platform), "notice.json");
17220
+ }
17221
+ function defaultTelemetryDeliveryHealthPath(env = process.env, home = homedir(), platform = process.platform) {
17222
+ return (platform === "win32" ? win32.join : posix.join)(defaultTelemetryStateDir(env, home, platform), "delivery-health.json");
17223
+ }
17245
17224
  function defaultArtifactDir(env = process.env, home = homedir(), platform = process.platform) {
17246
17225
  return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "artifacts");
17247
17226
  }
@@ -17256,6 +17235,10 @@ function defaultObservedOutputShapeCacheDir(env = process.env, home = homedir(),
17256
17235
  const DEFAULT_CONFIG_PATH = defaultConfigPath();
17257
17236
  const DEFAULT_AUTH_DIR = defaultAuthDir();
17258
17237
  const DEFAULT_ARTIFACT_DIR = defaultArtifactDir();
17238
+ const DEFAULT_TELEMETRY_STATE_DIR = defaultTelemetryStateDir();
17239
+ defaultTelemetryIdentityPath();
17240
+ defaultTelemetryNoticePath();
17241
+ defaultTelemetryDeliveryHealthPath();
17259
17242
  const DEFAULT_COMPLETION_CACHE_DIR = defaultCompletionCacheDir();
17260
17243
  const DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR = defaultObservedOutputShapeCacheDir();
17261
17244
  const PROJECT_CONFIG_FILE = join(".caplets", "config.json");
@@ -18627,8 +18610,8 @@ function compactToolSafetyHints(tool) {
18627
18610
  };
18628
18611
  }
18629
18612
  function compactToolSchemaHints(tool) {
18630
- const schema = isRecord$7(tool.inputSchema) ? tool.inputSchema : void 0;
18631
- const properties = isRecord$7(schema?.properties) ? schema.properties : {};
18613
+ const schema = isRecord$9(tool.inputSchema) ? tool.inputSchema : void 0;
18614
+ const properties = isRecord$9(schema?.properties) ? schema.properties : {};
18632
18615
  const acceptedArgs = Object.keys(properties).sort();
18633
18616
  const requiredArgs = Array.isArray(schema?.required) ? schema.required.filter((value) => typeof value === "string").sort() : [];
18634
18617
  const argsTemplate = compactArgsTemplate(properties, requiredArgs, acceptedArgs);
@@ -18652,7 +18635,7 @@ function compactArgsTemplate(properties, requiredArgs, acceptedArgs) {
18652
18635
  if (templateArgs.length === 0 || templateArgs.length > 4) return void 0;
18653
18636
  if (requiredArgs.length === 0 && acceptedArgs.length > 3) return void 0;
18654
18637
  const entries = templateArgs.flatMap((name) => {
18655
- const value = placeholderForSchema(isRecord$7(properties[name]) ? properties[name] : void 0);
18638
+ const value = placeholderForSchema(isRecord$9(properties[name]) ? properties[name] : void 0);
18656
18639
  return value === void 0 ? [] : [[name, value]];
18657
18640
  });
18658
18641
  return entries.length === templateArgs.length ? Object.fromEntries(entries) : void 0;
@@ -18672,13 +18655,13 @@ function placeholderForSchema(schema) {
18672
18655
  }
18673
18656
  }
18674
18657
  function compactToolSelectionHints(tool) {
18675
- if (!isRecord$7(tool)) return {};
18658
+ if (!isRecord$9(tool)) return {};
18676
18659
  return {
18677
18660
  ...typeof tool.useWhen === "string" && tool.useWhen.trim() ? { useWhen: tool.useWhen.trim() } : {},
18678
18661
  ...typeof tool.avoidWhen === "string" && tool.avoidWhen.trim() ? { avoidWhen: tool.avoidWhen.trim() } : {}
18679
18662
  };
18680
18663
  }
18681
- function isRecord$7(value) {
18664
+ function isRecord$9(value) {
18682
18665
  return value !== null && typeof value === "object" && !Array.isArray(value);
18683
18666
  }
18684
18667
  function sameServerConfig(left, right) {
@@ -18753,7 +18736,7 @@ function markdownCallToolResultContent(result, context = {}) {
18753
18736
  return textContent(renderStructuredMarkdown(result, context));
18754
18737
  }
18755
18738
  function hasRenderableStructuredContent(value) {
18756
- if (!isRecord$6(value)) return false;
18739
+ if (!isRecord$8(value)) return false;
18757
18740
  return Object.keys(value).some((key) => key !== "caplets" && key !== "elapsedMs");
18758
18741
  }
18759
18742
  function renderStructuredMarkdown(value, context) {
@@ -18887,13 +18870,13 @@ function renderErrorMarkdown(value, title) {
18887
18870
  ].join("\n");
18888
18871
  }
18889
18872
  function isDiscoveryWrapper(value) {
18890
- return isRecord$6(value) && "result" in value;
18873
+ return isRecord$8(value) && "result" in value;
18891
18874
  }
18892
18875
  function isErrorStructuredContent(value) {
18893
- return isRecord$6(value) && "error" in value;
18876
+ return isRecord$8(value) && "error" in value;
18894
18877
  }
18895
18878
  function isHttpLikeResult(value) {
18896
- return isRecord$6(value) && ("status" in value || "statusText" in value || "body" in value);
18879
+ return isRecord$8(value) && ("status" in value || "statusText" in value || "body" in value);
18897
18880
  }
18898
18881
  function isGraphQlHttpResult(value) {
18899
18882
  if (!isHttpLikeResult(value)) return false;
@@ -18901,7 +18884,7 @@ function isGraphQlHttpResult(value) {
18901
18884
  return Boolean(body && ("data" in body || "errors" in body));
18902
18885
  }
18903
18886
  function isCliResult(value) {
18904
- return isRecord$6(value) && ("exitCode" in value || "stdout" in value || "stderr" in value);
18887
+ return isRecord$8(value) && ("exitCode" in value || "stdout" in value || "stderr" in value);
18905
18888
  }
18906
18889
  function renderBodyValue(value) {
18907
18890
  if (value === void 0) return "_No response body._";
@@ -18969,8 +18952,8 @@ function compactListHints(record) {
18969
18952
  const acceptedArgs = stringArrayValue(record.acceptedArgs);
18970
18953
  if (requiredArgs.length > 0) hints.push(`required args: ${requiredArgs.join(", ")}`);
18971
18954
  else if (acceptedArgs.length > 0) hints.push(`args: ${acceptedArgs.join(", ")}`);
18972
- if (isRecord$6(record.argsTemplate)) hints.push(`args template: ${compactJsonText(record.argsTemplate, 160)}`);
18973
- if (isRecord$6(record.callTemplate)) hints.push(`call: ${compactJsonText(record.callTemplate, 220)}`);
18955
+ if (isRecord$8(record.argsTemplate)) hints.push(`args template: ${compactJsonText(record.argsTemplate, 160)}`);
18956
+ if (isRecord$8(record.callTemplate)) hints.push(`call: ${compactJsonText(record.callTemplate, 220)}`);
18974
18957
  if (record.supportsFields === true) hints.push("supports fields");
18975
18958
  if (record.readOnlyHint === true) hints.push("read-only");
18976
18959
  if (record.destructiveHint === true) hints.push("destructive");
@@ -19040,9 +19023,9 @@ function humanizeKey(key) {
19040
19023
  return key.replace(/([A-Z])/gu, " $1").replace(/^./u, (char) => char.toUpperCase());
19041
19024
  }
19042
19025
  function asRecord$3(value) {
19043
- return isRecord$6(value) ? value : void 0;
19026
+ return isRecord$8(value) ? value : void 0;
19044
19027
  }
19045
- function isRecord$6(value) {
19028
+ function isRecord$8(value) {
19046
19029
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
19047
19030
  }
19048
19031
  //#endregion
@@ -26005,7 +25988,11 @@ const capletExposureSchema = _enum([
26005
25988
  "direct_and_code_mode",
26006
25989
  "progressive_and_code_mode"
26007
25990
  ]).describe("How this Caplet is exposed to agents.");
26008
- const capletShadowingSchema = _enum(["forbid", "allow"]).describe("Whether attached local Caplets may shadow this remote Caplet ID.");
25991
+ const capletShadowingSchema = _enum([
25992
+ "forbid",
25993
+ "allow",
25994
+ "namespace"
25995
+ ]).describe("Whether attached local Caplets may shadow this remote Caplet ID.");
26009
25996
  const capletEndpointAuthSchema = discriminatedUnion("type", [
26010
25997
  object$1({ type: literal("none") }).strict(),
26011
25998
  object$1({
@@ -27288,7 +27275,33 @@ const exposureSchema = _enum([
27288
27275
  "direct_and_code_mode",
27289
27276
  "progressive_and_code_mode"
27290
27277
  ]).describe("How this Caplet is exposed to agents.");
27291
- const shadowingSchema = _enum(["forbid", "allow"]).default("forbid").describe("Whether attached local Caplets may shadow this remote Caplet ID.");
27278
+ const shadowingSchema = _enum([
27279
+ "forbid",
27280
+ "allow",
27281
+ "namespace"
27282
+ ]).default("forbid").describe("Whether attached local Caplets may shadow this remote Caplet ID.");
27283
+ const namespaceAliasLabelSchema = string().regex(NAMESPACE_ALIAS_LABEL_PATTERN, "namespace alias labels must be lowercase DNS-style labels using letters, numbers, or hyphens").describe("Namespace label used when qualifying colliding Caplet IDs.");
27284
+ const namespaceAliasesSchema = object$1({
27285
+ local: namespaceAliasLabelSchema.optional(),
27286
+ upstreams: record(string().trim().min(1), namespaceAliasLabelSchema).default({}).describe("Namespace aliases keyed by durable upstream source identity.")
27287
+ }).strict().default({ upstreams: {} }).superRefine((aliases, ctx) => {
27288
+ const seen = /* @__PURE__ */ new Map();
27289
+ const addAlias = (value, path) => {
27290
+ if (!value) return;
27291
+ const existing = seen.get(value);
27292
+ if (existing) {
27293
+ ctx.addIssue({
27294
+ code: "custom",
27295
+ path,
27296
+ message: `namespace alias '${value}' is already used at ${existing.join(".")}`
27297
+ });
27298
+ return;
27299
+ }
27300
+ seen.set(value, path);
27301
+ };
27302
+ addAlias(aliases.local, ["local"]);
27303
+ for (const [selector, alias] of Object.entries(aliases.upstreams)) addAlias(alias, ["upstreams", selector]);
27304
+ }).describe("Source-level namespace aliases for hash-qualified Caplet IDs.");
27292
27305
  const publicServerSchema = object$1({
27293
27306
  name: string().trim().min(1).max(80).describe("Human-readable server display name."),
27294
27307
  description: string().describe("Capability description shown to agents before downstream tools 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"),
@@ -27525,6 +27538,7 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, googleDi
27525
27538
  version: literal(1).default(1).describe("Caplets config schema version."),
27526
27539
  defaultSearchLimit: number$1().int().positive().default(20).describe("Default maximum number of same-server search results."),
27527
27540
  maxSearchLimit: number$1().int().positive().max(50).default(50).describe("Maximum accepted search_tools limit."),
27541
+ telemetry: boolean().optional().describe("Set false to disable anonymous Caplets telemetry for this user config."),
27528
27542
  completion: object$1({
27529
27543
  discoveryTimeoutMs: number$1().int().positive().default(750),
27530
27544
  overallTimeoutMs: number$1().int().positive().default(1500),
@@ -27545,6 +27559,7 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, googleDi
27545
27559
  exposureDiscoveryTimeoutMs: 15e3,
27546
27560
  exposureDiscoveryConcurrency: 4
27547
27561
  }).describe("Global Caplets runtime options."),
27562
+ namespaceAliases: namespaceAliasesSchema,
27548
27563
  mcpServers: record(string().regex(SERVER_ID_PATTERN), serverValueSchema).default({}).describe("Downstream MCP servers keyed by stable server ID."),
27549
27564
  openapiEndpoints: record(string().regex(SERVER_ID_PATTERN), openApiEndpointValueSchema).default({}).describe("OpenAPI endpoints keyed by stable Caplet ID."),
27550
27565
  googleDiscoveryApis: record(string().regex(SERVER_ID_PATTERN), googleDiscoveryApiValueSchema).default({}).describe("Google Discovery APIs keyed by stable Caplet ID."),
@@ -28321,6 +28336,8 @@ function mergeConfigInputs(...inputs) {
28321
28336
  merged = {
28322
28337
  ...merged,
28323
28338
  ...input,
28339
+ telemetry: input.telemetry === void 0 ? merged?.telemetry : input.telemetry,
28340
+ namespaceAliases: mergeNamespaceAliases(merged?.namespaceAliases, input.namespaceAliases),
28324
28341
  mcpServers: {
28325
28342
  ...merged?.mcpServers,
28326
28343
  ...input.mcpServers
@@ -28353,19 +28370,37 @@ function mergeConfigInputs(...inputs) {
28353
28370
  }
28354
28371
  return merged;
28355
28372
  }
28373
+ function mergeNamespaceAliases(left, right) {
28374
+ if (right !== void 0 && !isPlainObject$5(right)) return right;
28375
+ if (left !== void 0 && !isPlainObject$5(left)) return left;
28376
+ if (!isPlainObject$5(left) && !isPlainObject$5(right)) return;
28377
+ const leftRecord = isPlainObject$5(left) ? left : void 0;
28378
+ const rightRecord = isPlainObject$5(right) ? right : void 0;
28379
+ const leftUpstreams = isPlainObject$5(leftRecord?.upstreams) ? leftRecord.upstreams : void 0;
28380
+ const rightUpstreams = isPlainObject$5(rightRecord?.upstreams) ? rightRecord.upstreams : void 0;
28381
+ return stripUndefined({
28382
+ ...leftRecord,
28383
+ ...rightRecord,
28384
+ upstreams: {
28385
+ ...leftUpstreams,
28386
+ ...rightUpstreams
28387
+ }
28388
+ });
28389
+ }
28356
28390
  function mergeConfigInputsWithSources(...inputs) {
28357
28391
  let merged = {};
28358
28392
  const sources = {};
28359
28393
  const shadows = {};
28360
28394
  for (const entry of inputs) {
28361
28395
  if (entry?.input === void 0) continue;
28362
- for (const id of capletIds(entry.input)) {
28396
+ const entryInput = entry.source.kind === "global-config" ? entry.input : stripUserOnlyConfig(entry.input);
28397
+ for (const id of capletIds(entryInput)) {
28363
28398
  const source = sourceForId(entry.source, id);
28364
28399
  if (sources[id]) shadows[id] = [...shadows[id] ?? [], sources[id]];
28365
28400
  sources[id] = source;
28366
28401
  merged = removeCapletId(merged, id);
28367
28402
  }
28368
- merged = mergeConfigInputs(merged, entry.input) ?? {};
28403
+ merged = mergeConfigInputs(merged, entryInput) ?? {};
28369
28404
  }
28370
28405
  return {
28371
28406
  input: merged,
@@ -28373,6 +28408,10 @@ function mergeConfigInputsWithSources(...inputs) {
28373
28408
  shadows
28374
28409
  };
28375
28410
  }
28411
+ function stripUserOnlyConfig(input) {
28412
+ const { telemetry: _telemetry, ...rest } = input;
28413
+ return rest;
28414
+ }
28376
28415
  function removeCapletBackendId(input, backend, id) {
28377
28416
  const caplets = input[backend];
28378
28417
  if (!isPlainObject$5(caplets)) return input;
@@ -28469,6 +28508,7 @@ function parseConfig(input, options = {}) {
28469
28508
  });
28470
28509
  return {
28471
28510
  version: parsed.data.version,
28511
+ telemetry: parsed.data.telemetry,
28472
28512
  options: {
28473
28513
  defaultSearchLimit: parsed.data.defaultSearchLimit,
28474
28514
  maxSearchLimit: parsed.data.maxSearchLimit,
@@ -28477,6 +28517,10 @@ function parseConfig(input, options = {}) {
28477
28517
  exposureDiscoveryConcurrency: parsed.data.options.exposureDiscoveryConcurrency,
28478
28518
  completion: parsed.data.completion
28479
28519
  },
28520
+ namespaceAliases: stripUndefined({
28521
+ local: parsed.data.namespaceAliases.local,
28522
+ upstreams: parsed.data.namespaceAliases.upstreams
28523
+ }),
28480
28524
  mcpServers: servers,
28481
28525
  openapiEndpoints,
28482
28526
  googleDiscoveryApis,
@@ -28609,17 +28653,17 @@ function googleDiscoveryScopesForOperations(operations) {
28609
28653
  return [...new Set(operations.flatMap((operation) => operation.scopes))].sort();
28610
28654
  }
28611
28655
  function validateGoogleDiscoveryDocument(value) {
28612
- if (!isRecord$5(value)) throw new Error("Invalid Google Discovery document: expected an object");
28656
+ if (!isRecord$7(value)) throw new Error("Invalid Google Discovery document: expected an object");
28613
28657
  if (value.kind !== void 0 && value.kind !== "discovery#restDescription") throw new Error("Invalid Google Discovery document: expected kind discovery#restDescription");
28614
- if (value.resources !== void 0 && !isRecord$5(value.resources)) throw new Error("Invalid Google Discovery document: expected resources object");
28615
- if (value.methods !== void 0 && !isRecord$5(value.methods)) throw new Error("Invalid Google Discovery document: expected methods object");
28616
- if (!isRecord$5(value.resources) && !isRecord$5(value.methods)) throw new Error("Invalid Google Discovery document: expected resources or methods object");
28617
- if (value.schemas !== void 0 && !isRecord$5(value.schemas)) throw new Error("Invalid Google Discovery document: expected schemas object");
28618
- if (value.parameters !== void 0 && !isRecord$5(value.parameters)) throw new Error("Invalid Google Discovery document: expected parameters object");
28658
+ if (value.resources !== void 0 && !isRecord$7(value.resources)) throw new Error("Invalid Google Discovery document: expected resources object");
28659
+ if (value.methods !== void 0 && !isRecord$7(value.methods)) throw new Error("Invalid Google Discovery document: expected methods object");
28660
+ if (!isRecord$7(value.resources) && !isRecord$7(value.methods)) throw new Error("Invalid Google Discovery document: expected resources or methods object");
28661
+ if (value.schemas !== void 0 && !isRecord$7(value.schemas)) throw new Error("Invalid Google Discovery document: expected schemas object");
28662
+ if (value.parameters !== void 0 && !isRecord$7(value.parameters)) throw new Error("Invalid Google Discovery document: expected parameters object");
28619
28663
  return value;
28620
28664
  }
28621
28665
  function collectDocumentMethods(document) {
28622
- return [...Object.entries(document.methods ?? {}).filter((entry) => isRecord$5(entry[1])).map(([methodKey, method]) => ({
28666
+ return [...Object.entries(document.methods ?? {}).filter((entry) => isRecord$7(entry[1])).map(([methodKey, method]) => ({
28623
28667
  resourcePath: [],
28624
28668
  methodKey,
28625
28669
  method
@@ -28628,9 +28672,9 @@ function collectDocumentMethods(document) {
28628
28672
  function collectMethods(resources, resourcePath = []) {
28629
28673
  const entries = [];
28630
28674
  for (const [resourceName, resource] of Object.entries(resources)) {
28631
- if (!isRecord$5(resource)) continue;
28675
+ if (!isRecord$7(resource)) continue;
28632
28676
  const nextPath = [...resourcePath, resourceName];
28633
- for (const [methodKey, method] of Object.entries(resource.methods ?? {})) if (isRecord$5(method)) entries.push({
28677
+ for (const [methodKey, method] of Object.entries(resource.methods ?? {})) if (isRecord$7(method)) entries.push({
28634
28678
  resourcePath: nextPath,
28635
28679
  methodKey,
28636
28680
  method
@@ -28803,7 +28847,7 @@ function globMatches(pattern, name) {
28803
28847
  function isJsonSchemaObject(value) {
28804
28848
  return value.type === "object" || "properties" in value || "additionalProperties" in value;
28805
28849
  }
28806
- function isRecord$5(value) {
28850
+ function isRecord$7(value) {
28807
28851
  return typeof value === "object" && value !== null && !Array.isArray(value);
28808
28852
  }
28809
28853
  function collapseWhitespace(value) {
@@ -63892,6 +63936,746 @@ async function withTimeout(promise, timeoutMs) {
63892
63936
  }
63893
63937
  }
63894
63938
  //#endregion
63939
+ //#region src/telemetry/state.ts
63940
+ function telemetryStateDir(options = {}) {
63941
+ return options.stateDir ?? DEFAULT_TELEMETRY_STATE_DIR;
63942
+ }
63943
+ function telemetryIdentityPath(options = {}) {
63944
+ return join(telemetryStateDir(options), "identity.json");
63945
+ }
63946
+ function telemetryNoticePath(options = {}) {
63947
+ return join(telemetryStateDir(options), "notice.json");
63948
+ }
63949
+ function telemetryDeliveryHealthPath(options = {}) {
63950
+ return join(telemetryStateDir(options), "delivery-health.json");
63951
+ }
63952
+ function readTelemetryIdentity(options = {}) {
63953
+ const path = telemetryIdentityPath(options);
63954
+ const existing = readJson(path);
63955
+ if (typeof existing?.id === "string" && /^anon_[a-f0-9]{32}$/u.test(existing.id)) return {
63956
+ kind: "stable",
63957
+ id: existing.id
63958
+ };
63959
+ if (!options.create) return {
63960
+ kind: "ephemeral",
63961
+ id: ephemeralId(),
63962
+ reason: "state-unavailable"
63963
+ };
63964
+ const identity = {
63965
+ id: stableId(),
63966
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
63967
+ };
63968
+ if (!writePrivateJson(path, identity)) return {
63969
+ kind: "ephemeral",
63970
+ id: ephemeralId(),
63971
+ reason: "state-unavailable"
63972
+ };
63973
+ return {
63974
+ kind: "stable",
63975
+ id: identity.id
63976
+ };
63977
+ }
63978
+ function rotateTelemetryIdentity(options = {}) {
63979
+ const identity = {
63980
+ id: stableId(),
63981
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
63982
+ };
63983
+ if (!writePrivateJson(telemetryIdentityPath(options), identity)) return {
63984
+ kind: "ephemeral",
63985
+ id: ephemeralId(),
63986
+ reason: "state-unavailable"
63987
+ };
63988
+ return {
63989
+ kind: "stable",
63990
+ id: identity.id
63991
+ };
63992
+ }
63993
+ function deleteTelemetryIdentity(options = {}) {
63994
+ try {
63995
+ rmSync(telemetryIdentityPath(options), { force: true });
63996
+ } catch {}
63997
+ }
63998
+ function readTelemetryNotice(options = {}) {
63999
+ const existing = readJson(telemetryNoticePath(options));
64000
+ if (existing?.shown === true && typeof existing.shownAt === "string" && isTelemetrySurface(existing.surface)) return {
64001
+ shown: true,
64002
+ shownAt: existing.shownAt,
64003
+ surface: existing.surface
64004
+ };
64005
+ return { shown: false };
64006
+ }
64007
+ function recordTelemetryNoticeShown(options) {
64008
+ const notice = {
64009
+ shown: true,
64010
+ shownAt: (/* @__PURE__ */ new Date()).toISOString(),
64011
+ surface: options.surface
64012
+ };
64013
+ writePrivateJson(telemetryNoticePath(options), notice);
64014
+ return notice;
64015
+ }
64016
+ function readTelemetryDeliveryHealth(options = {}) {
64017
+ const existing = readJson(telemetryDeliveryHealthPath(options));
64018
+ if (!isDeliveryHealth(existing)) return {};
64019
+ return existing;
64020
+ }
64021
+ function recordTelemetryDrop(options) {
64022
+ const health = readTelemetryDeliveryHealth(options);
64023
+ health[options.provider] = health[options.provider] ?? {};
64024
+ health[options.provider][options.reason] = (health[options.provider][options.reason] ?? 0) + 1;
64025
+ writePrivateJson(telemetryDeliveryHealthPath(options), health);
64026
+ }
64027
+ function writePrivateJson(path, value) {
64028
+ try {
64029
+ mkdirSync(dirname(path), {
64030
+ recursive: true,
64031
+ mode: 448
64032
+ });
64033
+ const tmp = `${path}.${process.pid}.${randomUUID()}.tmp`;
64034
+ writeFileSync(tmp, `${JSON.stringify(value, null, 2)}\n`, { mode: 384 });
64035
+ renameSync(tmp, path);
64036
+ return true;
64037
+ } catch {
64038
+ return false;
64039
+ }
64040
+ }
64041
+ function readJson(path) {
64042
+ if (!existsSync(path)) return void 0;
64043
+ try {
64044
+ return JSON.parse(readFileSync(path, "utf8"));
64045
+ } catch {
64046
+ return;
64047
+ }
64048
+ }
64049
+ function stableId() {
64050
+ return `anon_${randomBytes(16).toString("hex")}`;
64051
+ }
64052
+ function ephemeralId() {
64053
+ return `ephemeral_${randomBytes(16).toString("hex")}`;
64054
+ }
64055
+ function isTelemetrySurface(value) {
64056
+ return value === "cli" || value === "serve" || value === "attach" || value === "daemon" || value === "native" || value === "code_mode";
64057
+ }
64058
+ function isDeliveryHealth(value) {
64059
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
64060
+ for (const provider of Object.values(value)) {
64061
+ if (!provider || typeof provider !== "object" || Array.isArray(provider)) return false;
64062
+ for (const count of Object.values(provider)) if (typeof count !== "number" || !Number.isInteger(count) || count < 0) return false;
64063
+ }
64064
+ return true;
64065
+ }
64066
+ //#endregion
64067
+ //#region src/telemetry/context.ts
64068
+ function resolveTelemetryState(options) {
64069
+ const env = options.env ?? process.env;
64070
+ const executionContext = classifyExecutionContext(env);
64071
+ const notice = readTelemetryNotice(options);
64072
+ const base = {
64073
+ surface: options.surface,
64074
+ visibility: options.visibility,
64075
+ executionContext,
64076
+ notice,
64077
+ stateDir: options.stateDir
64078
+ };
64079
+ if (options.debug) return {
64080
+ ...base,
64081
+ status: "debug",
64082
+ decider: "debug"
64083
+ };
64084
+ if (env.CAPLETS_DISABLE_TELEMETRY === "1") return {
64085
+ ...base,
64086
+ status: "disabled",
64087
+ decider: "env"
64088
+ };
64089
+ if (options.config?.telemetry === false) return {
64090
+ ...base,
64091
+ status: "disabled",
64092
+ decider: "config"
64093
+ };
64094
+ if (isTestEnv(env)) return {
64095
+ ...base,
64096
+ status: "disabled",
64097
+ decider: "test"
64098
+ };
64099
+ if (executionContext !== "ci" && !notice.shown && !options.allowWithoutNotice) return {
64100
+ ...base,
64101
+ status: "suppressed",
64102
+ decider: "notice"
64103
+ };
64104
+ return {
64105
+ ...base,
64106
+ status: "enabled",
64107
+ decider: "default",
64108
+ identity: readTelemetryIdentity({
64109
+ ...options,
64110
+ create: options.createIdentity !== false
64111
+ })
64112
+ };
64113
+ }
64114
+ function classifyExecutionContext(env = process.env) {
64115
+ if (env.CI === "true" || env.GITHUB_ACTIONS === "true" || env.BUILDKITE === "true") return "ci";
64116
+ return process.stdout.isTTY || process.stderr.isTTY ? "interactive" : "noninteractive";
64117
+ }
64118
+ function isTestEnv(env) {
64119
+ return env.NODE_ENV === "test" || env.VITEST === "true" || env.VITEST_WORKER_ID !== void 0 || env.CAPLETS_TEST === "1";
64120
+ }
64121
+ //#endregion
64122
+ //#region src/telemetry/notice.ts
64123
+ const TELEMETRY_NOTICE = "Caplets collects anonymous telemetry for product usage and reliability. Disable it with CAPLETS_DISABLE_TELEMETRY=1 or `caplets telemetry disable`.\n";
64124
+ function maybePrintTelemetryNotice(options) {
64125
+ if (!options.stderrIsTTY) return false;
64126
+ if (readTelemetryNotice(options).shown) return false;
64127
+ options.writeErr(TELEMETRY_NOTICE);
64128
+ recordTelemetryNoticeShown({
64129
+ ...options,
64130
+ surface: options.surface
64131
+ });
64132
+ return true;
64133
+ }
64134
+ //#endregion
64135
+ //#region src/telemetry/privacy.ts
64136
+ const ALLOWED_PROPERTY_KEYS = /* @__PURE__ */ new Set([
64137
+ "$process_person_profile",
64138
+ "$geoip_disable",
64139
+ "package",
64140
+ "version",
64141
+ "surface",
64142
+ "runtime_mode",
64143
+ "execution_context",
64144
+ "command_family",
64145
+ "operation_family",
64146
+ "outcome",
64147
+ "duration_bucket",
64148
+ "timeout_bucket",
64149
+ "integration",
64150
+ "exposure_mode",
64151
+ "backend_mcp_count",
64152
+ "backend_openapi_count",
64153
+ "backend_google_discovery_count",
64154
+ "backend_graphql_count",
64155
+ "backend_http_count",
64156
+ "backend_cli_count",
64157
+ "backend_caplets_count",
64158
+ "direct_count",
64159
+ "progressive_count",
64160
+ "code_mode_count",
64161
+ "session_category",
64162
+ "any_caplet_invoked",
64163
+ "provider",
64164
+ "reason",
64165
+ "count_bucket",
64166
+ "error_code",
64167
+ "diagnostic_category",
64168
+ "os_family",
64169
+ "arch",
64170
+ "node_major"
64171
+ ]);
64172
+ const SAFE_STRING = /^[a-zA-Z0-9@._:-]{1,80}$/u;
64173
+ const SAFE_PACKAGE = /^@?[a-zA-Z0-9._-]+(?:\/[a-zA-Z0-9._-]+)?$/u;
64174
+ const SUSPICIOUS_VALUE = [
64175
+ /^\/|^[A-Za-z]:\\/u,
64176
+ /^https?:\/\//iu,
64177
+ /[a-z0-9-]+\.[a-z]{2,}/iu,
64178
+ /(?:^|[_.-])token(?:$|[_.=-])/iu,
64179
+ /(?:^|[_.-])secret(?:$|[_.=-])/iu,
64180
+ /(?:^|[_.-])key(?:$|[_.=-])/iu,
64181
+ /^sk-[a-z0-9]/iu,
64182
+ /^gh[pousr]_[a-z0-9]/iu,
64183
+ /^[A-Z_]{3,}=.+/u
64184
+ ];
64185
+ const COMMAND_FAMILIES = /* @__PURE__ */ new Set([
64186
+ "init",
64187
+ "setup",
64188
+ "add",
64189
+ "install",
64190
+ "auth",
64191
+ "remote",
64192
+ "doctor",
64193
+ "serve",
64194
+ "attach",
64195
+ "daemon",
64196
+ "inspect",
64197
+ "check",
64198
+ "tools",
64199
+ "resources",
64200
+ "prompts",
64201
+ "complete",
64202
+ "code_mode",
64203
+ "native",
64204
+ "telemetry",
64205
+ "unknown"
64206
+ ]);
64207
+ const STRING_VALUE_ALLOWLISTS = {
64208
+ surface: /* @__PURE__ */ new Set([
64209
+ "cli",
64210
+ "serve",
64211
+ "attach",
64212
+ "daemon",
64213
+ "native",
64214
+ "code_mode"
64215
+ ]),
64216
+ runtime_mode: /* @__PURE__ */ new Set([
64217
+ "local",
64218
+ "remote",
64219
+ "cloud",
64220
+ "unknown"
64221
+ ]),
64222
+ execution_context: /* @__PURE__ */ new Set([
64223
+ "interactive",
64224
+ "noninteractive",
64225
+ "ci"
64226
+ ]),
64227
+ command_family: COMMAND_FAMILIES,
64228
+ operation_family: COMMAND_FAMILIES,
64229
+ outcome: /* @__PURE__ */ new Set([
64230
+ "success",
64231
+ "failure",
64232
+ "cancelled",
64233
+ "timeout",
64234
+ "suppressed"
64235
+ ]),
64236
+ duration_bucket: /* @__PURE__ */ new Set([
64237
+ "lt_100ms",
64238
+ "lt_1s",
64239
+ "lt_5s",
64240
+ "lt_30s",
64241
+ "gte_30s"
64242
+ ]),
64243
+ timeout_bucket: /* @__PURE__ */ new Set([
64244
+ "none",
64245
+ "lt_1s",
64246
+ "lt_10s",
64247
+ "lt_60s",
64248
+ "gte_60s"
64249
+ ]),
64250
+ integration: /* @__PURE__ */ new Set([
64251
+ "opencode",
64252
+ "pi",
64253
+ "native",
64254
+ "unknown"
64255
+ ]),
64256
+ exposure_mode: /* @__PURE__ */ new Set([
64257
+ "direct",
64258
+ "progressive",
64259
+ "code_mode",
64260
+ "mixed",
64261
+ "unknown"
64262
+ ]),
64263
+ session_category: /* @__PURE__ */ new Set([
64264
+ "created",
64265
+ "reused",
64266
+ "none",
64267
+ "unknown"
64268
+ ]),
64269
+ provider: /* @__PURE__ */ new Set(["posthog", "sentry"]),
64270
+ reason: /* @__PURE__ */ new Set(["not_configured", "send_failed"]),
64271
+ diagnostic_category: /* @__PURE__ */ new Set([
64272
+ "config",
64273
+ "auth",
64274
+ "network",
64275
+ "runtime",
64276
+ "validation",
64277
+ "code_mode",
64278
+ "provider",
64279
+ "unknown"
64280
+ ])
64281
+ };
64282
+ function assertTelemetrySafeProperties(properties) {
64283
+ for (const [key, value] of Object.entries(properties)) {
64284
+ if (!ALLOWED_PROPERTY_KEYS.has(key)) throw new Error(`unknown telemetry property: ${key}`);
64285
+ if (typeof value === "string") {
64286
+ const valueAllowlist = STRING_VALUE_ALLOWLISTS[key];
64287
+ if (valueAllowlist && !valueAllowlist.has(value)) throw new Error(`unsafe telemetry property ${key}`);
64288
+ if (key === "error_code" && !/^[A-Z_]{2,80}$/u.test(value)) throw new Error(`unsafe telemetry property ${key}`);
64289
+ if (!(key === "package" ? SAFE_PACKAGE.test(value) : SAFE_STRING.test(value)) || key !== "package" && key !== "version" && SUSPICIOUS_VALUE.some((pattern) => pattern.test(value))) throw new Error(`unsafe telemetry property ${key}`);
64290
+ continue;
64291
+ }
64292
+ if (typeof value === "number") {
64293
+ if (!Number.isFinite(value) || value < 0 || !Number.isInteger(value)) throw new Error(`unsafe telemetry property ${key}`);
64294
+ continue;
64295
+ }
64296
+ if (typeof value === "boolean") continue;
64297
+ throw new Error(`unsafe telemetry property ${key}`);
64298
+ }
64299
+ }
64300
+ function stripSentryEvent(event) {
64301
+ const stripped = {};
64302
+ if (event.tags && typeof event.tags === "object" && !Array.isArray(event.tags)) stripped.tags = event.tags;
64303
+ if (Array.isArray(event.fingerprint)) stripped.fingerprint = event.fingerprint;
64304
+ if (event.level) stripped.level = event.level;
64305
+ return stripped;
64306
+ }
64307
+ //#endregion
64308
+ //#region src/telemetry/events.ts
64309
+ const PRODUCT_EVENTS = /* @__PURE__ */ new Set([
64310
+ "caplets_cli_command",
64311
+ "caplets_tool_activation",
64312
+ "caplets_code_mode_outcome"
64313
+ ]);
64314
+ const RELIABILITY_EVENTS = /* @__PURE__ */ new Set(["caplets_reliability_error"]);
64315
+ function buildProductTelemetryEvent(input) {
64316
+ if (!PRODUCT_EVENTS.has(input.name)) throw new Error(`unknown telemetry event: ${input.name}`);
64317
+ assertTelemetrySafeProperties(input.properties);
64318
+ return {
64319
+ provider: "posthog",
64320
+ name: input.name,
64321
+ distinctId: input.distinctId,
64322
+ properties: {
64323
+ ...input.properties,
64324
+ $process_person_profile: false
64325
+ }
64326
+ };
64327
+ }
64328
+ function buildReliabilityTelemetryEvent(input) {
64329
+ if (!RELIABILITY_EVENTS.has(input.name)) throw new Error(`unknown telemetry event: ${input.name}`);
64330
+ assertTelemetrySafeProperties(input.properties);
64331
+ const tags = tagsFor(input.properties);
64332
+ return {
64333
+ provider: "sentry",
64334
+ name: input.name,
64335
+ tags,
64336
+ fingerprint: [
64337
+ tags.package ?? "unknown",
64338
+ tags.surface ?? "unknown",
64339
+ tags.command_family ?? "unknown",
64340
+ tags.runtime_mode ?? "unknown",
64341
+ tags.error_code ?? "unknown",
64342
+ tags.diagnostic_category ?? "unknown"
64343
+ ]
64344
+ };
64345
+ }
64346
+ function durationBucket(ms) {
64347
+ if (ms < 100) return "lt_100ms";
64348
+ if (ms < 1e3) return "lt_1s";
64349
+ if (ms < 5e3) return "lt_5s";
64350
+ if (ms < 3e4) return "lt_30s";
64351
+ return "gte_30s";
64352
+ }
64353
+ function timeoutBucket(ms) {
64354
+ if (ms === void 0) return "none";
64355
+ if (ms < 1e3) return "lt_1s";
64356
+ if (ms < 1e4) return "lt_10s";
64357
+ if (ms < 6e4) return "lt_60s";
64358
+ return "gte_60s";
64359
+ }
64360
+ function tagsFor(properties) {
64361
+ return Object.fromEntries(Object.entries(properties).map(([key, value]) => [key, String(value)]));
64362
+ }
64363
+ //#endregion
64364
+ //#region src/telemetry/debug.ts
64365
+ var TelemetryDebugSink = class {
64366
+ records = [];
64367
+ capture(state, event) {
64368
+ this.records.push({
64369
+ state,
64370
+ event
64371
+ });
64372
+ }
64373
+ toJSON() {
64374
+ return this.records;
64375
+ }
64376
+ };
64377
+ //#endregion
64378
+ //#region src/telemetry/providers.ts
64379
+ function createTelemetryDispatcher(options = {}) {
64380
+ let posthog;
64381
+ let sentry;
64382
+ async function posthogClient() {
64383
+ const token = options.posthogToken ?? process.env.CAPLETS_POSTHOG_TOKEN ?? "phc_pUZ2ZCRtFkC5qCGDNYcoYEhxxjTaooH57Cj4PTRXovyB";
64384
+ if (!token) return void 0;
64385
+ posthog ??= Promise.resolve((options.factories?.createPostHog ?? defaultPostHogFactory)(token));
64386
+ return posthog;
64387
+ }
64388
+ async function sentryClient() {
64389
+ const dsn = options.sentryDsn ?? process.env.CAPLETS_SENTRY_DSN ?? "https://c66cfd76aad69209bcf44be4cd79f9b5@o4508042228006912.ingest.us.sentry.io/4511620382392320";
64390
+ if (!dsn) return void 0;
64391
+ sentry ??= Promise.resolve((options.factories?.createSentry ?? defaultSentryFactory)(dsn));
64392
+ return sentry;
64393
+ }
64394
+ return {
64395
+ async capture(state, event) {
64396
+ if (state.status !== "enabled") return;
64397
+ try {
64398
+ if (event.provider === "posthog") {
64399
+ await capturePostHog(await posthogClient(), event, state.stateDir ?? options.stateDir);
64400
+ return;
64401
+ }
64402
+ await captureSentry(await sentryClient(), event, state.stateDir ?? options.stateDir);
64403
+ } catch {
64404
+ recordTelemetryDrop({
64405
+ stateDir: state.stateDir ?? options.stateDir,
64406
+ provider: event.provider,
64407
+ reason: "send_failed"
64408
+ });
64409
+ }
64410
+ },
64411
+ async shutdown() {
64412
+ const clients = await Promise.allSettled([posthog, sentry]);
64413
+ for (const client of clients) {
64414
+ if (client.status !== "fulfilled" || !client.value) continue;
64415
+ if ("shutdown" in client.value) await Promise.resolve(client.value.shutdown()).catch(() => void 0);
64416
+ if ("flush" in client.value) await Promise.resolve(client.value.flush(2e3)).catch(() => void 0);
64417
+ }
64418
+ }
64419
+ };
64420
+ }
64421
+ async function capturePostHog(client, event, stateDir) {
64422
+ if (!client) {
64423
+ recordTelemetryDrop({
64424
+ stateDir,
64425
+ provider: "posthog",
64426
+ reason: "not_configured"
64427
+ });
64428
+ return;
64429
+ }
64430
+ client.capture({
64431
+ distinctId: event.distinctId,
64432
+ event: event.name,
64433
+ properties: {
64434
+ ...event.properties,
64435
+ $geoip_disable: true
64436
+ }
64437
+ });
64438
+ }
64439
+ async function captureSentry(client, event, stateDir) {
64440
+ if (!client) {
64441
+ recordTelemetryDrop({
64442
+ stateDir,
64443
+ provider: "sentry",
64444
+ reason: "not_configured"
64445
+ });
64446
+ return;
64447
+ }
64448
+ client.captureEvent({
64449
+ level: "error",
64450
+ tags: event.tags,
64451
+ fingerprint: event.fingerprint
64452
+ });
64453
+ }
64454
+ async function defaultPostHogFactory(token) {
64455
+ const { PostHog } = await import("./node-BgWIvSVP.js");
64456
+ return new PostHog(token, {
64457
+ flushAt: 20,
64458
+ flushInterval: 1e4,
64459
+ disableGeoip: true,
64460
+ historicalMigration: false
64461
+ });
64462
+ }
64463
+ async function defaultSentryFactory(dsn) {
64464
+ const sentry = await import("./esm-Db9dhnIG.js");
64465
+ const options = {
64466
+ dsn,
64467
+ sendDefaultPii: false,
64468
+ defaultIntegrations: false,
64469
+ integrations: [],
64470
+ tracesSampleRate: 0,
64471
+ transport: sentry.makeNodeTransport,
64472
+ stackParser: sentry.defaultStackParser,
64473
+ beforeSend(event) {
64474
+ return stripSentryEvent(event);
64475
+ }
64476
+ };
64477
+ return new sentry.NodeClient(options);
64478
+ }
64479
+ //#endregion
64480
+ //#region package.json
64481
+ var version = "0.28.0";
64482
+ //#endregion
64483
+ //#region src/telemetry/runtime.ts
64484
+ function createRuntimeTelemetryContext(options) {
64485
+ return {
64486
+ ...options,
64487
+ dispatcher: options.dispatcher ?? createTelemetryDispatcher({ stateDir: options.stateDir })
64488
+ };
64489
+ }
64490
+ async function captureRuntimeTelemetryEvent(context, name, properties) {
64491
+ const state = resolveTelemetryState({
64492
+ config: context.config,
64493
+ env: context.env,
64494
+ stateDir: context.stateDir,
64495
+ surface: context.surface,
64496
+ visibility: context.visibility,
64497
+ debug: context.debugSink !== void 0
64498
+ });
64499
+ if (state.status !== "enabled" && state.status !== "debug") return;
64500
+ const event = buildProductTelemetryEvent({
64501
+ name,
64502
+ distinctId: (state.identity ?? readTelemetryIdentity({
64503
+ stateDir: context.stateDir,
64504
+ create: false
64505
+ })).id,
64506
+ properties: {
64507
+ package: "@caplets/core",
64508
+ version,
64509
+ surface: context.surface,
64510
+ runtime_mode: context.runtimeMode ?? "unknown",
64511
+ execution_context: state.executionContext,
64512
+ ...context.integration ? { integration: context.integration } : {},
64513
+ ...properties
64514
+ }
64515
+ });
64516
+ if (state.status === "debug") {
64517
+ context.debugSink?.capture("debug", event);
64518
+ return;
64519
+ }
64520
+ await context.dispatcher.capture(state, event);
64521
+ }
64522
+ async function captureRuntimeReliabilityEvent(context, properties) {
64523
+ const state = resolveTelemetryState({
64524
+ config: context.config,
64525
+ env: context.env,
64526
+ stateDir: context.stateDir,
64527
+ surface: context.surface,
64528
+ visibility: context.visibility,
64529
+ debug: context.debugSink !== void 0
64530
+ });
64531
+ if (state.status !== "enabled" && state.status !== "debug") return;
64532
+ const event = buildReliabilityTelemetryEvent({
64533
+ name: "caplets_reliability_error",
64534
+ properties: {
64535
+ package: "@caplets/core",
64536
+ version,
64537
+ surface: context.surface,
64538
+ runtime_mode: context.runtimeMode ?? "unknown",
64539
+ execution_context: state.executionContext,
64540
+ ...context.integration ? { integration: context.integration } : {},
64541
+ os_family: platform(),
64542
+ arch: arch(),
64543
+ node_major: Number(process.versions.node.split(".")[0] ?? 0),
64544
+ ...properties
64545
+ }
64546
+ });
64547
+ if (state.status === "debug") {
64548
+ context.debugSink?.capture("debug", event);
64549
+ return;
64550
+ }
64551
+ await context.dispatcher.capture(state, event);
64552
+ }
64553
+ function backendFamilyCounts(config) {
64554
+ return {
64555
+ backend_mcp_count: enabledCount(config.mcpServers),
64556
+ backend_openapi_count: enabledCount(config.openapiEndpoints),
64557
+ backend_google_discovery_count: enabledCount(config.googleDiscoveryApis),
64558
+ backend_graphql_count: enabledCount(config.graphqlEndpoints),
64559
+ backend_http_count: enabledCount(config.httpApis),
64560
+ backend_cli_count: enabledCount(config.cliTools),
64561
+ backend_caplets_count: enabledCount(config.capletSets)
64562
+ };
64563
+ }
64564
+ function exposureModeCounts(config) {
64565
+ let direct = 0;
64566
+ let progressive = 0;
64567
+ let codeMode = 0;
64568
+ for (const caplet of allCaplets$1(config)) {
64569
+ if (caplet.disabled || caplet.setup || caplet.projectBinding?.required) continue;
64570
+ const exposure = resolveExposure(caplet.exposure, config.options.exposure);
64571
+ if (exposure.direct) direct += 1;
64572
+ if (exposure.progressive) progressive += 1;
64573
+ if (exposure.codeMode) codeMode += 1;
64574
+ }
64575
+ return {
64576
+ direct_count: direct,
64577
+ progressive_count: progressive,
64578
+ code_mode_count: codeMode
64579
+ };
64580
+ }
64581
+ function operationFamilyFromOperation(operation) {
64582
+ if (operation === "inspect") return "inspect";
64583
+ if (operation === "check") return "check";
64584
+ if (operation === "tools" || operation === "search_tools" || operation === "get_tool" || operation === "describe_tool" || operation === "call_tool") return "tools";
64585
+ if (operation === "resources" || operation === "resource_templates" || operation === "read_resource" || operation === "search_resources" || operation === "list_resources" || operation === "list_resource_templates" || operation === "search_resource_templates") return "resources";
64586
+ if (operation === "prompts" || operation === "get_prompt" || operation === "list_prompts" || operation === "search_prompts") return "prompts";
64587
+ if (operation === "complete") return "complete";
64588
+ if (operation === "code_mode") return "code_mode";
64589
+ return "unknown";
64590
+ }
64591
+ function outcomeFromResult(result) {
64592
+ if (isRecord$6(result) && result.isError === true) {
64593
+ if (errorCodeFromResult$1(result).toLowerCase().includes("timeout")) return "timeout";
64594
+ return "failure";
64595
+ }
64596
+ if (isRecord$6(result) && result.ok === false) {
64597
+ const code = errorCodeFromResult$1(result);
64598
+ if (typeof code === "string" && code.toLowerCase().includes("timeout")) return "timeout";
64599
+ return "failure";
64600
+ }
64601
+ return "success";
64602
+ }
64603
+ function codeModeTelemetryProperties(envelope, durationMs, timeoutMs) {
64604
+ const record = isRecord$6(envelope) ? envelope : {};
64605
+ const meta = isRecord$6(record.meta) ? record.meta : {};
64606
+ const sessionStatus = meta.sessionStatus;
64607
+ const effectiveTimeoutMs = timeoutMs ?? (typeof meta.timeoutMs === "number" ? meta.timeoutMs : void 0);
64608
+ return {
64609
+ command_family: "code_mode",
64610
+ outcome: outcomeFromResult(record),
64611
+ duration_bucket: durationBucket(durationMs),
64612
+ timeout_bucket: timeoutBucket(effectiveTimeoutMs),
64613
+ session_category: sessionStatus === "created" || sessionStatus === "reused" ? sessionStatus : sessionStatus === null ? "none" : "unknown",
64614
+ any_caplet_invoked: codeModeEnvelopeInvokedCaplet(record)
64615
+ };
64616
+ }
64617
+ function toolActivationProperties(input) {
64618
+ return {
64619
+ operation_family: operationFamilyFromOperation(input.operation),
64620
+ exposure_mode: input.exposureMode,
64621
+ outcome: outcomeFromResult(input.result),
64622
+ duration_bucket: durationBucket(input.durationMs),
64623
+ ...backendFamilyCounts(input.config),
64624
+ ...exposureModeCounts(input.config)
64625
+ };
64626
+ }
64627
+ function enabledCount(record) {
64628
+ return Object.values(record).filter((caplet) => !caplet.disabled).length;
64629
+ }
64630
+ function allCaplets$1(config) {
64631
+ return [
64632
+ ...Object.values(config.mcpServers),
64633
+ ...Object.values(config.openapiEndpoints),
64634
+ ...Object.values(config.googleDiscoveryApis),
64635
+ ...Object.values(config.graphqlEndpoints),
64636
+ ...Object.values(config.httpApis),
64637
+ ...Object.values(config.cliTools),
64638
+ ...Object.values(config.capletSets)
64639
+ ];
64640
+ }
64641
+ function isRecord$6(value) {
64642
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
64643
+ }
64644
+ function runtimeFailureTelemetryProperties(input) {
64645
+ const errorCode = errorCodeFromResult$1(input.result);
64646
+ return {
64647
+ operation_family: operationFamilyFromOperation(input.operation),
64648
+ exposure_mode: input.exposureMode,
64649
+ error_code: errorCode,
64650
+ diagnostic_category: diagnosticCategoryFromCode(errorCode)
64651
+ };
64652
+ }
64653
+ function errorCodeFromResult$1(result) {
64654
+ if (!isRecord$6(result)) return "UNKNOWN";
64655
+ const error = isRecord$6(result.error) ? result.error : isRecord$6(result.structuredContent) && isRecord$6(result.structuredContent.error) ? result.structuredContent.error : void 0;
64656
+ if (isRecord$6(error) && typeof error.code === "string") return error.code;
64657
+ return "UNKNOWN";
64658
+ }
64659
+ function diagnosticCategoryFromCode(code) {
64660
+ if (code.startsWith("CONFIG")) return "config";
64661
+ if (code.startsWith("AUTH")) return "auth";
64662
+ if (code.includes("NETWORK") || code.includes("UNAVAILABLE")) return "network";
64663
+ if (code.includes("VALID") || code.includes("REQUEST")) return "validation";
64664
+ if (code.includes("CODE_MODE") || code.includes("SANDBOX")) return "code_mode";
64665
+ return "runtime";
64666
+ }
64667
+ function codeModeEnvelopeInvokedCaplet(record) {
64668
+ const meta = isRecord$6(record.meta) ? record.meta : void 0;
64669
+ return hasBooleanTrue(meta, "anyCapletInvoked") || hasBooleanTrue(meta, "capletInvoked") || hasPositiveNumber(meta, "capletInvocationCount") || hasPositiveNumber(meta, "toolCallCount");
64670
+ }
64671
+ function hasBooleanTrue(record, key) {
64672
+ return record?.[key] === true;
64673
+ }
64674
+ function hasPositiveNumber(record, key) {
64675
+ const value = record?.[key];
64676
+ return typeof value === "number" && value > 0;
64677
+ }
64678
+ //#endregion
63895
64679
  //#region src/engine.ts
63896
64680
  var CapletsEngine = class {
63897
64681
  registry;
@@ -63910,6 +64694,8 @@ var CapletsEngine = class {
63910
64694
  observedOutputShapeStore;
63911
64695
  observedOutputShapeScope;
63912
64696
  projectFingerprint;
64697
+ telemetry;
64698
+ telemetryExecuteExposureMode;
63913
64699
  reloadListeners = /* @__PURE__ */ new Set();
63914
64700
  lastExposureSnapshot;
63915
64701
  watchers = [];
@@ -63927,6 +64713,18 @@ var CapletsEngine = class {
63927
64713
  this.configLoader = options.configLoader ?? runtimeConfigLoader(options.authDir, options.vaultRecoveryTarget);
63928
64714
  const config = this.loadConfigWithWarnings();
63929
64715
  this.registry = new ServerRegistry(config);
64716
+ this.telemetry = createRuntimeTelemetryContext({
64717
+ config: this.registry.config,
64718
+ env: options.telemetryEnv,
64719
+ stateDir: options.telemetryStateDir,
64720
+ surface: options.telemetrySurface ?? "serve",
64721
+ visibility: options.telemetryVisibility ?? "unknown",
64722
+ runtimeMode: options.telemetryRuntimeMode ?? runtimeModeFromEnv(options.telemetryEnv),
64723
+ integration: options.telemetryIntegration,
64724
+ debugSink: options.telemetryDebugSink,
64725
+ dispatcher: options.telemetryDispatcher
64726
+ });
64727
+ this.telemetryExecuteExposureMode = options.telemetrySurface === "code_mode" ? "code_mode" : "progressive";
63930
64728
  this.downstream = new DownstreamManager(this.registry, selectAuthOptions(options.authDir));
63931
64729
  this.openapi = new OpenApiManager(this.registry, selectHttpLikeOptions(options));
63932
64730
  this.googleDiscovery = new GoogleDiscoveryManager(this.registry, selectHttpLikeOptions(options));
@@ -63991,44 +64789,73 @@ var CapletsEngine = class {
63991
64789
  return await this.reloading;
63992
64790
  }
63993
64791
  async execute(serverId, request) {
64792
+ const started = Date.now();
64793
+ let caplet;
63994
64794
  try {
63995
- return await handleServerTool(this.registry.require(serverId), request, this.registry, this.downstream, this.openapi, this.graphql, this.http, this.cli, this.capletSets, {
64795
+ caplet = this.registry.require(serverId);
64796
+ const result = await handleServerTool(caplet, request, this.registry, this.downstream, this.openapi, this.graphql, this.http, this.cli, this.capletSets, {
63996
64797
  observedOutputShapeStore: this.observedOutputShapeStore,
63997
64798
  observedOutputShapeScope: this.observedOutputShapeScope,
63998
64799
  projectFingerprint: this.projectFingerprint
63999
64800
  }, this.googleDiscovery);
64801
+ this.captureToolActivation(caplet, operationFromRequest(request), this.telemetryExecuteExposureMode, result, started);
64802
+ return result;
64000
64803
  } catch (error) {
64001
- return errorResult(error);
64804
+ const result = errorResult(error);
64805
+ this.captureReliabilityError(operationFromRequest(request), this.telemetryExecuteExposureMode, result);
64806
+ this.captureToolActivation(caplet, operationFromRequest(request), this.telemetryExecuteExposureMode, result, started);
64807
+ return result;
64002
64808
  }
64003
64809
  }
64004
64810
  async executeDirectTool(serverId, toolName, args) {
64811
+ const started = Date.now();
64812
+ let caplet;
64005
64813
  try {
64006
- const caplet = this.registry.require(serverId);
64007
- return annotateDirectResult(await this.callTool(caplet, toolName, args), caplet, toolName);
64814
+ caplet = this.registry.require(serverId);
64815
+ const annotated = annotateDirectResult(await this.callTool(caplet, toolName, args), caplet, toolName);
64816
+ this.captureToolActivation(caplet, "call_tool", "direct", annotated, started);
64817
+ return annotated;
64008
64818
  } catch (error) {
64009
- return errorResult(error);
64819
+ const result = errorResult(error);
64820
+ this.captureReliabilityError("call_tool", "direct", result);
64821
+ this.captureToolActivation(caplet, "call_tool", "direct", result, started);
64822
+ return result;
64010
64823
  }
64011
64824
  }
64012
64825
  async readDirectResource(serverId, downstreamUri) {
64826
+ const started = Date.now();
64827
+ let caplet;
64013
64828
  try {
64014
- const caplet = this.registry.require(serverId);
64829
+ caplet = this.registry.require(serverId);
64015
64830
  if (caplet.backend !== "mcp") throw new Error(`Caplet ${serverId} has no MCP resources`);
64016
- return annotateDirectResult(await this.downstream.readResource(caplet, downstreamUri), caplet, "read_resource");
64831
+ const annotated = annotateDirectResult(await this.downstream.readResource(caplet, downstreamUri), caplet, "read_resource");
64832
+ this.captureToolActivation(caplet, "read_resource", "direct", annotated, started);
64833
+ return annotated;
64017
64834
  } catch (error) {
64018
- return errorResult(error);
64835
+ const result = errorResult(error);
64836
+ this.captureReliabilityError("read_resource", "direct", result);
64837
+ this.captureToolActivation(caplet, "read_resource", "direct", result, started);
64838
+ return result;
64019
64839
  }
64020
64840
  }
64021
64841
  async getDirectPrompt(serverId, promptName, args) {
64842
+ const started = Date.now();
64843
+ let caplet;
64022
64844
  try {
64023
- const caplet = this.registry.require(serverId);
64845
+ caplet = this.registry.require(serverId);
64024
64846
  if (caplet.backend !== "mcp") throw new Error(`Caplet ${serverId} has no MCP prompts`);
64025
- return annotateDirectResult(await this.downstream.getPrompt(caplet, promptName, args), caplet, promptName);
64847
+ const annotated = annotateDirectResult(await this.downstream.getPrompt(caplet, promptName, args), caplet, promptName);
64848
+ this.captureToolActivation(caplet, "get_prompt", "direct", annotated, started);
64849
+ return annotated;
64026
64850
  } catch (error) {
64027
- return errorResult(error);
64851
+ const result = errorResult(error);
64852
+ this.captureReliabilityError("get_prompt", "direct", result);
64853
+ this.captureToolActivation(caplet, "get_prompt", "direct", result, started);
64854
+ return result;
64028
64855
  }
64029
64856
  }
64030
64857
  async completeCliWords(words) {
64031
- const { completeCliWords } = await import("./completion-CFOJucl5.js").then((n) => n.r);
64858
+ const { completeCliWords } = await import("./completion-CjE0EnbF.js").then((n) => n.r);
64032
64859
  return await completeCliWords(words, {
64033
64860
  config: this.registry.config,
64034
64861
  managers: {
@@ -64059,6 +64886,9 @@ var CapletsEngine = class {
64059
64886
  }
64060
64887
  });
64061
64888
  }
64889
+ async captureCodeModeOutcome(envelope, options) {
64890
+ await captureRuntimeTelemetryEvent(this.telemetry, "caplets_code_mode_outcome", codeModeTelemetryProperties(envelope, Date.now() - options.started, options.timeoutMs));
64891
+ }
64062
64892
  async close() {
64063
64893
  this.closed = true;
64064
64894
  try {
@@ -64075,6 +64905,7 @@ var CapletsEngine = class {
64075
64905
  this.closeWatchers();
64076
64906
  await this.downstream.close();
64077
64907
  await this.capletSets.close();
64908
+ await this.telemetry.dispatcher.shutdown();
64078
64909
  this.reloadListeners.clear();
64079
64910
  }
64080
64911
  }
@@ -64112,6 +64943,7 @@ var CapletsEngine = class {
64112
64943
  const previousConfig = this.registry.config;
64113
64944
  const nextRegistry = new ServerRegistry(nextConfig);
64114
64945
  this.registry = nextRegistry;
64946
+ this.telemetry.config = nextConfig;
64115
64947
  this.downstream.updateRegistry(nextRegistry);
64116
64948
  this.openapi.updateRegistry(nextRegistry);
64117
64949
  this.googleDiscovery.updateRegistry(nextRegistry);
@@ -64229,6 +65061,29 @@ var CapletsEngine = class {
64229
65061
  if (!this.closed) this.resetWatchers();
64230
65062
  }, this.watchDebounceMs);
64231
65063
  }
65064
+ captureReliabilityError(operation, exposureMode, result) {
65065
+ captureRuntimeReliabilityEvent(this.telemetry, {
65066
+ command_family: commandFamilyForTelemetrySurface(this.telemetry.surface),
65067
+ ...runtimeFailureTelemetryProperties({
65068
+ operation,
65069
+ exposureMode,
65070
+ result
65071
+ })
65072
+ }).catch(() => void 0);
65073
+ }
65074
+ captureToolActivation(caplet, operation, exposureMode, result, started) {
65075
+ captureRuntimeTelemetryEvent(this.telemetry, "caplets_tool_activation", {
65076
+ command_family: commandFamilyForTelemetrySurface(this.telemetry.surface),
65077
+ ...toolActivationProperties({
65078
+ config: this.registry.config,
65079
+ caplet,
65080
+ operation,
65081
+ exposureMode,
65082
+ result,
65083
+ durationMs: Date.now() - started
65084
+ })
65085
+ }).catch(() => void 0);
65086
+ }
64232
65087
  };
64233
65088
  function runtimeConfigLoader(authDir, vaultRecoveryTarget) {
64234
65089
  const vaultResolver = vaultResolverForAuthDir(authDir);
@@ -64331,7 +65186,7 @@ function annotateDirectResult(result, caplet, operation) {
64331
65186
  return {
64332
65187
  ...result,
64333
65188
  _meta: {
64334
- ...isRecord$4(existingMeta) ? existingMeta : {},
65189
+ ...isRecord$5(existingMeta) ? existingMeta : {},
64335
65190
  caplets: {
64336
65191
  capletId: caplet.server,
64337
65192
  backend: caplet.backend,
@@ -64344,9 +65199,25 @@ function annotateDirectResult(result, caplet, operation) {
64344
65199
  function isUnsupportedCapability(error) {
64345
65200
  return error instanceof CapletsError && error.code === "UNSUPPORTED_CAPABILITY";
64346
65201
  }
64347
- function isRecord$4(value) {
65202
+ function isRecord$5(value) {
64348
65203
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
64349
65204
  }
65205
+ function operationFromRequest(request) {
65206
+ return isRecord$5(request) ? request.operation : void 0;
65207
+ }
65208
+ function runtimeModeFromEnv(env) {
65209
+ const mode = env?.CAPLETS_MODE ?? process.env.CAPLETS_MODE;
65210
+ if (mode === "local" || mode === "remote" || mode === "cloud") return mode;
65211
+ return "unknown";
65212
+ }
65213
+ function commandFamilyForTelemetrySurface(surface) {
65214
+ if (surface === "serve") return "serve";
65215
+ if (surface === "attach") return "attach";
65216
+ if (surface === "daemon") return "daemon";
65217
+ if (surface === "code_mode") return "code_mode";
65218
+ if (surface === "native") return "native";
65219
+ return "tools";
65220
+ }
64350
65221
  //#endregion
64351
65222
  //#region src/code-mode/runtime-api.generated.ts
64352
65223
  const CODE_MODE_RUNTIME_API_DECLARATION = "type JsonPrimitive=string|number|boolean|null;type JsonValue=JsonPrimitive|JsonValue[]|{[key:string]:JsonValue};interface CapletHandle<Id extends string>{readonly id:Id;/** Show this Caplet card,without tool/resource/prompt schemas. */ inspect():Promise<CapletCard<Id>>;/** Check backend readiness/auth;expected unavailable states return ok:false. */ check():Promise<CapletsResult<BackendCheckResult>>;/** List tool summaries for the discovery pass;may be empty. */ tools(input?:PageInput):Promise<Page<ToolSummary>>;/** Search tool summaries for the discovery pass;may be empty. */ searchTools(query:string,input?:PageInput):Promise<Page<ToolSummary>>;/** Get schema,callSignature,types,examples;prefer outputSchema/outputTypeScript over observed hints. */ describeTool(name:string):Promise<CapletsResult<ToolDescriptor>>;/** Call one tool;expected failures return ok:false. Filter bulky data in script before returning. */ callTool(name:string,args?:unknown):Promise<CapletsResult<unknown>>;/** List readable resources for the discovery pass;many backends expose none. */ resources(input?:PageInput):Promise<Page<ResourceSummary>>;/** Search readable resources for the discovery pass;many backends expose none. */ searchResources(query:string,input?:PageInput):Promise<Page<ResourceSummary>>;/** List resource templates for the discovery pass;many backends expose none. */ resourceTemplates(input?:PageInput):Promise<Page<ResourceTemplateSummary>>;/** Read one resource by URI;unsupported/missing resources return ok:false. */ readResource(uri:string):Promise<CapletsResult<ResourceReadResult>>;/** List reusable prompts for the discovery pass;many backends expose none. */ prompts(input?:PageInput):Promise<Page<PromptSummary>>;/** Search reusable prompts for the discovery pass;many backends expose none. */ searchPrompts(query:string,input?:PageInput):Promise<Page<PromptSummary>>;/** Get one prompt by name and args;unsupported/missing prompts return ok:false. */ getPrompt(name:string,args?:unknown):Promise<CapletsResult<PromptResult>>;/** Complete a prompt or resource-template argument. */ complete(input:CompleteInput):Promise<CapletsResult<CompleteResult>>;}interface DebugApi{readLogs(input:ReadLogsInput):Promise<ReadLogsResult>;readRecovery(input:ReadCodeModeRecoveryInput):Promise<ReadCodeModeRecoveryResult>;}type CapletCard<Id extends string>={id:Id;name:string;description:string;useWhen?:string;avoidWhen?:string;tags?:string[];backend?:unknown;};type PageInput={limit?:number;cursor?:string};type Page<T>={items:T[];nextCursor?:string;truncated?:boolean};type CapletsResult<T>=|{ok:true;data:T;meta?:CapletsMeta}|{ok:false;error:CapletsError;meta?:CapletsMeta};type CapletsMeta={[key:string]:unknown};type CapletsError={code:string;message:string;details?:unknown};type BackendCheckResult=unknown;type ToolSummary={/** Exact downstream tool identifier for describeTool(name)and callTool(name,args). */ name:string;title?:string;description?:string;/** Optional author-supplied hint for when to prefer this tool. */ useWhen?:string;/** Optional author-supplied hint for when to avoid this tool. */ avoidWhen?:string;/** True when the tool declares that it only reads data. */ readOnlyHint?:boolean;/** True when the tool declares that it may perform destructive writes. */ destructiveHint?:boolean;};type ToolDescriptor={id?:string;tool?:unknown;inputSchema?:unknown;outputSchema?:unknown;callSignature?:string;inputTypeScript?:string;outputTypeScript?:string;observedOutputShape?:ObservedOutputShape;examples?:unknown[];};type ObservedOutputShape={version:1;source:\"observed\";observedAt:string;sampleCount:number;typeScript:string;jsonShape:JsonShape;truncated:boolean;};type JsonShape=|{kind:\"null\"}|{kind:\"boolean\"}|{kind:\"number\"}|{kind:\"string\"}|{kind:\"unknown\"}|{kind:\"array\";element?:JsonShape;truncated?:boolean}|{kind:\"object\";fields:Record<string,{optional:boolean;shape:JsonShape}>;truncated?:boolean;}|{kind:\"union\";variants:JsonShape[]};type ResourceSummary={uri?:string;name?:string;title?:string;description?:string};type ResourceTemplateSummary={uriTemplate?:string;name?:string;title?:string;description?:string;};type ResourceReadResult=unknown;type PromptSummary={name?:string;title?:string;description?:string};type PromptResult=unknown;type CompleteInput={ref:{type:\"prompt\";name:string}|{type:\"resourceTemplate\";uri:string};argument:{name:string;value:string};};type CompleteResult=unknown;type ReadLogsInput={logRef:string;cursor?:string;limit?:number};type ReadLogsResult={entries:CodeModeLogEntry[];nextCursor?:string};type ReadCodeModeRecoveryInput={recoveryRef:string;cursor?:string;limit?:number};type CodeModeDiagnostic={code:string;message:string;severity:\"error\"|\"warning\"|\"info\";line?:number;column?:number;};type CodeModeRecoveryClassification=\"setup_like\"|\"side_effecting\"|\"unknown\";type CodeModeRecoveryEntry={timestamp:string;code:string;declarationHash:string;outcome:{ok:true}|{ok:false;code:string;message:string};diagnostics:Array<Pick<CodeModeDiagnostic,\"code\"|\"severity\"|\"message\">>;recoveryClassification:CodeModeRecoveryClassification;logsStored?:boolean;summary?:string;};type ReadCodeModeRecoveryResult={entries:CodeModeRecoveryEntry[];nextCursor?:string};type CodeModeLogEntry={level:\"log\"|\"info\"|\"warn\"|\"error\"|\"debug\";message:string;timestamp:string;};type CodeModeSessionStatus=\"created\"|\"reused\";type CodeModeRunMeta={runId:string;traceId:string;declarationHash:string;durationMs:number;timeoutMs:number;maxTimeoutMs:number;sessionId?:string|null;sessionStatus?:CodeModeSessionStatus|null;recoveryRef?:string|null;};interface Console{log(...values:unknown[]):void;info(...values:unknown[]):void;warn(...values:unknown[]):void;error(...values:unknown[]):void;debug(...values:unknown[]):void;}declare const console:Console;";
@@ -79871,9 +80742,11 @@ async function runCodeMode(input) {
79871
80742
  const callable = listCodeModeCallableCaplets(input.service);
79872
80743
  const declaration = generateCodeModeDeclarations({ caplets: callable });
79873
80744
  const declarationHash = codeModeDeclarationHash(declaration);
80745
+ const platformRuntimeHash = codeModeDeclarationHash(CODE_MODE_PLATFORM_RUNTIME_SOURCE);
80746
+ let invokedCaplet = false;
79874
80747
  const sessionCompatibility = {
79875
80748
  declarationHash,
79876
- platformRuntimeHash: codeModeDeclarationHash(CODE_MODE_PLATFORM_RUNTIME_SOURCE),
80749
+ platformRuntimeHash,
79877
80750
  runtimeScope: input.runtimeScope ?? "",
79878
80751
  version: 1
79879
80752
  };
@@ -79890,7 +80763,8 @@ async function runCodeMode(input) {
79890
80763
  };
79891
80764
  const meta = () => ({
79892
80765
  ...metaBase,
79893
- durationMs: Date.now() - startedAt
80766
+ durationMs: Date.now() - startedAt,
80767
+ anyCapletInvoked: invokedCaplet
79894
80768
  });
79895
80769
  if (input.sessionId !== void 0 && !input.sessionManager) return {
79896
80770
  ok: false,
@@ -79977,7 +80851,6 @@ async function runCodeMode(input) {
79977
80851
  };
79978
80852
  }
79979
80853
  const capturedLogs = [];
79980
- let invokedCaplet = false;
79981
80854
  const api = createCodeModeCapletsApi({
79982
80855
  service: input.service,
79983
80856
  readLogs: async (readInput) => input.logStore?.read(readInput) ?? { entries: [] },
@@ -80283,6 +81156,7 @@ function emptyCodeModeRunMeta() {
80283
81156
  durationMs: 0,
80284
81157
  timeoutMs: 0,
80285
81158
  maxTimeoutMs: 0,
81159
+ anyCapletInvoked: false,
80286
81160
  sessionId: null,
80287
81161
  sessionStatus: null,
80288
81162
  recoveryRef: null
@@ -80542,18 +81416,28 @@ function resolveNativeCapletsServiceOptions(input = {}, env = process.env) {
80542
81416
  ...remoteFetch ? { fetch: remoteFetch } : {}
80543
81417
  }, env);
80544
81418
  const cloud = resolveNativeCloudPresence(input.remote?.cloud, env);
81419
+ const requestInit = mode.mode === "cloud" && cloud ? { headers: { Authorization: `Bearer ${cloud.accessToken}` } } : server.requestInit;
80545
81420
  return {
80546
81421
  mode: mode.mode,
80547
81422
  remote: {
80548
81423
  url: server.attachUrl,
80549
81424
  auth: nativeAuthFromRemoteAuth$1(server.auth),
80550
81425
  pollIntervalMs: parsePollInterval(input.remote?.pollIntervalMs),
80551
- requestInit: mode.mode === "cloud" && cloud ? { headers: { Authorization: `Bearer ${cloud.accessToken}` } } : server.requestInit,
81426
+ requestInit: withRequestHeaders(requestInit, input.remote?.requestHeaders),
80552
81427
  ...cloud ? { cloud } : {},
80553
81428
  ...server.fetch ? { fetch: server.fetch } : {}
80554
81429
  }
80555
81430
  };
80556
81431
  }
81432
+ function withRequestHeaders(requestInit, requestHeaders) {
81433
+ if (!requestHeaders) return requestInit;
81434
+ const headers = new Headers(requestInit.headers);
81435
+ for (const [name, value] of Object.entries(requestHeaders)) headers.set(name, value);
81436
+ return {
81437
+ ...requestInit,
81438
+ headers
81439
+ };
81440
+ }
80557
81441
  function resolveNativeHostedCloudRemote(url, workspace, fetch) {
80558
81442
  return resolveHostedCloudRemote({
80559
81443
  url,
@@ -80968,7 +81852,382 @@ function projectSyncFiles(projectRoot) {
80968
81852
  }));
80969
81853
  }
80970
81854
  //#endregion
81855
+ //#region src/attach/api.ts
81856
+ const CAPLETS_ATTACH_SESSION_HEADER = "caplets-attach-session-id";
81857
+ async function buildAttachProjection(engine) {
81858
+ const snapshot = await engine.exposureSnapshot();
81859
+ const partial = sortAttachProjectionInput({
81860
+ caplets: snapshot.progressiveCaplets.map(progressiveCapletExport),
81861
+ tools: snapshot.directTools.map(toolExport),
81862
+ resources: snapshot.directResources.map(resourceExport),
81863
+ resourceTemplates: snapshot.directResourceTemplates.map(resourceTemplateExport),
81864
+ prompts: snapshot.directPrompts.map(promptExport),
81865
+ completions: completionExports(snapshot),
81866
+ codeModeCaplets: snapshot.codeModeCaplets.map(codeModeCapletExport),
81867
+ diagnostics: snapshot.hiddenCaplets.map((hidden) => ({
81868
+ code: `ATTACH_CAPLET_${hidden.reason.toUpperCase()}`,
81869
+ message: `Caplet ${hidden.capletId} is not exported: ${hidden.reason}.`,
81870
+ capletId: hidden.capletId,
81871
+ ...hidden.error ? { details: hidden.error } : {}
81872
+ }))
81873
+ });
81874
+ const revision = revisionFor(partial);
81875
+ const manifest = {
81876
+ version: 1,
81877
+ revision,
81878
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
81879
+ ...withRevisionExportIds(revision, partial)
81880
+ };
81881
+ return {
81882
+ manifest,
81883
+ routes: routesFor(manifest)
81884
+ };
81885
+ }
81886
+ async function buildNativeAttachProjection(service) {
81887
+ const tools = service.listTools();
81888
+ const partial = sortAttachProjectionInput({
81889
+ caplets: nativeProgressiveCaplets(tools),
81890
+ tools: nativeDirectTools(tools),
81891
+ resources: [],
81892
+ resourceTemplates: [],
81893
+ prompts: [],
81894
+ completions: [],
81895
+ codeModeCaplets: nativeCodeModeCaplets(tools),
81896
+ diagnostics: []
81897
+ });
81898
+ const revision = revisionFor(partial);
81899
+ const manifest = {
81900
+ version: 1,
81901
+ revision,
81902
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
81903
+ ...withRevisionExportIds(revision, partial)
81904
+ };
81905
+ return {
81906
+ manifest,
81907
+ routes: routesFor(manifest)
81908
+ };
81909
+ }
81910
+ function nativeProgressiveCaplets(tools) {
81911
+ return tools.filter((tool) => tool.codeModeRun !== true && !nativeDirectToolOperation(tool)).map((tool) => ({
81912
+ stableId: `native:${tool.caplet}`,
81913
+ kind: "caplet",
81914
+ name: tool.caplet,
81915
+ title: tool.title,
81916
+ description: tool.description,
81917
+ inputSchema: tool.inputSchema,
81918
+ outputSchema: tool.outputSchema,
81919
+ annotations: tool.annotations,
81920
+ schemaHash: schemaHash(tool.inputSchema ?? null),
81921
+ capletId: tool.caplet,
81922
+ shadowing: tool.shadowing ?? "forbid"
81923
+ }));
81924
+ }
81925
+ function nativeDirectTools(tools) {
81926
+ return tools.flatMap((tool) => {
81927
+ const operation = nativeDirectToolOperation(tool);
81928
+ if (!operation || tool.codeModeRun === true || !tool.sourceCaplet) return [];
81929
+ return [{
81930
+ stableId: `native-tool:${tool.caplet}`,
81931
+ kind: "tool",
81932
+ name: tool.caplet,
81933
+ downstreamName: operation,
81934
+ title: tool.title,
81935
+ description: tool.description,
81936
+ inputSchema: tool.inputSchema,
81937
+ outputSchema: tool.outputSchema,
81938
+ annotations: tool.annotations,
81939
+ schemaHash: schemaHash({
81940
+ input: tool.inputSchema,
81941
+ output: tool.outputSchema
81942
+ }),
81943
+ capletId: tool.sourceCaplet,
81944
+ shadowing: tool.shadowing ?? "forbid"
81945
+ }];
81946
+ });
81947
+ }
81948
+ function nativeDirectToolOperation(tool) {
81949
+ if (!tool.sourceCaplet || !tool.caplet.startsWith(`${tool.sourceCaplet}__`)) return;
81950
+ return tool.caplet.slice(tool.sourceCaplet.length + 2);
81951
+ }
81952
+ function nativeCodeModeCaplets(tools) {
81953
+ return tools.flatMap((tool) => (tool.codeModeCaplets ?? []).map((caplet) => ({
81954
+ stableId: `native-code-mode:${caplet.id}`,
81955
+ kind: "caplet",
81956
+ name: caplet.name,
81957
+ title: caplet.name,
81958
+ description: caplet.description,
81959
+ schemaHash: null,
81960
+ capletId: caplet.id,
81961
+ shadowing: caplet.shadowing ?? "forbid"
81962
+ })));
81963
+ }
81964
+ async function invokeNativeAttachExport(service, projection, request) {
81965
+ if (request.revision !== projection.manifest.revision) throw new CapletsError("ATTACH_MANIFEST_STALE", "Attach manifest revision is stale.");
81966
+ const route = projection.routes.get(request.exportId);
81967
+ if (!route || route.kind !== request.kind) throw new CapletsError("ATTACH_EXPORT_NOT_FOUND", "Attach export was not found.");
81968
+ if (route.kind !== "caplet") {
81969
+ if (route.kind === "tool") return await service.execute(`${route.capletId}__${route.downstreamName}`, request.input);
81970
+ throw new CapletsError("REQUEST_INVALID", "Native attach sessions only support Caplet and tool exports.");
81971
+ }
81972
+ return await service.execute(route.capletId, request.input);
81973
+ }
81974
+ async function invokeAttachExport$1(engine, projection, request) {
81975
+ if (request.revision !== projection.manifest.revision) throw new CapletsError("ATTACH_MANIFEST_STALE", "Attach manifest revision is stale.");
81976
+ const route = projection.routes.get(request.exportId);
81977
+ if (!route || route.kind !== request.kind) throw new CapletsError("ATTACH_EXPORT_NOT_FOUND", "Attach export was not found.");
81978
+ if (route.kind === "caplet") return await engine.execute(route.capletId, request.input);
81979
+ if (route.kind === "tool") return await engine.executeDirectTool(route.capletId, route.downstreamName, isRecord$4(request.input) ? request.input : {});
81980
+ if (route.kind === "resource") return await engine.readDirectResource(route.capletId, route.downstreamUri);
81981
+ if (route.kind === "resourceTemplate") {
81982
+ const uri = isRecord$4(request.input) && typeof request.input.uri === "string" ? request.input.uri : void 0;
81983
+ if (!uri) throw new CapletsError("REQUEST_INVALID", "Attach resource template invoke requires input.uri.");
81984
+ const downstreamUri = downstreamResourceUri$1(route.capletId, uri);
81985
+ if (!directResourceUriMatchesTemplate(downstreamUri, route.downstreamUriTemplate)) throw new CapletsError("ATTACH_EXPORT_NOT_FOUND", "Attach resource URI does not match the exported resource template.");
81986
+ return await engine.readDirectResource(route.capletId, downstreamUri);
81987
+ }
81988
+ if (route.kind === "prompt") return await engine.getDirectPrompt(route.capletId, route.downstreamName, isRecord$4(request.input) ? stringifyRecord(request.input) : {});
81989
+ if (route.kind === "completion") return await engine.execute(route.capletId, {
81990
+ ...normalizeCompletionInput(projection.manifest, route.capletId, request.input),
81991
+ operation: "complete"
81992
+ });
81993
+ throw new CapletsError("REQUEST_INVALID", "Attach export kind is not invokable via /v1/attach/invoke.");
81994
+ }
81995
+ function attachErrorResponse(error) {
81996
+ const safe = toSafeError(error, "INTERNAL_ERROR");
81997
+ return {
81998
+ status: safe.code === "ATTACH_MANIFEST_STALE" ? 409 : safe.code === "ATTACH_EXPORT_NOT_FOUND" ? 404 : safe.code === "REQUEST_INVALID" ? 400 : 500,
81999
+ body: {
82000
+ ok: false,
82001
+ error: safe
82002
+ }
82003
+ };
82004
+ }
82005
+ function progressiveCapletExport(entry) {
82006
+ const inputSchema = generatedToolInputJsonSchemaForCaplet(entry.caplet);
82007
+ return {
82008
+ stableId: `progressive:${entry.caplet.server}`,
82009
+ kind: "caplet",
82010
+ name: entry.caplet.server,
82011
+ title: entry.caplet.name,
82012
+ description: entry.caplet.description,
82013
+ inputSchema,
82014
+ schemaHash: schemaHash(inputSchema),
82015
+ capletId: entry.caplet.server,
82016
+ shadowing: shadowingPolicy(entry.caplet)
82017
+ };
82018
+ }
82019
+ function codeModeCapletExport(entry) {
82020
+ return {
82021
+ stableId: `code_mode:${entry.caplet.server}`,
82022
+ kind: "caplet",
82023
+ name: entry.caplet.name,
82024
+ title: entry.caplet.name,
82025
+ description: entry.caplet.description,
82026
+ schemaHash: null,
82027
+ capletId: entry.caplet.server,
82028
+ shadowing: shadowingPolicy(entry.caplet)
82029
+ };
82030
+ }
82031
+ function toolExport(entry) {
82032
+ return {
82033
+ stableId: `tool:${entry.caplet.server}:${entry.downstreamName}`,
82034
+ kind: "tool",
82035
+ name: entry.name,
82036
+ downstreamName: entry.downstreamName,
82037
+ title: entry.tool.name,
82038
+ description: entry.tool.description,
82039
+ inputSchema: entry.tool.inputSchema,
82040
+ outputSchema: entry.tool.outputSchema,
82041
+ annotations: entry.tool.annotations,
82042
+ schemaHash: schemaHash({
82043
+ input: entry.tool.inputSchema,
82044
+ output: entry.tool.outputSchema
82045
+ }),
82046
+ capletId: entry.caplet.server,
82047
+ shadowing: shadowingPolicy(entry.caplet)
82048
+ };
82049
+ }
82050
+ function resourceExport(entry) {
82051
+ return {
82052
+ stableId: `resource:${entry.caplet.server}:${entry.downstreamUri}`,
82053
+ kind: "resource",
82054
+ uri: entry.uri,
82055
+ downstreamUri: entry.downstreamUri,
82056
+ title: entry.resource.name,
82057
+ description: entry.resource.description,
82058
+ ...entry.resource.mimeType ? { mimeType: entry.resource.mimeType } : {},
82059
+ ...typeof entry.resource.size === "number" ? { size: entry.resource.size } : {},
82060
+ schemaHash: null,
82061
+ capletId: entry.caplet.server,
82062
+ shadowing: shadowingPolicy(entry.caplet)
82063
+ };
82064
+ }
82065
+ function resourceTemplateExport(entry) {
82066
+ return {
82067
+ stableId: `resourceTemplate:${entry.caplet.server}:${entry.downstreamUriTemplate}`,
82068
+ kind: "resourceTemplate",
82069
+ uriTemplate: entry.uriTemplate,
82070
+ downstreamUriTemplate: entry.downstreamUriTemplate,
82071
+ title: entry.resourceTemplate.name,
82072
+ description: entry.resourceTemplate.description,
82073
+ ...entry.resourceTemplate.mimeType ? { mimeType: entry.resourceTemplate.mimeType } : {},
82074
+ schemaHash: null,
82075
+ capletId: entry.caplet.server,
82076
+ shadowing: shadowingPolicy(entry.caplet)
82077
+ };
82078
+ }
82079
+ function promptExport(entry) {
82080
+ const inputSchema = { arguments: entry.prompt.arguments ?? [] };
82081
+ return {
82082
+ stableId: `prompt:${entry.caplet.server}:${entry.downstreamName}`,
82083
+ kind: "prompt",
82084
+ name: entry.name,
82085
+ downstreamName: entry.downstreamName,
82086
+ title: entry.prompt.name,
82087
+ description: entry.prompt.description,
82088
+ inputSchema,
82089
+ schemaHash: schemaHash(inputSchema),
82090
+ capletId: entry.caplet.server,
82091
+ shadowing: shadowingPolicy(entry.caplet)
82092
+ };
82093
+ }
82094
+ function completionExports(snapshot) {
82095
+ return [...new Map([...snapshot.directPrompts, ...snapshot.directResourceTemplates].map((entry) => [entry.caplet.server, entry.caplet])).entries()].sort(([left], [right]) => left.localeCompare(right)).map(([capletId, caplet]) => ({
82096
+ stableId: `completion:${capletId}`,
82097
+ kind: "completion",
82098
+ name: `${capletId}:complete`,
82099
+ title: "Complete",
82100
+ description: `MCP completion for ${capletId}.`,
82101
+ schemaHash: null,
82102
+ capletId,
82103
+ shadowing: shadowingPolicy(caplet)
82104
+ }));
82105
+ }
82106
+ function shadowingPolicy(caplet) {
82107
+ return caplet.shadowing ?? "forbid";
82108
+ }
82109
+ function sortAttachProjectionInput(partial) {
82110
+ return {
82111
+ caplets: sortByStableId(partial.caplets),
82112
+ tools: sortByStableId(partial.tools),
82113
+ resources: sortByStableId(partial.resources),
82114
+ resourceTemplates: sortByStableId(partial.resourceTemplates),
82115
+ prompts: sortByStableId(partial.prompts),
82116
+ completions: sortByStableId(partial.completions),
82117
+ codeModeCaplets: sortByStableId(partial.codeModeCaplets),
82118
+ diagnostics: [...partial.diagnostics].sort((left, right) => diagnosticSortKey(left).localeCompare(diagnosticSortKey(right)))
82119
+ };
82120
+ }
82121
+ function sortByStableId(entries) {
82122
+ return [...entries].sort((left, right) => left.stableId.localeCompare(right.stableId));
82123
+ }
82124
+ function diagnosticSortKey(diagnostic) {
82125
+ return stableJsonStringify({
82126
+ code: diagnostic.code,
82127
+ capletId: diagnostic.capletId ?? "",
82128
+ message: diagnostic.message
82129
+ });
82130
+ }
82131
+ function revisionFor(value) {
82132
+ return `sha256:${createHash("sha256").update(stableJsonStringify(value)).digest("hex")}`;
82133
+ }
82134
+ function withRevisionExportIds(revision, partial) {
82135
+ return {
82136
+ ...partial,
82137
+ caplets: partial.caplets.map((entry) => withExportId(revision, entry)),
82138
+ tools: partial.tools.map((entry) => withExportId(revision, entry)),
82139
+ resources: partial.resources.map((entry) => withExportId(revision, entry)),
82140
+ resourceTemplates: partial.resourceTemplates.map((entry) => withExportId(revision, entry)),
82141
+ prompts: partial.prompts.map((entry) => withExportId(revision, entry)),
82142
+ completions: partial.completions.map((entry) => withExportId(revision, entry)),
82143
+ codeModeCaplets: partial.codeModeCaplets.map((entry) => withExportId(revision, entry))
82144
+ };
82145
+ }
82146
+ function withExportId(revision, entry) {
82147
+ return {
82148
+ ...entry,
82149
+ exportId: `${revision}:${entry.stableId}`
82150
+ };
82151
+ }
82152
+ function routesFor(manifest) {
82153
+ const routes = /* @__PURE__ */ new Map();
82154
+ for (const entry of manifest.caplets) routes.set(entry.exportId, {
82155
+ kind: "caplet",
82156
+ capletId: entry.capletId
82157
+ });
82158
+ for (const entry of manifest.tools) routes.set(entry.exportId, {
82159
+ kind: "tool",
82160
+ capletId: entry.capletId,
82161
+ downstreamName: entry.downstreamName
82162
+ });
82163
+ for (const entry of manifest.resources) routes.set(entry.exportId, {
82164
+ kind: "resource",
82165
+ capletId: entry.capletId,
82166
+ downstreamUri: entry.downstreamUri
82167
+ });
82168
+ for (const entry of manifest.resourceTemplates) routes.set(entry.exportId, {
82169
+ kind: "resourceTemplate",
82170
+ capletId: entry.capletId,
82171
+ downstreamUriTemplate: entry.downstreamUriTemplate
82172
+ });
82173
+ for (const entry of manifest.prompts) routes.set(entry.exportId, {
82174
+ kind: "prompt",
82175
+ capletId: entry.capletId,
82176
+ downstreamName: entry.downstreamName
82177
+ });
82178
+ for (const entry of manifest.completions) routes.set(entry.exportId, {
82179
+ kind: "completion",
82180
+ capletId: entry.capletId
82181
+ });
82182
+ for (const entry of manifest.codeModeCaplets) routes.set(entry.exportId, {
82183
+ kind: "caplet",
82184
+ capletId: entry.capletId
82185
+ });
82186
+ return routes;
82187
+ }
82188
+ function normalizeCompletionInput(manifest, capletId, input) {
82189
+ if (!isRecord$4(input)) return {};
82190
+ const ref = input.ref;
82191
+ if (!isRecord$4(ref)) return input;
82192
+ if (ref.type === "prompt" && typeof ref.name === "string") {
82193
+ const prompt = manifest.prompts.find((entry) => entry.capletId === capletId && (entry.name === ref.name || entry.downstreamName === ref.name));
82194
+ if (!prompt) return input;
82195
+ return {
82196
+ ...input,
82197
+ ref: {
82198
+ ...ref,
82199
+ name: prompt.downstreamName
82200
+ }
82201
+ };
82202
+ }
82203
+ if (ref.type === "resourceTemplate" && typeof ref.uri === "string") {
82204
+ const resourceTemplate = manifest.resourceTemplates.find((entry) => entry.capletId === capletId && (entry.uriTemplate === ref.uri || entry.downstreamUriTemplate === ref.uri));
82205
+ if (!resourceTemplate) return input;
82206
+ return {
82207
+ ...input,
82208
+ ref: {
82209
+ ...ref,
82210
+ uri: resourceTemplate.downstreamUriTemplate
82211
+ }
82212
+ };
82213
+ }
82214
+ return input;
82215
+ }
82216
+ function isRecord$4(value) {
82217
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
82218
+ }
82219
+ function stringifyRecord(record) {
82220
+ return Object.fromEntries(Object.entries(record).map(([key, value]) => [key, typeof value === "string" ? value : JSON.stringify(value)]));
82221
+ }
82222
+ function downstreamResourceUri$1(capletId, uri) {
82223
+ if (!uri.startsWith("caplets://")) return uri;
82224
+ const decoded = decodeDirectResourceUri(uri);
82225
+ if (decoded.capletId !== capletId) throw new CapletsError("ATTACH_EXPORT_NOT_FOUND", "Attach resource template URI belongs to a different Caplet.");
82226
+ return decoded.downstreamUri;
82227
+ }
82228
+ //#endregion
80971
82229
  //#region src/native/remote.ts
82230
+ const ATTACH_SESSION_UNSUPPORTED_RETRY_MS = 6e4;
80972
82231
  function createSdkRemoteCapletsClient(options) {
80973
82232
  const listeners = /* @__PURE__ */ new Set();
80974
82233
  let manifest;
@@ -80976,18 +82235,50 @@ function createSdkRemoteCapletsClient(options) {
80976
82235
  let eventsAbort;
80977
82236
  let eventsStartInFlight;
80978
82237
  let eventsReconnectTimer;
82238
+ let attachSessionId;
82239
+ let attachSessionInFlight;
82240
+ let attachSessionsUnsupportedUntil = 0;
80979
82241
  let closed = false;
80980
82242
  const resolveRuntimeOptions = async () => {
80981
82243
  return options.resolveRuntimeOptions ? await options.resolveRuntimeOptions() : options;
80982
82244
  };
80983
82245
  const fetchFor = (runtimeOptions) => runtimeOptions.fetch ?? fetch;
80984
82246
  const fetchCurrentManifest = async () => {
80985
- const runtimeOptions = await resolveRuntimeOptions();
80986
- return await fetchAttachManifest(runtimeOptions.url, runtimeOptions.requestInit, fetchFor(runtimeOptions));
82247
+ return await withAttachSessionRetry(async (runtimeOptions, sessionId) => {
82248
+ return await fetchAttachManifest(runtimeOptions.url, runtimeOptions.requestInit, sessionId, fetchFor(runtimeOptions));
82249
+ });
80987
82250
  };
80988
82251
  const invokeCurrentExport = async (body) => {
82252
+ return await withAttachSessionRetry(async (runtimeOptions, sessionId) => {
82253
+ return await invokeAttachExport(runtimeOptions.url, runtimeOptions.requestInit, sessionId, fetchFor(runtimeOptions), body);
82254
+ });
82255
+ };
82256
+ const ensureAttachSession = async (runtimeOptions) => {
82257
+ if (!options.attachSessionMetadata) return void 0;
82258
+ if (attachSessionsUnsupportedUntil > Date.now()) return void 0;
82259
+ attachSessionsUnsupportedUntil = 0;
82260
+ if (attachSessionId) return attachSessionId;
82261
+ if (attachSessionInFlight) return await attachSessionInFlight;
82262
+ attachSessionInFlight = createAttachSession(runtimeOptions.url, runtimeOptions.requestInit, fetchFor(runtimeOptions), options.attachSessionMetadata);
82263
+ try {
82264
+ attachSessionId = await attachSessionInFlight;
82265
+ if (!attachSessionId) attachSessionsUnsupportedUntil = Date.now() + ATTACH_SESSION_UNSUPPORTED_RETRY_MS;
82266
+ return attachSessionId;
82267
+ } finally {
82268
+ attachSessionInFlight = void 0;
82269
+ }
82270
+ };
82271
+ const withAttachSessionRetry = async (operation) => {
80989
82272
  const runtimeOptions = await resolveRuntimeOptions();
80990
- return await invokeAttachExport(runtimeOptions.url, runtimeOptions.requestInit, fetchFor(runtimeOptions), body);
82273
+ const sessionId = await ensureAttachSession(runtimeOptions);
82274
+ if (closed) throw new CapletsError("SERVER_UNAVAILABLE", "Remote Caplets client is closed.");
82275
+ try {
82276
+ return await operation(runtimeOptions, sessionId);
82277
+ } catch (error) {
82278
+ if (!options.attachSessionMetadata || attachSessionsUnsupportedUntil > Date.now() || !sessionId || !isAttachSessionNotFound(error)) throw error;
82279
+ if (attachSessionId === sessionId) attachSessionId = void 0;
82280
+ return await operation(runtimeOptions, await ensureAttachSession(runtimeOptions));
82281
+ }
80991
82282
  };
80992
82283
  const clearEventsReconnectTimer = () => {
80993
82284
  if (eventsReconnectTimer) {
@@ -81007,7 +82298,9 @@ function createSdkRemoteCapletsClient(options) {
81007
82298
  try {
81008
82299
  const runtimeOptions = await resolveRuntimeOptions();
81009
82300
  if (closed || eventsAbort || listeners.size === 0) return;
81010
- eventsAbort = startAttachEvents(runtimeOptions.url, runtimeOptions.requestInit, fetchFor(runtimeOptions), listeners, (closedAbort, retry) => {
82301
+ const sessionId = await ensureAttachSession(runtimeOptions);
82302
+ if (closed || eventsAbort || listeners.size === 0) return;
82303
+ eventsAbort = startAttachEvents(runtimeOptions.url, runtimeOptions.requestInit, sessionId, fetchFor(runtimeOptions), listeners, (closedAbort, retry) => {
81011
82304
  if (eventsAbort !== closedAbort) return;
81012
82305
  eventsAbort = void 0;
81013
82306
  if (!retry || closedAbort.signal.aborted || listeners.size === 0) return;
@@ -81089,6 +82382,13 @@ function createSdkRemoteCapletsClient(options) {
81089
82382
  eventsAbort?.abort();
81090
82383
  eventsAbort = void 0;
81091
82384
  listeners.clear();
82385
+ const pendingSessionId = await attachSessionInFlight?.catch(() => void 0);
82386
+ const sessionId = attachSessionId ?? pendingSessionId;
82387
+ attachSessionId = void 0;
82388
+ if (sessionId) await (async () => {
82389
+ const runtimeOptions = await resolveRuntimeOptions();
82390
+ await closeAttachSession(runtimeOptions.url, runtimeOptions.requestInit, fetchFor(runtimeOptions), sessionId);
82391
+ })().catch(() => void 0);
81092
82392
  }
81093
82393
  };
81094
82394
  }
@@ -81285,16 +82585,62 @@ function remoteCodeModeCallableNativeTools$1(tools) {
81285
82585
  function nativeToolRouteId(tool) {
81286
82586
  return tool.codeModeRun ? nativeCodeModeToolId : tool.name;
81287
82587
  }
81288
- async function fetchAttachManifest(attachUrl, requestInit, fetchImpl) {
82588
+ async function fetchAttachManifest(attachUrl, requestInit, attachSessionId, fetchImpl) {
82589
+ const headers = attachHeaders(requestInit, attachSessionId);
81289
82590
  const response = await fetchImpl(new URL("manifest", slashUrl(attachUrl)), {
81290
82591
  ...requestInit,
81291
- method: "GET"
82592
+ method: "GET",
82593
+ headers
81292
82594
  });
81293
- if (!response.ok) throw new CapletsError("SERVER_UNAVAILABLE", `Caplets attach manifest returned HTTP ${response.status}.`);
82595
+ if (!response.ok) {
82596
+ let payload;
82597
+ try {
82598
+ payload = await response.json();
82599
+ } catch {
82600
+ payload = { error: { message: `Caplets attach manifest returned HTTP ${response.status}.` } };
82601
+ }
82602
+ throw attachPayloadError(payload, response.status, "manifest");
82603
+ }
81294
82604
  return await response.json();
81295
82605
  }
81296
- async function invokeAttachExport(attachUrl, requestInit, fetchImpl, body) {
82606
+ async function createAttachSession(attachUrl, requestInit, fetchImpl, metadata) {
82607
+ const headers = new Headers(requestInit?.headers);
82608
+ headers.set("content-type", "application/json");
82609
+ const response = await fetchImpl(new URL("sessions", slashUrl(attachUrl)), {
82610
+ ...requestInit,
82611
+ method: "POST",
82612
+ headers,
82613
+ body: JSON.stringify(metadata)
82614
+ });
82615
+ if (!response.ok) {
82616
+ if (response.status === 404) return void 0;
82617
+ let payload;
82618
+ try {
82619
+ payload = await response.json();
82620
+ } catch {
82621
+ payload = void 0;
82622
+ }
82623
+ if (response.status === 400 && isAttachSessionProjectContextRejected(payload)) return;
82624
+ throw new CapletsError("SERVER_UNAVAILABLE", `Caplets attach session returned HTTP ${response.status}.`);
82625
+ }
82626
+ const payload = await response.json();
82627
+ if (!isPlainObject(payload) || typeof payload.sessionId !== "string") throw new CapletsError("SERVER_UNAVAILABLE", "Caplets attach session response was invalid.");
82628
+ return payload.sessionId;
82629
+ }
82630
+ async function closeAttachSession(attachUrl, requestInit, fetchImpl, attachSessionId) {
82631
+ await fetchImpl(new URL(`sessions/${encodeURIComponent(attachSessionId)}`, slashUrl(attachUrl)), {
82632
+ ...requestInit,
82633
+ method: "DELETE",
82634
+ headers: attachHeaders(requestInit, attachSessionId)
82635
+ });
82636
+ }
82637
+ function attachHeaders(requestInit, attachSessionId) {
81297
82638
  const headers = new Headers(requestInit?.headers);
82639
+ if (attachSessionId) headers.set(CAPLETS_ATTACH_SESSION_HEADER, attachSessionId);
82640
+ return headers;
82641
+ }
82642
+ async function invokeAttachExport(attachUrl, requestInit, attachSessionId, fetchImpl, body) {
82643
+ const headers = attachHeaders(requestInit, attachSessionId);
81298
82644
  headers.set("content-type", "application/json");
81299
82645
  const response = await fetchImpl(new URL("invoke", slashUrl(attachUrl)), {
81300
82646
  ...requestInit,
@@ -81306,10 +82652,10 @@ async function invokeAttachExport(attachUrl, requestInit, fetchImpl, body) {
81306
82652
  try {
81307
82653
  payload = await response.json();
81308
82654
  } catch (error) {
81309
- if (!response.ok) throw attachPayloadError({ error: { message: `Caplets attach invoke returned HTTP ${response.status}.` } }, response.status);
82655
+ if (!response.ok) throw attachPayloadError({ error: { message: `Caplets attach invoke returned HTTP ${response.status}.` } }, response.status, "invoke");
81310
82656
  throw error;
81311
82657
  }
81312
- if (!response.ok) throw attachPayloadError(payload, response.status);
82658
+ if (!response.ok) throw attachPayloadError(payload, response.status, "invoke");
81313
82659
  if (isPlainObject(payload) && payload.ok === true && "data" in payload) return payload.data;
81314
82660
  return payload;
81315
82661
  }
@@ -81409,7 +82755,7 @@ function primitiveInvokeInput(capletId, operation, input) {
81409
82755
  function toolsFromManifest(manifest) {
81410
82756
  const codeModeCaplets = manifest.codeModeCaplets ?? [];
81411
82757
  const codeModeMarker = attachCodeModeMarker(codeModeCaplets);
81412
- const codeModeShadowing = codeModeCaplets.some((entry) => entry.shadowing === "forbid") ? "forbid" : "allow";
82758
+ const codeModeShadowing = codeModeCaplets.some((entry) => entry.shadowing === "forbid") ? "forbid" : codeModeCaplets.some((entry) => entry.shadowing === "namespace") ? "namespace" : "allow";
81413
82759
  return [
81414
82760
  ...manifest.caplets.map((entry) => ({
81415
82761
  name: entry.capletId,
@@ -81566,9 +82912,9 @@ function slashUrl(url) {
81566
82912
  next.pathname = next.pathname.endsWith("/") ? next.pathname : `${next.pathname}/`;
81567
82913
  return next;
81568
82914
  }
81569
- function attachPayloadError(payload, status) {
82915
+ function attachPayloadError(payload, status, endpoint) {
81570
82916
  const error = isPlainObject(payload) && isPlainObject(payload.error) ? payload.error : void 0;
81571
- const message = typeof error?.message === "string" ? error.message : `Caplets attach invoke returned HTTP ${status}.`;
82917
+ const message = typeof error?.message === "string" ? error.message : `Caplets attach ${endpoint} returned HTTP ${status}.`;
81572
82918
  const thrown = new Error(message);
81573
82919
  thrown.status = status;
81574
82920
  if (error && "code" in error) thrown.code = error.code;
@@ -81577,14 +82923,23 @@ function attachPayloadError(payload, status) {
81577
82923
  function isAttachManifestStale(error) {
81578
82924
  return isPlainObject(error) && error.code === "ATTACH_MANIFEST_STALE";
81579
82925
  }
81580
- function startAttachEvents(attachUrl, requestInit, fetchImpl, listeners, onClose) {
82926
+ function isAttachSessionNotFound(error) {
82927
+ return error.code === "REQUEST_INVALID" && /\battach session was not found\b/iu.test(errorMessage$1(error));
82928
+ }
82929
+ function isAttachSessionProjectContextRejected(payload) {
82930
+ const error = isPlainObject(payload) && isPlainObject(payload.error) ? payload.error : void 0;
82931
+ return error?.code === "REQUEST_INVALID" && typeof error.message === "string" && /\bproject context is only accepted by loopback runtimes\b/iu.test(error.message);
82932
+ }
82933
+ function startAttachEvents(attachUrl, requestInit, attachSessionId, fetchImpl, listeners, onClose) {
81581
82934
  const abort = new AbortController();
81582
82935
  let retry = true;
81583
82936
  (async () => {
81584
82937
  try {
82938
+ const headers = attachHeaders(requestInit, attachSessionId);
81585
82939
  const response = await fetchImpl(new URL("events", slashUrl(attachUrl)), {
81586
82940
  ...requestInit,
81587
82941
  method: "GET",
82942
+ headers,
81588
82943
  signal: abort.signal
81589
82944
  });
81590
82945
  if (!response.ok) {
@@ -81711,6 +83066,119 @@ function isPermanentRemoteCredentialsCode(code) {
81711
83066
  return code === "remote_credentials_required" || code === "remote_credentials_revoked" || code === "remote_auth_failed";
81712
83067
  }
81713
83068
  //#endregion
83069
+ //#region src/exposure/namespace.ts
83070
+ function resolveNamespaceExposure(entries, options = {}) {
83071
+ const hashLength = options.hashLength ?? 4;
83072
+ const maxHashLength = options.maxHashLength ?? 8;
83073
+ const groups = groupByBaseId(entries);
83074
+ const visibleRecords = [];
83075
+ const suppressedBareIds = /* @__PURE__ */ new Map();
83076
+ const unavailableDiagnostics = [];
83077
+ const reservedBareIds = new Set(groups.keys());
83078
+ for (const [baseId, group] of groups) {
83079
+ if (group.length === 1) {
83080
+ visibleRecords.push(visibleRecord(group[0], baseId, false));
83081
+ continue;
83082
+ }
83083
+ if (!isNamespaceCollisionGroup(group)) {
83084
+ visibleRecords.push(visibleRecord(nonNamespaceWinner(group), baseId, false));
83085
+ continue;
83086
+ }
83087
+ const diagnostics = validateNamespaceGroup(baseId, group);
83088
+ if (diagnostics.length > 0) {
83089
+ unavailableDiagnostics.push(...diagnostics);
83090
+ continue;
83091
+ }
83092
+ const resolved = qualifyNamespaceGroup(group, {
83093
+ baseId,
83094
+ hashLength,
83095
+ maxHashLength,
83096
+ reservedBareIds
83097
+ });
83098
+ if ("diagnostic" in resolved) {
83099
+ unavailableDiagnostics.push(resolved.diagnostic);
83100
+ continue;
83101
+ }
83102
+ visibleRecords.push(...resolved.records);
83103
+ suppressedBareIds.set(baseId, diagnostic(baseId, "namespace_collision", group, resolved.records.map((record) => record.id)));
83104
+ }
83105
+ return {
83106
+ visibleRecords,
83107
+ routes: new Map(visibleRecords.map((record) => [record.id, record.route])),
83108
+ suppressedBareIds,
83109
+ unavailableDiagnostics
83110
+ };
83111
+ }
83112
+ function groupByBaseId(entries) {
83113
+ const groups = /* @__PURE__ */ new Map();
83114
+ for (const entry of entries) groups.set(entry.baseId, [...groups.get(entry.baseId) ?? [], entry]);
83115
+ return groups;
83116
+ }
83117
+ function isNamespaceCollisionGroup(group) {
83118
+ const upstreams = group.filter((entry) => entry.sourceKind === "upstream");
83119
+ return upstreams.length > 0 && upstreams.every((entry) => entry.shadowing === "namespace");
83120
+ }
83121
+ function nonNamespaceWinner(group) {
83122
+ const forbiddingUpstream = group.find((entry) => entry.sourceKind === "upstream" && entry.shadowing === "forbid");
83123
+ if (forbiddingUpstream) return forbiddingUpstream;
83124
+ const local = group.find((entry) => entry.sourceKind === "local");
83125
+ if (local) return local;
83126
+ return group.find((entry) => entry.sourceKind === "upstream") ?? group[0];
83127
+ }
83128
+ function validateNamespaceGroup(baseId, group) {
83129
+ const diagnostics = [];
83130
+ for (const entry of group) {
83131
+ if (!entry.durableSourceIdentity) {
83132
+ diagnostics.push(diagnostic(baseId, "missing_durable_source_identity", group, []));
83133
+ break;
83134
+ }
83135
+ if (entry.namespaceAlias && !NAMESPACE_ALIAS_LABEL_PATTERN.test(entry.namespaceAlias)) {
83136
+ diagnostics.push(diagnostic(baseId, "namespace_alias_invalid", group, []));
83137
+ break;
83138
+ }
83139
+ }
83140
+ return diagnostics;
83141
+ }
83142
+ function qualifyNamespaceGroup(group, options) {
83143
+ const ids = group.map((entry) => qualifiedId(entry, options.baseId, options.hashLength));
83144
+ if (!(new Set(ids).size !== ids.length || ids.some((id) => options.reservedBareIds.has(id) || !SERVER_ID_PATTERN.test(id)))) return { records: group.map((entry, index) => visibleRecord(entry, ids[index], true)) };
83145
+ return { diagnostic: diagnostic(options.baseId, "generated_id_collision", group, []) };
83146
+ }
83147
+ function qualifiedId(entry, baseId, hashLength) {
83148
+ return `${namespaceLabel(entry)}-${createHash("sha256").update(entry.durableSourceIdentity ?? "").digest("hex").slice(0, hashLength)}__${baseId}`;
83149
+ }
83150
+ function visibleRecord(entry, id, namespaced) {
83151
+ return {
83152
+ ...entry,
83153
+ id,
83154
+ label: namespaceLabel(entry),
83155
+ namespaced
83156
+ };
83157
+ }
83158
+ function namespaceLabel(entry) {
83159
+ return entry.namespaceAlias ?? entry.sourceLabel ?? entry.sourceKind;
83160
+ }
83161
+ function diagnostic(requestedId, reason, group, alternatives) {
83162
+ return {
83163
+ requestedId,
83164
+ reason,
83165
+ alternatives,
83166
+ sources: group.map((entry) => ({
83167
+ sourceKind: entry.sourceKind,
83168
+ label: namespaceLabel(entry),
83169
+ ...entry.durableSourceIdentity ? { durableSourceIdentity: entry.durableSourceIdentity } : {}
83170
+ })),
83171
+ hint: diagnosticHint(requestedId, reason, alternatives)
83172
+ };
83173
+ }
83174
+ function diagnosticHint(requestedId, reason, alternatives) {
83175
+ if (reason === "namespace_collision") return `Caplet '${requestedId}' is unavailable because namespace shadowing exposes qualified alternatives: ${alternatives.join(", ")}.`;
83176
+ if (reason === "missing_durable_source_identity") return `Caplet '${requestedId}' could not be namespaced because at least one source has no durable identity.`;
83177
+ if (reason === "namespace_alias_invalid") return `Caplet '${requestedId}' could not be namespaced because an alias label is invalid.`;
83178
+ if (reason === "unsupported_protocol") return `Caplet '${requestedId}' could not be namespaced because a source protocol cannot represent namespace metadata.`;
83179
+ return `Caplet '${requestedId}' could not be namespaced because generated qualified IDs were not unique.`;
83180
+ }
83181
+ //#endregion
81714
83182
  //#region src/cloud-auth/errors.ts
81715
83183
  const SECRET_PATTERN = /(cap_access_[a-z0-9._~+/=-]+|cap_refresh_[a-z0-9._~+/=-]+|one_time_code_[a-z0-9._~+/=-]+|Bearer\s+)[^\s"]*/giu;
81716
83184
  function redactCloudAuthSecrets(value) {
@@ -82852,7 +84320,11 @@ var DefaultNativeCapletsService = class {
82852
84320
  this.writeErr = options.writeErr ?? (() => void 0);
82853
84321
  this.engine = new CapletsEngine({
82854
84322
  ...options,
82855
- writeErr: this.writeErr
84323
+ writeErr: this.writeErr,
84324
+ telemetrySurface: options.telemetrySurface ?? "native",
84325
+ telemetryVisibility: options.telemetryVisibility ?? "hidden",
84326
+ telemetryRuntimeMode: options.telemetryRuntimeMode ?? runtimeModeFromNativeOptions(options),
84327
+ telemetryIntegration: options.telemetryIntegration ?? "native"
82856
84328
  });
82857
84329
  this.postReloadRefresh = this.refreshExposureSnapshot({ emitToolsChanged: this.hasSnapshotBackedDirectExposure() });
82858
84330
  this.unsubscribeEngineReload = this.engine.onReload(() => {
@@ -82883,7 +84355,16 @@ var DefaultNativeCapletsService = class {
82883
84355
  ];
82884
84356
  }
82885
84357
  async execute(capletId, request) {
82886
- if (capletId === "code_mode") return await executeCodeModeRunNative(this.codeModeDelegate(), request, this.codeModeSessions);
84358
+ if (capletId === "code_mode") {
84359
+ const started = Date.now();
84360
+ const envelope = await executeCodeModeRunNative(this.codeModeDelegate(), request, this.codeModeSessions);
84361
+ const parsed = codeModeRunInputSchema.safeParse(request);
84362
+ this.engine.captureCodeModeOutcome(envelope, {
84363
+ started,
84364
+ ...parsed.success && parsed.data.timeoutMs !== void 0 ? { timeoutMs: parsed.data.timeoutMs } : {}
84365
+ }).catch(() => void 0);
84366
+ return envelope;
84367
+ }
82887
84368
  const route = this.directToolRoutes.get(capletId);
82888
84369
  if (route) {
82889
84370
  if (isMcpPrimitiveRoute(route.operationName)) return await this.engine.execute(route.capletId, nativeMcpPrimitiveRequest(route.operationName, request));
@@ -82891,6 +84372,9 @@ var DefaultNativeCapletsService = class {
82891
84372
  }
82892
84373
  return await this.engine.execute(capletId, request);
82893
84374
  }
84375
+ async captureCodeModeOutcome(envelope, options) {
84376
+ await this.engine.captureCodeModeOutcome(envelope, options);
84377
+ }
82894
84378
  codeModeService() {
82895
84379
  return this.codeModeDelegate();
82896
84380
  }
@@ -83111,9 +84595,39 @@ function nativeMcpPrimitiveRequest(operationName, request) {
83111
84595
  };
83112
84596
  return { operation: operationName };
83113
84597
  }
84598
+ function operationFromNativeRequest(request) {
84599
+ return isRecord(request) ? request.operation : void 0;
84600
+ }
83114
84601
  function isRecord(value) {
83115
84602
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
83116
84603
  }
84604
+ function runtimeModeFromNativeOptions(options) {
84605
+ if (options.mode === "local") return "local";
84606
+ if (options.mode === "remote") return "remote";
84607
+ if (options.mode === "cloud") return "cloud";
84608
+ if (options.remote?.url) return "remote";
84609
+ const envMode = options.telemetryEnv?.CAPLETS_MODE ?? process.env.CAPLETS_MODE;
84610
+ if (envMode === "remote" || envMode === "cloud" || envMode === "local") return envMode;
84611
+ return "local";
84612
+ }
84613
+ function telemetryConfigFromNativeOptions(options) {
84614
+ const configPath = resolveConfigPath(options.configPath);
84615
+ const config = createLocalOverlayConfigLoader(options)(configPath, options.projectConfigPath ?? resolveProjectConfigPath());
84616
+ const explicitTelemetry = readTelemetryOnlyConfig(configPath);
84617
+ return explicitTelemetry === void 0 ? config : {
84618
+ ...config,
84619
+ telemetry: explicitTelemetry
84620
+ };
84621
+ }
84622
+ function readTelemetryOnlyConfig(path) {
84623
+ if (!existsSync(path)) return void 0;
84624
+ try {
84625
+ const parsed = JSON.parse(readFileSync(path, "utf8"));
84626
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? typeof parsed.telemetry === "boolean" ? parsed.telemetry : void 0 : void 0;
84627
+ } catch {
84628
+ return;
84629
+ }
84630
+ }
83117
84631
  function codeModeRunNativeTool(capletTools) {
83118
84632
  const codeModeCaplets = capletTools.map((tool) => ({
83119
84633
  id: tool.caplet,
@@ -83197,7 +84711,7 @@ function createLocalOverlayService(options) {
83197
84711
  }
83198
84712
  function createCompositeRemoteService(remoteOptions, local, options, authKind) {
83199
84713
  const { remote, presence } = createCompositeRemoteParts(remoteOptions, local, options, authKind);
83200
- return new CompositeNativeCapletsService(remote, local, options, presence);
84714
+ return new CompositeNativeCapletsService(remote, local, options, remoteOptions.url.toString(), presence);
83201
84715
  }
83202
84716
  function createCompositeRemoteParts(remoteOptions, local, options, authKind, resolveRuntimeRemoteOptions) {
83203
84717
  const remote = new RemoteNativeCapletsService({
@@ -83207,7 +84721,7 @@ function createCompositeRemoteParts(remoteOptions, local, options, authKind, res
83207
84721
  authKind,
83208
84722
  ...options.writeErr ? { writeErr: options.writeErr } : {}
83209
84723
  });
83210
- const presence = createProjectBindingSessionManager(remoteOptions.cloud, local, options);
84724
+ const presence = createProjectBindingSessionManager(remoteOptions.cloud, remoteOptions, local, options);
83211
84725
  return {
83212
84726
  remote,
83213
84727
  ...presence ? { presence } : {}
@@ -83215,13 +84729,33 @@ function createCompositeRemoteParts(remoteOptions, local, options, authKind, res
83215
84729
  }
83216
84730
  function createRemoteClient(remoteOptions, options, authKind, resolveRuntimeRemoteOptions) {
83217
84731
  if (options.remoteClientFactory) return options.remoteClientFactory(remoteOptions);
84732
+ const attachSessionMetadata = isLoopbackRemote(remoteOptions) ? attachSessionMetadataForOptions(options) : void 0;
83218
84733
  return createSdkRemoteCapletsClient({
83219
84734
  ...remoteOptions,
83220
84735
  authKind,
83221
84736
  ...options.writeErr ? { writeErr: options.writeErr } : {},
84737
+ ...attachSessionMetadata ? { attachSessionMetadata } : {},
83222
84738
  ...resolveRuntimeRemoteOptions ? { resolveRuntimeOptions: resolveRuntimeRemoteOptions } : {}
83223
84739
  });
83224
84740
  }
84741
+ function attachSessionMetadataForOptions(options) {
84742
+ if (!options.projectRoot) return void 0;
84743
+ const projectRoot = canonicalProjectRootForMetadata(options.projectRoot);
84744
+ return {
84745
+ projectRoot,
84746
+ projectConfigPath: resolve(projectRoot, ".caplets", "config.json")
84747
+ };
84748
+ }
84749
+ function canonicalProjectRootForMetadata(projectRoot) {
84750
+ try {
84751
+ return realpathSync(projectRoot);
84752
+ } catch {
84753
+ return projectRoot;
84754
+ }
84755
+ }
84756
+ function isLoopbackRemote(remoteOptions) {
84757
+ return remoteOptions.url.protocol === "http:" && isLoopbackHost(remoteOptions.url.hostname);
84758
+ }
83225
84759
  var ProfileBackedNativeCapletsService = class {
83226
84760
  options;
83227
84761
  baseRemote;
@@ -83289,7 +84823,7 @@ var ProfileBackedNativeCapletsService = class {
83289
84823
  const signature = remoteOptionsSignature(remoteOptions);
83290
84824
  if (!this.delegate) {
83291
84825
  const { remote, presence } = createCompositeRemoteParts(remoteOptions, this.local, this.options, this.authKind, () => this.resolveProfileRemoteOptions());
83292
- this.delegate = new CompositeNativeCapletsService(remote, this.local, this.options, presence);
84826
+ this.delegate = new CompositeNativeCapletsService(remote, this.local, this.options, remoteOptions.url.toString(), presence);
83293
84827
  this.unsubscribeDelegate = this.delegate.onToolsChanged((tools) => this.emit(tools));
83294
84828
  this.remoteSignature = signature;
83295
84829
  this.credentialExpiresAt = remoteOptions.credentialExpiresAt;
@@ -83301,7 +84835,7 @@ var ProfileBackedNativeCapletsService = class {
83301
84835
  await Promise.all([remote.close(), presence?.close()]);
83302
84836
  return;
83303
84837
  }
83304
- await this.delegate.replaceRemote(remote, presence);
84838
+ await this.delegate.replaceRemote(remote, remoteOptions.url.toString(), presence);
83305
84839
  this.remoteSignature = signature;
83306
84840
  this.credentialExpiresAt = remoteOptions.credentialExpiresAt;
83307
84841
  } catch (error) {
@@ -83386,23 +84920,44 @@ var CompositeNativeCapletsService = class {
83386
84920
  remote;
83387
84921
  local;
83388
84922
  options;
84923
+ remoteIdentity;
83389
84924
  presence;
83390
84925
  listeners = /* @__PURE__ */ new Set();
83391
84926
  unsubscribeRemote;
83392
84927
  unsubscribeLocal;
83393
84928
  warnedShadowedLocalCaplets = /* @__PURE__ */ new Set();
83394
84929
  tools = [];
84930
+ routes = /* @__PURE__ */ new Map();
84931
+ namespaceDiagnostics = /* @__PURE__ */ new Map();
83395
84932
  closed = false;
83396
84933
  batchingReload = false;
83397
84934
  codeModeSessions = new CodeModeSessionManager();
83398
- constructor(remote, local, options, presence) {
84935
+ telemetry;
84936
+ ownsTelemetryDispatcher;
84937
+ constructor(remote, local, options, remoteIdentity, presence) {
83399
84938
  this.remote = remote;
83400
84939
  this.local = local;
83401
84940
  this.options = options;
84941
+ this.remoteIdentity = remoteIdentity;
83402
84942
  this.presence = presence;
83403
84943
  this.unsubscribeRemote = this.remote.onToolsChanged(() => this.updateMergedTools());
83404
84944
  this.unsubscribeLocal = this.local.onToolsChanged(() => this.updateMergedTools());
83405
- this.tools = this.mergeTools();
84945
+ this.ownsTelemetryDispatcher = options.telemetryDispatcher === void 0;
84946
+ this.telemetry = createRuntimeTelemetryContext({
84947
+ config: telemetryConfigFromNativeOptions(options),
84948
+ env: options.telemetryEnv,
84949
+ stateDir: options.telemetryStateDir,
84950
+ surface: options.telemetrySurface ?? "native",
84951
+ visibility: options.telemetryVisibility ?? "hidden",
84952
+ runtimeMode: options.telemetryRuntimeMode ?? runtimeModeFromNativeOptions(options),
84953
+ integration: options.telemetryIntegration ?? "native",
84954
+ debugSink: options.telemetryDebugSink,
84955
+ dispatcher: options.telemetryDispatcher
84956
+ });
84957
+ const merged = this.mergeTools();
84958
+ this.tools = merged.tools;
84959
+ this.routes = merged.routes;
84960
+ this.namespaceDiagnostics = merged.namespaceDiagnostics;
83406
84961
  this.startPresence();
83407
84962
  }
83408
84963
  listTools() {
@@ -83410,8 +84965,12 @@ var CompositeNativeCapletsService = class {
83410
84965
  }
83411
84966
  async execute(capletId, request) {
83412
84967
  if (capletId === "code_mode") return await executeCodeModeRunNative(this, request, this.codeModeSessions);
83413
- if (this.localCanExecute(capletId)) return await this.local.execute(capletId, request);
83414
- return await this.remote.execute(capletId, request);
84968
+ const route = this.routes.get(capletId);
84969
+ if (route?.service === "local") return await this.local.execute(route.capletId, request);
84970
+ if (route?.service === "remote") return await this.executeRemote(route.capletId, request);
84971
+ const diagnostic = this.namespaceDiagnostics.get(capletId);
84972
+ if (diagnostic) throw new CapletsError("CAPLET_NAMESPACE_COLLISION", diagnostic.hint, diagnostic);
84973
+ return await this.executeRemote(capletId, request);
83415
84974
  }
83416
84975
  codeModeService() {
83417
84976
  return {
@@ -83431,6 +84990,8 @@ var CompositeNativeCapletsService = class {
83431
84990
  this.batchingReload = false;
83432
84991
  if (remoteReloaded === void 0 || localReloaded === void 0) return false;
83433
84992
  if (localReloaded) await this.presence?.updateAllowedCapletIds(this.local.listTools().map((tool) => tool.caplet));
84993
+ this.telemetry.config = telemetryConfigFromNativeOptions(this.options);
84994
+ this.startPresence();
83434
84995
  this.updateMergedTools();
83435
84996
  return remoteReloaded || localReloaded;
83436
84997
  }
@@ -83448,19 +85009,23 @@ var CompositeNativeCapletsService = class {
83448
85009
  await Promise.all([
83449
85010
  this.remote.close(),
83450
85011
  this.local.close(),
83451
- this.presence?.close()
85012
+ this.presence?.close(),
85013
+ this.ownsTelemetryDispatcher ? this.telemetry.dispatcher.shutdown() : void 0
83452
85014
  ]);
83453
85015
  }
83454
- async replaceRemote(remote, presence) {
85016
+ async replaceRemote(remote, remoteIdentityOrPresence, presence) {
85017
+ const remoteIdentity = typeof remoteIdentityOrPresence === "string" ? remoteIdentityOrPresence : this.remoteIdentity;
85018
+ const nextPresence = typeof remoteIdentityOrPresence === "string" ? presence : remoteIdentityOrPresence;
83455
85019
  if (this.closed) {
83456
- await Promise.all([remote.close(), presence?.close()]);
85020
+ await Promise.all([remote.close(), nextPresence?.close()]);
83457
85021
  return;
83458
85022
  }
83459
85023
  const previousRemote = this.remote;
83460
85024
  const previousPresence = this.presence;
83461
85025
  this.unsubscribeRemote();
83462
85026
  this.remote = remote;
83463
- this.presence = presence;
85027
+ this.remoteIdentity = remoteIdentity;
85028
+ this.presence = nextPresence;
83464
85029
  this.unsubscribeRemote = this.remote.onToolsChanged(() => this.updateMergedTools());
83465
85030
  await Promise.all([previousRemote.close(), previousPresence?.close()]);
83466
85031
  if (this.closed) return;
@@ -83469,30 +85034,145 @@ var CompositeNativeCapletsService = class {
83469
85034
  }
83470
85035
  updateMergedTools() {
83471
85036
  if (this.closed || this.batchingReload) return;
83472
- const tools = this.mergeTools();
83473
- if (JSON.stringify(tools) === JSON.stringify(this.tools)) return;
83474
- this.tools = tools;
85037
+ const merged = this.mergeTools();
85038
+ if (JSON.stringify(merged.tools) === JSON.stringify(this.tools)) {
85039
+ this.routes = merged.routes;
85040
+ this.namespaceDiagnostics = merged.namespaceDiagnostics;
85041
+ return;
85042
+ }
85043
+ this.tools = merged.tools;
85044
+ this.routes = merged.routes;
85045
+ this.namespaceDiagnostics = merged.namespaceDiagnostics;
83475
85046
  for (const listener of this.listeners) try {
83476
85047
  listener(this.listTools());
83477
85048
  } catch (error) {
83478
85049
  writeErr(this.options, `Caplets tools-changed listener failed: ${errorMessage(error)}\n`);
83479
85050
  }
83480
85051
  }
85052
+ async executeRemote(capletId, request) {
85053
+ const started = Date.now();
85054
+ try {
85055
+ const result = await this.remote.execute(capletId, request);
85056
+ this.captureRemoteToolActivation(request, result, started);
85057
+ return result;
85058
+ } catch (error) {
85059
+ const result = errorResult(error);
85060
+ this.captureRemoteReliabilityError(request, result);
85061
+ this.captureRemoteToolActivation(request, result, started);
85062
+ throw error;
85063
+ }
85064
+ }
85065
+ captureRemoteToolActivation(request, result, started) {
85066
+ captureRuntimeTelemetryEvent(this.telemetry, "caplets_tool_activation", {
85067
+ command_family: "native",
85068
+ ...toolActivationProperties({
85069
+ config: this.telemetry.config,
85070
+ caplet: void 0,
85071
+ operation: operationFromNativeRequest(request),
85072
+ exposureMode: "direct",
85073
+ result,
85074
+ durationMs: Date.now() - started
85075
+ })
85076
+ }).catch(() => void 0);
85077
+ }
85078
+ captureRemoteReliabilityError(request, result) {
85079
+ captureRuntimeReliabilityEvent(this.telemetry, {
85080
+ command_family: "native",
85081
+ ...runtimeFailureTelemetryProperties({
85082
+ operation: operationFromNativeRequest(request),
85083
+ exposureMode: "direct",
85084
+ result
85085
+ })
85086
+ }).catch(() => void 0);
85087
+ }
83481
85088
  mergeTools() {
83482
85089
  const allLocalTools = this.local.listTools();
83483
85090
  const allRemoteTools = this.remote.listTools();
83484
85091
  const remoteCodeModeTools = remoteCodeModeCallableNativeTools(allRemoteTools);
83485
85092
  const remoteIds = remoteSuppressedCapletIds(allRemoteTools, remoteCodeModeTools);
83486
- const localTools = allLocalTools.filter((tool) => tool.codeModeRun !== true && !remoteIds.has(tool.sourceCaplet ?? tool.caplet));
85093
+ const unsuppressedLocalTools = allLocalTools.filter((tool) => tool.codeModeRun !== true && !remoteIds.has(tool.sourceCaplet ?? tool.caplet));
83487
85094
  this.warnShadowedLocalCaplets(allLocalTools, remoteIds);
83488
- const localCodeModeTools = codeModeCallableNativeTools(allLocalTools, { fallbackToVisible: false }).filter((tool) => !remoteIds.has(tool.caplet));
83489
- const mergedTools = [...allRemoteTools.filter((tool) => tool.codeModeRun !== true), ...localTools];
83490
- const codeModeTools = [...remoteCodeModeTools, ...localCodeModeTools];
83491
- return [...mergedTools, ...codeModeTools.length > 0 ? [codeModeRunNativeTool(codeModeTools)] : []];
85095
+ const unsuppressedLocalCodeModeTools = codeModeCallableNativeTools(allLocalTools, { fallbackToVisible: false }).filter((tool) => !remoteIds.has(tool.caplet));
85096
+ const remoteTools = allRemoteTools.filter((tool) => tool.codeModeRun !== true);
85097
+ const resolved = this.resolveVisibleToolIds(remoteTools, unsuppressedLocalTools, remoteCodeModeTools, unsuppressedLocalCodeModeTools);
85098
+ const codeModeTools = [...resolved.remoteCodeModeTools, ...resolved.localCodeModeTools];
85099
+ return {
85100
+ tools: [
85101
+ ...resolved.remoteTools,
85102
+ ...resolved.localTools,
85103
+ ...codeModeTools.length > 0 ? [codeModeRunNativeTool(codeModeTools)] : []
85104
+ ],
85105
+ routes: resolved.routes,
85106
+ namespaceDiagnostics: resolved.namespaceDiagnostics
85107
+ };
83492
85108
  }
83493
- localCanExecute(capletId) {
83494
- const remoteIds = remoteSuppressedCapletIds(this.remote.listTools());
83495
- return localExecutionKeys(this.local.listTools(), capletId).some((key) => !remoteIds.has(key));
85109
+ resolveVisibleToolIds(remoteTools, localTools, remoteCodeModeTools, localCodeModeTools) {
85110
+ const resolution = resolveNamespaceExposure(nativeNamespaceEntries([{
85111
+ service: "remote",
85112
+ tools: [...remoteTools, ...remoteCodeModeTools]
85113
+ }, {
85114
+ service: "local",
85115
+ tools: [...localTools, ...localCodeModeTools]
85116
+ }], {
85117
+ ...nativeNamespaceContext(this.options),
85118
+ remoteIdentity: this.remoteIdentity
85119
+ }));
85120
+ const namespacedRecords = resolution.visibleRecords.filter((record) => record.namespaced);
85121
+ const namespacedBaseIds = new Set(namespacedRecords.map((record) => record.baseId));
85122
+ const diagnosticBaseIds = new Set(resolution.unavailableDiagnostics.map((diagnostic) => diagnostic.requestedId));
85123
+ const routes = /* @__PURE__ */ new Map();
85124
+ const namespaceDiagnostics = new Map(resolution.suppressedBareIds);
85125
+ for (const diagnostic of resolution.unavailableDiagnostics) namespaceDiagnostics.set(diagnostic.requestedId, diagnostic);
85126
+ const alternativesByBaseId = /* @__PURE__ */ new Map();
85127
+ const staleIdsByBaseId = /* @__PURE__ */ new Map();
85128
+ const setRoute = (visibleCapletId, route, overwrite) => {
85129
+ if (overwrite || !routes.has(visibleCapletId)) routes.set(visibleCapletId, route);
85130
+ };
85131
+ const rewrite = (service, tools, overwrite) => {
85132
+ const rewritten = [];
85133
+ for (const tool of tools) {
85134
+ const baseId = sourceBaseId(tool);
85135
+ if (diagnosticBaseIds.has(baseId)) continue;
85136
+ if (!namespacedBaseIds.has(baseId)) {
85137
+ rewritten.push(tool);
85138
+ setRoute(tool.caplet, {
85139
+ service,
85140
+ capletId: tool.caplet
85141
+ }, overwrite);
85142
+ continue;
85143
+ }
85144
+ const record = namespacedRecords.find((candidate) => candidate.baseId === baseId && candidate.route.service === service);
85145
+ if (!record) continue;
85146
+ const visibleTool = renameNativeTool(tool, record.id);
85147
+ rewritten.push(visibleTool);
85148
+ addMapSetValue(alternativesByBaseId, baseId, visibleTool.caplet);
85149
+ if (tool.caplet !== visibleTool.caplet) addMapSetValue(staleIdsByBaseId, baseId, tool.caplet);
85150
+ setRoute(visibleTool.caplet, {
85151
+ service,
85152
+ capletId: tool.caplet
85153
+ }, overwrite);
85154
+ }
85155
+ return rewritten;
85156
+ };
85157
+ const remoteVisibleTools = rewrite("remote", remoteTools, false);
85158
+ const localVisibleTools = rewrite("local", localTools, true);
85159
+ const remoteVisibleCodeModeTools = rewrite("remote", remoteCodeModeTools, false);
85160
+ const localVisibleCodeModeTools = rewrite("local", localCodeModeTools, true);
85161
+ for (const [baseId, alternatives] of alternativesByBaseId) {
85162
+ const baseDiagnostic = resolution.suppressedBareIds.get(baseId);
85163
+ if (!baseDiagnostic) continue;
85164
+ const alternativeList = [...alternatives];
85165
+ namespaceDiagnostics.set(baseId, namespaceDiagnosticWithAlternatives(baseId, baseDiagnostic, alternativeList));
85166
+ for (const staleId of staleIdsByBaseId.get(baseId) ?? []) namespaceDiagnostics.set(staleId, namespaceDiagnosticWithAlternatives(staleId, baseDiagnostic, alternativeList));
85167
+ }
85168
+ return {
85169
+ remoteTools: remoteVisibleTools,
85170
+ localTools: localVisibleTools,
85171
+ remoteCodeModeTools: remoteVisibleCodeModeTools,
85172
+ localCodeModeTools: localVisibleCodeModeTools,
85173
+ routes,
85174
+ namespaceDiagnostics
85175
+ };
83496
85176
  }
83497
85177
  warnShadowedLocalCaplets(localTools, remoteIds) {
83498
85178
  const localIds = /* @__PURE__ */ new Set([...localTools.filter((tool) => tool.codeModeRun !== true).map((tool) => tool.sourceCaplet ?? tool.caplet), ...codeModeCallableNativeTools(localTools, { fallbackToVisible: false }).map((tool) => tool.caplet)]);
@@ -83513,47 +85193,256 @@ var CompositeNativeCapletsService = class {
83513
85193
  }
83514
85194
  startPresence() {
83515
85195
  this.presence?.start().catch((error) => {
83516
- writeErr(this.options, `Could not register Caplets Cloud Project Binding: ${errorMessage(error)}\n`);
85196
+ writeErr(this.options, `Could not start upstream Project Binding: ${errorMessage(error)}\n`);
83517
85197
  });
83518
85198
  }
83519
85199
  };
85200
+ function addMapSetValue(map, key, value) {
85201
+ let values = map.get(key);
85202
+ if (!values) {
85203
+ values = /* @__PURE__ */ new Set();
85204
+ map.set(key, values);
85205
+ }
85206
+ values.add(value);
85207
+ }
85208
+ function namespaceDiagnosticWithAlternatives(requestedId, diagnostic, alternatives) {
85209
+ return {
85210
+ ...diagnostic,
85211
+ requestedId,
85212
+ alternatives,
85213
+ hint: `Caplet '${requestedId}' is unavailable because namespace shadowing exposes qualified alternatives: ${alternatives.join(", ")}.`
85214
+ };
85215
+ }
85216
+ function nativeNamespaceContext(options) {
85217
+ const configPath = options.configPath ?? resolveConfigPath();
85218
+ const projectConfigPath = options.projectConfigPath ?? resolveProjectConfigPath();
85219
+ let namespaceAliases = parseConfig({}).namespaceAliases;
85220
+ try {
85221
+ namespaceAliases = loadLocalOverlayConfigWithSources(configPath, projectConfigPath).config.namespaceAliases;
85222
+ } catch {}
85223
+ return {
85224
+ localIdentity: `local:${configPath}\0${projectConfigPath}`,
85225
+ namespaceAliases
85226
+ };
85227
+ }
85228
+ function nativeNamespaceEntries(groups, identities) {
85229
+ const entries = /* @__PURE__ */ new Map();
85230
+ for (const group of groups) {
85231
+ const byBaseId = /* @__PURE__ */ new Map();
85232
+ for (const tool of group.tools) {
85233
+ const baseId = sourceBaseId(tool);
85234
+ byBaseId.set(baseId, [...byBaseId.get(baseId) ?? [], tool]);
85235
+ }
85236
+ for (const [baseId, tools] of byBaseId) {
85237
+ const service = group.service;
85238
+ entries.set(`${service}:${baseId}`, {
85239
+ baseId,
85240
+ sourceKind: service === "local" ? "local" : "upstream",
85241
+ sourceLabel: service === "local" ? "local" : "remote",
85242
+ namespaceAlias: service === "local" ? identities.namespaceAliases.local : identities.namespaceAliases.upstreams[identities.remoteIdentity],
85243
+ durableSourceIdentity: service === "local" ? identities.localIdentity : identities.remoteIdentity,
85244
+ shadowing: aggregateShadowing(tools),
85245
+ route: {
85246
+ service,
85247
+ baseId
85248
+ }
85249
+ });
85250
+ }
85251
+ }
85252
+ return [...entries.values()];
85253
+ }
85254
+ function aggregateShadowing(tools) {
85255
+ if (tools.some((tool) => (tool.shadowing ?? "forbid") === "forbid")) return "forbid";
85256
+ if (tools.some((tool) => tool.shadowing === "namespace")) return "namespace";
85257
+ return "allow";
85258
+ }
85259
+ function sourceBaseId(tool) {
85260
+ return tool.sourceCaplet ?? tool.caplet;
85261
+ }
85262
+ function renameNativeTool(tool, visibleBaseId) {
85263
+ const baseId = sourceBaseId(tool);
85264
+ const visibleCapletId = tool.sourceCaplet && tool.caplet.startsWith(`${baseId}__`) ? `${visibleBaseId}${tool.caplet.slice(baseId.length)}` : visibleBaseId;
85265
+ const operationName = tool.sourceCaplet && tool.caplet.startsWith(`${baseId}__`) ? tool.caplet.slice(baseId.length + 2) : void 0;
85266
+ const toolName = operationName ? nativeDirectToolName(visibleBaseId, operationName) : nativeCapletToolName(visibleCapletId);
85267
+ return {
85268
+ ...tool,
85269
+ caplet: visibleCapletId,
85270
+ ...tool.sourceCaplet ? { sourceCaplet: visibleBaseId } : {},
85271
+ toolName
85272
+ };
85273
+ }
83520
85274
  function remoteCodeModeCallableNativeTools(tools) {
83521
85275
  return codeModeCallableNativeTools(tools, { fallbackToVisible: true });
83522
85276
  }
83523
85277
  function remoteSuppressedCapletIds(allRemoteTools, remoteCodeModeTools = remoteCodeModeCallableNativeTools(allRemoteTools)) {
83524
- return new Set([...allRemoteTools.filter((tool) => tool.codeModeRun !== true && tool.shadowing !== "allow").map((tool) => tool.sourceCaplet ?? tool.caplet), ...remoteCodeModeTools.filter((tool) => tool.shadowing !== "allow").map((tool) => tool.caplet)].filter((caplet) => caplet !== nativeCodeModeToolId));
85278
+ return new Set([...allRemoteTools.filter((tool) => tool.codeModeRun !== true && (tool.shadowing ?? "forbid") === "forbid").map((tool) => tool.sourceCaplet ?? tool.caplet), ...remoteCodeModeTools.filter((tool) => (tool.shadowing ?? "forbid") === "forbid").map((tool) => tool.caplet)].filter((caplet) => caplet !== nativeCodeModeToolId));
85279
+ }
85280
+ function createProjectBindingSessionManager(cloud, remoteOptions, local, options) {
85281
+ const allowedCapletIds = local.listTools().map((tool) => tool.caplet);
85282
+ if (cloud) {
85283
+ const projectRoot = cloud.projectRoot ?? findProjectRoot();
85284
+ const cloudFetch = options.remote?.fetch;
85285
+ return new ProjectBindingSessionManager({
85286
+ client: new CapletsCloudClient({
85287
+ baseUrl: cloud.url,
85288
+ accessToken: cloud.accessToken,
85289
+ ...cloudFetch ? { fetch: cloudFetch } : {}
85290
+ }),
85291
+ workspaceId: cloud.workspaceId,
85292
+ projectRoot,
85293
+ projectFingerprint: fingerprintProjectRoot(projectRoot),
85294
+ projectFiles: projectSyncFiles(projectRoot),
85295
+ allowedCapletIds,
85296
+ heartbeatIntervalMs: cloud.heartbeatIntervalMs,
85297
+ onError: (error) => {
85298
+ writeErr(options, `Caplets Cloud Project Binding heartbeat failed: ${errorMessage(error)}\n`);
85299
+ }
85300
+ });
85301
+ }
85302
+ if (!options.projectRoot || !isLoopbackRemote(remoteOptions)) return;
85303
+ return new RemoteProjectBindingSessionManager({
85304
+ attachUrl: remoteOptions.url,
85305
+ requestInit: remoteOptions.requestInit,
85306
+ fetch: remoteOptions.fetch,
85307
+ projectRoot: options.projectRoot,
85308
+ allowedCapletIds,
85309
+ heartbeatIntervalMs: 3e4,
85310
+ writeErr: options.writeErr
85311
+ });
83525
85312
  }
83526
- function localExecutionKeys(tools, capletId) {
83527
- const keys = [];
83528
- for (const tool of tools) {
83529
- if (tool.codeModeRun) {
83530
- for (const caplet of tool.codeModeCaplets ?? []) if (caplet.id === capletId) keys.push(caplet.id);
83531
- continue;
85313
+ var RemoteProjectBindingSessionManager = class {
85314
+ options;
85315
+ bindingId;
85316
+ sessionId;
85317
+ allowedCapletIds;
85318
+ heartbeatTimer;
85319
+ startPromise;
85320
+ unsupported = false;
85321
+ constructor(options) {
85322
+ this.options = options;
85323
+ this.allowedCapletIds = [...options.allowedCapletIds];
85324
+ }
85325
+ async start() {
85326
+ if (this.unsupported) return;
85327
+ if (!this.startPromise) {
85328
+ const start = this.register();
85329
+ this.startPromise = start;
85330
+ start.catch((error) => {
85331
+ if (isUnsupportedProjectBinding(error)) this.unsupported = true;
85332
+ if (this.startPromise === start) this.startPromise = void 0;
85333
+ });
83532
85334
  }
83533
- if (tool.caplet === capletId || tool.sourceCaplet === capletId) keys.push(tool.sourceCaplet ?? tool.caplet);
85335
+ return await this.startPromise;
83534
85336
  }
83535
- return keys;
83536
- }
83537
- function createProjectBindingSessionManager(cloud, local, options) {
83538
- if (!cloud) return;
83539
- const projectRoot = cloud.projectRoot ?? findProjectRoot();
83540
- const cloudFetch = options.remote?.fetch;
83541
- return new ProjectBindingSessionManager({
83542
- client: new CapletsCloudClient({
83543
- baseUrl: cloud.url,
83544
- accessToken: cloud.accessToken,
83545
- ...cloudFetch ? { fetch: cloudFetch } : {}
83546
- }),
83547
- workspaceId: cloud.workspaceId,
83548
- projectRoot,
83549
- projectFingerprint: fingerprintProjectRoot(projectRoot),
83550
- projectFiles: projectSyncFiles(projectRoot),
83551
- allowedCapletIds: local.listTools().map((tool) => tool.caplet),
83552
- heartbeatIntervalMs: cloud.heartbeatIntervalMs,
83553
- onError: (error) => {
83554
- writeErr(options, `Caplets Cloud Project Binding heartbeat failed: ${errorMessage(error)}\n`);
85337
+ async close() {
85338
+ await this.startPromise?.catch(() => void 0);
85339
+ this.stopHeartbeat();
85340
+ const bindingId = this.bindingId;
85341
+ this.bindingId = void 0;
85342
+ const sessionId = this.sessionId;
85343
+ this.sessionId = void 0;
85344
+ if (!bindingId || !sessionId) return;
85345
+ await this.fetchJson(projectBindingUrl(this.options.attachUrl, bindingId, "session"), {
85346
+ method: "DELETE",
85347
+ body: {
85348
+ sessionId,
85349
+ terminalReason: {
85350
+ code: "completed",
85351
+ message: "Binding Session completed."
85352
+ }
85353
+ }
85354
+ }).catch(() => void 0);
85355
+ }
85356
+ async updateAllowedCapletIds(allowedCapletIds) {
85357
+ this.allowedCapletIds = [...allowedCapletIds];
85358
+ await this.startPromise?.catch(() => void 0);
85359
+ if (!this.bindingId || !this.sessionId) return;
85360
+ await this.heartbeat().catch(() => void 0);
85361
+ }
85362
+ async register() {
85363
+ const projectFingerprint = fingerprintProjectRoot(this.options.projectRoot);
85364
+ const response = await this.fetchJson(projectBindingUrl(this.options.attachUrl, "sessions"), {
85365
+ method: "POST",
85366
+ body: {
85367
+ projectRoot: this.options.projectRoot,
85368
+ projectFingerprint,
85369
+ allowedCapletIds: this.allowedCapletIds
85370
+ }
85371
+ });
85372
+ if (!response.binding?.bindingId || !response.sessionId) throw new CapletsError("SERVER_UNAVAILABLE", "Project Binding session response was invalid.");
85373
+ this.bindingId = response.binding.bindingId;
85374
+ this.sessionId = response.sessionId;
85375
+ this.startHeartbeat();
85376
+ }
85377
+ startHeartbeat() {
85378
+ this.stopHeartbeat();
85379
+ this.heartbeatTimer = setInterval(() => {
85380
+ this.heartbeat().catch((error) => {
85381
+ this.disconnect();
85382
+ this.options.writeErr?.(`Remote Project Binding heartbeat failed: ${errorMessage(error)}\n`);
85383
+ });
85384
+ }, this.options.heartbeatIntervalMs);
85385
+ this.heartbeatTimer.unref?.();
85386
+ }
85387
+ stopHeartbeat() {
85388
+ if (!this.heartbeatTimer) return;
85389
+ clearInterval(this.heartbeatTimer);
85390
+ this.heartbeatTimer = void 0;
85391
+ }
85392
+ disconnect() {
85393
+ this.stopHeartbeat();
85394
+ this.bindingId = void 0;
85395
+ this.sessionId = void 0;
85396
+ this.startPromise = void 0;
85397
+ }
85398
+ async heartbeat() {
85399
+ if (!this.bindingId || !this.sessionId) return;
85400
+ await this.fetchJson(projectBindingUrl(this.options.attachUrl, this.bindingId, "heartbeat"), {
85401
+ method: "POST",
85402
+ body: {
85403
+ sessionId: this.sessionId,
85404
+ state: "ready",
85405
+ syncState: "idle",
85406
+ allowedCapletIds: this.allowedCapletIds
85407
+ }
85408
+ });
85409
+ }
85410
+ async fetchJson(url, input) {
85411
+ const headers = new Headers(this.options.requestInit.headers);
85412
+ headers.set("content-type", "application/json");
85413
+ const response = await (this.options.fetch ?? fetch)(url, {
85414
+ ...this.options.requestInit,
85415
+ method: input.method,
85416
+ headers,
85417
+ body: JSON.stringify(input.body)
85418
+ });
85419
+ if (!response.ok) {
85420
+ let payload;
85421
+ try {
85422
+ payload = await response.json();
85423
+ } catch {
85424
+ payload = void 0;
85425
+ }
85426
+ const error = isRecord(payload) && isRecord(payload.error) ? payload.error : void 0;
85427
+ if (error?.code === "UNSUPPORTED_CAPABILITY" && typeof error.message === "string") throw new CapletsError("UNSUPPORTED_CAPABILITY", error.message);
85428
+ throw new CapletsError("SERVER_UNAVAILABLE", `Project Binding request failed (${response.status}).`);
83555
85429
  }
83556
- });
85430
+ return await response.json().catch(() => ({}));
85431
+ }
85432
+ };
85433
+ function isUnsupportedProjectBinding(error) {
85434
+ return isRecord(error) && error.code === "UNSUPPORTED_CAPABILITY";
85435
+ }
85436
+ function projectBindingUrl(attachUrl, ...segments) {
85437
+ const url = new URL(attachUrl);
85438
+ url.pathname = [
85439
+ url.pathname.replace(/\/+$/u, ""),
85440
+ "project-bindings",
85441
+ ...segments.map(encodeURIComponent)
85442
+ ].join("/");
85443
+ url.search = "";
85444
+ url.hash = "";
85445
+ return url;
83557
85446
  }
83558
85447
  function createLocalOverlayConfigLoader(options) {
83559
85448
  let hasLoaded = false;
@@ -83591,4 +85480,4 @@ function errorMessage(error) {
83591
85480
  return error instanceof Error ? error.message : String(error);
83592
85481
  }
83593
85482
  //#endregion
83594
- export { resolveExposure as $, mergeCapabilities as $t, nativeCapletPromptGuidance as A, isJSONRPCRequest as An, runOAuthFlow as At, CodeModeSessionManager as B, safeParse as Bn, defaultConfigBaseDir as Bt, resolveHostedCloudRemote as C, ReadResourceRequestSchema as Cn, validateCapletFile as Ct, isLoopbackHost as D, assertCompleteRequestResourceTemplate as Dn, markdownStructuredContent as Dt, controlUrlForBase as E, assertCompleteRequestPrompt as En, markdownCallToolResultContent as Et, nativeCodeModeToolName as F, getSchemaDescription as Fn, readTokenBundle as Ft, CodeModeJournalStore as G, resolveProjectCapletsRoot as Gt, diagnoseCodeModeTypeScript as H, __exportAll as Hn, defaultStateBaseDir as Ht, codeModeRunInputSchema as I, isSchemaOptional as In, DEFAULT_AUTH_DIR as It, codeModeDeclarationHash as J, serializeMessage as Jt, CodeModeLogStore as K, resolveProjectConfigPath as Kt, codeModeRunParamsSchema as L, isZ4Schema as Ln, DEFAULT_COMPLETION_CACHE_DIR as Lt, nativeCapletToolName as M, getLiteralValue as Mn, startOAuthFlow as Mt, nativeCapletsSystemGuidance as N, getObjectShape as Nn, deleteTokenBundle as Nt, parseServerBaseUrl as O, isInitializeRequest as On, refreshOAuthTokenBundle as Ot, nativeCodeModeToolId as P, getParseErrorMessage as Pn, isTokenBundleExpired as Pt, CapletsEngine as Q, Protocol as Qt, emptyCodeModeRunMeta as R, normalizeObjectSchema as Rn, DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR as Rt, resolveCapletsRemote as S, McpError as Sn, discoverCapletFiles as St, appendBasePath as T, SetLevelRequestSchema as Tn, hasRenderableStructuredContent as Tt, createCodeModeCapletsApi as U, resolveCapletsRoot as Ut, QuickJsCodeModeSandbox as V, safeParseAsync as Vn, defaultConfigPath as Vt, listCodeModeCallableCaplets as W, resolveConfigPath as Wt, generateCodeModeRunToolDescription as X, assertToolsCallTaskCapability as Xt, generateCodeModeDeclarations as Y, assertClientRequestTaskCapability as Yt, minifyCodeModeDeclarationText as Z, AjvJsonSchemaValidator as Zt, CapletsCloudClient as _, ListResourceTemplatesRequestSchema as _n, FileVaultStore as _t, CloudAuthStore as a, CreateMessageResultWithToolsSchema as an, ServerRegistry as at, isCapletsCloudUrl as b, ListToolsRequestSchema as bn, decryptVaultValue as bt, redactedCloudAuthStatus as c, ElicitResultSchema as cn, loadConfig as ct, projectBindingError as d, GetPromptRequestSchema as dn, loadLocalOverlayConfigWithSources as dt, toJsonSchemaCompat as en, decodeDirectResourceUri as et, projectBindingRecovery as f, InitializeRequestSchema as fn, loadProjectConfig as ft, buildProjectSyncManifest as g, ListPromptsRequestSchema as gn, vaultStoreForAuthDir as gt, createSdkRemoteCapletsClient as h, LATEST_PROTOCOL_VERSION as hn, vaultResolverForAuthDir as ht, createRemoteProfileStore as i, CreateMessageResultSchema as in, handleServerTool as it, nativeCapletToolDescription as j, isJSONRPCResultResponse as jn, startGenericOAuthFlow as jt, resolveCapletsServer as k, isJSONRPCErrorResponse as kn, runGenericOAuthFlow as kt, PROJECT_BINDING_ERROR_CODES as l, EmptyResultSchema as ln, loadConfigWithSources as lt, RemoteNativeCapletsService as m, JSONRPCMessageSchema as mn, vaultBootstrapResolver as mt, resolveRemoteSelection as n, CallToolResultSchema as nn, findProjectRoot as nt, cloudAuthPath as o, CreateTaskResultSchema as on, capabilityDescription as ot, CloudAuthClient as p, InitializedNotificationSchema as pn, parseConfig as pt, redactCodeModeLogText as q, ReadBuffer as qt, cloudCredentialsFromRemoteProfile as r, CompleteRequestSchema as rn, fingerprintProjectRoot as rt, migrateCredentials as s, DEFAULT_NEGOTIATED_PROTOCOL_VERSION as sn, GoogleDiscoveryManager as st, createNativeCapletsService as t, CallToolRequestSchema as tn, directResourceUriMatchesTemplate as tt, ProjectBindingError as u, ErrorCode as un, loadGlobalConfig as ut, resolveNativeCapletsServiceOptions as v, ListResourcesRequestSchema as vn, VAULT_MAX_VALUE_BYTES as vt, resolveRemoteMode as w, SUPPORTED_PROTOCOL_VERSIONS as wn, loadCapletFilesFromMap as wt, normalizeRemoteProfileHostUrl as x, LoggingLevelSchema as xn, encryptVaultValue as xt, hostedCloudWorkspaceFromRemoteUrl as y, ListRootsResultSchema as yn, validateVaultKeyName as yt, runCodeMode as z, objectFromShape as zn, defaultCacheBaseDir as zt };
85483
+ export { redactCodeModeLogText as $, getParseErrorMessage as $n, readTokenBundle as $t, resolveRemoteMode as A, GetPromptRequestSchema as An, loadProjectConfig as At, nativeCodeModeToolId as B, LoggingLevelSchema as Bn, discoverCapletFiles as Bt, CapletsCloudClient as C, CreateMessageResultSchema as Cn, ServerRegistry as Ct, normalizeRemoteProfileHostUrl as D, ElicitResultSchema as Dn, loadConfigWithSources as Dt, isCapletsCloudUrl as E, DEFAULT_NEGOTIATED_PROTOCOL_VERSION as En, loadConfig as Et, resolveCapletsServer as F, ListPromptsRequestSchema as Fn, FileVaultStore as Ft, runCodeMode as G, assertCompleteRequestPrompt as Gn, markdownStructuredContent as Gt, codeModeRunInputSchema as H, ReadResourceRequestSchema as Hn, loadCapletFilesFromMap as Ht, nativeCapletPromptGuidance as I, ListResourceTemplatesRequestSchema as In, VAULT_MAX_VALUE_BYTES as It, diagnoseCodeModeTypeScript as J, isJSONRPCErrorResponse as Jn, runOAuthFlow as Jt, CodeModeSessionManager as K, assertCompleteRequestResourceTemplate as Kn, refreshOAuthTokenBundle as Kt, nativeCapletToolDescription as L, ListResourcesRequestSchema as Ln, validateVaultKeyName as Lt, controlUrlForBase as M, InitializedNotificationSchema as Mn, vaultBootstrapResolver as Mt, isLoopbackHost as N, JSONRPCMessageSchema as Nn, vaultResolverForAuthDir as Nt, resolveCapletsRemote as O, EmptyResultSchema as On, loadGlobalConfig as Ot, parseServerBaseUrl as P, LATEST_PROTOCOL_VERSION as Pn, vaultStoreForAuthDir as Pt, CodeModeLogStore as Q, getObjectShape as Qn, isTokenBundleExpired as Qt, nativeCapletToolName as R, ListRootsResultSchema as Rn, decryptVaultValue as Rt, buildProjectSyncManifest as S, CompleteRequestSchema as Sn, handleServerTool as St, hostedCloudWorkspaceFromRemoteUrl as T, CreateTaskResultSchema as Tn, GoogleDiscoveryManager as Tt, codeModeRunParamsSchema as U, SUPPORTED_PROTOCOL_VERSIONS as Un, hasRenderableStructuredContent as Ut, nativeCodeModeToolName as V, McpError as Vn, validateCapletFile as Vt, emptyCodeModeRunMeta as W, SetLevelRequestSchema as Wn, markdownCallToolResultContent as Wt, listCodeModeCallableCaplets as X, isJSONRPCResultResponse as Xn, startOAuthFlow as Xt, createCodeModeCapletsApi as Y, isJSONRPCRequest as Yn, startGenericOAuthFlow as Yt, CodeModeJournalStore as Z, getLiteralValue as Zn, deleteTokenBundle as Zt, attachErrorResponse as _, Protocol as _n, rotateTelemetryIdentity as _t, CloudAuthStore as a, defaultConfigPath as an, safeParse as ar, version as at, invokeAttachExport$1 as b, CallToolRequestSchema as bn, findProjectRoot as bt, redactedCloudAuthStatus as c, resolveCapletsRoot as cn, buildProductTelemetryEvent as ct, projectBindingError as d, resolveProjectConfigPath as dn, maybePrintTelemetryNotice as dt, DEFAULT_AUTH_DIR as en, getSchemaDescription as er, codeModeDeclarationHash as et, projectBindingRecovery as f, ReadBuffer as fn, resolveTelemetryState as ft, CAPLETS_ATTACH_SESSION_HEADER as g, AjvJsonSchemaValidator as gn, readTelemetryNotice as gt, createSdkRemoteCapletsClient as h, assertToolsCallTaskCapability as hn, readTelemetryIdentity as ht, createRemoteProfileStore as i, defaultConfigBaseDir as in, objectFromShape as ir, CapletsEngine as it, appendBasePath as j, InitializeRequestSchema as jn, parseConfig as jt, resolveHostedCloudRemote as k, ErrorCode as kn, loadLocalOverlayConfigWithSources as kt, PROJECT_BINDING_ERROR_CODES as l, resolveConfigPath as ln, buildReliabilityTelemetryEvent as lt, RemoteNativeCapletsService as m, assertClientRequestTaskCapability as mn, readTelemetryDeliveryHealth as mt, resolveRemoteSelection as n, DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR as nn, isZ4Schema as nr, generateCodeModeRunToolDescription as nt, cloudAuthPath as o, defaultStateBaseDir as on, safeParseAsync as or, createTelemetryDispatcher as ot, CloudAuthClient as p, serializeMessage as pn, deleteTelemetryIdentity as pt, QuickJsCodeModeSandbox as q, isInitializeRequest as qn, runGenericOAuthFlow as qt, cloudCredentialsFromRemoteProfile as r, defaultCacheBaseDir as rn, normalizeObjectSchema as rr, minifyCodeModeDeclarationText as rt, migrateCredentials as s, defaultTelemetryStateDir as sn, TelemetryDebugSink as st, createNativeCapletsService as t, DEFAULT_COMPLETION_CACHE_DIR as tn, isSchemaOptional as tr, generateCodeModeDeclarations as tt, ProjectBindingError as u, resolveProjectCapletsRoot as un, durationBucket as ut, buildAttachProjection as v, mergeCapabilities as vn, resolveExposure as vt, resolveNativeCapletsServiceOptions as w, CreateMessageResultWithToolsSchema as wn, capabilityDescription as wt, invokeNativeAttachExport as x, CallToolResultSchema as xn, fingerprintProjectRoot as xt, buildNativeAttachProjection as y, toJsonSchemaCompat as yn, decodeDirectResourceUri as yt, nativeCapletsSystemGuidance as z, ListToolsRequestSchema as zn, encryptVaultValue as zt };