@caplets/core 0.21.1 → 0.23.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 (44) hide show
  1. package/dist/auth.d.ts +2 -1
  2. package/dist/caplet-files-bundle.d.ts +66 -0
  3. package/dist/caplet-sets.d.ts +2 -0
  4. package/dist/caplet-source.js +101 -4
  5. package/dist/cli/add.d.ts +10 -0
  6. package/dist/cli/auth.d.ts +24 -0
  7. package/dist/cli/commands.d.ts +1 -1
  8. package/dist/cli.d.ts +1 -1
  9. package/dist/code-mode/diagnostics-builtins.generated.d.ts +1 -0
  10. package/dist/code-mode/platform-entry.d.ts +1 -0
  11. package/dist/code-mode/platform-host.d.ts +6 -0
  12. package/dist/code-mode/platform-runtime.generated.d.ts +1 -0
  13. package/dist/code-mode/types.d.ts +1 -0
  14. package/dist/code-mode.js +18 -13
  15. package/dist/{completion-Cb-pshjL.js → completion-BC4BNWo0.js} +14 -2
  16. package/dist/config/paths.d.ts +2 -0
  17. package/dist/config-runtime.d.ts +15 -1
  18. package/dist/config-runtime.js +46 -0
  19. package/dist/config.d.ts +32 -1
  20. package/dist/engine.d.ts +3 -0
  21. package/dist/google-discovery/index.d.ts +5 -0
  22. package/dist/google-discovery/manager.d.ts +37 -0
  23. package/dist/google-discovery/operations.d.ts +32 -0
  24. package/dist/google-discovery/request.d.ts +5 -0
  25. package/dist/google-discovery/schema.d.ts +2 -0
  26. package/dist/google-discovery/types.d.ts +70 -0
  27. package/dist/http/response.d.ts +14 -0
  28. package/dist/http-actions.d.ts +3 -0
  29. package/dist/index.js +111 -26
  30. package/dist/media/artifacts.d.ts +24 -0
  31. package/dist/media/index.d.ts +2 -0
  32. package/dist/media/input.d.ts +29 -0
  33. package/dist/native/remote.d.ts +1 -0
  34. package/dist/native/service.d.ts +2 -0
  35. package/dist/native.js +1 -1
  36. package/dist/{observed-output-shapes-CL5MFXwM.js → observed-output-shapes-D2k2-q8K.js} +9 -0
  37. package/dist/observed-output-shapes.js +1 -1
  38. package/dist/openapi.d.ts +2 -0
  39. package/dist/registry.d.ts +6 -0
  40. package/dist/runtime-plan.js +1 -1
  41. package/dist/runtime.d.ts +2 -0
  42. package/dist/{service-lkrQheFA.js → service-CSRCJfpA.js} +1776 -215
  43. package/dist/tools.d.ts +2 -1
  44. package/package.json +9 -2
@@ -1,9 +1,9 @@
1
1
  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-C0PNPwjS.js";
2
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-DgxCzt-A.js";
3
3
  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-CL5MFXwM.js";
4
+ import { f as observedOutputShapeKey, i as observeOutputShape, r as normalizedObservableValue, t as usefulOutputSchema, u as FileObservedOutputShapeStore } from "./observed-output-shapes-D2k2-q8K.js";
5
5
  import { createRequire } from "node:module";
6
- import { accessSync, chmodSync, constants, existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, statSync, watch, writeFileSync } from "node:fs";
6
+ import { accessSync, chmodSync, constants, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, 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";
@@ -11,6 +11,7 @@ import { PassThrough } from "node:stream";
11
11
  import { createServer } from "node:http";
12
12
  import { createHash, randomBytes, randomUUID } from "node:crypto";
13
13
  import { homedir } from "node:os";
14
+ import { readFile } from "node:fs/promises";
14
15
  import ts from "typescript";
15
16
  import { getQuickJS, shouldInterruptAfterDeadline } from "quickjs-emscripten";
16
17
  import { Buffer as Buffer$1 } from "node:buffer";
@@ -17241,6 +17242,9 @@ function defaultConfigPath(env = process.env, home = homedir(), platform = proce
17241
17242
  function defaultAuthDir(env = process.env, home = homedir(), platform = process.platform) {
17242
17243
  return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "auth");
17243
17244
  }
17245
+ function defaultArtifactDir(env = process.env, home = homedir(), platform = process.platform) {
17246
+ return (platform === "win32" ? win32.join : posix.join)(defaultStateBaseDir(env, home, platform), "caplets", "artifacts");
17247
+ }
17244
17248
  function defaultCompletionCacheDir(env = process.env, home = homedir(), platform = process.platform) {
17245
17249
  const pathJoin = platform === "win32" ? win32.join : posix.join;
17246
17250
  return platform === "win32" ? pathJoin(defaultCacheBaseDir(env, home, platform), "caplets", "cache", "completions") : pathJoin(defaultCacheBaseDir(env, home, platform), "caplets", "completions");
@@ -17251,6 +17255,7 @@ function defaultObservedOutputShapeCacheDir(env = process.env, home = homedir(),
17251
17255
  }
17252
17256
  const DEFAULT_CONFIG_PATH = defaultConfigPath();
17253
17257
  const DEFAULT_AUTH_DIR = defaultAuthDir();
17258
+ const DEFAULT_ARTIFACT_DIR = defaultArtifactDir();
17254
17259
  const DEFAULT_COMPLETION_CACHE_DIR = defaultCompletionCacheDir();
17255
17260
  const DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR = defaultObservedOutputShapeCacheDir();
17256
17261
  const PROJECT_CONFIG_FILE = join(".caplets", "config.json");
@@ -17568,7 +17573,7 @@ async function startGenericOAuthFlow(target, options) {
17568
17573
  assertAllowedAuthUrl(authorizationEndpoint, "authorization endpoint", allowLoopbackHttp);
17569
17574
  assertAllowedAuthUrl(tokenEndpoint, "token endpoint", allowLoopbackHttp);
17570
17575
  const client = await resolveGenericClient(target, authConfig, metadata, redirectUri, allowLoopbackHttp);
17571
- const scope = scopesFor(authConfig);
17576
+ const scope = scopesFor(authConfig, target.resolvedScopes);
17572
17577
  const authorizationUrl = new URL(authorizationEndpoint);
17573
17578
  authorizationUrl.searchParams.set("response_type", "code");
17574
17579
  authorizationUrl.searchParams.set("client_id", client.clientId);
@@ -17617,6 +17622,7 @@ async function startGenericOAuthFlow(target, options) {
17617
17622
  metadata: redactSecrets({
17618
17623
  protectedResource: target.url ?? target.baseUrl ?? target.specUrl,
17619
17624
  authorizationServer: metadata,
17625
+ requestedScopes: scope?.split(/\s+/u).filter(Boolean),
17620
17626
  dynamicClient: client.dynamic ? { client_id: client.clientId } : void 0
17621
17627
  })
17622
17628
  }), options.authDir);
@@ -17645,7 +17651,7 @@ async function runGenericOAuthFlow(target, options = {}) {
17645
17651
  assertAllowedAuthUrl(authorizationEndpoint, "authorization endpoint", allowLoopbackHttp);
17646
17652
  assertAllowedAuthUrl(tokenEndpoint, "token endpoint", allowLoopbackHttp);
17647
17653
  const client = await resolveGenericClient(target, authConfig, metadata, redirectUri, allowLoopbackHttp);
17648
- const scope = scopesFor(authConfig);
17654
+ const scope = scopesFor(authConfig, target.resolvedScopes);
17649
17655
  const authorizationUrl = new URL(authorizationEndpoint);
17650
17656
  authorizationUrl.searchParams.set("response_type", "code");
17651
17657
  authorizationUrl.searchParams.set("client_id", client.clientId);
@@ -17695,6 +17701,7 @@ async function runGenericOAuthFlow(target, options = {}) {
17695
17701
  metadata: redactSecrets({
17696
17702
  protectedResource: target.url ?? target.baseUrl ?? target.specUrl,
17697
17703
  authorizationServer: metadata,
17704
+ requestedScopes: scope?.split(/\s+/u).filter(Boolean),
17698
17705
  dynamicClient: client.dynamic ? { client_id: client.clientId } : void 0
17699
17706
  })
17700
17707
  });
@@ -17903,7 +17910,7 @@ async function refreshGenericOAuthBundle(target, authConfig, bundle, authDir) {
17903
17910
  refreshToken: asString(tokenResponse.refresh_token) ?? bundle.refreshToken,
17904
17911
  tokenType: asString(tokenResponse.token_type) ?? bundle.tokenType,
17905
17912
  expiresAt: refreshedExpiresAt(tokenResponse.expires_in, bundle.expiresAt),
17906
- scope: asString(tokenResponse.scope) ?? bundle.scope ?? scopesFor(authConfig),
17913
+ scope: asString(tokenResponse.scope) ?? bundle.scope ?? scopesFor(authConfig, target.resolvedScopes),
17907
17914
  idToken: idToken ?? bundle.idToken,
17908
17915
  issuer: asString(idClaims?.iss) ?? bundle.issuer ?? metadata.issuer ?? authConfig.issuer,
17909
17916
  subject: asString(idClaims?.sub) ?? bundle.subject,
@@ -17969,7 +17976,7 @@ function assertAllowedAuthUrl(value, label, allowLoopbackHttp = false) {
17969
17976
  function assertTokenBundleMatchesTarget(bundle, target, authConfig) {
17970
17977
  const configuredClientId = authConfig.clientId ?? authConfig.clientMetadataUrl;
17971
17978
  const expectedOrigin = protectedResourceOrigin(target, authConfig);
17972
- if (bundle.authType !== authConfig.type || expectedOrigin && bundle.protectedResourceOrigin !== expectedOrigin || configuredClientId && bundle.clientId !== configuredClientId || authConfig.issuer && bundle.issuer !== authConfig.issuer) throw new CapletsError("AUTH_REQUIRED", `OAuth credentials for ${target.server} do not match the configured backend`, {
17979
+ if (bundle.authType !== authConfig.type || expectedOrigin && bundle.protectedResourceOrigin !== expectedOrigin || configuredClientId && bundle.clientId !== configuredClientId || authConfig.issuer && bundle.issuer !== authConfig.issuer || tokenBundleMissingScopes(bundle, authConfig, target.resolvedScopes)) throw new CapletsError("AUTH_REQUIRED", `OAuth credentials for ${target.server} do not match the configured backend`, {
17973
17980
  server: target.server,
17974
17981
  backend: target.backend,
17975
17982
  authType: authConfig.type,
@@ -17997,8 +18004,39 @@ function isLoopbackHttpUrl(value) {
17997
18004
  "::1"
17998
18005
  ].includes(url.hostname);
17999
18006
  }
18000
- function scopesFor(authConfig) {
18007
+ function tokenBundleMissingScopes(bundle, authConfig, resolvedScopes) {
18008
+ const required = requiredStoredScopes(authConfig, resolvedScopes);
18009
+ if (required.length === 0) return false;
18010
+ const metadataScopes = requestedScopesFromMetadata(bundle.metadata);
18011
+ const actual = new Set(bundle.scope?.split(/\s+/u).filter(Boolean) ?? metadataScopes ?? []);
18012
+ return required.some((scope) => ![...actual].some((grantedScope) => oauthScopeSatisfies(grantedScope, scope)));
18013
+ }
18014
+ function oauthScopeSatisfies(grantedScope, requiredScope) {
18015
+ if (grantedScope === requiredScope) return true;
18016
+ const googleScopePrefix = "https://www.googleapis.com/auth/";
18017
+ if (!grantedScope.startsWith(googleScopePrefix) || !requiredScope.startsWith(googleScopePrefix)) return false;
18018
+ return requiredScope.startsWith(`${grantedScope}.`);
18019
+ }
18020
+ function requiredStoredScopes(authConfig, resolvedScopes) {
18021
+ if (authConfig.scopes?.length) return authConfig.scopes;
18022
+ return resolvedScopes?.length ? [...new Set(resolvedScopes)].sort() : [];
18023
+ }
18024
+ function requestedScopesFromMetadata(metadata) {
18025
+ if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) return void 0;
18026
+ const value = metadata.requestedScopes;
18027
+ return Array.isArray(value) && value.every((entry) => typeof entry === "string") ? value : void 0;
18028
+ }
18029
+ function scopesFor(authConfig, resolvedScopes) {
18001
18030
  if (authConfig.scopes?.length) return authConfig.scopes.join(" ");
18031
+ if (resolvedScopes?.length) {
18032
+ const apiScopes = [...new Set(resolvedScopes)].sort();
18033
+ return authConfig.type === "oidc" ? [
18034
+ "openid",
18035
+ "profile",
18036
+ "email",
18037
+ ...apiScopes
18038
+ ].join(" ") : apiScopes.join(" ");
18039
+ }
18002
18040
  return authConfig.type === "oidc" ? "openid profile email" : void 0;
18003
18041
  }
18004
18042
  function validateOidcToken(authConfig, metadata, idToken, claims, clientId) {
@@ -18589,8 +18627,8 @@ function compactToolSafetyHints(tool) {
18589
18627
  };
18590
18628
  }
18591
18629
  function compactToolSchemaHints(tool) {
18592
- const schema = isRecord$4(tool.inputSchema) ? tool.inputSchema : void 0;
18593
- const properties = isRecord$4(schema?.properties) ? schema.properties : {};
18630
+ const schema = isRecord$5(tool.inputSchema) ? tool.inputSchema : void 0;
18631
+ const properties = isRecord$5(schema?.properties) ? schema.properties : {};
18594
18632
  const acceptedArgs = Object.keys(properties).sort();
18595
18633
  const requiredArgs = Array.isArray(schema?.required) ? schema.required.filter((value) => typeof value === "string").sort() : [];
18596
18634
  const argsTemplate = compactArgsTemplate(properties, requiredArgs, acceptedArgs);
@@ -18614,7 +18652,7 @@ function compactArgsTemplate(properties, requiredArgs, acceptedArgs) {
18614
18652
  if (templateArgs.length === 0 || templateArgs.length > 4) return void 0;
18615
18653
  if (requiredArgs.length === 0 && acceptedArgs.length > 3) return void 0;
18616
18654
  const entries = templateArgs.flatMap((name) => {
18617
- const value = placeholderForSchema(isRecord$4(properties[name]) ? properties[name] : void 0);
18655
+ const value = placeholderForSchema(isRecord$5(properties[name]) ? properties[name] : void 0);
18618
18656
  return value === void 0 ? [] : [[name, value]];
18619
18657
  });
18620
18658
  return entries.length === templateArgs.length ? Object.fromEntries(entries) : void 0;
@@ -18634,13 +18672,13 @@ function placeholderForSchema(schema) {
18634
18672
  }
18635
18673
  }
18636
18674
  function compactToolSelectionHints(tool) {
18637
- if (!isRecord$4(tool)) return {};
18675
+ if (!isRecord$5(tool)) return {};
18638
18676
  return {
18639
18677
  ...typeof tool.useWhen === "string" && tool.useWhen.trim() ? { useWhen: tool.useWhen.trim() } : {},
18640
18678
  ...typeof tool.avoidWhen === "string" && tool.avoidWhen.trim() ? { avoidWhen: tool.avoidWhen.trim() } : {}
18641
18679
  };
18642
18680
  }
18643
- function isRecord$4(value) {
18681
+ function isRecord$5(value) {
18644
18682
  return value !== null && typeof value === "object" && !Array.isArray(value);
18645
18683
  }
18646
18684
  function sameServerConfig(left, right) {
@@ -18715,7 +18753,7 @@ function markdownCallToolResultContent(result, context = {}) {
18715
18753
  return textContent(renderStructuredMarkdown(result, context));
18716
18754
  }
18717
18755
  function hasRenderableStructuredContent(value) {
18718
- if (!isRecord$3(value)) return false;
18756
+ if (!isRecord$4(value)) return false;
18719
18757
  return Object.keys(value).some((key) => key !== "caplets" && key !== "elapsedMs");
18720
18758
  }
18721
18759
  function renderStructuredMarkdown(value, context) {
@@ -18739,7 +18777,7 @@ function markdownTitle(context) {
18739
18777
  return parts.length > 0 ? `# ${parts.join(" ")}` : "# Result";
18740
18778
  }
18741
18779
  function renderHttpMarkdown(value, title) {
18742
- const record = asRecord$2(value) ?? {};
18780
+ const record = asRecord$3(value) ?? {};
18743
18781
  const lines = [
18744
18782
  title,
18745
18783
  "",
@@ -18762,8 +18800,8 @@ function renderHttpMarkdown(value, title) {
18762
18800
  return lines.join("\n");
18763
18801
  }
18764
18802
  function renderGraphQlMarkdown(value, title) {
18765
- const record = asRecord$2(value) ?? {};
18766
- const body = asRecord$2(record.body);
18803
+ const record = asRecord$3(value) ?? {};
18804
+ const body = asRecord$3(record.body);
18767
18805
  if (!body || !("data" in body) && !("errors" in body)) return renderHttpMarkdown(value, title);
18768
18806
  const lines = [
18769
18807
  title,
@@ -18789,7 +18827,7 @@ function renderGraphQlMarkdown(value, title) {
18789
18827
  return lines.join("\n");
18790
18828
  }
18791
18829
  function renderCliMarkdown(value, title) {
18792
- const record = asRecord$2(value) ?? {};
18830
+ const record = asRecord$3(value) ?? {};
18793
18831
  const lines = [
18794
18832
  title,
18795
18833
  "",
@@ -18816,14 +18854,14 @@ function renderCliMarkdown(value, title) {
18816
18854
  return lines.join("\n");
18817
18855
  }
18818
18856
  function renderDiscoveryWrapper(value, context, title) {
18819
- const result = asRecord$2(value.result);
18857
+ const result = asRecord$3(value.result);
18820
18858
  const lines = [title, ""];
18821
18859
  let renderedKnownWrapper = true;
18822
18860
  if (context.operation === "tools" || context.operation === "search_tools") lines.push("## Tools", "", renderNamedList(arrayValue$1(result?.items ?? result?.tools), "tool"), "");
18823
18861
  else if (context.operation === "resources" || context.operation === "search_resources") lines.push("## Resources", "", renderNamedList(arrayValue$1(result?.items ?? result?.resources ?? result?.matches), "uri"), "");
18824
18862
  else if (context.operation === "resource_templates") lines.push("## Resource Templates", "", renderNamedList(arrayValue$1(result?.items ?? result?.resourceTemplates), "uriTemplate"), "");
18825
18863
  else if (context.operation === "prompts" || context.operation === "search_prompts") lines.push("## Prompts", "", renderNamedList(arrayValue$1(result?.items ?? result?.prompts), "prompt"), "");
18826
- else if (context.operation === "describe_tool") lines.push("## Tool", "", renderToolSummary(asRecord$2(result?.tool)), "");
18864
+ else if (context.operation === "describe_tool") lines.push("## Tool", "", renderToolSummary(asRecord$3(result?.tool)), "");
18827
18865
  else if (context.operation === "check") lines.push("## Backend Status", "", renderBackendStatus(result), "");
18828
18866
  else if (context.operation === "inspect") lines.push("## Caplet", "", renderCapletSummary(result), "");
18829
18867
  else renderedKnownWrapper = false;
@@ -18833,7 +18871,7 @@ function renderDiscoveryWrapper(value, context, title) {
18833
18871
  return lines.join("\n");
18834
18872
  }
18835
18873
  function renderErrorMarkdown(value, title) {
18836
- const error = asRecord$2(asRecord$2(value)?.error) ?? asRecord$2(value);
18874
+ const error = asRecord$3(asRecord$3(value)?.error) ?? asRecord$3(value);
18837
18875
  const code = typeof error?.code === "string" ? error.code : "Error";
18838
18876
  const message = typeof error?.message === "string" ? error.message : "Tool call failed.";
18839
18877
  return [
@@ -18849,21 +18887,21 @@ function renderErrorMarkdown(value, title) {
18849
18887
  ].join("\n");
18850
18888
  }
18851
18889
  function isDiscoveryWrapper(value) {
18852
- return isRecord$3(value) && "result" in value;
18890
+ return isRecord$4(value) && "result" in value;
18853
18891
  }
18854
18892
  function isErrorStructuredContent(value) {
18855
- return isRecord$3(value) && "error" in value;
18893
+ return isRecord$4(value) && "error" in value;
18856
18894
  }
18857
18895
  function isHttpLikeResult(value) {
18858
- return isRecord$3(value) && ("status" in value || "statusText" in value || "body" in value);
18896
+ return isRecord$4(value) && ("status" in value || "statusText" in value || "body" in value);
18859
18897
  }
18860
18898
  function isGraphQlHttpResult(value) {
18861
18899
  if (!isHttpLikeResult(value)) return false;
18862
- const body = asRecord$2(value.body);
18900
+ const body = asRecord$3(value.body);
18863
18901
  return Boolean(body && ("data" in body || "errors" in body));
18864
18902
  }
18865
18903
  function isCliResult(value) {
18866
- return isRecord$3(value) && ("exitCode" in value || "stdout" in value || "stderr" in value);
18904
+ return isRecord$4(value) && ("exitCode" in value || "stdout" in value || "stderr" in value);
18867
18905
  }
18868
18906
  function renderBodyValue(value) {
18869
18907
  if (value === void 0) return "_No response body._";
@@ -18894,7 +18932,7 @@ function textBlocksToString(content) {
18894
18932
  }
18895
18933
  function renderNamedList(items, nameKey) {
18896
18934
  if (items.length === 0) return "_No items._";
18897
- const records = items.map((item) => asRecord$2(item));
18935
+ const records = items.map((item) => asRecord$3(item));
18898
18936
  const commonDescriptionSuffix = repeatedDescriptionSuffix(records.map((record) => stringValue$1(record?.description)).filter((description) => Boolean(description)));
18899
18937
  const renderedItems = records.map((record, index) => {
18900
18938
  const name = stringValue$1(record?.[nameKey]) ?? stringValue$1(record?.name) ?? `Item ${index + 1}`;
@@ -18931,8 +18969,8 @@ function compactListHints(record) {
18931
18969
  const acceptedArgs = stringArrayValue(record.acceptedArgs);
18932
18970
  if (requiredArgs.length > 0) hints.push(`required args: ${requiredArgs.join(", ")}`);
18933
18971
  else if (acceptedArgs.length > 0) hints.push(`args: ${acceptedArgs.join(", ")}`);
18934
- if (isRecord$3(record.argsTemplate)) hints.push(`args template: ${compactJsonText(record.argsTemplate, 160)}`);
18935
- if (isRecord$3(record.callTemplate)) hints.push(`call: ${compactJsonText(record.callTemplate, 220)}`);
18972
+ if (isRecord$4(record.argsTemplate)) hints.push(`args template: ${compactJsonText(record.argsTemplate, 160)}`);
18973
+ if (isRecord$4(record.callTemplate)) hints.push(`call: ${compactJsonText(record.callTemplate, 220)}`);
18936
18974
  if (record.supportsFields === true) hints.push("supports fields");
18937
18975
  if (record.readOnlyHint === true) hints.push("read-only");
18938
18976
  if (record.destructiveHint === true) hints.push("destructive");
@@ -18981,7 +19019,7 @@ function renderCapletSummary(result) {
18981
19019
  "name",
18982
19020
  "description"
18983
19021
  ]) if (result[key] !== void 0) lines.push(`- **${humanizeKey(key)}:** ${String(result[key])}`);
18984
- const backend = asRecord$2(result.backend);
19022
+ const backend = asRecord$3(result.backend);
18985
19023
  if (backend?.type !== void 0) lines.push(`- **Backend:** \`${String(backend.type)}\``);
18986
19024
  return lines.length > 0 ? lines.join("\n") : jsonFence(result);
18987
19025
  }
@@ -19001,10 +19039,10 @@ function stringArrayValue(value) {
19001
19039
  function humanizeKey(key) {
19002
19040
  return key.replace(/([A-Z])/gu, " $1").replace(/^./u, (char) => char.toUpperCase());
19003
19041
  }
19004
- function asRecord$2(value) {
19005
- return isRecord$3(value) ? value : void 0;
19042
+ function asRecord$3(value) {
19043
+ return isRecord$4(value) ? value : void 0;
19006
19044
  }
19007
- function isRecord$3(value) {
19045
+ function isRecord$4(value) {
19008
19046
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
19009
19047
  }
19010
19048
  //#endregion
@@ -25967,6 +26005,7 @@ const capletExposureSchema = _enum([
25967
26005
  "direct_and_code_mode",
25968
26006
  "progressive_and_code_mode"
25969
26007
  ]).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.");
25970
26009
  const capletEndpointAuthSchema = discriminatedUnion("type", [
25971
26010
  object$1({ type: literal("none") }).strict(),
25972
26011
  object$1({
@@ -26099,6 +26138,36 @@ const capletOpenApiEndpointSchema = object$1({
26099
26138
  });
26100
26139
  validateEndpointAuthHeaders$1(endpoint.auth, ctx);
26101
26140
  });
26141
+ const capletGoogleDiscoveryOperationFilterSchema = array(string().trim().min(1).max(160));
26142
+ const capletGoogleDiscoveryApiSchema = object$1({
26143
+ discoveryPath: string().min(1).optional().describe("Local Google Discovery document path."),
26144
+ discoveryUrl: string().min(1).optional().describe("Remote Google Discovery document URL."),
26145
+ baseUrl: string().min(1).optional().describe("Override base URL for Google API requests."),
26146
+ auth: capletEndpointAuthSchema.describe("Explicit Google API request auth config. Use {\"type\":\"none\"} for public APIs."),
26147
+ requestTimeoutMs: number$1().int().positive().optional().describe("Timeout in milliseconds for Google API HTTP requests."),
26148
+ operationCacheTtlMs: number$1().int().nonnegative().optional().describe("Milliseconds Google Discovery operation metadata stays fresh. Set 0 to refresh every time."),
26149
+ includeOperations: capletGoogleDiscoveryOperationFilterSchema.optional(),
26150
+ excludeOperations: capletGoogleDiscoveryOperationFilterSchema.optional(),
26151
+ disabled: boolean().optional().describe("When true, omit this Caplet from discovery."),
26152
+ projectBinding: capletProjectBindingSchema.optional(),
26153
+ runtime: capletRuntimeRequirementsSchema.optional()
26154
+ }).strict().superRefine((api, ctx) => {
26155
+ if (Boolean(api.discoveryPath) === Boolean(api.discoveryUrl)) ctx.addIssue({
26156
+ code: "custom",
26157
+ message: "googleDiscoveryApi must define exactly one discovery source: discoveryPath or discoveryUrl"
26158
+ });
26159
+ if (api.discoveryUrl && !hasEnvReference$2(api.discoveryUrl) && !isAllowedRemoteUrl(api.discoveryUrl)) ctx.addIssue({
26160
+ code: "custom",
26161
+ path: ["discoveryUrl"],
26162
+ message: "Google Discovery discoveryUrl must use https except loopback development urls"
26163
+ });
26164
+ if (api.baseUrl && !hasEnvReference$2(api.baseUrl) && !isAllowedHttpBaseUrl(api.baseUrl)) ctx.addIssue({
26165
+ code: "custom",
26166
+ path: ["baseUrl"],
26167
+ message: "Google Discovery baseUrl must use https except loopback development urls and must not include credentials, query, or fragment"
26168
+ });
26169
+ validateEndpointAuthHeaders$1(api.auth, ctx);
26170
+ });
26102
26171
  const capletGraphQlOperationSchema = object$1({
26103
26172
  document: string().min(1).optional().describe("Inline GraphQL operation document."),
26104
26173
  documentPath: string().min(1).optional().describe("Path to a GraphQL operation document."),
@@ -26242,25 +26311,27 @@ const capletSetSchema = object$1({
26242
26311
  });
26243
26312
  });
26244
26313
  const capletFileSchema = object$1({
26245
- $schema: string().url().optional().describe("Optional JSON Schema URL for editor validation."),
26314
+ $schema: string().optional().describe("Optional JSON Schema for editor validation."),
26246
26315
  name: string().trim().min(1).max(80).describe("Human-readable Caplet display name."),
26247
26316
  description: string().describe("Compact capability description shown before the full Caplet card is 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"),
26248
26317
  tags: array(string().trim().min(1).max(80)).optional().describe("Optional tags for grouping or searching Caplets."),
26249
26318
  exposure: capletExposureSchema.optional(),
26319
+ shadowing: capletShadowingSchema.optional(),
26250
26320
  ...capletAgentSelectionHintsSchema,
26251
26321
  setup: capletSetupSchema.optional(),
26252
26322
  projectBinding: capletProjectBindingSchema.optional(),
26253
26323
  runtime: capletRuntimeRequirementsSchema.optional(),
26254
26324
  mcpServer: capletMcpServerSchema.describe("MCP server backend configuration for this Caplet.").optional(),
26255
26325
  openapiEndpoint: capletOpenApiEndpointSchema.describe("OpenAPI endpoint backend configuration for this Caplet.").optional(),
26326
+ googleDiscoveryApi: capletGoogleDiscoveryApiSchema.describe("Google Discovery API backend configuration for this Caplet.").optional(),
26256
26327
  graphqlEndpoint: capletGraphQlEndpointSchema.describe("GraphQL endpoint backend configuration for this Caplet.").optional(),
26257
26328
  httpApi: capletHttpApiSchema.describe("HTTP API backend configuration for this Caplet.").optional(),
26258
26329
  cliTools: capletCliToolsSchema.describe("CLI tools backend configuration for this Caplet.").optional(),
26259
26330
  capletSet: capletSetSchema.describe("Nested Caplet collection backend configuration for this Caplet.").optional()
26260
26331
  }).strict().superRefine((frontmatter, ctx) => {
26261
- if (Number(Boolean(frontmatter.mcpServer)) + Number(Boolean(frontmatter.openapiEndpoint)) + Number(Boolean(frontmatter.graphqlEndpoint)) + Number(Boolean(frontmatter.httpApi)) + Number(Boolean(frontmatter.cliTools)) + Number(Boolean(frontmatter.capletSet)) !== 1) ctx.addIssue({
26332
+ if (Number(Boolean(frontmatter.mcpServer)) + Number(Boolean(frontmatter.openapiEndpoint)) + Number(Boolean(frontmatter.googleDiscoveryApi)) + Number(Boolean(frontmatter.graphqlEndpoint)) + Number(Boolean(frontmatter.httpApi)) + Number(Boolean(frontmatter.cliTools)) + Number(Boolean(frontmatter.capletSet)) !== 1) ctx.addIssue({
26262
26333
  code: "custom",
26263
- message: "Caplet file must define exactly one backend: mcpServer, openapiEndpoint, graphqlEndpoint, httpApi, cliTools, or capletSet"
26334
+ message: "Caplet file must define exactly one backend: mcpServer, openapiEndpoint, googleDiscoveryApi, graphqlEndpoint, httpApi, cliTools, or capletSet"
26264
26335
  });
26265
26336
  });
26266
26337
  function loadCapletFilesFromMap(input) {
@@ -26279,13 +26350,14 @@ function loadCapletFilesFromMap(input) {
26279
26350
  function buildCapletFileLoadResultFromEntries(root, candidates, readConfig, warnings) {
26280
26351
  const servers = {};
26281
26352
  const openapiEndpoints = {};
26353
+ const googleDiscoveryApis = {};
26282
26354
  const graphqlEndpoints = {};
26283
26355
  const httpApis = {};
26284
26356
  const cliTools = {};
26285
26357
  const capletSets = {};
26286
26358
  const paths = {};
26287
26359
  function hasId(id) {
26288
- return Boolean(servers[id] || openapiEndpoints[id] || graphqlEndpoints[id] || httpApis[id] || cliTools[id] || capletSets[id]);
26360
+ return Boolean(servers[id] || openapiEndpoints[id] || googleDiscoveryApis[id] || graphqlEndpoints[id] || httpApis[id] || cliTools[id] || capletSets[id]);
26289
26361
  }
26290
26362
  for (const candidate of candidates) {
26291
26363
  if (hasId(candidate.id)) {
@@ -26312,6 +26384,9 @@ function buildCapletFileLoadResultFromEntries(root, candidates, readConfig, warn
26312
26384
  if (isPlainObject$6(config) && config.backend === "openapi") {
26313
26385
  const { backend: _backend, ...endpoint } = config;
26314
26386
  openapiEndpoints[candidate.id] = endpoint;
26387
+ } else if (isPlainObject$6(config) && config.backend === "googleDiscovery") {
26388
+ const { backend: _backend, ...api } = config;
26389
+ googleDiscoveryApis[candidate.id] = api;
26315
26390
  } else if (isPlainObject$6(config) && config.backend === "graphql") {
26316
26391
  const { backend: _backend, ...endpoint } = config;
26317
26392
  graphqlEndpoints[candidate.id] = endpoint;
@@ -26328,6 +26403,7 @@ function buildCapletFileLoadResultFromEntries(root, candidates, readConfig, warn
26328
26403
  }
26329
26404
  const hasServers = Object.keys(servers).length > 0;
26330
26405
  const hasOpenApi = Object.keys(openapiEndpoints).length > 0;
26406
+ const hasGoogleDiscovery = Object.keys(googleDiscoveryApis).length > 0;
26331
26407
  const hasGraphQl = Object.keys(graphqlEndpoints).length > 0;
26332
26408
  const hasHttpApis = Object.keys(httpApis).length > 0;
26333
26409
  const hasCliTools = Object.keys(cliTools).length > 0;
@@ -26335,6 +26411,7 @@ function buildCapletFileLoadResultFromEntries(root, candidates, readConfig, warn
26335
26411
  const config = {
26336
26412
  ...hasServers ? { mcpServers: servers } : {},
26337
26413
  ...hasOpenApi ? { openapiEndpoints } : {},
26414
+ ...hasGoogleDiscovery ? { googleDiscoveryApis } : {},
26338
26415
  ...hasGraphQl ? { graphqlEndpoints } : {},
26339
26416
  ...hasHttpApis ? { httpApis } : {},
26340
26417
  ...hasCliTools ? { cliTools } : {},
@@ -26394,6 +26471,15 @@ function capletToServerConfig(frontmatter, body, baseDir, normalizePath) {
26394
26471
  ...sharedCapletFields(frontmatter),
26395
26472
  body
26396
26473
  };
26474
+ if (frontmatter.googleDiscoveryApi) return {
26475
+ ...frontmatter.googleDiscoveryApi,
26476
+ discoveryPath: normalizePath(frontmatter.googleDiscoveryApi.discoveryPath, baseDir),
26477
+ backend: "googleDiscovery",
26478
+ name: frontmatter.name,
26479
+ description: frontmatter.description,
26480
+ ...sharedCapletFields(frontmatter),
26481
+ body
26482
+ };
26397
26483
  if (frontmatter.graphqlEndpoint) return {
26398
26484
  ...frontmatter.graphqlEndpoint,
26399
26485
  schemaPath: normalizePath(frontmatter.graphqlEndpoint.schemaPath, baseDir),
@@ -26444,6 +26530,7 @@ function sharedCapletFields(frontmatter) {
26444
26530
  return {
26445
26531
  ...frontmatter.tags ? { tags: frontmatter.tags } : {},
26446
26532
  ...frontmatter.exposure ? { exposure: frontmatter.exposure } : {},
26533
+ ...frontmatter.shadowing ? { shadowing: frontmatter.shadowing } : {},
26447
26534
  ...frontmatter.useWhen ? { useWhen: frontmatter.useWhen } : {},
26448
26535
  ...frontmatter.avoidWhen ? { avoidWhen: frontmatter.avoidWhen } : {},
26449
26536
  ...frontmatter.setup ? { setup: frontmatter.setup } : {},
@@ -26794,6 +26881,7 @@ const exposureSchema = _enum([
26794
26881
  "direct_and_code_mode",
26795
26882
  "progressive_and_code_mode"
26796
26883
  ]).describe("How this Caplet is exposed to agents.");
26884
+ const shadowingSchema = _enum(["forbid", "allow"]).default("forbid").describe("Whether attached local Caplets may shadow this remote Caplet ID.");
26797
26885
  const publicServerSchema = object$1({
26798
26886
  name: string().trim().min(1).max(80).describe("Human-readable server display name."),
26799
26887
  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"),
@@ -26810,6 +26898,7 @@ const publicServerSchema = object$1({
26810
26898
  auth: remoteAuthSchema.optional(),
26811
26899
  tags: array(string().trim().min(1).max(80)).optional(),
26812
26900
  exposure: exposureSchema.optional(),
26901
+ shadowing: shadowingSchema,
26813
26902
  ...agentSelectionHintsSchema,
26814
26903
  setup: setupSchema.optional(),
26815
26904
  projectBinding: projectBindingSchema.optional(),
@@ -26829,6 +26918,7 @@ const publicOpenApiEndpointSchema = object$1({
26829
26918
  auth: openApiAuthSchema.describe("Explicit OpenAPI request auth config. Use {\"type\":\"none\"} for public APIs."),
26830
26919
  tags: array(string().trim().min(1).max(80)).optional(),
26831
26920
  exposure: exposureSchema.optional(),
26921
+ shadowing: shadowingSchema,
26832
26922
  ...agentSelectionHintsSchema,
26833
26923
  setup: setupSchema.optional(),
26834
26924
  projectBinding: projectBindingSchema.optional(),
@@ -26838,6 +26928,28 @@ const publicOpenApiEndpointSchema = object$1({
26838
26928
  disabled: boolean().default(false).describe("When true, omit this OpenAPI Caplet from discovery.")
26839
26929
  }).strict();
26840
26930
  const normalizedOpenApiEndpointSchema = publicOpenApiEndpointSchema.extend({ body: string().optional() });
26931
+ const operationFilterSchema = array(string().trim().min(1).max(160));
26932
+ const publicGoogleDiscoveryApiSchema = object$1({
26933
+ name: string().trim().min(1).max(80).describe("Human-readable Google Discovery API display name."),
26934
+ description: string().describe("Capability description shown to agents before Google Discovery operations 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"),
26935
+ discoveryPath: string().min(1).optional().describe("Local Google Discovery document path."),
26936
+ discoveryUrl: string().url().optional().describe("Remote Google Discovery document URL."),
26937
+ baseUrl: string().url().optional().describe("Override base URL for Google API requests."),
26938
+ includeOperations: operationFilterSchema.optional(),
26939
+ excludeOperations: operationFilterSchema.optional(),
26940
+ auth: openApiAuthSchema.describe("Explicit Google API request auth config. Use {\"type\":\"none\"} for public APIs."),
26941
+ tags: array(string().trim().min(1).max(80)).optional(),
26942
+ exposure: exposureSchema.optional(),
26943
+ shadowing: shadowingSchema,
26944
+ ...agentSelectionHintsSchema,
26945
+ setup: setupSchema.optional(),
26946
+ projectBinding: projectBindingSchema.optional(),
26947
+ runtime: runtimeRequirementsSchema.optional(),
26948
+ requestTimeoutMs: number$1().int().positive().default(6e4).describe("Timeout in milliseconds for Google Discovery HTTP requests."),
26949
+ operationCacheTtlMs: number$1().int().nonnegative().default(3e4).describe("Milliseconds Google Discovery operation metadata stays fresh. Set 0 to refresh every time."),
26950
+ disabled: boolean().default(false).describe("When true, omit this Google Discovery Caplet from discovery.")
26951
+ }).strict();
26952
+ const normalizedGoogleDiscoveryApiSchema = publicGoogleDiscoveryApiSchema.extend({ body: string().optional() });
26841
26953
  const graphQlOperationSchema = object$1({
26842
26954
  document: string().min(1).optional().describe("Inline GraphQL operation document."),
26843
26955
  documentPath: string().min(1).optional().describe("Path to a GraphQL operation document."),
@@ -26861,6 +26973,7 @@ const publicGraphQlEndpointSchema = object$1({
26861
26973
  auth: openApiAuthSchema.describe("Explicit GraphQL request auth config. Use {\"type\":\"none\"} for public APIs."),
26862
26974
  tags: array(string().trim().min(1).max(80)).optional(),
26863
26975
  exposure: exposureSchema.optional(),
26976
+ shadowing: shadowingSchema,
26864
26977
  ...agentSelectionHintsSchema,
26865
26978
  setup: setupSchema.optional(),
26866
26979
  projectBinding: projectBindingSchema.optional(),
@@ -26912,6 +27025,7 @@ const publicHttpApiSchema = object$1({
26912
27025
  actions: record(string().regex(SERVER_ID_PATTERN), httpActionSchema).refine((actions) => Object.keys(actions).length > 0, "HTTP API must define at least one action").describe("Configured HTTP actions keyed by stable tool name."),
26913
27026
  tags: array(string().trim().min(1).max(80)).optional(),
26914
27027
  exposure: exposureSchema.optional(),
27028
+ shadowing: shadowingSchema,
26915
27029
  ...agentSelectionHintsSchema,
26916
27030
  setup: setupSchema.optional(),
26917
27031
  projectBinding: projectBindingSchema.optional(),
@@ -26950,6 +27064,7 @@ const publicCliToolsSchema = object$1({
26950
27064
  env: record(string(), string()).optional().describe("Default environment variables for CLI actions."),
26951
27065
  tags: array(string().trim().min(1).max(80)).optional(),
26952
27066
  exposure: exposureSchema.optional(),
27067
+ shadowing: shadowingSchema,
26953
27068
  ...agentSelectionHintsSchema,
26954
27069
  setup: setupSchema.optional(),
26955
27070
  projectBinding: projectBindingSchema.optional(),
@@ -26969,6 +27084,7 @@ const publicCapletSetSchema = object$1({
26969
27084
  toolCacheTtlMs: number$1().int().nonnegative().default(3e4).describe("Milliseconds child Caplet metadata stays fresh. Set 0 to refresh every time."),
26970
27085
  tags: array(string().trim().min(1).max(80)).optional(),
26971
27086
  exposure: exposureSchema.optional(),
27087
+ shadowing: shadowingSchema,
26972
27088
  ...agentSelectionHintsSchema,
26973
27089
  setup: setupSchema.optional(),
26974
27090
  projectBinding: projectBindingSchema.optional(),
@@ -26986,9 +27102,9 @@ const publicCapletSetSchema = object$1({
26986
27102
  });
26987
27103
  });
26988
27104
  const normalizedCapletSetSchema = publicCapletSetSchema.extend({ body: string().optional() });
26989
- function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlEndpointValueSchema, httpApiValueSchema, cliToolsValueSchema, capletSetValueSchema) {
27105
+ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, googleDiscoveryApiValueSchema, graphQlEndpointValueSchema, httpApiValueSchema, cliToolsValueSchema, capletSetValueSchema) {
26990
27106
  return object$1({
26991
- $schema: string().url().optional().describe("Optional JSON Schema URL for editor validation."),
27107
+ $schema: string().optional().describe("Optional JSON Schema for editor validation."),
26992
27108
  version: literal(1).default(1).describe("Caplets config schema version."),
26993
27109
  defaultSearchLimit: number$1().int().positive().default(20).describe("Default maximum number of same-server search results."),
26994
27110
  maxSearchLimit: number$1().int().positive().max(50).default(50).describe("Maximum accepted search_tools limit."),
@@ -27014,6 +27130,7 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
27014
27130
  }).describe("Global Caplets runtime options."),
27015
27131
  mcpServers: record(string().regex(SERVER_ID_PATTERN), serverValueSchema).default({}).describe("Downstream MCP servers keyed by stable server ID."),
27016
27132
  openapiEndpoints: record(string().regex(SERVER_ID_PATTERN), openApiEndpointValueSchema).default({}).describe("OpenAPI endpoints keyed by stable Caplet ID."),
27133
+ googleDiscoveryApis: record(string().regex(SERVER_ID_PATTERN), googleDiscoveryApiValueSchema).default({}).describe("Google Discovery APIs keyed by stable Caplet ID."),
27017
27134
  graphqlEndpoints: record(string().regex(SERVER_ID_PATTERN), graphQlEndpointValueSchema).default({}).describe("GraphQL endpoints keyed by stable Caplet ID."),
27018
27135
  httpApis: record(string().regex(SERVER_ID_PATTERN), httpApiValueSchema).default({}).describe("HTTP APIs keyed by stable Caplet ID."),
27019
27136
  cliTools: record(string().regex(SERVER_ID_PATTERN), cliToolsValueSchema).default({}).describe("CLI tools keyed by stable Caplet ID."),
@@ -27129,9 +27246,60 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
27129
27246
  });
27130
27247
  }
27131
27248
  }
27249
+ for (const [api, rawValue] of Object.entries(config.googleDiscoveryApis)) {
27250
+ const raw = rawValue;
27251
+ const duplicateBackend = config.mcpServers[api] ? "mcpServers" : config.openapiEndpoints[api] ? "openapiEndpoints" : config.graphqlEndpoints[api] ? "graphqlEndpoints" : config.httpApis[api] ? "httpApis" : config.cliTools[api] ? "cliTools" : config.capletSets[api] ? "capletSets" : void 0;
27252
+ if (duplicateBackend) ctx.addIssue({
27253
+ code: "custom",
27254
+ path: ["googleDiscoveryApis", api],
27255
+ message: `Caplet ID ${api} is already used by ${duplicateBackend}`
27256
+ });
27257
+ if (!SERVER_ID_PATTERN.test(api)) ctx.addIssue({
27258
+ code: "custom",
27259
+ path: ["googleDiscoveryApis", api],
27260
+ message: "Google Discovery API ID must match ^[a-zA-Z0-9_-]{1,64}$"
27261
+ });
27262
+ if (Boolean(raw.discoveryPath) === Boolean(raw.discoveryUrl)) ctx.addIssue({
27263
+ code: "custom",
27264
+ path: ["googleDiscoveryApis", api],
27265
+ message: "Google Discovery API must define exactly one discovery source: discoveryPath or discoveryUrl"
27266
+ });
27267
+ if (raw.discoveryUrl && !isAllowedRemoteUrl(raw.discoveryUrl)) ctx.addIssue({
27268
+ code: "custom",
27269
+ path: [
27270
+ "googleDiscoveryApis",
27271
+ api,
27272
+ "discoveryUrl"
27273
+ ],
27274
+ message: "Google Discovery API discoveryUrl must use https except loopback development urls"
27275
+ });
27276
+ if (raw.baseUrl && !isAllowedHttpBaseUrl(raw.baseUrl)) ctx.addIssue({
27277
+ code: "custom",
27278
+ path: [
27279
+ "googleDiscoveryApis",
27280
+ api,
27281
+ "baseUrl"
27282
+ ],
27283
+ message: "Google Discovery API baseUrl must use https except loopback development urls and must not include credentials, query, or fragment"
27284
+ });
27285
+ if (raw.auth?.type === "headers") for (const headerName of Object.keys(raw.auth.headers)) {
27286
+ const normalized = headerName.toLowerCase();
27287
+ if (!HEADER_NAME_PATTERN.test(headerName) || FORBIDDEN_HEADERS.has(normalized)) ctx.addIssue({
27288
+ code: "custom",
27289
+ path: [
27290
+ "googleDiscoveryApis",
27291
+ api,
27292
+ "auth",
27293
+ "headers",
27294
+ headerName
27295
+ ],
27296
+ message: `header ${headerName} is not allowed`
27297
+ });
27298
+ }
27299
+ }
27132
27300
  for (const [endpoint, rawValue] of Object.entries(config.graphqlEndpoints)) {
27133
27301
  const raw = rawValue;
27134
- const duplicateBackend = config.mcpServers[endpoint] ? "mcpServers" : config.openapiEndpoints[endpoint] ? "openapiEndpoints" : void 0;
27302
+ const duplicateBackend = config.mcpServers[endpoint] ? "mcpServers" : config.openapiEndpoints[endpoint] ? "openapiEndpoints" : config.googleDiscoveryApis[endpoint] ? "googleDiscoveryApis" : void 0;
27135
27303
  if (duplicateBackend) ctx.addIssue({
27136
27304
  code: "custom",
27137
27305
  path: ["graphqlEndpoints", endpoint],
@@ -27173,7 +27341,7 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
27173
27341
  }
27174
27342
  for (const [endpoint, rawValue] of Object.entries(config.httpApis)) {
27175
27343
  const raw = rawValue;
27176
- const duplicateBackend = config.mcpServers[endpoint] ? "mcpServers" : config.openapiEndpoints[endpoint] ? "openapiEndpoints" : config.graphqlEndpoints[endpoint] ? "graphqlEndpoints" : void 0;
27344
+ const duplicateBackend = config.mcpServers[endpoint] ? "mcpServers" : config.openapiEndpoints[endpoint] ? "openapiEndpoints" : config.googleDiscoveryApis[endpoint] ? "googleDiscoveryApis" : config.graphqlEndpoints[endpoint] ? "graphqlEndpoints" : void 0;
27177
27345
  if (duplicateBackend) ctx.addIssue({
27178
27346
  code: "custom",
27179
27347
  path: ["httpApis", endpoint],
@@ -27208,7 +27376,7 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
27208
27376
  }
27209
27377
  for (const [server, rawValue] of Object.entries(config.cliTools)) {
27210
27378
  const raw = rawValue;
27211
- const duplicateBackend = config.mcpServers[server] ? "mcpServers" : config.openapiEndpoints[server] ? "openapiEndpoints" : config.graphqlEndpoints[server] ? "graphqlEndpoints" : config.httpApis[server] ? "httpApis" : void 0;
27379
+ const duplicateBackend = config.mcpServers[server] ? "mcpServers" : config.openapiEndpoints[server] ? "openapiEndpoints" : config.googleDiscoveryApis[server] ? "googleDiscoveryApis" : config.graphqlEndpoints[server] ? "graphqlEndpoints" : config.httpApis[server] ? "httpApis" : void 0;
27212
27380
  if (duplicateBackend) ctx.addIssue({
27213
27381
  code: "custom",
27214
27382
  path: ["cliTools", server],
@@ -27232,7 +27400,7 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
27232
27400
  }
27233
27401
  for (const [server, rawValue] of Object.entries(config.capletSets)) {
27234
27402
  const raw = rawValue;
27235
- const duplicateBackend = config.mcpServers[server] ? "mcpServers" : config.openapiEndpoints[server] ? "openapiEndpoints" : config.graphqlEndpoints[server] ? "graphqlEndpoints" : config.httpApis[server] ? "httpApis" : config.cliTools[server] ? "cliTools" : void 0;
27403
+ const duplicateBackend = config.mcpServers[server] ? "mcpServers" : config.openapiEndpoints[server] ? "openapiEndpoints" : config.googleDiscoveryApis[server] ? "googleDiscoveryApis" : config.graphqlEndpoints[server] ? "graphqlEndpoints" : config.httpApis[server] ? "httpApis" : config.cliTools[server] ? "cliTools" : void 0;
27236
27404
  if (duplicateBackend) ctx.addIssue({
27237
27405
  code: "custom",
27238
27406
  path: ["capletSets", server],
@@ -27251,8 +27419,8 @@ function configSchemaFor(serverValueSchema, openApiEndpointValueSchema, graphQlE
27251
27419
  }
27252
27420
  });
27253
27421
  }
27254
- const configFileSchema = configSchemaFor(publicServerSchema, publicOpenApiEndpointSchema, publicGraphQlEndpointSchema, publicHttpApiSchema, publicCliToolsSchema, publicCapletSetSchema);
27255
- const normalizedConfigFileSchema = configSchemaFor(normalizedServerSchema, normalizedOpenApiEndpointSchema, normalizedGraphQlEndpointSchema, normalizedHttpApiSchema, normalizedCliToolsSchema, normalizedCapletSetSchema);
27422
+ const configFileSchema = configSchemaFor(publicServerSchema, publicOpenApiEndpointSchema, publicGoogleDiscoveryApiSchema, publicGraphQlEndpointSchema, publicHttpApiSchema, publicCliToolsSchema, publicCapletSetSchema);
27423
+ const normalizedConfigFileSchema = configSchemaFor(normalizedServerSchema, normalizedOpenApiEndpointSchema, normalizedGoogleDiscoveryApiSchema, normalizedGraphQlEndpointSchema, normalizedHttpApiSchema, normalizedCliToolsSchema, normalizedCapletSetSchema);
27256
27424
  function loadConfig(path = resolveConfigPath(), projectPath = resolveProjectConfigPath()) {
27257
27425
  return loadConfigWithSources(path, projectPath).config;
27258
27426
  }
@@ -27293,7 +27461,7 @@ function loadConfigWithSources(path = resolveConfigPath(), projectPath = resolve
27293
27461
  path: projectCaplets.paths
27294
27462
  }
27295
27463
  } : void 0
27296
- ], `Caplets config not found at ${path} or ${projectPath}`, "Caplets config must define at least one MCP server, OpenAPI endpoint, GraphQL endpoint, HTTP API, CLI tools backend, or Caplet set");
27464
+ ], `Caplets config not found at ${path} or ${projectPath}`, "Caplets config must define at least one MCP server, OpenAPI endpoint, Google Discovery API, GraphQL endpoint, HTTP API, CLI tools backend, or Caplet set");
27297
27465
  }
27298
27466
  function loadGlobalConfig(path = resolveConfigPath()) {
27299
27467
  const userConfig = existsSync(path) ? readPublicConfigInput(path) : void 0;
@@ -27335,7 +27503,7 @@ function buildConfigWithSources(inputs, notFoundMessage, emptyMessage) {
27335
27503
  try {
27336
27504
  const { input, sources, shadows } = mergeConfigInputsWithSources(...inputs);
27337
27505
  const config = parseConfig(input);
27338
- if (emptyMessage && Object.keys(config.mcpServers).length === 0 && Object.keys(config.openapiEndpoints).length === 0 && Object.keys(config.graphqlEndpoints).length === 0 && Object.keys(config.httpApis).length === 0 && Object.keys(config.cliTools).length === 0 && Object.keys(config.capletSets).length === 0) throw new CapletsError("CONFIG_INVALID", emptyMessage);
27506
+ if (emptyMessage && Object.keys(config.mcpServers).length === 0 && Object.keys(config.openapiEndpoints).length === 0 && Object.keys(config.googleDiscoveryApis).length === 0 && Object.keys(config.graphqlEndpoints).length === 0 && Object.keys(config.httpApis).length === 0 && Object.keys(config.cliTools).length === 0 && Object.keys(config.capletSets).length === 0) throw new CapletsError("CONFIG_INVALID", emptyMessage);
27339
27507
  return {
27340
27508
  config,
27341
27509
  sources,
@@ -27424,7 +27592,7 @@ function loadIsolatedConfig(options) {
27424
27592
  defaultSearchLimit: options.defaultSearchLimit,
27425
27593
  maxSearchLimit: options.maxSearchLimit
27426
27594
  }));
27427
- if (Object.keys(config.mcpServers).length === 0 && Object.keys(config.openapiEndpoints).length === 0 && Object.keys(config.graphqlEndpoints).length === 0 && Object.keys(config.httpApis).length === 0 && Object.keys(config.cliTools).length === 0 && Object.keys(config.capletSets).length === 0) throw new CapletsError("CONFIG_INVALID", "Nested Caplet set must define at least one Caplet");
27595
+ if (Object.keys(config.mcpServers).length === 0 && Object.keys(config.openapiEndpoints).length === 0 && Object.keys(config.googleDiscoveryApis).length === 0 && Object.keys(config.graphqlEndpoints).length === 0 && Object.keys(config.httpApis).length === 0 && Object.keys(config.cliTools).length === 0 && Object.keys(config.capletSets).length === 0) throw new CapletsError("CONFIG_INVALID", "Nested Caplet set must define at least one Caplet");
27428
27596
  return config;
27429
27597
  }
27430
27598
  function resolveProjectCapletsRootForConfigPath(projectPath) {
@@ -27446,6 +27614,7 @@ function normalizeLocalPaths(input, baseDir) {
27446
27614
  return stripUndefined({
27447
27615
  ...input,
27448
27616
  openapiEndpoints: normalizeEndpointPaths(input.openapiEndpoints, baseDir, normalizeOpenApiPath),
27617
+ googleDiscoveryApis: normalizeEndpointPaths(input.googleDiscoveryApis, baseDir, normalizeGoogleDiscoveryPath),
27449
27618
  graphqlEndpoints: normalizeEndpointPaths(input.graphqlEndpoints, baseDir, normalizeGraphQlPath),
27450
27619
  cliTools: normalizeEndpointPaths(input.cliTools, baseDir, normalizeCliToolsPaths),
27451
27620
  capletSets: normalizeEndpointPaths(input.capletSets, baseDir, normalizeCapletSetPaths)
@@ -27461,6 +27630,12 @@ function normalizeOpenApiPath(endpoint, baseDir) {
27461
27630
  specPath: normalizeLocalPath(endpoint.specPath, baseDir)
27462
27631
  };
27463
27632
  }
27633
+ function normalizeGoogleDiscoveryPath(endpoint, baseDir) {
27634
+ return {
27635
+ ...endpoint,
27636
+ discoveryPath: normalizeLocalPath(endpoint.discoveryPath, baseDir)
27637
+ };
27638
+ }
27464
27639
  function normalizeGraphQlPath(endpoint, baseDir) {
27465
27640
  const operations = isPlainObject$5(endpoint.operations) ? Object.fromEntries(Object.entries(endpoint.operations).map(([name, operation]) => [name, isPlainObject$5(operation) ? {
27466
27641
  ...operation,
@@ -27496,6 +27671,7 @@ function normalizeLocalPath(value, baseDir) {
27496
27671
  }
27497
27672
  function rejectProjectConfigExecutableBackendMaps(input, path) {
27498
27673
  if (input.openapiEndpoints && Object.keys(input.openapiEndpoints).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map openapiEndpoints; use project Markdown Caplet files or user config instead`);
27674
+ if (input.googleDiscoveryApis && Object.keys(input.googleDiscoveryApis).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map googleDiscoveryApis; use project Markdown Caplet files or user config instead`);
27499
27675
  if (input.graphqlEndpoints && Object.keys(input.graphqlEndpoints).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map graphqlEndpoints; use project Markdown Caplet files or user config instead`);
27500
27676
  if (input.httpApis && Object.keys(input.httpApis).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map httpApis; use project Markdown Caplet files or user config instead`);
27501
27677
  if (input.cliTools && Object.keys(input.cliTools).length > 0) throw new CapletsError("CONFIG_INVALID", `Project config at ${path} cannot define executable backend map cliTools; use project Markdown Caplet files or user config instead`);
@@ -27517,6 +27693,10 @@ function mergeConfigInputs(...inputs) {
27517
27693
  ...merged?.openapiEndpoints,
27518
27694
  ...input.openapiEndpoints
27519
27695
  },
27696
+ googleDiscoveryApis: {
27697
+ ...merged?.googleDiscoveryApis,
27698
+ ...input.googleDiscoveryApis
27699
+ },
27520
27700
  graphqlEndpoints: {
27521
27701
  ...merged?.graphqlEndpoints,
27522
27702
  ...input.graphqlEndpoints
@@ -27560,6 +27740,7 @@ function mergeConfigInputsWithSources(...inputs) {
27560
27740
  function removeCapletId(input, id) {
27561
27741
  const { [id]: _mcpServer, ...mcpServers } = input.mcpServers ?? {};
27562
27742
  const { [id]: _openapiEndpoint, ...openapiEndpoints } = input.openapiEndpoints ?? {};
27743
+ const { [id]: _googleDiscoveryApi, ...googleDiscoveryApis } = input.googleDiscoveryApis ?? {};
27563
27744
  const { [id]: _graphqlEndpoint, ...graphqlEndpoints } = input.graphqlEndpoints ?? {};
27564
27745
  const { [id]: _httpApi, ...httpApis } = input.httpApis ?? {};
27565
27746
  const { [id]: _cliTools, ...cliTools } = input.cliTools ?? {};
@@ -27568,6 +27749,7 @@ function removeCapletId(input, id) {
27568
27749
  ...input,
27569
27750
  mcpServers,
27570
27751
  openapiEndpoints,
27752
+ googleDiscoveryApis,
27571
27753
  graphqlEndpoints,
27572
27754
  httpApis,
27573
27755
  cliTools,
@@ -27578,6 +27760,7 @@ function capletIds(input) {
27578
27760
  return [
27579
27761
  ...Object.keys(input.mcpServers ?? {}),
27580
27762
  ...Object.keys(input.openapiEndpoints ?? {}),
27763
+ ...Object.keys(input.googleDiscoveryApis ?? {}),
27581
27764
  ...Object.keys(input.graphqlEndpoints ?? {}),
27582
27765
  ...Object.keys(input.httpApis ?? {}),
27583
27766
  ...Object.keys(input.cliTools ?? {}),
@@ -27609,6 +27792,12 @@ function parseConfig(input) {
27609
27792
  server,
27610
27793
  backend: "openapi"
27611
27794
  });
27795
+ const googleDiscoveryApis = {};
27796
+ for (const [server, raw] of Object.entries(parsed.data.googleDiscoveryApis)) googleDiscoveryApis[server] = stripUndefined({
27797
+ ...raw,
27798
+ server,
27799
+ backend: "googleDiscovery"
27800
+ });
27612
27801
  const graphqlEndpoints = {};
27613
27802
  for (const [server, raw] of Object.entries(parsed.data.graphqlEndpoints)) graphqlEndpoints[server] = stripUndefined({
27614
27803
  ...raw,
@@ -27645,6 +27834,7 @@ function parseConfig(input) {
27645
27834
  },
27646
27835
  mcpServers: servers,
27647
27836
  openapiEndpoints,
27837
+ googleDiscoveryApis,
27648
27838
  graphqlEndpoints,
27649
27839
  httpApis,
27650
27840
  cliTools,
@@ -27677,7 +27867,7 @@ function interpolateConfig(value, path = []) {
27677
27867
  return value;
27678
27868
  }
27679
27869
  function isPublicMetadataPath(path) {
27680
- if (path.length < 3 || path[0] !== "mcpServers" && path[0] !== "openapiEndpoints" && path[0] !== "graphqlEndpoints" && path[0] !== "httpApis" && path[0] !== "cliTools" && path[0] !== "capletSets") return false;
27870
+ if (path.length < 3 || path[0] !== "mcpServers" && path[0] !== "openapiEndpoints" && path[0] !== "googleDiscoveryApis" && path[0] !== "graphqlEndpoints" && path[0] !== "httpApis" && path[0] !== "cliTools" && path[0] !== "capletSets") return false;
27681
27871
  return NON_INTERPOLATED_SERVER_FIELDS.has(path[2] ?? "");
27682
27872
  }
27683
27873
  function isPlainObject$5(value) {
@@ -27690,6 +27880,1272 @@ function interpolateEnv(value) {
27690
27880
  return value.replace(/\$\{([A-Za-z_][A-Za-z0-9_]*)\}/g, (_match, name) => process.env[name] ?? "").replace(/\$env:([A-Za-z_][A-Za-z0-9_]*)/g, (_match, name) => process.env[name] ?? "");
27691
27881
  }
27692
27882
  //#endregion
27883
+ //#region src/google-discovery/schema.ts
27884
+ function googleDiscoverySchemaToJsonSchema(value, schemas = {}, seen = /* @__PURE__ */ new Set()) {
27885
+ if (!value) return {};
27886
+ if (value.$ref) {
27887
+ const target = schemas[value.$ref];
27888
+ if (!target || seen.has(value.$ref)) return {
27889
+ type: "object",
27890
+ additionalProperties: true
27891
+ };
27892
+ return googleDiscoverySchemaToJsonSchema(target, schemas, new Set([...seen, value.$ref]));
27893
+ }
27894
+ const type = discoveryTypeToJsonSchemaType(value.type);
27895
+ const converted = {};
27896
+ if (value.description) converted.description = collapseWhitespace$1(value.description);
27897
+ if (type) converted.type = type;
27898
+ if (value.format) converted.format = value.format;
27899
+ if (value.enum) converted.enum = value.enum;
27900
+ const defaultValue = convertedDefault(value.default, type);
27901
+ if (defaultValue !== void 0) converted.default = defaultValue;
27902
+ if (value.repeated) return {
27903
+ ...converted.description ? { description: converted.description } : {},
27904
+ type: "array",
27905
+ items: omit(converted, ["description", "default"])
27906
+ };
27907
+ if (value.items) converted.items = googleDiscoverySchemaToJsonSchema(value.items, schemas, seen);
27908
+ if (value.properties) {
27909
+ converted.type = converted.type ?? "object";
27910
+ converted.properties = Object.fromEntries(Object.entries(value.properties).map(([key, schema]) => [key, googleDiscoverySchemaToJsonSchema(schema, schemas, seen)]));
27911
+ converted.additionalProperties = false;
27912
+ }
27913
+ if (typeof value.additionalProperties === "boolean") converted.additionalProperties = value.additionalProperties;
27914
+ else if (value.additionalProperties) converted.additionalProperties = googleDiscoverySchemaToJsonSchema(value.additionalProperties, schemas, seen);
27915
+ return converted;
27916
+ }
27917
+ function discoveryTypeToJsonSchemaType(type) {
27918
+ if (type === "any") return "object";
27919
+ return type;
27920
+ }
27921
+ function convertedDefault(value, type) {
27922
+ if (value === void 0) return void 0;
27923
+ if (type === "boolean" && typeof value === "string") return value === "true";
27924
+ if ((type === "integer" || type === "number") && typeof value === "string") {
27925
+ const number = Number(value);
27926
+ return Number.isFinite(number) ? number : value;
27927
+ }
27928
+ return value;
27929
+ }
27930
+ function collapseWhitespace$1(value) {
27931
+ return value.replace(/\s+/gu, " ").trim();
27932
+ }
27933
+ function omit(value, keys) {
27934
+ return Object.fromEntries(Object.entries(value).filter(([key]) => !keys.includes(key)));
27935
+ }
27936
+ //#endregion
27937
+ //#region src/google-discovery/operations.ts
27938
+ function discoveryOperations(options) {
27939
+ const document = validateGoogleDiscoveryDocument(options.document);
27940
+ const schemas = document.schemas ?? {};
27941
+ return collectDocumentMethods(document).map((entry) => operationFromMethod(options.server, document, schemas, entry)).filter((operation) => isIncluded(operation.name, options.includeOperations)).filter((operation) => !isExcluded(operation.name, options.excludeOperations)).sort((left, right) => left.name.localeCompare(right.name));
27942
+ }
27943
+ function googleDiscoveryScopesForOperations(operations) {
27944
+ return [...new Set(operations.flatMap((operation) => operation.scopes))].sort();
27945
+ }
27946
+ function validateGoogleDiscoveryDocument(value) {
27947
+ if (!isRecord$3(value)) throw new Error("Invalid Google Discovery document: expected an object");
27948
+ if (value.kind !== void 0 && value.kind !== "discovery#restDescription") throw new Error("Invalid Google Discovery document: expected kind discovery#restDescription");
27949
+ if (value.resources !== void 0 && !isRecord$3(value.resources)) throw new Error("Invalid Google Discovery document: expected resources object");
27950
+ if (value.methods !== void 0 && !isRecord$3(value.methods)) throw new Error("Invalid Google Discovery document: expected methods object");
27951
+ if (!isRecord$3(value.resources) && !isRecord$3(value.methods)) throw new Error("Invalid Google Discovery document: expected resources or methods object");
27952
+ if (value.schemas !== void 0 && !isRecord$3(value.schemas)) throw new Error("Invalid Google Discovery document: expected schemas object");
27953
+ if (value.parameters !== void 0 && !isRecord$3(value.parameters)) throw new Error("Invalid Google Discovery document: expected parameters object");
27954
+ return value;
27955
+ }
27956
+ function collectDocumentMethods(document) {
27957
+ return [...Object.entries(document.methods ?? {}).filter((entry) => isRecord$3(entry[1])).map(([methodKey, method]) => ({
27958
+ resourcePath: [],
27959
+ methodKey,
27960
+ method
27961
+ })), ...collectMethods(document.resources ?? {})];
27962
+ }
27963
+ function collectMethods(resources, resourcePath = []) {
27964
+ const entries = [];
27965
+ for (const [resourceName, resource] of Object.entries(resources)) {
27966
+ if (!isRecord$3(resource)) continue;
27967
+ const nextPath = [...resourcePath, resourceName];
27968
+ for (const [methodKey, method] of Object.entries(resource.methods ?? {})) if (isRecord$3(method)) entries.push({
27969
+ resourcePath: nextPath,
27970
+ methodKey,
27971
+ method
27972
+ });
27973
+ entries.push(...collectMethods(resource.resources ?? {}, nextPath));
27974
+ }
27975
+ return entries;
27976
+ }
27977
+ function operationFromMethod(server, document, schemas, entry) {
27978
+ const method = normalizedHttpMethod(entry.method.httpMethod);
27979
+ const name = entry.method.id ?? [
27980
+ server,
27981
+ ...entry.resourcePath,
27982
+ entry.methodKey
27983
+ ].join(".");
27984
+ const scopes = selectGoogleDiscoveryScopes(entry.method.scopes);
27985
+ const inputSchema = buildInputSchema(document.parameters ?? {}, entry.method, schemas);
27986
+ const bodyOutputSchema = entry.method.response?.$ref ? googleDiscoverySchemaToJsonSchema(entry.method.response, schemas) : void 0;
27987
+ const outputSchema = bodyOutputSchema ? structuredOutputSchema$1(bodyOutputSchema) : void 0;
27988
+ const mediaUpload = entry.method.mediaUpload?.accept || entry.method.mediaUpload?.maxSize ? {
27989
+ ...entry.method.mediaUpload.accept ? { accept: entry.method.mediaUpload.accept } : {},
27990
+ ...entry.method.mediaUpload.maxSize ? { maxSize: entry.method.mediaUpload.maxSize } : {}
27991
+ } : void 0;
27992
+ return {
27993
+ name,
27994
+ method,
27995
+ path: entry.method.path ?? entry.method.flatPath ?? "",
27996
+ ...entry.method.description ? { description: collapseWhitespace(entry.method.description) } : {},
27997
+ inputSchema,
27998
+ ...outputSchema ? { outputSchema } : {},
27999
+ readOnlyHint: method === "get" || method === "head",
28000
+ destructiveHint: method === "delete" || /\.(delete|emptyTrash)$/u.test(name),
28001
+ scopes,
28002
+ supportsMediaUpload: entry.method.supportsMediaUpload === true,
28003
+ supportsMediaDownload: entry.method.supportsMediaDownload === true,
28004
+ ...mediaUpload ? { mediaUpload } : {},
28005
+ mediaUploadProtocols: mediaUploadProtocols(entry.method),
28006
+ parameterOrder: entry.method.parameterOrder ?? []
28007
+ };
28008
+ }
28009
+ function mediaUploadProtocols(method) {
28010
+ const protocols = { ...method.mediaUpload?.protocols };
28011
+ if (!protocols.multipart && protocols.simple?.multipart === true) protocols.multipart = protocols.simple;
28012
+ return protocols;
28013
+ }
28014
+ function selectGoogleDiscoveryScopes(scopes) {
28015
+ const preferred = [...new Set(scopes ?? [])].sort().toSorted(compareScopePreference)[0];
28016
+ return preferred ? [preferred] : [];
28017
+ }
28018
+ function compareScopePreference(left, right) {
28019
+ return scopePreferenceRank(left) - scopePreferenceRank(right) || right.length - left.length || left.localeCompare(right);
28020
+ }
28021
+ function scopePreferenceRank(scope) {
28022
+ const suffix = scope.toLowerCase().split("/").pop() ?? scope.toLowerCase();
28023
+ const tokens = suffix.split(/[._:-]+/u);
28024
+ if (tokens.includes("readonly")) return 0;
28025
+ if (tokens.includes("file")) return 1;
28026
+ if (tokens.includes("metadata") || tokens.includes("appdata")) return 2;
28027
+ if (tokens.includes("read")) return 3;
28028
+ if (suffix === "cloud-platform") return 5;
28029
+ return 4;
28030
+ }
28031
+ function structuredOutputSchema$1(bodySchema) {
28032
+ return {
28033
+ type: "object",
28034
+ additionalProperties: false,
28035
+ required: [
28036
+ "status",
28037
+ "statusText",
28038
+ "headers"
28039
+ ],
28040
+ properties: {
28041
+ status: { type: "number" },
28042
+ statusText: { type: "string" },
28043
+ headers: {
28044
+ type: "object",
28045
+ additionalProperties: false,
28046
+ required: ["content-type"],
28047
+ properties: { "content-type": { type: "string" } }
28048
+ },
28049
+ body: bodySchema
28050
+ }
28051
+ };
28052
+ }
28053
+ function buildInputSchema(globalParameters, method, schemas) {
28054
+ const groups = /* @__PURE__ */ new Map();
28055
+ const requiredByGroup = /* @__PURE__ */ new Map();
28056
+ const parameters = {
28057
+ ...globalParameters,
28058
+ ...method.parameters
28059
+ };
28060
+ for (const [name, parameter] of Object.entries(parameters)) {
28061
+ const location = parameter.location ?? "query";
28062
+ const group = groups.get(location) ?? {};
28063
+ group[name] = googleDiscoverySchemaToJsonSchema(parameter, schemas);
28064
+ groups.set(location, group);
28065
+ if (parameter.required === true) {
28066
+ const required = requiredByGroup.get(location) ?? [];
28067
+ required.push(name);
28068
+ requiredByGroup.set(location, required);
28069
+ }
28070
+ }
28071
+ if (method.request?.$ref) groups.set("body", googleDiscoverySchemaToJsonSchema(method.request, schemas));
28072
+ if (method.supportsMediaUpload === true) groups.set("media", {
28073
+ type: "object",
28074
+ additionalProperties: false,
28075
+ properties: {
28076
+ path: { type: "string" },
28077
+ artifact: { type: "string" },
28078
+ dataUrl: { type: "string" },
28079
+ mimeType: { type: "string" },
28080
+ filename: { type: "string" }
28081
+ }
28082
+ });
28083
+ const properties = {};
28084
+ const required = [];
28085
+ for (const location of [
28086
+ "path",
28087
+ "query",
28088
+ "header",
28089
+ "body",
28090
+ "media"
28091
+ ]) {
28092
+ const group = groups.get(location);
28093
+ if (!group) continue;
28094
+ if ((location === "body" || location === "media") && isJsonSchemaObject(group)) properties[location] = group;
28095
+ else {
28096
+ const groupRequired = requiredByGroup.get(location) ?? [];
28097
+ properties[location] = {
28098
+ type: "object",
28099
+ ...groupRequired.length > 0 ? { required: groupRequired } : {},
28100
+ properties: group,
28101
+ additionalProperties: false
28102
+ };
28103
+ }
28104
+ if (location === "path" || requiredByGroup.has(location)) required.push(location);
28105
+ }
28106
+ if (method.supportsMediaDownload === true) {
28107
+ properties.filename = { type: "string" };
28108
+ properties.outputPath = { type: "string" };
28109
+ }
28110
+ return {
28111
+ type: "object",
28112
+ ...required.length > 0 ? { required } : {},
28113
+ properties,
28114
+ additionalProperties: false
28115
+ };
28116
+ }
28117
+ function normalizedHttpMethod(method) {
28118
+ const normalized = method?.toLowerCase();
28119
+ if (normalized === "get" || normalized === "put" || normalized === "post" || normalized === "delete" || normalized === "patch" || normalized === "head") return normalized;
28120
+ return "get";
28121
+ }
28122
+ function isIncluded(name, includeOperations) {
28123
+ return !includeOperations?.length || includeOperations.some((pattern) => globMatches(pattern, name));
28124
+ }
28125
+ function isExcluded(name, excludeOperations) {
28126
+ return excludeOperations?.some((pattern) => globMatches(pattern, name)) === true;
28127
+ }
28128
+ function globMatches(pattern, name) {
28129
+ const patternSegments = pattern.split(".");
28130
+ const nameSegments = name.split(".");
28131
+ if (patternSegments[0] === "*" && patternSegments.length < nameSegments.length) {
28132
+ const suffix = patternSegments.slice(1);
28133
+ return suffix.every((segment, index) => segment === nameSegments[nameSegments.length - suffix.length + index]);
28134
+ }
28135
+ if (patternSegments.length !== nameSegments.length) return false;
28136
+ return patternSegments.every((segment, index) => segment === "*" || segment === nameSegments[index]);
28137
+ }
28138
+ function isJsonSchemaObject(value) {
28139
+ return value.type === "object" || "properties" in value || "additionalProperties" in value;
28140
+ }
28141
+ function isRecord$3(value) {
28142
+ return typeof value === "object" && value !== null && !Array.isArray(value);
28143
+ }
28144
+ function collapseWhitespace(value) {
28145
+ return value.replace(/\s+/gu, " ").trim();
28146
+ }
28147
+ //#endregion
28148
+ //#region src/google-discovery/request.ts
28149
+ function buildGoogleDiscoveryUrl(api, operation, args) {
28150
+ const base = api.baseUrl;
28151
+ validateBaseUrl$1(api, base);
28152
+ const url = buildOperationUrl$1(base, substitutePath$2(operation.path, asRecord$2(args.path), operation));
28153
+ appendQueryArgs(url, args);
28154
+ return url;
28155
+ }
28156
+ function buildGoogleDiscoveryUploadUrl(api, operation, uploadPath, uploadType, args) {
28157
+ const base = api.baseUrl;
28158
+ validateBaseUrl$1(api, base);
28159
+ const url = buildUploadOperationUrl(base, substitutePath$2(uploadPath, asRecord$2(args.path), operation));
28160
+ appendQueryArgs(url, args);
28161
+ url.searchParams.set("uploadType", uploadType);
28162
+ return url;
28163
+ }
28164
+ function buildJsonRequestInit(operation, args, headers) {
28165
+ for (const [key, value] of Object.entries(asRecord$2(args.header))) if (value !== void 0 && value !== null) {
28166
+ const normalized = key.toLowerCase();
28167
+ if (FORBIDDEN_HEADERS.has(normalized)) throw new CapletsError("REQUEST_INVALID", `Header ${key} cannot be supplied by arguments`);
28168
+ headers.set(key, serializeGoogleDiscoveryValue("header", key, value));
28169
+ }
28170
+ if ("body" in args) {
28171
+ headers.set("content-type", "application/json");
28172
+ return {
28173
+ method: operation.method.toUpperCase(),
28174
+ headers,
28175
+ body: JSON.stringify(args.body),
28176
+ redirect: "manual"
28177
+ };
28178
+ }
28179
+ return {
28180
+ method: operation.method.toUpperCase(),
28181
+ headers,
28182
+ redirect: "manual"
28183
+ };
28184
+ }
28185
+ function validateBaseUrl$1(api, base) {
28186
+ if (!base) throw new CapletsError("CONFIG_INVALID", `${api.server} is missing Google Discovery baseUrl`);
28187
+ if (!isAllowedRemoteUrl(base)) throw new CapletsError("CONFIG_INVALID", `${api.server} Google Discovery baseUrl is not allowed`);
28188
+ const url = new URL(base);
28189
+ if (url.username || url.password || url.search || url.hash) throw new CapletsError("CONFIG_INVALID", `${api.server} Google Discovery baseUrl must not include credentials, query, or fragment`);
28190
+ }
28191
+ function buildOperationUrl$1(base, operationPath) {
28192
+ if (/^[a-z][a-z0-9+.-]*:/iu.test(operationPath) || operationPath.startsWith("//")) throw new CapletsError("CONFIG_INVALID", "Google Discovery operation path cannot change origin");
28193
+ const baseUrl = new URL(base);
28194
+ const basePath = baseUrl.pathname.replace(/\/+$/u, "");
28195
+ const relativePath = operationPath.replace(/^\/+/u, "");
28196
+ assertSafeRelativePath(relativePath);
28197
+ baseUrl.pathname = [basePath, relativePath].filter(Boolean).join("/");
28198
+ assertInsideBasePath(baseUrl, basePath);
28199
+ return baseUrl;
28200
+ }
28201
+ function buildUploadOperationUrl(base, uploadPath) {
28202
+ if (/^[a-z][a-z0-9+.-]*:/iu.test(uploadPath) || uploadPath.startsWith("//")) throw new CapletsError("CONFIG_INVALID", "Google Discovery upload path cannot change origin");
28203
+ const baseUrl = new URL(base);
28204
+ const relativePath = uploadPath.replace(/^\/+/u, "");
28205
+ assertSafeRelativePath(relativePath);
28206
+ return uploadPath.startsWith("/") ? new URL(`/${relativePath}`, baseUrl.origin) : buildOperationUrl$1(base, uploadPath);
28207
+ }
28208
+ function appendQueryArgs(url, args) {
28209
+ for (const [key, value] of Object.entries(asRecord$2(args.query))) {
28210
+ if (value === void 0 || value === null) continue;
28211
+ if (Array.isArray(value)) {
28212
+ for (const entry of value) url.searchParams.append(key, serializeGoogleDiscoveryValue("query", key, entry));
28213
+ continue;
28214
+ }
28215
+ url.searchParams.append(key, serializeGoogleDiscoveryValue("query", key, value));
28216
+ }
28217
+ }
28218
+ function substitutePath$2(path, values, operation) {
28219
+ return path.replace(/\{([^}]+)\}/gu, (_match, expression) => {
28220
+ const reserved = expression.startsWith("+");
28221
+ const name = reserved ? expression.slice(1) : expression;
28222
+ const value = values[name];
28223
+ if (value === void 0 || value === null || value === "") throw new CapletsError("REQUEST_INVALID", `Missing required path parameter ${name}`, { tool: operation.name });
28224
+ const serialized = serializeGoogleDiscoveryValue("path", name, value);
28225
+ return reserved ? encodeReservedPathValue(serialized) : encodeURIComponent(serialized);
28226
+ });
28227
+ }
28228
+ function encodeReservedPathValue(value) {
28229
+ return value.split("/").map((segment) => encodeURIComponent(segment)).join("/");
28230
+ }
28231
+ function assertSafeRelativePath(path) {
28232
+ for (const segment of path.split("/")) {
28233
+ const decoded = safeDecodePathSegment(segment);
28234
+ if (decoded === "." || decoded === "..") throw new CapletsError("CONFIG_INVALID", "Google Discovery operation path cannot escape baseUrl");
28235
+ }
28236
+ }
28237
+ function assertInsideBasePath(url, basePath) {
28238
+ const normalizedBase = basePath === "" ? "/" : `${basePath}/`;
28239
+ if (normalizedBase === "/") return;
28240
+ const pathname = url.pathname.endsWith("/") ? url.pathname : `${url.pathname}/`;
28241
+ if (pathname !== normalizedBase && !pathname.startsWith(normalizedBase)) throw new CapletsError("CONFIG_INVALID", "Google Discovery operation path cannot escape baseUrl");
28242
+ }
28243
+ function safeDecodePathSegment(segment) {
28244
+ try {
28245
+ return decodeURIComponent(segment);
28246
+ } catch {
28247
+ return segment;
28248
+ }
28249
+ }
28250
+ function serializeGoogleDiscoveryValue(location, name, value) {
28251
+ switch (typeof value) {
28252
+ case "string":
28253
+ case "number":
28254
+ case "boolean": return String(value);
28255
+ default: throw new CapletsError("REQUEST_INVALID", `Google Discovery ${location} parameter ${name} must be a string, number, or boolean`);
28256
+ }
28257
+ }
28258
+ function asRecord$2(value) {
28259
+ return value && typeof value === "object" && !Array.isArray(value) ? value : {};
28260
+ }
28261
+ //#endregion
28262
+ //#region src/media/artifacts.ts
28263
+ function artifactUri(capletId, callId, filename) {
28264
+ return `caplets://artifacts/${encodeURIComponent(capletId)}/${encodeURIComponent(callId)}/${encodeURIComponent(filename)}`;
28265
+ }
28266
+ async function writeMediaArtifact(input) {
28267
+ const rootDir = resolve(input.rootDir ?? DEFAULT_ARTIFACT_DIR);
28268
+ const capletId = requiredSafePathSegment(input.capletId, "capletId");
28269
+ const callId = safePathSegment(input.callId ?? defaultCallId(), "call");
28270
+ const filename = safeFilename(input.suggestedFilename ?? (input.outputPath ? basename(input.outputPath) : "response.bin"));
28271
+ const target = input.outputPath ? assertInsideRoot(rootDir, input.outputPath) : assertInsideRoot(rootDir, resolve(rootDir, capletId, callId, filename));
28272
+ rejectSymlinkPathComponents(rootDir, target, true);
28273
+ const uriParts = input.outputPath ? uriPartsForOutputPath(rootDir, target) : {
28274
+ capletId,
28275
+ callId,
28276
+ filename: safeFilename(basename(target))
28277
+ };
28278
+ const bytes = Buffer.from(input.bytes);
28279
+ mkdirSync(dirname(target), {
28280
+ recursive: true,
28281
+ mode: 448
28282
+ });
28283
+ writeFileSync(target, bytes, { mode: 384 });
28284
+ chmodSync(target, 384);
28285
+ const artifactFilename = uriParts.filename;
28286
+ writeArtifactMetadata(target, input.mimeType ? { mimeType: input.mimeType } : {});
28287
+ return {
28288
+ uri: artifactUri(uriParts.capletId, uriParts.callId, artifactFilename),
28289
+ ...input.exposeLocalPath === false ? {} : { path: target },
28290
+ filename: artifactFilename,
28291
+ ...input.mimeType ? { mimeType: input.mimeType } : {},
28292
+ byteLength: bytes.byteLength,
28293
+ sha256: sha256(bytes)
28294
+ };
28295
+ }
28296
+ function resolveMediaArtifact(uri, options = {}) {
28297
+ const parsed = parseArtifactUri(uri);
28298
+ const rootDir = resolve(options.artifactRoot ?? DEFAULT_ARTIFACT_DIR);
28299
+ const path = assertInsideRoot(rootDir, resolve(rootDir, parsed.capletId, parsed.callId, parsed.filename));
28300
+ rejectSymlinkPathComponents(rootDir, path, true);
28301
+ if (!existsSync(path)) throw new CapletsError("REQUEST_INVALID", "Media artifact was not found");
28302
+ const stat = statSync(path);
28303
+ if (!stat.isFile()) throw new CapletsError("REQUEST_INVALID", "Media artifact must resolve to a file");
28304
+ if (options.maxBytes !== void 0 && stat.size > options.maxBytes) throw new CapletsError("REQUEST_INVALID", `media exceeds byte limit ${options.maxBytes}`);
28305
+ const bytes = readFileSync(path);
28306
+ const metadata = readArtifactMetadata(path);
28307
+ return {
28308
+ uri,
28309
+ path,
28310
+ filename: parsed.filename,
28311
+ ...metadata?.mimeType ? { mimeType: metadata.mimeType } : {},
28312
+ byteLength: bytes.byteLength,
28313
+ sha256: sha256(bytes)
28314
+ };
28315
+ }
28316
+ function parseArtifactUri(uri) {
28317
+ let url;
28318
+ try {
28319
+ url = new URL(uri);
28320
+ } catch {
28321
+ throw new CapletsError("REQUEST_INVALID", "Media artifact URI is invalid");
28322
+ }
28323
+ if (url.protocol !== "caplets:" || url.hostname !== "artifacts") throw new CapletsError("REQUEST_INVALID", "Media artifact URI must start with caplets://artifacts/");
28324
+ const parts = url.pathname.split("/").filter(Boolean);
28325
+ if (parts.length !== 3) throw new CapletsError("REQUEST_INVALID", "Media artifact URI is missing required parts");
28326
+ return {
28327
+ capletId: decodeSafePathSegment(parts[0], "capletId"),
28328
+ callId: decodeSafePathSegment(parts[1], "callId"),
28329
+ filename: decodeSafeFilename(parts[2])
28330
+ };
28331
+ }
28332
+ function decodeSafePathSegment(value, label) {
28333
+ const decoded = decodeArtifactUriPart(value);
28334
+ const safe = safePathSegment(decoded, "");
28335
+ if (!safe || safe !== decoded) throw new CapletsError("REQUEST_INVALID", `Media artifact URI ${label} is invalid`);
28336
+ return safe;
28337
+ }
28338
+ function decodeSafeFilename(value) {
28339
+ const decoded = decodeArtifactUriPart(value);
28340
+ const safe = safeFilename(decoded);
28341
+ if (safe !== decoded) throw new CapletsError("REQUEST_INVALID", "Media artifact URI filename is invalid");
28342
+ return safe;
28343
+ }
28344
+ function decodeArtifactUriPart(value) {
28345
+ try {
28346
+ return decodeURIComponent(value);
28347
+ } catch {
28348
+ throw new CapletsError("REQUEST_INVALID", "Media artifact URI contains invalid encoding");
28349
+ }
28350
+ }
28351
+ function assertInsideRoot(rootDir, candidate) {
28352
+ if (!isAbsolute(candidate)) throw new CapletsError("REQUEST_INVALID", "Media artifact outputPath must be absolute");
28353
+ const resolvedRoot = resolve(rootDir);
28354
+ const resolved = resolve(candidate);
28355
+ const rel = relative(resolvedRoot, resolved);
28356
+ if (rel.startsWith("..") || isAbsolute(rel)) throw new CapletsError("REQUEST_INVALID", "Media artifact outputPath must stay inside the artifact root");
28357
+ return resolved;
28358
+ }
28359
+ function rejectSymlinkPathComponents(rootDir, target, includeTarget) {
28360
+ const resolvedRoot = resolve(rootDir);
28361
+ rejectSymlinkRoot(resolvedRoot);
28362
+ const parts = relative(resolvedRoot, resolve(target)).split(/[\\/]+/u).filter(Boolean);
28363
+ let current = resolvedRoot;
28364
+ const limit = includeTarget ? parts.length : Math.max(0, parts.length - 1);
28365
+ for (let index = 0; index < limit; index += 1) {
28366
+ current = resolve(current, parts[index]);
28367
+ try {
28368
+ if (lstatSync(current).isSymbolicLink()) throw new CapletsError("REQUEST_INVALID", "Media artifact path must not contain symlinks");
28369
+ } catch (error) {
28370
+ if (error instanceof CapletsError) throw error;
28371
+ if (error.code === "ENOENT") return;
28372
+ throw error;
28373
+ }
28374
+ }
28375
+ }
28376
+ function rejectSymlinkRoot(rootDir) {
28377
+ try {
28378
+ if (lstatSync(rootDir).isSymbolicLink()) throw new CapletsError("REQUEST_INVALID", "Media artifact root must not be a symlink");
28379
+ } catch (error) {
28380
+ if (error instanceof CapletsError) throw error;
28381
+ if (error.code === "ENOENT") return;
28382
+ throw error;
28383
+ }
28384
+ }
28385
+ function uriPartsForOutputPath(rootDir, target) {
28386
+ const parts = relative(resolve(rootDir), target).split(/[\\/]+/u).filter(Boolean);
28387
+ if (parts.length !== 3) throw new CapletsError("REQUEST_INVALID", "Media artifact outputPath must be under <artifact-root>/<caplet-id>/<call-id>/<filename>");
28388
+ return {
28389
+ capletId: requireAlreadySafePathSegment(parts[0], "capletId"),
28390
+ callId: requireAlreadySafePathSegment(parts[1], "callId"),
28391
+ filename: requireAlreadySafeFilename(parts[2])
28392
+ };
28393
+ }
28394
+ function requiredSafePathSegment(value, label) {
28395
+ const safe = safePathSegment(value, "");
28396
+ if (!safe) throw new CapletsError("REQUEST_INVALID", `Media artifact ${label} is required`);
28397
+ return safe;
28398
+ }
28399
+ function requireAlreadySafePathSegment(value, label) {
28400
+ const safe = requiredSafePathSegment(value, label);
28401
+ if (safe !== value) throw new CapletsError("REQUEST_INVALID", `Media artifact outputPath ${label} is invalid`);
28402
+ return safe;
28403
+ }
28404
+ function requireAlreadySafeFilename(value) {
28405
+ const safe = safeFilename(value);
28406
+ if (safe !== value) throw new CapletsError("REQUEST_INVALID", "Media artifact outputPath filename is invalid");
28407
+ return safe;
28408
+ }
28409
+ function safePathSegment(value, fallback) {
28410
+ return safeFilename(value, fallback);
28411
+ }
28412
+ function safeFilename(value, fallback = "response.bin") {
28413
+ const name = basename(value).trim().replace(/[^\w.-]+/gu, "_");
28414
+ return name && name !== "." && name !== ".." ? name : fallback;
28415
+ }
28416
+ function defaultCallId() {
28417
+ return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/gu, "-")}-${randomUUID()}`;
28418
+ }
28419
+ function sha256(bytes) {
28420
+ return createHash("sha256").update(bytes).digest("hex");
28421
+ }
28422
+ function artifactMetadataPath(path) {
28423
+ return `${path}.caplets.json`;
28424
+ }
28425
+ function writeArtifactMetadata(path, metadata) {
28426
+ const metadataPath = artifactMetadataPath(path);
28427
+ if (!metadata.mimeType) {
28428
+ rmSync(metadataPath, { force: true });
28429
+ return;
28430
+ }
28431
+ writeFileSync(metadataPath, `${JSON.stringify(metadata)}\n`, { mode: 384 });
28432
+ chmodSync(metadataPath, 384);
28433
+ }
28434
+ function readArtifactMetadata(path) {
28435
+ const metadataPath = artifactMetadataPath(path);
28436
+ if (!existsSync(metadataPath)) return void 0;
28437
+ let parsed;
28438
+ try {
28439
+ parsed = JSON.parse(readFileSync(metadataPath, "utf8"));
28440
+ } catch {
28441
+ throw new CapletsError("REQUEST_INVALID", "Media artifact metadata is invalid");
28442
+ }
28443
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new CapletsError("REQUEST_INVALID", "Media artifact metadata is invalid");
28444
+ const value = parsed;
28445
+ return typeof value.mimeType === "string" && value.mimeType ? { mimeType: value.mimeType } : {};
28446
+ }
28447
+ //#endregion
28448
+ //#region src/media/input.ts
28449
+ const DEFAULT_MAX_MEDIA_BYTES = 100 * 1024 * 1024;
28450
+ async function readMediaInput(input, options = {}) {
28451
+ if (!input || typeof input !== "object" || Array.isArray(input)) throw new CapletsError("REQUEST_INVALID", "media must be an object");
28452
+ const media = input;
28453
+ if ([
28454
+ "path",
28455
+ "artifact",
28456
+ "dataUrl"
28457
+ ].filter((key) => typeof media[key] === "string").length !== 1) throw new CapletsError("REQUEST_INVALID", "media must define exactly one of path, artifact, or dataUrl");
28458
+ const filename = typeof media.filename === "string" ? media.filename : void 0;
28459
+ const mimeType = typeof media.mimeType === "string" ? media.mimeType : void 0;
28460
+ if (typeof media.path === "string") {
28461
+ if (options.allowLocalPaths === false) throw new CapletsError("REQUEST_INVALID", "media.path is not available in this runtime");
28462
+ enforceSize(statMediaFile(media.path).size, options.maxBytes);
28463
+ const resolvedFilename = filename ?? basename(media.path);
28464
+ const resolvedMimeType = mimeType ?? mimeTypeFromFilename(resolvedFilename);
28465
+ return {
28466
+ bytes: readMediaFile(media.path),
28467
+ filename: resolvedFilename,
28468
+ ...resolvedMimeType ? { mimeType: resolvedMimeType } : {}
28469
+ };
28470
+ }
28471
+ if (typeof media.artifact === "string") {
28472
+ const artifactOptions = {};
28473
+ if (options.artifactRoot !== void 0) artifactOptions.artifactRoot = options.artifactRoot;
28474
+ artifactOptions.maxBytes = options.maxBytes ?? DEFAULT_MAX_MEDIA_BYTES;
28475
+ const artifact = resolveMediaArtifact(media.artifact, artifactOptions);
28476
+ if (!artifact.path) throw new CapletsError("REQUEST_INVALID", "Media artifact cannot be read from this runtime");
28477
+ const resolvedMimeType = mimeType ?? artifact.mimeType;
28478
+ return {
28479
+ bytes: readMediaFile(artifact.path),
28480
+ filename: filename ?? artifact.filename,
28481
+ ...resolvedMimeType ? { mimeType: resolvedMimeType } : {}
28482
+ };
28483
+ }
28484
+ const dataUrlOptions = {};
28485
+ if (filename !== void 0) dataUrlOptions.filename = filename;
28486
+ if (mimeType !== void 0) dataUrlOptions.mimeType = mimeType;
28487
+ if (options.maxBytes !== void 0) dataUrlOptions.maxBytes = options.maxBytes;
28488
+ return readDataUrl(media.dataUrl, dataUrlOptions);
28489
+ }
28490
+ function mimeTypeFromFilename(filename) {
28491
+ switch (extname(filename).toLowerCase()) {
28492
+ case ".csv": return "text/csv";
28493
+ case ".gif": return "image/gif";
28494
+ case ".htm":
28495
+ case ".html": return "text/html";
28496
+ case ".jpeg":
28497
+ case ".jpg": return "image/jpeg";
28498
+ case ".json": return "application/json";
28499
+ case ".pdf": return "application/pdf";
28500
+ case ".png": return "image/png";
28501
+ case ".txt": return "text/plain";
28502
+ case ".webp": return "image/webp";
28503
+ case ".xml": return "application/xml";
28504
+ default: return;
28505
+ }
28506
+ }
28507
+ function readDataUrl(dataUrl, options) {
28508
+ const match = /^data:([^;,]+)(?:;[^,;=]+=[^,;]*)*;base64,([A-Za-z0-9+/=]*)$/u.exec(dataUrl);
28509
+ if (!match) throw new CapletsError("REQUEST_INVALID", "media.dataUrl must be a base64 data URL");
28510
+ const dataMimeType = match[1] ?? "";
28511
+ const base64 = match[2] ?? "";
28512
+ if (!dataMimeType || !isStrictBase64(base64)) throw new CapletsError("REQUEST_INVALID", "media.dataUrl must be a base64 data URL");
28513
+ enforceSize(decodedBase64Length(base64), options.maxBytes);
28514
+ return {
28515
+ bytes: Buffer.from(base64, "base64"),
28516
+ filename: options.filename ?? "media.bin",
28517
+ mimeType: options.mimeType ?? dataMimeType
28518
+ };
28519
+ }
28520
+ function isStrictBase64(value) {
28521
+ return value.length % 4 === 0 && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value);
28522
+ }
28523
+ function decodedBase64Length(value) {
28524
+ const padding = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
28525
+ return value.length / 4 * 3 - padding;
28526
+ }
28527
+ function statMediaFile(path) {
28528
+ try {
28529
+ const stat = statSync(path);
28530
+ if (!stat.isFile()) throw new CapletsError("REQUEST_INVALID", "media.path must reference a file");
28531
+ return stat;
28532
+ } catch (error) {
28533
+ if (error instanceof CapletsError) throw error;
28534
+ throw new CapletsError("REQUEST_INVALID", "media.path could not be read");
28535
+ }
28536
+ }
28537
+ function readMediaFile(path) {
28538
+ try {
28539
+ return readFileSync(path);
28540
+ } catch {
28541
+ throw new CapletsError("REQUEST_INVALID", "media file could not be read");
28542
+ }
28543
+ }
28544
+ function enforceSize(size, maxBytes = DEFAULT_MAX_MEDIA_BYTES) {
28545
+ if (size > maxBytes) throw new CapletsError("REQUEST_INVALID", `media exceeds byte limit ${maxBytes}`);
28546
+ }
28547
+ function parseHttpBody(contentType, text) {
28548
+ if (!text) return;
28549
+ const mime = contentType.split(";")[0]?.toLowerCase().trim() ?? "";
28550
+ if (mime !== "application/json" && !mime.endsWith("+json") && !mime.endsWith("/json")) return text;
28551
+ try {
28552
+ return JSON.parse(text);
28553
+ } catch {
28554
+ return text;
28555
+ }
28556
+ }
28557
+ async function readLimitedText(response, options) {
28558
+ if (!response.body) return "";
28559
+ const reader = response.body.getReader();
28560
+ const chunks = [];
28561
+ let bytes = 0;
28562
+ while (true) {
28563
+ const { done, value } = await reader.read();
28564
+ if (done) break;
28565
+ if (value) {
28566
+ bytes += value.byteLength;
28567
+ if (bytes > (options.maxBytes ?? 1048576)) {
28568
+ await reader.cancel();
28569
+ throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", options.errorMessage);
28570
+ }
28571
+ chunks.push(value);
28572
+ }
28573
+ }
28574
+ return new TextDecoder().decode(Buffer.concat(chunks));
28575
+ }
28576
+ function isAbortError(error) {
28577
+ return error instanceof DOMException && error.name === "AbortError";
28578
+ }
28579
+ //#endregion
28580
+ //#region src/http/response.ts
28581
+ async function readHttpLikeResponse(response, options) {
28582
+ const contentType = response.headers.get("content-type") ?? "";
28583
+ const mimeType = mimeFromContentType(contentType);
28584
+ const maxInlineBytes = options.maxInlineBytes ?? 1048576;
28585
+ const maxBytes = options.maxBytes ?? 1048576;
28586
+ const method = options.method?.toUpperCase();
28587
+ await rejectOversizedContentLength(response, maxBytes, method);
28588
+ if (method === "HEAD") return responseEnvelope(response, contentType);
28589
+ if (!options.forceArtifact && shouldInline(response, mimeType)) {
28590
+ const inline = await readInlineCandidate(response, {
28591
+ maxInlineBytes,
28592
+ maxBytes
28593
+ });
28594
+ if (!inline.exceeded) return responseEnvelope(response, contentType, parseHttpBody(contentType, new TextDecoder().decode(inline.bytes)));
28595
+ return responseEnvelope(response, contentType, { artifact: await writeResponseArtifact(response, options, mimeType, inline.bytes) });
28596
+ }
28597
+ return responseEnvelope(response, contentType, { artifact: await writeResponseArtifact(response, options, mimeType, await readBoundedBytes(response, maxBytes)) });
28598
+ }
28599
+ async function readInlineCandidate(response, options) {
28600
+ if (!response.body) return {
28601
+ bytes: Buffer.alloc(0),
28602
+ exceeded: false
28603
+ };
28604
+ const reader = response.body.getReader();
28605
+ const chunks = [];
28606
+ let bytes = 0;
28607
+ let exceeded = false;
28608
+ while (true) {
28609
+ const { done, value } = await reader.read();
28610
+ if (done) break;
28611
+ if (value) {
28612
+ bytes += value.byteLength;
28613
+ if (bytes > options.maxBytes) {
28614
+ await reader.cancel();
28615
+ throw responseExceededLimit(options.maxBytes);
28616
+ }
28617
+ if (bytes > options.maxInlineBytes) exceeded = true;
28618
+ chunks.push(value);
28619
+ }
28620
+ }
28621
+ return {
28622
+ bytes: Buffer.concat(chunks),
28623
+ exceeded
28624
+ };
28625
+ }
28626
+ async function readBoundedBytes(response, maxBytes) {
28627
+ if (!response.body) return Buffer.alloc(0);
28628
+ const reader = response.body.getReader();
28629
+ const chunks = [];
28630
+ let bytes = 0;
28631
+ while (true) {
28632
+ const { done, value } = await reader.read();
28633
+ if (done) break;
28634
+ if (value) {
28635
+ bytes += value.byteLength;
28636
+ if (bytes > maxBytes) {
28637
+ await reader.cancel();
28638
+ throw responseExceededLimit(maxBytes);
28639
+ }
28640
+ chunks.push(value);
28641
+ }
28642
+ }
28643
+ return Buffer.concat(chunks);
28644
+ }
28645
+ async function rejectOversizedContentLength(response, maxBytes, method) {
28646
+ if (method === "HEAD") return;
28647
+ const contentLength = response.headers.get("content-length");
28648
+ if (!contentLength) return;
28649
+ const byteLength = Number.parseInt(contentLength, 10);
28650
+ if (Number.isFinite(byteLength) && byteLength > maxBytes) {
28651
+ await response.body?.cancel().catch(() => {});
28652
+ throw responseExceededLimit(maxBytes);
28653
+ }
28654
+ }
28655
+ function responseExceededLimit(maxBytes) {
28656
+ return new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", `HTTP response exceeded byte limit ${maxBytes}`);
28657
+ }
28658
+ async function writeResponseArtifact(response, options, mimeType, bytes) {
28659
+ return await writeMediaArtifact({
28660
+ capletId: options.capletId,
28661
+ ...options.artifactDir ? { rootDir: options.artifactDir } : {},
28662
+ ...response.ok && options.outputPath ? { outputPath: options.outputPath } : {},
28663
+ ...options.exposeLocalPath === false ? { exposeLocalPath: false } : {},
28664
+ suggestedFilename: options.filename ?? filenameFromContentDisposition(response) ?? "response.bin",
28665
+ ...mimeType ? { mimeType } : {},
28666
+ bytes
28667
+ });
28668
+ }
28669
+ function responseEnvelope(response, contentType, body) {
28670
+ return {
28671
+ status: response.status,
28672
+ statusText: response.statusText,
28673
+ headers: { "content-type": contentType },
28674
+ ...body === void 0 ? {} : { body }
28675
+ };
28676
+ }
28677
+ function shouldInline(response, mimeType) {
28678
+ if (isAttachment(response)) return false;
28679
+ return mimeType === "" || mimeType === "application/json" || mimeType.endsWith("+json") || mimeType.endsWith("/json") || mimeType.startsWith("text/");
28680
+ }
28681
+ function isAttachment(response) {
28682
+ return /\battachment\b/iu.test(response.headers.get("content-disposition") ?? "");
28683
+ }
28684
+ function mimeFromContentType(contentType) {
28685
+ return contentType.split(";")[0]?.toLowerCase().trim() ?? "";
28686
+ }
28687
+ function filenameFromContentDisposition(response) {
28688
+ const contentDisposition = response.headers.get("content-disposition");
28689
+ if (!contentDisposition) return;
28690
+ return parseRfc5987Filename(contentDisposition) ?? parseQuotedFilename(contentDisposition);
28691
+ }
28692
+ function parseRfc5987Filename(contentDisposition) {
28693
+ const value = /(?:^|;)\s*filename\*=([^;]+)/iu.exec(contentDisposition)?.[1]?.trim();
28694
+ if (!value) return;
28695
+ const encoded = value.replace(/^UTF-8''/iu, "");
28696
+ try {
28697
+ return decodeURIComponent(encoded.replace(/^"|"$/gu, ""));
28698
+ } catch {
28699
+ return encoded;
28700
+ }
28701
+ }
28702
+ function parseQuotedFilename(contentDisposition) {
28703
+ const quoted = /(?:^|;)\s*filename="([^"]+)"/iu.exec(contentDisposition)?.[1];
28704
+ if (quoted) return quoted;
28705
+ return /(?:^|;)\s*filename=([^;]+)/iu.exec(contentDisposition)?.[1]?.trim();
28706
+ }
28707
+ //#endregion
28708
+ //#region src/google-discovery/manager.ts
28709
+ const DEFAULT_RESUMABLE_THRESHOLD_BYTES = 8 * 1024 * 1024;
28710
+ const DEFAULT_MEDIA_RESPONSE_MAX_BYTES = 100 * 1024 * 1024;
28711
+ const DEFAULT_DISCOVERY_DOCUMENT_MAX_BYTES = 20 * 1024 * 1024;
28712
+ var GoogleDiscoveryManager = class {
28713
+ registry;
28714
+ options;
28715
+ cache = /* @__PURE__ */ new Map();
28716
+ constructor(registry, options = {}) {
28717
+ this.registry = registry;
28718
+ this.options = options;
28719
+ }
28720
+ updateRegistry(registry) {
28721
+ this.registry = registry;
28722
+ }
28723
+ invalidate(serverId) {
28724
+ this.cache.delete(serverId);
28725
+ }
28726
+ async checkApi(api) {
28727
+ const startedAt = Date.now();
28728
+ try {
28729
+ const operations = await this.refreshOperations(api, true);
28730
+ this.registry.setStatus(api.server, "available");
28731
+ return {
28732
+ id: api.server,
28733
+ status: "available",
28734
+ toolCount: operations.length,
28735
+ elapsedMs: Date.now() - startedAt
28736
+ };
28737
+ } catch (error) {
28738
+ const safe = toSafeError(error, "SERVER_UNAVAILABLE");
28739
+ this.registry.setStatus(api.server, "unavailable", safe);
28740
+ return {
28741
+ id: api.server,
28742
+ status: "unavailable",
28743
+ elapsedMs: Date.now() - startedAt,
28744
+ error: safe
28745
+ };
28746
+ }
28747
+ }
28748
+ async listTools(api) {
28749
+ return (await this.refreshOperations(api, false)).map((operation) => this.toTool(operation));
28750
+ }
28751
+ async getTool(api, toolName) {
28752
+ return this.toTool(await this.getOperation(api, toolName));
28753
+ }
28754
+ async callTool(api, toolName, args) {
28755
+ const operation = await this.getOperation(api, toolName);
28756
+ const requestApi = await this.resolveRequestApi(api);
28757
+ if (operation.supportsMediaUpload && "media" in args) return this.callMediaUpload(requestApi, operation, args);
28758
+ const url = buildGoogleDiscoveryUrl(requestApi, operation, shouldRequestMediaDownload(operation, args) ? withMediaDownloadQuery(args) : args);
28759
+ const init = buildJsonRequestInit(operation, args, new Headers(await authHeaders$2(requestApi, this.options.authDir, operation.scopes)));
28760
+ const controller = new AbortController();
28761
+ const timeout = setTimeout(() => controller.abort(), requestApi.requestTimeoutMs);
28762
+ try {
28763
+ const response = await fetch(url, {
28764
+ ...init,
28765
+ signal: controller.signal
28766
+ });
28767
+ if (response.status >= 300 && response.status < 400) throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Google Discovery request returned a redirect", {
28768
+ server: requestApi.server,
28769
+ status: response.status,
28770
+ location: response.headers.get("location") ? "[REDACTED]" : void 0
28771
+ });
28772
+ if (response.status === 401 || response.status === 403) throw googleAuthError(requestApi, response);
28773
+ const parsed = await readHttpLikeResponse(response, {
28774
+ capletId: requestApi.server,
28775
+ method: operation.method,
28776
+ ...this.options.artifactDir ? { artifactDir: this.options.artifactDir } : {},
28777
+ ...this.options.exposeLocalArtifactPaths === false ? { exposeLocalPath: false } : {},
28778
+ ...typeof args.filename === "string" ? { filename: args.filename } : {},
28779
+ ...typeof args.outputPath === "string" ? { outputPath: args.outputPath } : {},
28780
+ maxBytes: DEFAULT_MEDIA_RESPONSE_MAX_BYTES,
28781
+ ...operation.supportsMediaDownload && (typeof args.filename === "string" || typeof args.outputPath === "string") ? { forceArtifact: true } : {}
28782
+ });
28783
+ return {
28784
+ content: markdownStructuredContent(parsed, {
28785
+ title: `${requestApi.name} call_tool ${toolName}`,
28786
+ backend: "googleDiscovery",
28787
+ operation: "call_tool",
28788
+ tool: toolName
28789
+ }),
28790
+ structuredContent: parsed,
28791
+ isError: !response.ok
28792
+ };
28793
+ } catch (error) {
28794
+ if (isAbortError(error)) throw new CapletsError("TOOL_CALL_TIMEOUT", `Google Discovery request timed out for ${requestApi.server}/${toolName}`);
28795
+ if (error instanceof CapletsError) throw error;
28796
+ throw new CapletsError("DOWNSTREAM_TOOL_ERROR", `Google Discovery request failed for ${requestApi.server}/${toolName}`, toSafeError(error));
28797
+ } finally {
28798
+ clearTimeout(timeout);
28799
+ }
28800
+ }
28801
+ async callMediaUpload(api, operation, args) {
28802
+ const mediaOptions = {};
28803
+ if (this.options.artifactDir) mediaOptions.artifactRoot = this.options.artifactDir;
28804
+ if (this.options.exposeLocalArtifactPaths === false) mediaOptions.allowLocalPaths = false;
28805
+ const media = await readMediaInput(args.media, mediaOptions);
28806
+ const headers = new Headers(await authHeaders$2(api, this.options.authDir, operation.scopes));
28807
+ const protocol = selectUploadProtocol(operation, media, args);
28808
+ const controller = new AbortController();
28809
+ const timeout = setTimeout(() => controller.abort(), api.requestTimeoutMs);
28810
+ try {
28811
+ const response = protocol === "resumable" ? await this.callResumableUpload(api, operation, args, media, headers, controller.signal) : await this.callSingleUpload(api, operation, args, media, headers, protocol, controller.signal);
28812
+ const parsed = await readHttpLikeResponse(response, {
28813
+ capletId: api.server,
28814
+ method: operation.method,
28815
+ ...this.options.artifactDir ? { artifactDir: this.options.artifactDir } : {},
28816
+ ...this.options.exposeLocalArtifactPaths === false ? { exposeLocalPath: false } : {}
28817
+ });
28818
+ return {
28819
+ content: markdownStructuredContent(parsed, {
28820
+ title: `${api.name} call_tool ${operation.name}`,
28821
+ backend: "googleDiscovery",
28822
+ operation: "call_tool",
28823
+ tool: operation.name
28824
+ }),
28825
+ structuredContent: parsed,
28826
+ isError: !response.ok
28827
+ };
28828
+ } catch (error) {
28829
+ if (isAbortError(error)) throw new CapletsError("TOOL_CALL_TIMEOUT", `Google Discovery request timed out for ${api.server}/${operation.name}`);
28830
+ if (error instanceof CapletsError) throw error;
28831
+ throw new CapletsError("DOWNSTREAM_TOOL_ERROR", `Google Discovery request failed for ${api.server}/${operation.name}`, toSafeError(error));
28832
+ } finally {
28833
+ clearTimeout(timeout);
28834
+ }
28835
+ }
28836
+ async callSingleUpload(api, operation, args, media, headers, protocol, signal) {
28837
+ const upload = operation.mediaUploadProtocols[protocol];
28838
+ if (!upload?.path) throw new CapletsError("CONFIG_INVALID", `Google Discovery ${protocol} upload path is missing`);
28839
+ return fetchGoogleRequest(api, operation, buildGoogleDiscoveryUploadUrl(api, operation, upload.path, protocol === "simple" ? "media" : "multipart", args), protocol === "simple" ? simpleUploadInit(operation, media, headers) : multipartUploadInit(operation, args.body, media, headers), { signal });
28840
+ }
28841
+ async callResumableUpload(api, operation, args, media, headers, signal) {
28842
+ const upload = operation.mediaUploadProtocols.resumable;
28843
+ if (!upload?.path) throw new CapletsError("CONFIG_INVALID", "Google Discovery resumable upload path is missing");
28844
+ const contentType = safeMediaContentType(media.mimeType);
28845
+ const startUrl = buildGoogleDiscoveryUploadUrl(api, operation, upload.path, "resumable", args);
28846
+ headers.set("content-type", "application/json; charset=UTF-8");
28847
+ headers.set("x-upload-content-type", contentType);
28848
+ headers.set("x-upload-content-length", String(media.bytes.byteLength));
28849
+ const started = await fetchGoogleRequest(api, operation, startUrl, {
28850
+ method: operation.method.toUpperCase(),
28851
+ headers,
28852
+ body: JSON.stringify(args.body ?? {}),
28853
+ redirect: "manual"
28854
+ }, { signal });
28855
+ if (!started.ok) return started;
28856
+ const location = started.headers.get("location");
28857
+ if (!location) throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Google resumable upload missing Location");
28858
+ const uploadUrl = new URL(location);
28859
+ const uploadHeaders = new Headers();
28860
+ uploadHeaders.set("content-type", contentType);
28861
+ uploadHeaders.set("content-length", String(media.bytes.byteLength));
28862
+ uploadHeaders.set("content-range", resumableContentRange(media.bytes.byteLength));
28863
+ copySessionAuthorization(api, startUrl, uploadUrl, headers, uploadHeaders);
28864
+ return fetchGoogleRequest(api, operation, uploadUrl, {
28865
+ method: "PUT",
28866
+ headers: uploadHeaders,
28867
+ body: media.bytes,
28868
+ redirect: "manual"
28869
+ }, { signal });
28870
+ }
28871
+ compact(_api, tool) {
28872
+ return {
28873
+ name: tool.name,
28874
+ ...tool.description ? { description: tool.description } : {},
28875
+ hasInputSchema: Boolean(tool.inputSchema),
28876
+ hasOutputSchema: Boolean(tool.outputSchema),
28877
+ supportsFields: Boolean(tool.outputSchema),
28878
+ ...compactToolSelectionHints(tool),
28879
+ ...compactToolSchemaHints(tool),
28880
+ ...compactToolSafetyHints(tool)
28881
+ };
28882
+ }
28883
+ search(api, tools, query, limit) {
28884
+ return searchToolList(tools, query, limit, (tool) => this.compact(api, tool));
28885
+ }
28886
+ async resolveAuthScopes(api) {
28887
+ return googleDiscoveryScopesForOperations(await this.refreshOperations(api, false));
28888
+ }
28889
+ async getOperation(api, toolName) {
28890
+ const operations = await this.refreshOperations(api, false);
28891
+ const operation = operations.find((candidate) => candidate.name === toolName);
28892
+ if (!operation) throw new CapletsError("TOOL_NOT_FOUND", `Tool ${toolName} was not found on ${api.server}`, {
28893
+ server: api.server,
28894
+ tool: toolName,
28895
+ suggestions: operations.map((candidate) => candidate.name).filter((name) => name.toLocaleLowerCase().includes(toolName.toLocaleLowerCase()[0] ?? "")).slice(0, 5)
28896
+ });
28897
+ return operation;
28898
+ }
28899
+ async refreshOperations(api, force) {
28900
+ const cached = this.cache.get(api.server);
28901
+ const cacheKey = googleDiscoveryCacheKey(api);
28902
+ const now = Date.now();
28903
+ const isFresh = cached?.operations && cached.cacheKey === cacheKey && cached.fetchedAt !== void 0 && api.operationCacheTtlMs > 0 && now - cached.fetchedAt <= api.operationCacheTtlMs;
28904
+ if (!force && isFresh) return cached.operations ?? [];
28905
+ try {
28906
+ const document = await loadGoogleDiscoveryDocument(api, this.options.authDir);
28907
+ const baseUrl = googleDiscoveryBaseUrl(api, document);
28908
+ const operations = discoveryOperations({
28909
+ server: api.server,
28910
+ document,
28911
+ ...api.includeOperations ? { includeOperations: api.includeOperations } : {},
28912
+ ...api.excludeOperations ? { excludeOperations: api.excludeOperations } : {}
28913
+ });
28914
+ this.cache.set(api.server, {
28915
+ operations,
28916
+ ...baseUrl ? { baseUrl } : {},
28917
+ fetchedAt: Date.now(),
28918
+ cacheKey
28919
+ });
28920
+ this.registry.setStatus(api.server, "available");
28921
+ return operations;
28922
+ } catch (error) {
28923
+ const safe = toSafeError(error, "DOWNSTREAM_PROTOCOL_ERROR");
28924
+ this.registry.setStatus(api.server, "unavailable", safe);
28925
+ throw new CapletsError(safe.code, `Could not load Google Discovery operations for ${api.server}`, safe);
28926
+ }
28927
+ }
28928
+ toTool(operation) {
28929
+ return {
28930
+ name: operation.name,
28931
+ ...operation.description ? { description: operation.description } : {},
28932
+ inputSchema: operation.inputSchema,
28933
+ ...operation.outputSchema ? { outputSchema: operation.outputSchema } : {},
28934
+ annotations: {
28935
+ readOnlyHint: operation.readOnlyHint,
28936
+ destructiveHint: operation.destructiveHint
28937
+ }
28938
+ };
28939
+ }
28940
+ async resolveBaseUrl(api) {
28941
+ await this.refreshOperations(api, false);
28942
+ return this.cache.get(api.server)?.baseUrl;
28943
+ }
28944
+ async resolveRequestApi(api) {
28945
+ if (api.baseUrl) return api;
28946
+ const baseUrl = await this.resolveBaseUrl(api);
28947
+ if (!baseUrl) throw new CapletsError("CONFIG_INVALID", `${api.server} is missing Google Discovery baseUrl`);
28948
+ return {
28949
+ ...api,
28950
+ baseUrl
28951
+ };
28952
+ }
28953
+ };
28954
+ function selectUploadProtocol(operation, media, args) {
28955
+ if (media.bytes.byteLength > DEFAULT_RESUMABLE_THRESHOLD_BYTES && operation.mediaUploadProtocols.resumable) return "resumable";
28956
+ if ("body" in args) {
28957
+ if (operation.mediaUploadProtocols.multipart) return "multipart";
28958
+ if (operation.mediaUploadProtocols.resumable) return "resumable";
28959
+ throw new CapletsError("CONFIG_INVALID", "Google Discovery media upload metadata requires multipart or resumable upload");
28960
+ }
28961
+ if (operation.mediaUploadProtocols.simple) return "simple";
28962
+ if (operation.mediaUploadProtocols.resumable) return "resumable";
28963
+ throw new CapletsError("CONFIG_INVALID", "Google Discovery media upload has no supported protocol");
28964
+ }
28965
+ function simpleUploadInit(operation, media, headers) {
28966
+ headers.set("content-type", safeMediaContentType(media.mimeType));
28967
+ headers.set("content-length", String(media.bytes.byteLength));
28968
+ return {
28969
+ method: operation.method.toUpperCase(),
28970
+ headers,
28971
+ body: media.bytes,
28972
+ redirect: "manual"
28973
+ };
28974
+ }
28975
+ function multipartUploadInit(operation, body, media, headers) {
28976
+ const boundary = `caplets_${randomUUID().replace(/-/gu, "")}`;
28977
+ const contentType = safeMediaContentType(media.mimeType);
28978
+ const payload = Buffer.concat([
28979
+ Buffer.from(`--${boundary}\r\ncontent-type: application/json; charset=UTF-8\r\n\r\n${JSON.stringify(body ?? {})}\r\n`),
28980
+ Buffer.from(`--${boundary}\r\ncontent-type: ${contentType}\r\n\r\n`),
28981
+ media.bytes,
28982
+ Buffer.from(`\r\n--${boundary}--\r\n`)
28983
+ ]);
28984
+ headers.set("content-type", `multipart/related; boundary=${boundary}`);
28985
+ headers.set("content-length", String(payload.byteLength));
28986
+ return {
28987
+ method: operation.method.toUpperCase(),
28988
+ headers,
28989
+ body: payload,
28990
+ redirect: "manual"
28991
+ };
28992
+ }
28993
+ function resumableContentRange(byteLength) {
28994
+ return byteLength === 0 ? "bytes */0" : `bytes 0-${byteLength - 1}/${byteLength}`;
28995
+ }
28996
+ function safeMediaContentType(mimeType) {
28997
+ const contentType = mimeType ?? "application/octet-stream";
28998
+ if (/[\r\n]/u.test(contentType)) throw new CapletsError("REQUEST_INVALID", "media.mimeType must not contain line breaks");
28999
+ return contentType;
29000
+ }
29001
+ function googleDiscoveryBaseUrl(api, document) {
29002
+ if (api.baseUrl) return api.baseUrl;
29003
+ if (document.baseUrl) return document.baseUrl;
29004
+ if (document.rootUrl && document.servicePath) return new URL(document.servicePath, document.rootUrl).toString();
29005
+ }
29006
+ async function fetchGoogleRequest(api, operation, url, init, options = {}) {
29007
+ const controller = options.signal ? void 0 : new AbortController();
29008
+ const timeout = controller ? setTimeout(() => controller.abort(), api.requestTimeoutMs) : void 0;
29009
+ try {
29010
+ const response = await fetch(url, {
29011
+ ...init,
29012
+ signal: options.signal ?? controller.signal
29013
+ });
29014
+ if (response.status >= 300 && response.status < 400) throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Google Discovery request returned a redirect", {
29015
+ server: api.server,
29016
+ status: response.status,
29017
+ location: response.headers.get("location") ? "[REDACTED]" : void 0
29018
+ });
29019
+ if (response.status === 401 || response.status === 403) throw googleAuthError(api, response);
29020
+ return response;
29021
+ } catch (error) {
29022
+ if (isAbortError(error)) throw new CapletsError("TOOL_CALL_TIMEOUT", `Google Discovery request timed out for ${api.server}/${operation.name}`);
29023
+ throw error;
29024
+ } finally {
29025
+ if (timeout) clearTimeout(timeout);
29026
+ }
29027
+ }
29028
+ async function loadGoogleDiscoveryDocument(api, authDir) {
29029
+ const source = await loadGoogleDiscoverySource(api, authDir);
29030
+ let parsed;
29031
+ try {
29032
+ parsed = JSON.parse(source);
29033
+ } catch (error) {
29034
+ throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Google Discovery document is not JSON", {
29035
+ server: api.server,
29036
+ error: error instanceof Error ? error.message : String(error)
29037
+ });
29038
+ }
29039
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Google Discovery document is not an object");
29040
+ return parsed;
29041
+ }
29042
+ async function loadGoogleDiscoverySource(api, authDir) {
29043
+ if (api.discoveryPath) return readFile(api.discoveryPath, "utf8");
29044
+ if (!api.discoveryUrl) throw new CapletsError("CONFIG_INVALID", `${api.server} is missing Google Discovery document source`);
29045
+ return fetchDiscoverySource(api, await discoveryAuthHeaders(api, authDir));
29046
+ }
29047
+ async function fetchDiscoverySource(api, headers) {
29048
+ const controller = new AbortController();
29049
+ const timeout = setTimeout(() => controller.abort(), api.requestTimeoutMs);
29050
+ try {
29051
+ const response = await fetch(api.discoveryUrl, {
29052
+ headers,
29053
+ redirect: "manual",
29054
+ signal: controller.signal
29055
+ });
29056
+ if (response.status >= 300 && response.status < 400) throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Google Discovery document request returned a redirect");
29057
+ if (!response.ok) throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Google Discovery document request failed", { status: response.status });
29058
+ return await readLimitedText(response, {
29059
+ maxBytes: DEFAULT_DISCOVERY_DOCUMENT_MAX_BYTES,
29060
+ errorMessage: "Google Discovery document exceeded byte limit"
29061
+ });
29062
+ } catch (error) {
29063
+ if (isAbortError(error)) throw new CapletsError("TOOL_CALL_TIMEOUT", "Google Discovery document request timed out");
29064
+ throw error;
29065
+ } finally {
29066
+ clearTimeout(timeout);
29067
+ }
29068
+ }
29069
+ async function discoveryAuthHeaders(api, authDir) {
29070
+ if (api.auth.type === "none") return {};
29071
+ if (api.auth.type === "oauth2" || api.auth.type === "oidc") {
29072
+ const protectedOrigin = discoveryProtectedResourceOrigin(api, authDir);
29073
+ if (!protectedOrigin || !shouldSendDiscoveryAuth(api, protectedOrigin)) return {};
29074
+ const bundle = readTokenBundle(api.server, authDir);
29075
+ if (!bundle?.accessToken && !bundle?.refreshToken) return {};
29076
+ return genericOAuthHeaders({
29077
+ ...api,
29078
+ baseUrl: protectedOrigin
29079
+ }, authDir);
29080
+ }
29081
+ if (!api.baseUrl || !shouldSendDiscoveryAuth(api, new URL(api.baseUrl).origin)) return {};
29082
+ return authHeaders$2(api, authDir);
29083
+ }
29084
+ async function authHeaders$2(api, authDir, resolvedScopes) {
29085
+ switch (api.auth.type) {
29086
+ case "none": return {};
29087
+ case "bearer": return { authorization: `Bearer ${api.auth.token}` };
29088
+ case "headers": return api.auth.headers;
29089
+ case "oauth2":
29090
+ case "oidc": return genericOAuthHeaders({
29091
+ ...api,
29092
+ resolvedScopes
29093
+ }, authDir);
29094
+ }
29095
+ }
29096
+ function discoveryProtectedResourceOrigin(api, authDir) {
29097
+ if (api.baseUrl) return new URL(api.baseUrl).origin;
29098
+ return readTokenBundle(api.server, authDir)?.protectedResourceOrigin;
29099
+ }
29100
+ function copySessionAuthorization(api, startUrl, uploadUrl, source, target) {
29101
+ const authorization = source.get("authorization");
29102
+ if (!authorization || !isAllowedUploadSessionOrigin(api, startUrl, uploadUrl)) return;
29103
+ target.set("authorization", authorization);
29104
+ }
29105
+ function isAllowedUploadSessionOrigin(api, startUrl, uploadUrl) {
29106
+ if (uploadUrl.origin === startUrl.origin) return true;
29107
+ if (api.baseUrl && uploadUrl.origin === new URL(api.baseUrl).origin) return true;
29108
+ return isGoogleApiOrigin(uploadUrl);
29109
+ }
29110
+ function isGoogleApiOrigin(url) {
29111
+ return url.protocol === "https:" && url.hostname.endsWith(".googleapis.com");
29112
+ }
29113
+ function shouldRequestMediaDownload(operation, args) {
29114
+ return operation.supportsMediaDownload && (typeof args.filename === "string" || typeof args.outputPath === "string");
29115
+ }
29116
+ function withMediaDownloadQuery(args) {
29117
+ const query = args.query && typeof args.query === "object" && !Array.isArray(args.query) ? args.query : {};
29118
+ return {
29119
+ ...args,
29120
+ query: {
29121
+ ...query,
29122
+ alt: "media"
29123
+ }
29124
+ };
29125
+ }
29126
+ function googleAuthError(api, response) {
29127
+ return new CapletsError(response.status === 401 ? "AUTH_REQUIRED" : "AUTH_FAILED", "Google Discovery authentication failed", {
29128
+ server: api.server,
29129
+ status: response.status,
29130
+ message: response.statusText,
29131
+ authType: api.auth.type,
29132
+ challenge: response.headers.get("www-authenticate") ? "[REDACTED]" : void 0,
29133
+ ...api.auth.type === "oauth2" || api.auth.type === "oidc" ? { nextAction: "run_caplets_auth_login" } : {}
29134
+ });
29135
+ }
29136
+ function shouldSendDiscoveryAuth(api, protectedResourceOrigin) {
29137
+ return Boolean(api.discoveryUrl && new URL(api.discoveryUrl).origin === protectedResourceOrigin);
29138
+ }
29139
+ function googleDiscoveryCacheKey(api) {
29140
+ return JSON.stringify({
29141
+ discoveryPath: api.discoveryPath,
29142
+ discoveryUrl: api.discoveryUrl,
29143
+ baseUrl: api.baseUrl,
29144
+ includeOperations: api.includeOperations,
29145
+ excludeOperations: api.excludeOperations
29146
+ });
29147
+ }
29148
+ //#endregion
27693
29149
  //#region ../../node_modules/.pnpm/graphql@16.14.2/node_modules/graphql/version.js
27694
29150
  var require_version = /* @__PURE__ */ __commonJSMin(((exports) => {
27695
29151
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -48082,7 +49538,7 @@ var require_utilities = /* @__PURE__ */ __commonJSMin(((exports) => {
48082
49538
  var _resolveSchemaCoordinate = require_resolveSchemaCoordinate();
48083
49539
  }));
48084
49540
  //#endregion
48085
- //#region src/http/utils.ts
49541
+ //#region src/graphql.ts
48086
49542
  var import_graphql = (/* @__PURE__ */ __commonJSMin(((exports) => {
48087
49543
  Object.defineProperty(exports, "__esModule", { value: true });
48088
49544
  Object.defineProperty(exports, "BREAK", {
@@ -49384,40 +50840,6 @@ var import_graphql = (/* @__PURE__ */ __commonJSMin(((exports) => {
49384
50840
  var _index5 = require_error();
49385
50841
  var _index6 = require_utilities();
49386
50842
  })))();
49387
- function parseHttpBody(contentType, text) {
49388
- if (!text) return;
49389
- const mime = contentType.split(";")[0]?.toLowerCase().trim() ?? "";
49390
- if (mime !== "application/json" && !mime.endsWith("+json") && !mime.endsWith("/json")) return text;
49391
- try {
49392
- return JSON.parse(text);
49393
- } catch {
49394
- return text;
49395
- }
49396
- }
49397
- async function readLimitedText(response, options) {
49398
- if (!response.body) return "";
49399
- const reader = response.body.getReader();
49400
- const chunks = [];
49401
- let bytes = 0;
49402
- while (true) {
49403
- const { done, value } = await reader.read();
49404
- if (done) break;
49405
- if (value) {
49406
- bytes += value.byteLength;
49407
- if (bytes > (options.maxBytes ?? 1048576)) {
49408
- await reader.cancel();
49409
- throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", options.errorMessage);
49410
- }
49411
- chunks.push(value);
49412
- }
49413
- }
49414
- return new TextDecoder().decode(Buffer.concat(chunks));
49415
- }
49416
- function isAbortError(error) {
49417
- return error instanceof DOMException && error.name === "AbortError";
49418
- }
49419
- //#endregion
49420
- //#region src/graphql.ts
49421
50843
  const GRAPHQL_METHOD = "POST";
49422
50844
  const SCALAR_JSON_SCHEMA = {
49423
50845
  String: { type: "string" },
@@ -49921,7 +51343,17 @@ var HttpActionManager = class {
49921
51343
  status: response.status,
49922
51344
  location: response.headers.get("location") ? "[REDACTED]" : void 0
49923
51345
  });
49924
- const parsed = await readResponse$1(response, api, Date.now() - startedAt);
51346
+ const parsed = {
51347
+ ...await readHttpLikeResponse(response, {
51348
+ capletId: api.server,
51349
+ method: operation.method,
51350
+ ...this.options.artifactDir ? { artifactDir: this.options.artifactDir } : {},
51351
+ ...this.options.exposeLocalArtifactPaths === false ? { exposeLocalPath: false } : {},
51352
+ maxInlineBytes: this.options.maxInlineBytes ?? api.maxResponseBytes,
51353
+ maxBytes: api.maxResponseBytes
51354
+ }),
51355
+ elapsedMs: Date.now() - startedAt
51356
+ };
49925
51357
  return {
49926
51358
  content: markdownStructuredContent(parsed, {
49927
51359
  title: `${api.name} call_tool ${toolName}`,
@@ -50087,23 +51519,6 @@ async function authHeaders$1(api, authDir) {
50087
51519
  }, authDir);
50088
51520
  }
50089
51521
  }
50090
- async function readResponse$1(response, api, elapsedMs) {
50091
- const contentType = response.headers.get("content-type") ?? "";
50092
- const body = parseHttpBody(contentType, await readLimitedText(response, {
50093
- maxBytes: maxResponseBytes(api),
50094
- errorMessage: "HTTP action response exceeded byte limit"
50095
- }));
50096
- return {
50097
- status: response.status,
50098
- statusText: response.statusText,
50099
- headers: { "content-type": contentType },
50100
- ...body === void 0 ? {} : { body },
50101
- elapsedMs
50102
- };
50103
- }
50104
- function maxResponseBytes(api) {
50105
- return api.maxResponseBytes;
50106
- }
50107
51522
  function validateBaseUrl(api) {
50108
51523
  if (!isAllowedRemoteUrl(api.baseUrl)) throw new CapletsError("CONFIG_INVALID", `${api.server} HTTP API baseUrl is not allowed`);
50109
51524
  const url = new URL(api.baseUrl);
@@ -59843,6 +61258,7 @@ const HTTP_METHODS = [
59843
61258
  "patch",
59844
61259
  "trace"
59845
61260
  ];
61261
+ const DEFAULT_OPENAPI_RESPONSE_MAX_BYTES = 100 * 1024 * 1024;
59846
61262
  const JSON_CONTENT_TYPES = ["application/json"];
59847
61263
  const FORBIDDEN_ARGUMENT_HEADERS = new Set([
59848
61264
  "accept",
@@ -59929,7 +61345,13 @@ var OpenApiManager = class {
59929
61345
  challenge: response.headers.get("www-authenticate") ? "[REDACTED]" : void 0,
59930
61346
  ...endpoint.auth.type === "oauth2" || endpoint.auth.type === "oidc" ? { nextAction: "run_caplets_auth_login" } : {}
59931
61347
  });
59932
- const parsed = await readResponse(response);
61348
+ const parsed = await readHttpLikeResponse(response, {
61349
+ capletId: endpoint.server,
61350
+ method: operation.method,
61351
+ ...this.options.artifactDir ? { artifactDir: this.options.artifactDir } : {},
61352
+ ...this.options.exposeLocalArtifactPaths === false ? { exposeLocalPath: false } : {},
61353
+ maxBytes: DEFAULT_OPENAPI_RESPONSE_MAX_BYTES
61354
+ });
59933
61355
  return {
59934
61356
  content: markdownStructuredContent(parsed, {
59935
61357
  title: `${endpoint.name} call_tool ${toolName}`,
@@ -60258,16 +61680,6 @@ async function authHeaders(endpoint, authDir) {
60258
61680
  function shouldSendSpecAuth(endpoint) {
60259
61681
  return Boolean(endpoint.specUrl && endpoint.baseUrl && new URL(endpoint.specUrl).origin === new URL(endpoint.baseUrl).origin);
60260
61682
  }
60261
- async function readResponse(response) {
60262
- const contentType = response.headers.get("content-type") ?? "";
60263
- const body = parseHttpBody(contentType, await readLimitedText(response, { errorMessage: "OpenAPI response exceeded byte limit" }));
60264
- return {
60265
- status: response.status,
60266
- statusText: response.statusText,
60267
- headers: { "content-type": contentType },
60268
- ...body === void 0 ? {} : { body }
60269
- };
60270
- }
60271
61683
  async function fetchWithLimit(url, timeoutMs, headers = {}) {
60272
61684
  const controller = new AbortController();
60273
61685
  const timeout = setTimeout(() => controller.abort(), timeoutMs);
@@ -60332,7 +61744,7 @@ var ServerRegistry = class {
60332
61744
  return this.allCaplets().filter((server) => !server.disabled);
60333
61745
  }
60334
61746
  get(serverId) {
60335
- const server = this.config.mcpServers[serverId] ?? this.config.openapiEndpoints[serverId] ?? this.config.graphqlEndpoints[serverId] ?? this.config.httpApis[serverId] ?? this.config.cliTools[serverId] ?? this.config.capletSets[serverId];
61747
+ const server = this.config.mcpServers[serverId] ?? this.config.openapiEndpoints[serverId] ?? this.config.googleDiscoveryApis?.[serverId] ?? this.config.graphqlEndpoints[serverId] ?? this.config.httpApis[serverId] ?? this.config.cliTools[serverId] ?? this.config.capletSets[serverId];
60336
61748
  return server?.disabled ? void 0 : server;
60337
61749
  }
60338
61750
  require(serverId) {
@@ -60378,6 +61790,7 @@ var ServerRegistry = class {
60378
61790
  return [
60379
61791
  ...Object.values(this.config.mcpServers),
60380
61792
  ...Object.values(this.config.openapiEndpoints),
61793
+ ...Object.values(this.config.googleDiscoveryApis ?? {}),
60381
61794
  ...Object.values(this.config.graphqlEndpoints),
60382
61795
  ...Object.values(this.config.httpApis),
60383
61796
  ...Object.values(this.config.cliTools),
@@ -60393,6 +61806,13 @@ function backendDetail(server) {
60393
61806
  operationCacheTtlMs: server.operationCacheTtlMs,
60394
61807
  source: server.specPath ? "specPath" : "specUrl"
60395
61808
  };
61809
+ if (server.backend === "googleDiscovery") return {
61810
+ type: "googleDiscovery",
61811
+ disabled: server.disabled,
61812
+ requestTimeoutMs: server.requestTimeoutMs,
61813
+ operationCacheTtlMs: server.operationCacheTtlMs,
61814
+ source: googleDiscoverySource(server)
61815
+ };
60396
61816
  if (server.backend === "graphql") return {
60397
61817
  type: "graphql",
60398
61818
  disabled: server.disabled,
@@ -60429,6 +61849,9 @@ function backendDetail(server) {
60429
61849
  toolCacheTtlMs: server.toolCacheTtlMs
60430
61850
  };
60431
61851
  }
61852
+ function googleDiscoverySource(server) {
61853
+ return server.discoveryPath ? "discoveryPath" : "discoveryUrl";
61854
+ }
60432
61855
  function capletSetSource(server) {
60433
61856
  return server.configPath && server.capletsRoot ? "both" : server.configPath ? "configPath" : "capletsRoot";
60434
61857
  }
@@ -60550,14 +61973,14 @@ const ajv = new import_ajv.default({
60550
61973
  });
60551
61974
  const compiledValidators = /* @__PURE__ */ new WeakMap();
60552
61975
  const MAX_SCHEMA_ERRORS = 8;
60553
- async function handleServerTool(server, request, registry, downstream, openapi, graphql, http, cli, caplets, options = {}) {
61976
+ async function handleServerTool(server, request, registry, downstream, openapi, graphql, http, cli, caplets, options = {}, googleDiscovery) {
60554
61977
  const startedAt = Date.now();
60555
61978
  const parsed = validateOperationRequest(request, registry.config.options.maxSearchLimit, server.backend);
60556
61979
  switch (parsed.operation) {
60557
61980
  case "inspect": return jsonResult(registry.detail(server), metadataFor(server, "inspect", void 0, startedAt));
60558
- case "check": return jsonResult(await backendFor(server, downstream, openapi, graphql, http, cli, caplets).check(server), metadataFor(server, "check", void 0, startedAt));
61981
+ case "check": return jsonResult(await backendFor(server, downstream, openapi, graphql, http, cli, caplets, googleDiscovery).check(server), metadataFor(server, "check", void 0, startedAt));
60559
61982
  case "tools": {
60560
- const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets);
61983
+ const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets, googleDiscovery);
60561
61984
  const page = pageItems((await backend.listTools(server)).map((tool) => backend.compact(server, tool)), parsed, registry.config.options.maxSearchLimit);
60562
61985
  return jsonResult({
60563
61986
  id: server.server,
@@ -60566,7 +61989,7 @@ async function handleServerTool(server, request, registry, downstream, openapi,
60566
61989
  }, metadataFor(server, "tools", void 0, startedAt));
60567
61990
  }
60568
61991
  case "search_tools": {
60569
- const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets);
61992
+ const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets, googleDiscovery);
60570
61993
  const tools = await backend.listTools(server);
60571
61994
  const limit = parsed.limit ?? registry.config.options.defaultSearchLimit;
60572
61995
  const page = pageItems(backend.search(server, tools, parsed.query, limit), parsed, registry.config.options.maxSearchLimit);
@@ -60578,7 +62001,7 @@ async function handleServerTool(server, request, registry, downstream, openapi,
60578
62001
  }, metadataFor(server, "search_tools", void 0, startedAt));
60579
62002
  }
60580
62003
  case "describe_tool": {
60581
- const tool = await backendFor(server, downstream, openapi, graphql, http, cli, caplets).getTool(server, parsed.name);
62004
+ const tool = await backendFor(server, downstream, openapi, graphql, http, cli, caplets, googleDiscovery).getTool(server, parsed.name);
60582
62005
  const observedOutputShape = await readObservedOutputShape(options, server, parsed.name, tool.outputSchema);
60583
62006
  return jsonResult({
60584
62007
  id: server.server,
@@ -60588,7 +62011,7 @@ async function handleServerTool(server, request, registry, downstream, openapi,
60588
62011
  }, metadataFor(server, "describe_tool", parsed.name, startedAt));
60589
62012
  }
60590
62013
  case "call_tool": {
60591
- const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets);
62014
+ const backend = backendFor(server, downstream, openapi, graphql, http, cli, caplets, googleDiscovery);
60592
62015
  const tool = await maybeGetToolForValidation(backend, server, parsed.name);
60593
62016
  validateToolArgsForAgent(tool, parsed.name, parsed.args);
60594
62017
  if (parsed.fields === void 0) {
@@ -61146,6 +62569,7 @@ function projectCallToolResult(result, outputSchema, fields, context = {}) {
61146
62569
  if (result.isError === true) return result;
61147
62570
  const structuredContent = result.structuredContent;
61148
62571
  if (!isPlainObject$2(structuredContent)) throw new CapletsError("DOWNSTREAM_PROTOCOL_ERROR", "Field selection requires the downstream tool to return object structuredContent");
62572
+ if (hasArtifactPlaceholderForSelectedFields(structuredContent, fields)) throw new CapletsError("REQUEST_INVALID", "Field selection cannot project from an artifact response. Retry without fields and read the returned artifact.");
61149
62573
  const projected = projectStructuredContent(structuredContent, outputSchema, fields);
61150
62574
  return {
61151
62575
  ...result,
@@ -61153,10 +62577,19 @@ function projectCallToolResult(result, outputSchema, fields, context = {}) {
61153
62577
  structuredContent: projected
61154
62578
  };
61155
62579
  }
62580
+ function hasArtifactPlaceholderForSelectedFields(structuredContent, fields) {
62581
+ const body = structuredContent.body;
62582
+ return isPlainObject$2(body) && isPlainObject$2(body.artifact) && isArtifactPlaceholder(body.artifact) && fields.some((field) => field === "body" || field.startsWith("body."));
62583
+ }
62584
+ function isArtifactPlaceholder(value) {
62585
+ return typeof value.uri === "string" && value.uri.startsWith("caplets://artifacts/") && typeof value.byteLength === "number" && typeof value.sha256 === "string";
62586
+ }
61156
62587
  function extractArtifacts(result) {
61157
- if (!isPlainObject$2(result) || !Array.isArray(result.content)) return [];
62588
+ if (!isPlainObject$2(result)) return [];
61158
62589
  const artifacts = [];
61159
62590
  const seen = /* @__PURE__ */ new Set();
62591
+ addStructuredArtifact(artifacts, seen, result.structuredContent);
62592
+ if (!Array.isArray(result.content)) return artifacts;
61160
62593
  for (const item of result.content) {
61161
62594
  if (!isPlainObject$2(item) || item.type !== "text" || typeof item.text !== "string") continue;
61162
62595
  const text = item.text;
@@ -61185,6 +62618,21 @@ function extractArtifacts(result) {
61185
62618
  }
61186
62619
  return artifacts;
61187
62620
  }
62621
+ function addStructuredArtifact(artifacts, seen, structuredContent) {
62622
+ if (!isPlainObject$2(structuredContent)) return;
62623
+ const body = structuredContent.body;
62624
+ if (!isPlainObject$2(body) || !isPlainObject$2(body.artifact)) return;
62625
+ const path = typeof body.artifact.path === "string" ? body.artifact.path : void 0;
62626
+ const uri = typeof body.artifact.uri === "string" ? body.artifact.uri : void 0;
62627
+ const displayPath = path ?? uri;
62628
+ if (!displayPath || seen.has(displayPath)) return;
62629
+ seen.add(displayPath);
62630
+ artifacts.push({
62631
+ kind: "file",
62632
+ displayPath,
62633
+ pathResolution: path ? "absolute" : "relative-to-mcp-server"
62634
+ });
62635
+ }
61188
62636
  function parseMarkdownLinks(text) {
61189
62637
  const links = [];
61190
62638
  let index = 0;
@@ -61276,7 +62724,7 @@ function artifactKindFromText(text) {
61276
62724
  function isPlainObject$2(value) {
61277
62725
  return Boolean(value) && typeof value === "object" && !Array.isArray(value);
61278
62726
  }
61279
- function backendFor(server, downstream, openapi, graphql, http, cli, caplets) {
62727
+ function backendFor(server, downstream, openapi, graphql, http, cli, caplets, googleDiscovery) {
61280
62728
  if (server.backend === "mcp") return {
61281
62729
  check: (...args) => downstream.checkServer(...args),
61282
62730
  listTools: (...args) => downstream.listTools(...args),
@@ -61285,6 +62733,17 @@ function backendFor(server, downstream, openapi, graphql, http, cli, caplets) {
61285
62733
  compact: (...args) => downstream.compact(...args),
61286
62734
  search: (...args) => downstream.search(...args)
61287
62735
  };
62736
+ if (server.backend === "googleDiscovery") {
62737
+ if (!googleDiscovery) throw new CapletsError("INTERNAL_ERROR", "Google Discovery manager is not configured");
62738
+ return {
62739
+ check: (...args) => googleDiscovery.checkApi(...args),
62740
+ listTools: (...args) => googleDiscovery.listTools(...args),
62741
+ getTool: (...args) => googleDiscovery.getTool(...args),
62742
+ callTool: (...args) => googleDiscovery.callTool(...args),
62743
+ compact: (...args) => googleDiscovery.compact(...args),
62744
+ search: (...args) => googleDiscovery.search(...args)
62745
+ };
62746
+ }
61288
62747
  if (server.backend === "graphql") {
61289
62748
  if (!graphql) throw new CapletsError("INTERNAL_ERROR", "GraphQL manager is not configured");
61290
62749
  return {
@@ -61409,7 +62868,7 @@ var CapletSetManager = class CapletSetManager {
61409
62868
  suggestions: nearbyCapletNames(child.registry.enabledServers(), toolName)
61410
62869
  });
61411
62870
  try {
61412
- return await handleServerTool(caplet, args, child.registry, child.downstream, child.openapi, child.graphql, child.http, child.cli, child.capletSets);
62871
+ return await handleServerTool(caplet, args, child.registry, child.downstream, child.openapi, child.graphql, child.http, child.cli, child.capletSets, {}, child.googleDiscovery);
61413
62872
  } catch (error) {
61414
62873
  return errorResult(error);
61415
62874
  }
@@ -61458,17 +62917,22 @@ var CapletSetManager = class CapletSetManager {
61458
62917
  defaultSearchLimit: config.defaultSearchLimit,
61459
62918
  maxSearchLimit: config.maxSearchLimit
61460
62919
  }));
61461
- const authOptions = this.options.authDir ? { authDir: this.options.authDir } : {};
62920
+ const sharedOptions = {
62921
+ ...this.options.authDir ? { authDir: this.options.authDir } : {},
62922
+ ...this.options.artifactDir ? { artifactDir: this.options.artifactDir } : {},
62923
+ ...this.options.exposeLocalArtifactPaths === false ? { exposeLocalArtifactPaths: false } : {}
62924
+ };
61462
62925
  const childAncestry = new Set([...ancestry, cacheKey]);
61463
62926
  child = {
61464
62927
  registry,
61465
- downstream: new DownstreamManager(registry, authOptions),
61466
- openapi: new OpenApiManager(registry, authOptions),
61467
- graphql: new GraphQLManager(registry, authOptions),
61468
- http: new HttpActionManager(registry, authOptions),
62928
+ downstream: new DownstreamManager(registry, sharedOptions),
62929
+ openapi: new OpenApiManager(registry, sharedOptions),
62930
+ graphql: new GraphQLManager(registry, sharedOptions),
62931
+ http: new HttpActionManager(registry, sharedOptions),
61469
62932
  cli: new CliToolsManager(registry),
62933
+ googleDiscovery: new GoogleDiscoveryManager(registry, sharedOptions),
61470
62934
  capletSets: new CapletSetManager(registry, {
61471
- ...authOptions,
62935
+ ...sharedOptions,
61472
62936
  ancestry: childAncestry
61473
62937
  }),
61474
62938
  cacheKey,
@@ -61767,6 +63231,7 @@ var CapletsEngine = class {
61767
63231
  registry;
61768
63232
  downstream;
61769
63233
  openapi;
63234
+ googleDiscovery;
61770
63235
  graphql;
61771
63236
  http;
61772
63237
  cli;
@@ -61796,11 +63261,12 @@ var CapletsEngine = class {
61796
63261
  const config = this.configLoader(this.paths.configPath, this.paths.projectConfigPath);
61797
63262
  this.registry = new ServerRegistry(config);
61798
63263
  this.downstream = new DownstreamManager(this.registry, selectAuthOptions(options.authDir));
61799
- this.openapi = new OpenApiManager(this.registry, selectAuthOptions(options.authDir));
63264
+ this.openapi = new OpenApiManager(this.registry, selectHttpLikeOptions(options));
63265
+ this.googleDiscovery = new GoogleDiscoveryManager(this.registry, selectHttpLikeOptions(options));
61800
63266
  this.graphql = new GraphQLManager(this.registry, selectAuthOptions(options.authDir));
61801
- this.http = new HttpActionManager(this.registry, selectAuthOptions(options.authDir));
63267
+ this.http = new HttpActionManager(this.registry, selectHttpLikeOptions(options));
61802
63268
  this.cli = new CliToolsManager(this.registry);
61803
- this.capletSets = new CapletSetManager(this.registry, selectAuthOptions(options.authDir));
63269
+ this.capletSets = new CapletSetManager(this.registry, selectHttpLikeOptions(options));
61804
63270
  this.watchDebounceMs = options.watchDebounceMs ?? 250;
61805
63271
  this.watchEnabled = options.watch ?? true;
61806
63272
  this.writeErr = options.writeErr ?? ((value) => process.stderr.write(value));
@@ -61864,7 +63330,7 @@ var CapletsEngine = class {
61864
63330
  observedOutputShapeStore: this.observedOutputShapeStore,
61865
63331
  observedOutputShapeScope: this.observedOutputShapeScope,
61866
63332
  projectFingerprint: this.projectFingerprint
61867
- });
63333
+ }, this.googleDiscovery);
61868
63334
  } catch (error) {
61869
63335
  return errorResult(error);
61870
63336
  }
@@ -61896,7 +63362,7 @@ var CapletsEngine = class {
61896
63362
  }
61897
63363
  }
61898
63364
  async completeCliWords(words) {
61899
- const { completeCliWords } = await import("./completion-Cb-pshjL.js").then((n) => n.r);
63365
+ const { completeCliWords } = await import("./completion-BC4BNWo0.js").then((n) => n.r);
61900
63366
  return await completeCliWords(words, {
61901
63367
  config: this.registry.config,
61902
63368
  managers: {
@@ -61947,16 +63413,16 @@ var CapletsEngine = class {
61947
63413
  }
61948
63414
  }
61949
63415
  async listCompletionTools(server) {
61950
- return (server.backend === "mcp" ? await this.downstream.listTools(server) : server.backend === "openapi" ? await this.openapi.listTools(server) : server.backend === "graphql" ? await this.graphql.listTools(server) : server.backend === "http" ? await this.http.listTools(server) : server.backend === "cli" ? await this.cli.listTools(server) : await this.capletSets.listTools(server)).map((tool) => ({
63416
+ return (server.backend === "mcp" ? await this.downstream.listTools(server) : server.backend === "openapi" ? await this.openapi.listTools(server) : server.backend === "googleDiscovery" ? await this.googleDiscovery.listTools(server) : server.backend === "graphql" ? await this.graphql.listTools(server) : server.backend === "http" ? await this.http.listTools(server) : server.backend === "cli" ? await this.cli.listTools(server) : await this.capletSets.listTools(server)).map((tool) => ({
61951
63417
  name: tool.name,
61952
63418
  ...tool.description ? { description: tool.description } : {}
61953
63419
  }));
61954
63420
  }
61955
63421
  async listTools(server) {
61956
- return server.backend === "mcp" ? await this.downstream.listTools(server) : server.backend === "openapi" ? await this.openapi.listTools(server) : server.backend === "graphql" ? await this.graphql.listTools(server) : server.backend === "http" ? await this.http.listTools(server) : server.backend === "cli" ? await this.cli.listTools(server) : await this.capletSets.listTools(server);
63422
+ return server.backend === "mcp" ? await this.downstream.listTools(server) : server.backend === "openapi" ? await this.openapi.listTools(server) : server.backend === "googleDiscovery" ? await this.googleDiscovery.listTools(server) : server.backend === "graphql" ? await this.graphql.listTools(server) : server.backend === "http" ? await this.http.listTools(server) : server.backend === "cli" ? await this.cli.listTools(server) : await this.capletSets.listTools(server);
61957
63423
  }
61958
63424
  async callTool(server, toolName, args) {
61959
- return server.backend === "mcp" ? await this.downstream.callTool(server, toolName, args) : server.backend === "openapi" ? await this.openapi.callTool(server, toolName, args) : server.backend === "graphql" ? await this.graphql.callTool(server, toolName, args) : server.backend === "http" ? await this.http.callTool(server, toolName, args) : server.backend === "cli" ? await this.cli.callTool(server, toolName, args) : await this.capletSets.callTool(server, toolName, args);
63425
+ return server.backend === "mcp" ? await this.downstream.callTool(server, toolName, args) : server.backend === "openapi" ? await this.openapi.callTool(server, toolName, args) : server.backend === "googleDiscovery" ? await this.googleDiscovery.callTool(server, toolName, args) : server.backend === "graphql" ? await this.graphql.callTool(server, toolName, args) : server.backend === "http" ? await this.http.callTool(server, toolName, args) : server.backend === "cli" ? await this.cli.callTool(server, toolName, args) : await this.capletSets.callTool(server, toolName, args);
61960
63426
  }
61961
63427
  async optionalMcpList(caplet, list) {
61962
63428
  try {
@@ -61982,6 +63448,7 @@ var CapletsEngine = class {
61982
63448
  this.registry = nextRegistry;
61983
63449
  this.downstream.updateRegistry(nextRegistry);
61984
63450
  this.openapi.updateRegistry(nextRegistry);
63451
+ this.googleDiscovery.updateRegistry(nextRegistry);
61985
63452
  this.graphql.updateRegistry(nextRegistry);
61986
63453
  this.http.updateRegistry(nextRegistry);
61987
63454
  this.cli.updateRegistry(nextRegistry);
@@ -62035,6 +63502,7 @@ var CapletsEngine = class {
62035
63502
  if (!(serializeCaplet(before) !== serializeCaplet(after))) continue;
62036
63503
  if (before?.backend === "mcp") await this.downstream.closeServer(serverId);
62037
63504
  if (before?.backend === "openapi" || after?.backend === "openapi" || !after) this.openapi.invalidate(serverId);
63505
+ if (before?.backend === "googleDiscovery" || after?.backend === "googleDiscovery" || !after) this.googleDiscovery.invalidate(serverId);
62038
63506
  if (before?.backend === "graphql" || after?.backend === "graphql" || !after) this.graphql.invalidate(serverId);
62039
63507
  if (before?.backend === "http" || after?.backend === "http" || !after) this.http.invalidate(serverId);
62040
63508
  if (before?.backend === "cli" || after?.backend === "cli" || !after) this.cli.invalidate(serverId);
@@ -62094,6 +63562,13 @@ var CapletsEngine = class {
62094
63562
  function selectAuthOptions(authDir) {
62095
63563
  return authDir ? { authDir } : {};
62096
63564
  }
63565
+ function selectHttpLikeOptions(options) {
63566
+ return {
63567
+ ...selectAuthOptions(options.authDir),
63568
+ ...options.artifactDir ? { artifactDir: options.artifactDir } : {},
63569
+ ...options.exposeLocalArtifactPaths === false ? { exposeLocalArtifactPaths: false } : {}
63570
+ };
63571
+ }
62097
63572
  function safeProjectFingerprint() {
62098
63573
  try {
62099
63574
  return fingerprintProjectRoot(findProjectRoot());
@@ -62136,6 +63611,7 @@ function allCaplets(config) {
62136
63611
  return [
62137
63612
  ...Object.values(config.mcpServers),
62138
63613
  ...Object.values(config.openapiEndpoints),
63614
+ ...Object.values(config.googleDiscoveryApis ?? {}),
62139
63615
  ...Object.values(config.graphqlEndpoints),
62140
63616
  ...Object.values(config.httpApis),
62141
63617
  ...Object.values(config.cliTools),
@@ -62233,7 +63709,7 @@ function capletHintText(caplet) {
62233
63709
  ].filter((value) => Boolean(value)).join(" ");
62234
63710
  }
62235
63711
  function minifyCodeModeDeclarationText(value) {
62236
- return value.replace(/^\s*export\s*\{\s*\}\s*;?\s*/u, "").replace(/\r\n?/gu, "\n").split("\n").map((line) => line.trim()).filter(Boolean).join(" ").replace(/\s+/gu, " ").replace(/\s*([{}()[\]:;,|&=])\s*/gu, "$1").replace(/\s*<\s*/gu, "<").replace(/\s*>\s*/gu, ">").replace(/\?\s*:/gu, "?:").trim();
63712
+ return value.replace(/^\s*export\s*\{\s*\}\s*;?\s*/u, "").replace(/\s*export\s*\{\s*\}\s*;?\s*$/u, "").replace(/\r\n?/gu, "\n").split("\n").map((line) => line.trim()).filter(Boolean).join(" ").replace(/\s+/gu, " ").replace(/\s*([{}()[\]:;,|&=])\s*/gu, "$1").replace(/\s*<\s*/gu, "<").replace(/\s*>\s*/gu, ">").replace(/\?\s*:/gu, "?:").trim();
62237
63713
  }
62238
63714
  function codeModeDeclarationHash(declaration) {
62239
63715
  return [
@@ -62859,6 +64335,9 @@ function isPlainObject$1(value) {
62859
64335
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
62860
64336
  }
62861
64337
  //#endregion
64338
+ //#region src/code-mode/diagnostics-builtins.generated.ts
64339
+ const CODE_MODE_DIAGNOSTICS_BUILTINS_DECLARATION = "type CodeModeBufferEncoding=\"utf8\"|\"utf-8\"|\"base64\"|\"base64url\"|\"hex\";interface CodeModeBuffer{readonly byteLength:number;readonly length:number;toString(encoding?:CodeModeBufferEncoding):string;toUint8Array():Uint8Array;}interface CodeModeBufferConstructor{from(input:string|ArrayLike<number>|ArrayBuffer|ArrayBufferView|CodeModeBuffer,encoding?:CodeModeBufferEncoding,):CodeModeBuffer;isBuffer(value:unknown):value is CodeModeBuffer;byteLength(input:string|ArrayLike<number>|ArrayBuffer|ArrayBufferView|CodeModeBuffer,encoding?:CodeModeBufferEncoding,):number;}declare const Buffer:CodeModeBufferConstructor;declare function atob(input:string):string;declare function btoa(input:string):string;type CodeModeURLSearchParamsInit=|string|Array<[string,string]>|Record<string,string>|URLSearchParams;declare class URLSearchParams{constructor(init?:CodeModeURLSearchParamsInit);append(name:string,value:string):void;delete(name:string):void;entries():IterableIterator<[string,string]>;forEach(callback:(value:string,key:string,parent:URLSearchParams)=>void):void;get(name:string):string|null;getAll(name:string):string[];has(name:string):boolean;keys():IterableIterator<string>;set(name:string,value:string):void;toString():string;values():IterableIterator<string>;[Symbol.iterator]():IterableIterator<[string,string]>;}declare class URL{constructor(input:string|URL,base?:string|URL);readonly hash:string;readonly host:string;readonly hostname:string;readonly href:string;readonly origin:string;readonly password:string;readonly pathname:string;readonly port:string;readonly protocol:string;readonly search:string;readonly searchParams:URLSearchParams;readonly username:string;toJSON():string;toString():string;}declare class TextEncoder{readonly encoding:\"utf-8\";encode(input?:string):Uint8Array;}declare class TextDecoder{readonly encoding:\"utf-8\";constructor(label?:string);decode(input?:ArrayBuffer|ArrayBufferView):string;}interface CodeModeCrypto{randomUUID():string;getRandomValues<T extends ArrayBufferView>(typedArray:T):T;}declare const crypto:CodeModeCrypto;declare function structuredClone<T>(value:T):T;type CodeModeHeadersInit=Headers|Record<string,string>|Array<[string,string]>;declare class Headers{constructor(init?:CodeModeHeadersInit);append(name:string,value:string):void;delete(name:string):void;entries():IterableIterator<[string,string]>;forEach(callback:(value:string,key:string,parent:Headers)=>void):void;get(name:string):string|null;has(name:string):boolean;keys():IterableIterator<string>;set(name:string,value:string):void;values():IterableIterator<string>;[Symbol.iterator]():IterableIterator<[string,string]>;}type CodeModeBlobPart=string|ArrayBuffer|ArrayBufferView|Blob;type CodeModeEndingType=\"transparent\"|\"native\";declare class Blob{constructor(parts?:CodeModeBlobPart[],options?:{type?:string;endings?:CodeModeEndingType},);readonly size:number;readonly type:string;arrayBuffer():Promise<ArrayBuffer>;slice(start?:number,end?:number,type?:string):Blob;text():Promise<string>;}declare class File extends Blob{constructor(parts:CodeModeBlobPart[],name:string,options?:{type?:string;lastModified?:number},);readonly lastModified:number;readonly name:string;}declare class FormData{constructor();append(name:string,value:string|Blob,filename?:string):void;delete(name:string):void;entries():IterableIterator<[string,string|File]>;get(name:string):string|File|null;getAll(name:string):Array<string|File>;has(name:string):boolean;keys():IterableIterator<string>;set(name:string,value:string|Blob,filename?:string):void;values():IterableIterator<string|File>;[Symbol.iterator]():IterableIterator<[string,string|File]>;}type CodeModeReadableStreamReadResult<T>=|{done:false;value:T}|{done:true;value?:undefined};interface ReadableStreamDefaultController<T>{enqueue(value:T):void;close():void;}interface ReadableStreamDefaultReader<T>{read():Promise<CodeModeReadableStreamReadResult<T>>;}declare class ReadableStream<T=unknown>{constructor(source?:{start?:(controller:ReadableStreamDefaultController<T>)=>void});getReader():ReadableStreamDefaultReader<T>;}interface WritableStreamDefaultWriter<T>{write(chunk:T):Promise<void>;close():Promise<void>;}declare class WritableStream<T=unknown>{constructor(sink?:{write?:(chunk:T)=>unknown;close?:()=>unknown});getWriter():WritableStreamDefaultWriter<T>;}interface TransformStreamDefaultController<T>{enqueue(value:T):void;}declare class TransformStream<I=unknown,O=unknown>{constructor(transformer?:{transform?:(chunk:I,controller:TransformStreamDefaultController<O>)=>void;flush?:(controller:ReadableStreamDefaultController<O>)=>void;});readonly readable:ReadableStream<O>;readonly writable:WritableStream<I>;}type CodeModeAbortListener=(event:{type:\"abort\";target:AbortSignal})=>void;declare class AbortSignal{readonly aborted:boolean;readonly reason:unknown;onabort:CodeModeAbortListener|null;addEventListener(type:\"abort\",listener:CodeModeAbortListener|null):void;removeEventListener(type:\"abort\",listener:CodeModeAbortListener|null):void;dispatchEvent(event:{type:\"abort\";target:AbortSignal}):boolean;throwIfAborted():void;static abort(reason?:unknown):AbortSignal;}declare class AbortController{readonly signal:AbortSignal;abort(reason?:unknown):void;}type CodeModeBodyInit=Blob|FormData|string|ArrayBuffer|ArrayBufferView|null|undefined;interface Body{readonly body:null;readonly bodyUsed:boolean;arrayBuffer():Promise<ArrayBuffer>;blob():Promise<Blob>;formData():Promise<FormData>;json():Promise<unknown>;text():Promise<string>;}declare class Request implements Body{constructor(input:string|URL|Request,init?:{method?:string;headers?:CodeModeHeadersInit;body?:CodeModeBodyInit;signal?:AbortSignal;},);readonly body:null;readonly bodyUsed:boolean;readonly headers:Headers;readonly method:string;readonly signal:AbortSignal;readonly url:string;arrayBuffer():Promise<ArrayBuffer>;blob():Promise<Blob>;clone():Request;formData():Promise<FormData>;json():Promise<unknown>;text():Promise<string>;}declare class Response implements Body{constructor(body?:CodeModeBodyInit,init?:{headers?:CodeModeHeadersInit;status?:number;statusText?:string},);readonly body:null;readonly bodyUsed:boolean;readonly headers:Headers;readonly ok:boolean;readonly redirected:false;readonly status:number;readonly statusText:string;readonly type:\"default\";readonly url:\"\";arrayBuffer():Promise<ArrayBuffer>;blob():Promise<Blob>;clone():Response;formData():Promise<FormData>;json():Promise<unknown>;text():Promise<string>;static json(data:unknown,init?:{headers?:CodeModeHeadersInit;status?:number;statusText?:string},):Response;}declare function queueMicrotask(callback:()=>void):void;type CodeModeTimerHandler=(...args:unknown[])=>void;declare function setTimeout(callback:CodeModeTimerHandler,delay?:number,...args:unknown[]):number;declare function clearTimeout(timerId:number):void;declare function setInterval(callback:CodeModeTimerHandler,delay?:number,...args:unknown[]):number;declare function clearInterval(timerId:number):void;";
64340
+ //#endregion
62862
64341
  //#region src/code-mode/static-analysis.ts
62863
64342
  var import_lib = (/* @__PURE__ */ __commonJSMin(((exports) => {
62864
64343
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -75451,7 +76930,7 @@ const PARSER_OPTIONS = {
75451
76930
  ]
75452
76931
  };
75453
76932
  function hasDirectFetchCall(code) {
75454
- return hasMatchingAstNode(code, (node) => isCallExpression(node) && isFetchCallee(node.callee));
76933
+ return hasMatchingAstNode(code, isDirectFetchCallNode);
75455
76934
  }
75456
76935
  function hasExecutableImport(code) {
75457
76936
  return hasMatchingAstNode(code, isExecutableImportNode);
@@ -75460,9 +76939,9 @@ function hasMatchingAstNode(code, predicate) {
75460
76939
  const ast = parseCode(code);
75461
76940
  if (!ast) return false;
75462
76941
  let found = false;
75463
- visitAst(ast, (node) => {
76942
+ visitAst(ast, (node, parent) => {
75464
76943
  if (found) return;
75465
- found = predicate(node);
76944
+ found = predicate(node, parent);
75466
76945
  });
75467
76946
  return found;
75468
76947
  }
@@ -75480,11 +76959,10 @@ function isExecutableImportNode(node) {
75480
76959
  function isCallExpression(node) {
75481
76960
  return (node.type === "CallExpression" || node.type === "OptionalCallExpression") && "callee" in node;
75482
76961
  }
75483
- function isFetchCallee(value) {
75484
- if (!isNode(value)) return false;
75485
- if (value.type === "Identifier") return value.name === "fetch";
75486
- if (value.type === "MemberExpression" || value.type === "OptionalMemberExpression") return isGlobalFetchMember(value);
75487
- return false;
76962
+ function isDirectFetchCallNode(node) {
76963
+ if (!isCallExpression(node) || !isNode(node.callee)) return false;
76964
+ if (isIdentifierNamed(node.callee, "fetch")) return true;
76965
+ return (node.callee.type === "MemberExpression" || node.callee.type === "OptionalMemberExpression") && isGlobalFetchMember(node.callee);
75488
76966
  }
75489
76967
  function isGlobalFetchMember(node) {
75490
76968
  if (!isIdentifierNamed(node.object, "globalThis", "window", "self")) return false;
@@ -75494,16 +76972,22 @@ function isGlobalFetchMember(node) {
75494
76972
  function isExportDeclaration(node) {
75495
76973
  return node.type === "ExportAllDeclaration" || node.type === "ExportDefaultDeclaration" || node.type === "ExportNamedDeclaration";
75496
76974
  }
75497
- function visitAst(value, visit) {
76975
+ function visitAst(value, visit, parent) {
75498
76976
  if (!isNode(value)) return;
75499
- visit(value);
76977
+ visit(value, parent);
75500
76978
  for (const [key, child] of Object.entries(value)) {
75501
76979
  if (key === "loc" || key === "start" || key === "end" || key === "extra") continue;
75502
76980
  if (Array.isArray(child)) {
75503
- for (const item of child) visitAst(item, visit);
76981
+ for (const item of child) visitAst(item, visit, {
76982
+ node: value,
76983
+ key
76984
+ });
75504
76985
  continue;
75505
76986
  }
75506
- visitAst(child, visit);
76987
+ visitAst(child, visit, {
76988
+ node: value,
76989
+ key
76990
+ });
75507
76991
  }
75508
76992
  }
75509
76993
  function isNode(value) {
@@ -75547,7 +77031,7 @@ function diagnoseCodeModeTypeScript(input) {
75547
77031
  const host = createVirtualCompilerHost(compilerOptions, {
75548
77032
  [CODE_FILE]: wrappedCode,
75549
77033
  [DECLARATION_FILE]: input.declaration,
75550
- [AMBIENT_FILE]: ambientDeclarations()
77034
+ [AMBIENT_FILE]: CODE_MODE_DIAGNOSTICS_BUILTINS_DECLARATION
75551
77035
  });
75552
77036
  const program = ts.createProgram([
75553
77037
  CODE_FILE,
@@ -75593,7 +77077,7 @@ function preflightDiagnostics(code) {
75593
77077
  if (hasDirectFetchCall(code)) diagnostics.push({
75594
77078
  code: "FETCH_UNAVAILABLE",
75595
77079
  severity: "error",
75596
- message: "Direct fetch is not available in Code Mode; use a Caplet instead."
77080
+ message: "Direct fetch is not available in Code Mode; use a Caplet instead. Cannot find name 'fetch'."
75597
77081
  });
75598
77082
  return diagnostics;
75599
77083
  }
@@ -75630,23 +77114,82 @@ function formatDiagnostic(diagnostic, syntacticDiagnostic = false) {
75630
77114
  } : {}
75631
77115
  };
75632
77116
  }
75633
- function ambientDeclarations() {
75634
- return [
75635
- "declare class URL {",
75636
- " constructor(input: string, base?: string);",
75637
- " readonly href: string;",
75638
- " readonly searchParams: URLSearchParams;",
75639
- " toString(): string;",
75640
- "}",
75641
- "declare class URLSearchParams {",
75642
- " constructor(init?: string | Record<string, string> | Array<[string, string]>);",
75643
- " get(name: string): string | null;",
75644
- " set(name: string, value: string): void;",
75645
- " has(name: string): boolean;",
75646
- " toString(): string;",
75647
- "}"
75648
- ].join("\n");
77117
+ //#endregion
77118
+ //#region src/code-mode/platform-host.ts
77119
+ const MAX_RANDOM_VALUES_BYTES = 65536;
77120
+ function installCodeModePlatformHost(context, pendingDeferreds, _options) {
77121
+ const timers = /* @__PURE__ */ new Map();
77122
+ const randomUuidBridge = context.newFunction("__caplets_platform_random_uuid", () => {
77123
+ return context.newString(randomUUID());
77124
+ });
77125
+ context.setProp(context.global, "__caplets_platform_random_uuid", randomUuidBridge);
77126
+ randomUuidBridge.dispose();
77127
+ const randomValuesBridge = context.newFunction("__caplets_platform_random_values", (lengthHandle) => {
77128
+ const length = context.dump(lengthHandle);
77129
+ if (!Number.isSafeInteger(length) || length < 0) return context.newError("Random byte length must be a non-negative safe integer");
77130
+ if (length > MAX_RANDOM_VALUES_BYTES) return context.newError("Random byte length cannot exceed 65,536 bytes");
77131
+ return numberArrayHandle(context, [...randomBytes(length)]);
77132
+ });
77133
+ context.setProp(context.global, "__caplets_platform_random_values", randomValuesBridge);
77134
+ randomValuesBridge.dispose();
77135
+ const sleepBridge = context.newFunction("__caplets_platform_sleep", (timerIdHandle, delayHandle) => {
77136
+ const timerId = context.dump(timerIdHandle);
77137
+ const delayMs = context.dump(delayHandle);
77138
+ const deferred = context.newPromise();
77139
+ pendingDeferreds.add(deferred);
77140
+ deferred.settled.finally(() => pendingDeferreds.delete(deferred));
77141
+ const timeout = setTimeout(() => {
77142
+ timers.delete(timerId);
77143
+ resolveTimer(context, deferred, true);
77144
+ }, Math.max(0, Number(delayMs) || 0));
77145
+ const existing = timers.get(timerId);
77146
+ if (existing) {
77147
+ clearTimeout(existing.timeout);
77148
+ resolveTimer(context, existing.deferred, false);
77149
+ }
77150
+ timers.set(timerId, {
77151
+ deferred,
77152
+ timeout
77153
+ });
77154
+ return deferred.handle;
77155
+ });
77156
+ context.setProp(context.global, "__caplets_platform_sleep", sleepBridge);
77157
+ sleepBridge.dispose();
77158
+ const clearTimerBridge = context.newFunction("__caplets_platform_clear_timer", (timerIdHandle) => {
77159
+ const timerId = context.dump(timerIdHandle);
77160
+ const timer = timers.get(timerId);
77161
+ if (!timer) return context.false;
77162
+ timers.delete(timerId);
77163
+ clearTimeout(timer.timeout);
77164
+ resolveTimer(context, timer.deferred, false);
77165
+ return context.true;
77166
+ });
77167
+ context.setProp(context.global, "__caplets_platform_clear_timer", clearTimerBridge);
77168
+ clearTimerBridge.dispose();
77169
+ return { dispose() {
77170
+ for (const timer of timers.values()) {
77171
+ clearTimeout(timer.timeout);
77172
+ resolveTimer(context, timer.deferred, false);
77173
+ }
77174
+ timers.clear();
77175
+ } };
75649
77176
  }
77177
+ function numberArrayHandle(context, values) {
77178
+ const arrayHandle = context.newArray();
77179
+ for (let index = 0; index < values.length; index += 1) {
77180
+ const valueHandle = context.newNumber(values[index] ?? 0);
77181
+ context.setProp(arrayHandle, index, valueHandle);
77182
+ valueHandle.dispose();
77183
+ }
77184
+ return arrayHandle;
77185
+ }
77186
+ function resolveTimer(context, deferred, fired) {
77187
+ if (!deferred.alive) return;
77188
+ deferred.resolve(fired ? context.true : context.false);
77189
+ }
77190
+ //#endregion
77191
+ //#region src/code-mode/platform-runtime.generated.ts
77192
+ const CODE_MODE_PLATFORM_RUNTIME_SOURCE = "(function() {\n //#region node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/deserialize.js\n const env = typeof self === \"object\" ? self : globalThis;\n const guard = (name, init) => {\n switch (name) {\n case \"Function\":\n case \"SharedWorker\":\n case \"Worker\":\n case \"eval\":\n case \"setInterval\":\n case \"setTimeout\": throw new TypeError(\"unable to deserialize \" + name);\n }\n return new env[name](init);\n };\n const deserializer = ($, _) => {\n const as = (out, index) => {\n $.set(index, out);\n return out;\n };\n const unpair = (index) => {\n if ($.has(index)) return $.get(index);\n const [type, value] = _[index];\n switch (type) {\n case 0:\n case -1: return as(value, index);\n case 1: {\n const arr = as([], index);\n for (const index of value) arr.push(unpair(index));\n return arr;\n }\n case 2: {\n const object = as({}, index);\n for (const [key, index] of value) object[unpair(key)] = unpair(index);\n return object;\n }\n case 3: return as(new Date(value), index);\n case 4: {\n const { source, flags } = value;\n return as(new RegExp(source, flags), index);\n }\n case 5: {\n const map = as(/* @__PURE__ */ new Map(), index);\n for (const [key, index] of value) map.set(unpair(key), unpair(index));\n return map;\n }\n case 6: {\n const set = as(/* @__PURE__ */ new Set(), index);\n for (const index of value) set.add(unpair(index));\n return set;\n }\n case 7: {\n const { name, message } = value;\n return as(guard(name, message), index);\n }\n case 8: return as(BigInt(value), index);\n case \"BigInt\": return as(Object(BigInt(value)), index);\n case \"ArrayBuffer\": return as(new Uint8Array(value).buffer, value);\n case \"DataView\": {\n const { buffer } = new Uint8Array(value);\n return as(new DataView(buffer), value);\n }\n }\n return as(guard(type, value), index);\n };\n return unpair;\n };\n /**\n * @typedef {Array<string,any>} Record a type representation\n */\n /**\n * Returns a deserialized value from a serialized array of Records.\n * @param {Record[]} serialized a previously serialized value.\n * @returns {any}\n */\n const deserialize = (serialized) => deserializer(/* @__PURE__ */ new Map(), serialized)(0);\n //#endregion\n //#region node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/serialize.js\n const EMPTY = \"\";\n const { toString } = {};\n const { keys } = Object;\n const typeOf = (value) => {\n const type = typeof value;\n if (type !== \"object\" || !value) return [0, type];\n const asString = toString.call(value).slice(8, -1);\n switch (asString) {\n case \"Array\": return [1, EMPTY];\n case \"Object\": return [2, EMPTY];\n case \"Date\": return [3, EMPTY];\n case \"RegExp\": return [4, EMPTY];\n case \"Map\": return [5, EMPTY];\n case \"Set\": return [6, EMPTY];\n case \"DataView\": return [1, asString];\n }\n if (asString.includes(\"Array\")) return [1, asString];\n if (asString.includes(\"Error\")) return [7, asString];\n return [2, asString];\n };\n const shouldSkip = ([TYPE, type]) => TYPE === 0 && (type === \"function\" || type === \"symbol\");\n const serializer = (strict, json, $, _) => {\n const as = (out, value) => {\n const index = _.push(out) - 1;\n $.set(value, index);\n return index;\n };\n const pair = (value) => {\n if ($.has(value)) return $.get(value);\n let [TYPE, type] = typeOf(value);\n switch (TYPE) {\n case 0: {\n let entry = value;\n switch (type) {\n case \"bigint\":\n TYPE = 8;\n entry = value.toString();\n break;\n case \"function\":\n case \"symbol\":\n if (strict) throw new TypeError(\"unable to serialize \" + type);\n entry = null;\n break;\n case \"undefined\": return as([-1], value);\n }\n return as([TYPE, entry], value);\n }\n case 1: {\n if (type) {\n let spread = value;\n if (type === \"DataView\") spread = new Uint8Array(value.buffer);\n else if (type === \"ArrayBuffer\") spread = new Uint8Array(value);\n return as([type, [...spread]], value);\n }\n const arr = [];\n const index = as([TYPE, arr], value);\n for (const entry of value) arr.push(pair(entry));\n return index;\n }\n case 2: {\n if (type) switch (type) {\n case \"BigInt\": return as([type, value.toString()], value);\n case \"Boolean\":\n case \"Number\":\n case \"String\": return as([type, value.valueOf()], value);\n }\n if (json && \"toJSON\" in value) return pair(value.toJSON());\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const key of keys(value)) if (strict || !shouldSkip(typeOf(value[key]))) entries.push([pair(key), pair(value[key])]);\n return index;\n }\n case 3: return as([TYPE, value.toISOString()], value);\n case 4: {\n const { source, flags } = value;\n return as([TYPE, {\n source,\n flags\n }], value);\n }\n case 5: {\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const [key, entry] of value) if (strict || !(shouldSkip(typeOf(key)) || shouldSkip(typeOf(entry)))) entries.push([pair(key), pair(entry)]);\n return index;\n }\n case 6: {\n const entries = [];\n const index = as([TYPE, entries], value);\n for (const entry of value) if (strict || !shouldSkip(typeOf(entry))) entries.push(pair(entry));\n return index;\n }\n }\n const { message } = value;\n return as([TYPE, {\n name: type,\n message\n }], value);\n };\n return pair;\n };\n /**\n * @typedef {Array<string,any>} Record a type representation\n */\n /**\n * Returns an array of serialized Records.\n * @param {any} value a serializable value.\n * @param {{json?: boolean, lossy?: boolean}?} options an object with a `lossy` or `json` property that,\n * if `true`, will not throw errors on incompatible types, and behave more\n * like JSON stringify would behave. Symbol and Function will be discarded.\n * @returns {Record[]}\n */\n const serialize = (value, { json, lossy } = {}) => {\n const _ = [];\n return serializer(!(json || lossy), !!json, /* @__PURE__ */ new Map(), _)(value), _;\n };\n //#endregion\n //#region node_modules/.pnpm/@ungap+structured-clone@1.3.1/node_modules/@ungap/structured-clone/esm/index.js\n /**\n * @typedef {Array<string,any>} Record a type representation\n */\n /**\n * Returns an array of serialized Records.\n * @param {any} any a serializable value.\n * @param {{transfer?: any[], json?: boolean, lossy?: boolean}?} options an object with\n * a transfer option (ignored when polyfilled) and/or non standard fields that\n * fallback to the polyfill if present.\n * @returns {Record[]}\n */\n var esm_default = typeof structuredClone === \"function\" ? (any, options) => options && (\"json\" in options || \"lossy\" in options) ? deserialize(serialize(any, options)) : structuredClone(any) : (any, options) => deserialize(serialize(any, options));\n //#endregion\n //#region node_modules/.pnpm/formdata-node@6.0.3/node_modules/formdata-node/lib/form-data.js\n var __accessCheck = (obj, member, msg) => {\n if (!member.has(obj)) throw TypeError(\"Cannot \" + msg);\n };\n var __privateGet = (obj, member, getter) => {\n __accessCheck(obj, member, \"read from private field\");\n return getter ? getter.call(obj) : member.get(obj);\n };\n var __privateAdd = (obj, member, value) => {\n if (member.has(obj)) throw TypeError(\"Cannot add the same private member more than once\");\n member instanceof WeakSet ? member.add(obj) : member.set(obj, value);\n };\n var __privateSet = (obj, member, value, setter) => {\n __accessCheck(obj, member, \"write to private field\");\n setter ? setter.call(obj, value) : member.set(obj, value);\n return value;\n };\n var __privateMethod = (obj, member, method) => {\n __accessCheck(obj, member, \"access private method\");\n return method;\n };\n var isFunction = (value) => typeof value === \"function\";\n var isObject = (value) => typeof value === \"object\" && value != null && !Array.isArray(value);\n var isAsyncIterable = (value) => isObject(value) && isFunction(value[Symbol.asyncIterator]);\n var MAX_CHUNK_SIZE = 65536;\n async function* clonePart(value) {\n if (value.byteLength <= MAX_CHUNK_SIZE) {\n yield value;\n return;\n }\n let offset = 0;\n while (offset < value.byteLength) {\n const size = Math.min(value.byteLength - offset, MAX_CHUNK_SIZE);\n const buffer = value.buffer.slice(offset, offset + size);\n offset += buffer.byteLength;\n yield new Uint8Array(buffer);\n }\n }\n async function* readStream(readable) {\n const reader = readable.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n yield value;\n }\n }\n async function* chunkStream(stream) {\n for await (const value of stream) yield* clonePart(value);\n }\n var getStreamIterator = (source) => {\n if (isAsyncIterable(source)) return chunkStream(source);\n if (isFunction(source.getReader)) return chunkStream(readStream(source));\n throw new TypeError(\"Unsupported data source: Expected either ReadableStream or async iterable.\");\n };\n async function* consumeNodeBlob(blob) {\n let position = 0;\n while (position !== blob.size) {\n const buffer = await blob.slice(position, Math.min(blob.size, position + MAX_CHUNK_SIZE)).arrayBuffer();\n position += buffer.byteLength;\n yield new Uint8Array(buffer);\n }\n }\n async function* consumeBlobParts(parts, clone = false) {\n for (const part of parts) if (ArrayBuffer.isView(part)) if (clone) yield* clonePart(part);\n else yield part;\n else if (isFunction(part.stream)) yield* getStreamIterator(part.stream());\n else yield* consumeNodeBlob(part);\n }\n function* sliceBlob(blobParts, blobSize, start = 0, end) {\n end ??= blobSize;\n let relativeStart = start < 0 ? Math.max(blobSize + start, 0) : Math.min(start, blobSize);\n let relativeEnd = end < 0 ? Math.max(blobSize + end, 0) : Math.min(end, blobSize);\n const span = Math.max(relativeEnd - relativeStart, 0);\n let added = 0;\n for (const part of blobParts) {\n if (added >= span) break;\n const partSize = ArrayBuffer.isView(part) ? part.byteLength : part.size;\n if (relativeStart && partSize <= relativeStart) {\n relativeStart -= partSize;\n relativeEnd -= partSize;\n } else {\n let chunk;\n if (ArrayBuffer.isView(part)) {\n chunk = part.subarray(relativeStart, Math.min(partSize, relativeEnd));\n added += chunk.byteLength;\n } else {\n chunk = part.slice(relativeStart, Math.min(partSize, relativeEnd));\n added += chunk.size;\n }\n relativeEnd -= partSize;\n relativeStart = 0;\n yield chunk;\n }\n }\n }\n var _parts, _type, _size;\n var _Blob = class _Blob {\n /**\n * Returns a new [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object.\n * The content of the blob consists of the concatenation of the values given in the parameter array.\n *\n * @param blobParts An `Array` strings, or [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), [`ArrayBufferView`](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView), [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects, or a mix of any of such objects, that will be put inside the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n * @param options An optional object of type `BlobPropertyBag`.\n */\n constructor(blobParts = [], options = {}) {\n /**\n * An `Array` of [`ArrayBufferView`](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView) or [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects, or a mix of any of such objects, that will be put inside the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n */\n __privateAdd(this, _parts, []);\n /**\n * Returns the [`MIME type`](https://developer.mozilla.org/en-US/docs/Glossary/MIME_type) of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).\n */\n __privateAdd(this, _type, \"\");\n /**\n * Returns the size of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) in bytes.\n */\n __privateAdd(this, _size, 0);\n options ??= {};\n if (typeof blobParts !== \"object\" || blobParts === null) throw new TypeError(\"Failed to construct 'Blob': The provided value cannot be converted to a sequence.\");\n if (!isFunction(blobParts[Symbol.iterator])) throw new TypeError(\"Failed to construct 'Blob': The object must have a callable @@iterator property.\");\n if (typeof options !== \"object\" && !isFunction(options)) throw new TypeError(\"Failed to construct 'Blob': parameter 2 cannot convert to dictionary.\");\n const encoder = new TextEncoder();\n for (const raw of blobParts) {\n let part;\n if (ArrayBuffer.isView(raw)) part = new Uint8Array(raw.buffer.slice(raw.byteOffset, raw.byteOffset + raw.byteLength));\n else if (raw instanceof ArrayBuffer) part = new Uint8Array(raw.slice(0));\n else if (raw instanceof _Blob) part = raw;\n else part = encoder.encode(String(raw));\n __privateSet(this, _size, __privateGet(this, _size) + (ArrayBuffer.isView(part) ? part.byteLength : part.size));\n __privateGet(this, _parts).push(part);\n }\n const type = options.type === void 0 ? \"\" : String(options.type);\n __privateSet(this, _type, /^[\\x20-\\x7E]*$/.test(type) ? type : \"\");\n }\n static [Symbol.hasInstance](value) {\n return Boolean(value && typeof value === \"object\" && isFunction(value.constructor) && (isFunction(value.stream) || isFunction(value.arrayBuffer)) && /^(Blob|File)$/.test(value[Symbol.toStringTag]));\n }\n /**\n * Returns the [`MIME type`](https://developer.mozilla.org/en-US/docs/Glossary/MIME_type) of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).\n */\n get type() {\n return __privateGet(this, _type);\n }\n /**\n * Returns the size of the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) in bytes.\n */\n get size() {\n return __privateGet(this, _size);\n }\n /**\n * Creates and returns a new [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) object which contains data from a subset of the blob on which it's called.\n *\n * @param start An index into the Blob indicating the first byte to include in the new Blob. If you specify a negative value, it's treated as an offset from the end of the Blob toward the beginning. For example, -10 would be the 10th from last byte in the Blob. The default value is 0. If you specify a value for start that is larger than the size of the source Blob, the returned Blob has size 0 and contains no data.\n * @param end An index into the Blob indicating the first byte that will *not* be included in the new Blob (i.e. the byte exactly at this index is not included). If you specify a negative value, it's treated as an offset from the end of the Blob toward the beginning. For example, -10 would be the 10th from last byte in the Blob. The default value is size.\n * @param contentType The content type to assign to the new Blob; this will be the value of its type property. The default value is an empty string.\n */\n slice(start, end, contentType) {\n return new _Blob(sliceBlob(__privateGet(this, _parts), this.size, start, end), { type: contentType });\n }\n /**\n * Returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that resolves with a string containing the contents of the blob, interpreted as UTF-8.\n */\n async text() {\n const decoder = new TextDecoder();\n let result = \"\";\n for await (const chunk of consumeBlobParts(__privateGet(this, _parts))) result += decoder.decode(chunk, { stream: true });\n result += decoder.decode();\n return result;\n }\n /**\n * Returns a [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that resolves with the contents of the blob as binary data contained in an [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer).\n */\n async arrayBuffer() {\n const view = new Uint8Array(this.size);\n let offset = 0;\n for await (const chunk of consumeBlobParts(__privateGet(this, _parts))) {\n view.set(chunk, offset);\n offset += chunk.length;\n }\n return view.buffer;\n }\n /**\n * Returns a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) which upon reading returns the data contained within the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).\n */\n stream() {\n const iterator = consumeBlobParts(__privateGet(this, _parts), true);\n return new ReadableStream({\n async pull(controller) {\n const { value, done } = await iterator.next();\n if (done) return queueMicrotask(() => controller.close());\n controller.enqueue(value);\n },\n async cancel() {\n await iterator.return();\n }\n });\n }\n get [Symbol.toStringTag]() {\n return \"Blob\";\n }\n };\n _parts = /* @__PURE__ */ new WeakMap();\n _type = /* @__PURE__ */ new WeakMap();\n _size = /* @__PURE__ */ new WeakMap();\n var Blob = _Blob;\n Object.defineProperties(Blob.prototype, {\n type: { enumerable: true },\n size: { enumerable: true },\n slice: { enumerable: true },\n stream: { enumerable: true },\n text: { enumerable: true },\n arrayBuffer: { enumerable: true }\n });\n var isBlob = (value) => value instanceof Blob;\n var _name, _lastModified;\n var File = class extends Blob {\n /**\n * Creates a new File instance.\n *\n * @param fileBits An `Array` strings, or [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), [`ArrayBufferView`](https://developer.mozilla.org/en-US/docs/Web/API/ArrayBufferView), [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) objects, or a mix of any of such objects, that will be put inside the [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File).\n * @param name The name of the file.\n * @param options An options object containing optional attributes for the file.\n */\n constructor(fileBits, name, options = {}) {\n super(fileBits, options);\n /**\n * Returns the name of the file referenced by the File object.\n */\n __privateAdd(this, _name, void 0);\n /**\n * The last modified date of the file as the number of milliseconds since the Unix epoch (January 1, 1970 at midnight). Files without a known last modified date return the current date.\n */\n __privateAdd(this, _lastModified, 0);\n if (arguments.length < 2) throw new TypeError(`Failed to construct 'File': 2 arguments required, but only ${arguments.length} present.`);\n __privateSet(this, _name, String(name));\n const lastModified = options.lastModified === void 0 ? Date.now() : Number(options.lastModified);\n if (!Number.isNaN(lastModified)) __privateSet(this, _lastModified, lastModified);\n }\n static [Symbol.hasInstance](value) {\n return value instanceof Blob && value[Symbol.toStringTag] === \"File\" && typeof value.name === \"string\";\n }\n /**\n * Name of the file referenced by the File object.\n */\n get name() {\n return __privateGet(this, _name);\n }\n /* c8 ignore next 3 */\n get webkitRelativePath() {\n return \"\";\n }\n /**\n * The last modified date of the file as the number of milliseconds since the Unix epoch (January 1, 1970 at midnight). Files without a known last modified date return the current date.\n */\n get lastModified() {\n return __privateGet(this, _lastModified);\n }\n get [Symbol.toStringTag]() {\n return \"File\";\n }\n };\n _name = /* @__PURE__ */ new WeakMap();\n _lastModified = /* @__PURE__ */ new WeakMap();\n var isFile = (value) => value instanceof File;\n var _entries, _setEntry, setEntry_fn;\n var FormData = class {\n constructor() {\n __privateAdd(this, _setEntry);\n /**\n * Stores internal data for every entry\n */\n __privateAdd(this, _entries, /* @__PURE__ */ new Map());\n }\n static [Symbol.hasInstance](value) {\n if (!value) return false;\n const val = value;\n return Boolean(isFunction(val.constructor) && val[Symbol.toStringTag] === \"FormData\" && isFunction(val.append) && isFunction(val.set) && isFunction(val.get) && isFunction(val.getAll) && isFunction(val.has) && isFunction(val.delete) && isFunction(val.entries) && isFunction(val.values) && isFunction(val.keys) && isFunction(val[Symbol.iterator]) && isFunction(val.forEach));\n }\n /**\n * Appends a new value onto an existing key inside a FormData object,\n * or adds the key if it does not already exist.\n *\n * The difference between `set()` and `append()` is that if the specified key already exists, `set()` will overwrite all existing values with the new one, whereas `append()` will append the new value onto the end of the existing set of values.\n *\n * @param name The name of the field whose data is contained in `value`.\n * @param value The field's value. This can be [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)\n or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File). If none of these are specified the value is converted to a string.\n * @param fileName The filename reported to the server, when a Blob or File is passed as the second parameter. The default filename for Blob objects is \"blob\". The default filename for File objects is the file's filename.\n */\n append(name, value, fileName) {\n __privateMethod(this, _setEntry, setEntry_fn).call(this, {\n name,\n fileName,\n append: true,\n rawValue: value,\n argsLength: arguments.length\n });\n }\n /**\n * Set a new value for an existing key inside FormData,\n * or add the new field if it does not already exist.\n *\n * @param name The name of the field whose data is contained in `value`.\n * @param value The field's value. This can be [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob)\n or [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File). If none of these are specified the value is converted to a string.\n * @param fileName The filename reported to the server, when a Blob or File is passed as the second parameter. The default filename for Blob objects is \"blob\". The default filename for File objects is the file's filename.\n *\n */\n set(name, value, fileName) {\n __privateMethod(this, _setEntry, setEntry_fn).call(this, {\n name,\n fileName,\n append: false,\n rawValue: value,\n argsLength: arguments.length\n });\n }\n /**\n * Returns the first value associated with a given key from within a `FormData` object.\n * If you expect multiple values and want all of them, use the `getAll()` method instead.\n *\n * @param {string} name A name of the value you want to retrieve.\n *\n * @returns A `FormDataEntryValue` containing the value. If the key doesn't exist, the method returns null.\n */\n get(name) {\n const field = __privateGet(this, _entries).get(String(name));\n if (!field) return null;\n return field[0];\n }\n /**\n * Returns all the values associated with a given key from within a `FormData` object.\n *\n * @param {string} name A name of the value you want to retrieve.\n *\n * @returns An array of `FormDataEntryValue` whose key matches the value passed in the `name` parameter. If the key doesn't exist, the method returns an empty list.\n */\n getAll(name) {\n const field = __privateGet(this, _entries).get(String(name));\n if (!field) return [];\n return field.slice();\n }\n /**\n * Returns a boolean stating whether a `FormData` object contains a certain key.\n *\n * @param name A string representing the name of the key you want to test for.\n *\n * @return A boolean value.\n */\n has(name) {\n return __privateGet(this, _entries).has(String(name));\n }\n /**\n * Deletes a key and its value(s) from a `FormData` object.\n *\n * @param name The name of the key you want to delete.\n */\n delete(name) {\n __privateGet(this, _entries).delete(String(name));\n }\n /**\n * Returns an [`iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) allowing to go through all keys contained in this `FormData` object.\n * Each key is a `string`.\n */\n *keys() {\n for (const key of __privateGet(this, _entries).keys()) yield key;\n }\n /**\n * Returns an [`iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) allowing to go through the `FormData` key/value pairs.\n * The key of each pair is a string; the value is a [`FormDataValue`](https://developer.mozilla.org/en-US/docs/Web/API/FormDataEntryValue).\n */\n *entries() {\n for (const name of this.keys()) {\n const values = this.getAll(name);\n for (const value of values) yield [name, value];\n }\n }\n /**\n * Returns an [`iterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) allowing to go through all values contained in this object `FormData` object.\n * Each value is a [`FormDataValue`](https://developer.mozilla.org/en-US/docs/Web/API/FormDataEntryValue).\n */\n *values() {\n for (const [, value] of this) yield value;\n }\n /**\n * An alias for FormData#entries()\n */\n [Symbol.iterator]() {\n return this.entries();\n }\n /**\n * Executes given callback function for each field of the FormData instance\n */\n forEach(callback, thisArg) {\n for (const [name, value] of this) callback.call(thisArg, value, name, this);\n }\n get [Symbol.toStringTag]() {\n return \"FormData\";\n }\n };\n _entries = /* @__PURE__ */ new WeakMap();\n _setEntry = /* @__PURE__ */ new WeakSet();\n setEntry_fn = function({ name, rawValue, append, fileName, argsLength }) {\n const methodName = append ? \"append\" : \"set\";\n if (argsLength < 2) throw new TypeError(`Failed to execute '${methodName}' on 'FormData': 2 arguments required, but only ${argsLength} present.`);\n name = String(name);\n let value;\n if (isFile(rawValue)) value = fileName === void 0 ? rawValue : new File([rawValue], fileName, {\n type: rawValue.type,\n lastModified: rawValue.lastModified\n });\n else if (isBlob(rawValue)) value = new File([rawValue], fileName === void 0 ? \"blob\" : fileName, { type: rawValue.type });\n else if (fileName) throw new TypeError(`Failed to execute '${methodName}' on 'FormData': parameter 2 is not of type 'Blob'.`);\n else value = String(rawValue);\n const values = __privateGet(this, _entries).get(name);\n if (!values) {\n __privateGet(this, _entries).set(name, [value]);\n return;\n }\n if (!append) {\n __privateGet(this, _entries).set(name, [value]);\n return;\n }\n values.push(value);\n };\n /*! Based on fetch-blob. MIT License. Jimmy Wärting <https://jimmy.warting.se/opensource> & David Frank */\n //#endregion\n //#region node_modules/.pnpm/set-cookie-parser@3.1.0/node_modules/set-cookie-parser/lib/set-cookie.js\n var defaultParseOptions = {\n decodeValues: true,\n map: false,\n silent: false,\n split: \"auto\"\n };\n function isForbiddenKey(key) {\n return typeof key !== \"string\" || key in {};\n }\n function createNullObj() {\n return Object.create(null);\n }\n function isNonEmptyString(str) {\n return typeof str === \"string\" && !!str.trim();\n }\n function parseString(setCookieValue, options) {\n var parts = setCookieValue.split(\";\").filter(isNonEmptyString);\n var parsed = parseNameValuePair(parts.shift());\n var name = parsed.name;\n var value = parsed.value;\n options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;\n if (isForbiddenKey(name)) return null;\n try {\n value = options.decodeValues ? decodeURIComponent(value) : value;\n } catch (e) {\n console.error(\"set-cookie-parser: failed to decode cookie value. Set options.decodeValues=false to disable decoding.\", e);\n }\n var cookie = createNullObj();\n cookie.name = name;\n cookie.value = value;\n parts.forEach(function(part) {\n var sides = part.split(\"=\");\n var key = sides.shift().trimLeft().toLowerCase();\n if (isForbiddenKey(key)) return;\n var value = sides.join(\"=\");\n if (key === \"expires\") cookie.expires = new Date(value);\n else if (key === \"max-age\") {\n var n = parseInt(value, 10);\n if (!Number.isNaN(n)) cookie.maxAge = n;\n } else if (key === \"secure\") cookie.secure = true;\n else if (key === \"httponly\") cookie.httpOnly = true;\n else if (key === \"samesite\") cookie.sameSite = value;\n else if (key === \"partitioned\") cookie.partitioned = true;\n else if (key) cookie[key] = value;\n });\n return cookie;\n }\n function parseNameValuePair(nameValuePairStr) {\n var name = \"\";\n var value = \"\";\n var nameValueArr = nameValuePairStr.split(\"=\");\n if (nameValueArr.length > 1) {\n name = nameValueArr.shift();\n value = nameValueArr.join(\"=\");\n } else value = nameValuePairStr;\n return {\n name,\n value\n };\n }\n function parseSetCookie(input, options) {\n options = options ? Object.assign({}, defaultParseOptions, options) : defaultParseOptions;\n if (!input) if (!options.map) return [];\n else return createNullObj();\n if (input.headers) if (typeof input.headers.getSetCookie === \"function\") input = input.headers.getSetCookie();\n else if (input.headers[\"set-cookie\"]) input = input.headers[\"set-cookie\"];\n else {\n var sch = input.headers[Object.keys(input.headers).find(function(key) {\n return key.toLowerCase() === \"set-cookie\";\n })];\n if (!sch && input.headers.cookie && !options.silent) console.warn(\"Warning: set-cookie-parser appears to have been called on a request object. It is designed to parse Set-Cookie headers from responses, not Cookie headers from requests. Set the option {silent: true} to suppress this warning.\");\n input = sch;\n }\n var split = options.split;\n var isArray = Array.isArray(input);\n if (split === \"auto\") split = !isArray;\n if (!isArray) input = [input];\n input = input.filter(isNonEmptyString);\n if (split) input = input.map(splitCookiesString).flat();\n if (!options.map) return input.map(function(str) {\n return parseString(str, options);\n }).filter(Boolean);\n else {\n var cookies = createNullObj();\n return input.reduce(function(cookies, str) {\n var cookie = parseString(str, options);\n if (cookie && !isForbiddenKey(cookie.name)) cookies[cookie.name] = cookie;\n return cookies;\n }, cookies);\n }\n }\n function splitCookiesString(cookiesString) {\n if (Array.isArray(cookiesString)) return cookiesString;\n if (typeof cookiesString !== \"string\") return [];\n var cookiesStrings = [];\n var pos = 0;\n var start;\n var ch;\n var lastComma;\n var nextStart;\n var cookiesSeparatorFound;\n function skipWhitespace() {\n while (pos < cookiesString.length && /\\s/.test(cookiesString.charAt(pos))) pos += 1;\n return pos < cookiesString.length;\n }\n function notSpecialChar() {\n ch = cookiesString.charAt(pos);\n return ch !== \"=\" && ch !== \";\" && ch !== \",\";\n }\n while (pos < cookiesString.length) {\n start = pos;\n cookiesSeparatorFound = false;\n while (skipWhitespace()) {\n ch = cookiesString.charAt(pos);\n if (ch === \",\") {\n lastComma = pos;\n pos += 1;\n skipWhitespace();\n nextStart = pos;\n while (pos < cookiesString.length && notSpecialChar()) pos += 1;\n if (pos < cookiesString.length && cookiesString.charAt(pos) === \"=\") {\n cookiesSeparatorFound = true;\n pos = nextStart;\n cookiesStrings.push(cookiesString.substring(start, lastComma));\n start = pos;\n } else pos = lastComma + 1;\n } else pos += 1;\n }\n if (!cookiesSeparatorFound || pos >= cookiesString.length) cookiesStrings.push(cookiesString.substring(start, cookiesString.length));\n }\n return cookiesStrings;\n }\n parseSetCookie.parseSetCookie = parseSetCookie;\n parseSetCookie.parse = parseSetCookie;\n parseSetCookie.parseString = parseString;\n parseSetCookie.splitCookiesString = splitCookiesString;\n //#endregion\n //#region node_modules/.pnpm/headers-polyfill@5.0.1/node_modules/headers-polyfill/lib/index.mjs\n const HEADERS_INVALID_CHARACTERS = /[^a-z0-9\\-#$%&'*+.^_`|~]/i;\n function normalizeHeaderName(name) {\n if (HEADERS_INVALID_CHARACTERS.test(name) || name.trim() === \"\") throw new TypeError(\"Invalid character in header field name\");\n return name.trim().toLowerCase();\n }\n const charCodesToRemove = [\n String.fromCharCode(10),\n String.fromCharCode(13),\n String.fromCharCode(9),\n String.fromCharCode(32)\n ];\n const HEADER_VALUE_REMOVE_REGEXP = new RegExp(`(^[${charCodesToRemove.join(\"\")}]|$[${charCodesToRemove.join(\"\")}])`, \"g\");\n /**\n * Normalize the given header value.\n * @see https://fetch.spec.whatwg.org/#concept-header-value-normalize\n */\n function normalizeHeaderValue(value) {\n return value.replace(HEADER_VALUE_REMOVE_REGEXP, \"\");\n }\n /**\n * Validate the given header name.\n * @see https://fetch.spec.whatwg.org/#header-name\n */\n function isValidHeaderName(value) {\n if (typeof value !== \"string\") return false;\n if (value.length === 0) return false;\n for (let i = 0; i < value.length; i++) {\n const character = value.charCodeAt(i);\n if (character > 127 || !isToken(character)) return false;\n }\n return true;\n }\n function isToken(value) {\n return ![\n 127,\n 32,\n \"(\",\n \")\",\n \"<\",\n \">\",\n \"@\",\n \",\",\n \";\",\n \":\",\n \"\\\\\",\n \"\\\"\",\n \"/\",\n \"[\",\n \"]\",\n \"?\",\n \"=\",\n \"{\",\n \"}\"\n ].includes(value);\n }\n /**\n * Validate the given header value.\n * @see https://fetch.spec.whatwg.org/#header-value\n */\n function isValidHeaderValue(value) {\n if (typeof value !== \"string\") return false;\n if (value.trim() !== value) return false;\n for (let i = 0; i < value.length; i++) {\n const character = value.charCodeAt(i);\n if (character === 0 || character === 10 || character === 13) return false;\n }\n return true;\n }\n let _Symbol$toStringTag;\n const NORMALIZED_HEADERS = Symbol(\"normalizedHeaders\");\n const RAW_HEADER_NAMES = Symbol(\"rawHeaderNames\");\n const HEADER_VALUE_DELIMITER = \", \";\n var Headers = class Headers {\n constructor(init) {\n this[NORMALIZED_HEADERS] = {};\n this[RAW_HEADER_NAMES] = /* @__PURE__ */ new Map();\n this[_Symbol$toStringTag] = \"Headers\";\n /**\n * @note Cannot necessarily check if the `init` is an instance of the\n * `Headers` because that class may not be defined in Node or jsdom.\n */\n if ([\"Headers\", \"HeadersPolyfill\"].includes(init?.constructor?.name) || init instanceof Headers || typeof globalThis.Headers !== \"undefined\" && init instanceof globalThis.Headers) init.forEach((value, name) => {\n this.append(name, value);\n }, this);\n else if (Array.isArray(init)) init.forEach(([name, value]) => {\n this.append(name, Array.isArray(value) ? value.join(HEADER_VALUE_DELIMITER) : value);\n });\n else if (init) Object.getOwnPropertyNames(init).forEach((name) => {\n const value = init[name];\n this.append(name, Array.isArray(value) ? value.join(HEADER_VALUE_DELIMITER) : value);\n });\n }\n [(_Symbol$toStringTag = Symbol.toStringTag, Symbol.iterator)]() {\n return this.entries();\n }\n *keys() {\n for (const [name] of this.entries()) yield name;\n }\n *values() {\n for (const [, value] of this.entries()) yield value;\n }\n *entries() {\n let sortedKeys = Object.keys(this[NORMALIZED_HEADERS]).sort((a, b) => a.localeCompare(b));\n for (const name of sortedKeys) if (name === \"set-cookie\") for (const value of this.getSetCookie()) yield [name, value];\n else yield [name, this.get(name)];\n }\n /**\n * Returns a boolean stating whether a `Headers` object contains a certain header.\n */\n has(name) {\n if (!isValidHeaderName(name)) throw new TypeError(`Invalid header name \"${name}\"`);\n return this[NORMALIZED_HEADERS].hasOwnProperty(normalizeHeaderName(name));\n }\n /**\n * Returns a `ByteString` sequence of all the values of a header with a given name.\n */\n get(name) {\n if (!isValidHeaderName(name)) throw TypeError(`Invalid header name \"${name}\"`);\n return this[NORMALIZED_HEADERS][normalizeHeaderName(name)] ?? null;\n }\n /**\n * Sets a new value for an existing header inside a `Headers` object, or adds the header if it does not already exist.\n */\n set(name, value) {\n if (!isValidHeaderName(name) || !isValidHeaderValue(value)) return;\n const normalizedName = normalizeHeaderName(name);\n const normalizedValue = normalizeHeaderValue(value);\n this[NORMALIZED_HEADERS][normalizedName] = normalizeHeaderValue(normalizedValue);\n this[RAW_HEADER_NAMES].set(normalizedName, name);\n }\n /**\n * Appends a new value onto an existing header inside a `Headers` object, or adds the header if it does not already exist.\n */\n append(name, value) {\n if (!isValidHeaderName(name) || !isValidHeaderValue(value)) return;\n const normalizedName = normalizeHeaderName(name);\n const normalizedValue = normalizeHeaderValue(value);\n let resolvedValue = this.has(normalizedName) ? `${this.get(normalizedName)}, ${normalizedValue}` : normalizedValue;\n this.set(name, resolvedValue);\n }\n /**\n * Deletes a header from the `Headers` object.\n */\n delete(name) {\n if (!isValidHeaderName(name)) return;\n if (!this.has(name)) return;\n const normalizedName = normalizeHeaderName(name);\n delete this[NORMALIZED_HEADERS][normalizedName];\n this[RAW_HEADER_NAMES].delete(normalizedName);\n }\n /**\n * Traverses the `Headers` object,\n * calling the given callback for each header.\n */\n forEach(callback, thisArg) {\n for (const [name, value] of this.entries()) callback.call(thisArg, value, name, this);\n }\n /**\n * Returns an array containing the values\n * of all Set-Cookie headers associated\n * with a response\n */\n getSetCookie() {\n const setCookieHeader = this.get(\"set-cookie\");\n if (setCookieHeader === null) return [];\n if (setCookieHeader === \"\") return [\"\"];\n return splitCookiesString(setCookieHeader);\n }\n };\n //#endregion\n //#region packages/core/src/code-mode/platform-entry.ts\n const platformBridgeGlobalThis = globalThis;\n const capletsPlatformHost = {\n randomUUID: platformBridgeGlobalThis.__caplets_platform_random_uuid,\n randomValues: platformBridgeGlobalThis.__caplets_platform_random_values,\n sleep: platformBridgeGlobalThis.__caplets_platform_sleep,\n clearTimer: platformBridgeGlobalThis.__caplets_platform_clear_timer\n };\n delete platformBridgeGlobalThis.__caplets_platform_random_uuid;\n delete platformBridgeGlobalThis.__caplets_platform_random_values;\n delete platformBridgeGlobalThis.__caplets_platform_sleep;\n delete platformBridgeGlobalThis.__caplets_platform_clear_timer;\n const DISABLED_FETCH_MESSAGE = \"Direct fetch is not available in Code Mode; use a Caplet instead.\";\n const BASE64_ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n const base64Lookup = new Map(BASE64_ALPHABET.split(\"\").map((char, index) => [char, index]));\n function utf8Encode(input) {\n const encoded = encodeURIComponent(input);\n const bytes = [];\n for (let index = 0; index < encoded.length; index += 1) {\n if (encoded[index] === \"%\") {\n bytes.push(Number.parseInt(encoded.slice(index + 1, index + 3), 16));\n index += 2;\n continue;\n }\n bytes.push(encoded.charCodeAt(index));\n }\n return Uint8Array.from(bytes);\n }\n function utf8Decode(input) {\n let output = \"\";\n for (let index = 0; index < input.length; index += 1) {\n const first = input[index] ?? 0;\n if (first < 128) {\n output += String.fromCharCode(first);\n continue;\n }\n if (first >= 194 && first <= 223) {\n const second = input[index + 1];\n if (isUtf8Continuation(second)) {\n output += String.fromCodePoint((first & 31) << 6 | second & 63);\n index += 1;\n continue;\n }\n output += \"�\";\n continue;\n }\n if (first >= 224 && first <= 239) {\n const second = input[index + 1];\n const third = input[index + 2];\n if (isValidUtf8SecondForThreeByte(first, second) && isUtf8Continuation(third)) {\n output += String.fromCodePoint((first & 15) << 12 | (second & 63) << 6 | third & 63);\n index += 2;\n continue;\n }\n output += \"�\";\n if (isValidUtf8SecondForThreeByte(first, second)) index += 1;\n continue;\n }\n if (first >= 240 && first <= 244) {\n const second = input[index + 1];\n const third = input[index + 2];\n const fourth = input[index + 3];\n if (isValidUtf8SecondForFourByte(first, second) && isUtf8Continuation(third) && isUtf8Continuation(fourth)) {\n output += String.fromCodePoint((first & 7) << 18 | (second & 63) << 12 | (third & 63) << 6 | fourth & 63);\n index += 3;\n continue;\n }\n output += \"�\";\n if (isValidUtf8SecondForFourByte(first, second)) index += isUtf8Continuation(third) ? 2 : 1;\n continue;\n }\n output += \"�\";\n }\n return output;\n }\n function isUtf8Continuation(value) {\n return value !== void 0 && value >= 128 && value <= 191;\n }\n function isValidUtf8SecondForThreeByte(first, second) {\n if (second === void 0) return false;\n if (first === 224) return second >= 160 && second <= 191;\n if (first === 237) return second >= 128 && second <= 159;\n return second >= 128 && second <= 191;\n }\n function isValidUtf8SecondForFourByte(first, second) {\n if (second === void 0) return false;\n if (first === 240) return second >= 144 && second <= 191;\n if (first === 244) return second >= 128 && second <= 143;\n return second >= 128 && second <= 191;\n }\n var TextEncoderShim = class {\n encoding = \"utf-8\";\n encode(input = \"\") {\n return utf8Encode(String(input));\n }\n };\n var TextDecoderShim = class {\n encoding;\n constructor(label = \"utf-8\") {\n const normalized = label.toLowerCase();\n if (![\n \"utf-8\",\n \"utf8\",\n \"unicode-1-1-utf-8\"\n ].includes(normalized)) throw new TypeError(`Unsupported encoding: ${label}`);\n this.encoding = \"utf-8\";\n }\n decode(input) {\n if (input === void 0) return \"\";\n return utf8Decode(copyBytes(input));\n }\n };\n const textEncoder = new TextEncoderShim();\n const textDecoder = new TextDecoderShim();\n var URLSearchParamsShim = class URLSearchParamsShim {\n #entries = [];\n #onChange;\n constructor(init = \"\", onChange) {\n this.#onChange = onChange;\n if (typeof init === \"string\") {\n const source = init.startsWith(\"?\") ? init.slice(1) : init;\n if (!source) return;\n for (const pair of source.split(\"&\")) {\n if (!pair) continue;\n const separatorIndex = pair.indexOf(\"=\");\n const key = separatorIndex >= 0 ? pair.slice(0, separatorIndex) : pair;\n const value = separatorIndex >= 0 ? pair.slice(separatorIndex + 1) : \"\";\n this.#entries.push([decodeUrlParam(key), decodeUrlParam(value)]);\n }\n return;\n }\n if (init instanceof URLSearchParamsShim) {\n this.#entries = [...init.#entries];\n return;\n }\n if (Array.isArray(init)) {\n this.#entries = init.map(([key, value]) => [String(key), String(value)]);\n return;\n }\n this.#entries = Object.entries(init).map(([key, value]) => [key, String(value)]);\n }\n append(name, value) {\n this.#entries.push([String(name), String(value)]);\n this.#onChange?.();\n }\n delete(name) {\n const normalized = String(name);\n this.#entries = this.#entries.filter(([key]) => key !== normalized);\n this.#onChange?.();\n }\n entries() {\n return this.#entries[Symbol.iterator]();\n }\n forEach(callback) {\n for (const [key, value] of this.#entries) callback(value, key, this);\n }\n get(name) {\n return this.#entries.find(([key]) => key === String(name))?.[1] ?? null;\n }\n getAll(name) {\n return this.#entries.filter(([key]) => key === String(name)).map(([, value]) => value);\n }\n has(name) {\n return this.#entries.some(([key]) => key === String(name));\n }\n keys() {\n return this.#entries.map(([key]) => key)[Symbol.iterator]();\n }\n set(name, value) {\n const normalizedName = String(name);\n const normalizedValue = String(value);\n const next = [];\n let replaced = false;\n for (const entry of this.#entries) {\n if (entry[0] !== normalizedName) {\n next.push(entry);\n continue;\n }\n if (!replaced) {\n next.push([normalizedName, normalizedValue]);\n replaced = true;\n }\n }\n if (!replaced) next.push([normalizedName, normalizedValue]);\n this.#entries = next;\n this.#onChange?.();\n }\n toString() {\n return this.#entries.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join(\"&\");\n }\n values() {\n return this.#entries.map(([, value]) => value)[Symbol.iterator]();\n }\n [Symbol.iterator]() {\n return this.entries();\n }\n };\n function decodeUrlParam(value) {\n return decodeURIComponent(value.replace(/\\+/gu, \" \"));\n }\n function parseAbsoluteUrl(input) {\n const match = /^(?<protocol>[a-zA-Z][a-zA-Z\\d+.-]*:)\\/\\/(?<host>[^/?#]*)(?<pathname>[^?#]*)?(?<search>\\?[^#]*)?(?<hash>#.*)?$/u.exec(input);\n if (!match?.groups?.protocol || !match.groups.host) return;\n return {\n protocol: match.groups.protocol,\n host: match.groups.host,\n pathname: match.groups.pathname || \"/\",\n search: match.groups.search || \"\",\n hash: match.groups.hash || \"\"\n };\n }\n function normalizePathname(pathname) {\n const segments = [];\n for (const part of pathname.split(\"/\")) {\n if (!part || part === \".\") continue;\n if (part === \"..\") {\n segments.pop();\n continue;\n }\n segments.push(part);\n }\n return `/${segments.join(\"/\")}`;\n }\n function resolveUrl(input, base) {\n const absolute = parseAbsoluteUrl(input);\n if (absolute) return absolute;\n if (base === void 0) throw new TypeError(`Invalid URL: ${input}`);\n const baseUrl = base instanceof URLShim ? base : new URLShim(String(base));\n const basePath = baseUrl.pathname.endsWith(\"/\") ? baseUrl.pathname : baseUrl.pathname.slice(0, baseUrl.pathname.lastIndexOf(\"/\") + 1);\n const [beforeHash, rawHash = \"\"] = input.split(\"#\");\n const hasExplicitSearch = beforeHash?.includes(\"?\") ?? false;\n const [rawPath, rawSearch = \"\"] = (beforeHash ?? \"\").split(\"?\");\n const pathname = rawPath === \"\" && (input === \"\" || input.startsWith(\"?\") || input.startsWith(\"#\")) ? baseUrl.pathname : rawPath?.startsWith(\"/\") ? rawPath : `${basePath}${rawPath || \"\"}`;\n return {\n protocol: baseUrl.protocol,\n host: baseUrl.host,\n pathname: normalizePathname(pathname),\n search: hasExplicitSearch ? `?${rawSearch}` : rawPath === \"\" && (input === \"\" || input.startsWith(\"#\")) ? baseUrl.search : \"\",\n hash: rawHash ? `#${rawHash}` : \"\"\n };\n }\n var URLShim = class {\n host;\n hostname;\n origin;\n password = \"\";\n port;\n protocol;\n searchParams;\n username = \"\";\n hash;\n pathname;\n #search;\n constructor(input, base) {\n const parsed = resolveUrl(String(input), base);\n this.protocol = parsed.protocol;\n this.host = parsed.host;\n const portIndex = this.host.lastIndexOf(\":\");\n this.hostname = portIndex >= 0 ? this.host.slice(0, portIndex) : this.host;\n this.port = portIndex >= 0 ? this.host.slice(portIndex + 1) : \"\";\n this.pathname = parsed.pathname;\n this.#search = parsed.search;\n this.hash = parsed.hash;\n this.origin = `${this.protocol}//${this.host}`;\n this.searchParams = new URLSearchParamsShim(this.#search, () => {\n const next = this.searchParams.toString();\n this.#search = next ? `?${next}` : \"\";\n });\n }\n get href() {\n return `${this.origin}${this.pathname}${this.#search}${this.hash}`;\n }\n get search() {\n return this.#search;\n }\n toString() {\n return this.href;\n }\n toJSON() {\n return this.href;\n }\n };\n var ReadableStreamShim = class {\n #queue = [];\n #closed = false;\n #pulling = false;\n #source;\n #controller;\n #pending;\n constructor(source = {}) {\n this.#source = source;\n this.#controller = {\n enqueue: (value) => {\n if (this.#pending) {\n this.#pending.resolve({\n done: false,\n value\n });\n this.#pending = void 0;\n return;\n }\n this.#queue.push(value);\n },\n close: () => {\n this.#closed = true;\n if (this.#pending) {\n this.#pending.resolve({ done: true });\n this.#pending = void 0;\n }\n }\n };\n source.start?.(this.#controller);\n }\n async #pull() {\n if (this.#pulling || this.#closed || !this.#source.pull) return;\n this.#pulling = true;\n try {\n await this.#source.pull(this.#controller);\n } finally {\n this.#pulling = false;\n }\n }\n getReader() {\n return { read: async () => {\n if (this.#queue.length > 0) return {\n done: false,\n value: this.#queue.shift()\n };\n await this.#pull();\n if (this.#queue.length > 0) return {\n done: false,\n value: this.#queue.shift()\n };\n if (this.#closed) return {\n done: true,\n value: void 0\n };\n return await new Promise((resolve) => {\n this.#pending = { resolve };\n this.#pull();\n });\n } };\n }\n };\n var WritableStreamShim = class {\n #sink;\n constructor(sink = {}) {\n this.#sink = sink;\n }\n getWriter() {\n return {\n write: async (chunk) => {\n await this.#sink.write?.(chunk);\n },\n close: async () => {\n await this.#sink.close?.();\n }\n };\n }\n };\n var TransformStreamShim = class {\n readable;\n writable;\n constructor(transformer = {}) {\n const queue = [];\n let closed = false;\n let pending;\n const controller = {\n enqueue: (value) => {\n if (pending) {\n pending.resolve({\n done: false,\n value\n });\n pending = void 0;\n return;\n }\n queue.push(value);\n },\n close: () => {\n closed = true;\n if (pending) {\n pending.resolve({ done: true });\n pending = void 0;\n }\n }\n };\n this.readable = { getReader() {\n return { read: async () => {\n if (queue.length > 0) return {\n done: false,\n value: queue.shift()\n };\n if (closed) return {\n done: true,\n value: void 0\n };\n return await new Promise((resolve) => {\n pending = { resolve };\n });\n } };\n } };\n this.writable = new WritableStreamShim({\n write: async (chunk) => {\n transformer.transform?.(chunk, controller);\n },\n close: async () => {\n transformer.flush?.(controller);\n controller.close();\n }\n });\n }\n };\n function definePlatformGlobal(name, value, options = {}) {\n if (!options.overwrite && name in globalThis) return;\n Object.defineProperty(globalThis, name, {\n value,\n writable: true,\n configurable: true\n });\n }\n function formatLogArg(value) {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n }\n function formatLogLine(args) {\n return args.map(formatLogArg).join(\" \");\n }\n const platformConsole = {\n log: (...args) => __caplets_log(\"log\", formatLogLine(args)),\n info: (...args) => __caplets_log(\"info\", formatLogLine(args)),\n warn: (...args) => __caplets_log(\"warn\", formatLogLine(args)),\n error: (...args) => __caplets_log(\"error\", formatLogLine(args)),\n debug: (...args) => __caplets_log(\"debug\", formatLogLine(args))\n };\n function normalizeEncoding(encoding) {\n const normalized = (encoding ?? \"utf8\").toLowerCase();\n switch (normalized) {\n case \"utf8\":\n case \"utf-8\":\n case \"base64\":\n case \"base64url\":\n case \"hex\": return normalized;\n default: throw new TypeError(`Unsupported Buffer encoding: ${encoding}`);\n }\n }\n function hexToBytes(value) {\n if (value.length % 2 !== 0) throw new TypeError(\"Invalid hex string length\");\n const bytes = new Uint8Array(value.length / 2);\n for (let index = 0; index < value.length; index += 2) {\n const parsed = Number.parseInt(value.slice(index, index + 2), 16);\n if (Number.isNaN(parsed)) throw new TypeError(\"Invalid hex string\");\n bytes[index / 2] = parsed;\n }\n return bytes;\n }\n function bytesToHex(bytes) {\n return Array.from(bytes, (value) => value.toString(16).padStart(2, \"0\")).join(\"\");\n }\n function base64ToBytes(value, encoding) {\n let normalized = value.replace(/\\s+/gu, \"\");\n if (encoding === \"base64url\") normalized = normalized.replace(/-/gu, \"+\").replace(/_/gu, \"/\");\n const padding = normalized.length % 4;\n if (padding === 1) throw new TypeError(\"Invalid base64 string\");\n if (padding > 0) normalized = normalized.padEnd(normalized.length + (4 - padding), \"=\");\n const output = [];\n for (let index = 0; index < normalized.length; index += 4) {\n const values = normalized.slice(index, index + 4).split(\"\").map((char) => char === \"=\" ? 64 : base64Lookup.get(char) ?? NaN);\n if (values.some((entry) => Number.isNaN(entry))) throw new TypeError(\"Invalid base64 string\");\n const [a = 0, b = 0, c = 64, d = 64] = values;\n const triple = a << 18 | b << 12 | (c & 63) << 6 | d & 63;\n output.push(triple >> 16 & 255);\n if (c !== 64) output.push(triple >> 8 & 255);\n if (d !== 64) output.push(triple & 255);\n }\n return Uint8Array.from(output);\n }\n function bytesToBase64(bytes, encoding) {\n let output = \"\";\n for (let index = 0; index < bytes.length; index += 3) {\n const a = bytes[index] ?? 0;\n const b = bytes[index + 1] ?? 0;\n const c = bytes[index + 2] ?? 0;\n const triple = a << 16 | b << 8 | c;\n output += BASE64_ALPHABET[triple >> 18 & 63];\n output += BASE64_ALPHABET[triple >> 12 & 63];\n output += index + 1 < bytes.length ? BASE64_ALPHABET[triple >> 6 & 63] : \"=\";\n output += index + 2 < bytes.length ? BASE64_ALPHABET[triple & 63] : \"=\";\n }\n if (encoding === \"base64url\") return output.replace(/\\+/gu, \"-\").replace(/\\//gu, \"_\").replace(/=+$/gu, \"\");\n return output;\n }\n function copyBytes(input) {\n if (input instanceof ArrayBuffer) return new Uint8Array(input.slice(0));\n return new Uint8Array(input.buffer.slice(input.byteOffset, input.byteOffset + input.byteLength));\n }\n function toBytes(input, encoding) {\n if (input instanceof BufferShim) return input.toUint8Array();\n if (typeof input === \"string\") switch (normalizeEncoding(encoding)) {\n case \"utf8\":\n case \"utf-8\": return textEncoder.encode(input);\n case \"base64\":\n case \"base64url\": return base64ToBytes(input, normalizeEncoding(encoding));\n case \"hex\": return hexToBytes(input);\n }\n if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) return copyBytes(input);\n if (Array.isArray(input)) return Uint8Array.from(input);\n throw new TypeError(\"Buffer.from only supports strings, arrays, ArrayBuffers, and typed arrays\");\n }\n var BufferShim = class BufferShim {\n #bytes;\n byteLength;\n length;\n constructor(bytes) {\n this.#bytes = bytes;\n this.byteLength = bytes.byteLength;\n this.length = bytes.length;\n }\n static from(input, encoding) {\n return new BufferShim(toBytes(input, encoding));\n }\n static isBuffer(value) {\n return value instanceof BufferShim;\n }\n static byteLength(input, encoding) {\n return toBytes(input, encoding).byteLength;\n }\n toUint8Array() {\n return new Uint8Array(this.#bytes);\n }\n toString(encoding) {\n switch (normalizeEncoding(encoding)) {\n case \"utf8\":\n case \"utf-8\": return textDecoder.decode(this.#bytes);\n case \"base64\":\n case \"base64url\": return bytesToBase64(this.#bytes, normalizeEncoding(encoding));\n case \"hex\": return bytesToHex(this.#bytes);\n }\n }\n };\n function atobShim(input) {\n return Array.from(base64ToBytes(String(input), \"base64\"), (value) => String.fromCharCode(value)).join(\"\");\n }\n function btoaShim(input) {\n const bytes = new Uint8Array(input.length);\n for (let index = 0; index < input.length; index += 1) {\n const codePoint = input.charCodeAt(index);\n if (codePoint > 255) throw new TypeError(\"The string to be encoded contains characters outside of Latin1\");\n bytes[index] = codePoint;\n }\n return bytesToBase64(bytes, \"base64\");\n }\n function queueMicrotaskShim(callback) {\n Promise.resolve().then(callback);\n }\n var AbortSignalShim = class AbortSignalShim {\n aborted = false;\n reason;\n onabort = null;\n #listeners = /* @__PURE__ */ new Set();\n addEventListener(type, listener) {\n if (type === \"abort\" && listener) this.#listeners.add(listener);\n }\n removeEventListener(type, listener) {\n if (type === \"abort\" && listener) this.#listeners.delete(listener);\n }\n dispatchEvent(event) {\n if (event.type !== \"abort\") return true;\n this.onabort?.(event);\n for (const listener of this.#listeners) listener(event);\n return true;\n }\n throwIfAborted() {\n if (this.aborted) throw this.reason ?? /* @__PURE__ */ new Error(\"Operation was aborted\");\n }\n static abort(reason) {\n const signal = new AbortSignalShim();\n signal.abort(reason);\n return signal;\n }\n abort(reason) {\n if (this.aborted) return;\n this.aborted = true;\n this.reason = reason;\n this.dispatchEvent({\n type: \"abort\",\n target: this\n });\n }\n };\n var AbortControllerShim = class {\n signal = new AbortSignalShim();\n abort(reason) {\n this.signal.abort(reason);\n }\n };\n function cloneFormData(input) {\n const clone = new FormData();\n for (const [name, value] of input.entries()) {\n if (value instanceof File) {\n clone.append(name, new File([value], value.name, { type: value.type }), value.name);\n continue;\n }\n clone.append(name, value);\n }\n return clone;\n }\n function cloneBodyValue(input) {\n if (input === null || input === void 0 || typeof input === \"string\") return input;\n if (input instanceof FormData) return cloneFormData(input);\n if (input instanceof Blob) return input.slice(0, input.size, input.type);\n if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) return copyBytes(input);\n return input;\n }\n function blobFromBody(input) {\n if (input instanceof Blob) return input;\n if (typeof input === \"string\") return new Blob([input], { type: \"text/plain;charset=utf-8\" });\n if (input instanceof FormData) throw new TypeError(\"FormData body reading is not supported in Code Mode\");\n if (input instanceof ArrayBuffer || ArrayBuffer.isView(input)) return new Blob([copyBytes(input)]);\n return new Blob([]);\n }\n var BodyMixin = class {\n _bodyInit;\n bodyUsed = false;\n body = null;\n constructor(body) {\n this._bodyInit = cloneBodyValue(body);\n }\n async arrayBuffer() {\n this.bodyUsed = true;\n return await blobFromBody(this._bodyInit).arrayBuffer();\n }\n async blob() {\n this.bodyUsed = true;\n return blobFromBody(this._bodyInit);\n }\n async formData() {\n this.bodyUsed = true;\n if (this._bodyInit instanceof FormData) return cloneFormData(this._bodyInit);\n throw new TypeError(\"Body does not contain FormData\");\n }\n async json() {\n return JSON.parse(await this.text());\n }\n async text() {\n this.bodyUsed = true;\n return await blobFromBody(this._bodyInit).text();\n }\n };\n function toHeaders(init) {\n return init instanceof Headers ? new Headers(init) : new Headers(init ?? {});\n }\n function normalizeMethod(method) {\n return String(method ?? \"GET\").toUpperCase();\n }\n var RequestShim = class RequestShim extends BodyMixin {\n headers;\n method;\n signal;\n url;\n constructor(input, init = {}) {\n const sourceBody = input instanceof RequestShim ? input._bodyInit : void 0;\n super(init.body ?? sourceBody);\n if (input instanceof RequestShim) this.url = input.url;\n else this.url = input instanceof URLShim ? input.href : new URLShim(String(input)).href;\n this.method = normalizeMethod(init.method ?? (input instanceof RequestShim ? input.method : \"GET\"));\n this.headers = toHeaders(init.headers ?? (input instanceof RequestShim ? input.headers : void 0));\n this.signal = init.signal ?? (input instanceof RequestShim ? input.signal : new AbortControllerShim().signal);\n }\n clone() {\n return new RequestShim(this, {\n method: this.method,\n headers: this.headers,\n body: this._bodyInit,\n signal: this.signal\n });\n }\n };\n var ResponseShim = class ResponseShim extends BodyMixin {\n headers;\n ok;\n redirected = false;\n status;\n statusText;\n type = \"default\";\n url = \"\";\n constructor(body, init = {}) {\n super(body);\n this.status = init.status ?? 200;\n this.statusText = init.statusText ?? \"\";\n this.headers = toHeaders(init.headers);\n this.ok = this.status >= 200 && this.status <= 299;\n }\n clone() {\n return new ResponseShim(this._bodyInit, {\n headers: this.headers,\n status: this.status,\n statusText: this.statusText\n });\n }\n static json(data, init) {\n const headers = toHeaders(init?.headers);\n if (!headers.has(\"content-type\")) headers.set(\"content-type\", \"application/json\");\n const responseInit = { headers };\n if (init?.status !== void 0) responseInit.status = init.status;\n if (init?.statusText !== void 0) responseInit.statusText = init.statusText;\n return new ResponseShim(JSON.stringify(data), responseInit);\n }\n };\n function disabledFetch() {\n throw new Error(DISABLED_FETCH_MESSAGE);\n }\n const integerTypedArrayConstructors = new Set([\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n typeof BigInt64Array === \"undefined\" ? void 0 : BigInt64Array,\n typeof BigUint64Array === \"undefined\" ? void 0 : BigUint64Array\n ]);\n var QuotaExceededErrorShim = class extends Error {\n constructor(message) {\n super(message);\n this.name = \"QuotaExceededError\";\n }\n };\n const platformCrypto = {\n randomUUID() {\n const randomUUID = capletsPlatformHost.randomUUID;\n if (!randomUUID) throw new Error(\"Code Mode platform random UUID bridge is not installed\");\n return randomUUID();\n },\n getRandomValues(typedArray) {\n if (!ArrayBuffer.isView(typedArray) || typedArray instanceof DataView) throw new TypeError(\"crypto.getRandomValues requires an integer typed array\");\n if (!integerTypedArrayConstructors.has(typedArray.constructor)) throw new TypeError(\"crypto.getRandomValues requires an integer typed array\");\n if (typedArray.byteLength > 65536) throw new QuotaExceededErrorShim(\"crypto.getRandomValues cannot generate more than 65,536 bytes\");\n const randomValues = capletsPlatformHost.randomValues;\n if (!randomValues) throw new Error(\"Code Mode platform random values bridge is not installed\");\n const bytes = randomValues(typedArray.byteLength);\n new Uint8Array(typedArray.buffer, typedArray.byteOffset, typedArray.byteLength).set(bytes);\n return typedArray;\n }\n };\n let nextTimerId = 1;\n const activeTimers = /* @__PURE__ */ new Set();\n function normalizeTimerDelay(delay) {\n const value = Number(delay ?? 0);\n if (!Number.isFinite(value) || value <= 0) return 0;\n return Math.trunc(value);\n }\n function setTimeoutShim(callback, delay, ...args) {\n if (typeof callback !== \"function\") throw new TypeError(\"setTimeout callback must be a function\");\n const timerId = nextTimerId++;\n activeTimers.add(timerId);\n const sleep = capletsPlatformHost.sleep;\n if (!sleep) throw new Error(\"Code Mode platform sleep bridge is not installed\");\n sleep(timerId, normalizeTimerDelay(delay)).then((fired) => {\n activeTimers.delete(timerId);\n if (fired) callback(...args);\n });\n return timerId;\n }\n function clearTimeoutShim(timerId) {\n const id = Number(timerId);\n activeTimers.delete(id);\n capletsPlatformHost.clearTimer?.(id);\n }\n function setIntervalShim(callback, delay, ...args) {\n if (typeof callback !== \"function\") throw new TypeError(\"setInterval callback must be a function\");\n const timerId = nextTimerId++;\n const intervalDelay = normalizeTimerDelay(delay);\n activeTimers.add(timerId);\n const tick = () => {\n const sleep = capletsPlatformHost.sleep;\n if (!sleep) throw new Error(\"Code Mode platform sleep bridge is not installed\");\n sleep(timerId, intervalDelay).then((fired) => {\n if (!fired || !activeTimers.has(timerId)) {\n activeTimers.delete(timerId);\n return;\n }\n callback(...args);\n if (activeTimers.has(timerId)) tick();\n });\n };\n tick();\n return timerId;\n }\n function clearIntervalShim(timerId) {\n clearTimeoutShim(timerId);\n }\n definePlatformGlobal(\"atob\", atobShim);\n definePlatformGlobal(\"btoa\", btoaShim);\n definePlatformGlobal(\"Buffer\", BufferShim);\n definePlatformGlobal(\"TextEncoder\", TextEncoderShim);\n definePlatformGlobal(\"TextDecoder\", TextDecoderShim);\n definePlatformGlobal(\"URL\", URLShim);\n definePlatformGlobal(\"URLSearchParams\", URLSearchParamsShim);\n definePlatformGlobal(\"structuredClone\", esm_default);\n definePlatformGlobal(\"Headers\", Headers);\n definePlatformGlobal(\"Blob\", Blob);\n definePlatformGlobal(\"File\", File);\n definePlatformGlobal(\"FormData\", FormData);\n definePlatformGlobal(\"ReadableStream\", ReadableStreamShim);\n definePlatformGlobal(\"WritableStream\", WritableStreamShim);\n definePlatformGlobal(\"TransformStream\", TransformStreamShim);\n definePlatformGlobal(\"AbortController\", AbortControllerShim);\n definePlatformGlobal(\"AbortSignal\", AbortSignalShim);\n definePlatformGlobal(\"Request\", RequestShim);\n definePlatformGlobal(\"Response\", ResponseShim);\n definePlatformGlobal(\"crypto\", platformCrypto);\n definePlatformGlobal(\"setTimeout\", setTimeoutShim);\n definePlatformGlobal(\"clearTimeout\", clearTimeoutShim);\n definePlatformGlobal(\"setInterval\", setIntervalShim);\n definePlatformGlobal(\"clearInterval\", clearIntervalShim);\n definePlatformGlobal(\"queueMicrotask\", queueMicrotaskShim);\n definePlatformGlobal(\"console\", platformConsole);\n definePlatformGlobal(\"fetch\", disabledFetch, { overwrite: true });\n //#endregion\n})();";
75650
77193
  //#endregion
75651
77194
  //#region src/code-mode/sandbox.ts
75652
77195
  var QuickJsCodeModeSandbox = class {
@@ -75676,6 +77219,7 @@ async function evaluateInQuickJs(input) {
75676
77219
  });
75677
77220
  context.setProp(context.global, "__caplets_log", logBridge);
75678
77221
  logBridge.dispose();
77222
+ const platformHost = installCodeModePlatformHost(context, pendingDeferreds, {});
75679
77223
  const invokeBridge = createInvokeBridge(context, pendingDeferreds, input.invoke, deadlineMs, timeoutMs);
75680
77224
  context.setProp(context.global, "__caplets_invoke", invokeBridge);
75681
77225
  invokeBridge.dispose();
@@ -75735,6 +77279,7 @@ async function evaluateInQuickJs(input) {
75735
77279
  };
75736
77280
  } finally {
75737
77281
  stateHandle.dispose();
77282
+ platformHost.dispose();
75738
77283
  }
75739
77284
  } finally {
75740
77285
  for (const deferred of pendingDeferreds) if (deferred.alive) deferred.dispose();
@@ -75794,19 +77339,7 @@ function buildExecutionSource(code, capletIds) {
75794
77339
  } }).outputText;
75795
77340
  return [
75796
77341
  "\"use strict\";",
75797
- "const __formatLogArg = (value) => {",
75798
- " if (typeof value === 'string') return value;",
75799
- " try { return JSON.stringify(value); } catch { return String(value); }",
75800
- "};",
75801
- "const __formatLogLine = (args) => args.map(__formatLogArg).join(' ');",
75802
- "const console = {",
75803
- " log: (...args) => __caplets_log('log', __formatLogLine(args)),",
75804
- " info: (...args) => __caplets_log('info', __formatLogLine(args)),",
75805
- " warn: (...args) => __caplets_log('warn', __formatLogLine(args)),",
75806
- " error: (...args) => __caplets_log('error', __formatLogLine(args)),",
75807
- " debug: (...args) => __caplets_log('debug', __formatLogLine(args)),",
75808
- "};",
75809
- "const fetch = () => { throw new Error('fetch is disabled in Code Mode'); };",
77342
+ CODE_MODE_PLATFORM_RUNTIME_SOURCE,
75810
77343
  "const __invoke = (capletId, method, args) => Promise.resolve(__caplets_invoke(capletId, method, args)).then(JSON.parse);",
75811
77344
  "const __handle = (capletId) => ({",
75812
77345
  " id: capletId,",
@@ -76978,6 +78511,7 @@ function remoteToolToNativeTool(tool) {
76978
78511
  return {
76979
78512
  caplet: capletId,
76980
78513
  ...sourceCaplet && sourceCaplet !== capletId ? { sourceCaplet } : {},
78514
+ ...tool.shadowing ? { shadowing: tool.shadowing } : {},
76981
78515
  toolName,
76982
78516
  title: tool.title ?? capletId,
76983
78517
  description: [
@@ -76991,7 +78525,8 @@ function remoteToolToNativeTool(tool) {
76991
78525
  ...tool.codeModeCaplets ? { codeModeCaplets: tool.codeModeCaplets.map((caplet) => ({
76992
78526
  id: caplet.capletId,
76993
78527
  name: caplet.name,
76994
- description: caplet.description ?? ""
78528
+ description: caplet.description ?? "",
78529
+ shadowing: caplet.shadowing
76995
78530
  })) } : {},
76996
78531
  inputSchema,
76997
78532
  ...isPlainObject(tool.outputSchema) ? { outputSchema: tool.outputSchema } : {},
@@ -77125,6 +78660,7 @@ function primitiveInvokeInput(capletId, operation, input) {
77125
78660
  }
77126
78661
  function toolsFromManifest(manifest) {
77127
78662
  const codeModeMarker = attachCodeModeMarker(manifest);
78663
+ const codeModeShadowing = manifest.codeModeCaplets.some((entry) => entry.shadowing === "forbid") ? "forbid" : "allow";
77128
78664
  return [
77129
78665
  ...manifest.caplets.map((entry) => ({
77130
78666
  name: entry.capletId,
@@ -77132,6 +78668,7 @@ function toolsFromManifest(manifest) {
77132
78668
  title: entry.title ?? entry.name,
77133
78669
  description: entry.description,
77134
78670
  inputSchema: entry.inputSchema,
78671
+ shadowing: entry.shadowing,
77135
78672
  ...codeModeMarker
77136
78673
  })),
77137
78674
  ...manifest.tools.map((entry) => ({
@@ -77143,6 +78680,7 @@ function toolsFromManifest(manifest) {
77143
78680
  inputSchema: entry.inputSchema,
77144
78681
  outputSchema: entry.outputSchema,
77145
78682
  annotations: entry.annotations,
78683
+ shadowing: entry.shadowing,
77146
78684
  ...codeModeMarker
77147
78685
  })),
77148
78686
  ...primitiveToolsFromManifest(manifest, codeModeMarker),
@@ -77153,6 +78691,7 @@ function toolsFromManifest(manifest) {
77153
78691
  description: "Remote Caplets available to locally-run attached Code Mode.",
77154
78692
  codeModeRun: true,
77155
78693
  codeModeCaplets: manifest.codeModeCaplets,
78694
+ shadowing: codeModeShadowing,
77156
78695
  inputSchema: codeModeRunInputJsonSchema()
77157
78696
  }] : []
77158
78697
  ];
@@ -77163,46 +78702,50 @@ function attachCodeModeMarker(manifest) {
77163
78702
  function primitiveToolsFromManifest(manifest, codeModeMarker) {
77164
78703
  const directToolNames = new Set(manifest.tools.map((entry) => entry.name));
77165
78704
  const byCaplet = /* @__PURE__ */ new Map();
77166
- const entryFor = (capletId) => {
78705
+ const entryFor = (capletId, shadowing) => {
77167
78706
  const existing = byCaplet.get(capletId);
77168
- if (existing) return existing;
78707
+ if (existing) {
78708
+ if (shadowing === "forbid") existing.shadowing = "forbid";
78709
+ return existing;
78710
+ }
77169
78711
  const next = {
77170
78712
  resources: false,
77171
78713
  resourceTemplates: false,
77172
78714
  prompts: false,
77173
- completions: false
78715
+ completions: false,
78716
+ shadowing
77174
78717
  };
77175
78718
  byCaplet.set(capletId, next);
77176
78719
  return next;
77177
78720
  };
77178
- for (const entry of manifest.resources) entryFor(entry.capletId).resources = true;
77179
- for (const entry of manifest.resourceTemplates) entryFor(entry.capletId).resourceTemplates = true;
77180
- for (const entry of manifest.prompts) entryFor(entry.capletId).prompts = true;
77181
- for (const entry of manifest.completions) entryFor(entry.capletId).completions = true;
78721
+ for (const entry of manifest.resources) entryFor(entry.capletId, entry.shadowing).resources = true;
78722
+ for (const entry of manifest.resourceTemplates) entryFor(entry.capletId, entry.shadowing).resourceTemplates = true;
78723
+ for (const entry of manifest.prompts) entryFor(entry.capletId, entry.shadowing).prompts = true;
78724
+ for (const entry of manifest.completions) entryFor(entry.capletId, entry.shadowing).completions = true;
77182
78725
  const tools = [];
77183
- const addPrimitiveTool = (capletId, operation) => {
78726
+ const addPrimitiveTool = (capletId, operation, shadowing) => {
77184
78727
  const name = `${capletId}__${operation}`;
77185
78728
  if (directToolNames.has(name)) return;
77186
- tools.push(primitiveTool(capletId, operation, codeModeMarker));
78729
+ tools.push(primitiveTool(capletId, operation, shadowing, codeModeMarker));
77187
78730
  };
77188
78731
  for (const [capletId, flags] of byCaplet) {
77189
78732
  if (flags.resources) {
77190
- addPrimitiveTool(capletId, "list_resources");
77191
- addPrimitiveTool(capletId, "read_resource");
78733
+ addPrimitiveTool(capletId, "list_resources", flags.shadowing);
78734
+ addPrimitiveTool(capletId, "read_resource", flags.shadowing);
77192
78735
  }
77193
78736
  if (flags.resourceTemplates) {
77194
- addPrimitiveTool(capletId, "list_resource_templates");
77195
- addPrimitiveTool(capletId, "read_resource");
78737
+ addPrimitiveTool(capletId, "list_resource_templates", flags.shadowing);
78738
+ addPrimitiveTool(capletId, "read_resource", flags.shadowing);
77196
78739
  }
77197
78740
  if (flags.prompts) {
77198
- addPrimitiveTool(capletId, "list_prompts");
77199
- addPrimitiveTool(capletId, "get_prompt");
78741
+ addPrimitiveTool(capletId, "list_prompts", flags.shadowing);
78742
+ addPrimitiveTool(capletId, "get_prompt", flags.shadowing);
77200
78743
  }
77201
- if (flags.completions) addPrimitiveTool(capletId, "complete");
78744
+ if (flags.completions) addPrimitiveTool(capletId, "complete", flags.shadowing);
77202
78745
  }
77203
78746
  return [...new Map(tools.map((tool) => [tool.name, tool])).values()];
77204
78747
  }
77205
- function primitiveTool(capletId, operation, codeModeMarker) {
78748
+ function primitiveTool(capletId, operation, shadowing, codeModeMarker) {
77206
78749
  return {
77207
78750
  name: `${capletId}__${operation}`,
77208
78751
  capletId,
@@ -77210,6 +78753,7 @@ function primitiveTool(capletId, operation, codeModeMarker) {
77210
78753
  title: operation,
77211
78754
  description: `MCP ${operation.replace(/_/g, " ")}.`,
77212
78755
  inputSchema: primitiveInputSchema(operation),
78756
+ shadowing,
77213
78757
  ...codeModeMarker
77214
78758
  };
77215
78759
  }
@@ -77810,7 +79354,7 @@ var DefaultNativeCapletsService = class {
77810
79354
  ...options,
77811
79355
  writeErr: this.writeErr
77812
79356
  });
77813
- this.postReloadRefresh = this.refreshExposureSnapshot({ emitToolsChanged: this.hasDirectMcpExposure() });
79357
+ this.postReloadRefresh = this.refreshExposureSnapshot({ emitToolsChanged: this.hasSnapshotBackedDirectExposure() });
77814
79358
  this.unsubscribeEngineReload = this.engine.onReload(() => {
77815
79359
  this.postReloadRefresh = this.refreshExposureSnapshot({ emitToolsChanged: true });
77816
79360
  });
@@ -77879,13 +79423,13 @@ var DefaultNativeCapletsService = class {
77879
79423
  ...action.outputSchema ? { outputSchema: action.outputSchema } : {},
77880
79424
  ...action.annotations ? { annotations: action.annotations } : {}
77881
79425
  }));
77882
- if (caplet.backend === "mcp") return [...snapshot?.directTools.filter((entry) => entry.caplet.server === caplet.server).map((entry) => this.directMcpTool(caplet, entry)) ?? [], ...mcpPrimitiveNativeTools(caplet, snapshot).map((operationName) => this.directNativeTool(caplet, operationName, {
79426
+ if (caplet.backend === "mcp") return [...snapshot?.directTools.filter((entry) => entry.caplet.server === caplet.server).map((entry) => this.directDiscoveredTool(caplet, entry)) ?? [], ...mcpPrimitiveNativeTools(caplet, snapshot).map((operationName) => this.directNativeTool(caplet, operationName, {
77883
79427
  description: `MCP ${operationName.replace(/_/g, " ")}.`,
77884
79428
  inputSchema: nativeMcpPrimitiveInputSchema(operationName)
77885
79429
  }))];
77886
- return [];
79430
+ return snapshot?.directTools.filter((entry) => entry.caplet.server === caplet.server).map((entry) => this.directDiscoveredTool(caplet, entry)) ?? [];
77887
79431
  }
77888
- directMcpTool(caplet, entry) {
79432
+ directDiscoveredTool(caplet, entry) {
77889
79433
  return this.directNativeTool(caplet, entry.downstreamName, {
77890
79434
  ...entry.tool.description ? { description: entry.tool.description } : {},
77891
79435
  ...entry.tool.inputSchema ? { inputSchema: entry.tool.inputSchema } : {},
@@ -77902,6 +79446,7 @@ var DefaultNativeCapletsService = class {
77902
79446
  });
77903
79447
  return {
77904
79448
  caplet: routeId,
79449
+ sourceCaplet: caplet.server,
77905
79450
  toolName,
77906
79451
  title: operationName,
77907
79452
  description: options.description ?? "",
@@ -77926,9 +79471,10 @@ var DefaultNativeCapletsService = class {
77926
79471
  this.writeErr(`${error instanceof Error ? error.message : String(error)}\n`);
77927
79472
  }
77928
79473
  }
77929
- hasDirectMcpExposure() {
79474
+ hasSnapshotBackedDirectExposure() {
77930
79475
  return this.engine.enabledServers().some((caplet) => {
77931
- if (caplet.backend !== "mcp" || caplet.setup || caplet.projectBinding?.required) return false;
79476
+ if (caplet.setup || caplet.projectBinding?.required) return false;
79477
+ if (caplet.backend === "http" || caplet.backend === "cli") return false;
77932
79478
  return resolveExposure(caplet.exposure, this.engine.currentConfig().options.exposure).direct;
77933
79479
  });
77934
79480
  }
@@ -78069,6 +79615,7 @@ function codeModeRunNativeTool(capletTools) {
78069
79615
  id: tool.caplet,
78070
79616
  name: tool.title,
78071
79617
  description: tool.description,
79618
+ ...tool.shadowing ? { shadowing: tool.shadowing } : {},
78072
79619
  ...tool.useWhen ? { useWhen: tool.useWhen } : {},
78073
79620
  ...tool.avoidWhen ? { avoidWhen: tool.avoidWhen } : {}
78074
79621
  }));
@@ -78103,6 +79650,7 @@ function codeModeCallableNativeTools(tools, options) {
78103
79650
  toolName: tool?.toolName ?? nativeCapletToolName(caplet.id),
78104
79651
  title: caplet.name,
78105
79652
  description: caplet.description,
79653
+ ...caplet.shadowing ? { shadowing: caplet.shadowing } : {},
78106
79654
  ...caplet.useWhen ? { useWhen: caplet.useWhen } : {},
78107
79655
  ...caplet.avoidWhen ? { avoidWhen: caplet.avoidWhen } : {},
78108
79656
  promptGuidance: tool?.promptGuidance ?? []
@@ -78275,9 +79823,7 @@ var CompositeNativeCapletsService = class {
78275
79823
  }
78276
79824
  async execute(capletId, request) {
78277
79825
  if (capletId === "code_mode") return await executeCodeModeRunNative(this, request);
78278
- const localHasCaplet = serviceHasCaplet(this.local, capletId);
78279
- const remoteHasCaplet = serviceHasCaplet(this.remote, capletId);
78280
- if (localHasCaplet && !remoteHasCaplet) return await this.local.execute(capletId, request);
79826
+ if (this.localCanExecute(capletId)) return await this.local.execute(capletId, request);
78281
79827
  return await this.remote.execute(capletId, request);
78282
79828
  }
78283
79829
  async reload() {
@@ -78320,8 +79866,8 @@ var CompositeNativeCapletsService = class {
78320
79866
  mergeTools() {
78321
79867
  const allLocalTools = this.local.listTools();
78322
79868
  const allRemoteTools = this.remote.listTools();
78323
- const remoteCodeModeTools = codeModeCallableNativeTools(allRemoteTools, { fallbackToVisible: true });
78324
- const remoteIds = new Set([...allRemoteTools.filter((tool) => tool.codeModeRun !== true).map((tool) => tool.sourceCaplet ?? tool.caplet), ...remoteCodeModeTools.map((tool) => tool.caplet)].filter((caplet) => caplet !== nativeCodeModeToolId));
79869
+ const remoteCodeModeTools = remoteCodeModeCallableNativeTools(allRemoteTools);
79870
+ const remoteIds = remoteSuppressedCapletIds(allRemoteTools, remoteCodeModeTools);
78325
79871
  const localTools = allLocalTools.filter((tool) => tool.codeModeRun !== true && !remoteIds.has(tool.sourceCaplet ?? tool.caplet));
78326
79872
  this.warnShadowedLocalCaplets(allLocalTools, remoteIds);
78327
79873
  const localCodeModeTools = codeModeCallableNativeTools(allLocalTools, { fallbackToVisible: false }).filter((tool) => !remoteIds.has(tool.caplet));
@@ -78329,6 +79875,10 @@ var CompositeNativeCapletsService = class {
78329
79875
  const codeModeTools = [...remoteCodeModeTools, ...localCodeModeTools];
78330
79876
  return [...mergedTools, ...codeModeTools.length > 0 ? [codeModeRunNativeTool(codeModeTools)] : []];
78331
79877
  }
79878
+ localCanExecute(capletId) {
79879
+ const remoteIds = remoteSuppressedCapletIds(this.remote.listTools());
79880
+ return localExecutionKeys(this.local.listTools(), capletId).some((key) => !remoteIds.has(key));
79881
+ }
78332
79882
  warnShadowedLocalCaplets(localTools, remoteIds) {
78333
79883
  const localIds = new Set([...localTools.filter((tool) => tool.codeModeRun !== true).map((tool) => tool.sourceCaplet ?? tool.caplet), ...codeModeCallableNativeTools(localTools, { fallbackToVisible: false }).map((tool) => tool.caplet)]);
78334
79884
  for (const capletId of localIds) {
@@ -78347,11 +79897,22 @@ var CompositeNativeCapletsService = class {
78347
79897
  }
78348
79898
  }
78349
79899
  };
78350
- function serviceHasCaplet(service, capletId) {
78351
- return service.listTools().some((tool) => {
78352
- if (tool.codeModeRun) return tool.codeModeCaplets?.some((caplet) => caplet.id === capletId) ?? false;
78353
- return tool.caplet === capletId || tool.sourceCaplet === capletId;
78354
- });
79900
+ function remoteCodeModeCallableNativeTools(tools) {
79901
+ return codeModeCallableNativeTools(tools, { fallbackToVisible: true });
79902
+ }
79903
+ function remoteSuppressedCapletIds(allRemoteTools, remoteCodeModeTools = remoteCodeModeCallableNativeTools(allRemoteTools)) {
79904
+ 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));
79905
+ }
79906
+ function localExecutionKeys(tools, capletId) {
79907
+ const keys = [];
79908
+ for (const tool of tools) {
79909
+ if (tool.codeModeRun) {
79910
+ for (const caplet of tool.codeModeCaplets ?? []) if (caplet.id === capletId) keys.push(caplet.id);
79911
+ continue;
79912
+ }
79913
+ if (tool.caplet === capletId || tool.sourceCaplet === capletId) keys.push(tool.sourceCaplet ?? tool.caplet);
79914
+ }
79915
+ return keys;
78355
79916
  }
78356
79917
  function createProjectBindingSessionManager(cloud, local, options) {
78357
79918
  if (!cloud) return;
@@ -78410,4 +79971,4 @@ function errorMessage(error) {
78410
79971
  return error instanceof Error ? error.message : String(error);
78411
79972
  }
78412
79973
  //#endregion
78413
- export { loadGlobalConfig as $, ListRootsResultSchema as $t, codeModeRunParamsSchema as A, assertToolsCallTaskCapability as At, generateCodeModeRunToolDescription as B, CreateTaskResultSchema as Bt, nativeCapletPromptGuidance as C, resolveCapletsRoot as Ct, nativeCodeModeToolId as D, ReadBuffer as Dt, nativeCapletsSystemGuidance as E, resolveProjectConfigPath as Et, listCodeModeCallableCaplets as F, CallToolRequestSchema as Ft, directResourceUriMatchesTemplate as G, GetPromptRequestSchema as Gt, CapletsEngine as H, ElicitResultSchema as Ht, CodeModeLogStore as I, CallToolResultSchema as It, handleServerTool as J, JSONRPCMessageSchema as Jt, findProjectRoot as K, InitializeRequestSchema as Kt, redactCodeModeLogText as L, CompleteRequestSchema as Lt, QuickJsCodeModeSandbox as M, Protocol as Mt, diagnoseCodeModeTypeScript as N, mergeCapabilities as Nt, nativeCodeModeToolName as O, serializeMessage as Ot, createCodeModeCapletsApi as P, toJsonSchemaCompat as Pt, loadConfigWithSources as Q, ListResourcesRequestSchema as Qt, codeModeDeclarationHash as R, CreateMessageResultSchema as Rt, resolveCapletsServer as S, __exportAll as Sn, defaultStateBaseDir as St, nativeCapletToolName as T, resolveProjectCapletsRoot as Tt, resolveExposure as U, EmptyResultSchema as Ut, minifyCodeModeDeclarationText as V, DEFAULT_NEGOTIATED_PROTOCOL_VERSION as Vt, decodeDirectResourceUri as W, ErrorCode as Wt, capabilityDescription as X, ListPromptsRequestSchema as Xt, ServerRegistry as Y, LATEST_PROTOCOL_VERSION as Yt, loadConfig as Z, ListResourceTemplatesRequestSchema as Zt, resolveHostedCloudRemote as _, isZ4Schema as _n, DEFAULT_AUTH_DIR as _t, projectBindingError as a, SetLevelRequestSchema as an, loadCapletFilesFromMap as at, parseServerBaseUrl as b, safeParse as bn, defaultCacheBaseDir as bt, cloudAuthPath as c, isInitializeRequest as cn, markdownStructuredContent as ct, CloudAuthClient as d, isJSONRPCResultResponse as dn, runOAuthFlow as dt, ListToolsRequestSchema as en, loadLocalOverlayConfigWithSources as et, RemoteNativeCapletsService as f, getLiteralValue as fn, startGenericOAuthFlow as ft, resolveCapletsRemote as g, isSchemaOptional as gn, readTokenBundle as gt, resolveNativeCapletsServiceOptions as h, getSchemaDescription as hn, isTokenBundleExpired as ht, ProjectBindingError as i, SUPPORTED_PROTOCOL_VERSIONS as in, validateCapletFile as it, runCodeMode as j, AjvJsonSchemaValidator as jt, codeModeRunInputSchema as k, assertClientRequestTaskCapability as kt, migrateCredentials as l, isJSONRPCErrorResponse as ln, refreshOAuthTokenBundle as lt, buildProjectSyncManifest as m, getParseErrorMessage as mn, deleteTokenBundle as mt, resolveRemoteSelection as n, McpError as nn, parseConfig as nt, projectBindingRecovery as o, assertCompleteRequestPrompt as on, hasRenderableStructuredContent as ot, createSdkRemoteCapletsClient as p, getObjectShape as pn, startOAuthFlow as pt, fingerprintProjectRoot as q, InitializedNotificationSchema as qt, PROJECT_BINDING_ERROR_CODES as r, ReadResourceRequestSchema as rn, discoverCapletFiles as rt, CloudAuthStore as s, assertCompleteRequestResourceTemplate as sn, markdownCallToolResultContent as st, createNativeCapletsService as t, LoggingLevelSchema as tn, loadProjectConfig as tt, redactedCloudAuthStatus as u, isJSONRPCRequest as un, runGenericOAuthFlow as ut, resolveRemoteMode as v, normalizeObjectSchema as vn, DEFAULT_COMPLETION_CACHE_DIR as vt, nativeCapletToolDescription as w, resolveConfigPath as wt, resolveCapletsMode as x, safeParseAsync as xn, defaultConfigBaseDir as xt, controlUrlForBase as y, objectFromShape as yn, DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR as yt, generateCodeModeDeclarations as z, CreateMessageResultWithToolsSchema as zt };
79974
+ export { loadConfigWithSources as $, ListResourcesRequestSchema as $t, codeModeRunParamsSchema as A, assertClientRequestTaskCapability as At, generateCodeModeRunToolDescription as B, CreateMessageResultWithToolsSchema as Bt, nativeCapletPromptGuidance as C, __exportAll as Cn, defaultStateBaseDir as Ct, nativeCodeModeToolId as D, resolveProjectConfigPath as Dt, nativeCapletsSystemGuidance as E, resolveProjectCapletsRoot as Et, listCodeModeCallableCaplets as F, toJsonSchemaCompat as Ft, directResourceUriMatchesTemplate as G, ErrorCode as Gt, CapletsEngine as H, DEFAULT_NEGOTIATED_PROTOCOL_VERSION as Ht, CodeModeLogStore as I, CallToolRequestSchema as It, handleServerTool as J, InitializedNotificationSchema as Jt, findProjectRoot as K, GetPromptRequestSchema as Kt, redactCodeModeLogText as L, CallToolResultSchema as Lt, QuickJsCodeModeSandbox as M, AjvJsonSchemaValidator as Mt, diagnoseCodeModeTypeScript as N, Protocol as Nt, nativeCodeModeToolName as O, ReadBuffer as Ot, createCodeModeCapletsApi as P, mergeCapabilities as Pt, loadConfig as Q, ListResourceTemplatesRequestSchema as Qt, codeModeDeclarationHash as R, CompleteRequestSchema as Rt, resolveCapletsServer as S, safeParseAsync as Sn, defaultConfigBaseDir as St, nativeCapletToolName as T, resolveConfigPath as Tt, resolveExposure as U, ElicitResultSchema as Ut, minifyCodeModeDeclarationText as V, CreateTaskResultSchema as Vt, decodeDirectResourceUri as W, EmptyResultSchema as Wt, capabilityDescription as X, LATEST_PROTOCOL_VERSION as Xt, ServerRegistry as Y, JSONRPCMessageSchema as Yt, GoogleDiscoveryManager as Z, ListPromptsRequestSchema as Zt, resolveHostedCloudRemote as _, isSchemaOptional as _n, readTokenBundle as _t, projectBindingError as a, SUPPORTED_PROTOCOL_VERSIONS as an, validateCapletFile as at, parseServerBaseUrl as b, objectFromShape as bn, DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR as bt, cloudAuthPath as c, assertCompleteRequestResourceTemplate as cn, markdownCallToolResultContent as ct, CloudAuthClient as d, isJSONRPCRequest as dn, runGenericOAuthFlow as dt, ListRootsResultSchema as en, loadGlobalConfig as et, RemoteNativeCapletsService as f, isJSONRPCResultResponse as fn, runOAuthFlow as ft, resolveCapletsRemote as g, getSchemaDescription as gn, isTokenBundleExpired as gt, resolveNativeCapletsServiceOptions as h, getParseErrorMessage as hn, deleteTokenBundle as ht, ProjectBindingError as i, ReadResourceRequestSchema as in, discoverCapletFiles as it, runCodeMode as j, assertToolsCallTaskCapability as jt, codeModeRunInputSchema as k, serializeMessage as kt, migrateCredentials as l, isInitializeRequest as ln, markdownStructuredContent as lt, buildProjectSyncManifest as m, getObjectShape as mn, startOAuthFlow as mt, resolveRemoteSelection as n, LoggingLevelSchema as nn, loadProjectConfig as nt, projectBindingRecovery as o, SetLevelRequestSchema as on, loadCapletFilesFromMap as ot, createSdkRemoteCapletsClient as p, getLiteralValue as pn, startGenericOAuthFlow as pt, fingerprintProjectRoot as q, InitializeRequestSchema as qt, PROJECT_BINDING_ERROR_CODES as r, McpError as rn, parseConfig as rt, CloudAuthStore as s, assertCompleteRequestPrompt as sn, hasRenderableStructuredContent as st, createNativeCapletsService as t, ListToolsRequestSchema as tn, loadLocalOverlayConfigWithSources as tt, redactedCloudAuthStatus as u, isJSONRPCErrorResponse as un, refreshOAuthTokenBundle as ut, resolveRemoteMode as v, isZ4Schema as vn, DEFAULT_AUTH_DIR as vt, nativeCapletToolDescription as w, resolveCapletsRoot as wt, resolveCapletsMode as x, safeParse as xn, defaultCacheBaseDir as xt, controlUrlForBase as y, normalizeObjectSchema as yn, DEFAULT_COMPLETION_CACHE_DIR as yt, generateCodeModeDeclarations as z, CreateMessageResultSchema as zt };