@caplets/core 0.19.0 → 0.20.1

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 (75) hide show
  1. package/dist/auth.d.ts +2 -2
  2. package/dist/caplet-files-bundle.d.ts +24 -9
  3. package/dist/caplet-source.js +368 -4588
  4. package/dist/cli/auth.d.ts +40 -2
  5. package/dist/cli/cloud-add.d.ts +8 -0
  6. package/dist/cli/code-mode.d.ts +16 -0
  7. package/dist/cli/commands.d.ts +3 -1
  8. package/dist/cli/doctor.d.ts +3 -0
  9. package/dist/cli/setup.d.ts +7 -0
  10. package/dist/cli-tools.d.ts +1 -1
  11. package/dist/cli.d.ts +1 -0
  12. package/dist/cloud-auth/client.d.ts +15 -0
  13. package/dist/cloud-auth/types.d.ts +2 -1
  14. package/dist/code-mode/api.d.ts +32 -0
  15. package/dist/code-mode/declarations.d.ts +5 -0
  16. package/dist/code-mode/diagnostics.d.ts +8 -0
  17. package/dist/code-mode/index.d.ts +4 -0
  18. package/dist/code-mode/logs.d.ts +21 -0
  19. package/dist/code-mode/runner.d.ts +15 -0
  20. package/dist/code-mode/runtime-api.generated.d.ts +1 -0
  21. package/dist/code-mode/sandbox.d.ts +28 -0
  22. package/dist/code-mode/static-analysis.d.ts +2 -0
  23. package/dist/code-mode/tool.d.ts +11 -0
  24. package/dist/code-mode/types.d.ts +120 -0
  25. package/dist/code-mode.js +147855 -0
  26. package/dist/{completion-brgziz4L.js → completion-D-kuyArL.js} +5 -2
  27. package/dist/config/paths.d.ts +2 -0
  28. package/dist/config-runtime.d.ts +13 -4
  29. package/dist/config-runtime.js +31 -2
  30. package/dist/config.d.ts +34 -9
  31. package/dist/downstream.d.ts +20 -2
  32. package/dist/engine.d.ts +20 -0
  33. package/dist/exposure/direct-names.d.ts +9 -0
  34. package/dist/exposure/discovery.d.ts +75 -0
  35. package/dist/exposure/policy.d.ts +8 -0
  36. package/dist/generated-tool-input-schema.d.ts +89 -59
  37. package/dist/generated-tool-input-schema.js +38 -27
  38. package/dist/graphql.d.ts +1 -1
  39. package/dist/http-actions.d.ts +1 -1
  40. package/dist/index.d.ts +13 -0
  41. package/dist/index.js +1096 -154
  42. package/dist/native/service.d.ts +6 -0
  43. package/dist/native/tools.d.ts +2 -0
  44. package/dist/native.d.ts +1 -1
  45. package/dist/native.js +2 -2
  46. package/dist/observed-output-shapes/extract.d.ts +5 -0
  47. package/dist/observed-output-shapes/file-store.d.ts +17 -0
  48. package/dist/observed-output-shapes/index.d.ts +7 -0
  49. package/dist/observed-output-shapes/key.d.ts +14 -0
  50. package/dist/observed-output-shapes/merge.d.ts +2 -0
  51. package/dist/observed-output-shapes/pure.d.ts +5 -0
  52. package/dist/observed-output-shapes/pure.js +241 -0
  53. package/dist/observed-output-shapes/schema.d.ts +1 -0
  54. package/dist/observed-output-shapes/types.d.ts +84 -0
  55. package/dist/observed-output-shapes/typescript.d.ts +7 -0
  56. package/dist/observed-output-shapes-uzAMQPhg.js +485 -0
  57. package/dist/observed-output-shapes.js +2 -0
  58. package/dist/openapi.d.ts +1 -1
  59. package/dist/project-binding/index.d.ts +2 -0
  60. package/dist/project-binding.js +22 -0
  61. package/dist/redaction.d.ts +14 -0
  62. package/dist/redaction.js +30 -0
  63. package/dist/registry.d.ts +4 -0
  64. package/dist/remote/options.d.ts +2 -0
  65. package/dist/remote-control/types.d.ts +1 -1
  66. package/dist/runtime-plan/resources.d.ts +2 -0
  67. package/dist/runtime-plan.js +8 -2
  68. package/dist/schemas-1HZ0kFpx.js +4270 -0
  69. package/dist/serve/session.d.ts +15 -3
  70. package/dist/{service-BXcE4Rv8.js → service-Bsq7R0mt.js} +29312 -26554
  71. package/dist/stable-json.d.ts +3 -0
  72. package/dist/stable-json.js +26 -0
  73. package/dist/tools.d.ts +22 -11
  74. package/dist/{validation-BBG4skZf.js → validation-CdqbI2zN.js} +25 -4
  75. package/package.json +29 -3
package/dist/index.js CHANGED
@@ -1,18 +1,19 @@
1
- import { $ as ElicitResultSchema, $t as markdownStructuredContent, A as capabilityDescription, At as objectFromShape, B as assertClientRequestTaskCapability, C as migrateCredentials, Ct as getLiteralValue, D as CapletsEngine, Dt as isSchemaOptional, E as fingerprintProjectRoot, Et as getSchemaDescription, F as deleteTokenBundle, Ft as loadGlobalConfig, G as toJsonSchemaCompat, Gt as resolveConfigPath, H as AjvJsonSchemaValidator, Ht as defaultConfigBaseDir, I as isTokenBundleExpired, It as loadLocalOverlayConfigWithSources, J as CompleteRequestSchema, Jt as discoverCapletFiles, K as CallToolRequestSchema, Kt as resolveProjectCapletsRoot, L as readTokenBundle, Lt as loadProjectConfig, M as runOAuthFlow, Mt as safeParseAsync, N as startGenericOAuthFlow, Nt as loadConfig, O as handleServerTool, Ot as isZ4Schema, P as startOAuthFlow, Pt as loadConfigWithSources, Qt as markdownCallToolResultContent, R as ReadBuffer, Rt as parseConfig, S as cloudAuthPath, St as isJSONRPCResultResponse, T as findProjectRoot, Tt as getParseErrorMessage, U as Protocol, Ut as defaultStateBaseDir, V as assertToolsCallTaskCapability, Vt as defaultCacheBaseDir, W as mergeCapabilities, Wt as resolveCapletsRoot, X as CreateMessageResultWithToolsSchema, Xt as loadCapletFilesFromMap, Y as CreateMessageResultSchema, Yt as validateCapletFile, Z as CreateTaskResultSchema, Zt as hasRenderableStructuredContent, _ as controlUrlForBase, _t as assertCompleteRequestPrompt, a as createSdkRemoteCapletsClient, at as JSONRPCMessageSchema, b as resolveCapletsServer, bt as isJSONRPCErrorResponse, ct as ListResourceTemplatesRequestSchema, d as PROJECT_BINDING_ERROR_CODES, dt as ListToolsRequestSchema, et as EmptyResultSchema, f as ProjectBindingError, ft as LoggingLevelSchema, g as resolveCapletsRemote, gt as SetLevelRequestSchema, h as CloudAuthClient, ht as SUPPORTED_PROTOCOL_VERSIONS, it as InitializedNotificationSchema, j as runGenericOAuthFlow, jt as safeParse, k as ServerRegistry, kt as normalizeObjectSchema, lt as ListResourcesRequestSchema, m as projectBindingRecovery, mt as ReadResourceRequestSchema, n as buildProjectSyncManifest, nt as GetPromptRequestSchema, ot as LATEST_PROTOCOL_VERSION, p as projectBindingError, pt as McpError, q as CallToolResultSchema, qt as resolveProjectConfigPath, rt as InitializeRequestSchema, st as ListPromptsRequestSchema, t as createNativeCapletsService, tt as ErrorCode, u as resolveRemoteSelection, ut as ListRootsResultSchema, v as parseServerBaseUrl, vt as assertCompleteRequestResourceTemplate, w as redactedCloudAuthStatus, wt as getObjectShape, x as CloudAuthStore, xt as isJSONRPCRequest, y as resolveCapletsMode, yt as isInitializeRequest, z as serializeMessage } from "./service-BXcE4Rv8.js";
2
- import { f as redactSecrets, i as SERVER_ID_PATTERN, l as CAPLETS_ERROR_CODES, p as toSafeError, u as CapletsError } from "./validation-BBG4skZf.js";
1
+ import { $ as parseConfig, $t as ReadResourceRequestSchema, A as QuickJsCodeModeSandbox, At as toJsonSchemaCompat, B as CapletsEngine, Bt as ErrorCode, C as nativeCapletToolName, Ct as ReadBuffer, D as codeModeRunInputSchema, Dt as AjvJsonSchemaValidator, Et as assertToolsCallTaskCapability, F as redactCodeModeLogText, Ft as CreateMessageResultWithToolsSchema, G as handleServerTool, Gt as LATEST_PROTOCOL_VERSION, H as decodeDirectResourceUri, Ht as InitializeRequestSchema, I as codeModeDeclarationHash, It as CreateTaskResultSchema, J as loadConfig, Jt as ListResourcesRequestSchema, K as ServerRegistry, Kt as ListPromptsRequestSchema, L as generateCodeModeDeclarations, M as createCodeModeCapletsApi, Mt as CallToolResultSchema, N as listCodeModeCallableCaplets, Nt as CompleteRequestSchema, O as codeModeRunParamsSchema, Ot as Protocol, P as CodeModeLogStore, Pt as CreateMessageResultSchema, Q as loadProjectConfig, Qt as McpError, R as generateCodeModeRunToolDescription, Rt as ElicitResultSchema, S as nativeCapletToolDescription, St as resolveProjectConfigPath, T as nativeCodeModeToolId, Tt as assertClientRequestTaskCapability, U as findProjectRoot, Ut as InitializedNotificationSchema, V as resolveExposure, Vt as GetPromptRequestSchema, W as fingerprintProjectRoot, Wt as JSONRPCMessageSchema, X as loadGlobalConfig, Xt as ListToolsRequestSchema, Y as loadConfigWithSources, Yt as ListRootsResultSchema, Z as loadLocalOverlayConfigWithSources, Zt as LoggingLevelSchema, _ as controlUrlForBase, _n as safeParseAsync, _t as defaultConfigBaseDir, a as projectBindingError, an as isJSONRPCErrorResponse, at as markdownStructuredContent, b as resolveCapletsServer, bt as resolveConfigPath, c as cloudAuthPath, cn as getLiteralValue, ct as startGenericOAuthFlow, d as CloudAuthClient, dn as getSchemaDescription, dt as isTokenBundleExpired, en as SUPPORTED_PROTOCOL_VERSIONS, et as discoverCapletFiles, fn as isSchemaOptional, ft as readTokenBundle, g as resolveCapletsRemote, gn as safeParse, gt as defaultCacheBaseDir, hn as objectFromShape, ht as DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR, i as ProjectBindingError, in as isInitializeRequest, it as markdownCallToolResultContent, j as diagnoseCodeModeTypeScript, jt as CallToolRequestSchema, k as runCodeMode, kt as mergeCapabilities, l as migrateCredentials, ln as getObjectShape, lt as startOAuthFlow, m as buildProjectSyncManifest, mn as normalizeObjectSchema, n as resolveRemoteSelection, nn as assertCompleteRequestPrompt, nt as loadCapletFilesFromMap, o as projectBindingRecovery, on as isJSONRPCRequest, ot as runGenericOAuthFlow, p as createSdkRemoteCapletsClient, pn as isZ4Schema, q as capabilityDescription, qt as ListResourceTemplatesRequestSchema, r as PROJECT_BINDING_ERROR_CODES, rn as assertCompleteRequestResourceTemplate, rt as hasRenderableStructuredContent, s as CloudAuthStore, sn as isJSONRPCResultResponse, st as runOAuthFlow, t as createNativeCapletsService, tn as SetLevelRequestSchema, tt as validateCapletFile, u as redactedCloudAuthStatus, un as getParseErrorMessage, ut as deleteTokenBundle, v as parseServerBaseUrl, vt as defaultStateBaseDir, wt as serializeMessage, x as nativeCapletPromptGuidance, xt as resolveProjectCapletsRoot, y as resolveCapletsMode, yt as resolveCapletsRoot, z as minifyCodeModeDeclarationText, zt as EmptyResultSchema } from "./service-Bsq7R0mt.js";
3
2
  import { _ as record, b as unknown, d as literal, m as object, n as ZodOptional, o as array, p as number, r as _enum, s as boolean, v as string, x as url } from "./schemas-BZ6BBrh7.js";
3
+ import { f as redactSecrets, i as SERVER_ID_PATTERN, l as CAPLETS_ERROR_CODES, p as toSafeError, u as CapletsError } from "./validation-CdqbI2zN.js";
4
4
  import { generatedToolInputSchema, generatedToolInputSchemaForCaplet } from "./generated-tool-input-schema.js";
5
- import { a as formatCapletList, c as resolveCliConfigPaths, l as cliCommands$1, n as completionScript, o as formatConfigPaths, s as listCaplets, t as completeCliWords, u as completionShells } from "./completion-brgziz4L.js";
5
+ import { f as observedOutputShapeKey, i as observeOutputShape, u as FileObservedOutputShapeStore } from "./observed-output-shapes-uzAMQPhg.js";
6
+ import { a as formatCapletList, c as resolveCliConfigPaths, l as cliCommands$1, n as completionScript, o as formatConfigPaths, s as listCaplets, t as completeCliWords, u as completionShells } from "./completion-D-kuyArL.js";
6
7
  import { n as normalizeCapletSourcePath, t as FilesystemCapletSource } from "./filesystem-Kkg32TOJ.js";
7
8
  import { parseConfig as parseConfig$1 } from "./config-runtime.js";
8
9
  import fs, { accessSync, chmodSync, closeSync, constants, copyFileSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, readlinkSync, realpathSync, rmSync, statSync, writeFileSync, writeSync } from "node:fs";
9
10
  import path, { basename, dirname, isAbsolute, join, parse, posix, relative, resolve, sep, win32 } from "node:path";
10
11
  import childProcess, { execFile, execFileSync, spawn } from "node:child_process";
11
- import { homedir, tmpdir } from "node:os";
12
12
  import process$1, { stdin, stdout } from "node:process";
13
13
  import { Readable } from "node:stream";
14
14
  import { STATUS_CODES, createServer } from "node:http";
15
15
  import { createHash, randomUUID, timingSafeEqual } from "node:crypto";
16
+ import { homedir, tmpdir } from "node:os";
16
17
  import { EventEmitter } from "node:events";
17
18
  import { promisify, stripVTControlCharacters } from "node:util";
18
19
  import { createInterface } from "node:readline/promises";
@@ -598,6 +599,203 @@ var McpZodTypeKind;
598
599
  McpZodTypeKind["Completable"] = "McpCompletable";
599
600
  })(McpZodTypeKind || (McpZodTypeKind = {}));
600
601
  //#endregion
602
+ //#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/uriTemplate.js
603
+ const MAX_TEMPLATE_LENGTH = 1e6;
604
+ const MAX_VARIABLE_LENGTH = 1e6;
605
+ const MAX_TEMPLATE_EXPRESSIONS = 1e4;
606
+ const MAX_REGEX_LENGTH = 1e6;
607
+ var UriTemplate = class UriTemplate {
608
+ /**
609
+ * Returns true if the given string contains any URI template expressions.
610
+ * A template expression is a sequence of characters enclosed in curly braces,
611
+ * like {foo} or {?bar}.
612
+ */
613
+ static isTemplate(str) {
614
+ return /\{[^}\s]+\}/.test(str);
615
+ }
616
+ static validateLength(str, max, context) {
617
+ if (str.length > max) throw new Error(`${context} exceeds maximum length of ${max} characters (got ${str.length})`);
618
+ }
619
+ get variableNames() {
620
+ return this.parts.flatMap((part) => typeof part === "string" ? [] : part.names);
621
+ }
622
+ constructor(template) {
623
+ UriTemplate.validateLength(template, MAX_TEMPLATE_LENGTH, "Template");
624
+ this.template = template;
625
+ this.parts = this.parse(template);
626
+ }
627
+ toString() {
628
+ return this.template;
629
+ }
630
+ parse(template) {
631
+ const parts = [];
632
+ let currentText = "";
633
+ let i = 0;
634
+ let expressionCount = 0;
635
+ while (i < template.length) if (template[i] === "{") {
636
+ if (currentText) {
637
+ parts.push(currentText);
638
+ currentText = "";
639
+ }
640
+ const end = template.indexOf("}", i);
641
+ if (end === -1) throw new Error("Unclosed template expression");
642
+ expressionCount++;
643
+ if (expressionCount > MAX_TEMPLATE_EXPRESSIONS) throw new Error(`Template contains too many expressions (max ${MAX_TEMPLATE_EXPRESSIONS})`);
644
+ const expr = template.slice(i + 1, end);
645
+ const operator = this.getOperator(expr);
646
+ const exploded = expr.includes("*");
647
+ const names = this.getNames(expr);
648
+ const name = names[0];
649
+ for (const name of names) UriTemplate.validateLength(name, MAX_VARIABLE_LENGTH, "Variable name");
650
+ parts.push({
651
+ name,
652
+ operator,
653
+ names,
654
+ exploded
655
+ });
656
+ i = end + 1;
657
+ } else {
658
+ currentText += template[i];
659
+ i++;
660
+ }
661
+ if (currentText) parts.push(currentText);
662
+ return parts;
663
+ }
664
+ getOperator(expr) {
665
+ return [
666
+ "+",
667
+ "#",
668
+ ".",
669
+ "/",
670
+ "?",
671
+ "&"
672
+ ].find((op) => expr.startsWith(op)) || "";
673
+ }
674
+ getNames(expr) {
675
+ const operator = this.getOperator(expr);
676
+ return expr.slice(operator.length).split(",").map((name) => name.replace("*", "").trim()).filter((name) => name.length > 0);
677
+ }
678
+ encodeValue(value, operator) {
679
+ UriTemplate.validateLength(value, MAX_VARIABLE_LENGTH, "Variable value");
680
+ if (operator === "+" || operator === "#") return encodeURI(value);
681
+ return encodeURIComponent(value);
682
+ }
683
+ expandPart(part, variables) {
684
+ if (part.operator === "?" || part.operator === "&") {
685
+ const pairs = part.names.map((name) => {
686
+ const value = variables[name];
687
+ if (value === void 0) return "";
688
+ return `${name}=${Array.isArray(value) ? value.map((v) => this.encodeValue(v, part.operator)).join(",") : this.encodeValue(value.toString(), part.operator)}`;
689
+ }).filter((pair) => pair.length > 0);
690
+ if (pairs.length === 0) return "";
691
+ return (part.operator === "?" ? "?" : "&") + pairs.join("&");
692
+ }
693
+ if (part.names.length > 1) {
694
+ const values = part.names.map((name) => variables[name]).filter((v) => v !== void 0);
695
+ if (values.length === 0) return "";
696
+ return values.map((v) => Array.isArray(v) ? v[0] : v).join(",");
697
+ }
698
+ const value = variables[part.name];
699
+ if (value === void 0) return "";
700
+ const encoded = (Array.isArray(value) ? value : [value]).map((v) => this.encodeValue(v, part.operator));
701
+ switch (part.operator) {
702
+ case "": return encoded.join(",");
703
+ case "+": return encoded.join(",");
704
+ case "#": return "#" + encoded.join(",");
705
+ case ".": return "." + encoded.join(".");
706
+ case "/": return "/" + encoded.join("/");
707
+ default: return encoded.join(",");
708
+ }
709
+ }
710
+ expand(variables) {
711
+ let result = "";
712
+ let hasQueryParam = false;
713
+ for (const part of this.parts) {
714
+ if (typeof part === "string") {
715
+ result += part;
716
+ continue;
717
+ }
718
+ const expanded = this.expandPart(part, variables);
719
+ if (!expanded) continue;
720
+ if ((part.operator === "?" || part.operator === "&") && hasQueryParam) result += expanded.replace("?", "&");
721
+ else result += expanded;
722
+ if (part.operator === "?" || part.operator === "&") hasQueryParam = true;
723
+ }
724
+ return result;
725
+ }
726
+ escapeRegExp(str) {
727
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
728
+ }
729
+ partToRegExp(part) {
730
+ const patterns = [];
731
+ for (const name of part.names) UriTemplate.validateLength(name, MAX_VARIABLE_LENGTH, "Variable name");
732
+ if (part.operator === "?" || part.operator === "&") {
733
+ for (let i = 0; i < part.names.length; i++) {
734
+ const name = part.names[i];
735
+ const prefix = i === 0 ? "\\" + part.operator : "&";
736
+ patterns.push({
737
+ pattern: prefix + this.escapeRegExp(name) + "=([^&]+)",
738
+ name
739
+ });
740
+ }
741
+ return patterns;
742
+ }
743
+ let pattern;
744
+ const name = part.name;
745
+ switch (part.operator) {
746
+ case "":
747
+ pattern = part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)";
748
+ break;
749
+ case "+":
750
+ case "#":
751
+ pattern = "(.+)";
752
+ break;
753
+ case ".":
754
+ pattern = "\\.([^/,]+)";
755
+ break;
756
+ case "/":
757
+ pattern = "/" + (part.exploded ? "([^/,]+(?:,[^/,]+)*)" : "([^/,]+)");
758
+ break;
759
+ default: pattern = "([^/]+)";
760
+ }
761
+ patterns.push({
762
+ pattern,
763
+ name
764
+ });
765
+ return patterns;
766
+ }
767
+ match(uri) {
768
+ UriTemplate.validateLength(uri, MAX_TEMPLATE_LENGTH, "URI");
769
+ let pattern = "^";
770
+ const names = [];
771
+ for (const part of this.parts) if (typeof part === "string") pattern += this.escapeRegExp(part);
772
+ else {
773
+ const patterns = this.partToRegExp(part);
774
+ for (const { pattern: partPattern, name } of patterns) {
775
+ pattern += partPattern;
776
+ names.push({
777
+ name,
778
+ exploded: part.exploded
779
+ });
780
+ }
781
+ }
782
+ pattern += "$";
783
+ UriTemplate.validateLength(pattern, MAX_REGEX_LENGTH, "Generated regex pattern");
784
+ const regex = new RegExp(pattern);
785
+ const match = uri.match(regex);
786
+ if (!match) return null;
787
+ const result = {};
788
+ for (let i = 0; i < names.length; i++) {
789
+ const { name, exploded } = names[i];
790
+ const value = match[i + 1];
791
+ const cleanName = name.replace("*", "");
792
+ if (exploded && value.includes(",")) result[cleanName] = value.split(",");
793
+ else result[cleanName] = value;
794
+ }
795
+ return result;
796
+ }
797
+ };
798
+ //#endregion
601
799
  //#region ../../node_modules/.pnpm/@modelcontextprotocol+sdk@1.29.0_zod@4.4.3/node_modules/@modelcontextprotocol/sdk/dist/esm/shared/toolNameValidation.js
602
800
  /**
603
801
  * Tool name validation utilities according to SEP: Specify Format for Tool Names
@@ -1250,6 +1448,34 @@ var McpServer = class {
1250
1448
  if (this.isConnected()) this.server.sendPromptListChanged();
1251
1449
  }
1252
1450
  };
1451
+ /**
1452
+ * A resource template combines a URI pattern with optional functionality to enumerate
1453
+ * all resources matching that pattern.
1454
+ */
1455
+ var ResourceTemplate = class {
1456
+ constructor(uriTemplate, _callbacks) {
1457
+ this._callbacks = _callbacks;
1458
+ this._uriTemplate = typeof uriTemplate === "string" ? new UriTemplate(uriTemplate) : uriTemplate;
1459
+ }
1460
+ /**
1461
+ * Gets the URI template pattern.
1462
+ */
1463
+ get uriTemplate() {
1464
+ return this._uriTemplate;
1465
+ }
1466
+ /**
1467
+ * Gets the list callback, if one was provided.
1468
+ */
1469
+ get listCallback() {
1470
+ return this._callbacks.list;
1471
+ }
1472
+ /**
1473
+ * Gets the callback for completing a specific URI template variable, if one was provided.
1474
+ */
1475
+ completeCallback(variable) {
1476
+ return this._callbacks.complete?.[variable];
1477
+ }
1478
+ };
1253
1479
  const EMPTY_OBJECT_JSON_SCHEMA = {
1254
1480
  type: "object",
1255
1481
  properties: {}
@@ -1327,13 +1553,16 @@ const EMPTY_COMPLETION_RESULT = { completion: {
1327
1553
  } };
1328
1554
  //#endregion
1329
1555
  //#region package.json
1330
- var version = "0.19.0";
1556
+ var version = "0.20.1";
1331
1557
  //#endregion
1332
1558
  //#region src/serve/session.ts
1333
1559
  var CapletsMcpSession = class {
1334
1560
  engine;
1335
1561
  server;
1336
1562
  tools = /* @__PURE__ */ new Map();
1563
+ resources = /* @__PURE__ */ new Map();
1564
+ prompts = /* @__PURE__ */ new Map();
1565
+ codeModeTool;
1337
1566
  unsubscribeReload;
1338
1567
  closed = false;
1339
1568
  constructor(engine, options = {}) {
@@ -1342,71 +1571,284 @@ var CapletsMcpSession = class {
1342
1571
  name: "caplets",
1343
1572
  version
1344
1573
  });
1345
- this.unsubscribeReload = this.engine.onReload(({ previous, next }) => this.reconcileTools(previous, next));
1346
- this.reconcileTools(void 0, this.engine.currentConfig());
1574
+ this.unsubscribeReload = this.engine.onReload(({ previous, next }) => {
1575
+ this.reconcileFromSnapshot(staticExposureSnapshot(next, this.engine.enabledServers()));
1576
+ this.refreshExposure(previous, next);
1577
+ });
1578
+ this.reconcileFromSnapshot(staticExposureSnapshot(this.engine.currentConfig(), this.engine.enabledServers()));
1347
1579
  }
1348
1580
  async connect(transport) {
1581
+ await this.refreshExposure(void 0, this.engine.currentConfig());
1349
1582
  await this.server.connect(transport);
1350
1583
  }
1351
1584
  registeredToolIds() {
1352
1585
  return [...this.tools.keys()].sort();
1353
1586
  }
1587
+ async refreshExposure(_previous = void 0, _next = this.engine.currentConfig()) {
1588
+ if (this.closed) return;
1589
+ this.reconcileFromSnapshot(await this.engine.exposureSnapshot());
1590
+ }
1354
1591
  async close() {
1355
1592
  if (this.closed) return;
1356
1593
  this.closed = true;
1357
1594
  this.unsubscribeReload();
1358
- this.tools.clear();
1595
+ this.clearRegistrations();
1359
1596
  await this.server.close();
1360
1597
  }
1361
- reconcileTools(previous, next) {
1362
- const enabled = new Map(nextEnabledServers(next).map((server) => [server.server, server]));
1363
- for (const [serverId, tool] of this.tools) {
1364
- const caplet = enabled.get(serverId);
1365
- if (!caplet) {
1598
+ reconcileFromSnapshot(snapshot) {
1599
+ if (snapshot.codeModeCaplets.length > 0) if (this.codeModeTool) this.codeModeTool.update({
1600
+ title: "Code Mode",
1601
+ description: codeModeRunToolDescription(snapshot.codeModeCaplets),
1602
+ paramsSchema: codeModeRunParamsSchema,
1603
+ callback: async (request) => this.handleCodeModeRunTool(request),
1604
+ enabled: true
1605
+ });
1606
+ else this.codeModeTool = this.registerCodeModeTool(snapshot);
1607
+ else if (this.codeModeTool) {
1608
+ this.codeModeTool.remove();
1609
+ this.codeModeTool = void 0;
1610
+ }
1611
+ const desiredTools = /* @__PURE__ */ new Map();
1612
+ for (const entry of snapshot.progressiveCaplets) desiredTools.set(entry.caplet.server, {
1613
+ register: () => this.registerCapletTool(entry.caplet),
1614
+ update: (tool) => tool.update({
1615
+ title: entry.caplet.name,
1616
+ description: capabilityDescription(entry.caplet),
1617
+ paramsSchema: generatedToolInputSchemaForCaplet(entry.caplet).shape,
1618
+ callback: async (request) => this.engine.execute(entry.caplet.server, request),
1619
+ enabled: true
1620
+ })
1621
+ });
1622
+ for (const entry of snapshot.directTools) desiredTools.set(entry.name, {
1623
+ register: () => this.registerDirectTool(entry),
1624
+ update: (tool) => tool.update({
1625
+ title: entry.tool.name,
1626
+ description: entry.tool.description,
1627
+ paramsSchema: entry.tool.inputSchema,
1628
+ outputSchema: entry.tool.outputSchema,
1629
+ annotations: entry.tool.annotations,
1630
+ _meta: { caplets: {
1631
+ capletId: entry.caplet.server,
1632
+ downstreamName: entry.downstreamName,
1633
+ exposure: "direct"
1634
+ } },
1635
+ callback: async (request) => this.engine.executeDirectTool(entry.caplet.server, entry.downstreamName, isRecord$3(request) ? request : {}),
1636
+ enabled: true
1637
+ })
1638
+ });
1639
+ for (const [name, tool] of this.tools) {
1640
+ const plan = desiredTools.get(name);
1641
+ if (!plan) {
1366
1642
  tool.remove();
1367
- this.tools.delete(serverId);
1368
- continue;
1643
+ this.tools.delete(name);
1644
+ } else plan.update(tool);
1645
+ }
1646
+ for (const [name, plan] of desiredTools) if (!this.tools.has(name)) this.tools.set(name, plan.register());
1647
+ for (const resource of this.resources.values()) resource.remove();
1648
+ for (const prompt of this.prompts.values()) prompt.remove();
1649
+ this.resources.clear();
1650
+ this.prompts.clear();
1651
+ for (const entry of snapshot.directResources) this.resources.set(entry.uri, this.registerDirectResource(entry));
1652
+ for (const entry of snapshot.directResourceTemplates) this.resources.set(entry.uriTemplate, this.registerDirectResourceTemplate(entry));
1653
+ for (const entry of snapshot.directPrompts) this.prompts.set(entry.name, this.registerDirectPrompt(entry));
1654
+ }
1655
+ clearRegistrations() {
1656
+ this.codeModeTool?.remove();
1657
+ this.codeModeTool = void 0;
1658
+ for (const tool of this.tools.values()) tool.remove();
1659
+ for (const resource of this.resources.values()) resource.remove();
1660
+ for (const prompt of this.prompts.values()) prompt.remove();
1661
+ this.tools.clear();
1662
+ this.resources.clear();
1663
+ this.prompts.clear();
1664
+ }
1665
+ registerCodeModeTool(snapshot) {
1666
+ return this.server.registerTool("code_mode", {
1667
+ title: "Code Mode",
1668
+ description: codeModeRunToolDescription(snapshot.codeModeCaplets),
1669
+ inputSchema: codeModeRunParamsSchema
1670
+ }, async (request) => this.handleCodeModeRunTool(request));
1671
+ }
1672
+ async handleCodeModeRunTool(request) {
1673
+ const parsed = codeModeRunInputSchema.safeParse(request);
1674
+ const envelope = parsed.success ? await runCodeMode({
1675
+ code: parsed.data.code,
1676
+ service: new EngineNativeCapletsService(this.engine),
1677
+ ...parsed.data.timeoutMs === void 0 ? {} : { timeoutMs: parsed.data.timeoutMs },
1678
+ logStore: new CodeModeLogStore()
1679
+ }) : {
1680
+ ok: false,
1681
+ error: {
1682
+ code: "REQUEST_INVALID",
1683
+ message: "Code Mode run input is invalid.",
1684
+ details: parsed.error.issues
1685
+ },
1686
+ diagnostics: [],
1687
+ logs: {
1688
+ entries: [],
1689
+ truncated: false,
1690
+ stored: false
1691
+ },
1692
+ meta: {
1693
+ runId: "",
1694
+ traceId: "",
1695
+ declarationHash: "",
1696
+ durationMs: 0,
1697
+ timeoutMs: 0,
1698
+ maxTimeoutMs: 0
1369
1699
  }
1370
- const previousCaplet = previous ? capletById(previous, serverId) : void 0;
1371
- if (!previousCaplet || serializeCaplet(previousCaplet) !== serializeCaplet(caplet)) tool.update({
1372
- title: caplet.name,
1373
- description: capabilityDescription(caplet),
1374
- paramsSchema: generatedToolInputSchemaForCaplet(caplet).shape,
1375
- callback: async (request) => this.handleTool(serverId, request),
1376
- enabled: true
1377
- });
1378
- }
1379
- for (const caplet of enabled.values()) {
1380
- if (this.tools.has(caplet.server)) continue;
1381
- this.tools.set(caplet.server, this.registerCapletTool(caplet));
1382
- }
1700
+ };
1701
+ return {
1702
+ content: [{
1703
+ type: "text",
1704
+ text: JSON.stringify(envelope, null, 2)
1705
+ }],
1706
+ structuredContent: envelope,
1707
+ isError: !envelope.ok
1708
+ };
1383
1709
  }
1384
1710
  registerCapletTool(caplet) {
1385
1711
  return this.server.registerTool(caplet.server, {
1386
1712
  title: caplet.name,
1387
1713
  description: capabilityDescription(caplet),
1388
1714
  inputSchema: generatedToolInputSchemaForCaplet(caplet).shape
1389
- }, async (request) => this.handleTool(caplet.server, request));
1715
+ }, async (request) => this.engine.execute(caplet.server, request));
1716
+ }
1717
+ registerDirectTool(entry) {
1718
+ return this.server.registerTool(entry.name, {
1719
+ title: entry.tool.name,
1720
+ ...entry.tool.description ? { description: entry.tool.description } : {},
1721
+ ...entry.tool.inputSchema ? { inputSchema: entry.tool.inputSchema } : {},
1722
+ ...entry.tool.outputSchema ? { outputSchema: entry.tool.outputSchema } : {},
1723
+ ...entry.tool.annotations ? { annotations: entry.tool.annotations } : {},
1724
+ _meta: { caplets: {
1725
+ capletId: entry.caplet.server,
1726
+ downstreamName: entry.downstreamName,
1727
+ exposure: "direct"
1728
+ } }
1729
+ }, async (request) => this.engine.executeDirectTool(entry.caplet.server, entry.downstreamName, isRecord$3(request) ? request : {}));
1730
+ }
1731
+ registerDirectResource(entry) {
1732
+ if (!this.server.registerResource) throw new Error("MCP server does not support resource registration");
1733
+ return this.server.registerResource(entry.resource.name ?? entry.uri, entry.uri, resourceMetadata(entry.resource), async () => this.directResourceResult(entry.caplet.server, entry.downstreamUri));
1734
+ }
1735
+ registerDirectResourceTemplate(entry) {
1736
+ if (!this.server.registerResource) throw new Error("MCP server does not support resource registration");
1737
+ return this.server.registerResource(`${entry.caplet.server}:${entry.resourceTemplate.name ?? entry.downstreamUriTemplate}`, new ResourceTemplate(entry.uriTemplate, { list: void 0 }), resourceTemplateMetadata(entry.resourceTemplate), async (uri) => {
1738
+ const decoded = decodeDirectResourceUri(uri.toString());
1739
+ return this.directResourceResult(decoded.capletId, decoded.downstreamUri);
1740
+ });
1741
+ }
1742
+ registerDirectPrompt(entry) {
1743
+ if (!this.server.registerPrompt) throw new Error("MCP server does not support prompt registration");
1744
+ return this.server.registerPrompt(entry.name, {
1745
+ title: entry.prompt.name,
1746
+ ...entry.prompt.description ? { description: entry.prompt.description } : {},
1747
+ argsSchema: promptArgsSchema(entry.prompt.arguments)
1748
+ }, async (args) => await this.engine.getDirectPrompt(entry.caplet.server, entry.downstreamName, isRecord$3(args) ? stringifyRecord(args) : {}));
1749
+ }
1750
+ async directResourceResult(serverId, downstreamUri) {
1751
+ const result = await this.engine.readDirectResource(serverId, downstreamUri);
1752
+ if (isRecord$3(result) && "contents" in result) return result;
1753
+ return { contents: [{
1754
+ uri: downstreamUri,
1755
+ mimeType: "application/json",
1756
+ text: JSON.stringify(result, null, 2)
1757
+ }] };
1390
1758
  }
1391
- async handleTool(serverId, request) {
1392
- return await this.engine.execute(serverId, request);
1759
+ };
1760
+ function codeModeRunToolDescription(caplets) {
1761
+ return generateCodeModeRunToolDescription(generateCodeModeDeclarations({ caplets: caplets.map((entry) => ({
1762
+ id: entry.caplet.server,
1763
+ name: entry.caplet.name,
1764
+ description: capabilityDescription(entry.caplet),
1765
+ ...entry.caplet.useWhen ? { useWhen: entry.caplet.useWhen } : {},
1766
+ ...entry.caplet.avoidWhen ? { avoidWhen: entry.caplet.avoidWhen } : {}
1767
+ })) }));
1768
+ }
1769
+ var EngineNativeCapletsService = class {
1770
+ engine;
1771
+ constructor(engine) {
1772
+ this.engine = engine;
1393
1773
  }
1774
+ listTools() {
1775
+ return (this.engine.currentExposureSnapshot()?.codeModeCaplets.map((entry) => entry.caplet) ?? this.engine.enabledServers()).map((caplet) => {
1776
+ const toolName = nativeCapletToolName(caplet.server);
1777
+ return {
1778
+ caplet: caplet.server,
1779
+ toolName,
1780
+ title: caplet.name,
1781
+ description: nativeCapletToolDescription(toolName, caplet),
1782
+ promptGuidance: nativeCapletPromptGuidance(toolName, caplet)
1783
+ };
1784
+ });
1785
+ }
1786
+ async execute(capletId, request) {
1787
+ return await this.engine.execute(capletId, request);
1788
+ }
1789
+ async reload() {
1790
+ return await this.engine.reload();
1791
+ }
1792
+ onToolsChanged(listener) {
1793
+ return this.engine.onReload(() => listener(this.listTools()));
1794
+ }
1795
+ async close() {}
1394
1796
  };
1395
- function nextEnabledServers(config) {
1396
- return [
1397
- ...Object.values(config.mcpServers),
1398
- ...Object.values(config.openapiEndpoints),
1399
- ...Object.values(config.graphqlEndpoints),
1400
- ...Object.values(config.httpApis),
1401
- ...Object.values(config.cliTools),
1402
- ...Object.values(config.capletSets)
1403
- ].filter((server) => !server.disabled);
1797
+ function resourceMetadata(resource) {
1798
+ return {
1799
+ ...resource.description ? { description: resource.description } : {},
1800
+ ...resource.mimeType ? { mimeType: resource.mimeType } : {},
1801
+ ...typeof resource.size === "number" ? { size: resource.size } : {},
1802
+ _meta: { caplets: {
1803
+ downstreamUri: resource.uri,
1804
+ exposure: "direct"
1805
+ } }
1806
+ };
1404
1807
  }
1405
- function capletById(config, serverId) {
1406
- return config.mcpServers[serverId] ?? config.openapiEndpoints[serverId] ?? config.graphqlEndpoints[serverId] ?? config.httpApis[serverId] ?? config.cliTools[serverId] ?? config.capletSets[serverId];
1808
+ function resourceTemplateMetadata(resourceTemplate) {
1809
+ return {
1810
+ ...resourceTemplate.description ? { description: resourceTemplate.description } : {},
1811
+ ...resourceTemplate.mimeType ? { mimeType: resourceTemplate.mimeType } : {},
1812
+ _meta: { caplets: {
1813
+ downstreamUriTemplate: resourceTemplate.uriTemplate,
1814
+ exposure: "direct"
1815
+ } }
1816
+ };
1407
1817
  }
1408
- function serializeCaplet(caplet) {
1409
- return JSON.stringify(caplet ?? null);
1818
+ function promptArgsSchema(args) {
1819
+ const shape = {};
1820
+ for (const arg of args ?? []) shape[arg.name] = string().optional();
1821
+ return shape;
1822
+ }
1823
+ function stringifyRecord(value) {
1824
+ return Object.fromEntries(Object.entries(value).map(([key, nested]) => [key, nested === void 0 ? "" : String(nested)]));
1825
+ }
1826
+ function isRecord$3(value) {
1827
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1828
+ }
1829
+ function staticExposureSnapshot(config, caplets) {
1830
+ const callableCaplets = caplets.filter((caplet) => !caplet.disabled && !caplet.setup && !caplet.projectBinding?.required).map((caplet) => ({
1831
+ caplet,
1832
+ exposure: resolveExposure(caplet.exposure, config.options.exposure),
1833
+ tools: [],
1834
+ resources: [],
1835
+ resourceTemplates: [],
1836
+ prompts: [],
1837
+ discoveredAt: Date.now()
1838
+ }));
1839
+ return {
1840
+ callableCaplets,
1841
+ progressiveCaplets: callableCaplets.filter((entry) => entry.exposure.progressive),
1842
+ codeModeCaplets: callableCaplets.filter((entry) => entry.exposure.codeMode),
1843
+ directTools: [],
1844
+ directResources: [],
1845
+ directResourceTemplates: [],
1846
+ directPrompts: [],
1847
+ hiddenCaplets: caplets.filter((caplet) => caplet.disabled || caplet.setup || caplet.projectBinding?.required).map((caplet) => ({
1848
+ capletId: caplet.server,
1849
+ reason: caplet.disabled ? "disabled" : caplet.setup ? "setup_required" : "project_binding_required"
1850
+ }))
1851
+ };
1410
1852
  }
1411
1853
  //#endregion
1412
1854
  //#region src/runtime.ts
@@ -4863,6 +5305,42 @@ function isUrlLike(value) {
4863
5305
  return /^https?:\/\//i.test(value);
4864
5306
  }
4865
5307
  //#endregion
5308
+ //#region src/cli/cloud-add.ts
5309
+ const MAX_CLOUD_CAPLET_BUNDLE_BYTES = 2 * 1024 * 1024;
5310
+ const SKIPPED_DIRECTORY_NAMES = new Set([
5311
+ ".git",
5312
+ "node_modules",
5313
+ "auth"
5314
+ ]);
5315
+ function buildCloudCapletBundle(rootInput) {
5316
+ const root = resolve(rootInput);
5317
+ if (!existsSync(root)) throw new CapletsError("CONFIG_INVALID", `Caplet path does not exist: ${rootInput}`);
5318
+ if (!statSync(root).isDirectory()) throw new CapletsError("CONFIG_INVALID", `Caplet path must be a directory: ${rootInput}`);
5319
+ const files = collectFiles(root).map((filePath) => ({
5320
+ path: relative(root, filePath).split(sep).join("/"),
5321
+ content: readFileSync(filePath, "utf8")
5322
+ })).filter((file) => file.path !== "config.json").sort((left, right) => left.path.localeCompare(right.path));
5323
+ const totalBytes = files.reduce((total, file) => total + Buffer.byteLength(file.content), 0);
5324
+ if (totalBytes > MAX_CLOUD_CAPLET_BUNDLE_BYTES) throw new CapletsError("CONFIG_INVALID", `Caplet bundle is too large for Cloud upload (${totalBytes} bytes).`);
5325
+ if (!files.some((file) => file.path.endsWith(".md") || file.path.endsWith("/CAPLET.md"))) throw new CapletsError("CONFIG_INVALID", `No Caplet files found under ${rootInput}`);
5326
+ return { files };
5327
+ }
5328
+ function collectFiles(root) {
5329
+ const entries = readdirSync(root, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name));
5330
+ const files = [];
5331
+ for (const entry of entries) {
5332
+ if (entry.isSymbolicLink()) continue;
5333
+ const path = resolve(root, entry.name);
5334
+ if (entry.isDirectory()) {
5335
+ if (SKIPPED_DIRECTORY_NAMES.has(entry.name)) continue;
5336
+ files.push(...collectFiles(path));
5337
+ continue;
5338
+ }
5339
+ if (entry.isFile()) files.push(path);
5340
+ }
5341
+ return files;
5342
+ }
5343
+ //#endregion
4866
5344
  //#region src/cli/auth.ts
4867
5345
  async function loginAuth(serverId, options) {
4868
5346
  const server = findAuthTarget(serverId, options.config ?? loadConfig(options.configPath));
@@ -4996,6 +5474,86 @@ async function maybeReadManualInput() {
4996
5474
  }
4997
5475
  }
4998
5476
  //#endregion
5477
+ //#region src/cli/code-mode.ts
5478
+ async function runCodeModeCli(options) {
5479
+ const service = createNativeCapletsService({
5480
+ mode: "local",
5481
+ ...options.configPath ? { configPath: options.configPath } : {},
5482
+ ...options.projectConfigPath ? { projectConfigPath: options.projectConfigPath } : {},
5483
+ ...options.authDir ? { authDir: options.authDir } : {}
5484
+ });
5485
+ try {
5486
+ const code = await readCodeModeCliCode(options);
5487
+ const result = await service.execute(nativeCodeModeToolId, {
5488
+ code,
5489
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
5490
+ });
5491
+ if (options.json) options.writeOut(`${JSON.stringify(result, null, 2)}\n`);
5492
+ else if (result.ok) options.writeOut(`${formatHumanValue(result.value)}\n`);
5493
+ else {
5494
+ options.writeOut(`${result.error.code}: ${result.error.message}\n`);
5495
+ if (result.diagnostics.length > 0) options.writeOut(`${result.diagnostics.map((diagnostic) => `- ${diagnostic.message}`).join("\n")}\n`);
5496
+ }
5497
+ if (!result.ok) options.setExitCode(1);
5498
+ } finally {
5499
+ await service.close();
5500
+ }
5501
+ }
5502
+ async function codeModeTypesCli(options) {
5503
+ const engine = new CapletsEngine({
5504
+ ...options.configPath ? { configPath: options.configPath } : {},
5505
+ ...options.projectConfigPath ? { projectConfigPath: options.projectConfigPath } : {},
5506
+ ...options.authDir ? { authDir: options.authDir } : {}
5507
+ });
5508
+ try {
5509
+ const caplets = listCodeModeCallableCaplets$1(engine);
5510
+ const declaration = generateCodeModeDeclarations({ caplets });
5511
+ if (!options.json) {
5512
+ options.writeOut(declaration);
5513
+ return;
5514
+ }
5515
+ const output = {
5516
+ declaration,
5517
+ declarationHash: codeModeDeclarationHash(declaration),
5518
+ callableCount: caplets.length,
5519
+ generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5520
+ runtimeScope: runtimeScope(options.env)
5521
+ };
5522
+ options.writeOut(`${JSON.stringify(output, null, 2)}\n`);
5523
+ } finally {
5524
+ await engine.close();
5525
+ }
5526
+ }
5527
+ async function readCodeModeCliCode(options) {
5528
+ if (options.inlineCode !== void 0) return options.inlineCode;
5529
+ if (options.file !== void 0) return readFileSync(resolve(process.cwd(), options.file), "utf8");
5530
+ return await (options.readStdin ?? readProcessStdin)();
5531
+ }
5532
+ async function readProcessStdin() {
5533
+ const chunks = [];
5534
+ for await (const chunk of process.stdin) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
5535
+ return Buffer.concat(chunks).toString("utf8");
5536
+ }
5537
+ function formatHumanValue(value) {
5538
+ return typeof value === "string" ? value : JSON.stringify(value, null, 2);
5539
+ }
5540
+ function runtimeScope(env = process.env) {
5541
+ return env.CAPLETS_MODE?.trim() || "local";
5542
+ }
5543
+ function listCodeModeCallableCaplets$1(engine) {
5544
+ const defaultExposure = engine.currentConfig().options.exposure;
5545
+ return engine.enabledServers().filter((caplet) => {
5546
+ if (caplet.setup || caplet.projectBinding?.required) return false;
5547
+ return resolveExposure(caplet.exposure, defaultExposure).codeMode;
5548
+ }).map((caplet) => ({
5549
+ id: caplet.server,
5550
+ name: caplet.name,
5551
+ description: caplet.description,
5552
+ ...caplet.useWhen ? { useWhen: caplet.useWhen } : {},
5553
+ ...caplet.avoidWhen ? { avoidWhen: caplet.avoidWhen } : {}
5554
+ })).sort((left, right) => left.id.localeCompare(right.id));
5555
+ }
5556
+ //#endregion
4999
5557
  //#region src/cli/init.ts
5000
5558
  function initConfig(options = {}) {
5001
5559
  const path = resolveConfigPath(options.path);
@@ -5257,7 +5815,9 @@ async function doctorJsonReport(options = {}) {
5257
5815
  configured: false,
5258
5816
  running: false
5259
5817
  },
5260
- cloudAuth: redactedCloudAuthStatus(credentials)
5818
+ cloudAuth: redactedCloudAuthStatus(credentials),
5819
+ exposure: await resolveExposureSection(env),
5820
+ codeMode: await resolveCodeModeSection(options, env)
5261
5821
  };
5262
5822
  }
5263
5823
  async function formatDoctorReport(options = {}) {
@@ -5298,9 +5858,68 @@ async function formatDoctorReport(options = {}) {
5298
5858
  "Cloud Auth",
5299
5859
  ` Authenticated: ${yesNo(Boolean(report.cloudAuth.authenticated))}`,
5300
5860
  ...report.cloudAuth.cloudUrl ? [` Cloud URL: ${report.cloudAuth.cloudUrl}`] : [],
5301
- ...report.cloudAuth.workspaceSlug || report.cloudAuth.workspaceId ? [` Selected Workspace: ${report.cloudAuth.workspaceSlug ?? report.cloudAuth.workspaceId}`] : []
5861
+ ...report.cloudAuth.workspaceSlug || report.cloudAuth.workspaceId ? [` Selected Workspace: ${report.cloudAuth.workspaceSlug ?? report.cloudAuth.workspaceId}`] : [],
5862
+ "",
5863
+ "Exposure",
5864
+ ` Default: ${report.exposure.default ?? "unknown"}`,
5865
+ ` Discovery timeout: ${report.exposure.discoveryTimeoutMs ?? "unknown"}ms`,
5866
+ ` Discovery concurrency: ${report.exposure.discoveryConcurrency ?? "unknown"}`,
5867
+ ` Callable native tools: ${report.exposure.callableNativeToolCount ?? 0}`,
5868
+ ...Array.isArray(report.exposure.caplets) ? report.exposure.caplets.map((caplet) => ` ${caplet.id}: ${caplet.exposure} (${caplet.callable ? "callable" : `hidden: ${caplet.hiddenReason}`})`) : [],
5869
+ "",
5870
+ "Code Mode",
5871
+ ` Types generation: ${doctorOk(report.codeMode.typesGeneration)}`,
5872
+ ` Diagnostics: ${doctorOk(report.codeMode.diagnostics)}`,
5873
+ ` Sandbox smoke: ${doctorOk(report.codeMode.sandboxSmoke)}`,
5874
+ ` Log storage: ${doctorOk(report.codeMode.logStorage)}`,
5875
+ ` Callable index: ${doctorOk(report.codeMode.callableIndex)}`,
5876
+ ` Observed output shapes: ${doctorOk(report.codeMode.observedOutputShapes)}`,
5877
+ ...observedOutputShapePath(report.codeMode.observedOutputShapes) ? [` Observed output shape cache: ${observedOutputShapePath(report.codeMode.observedOutputShapes)}`] : []
5302
5878
  ].join("\n")}\n`;
5303
5879
  }
5880
+ async function resolveExposureSection(env) {
5881
+ const configPath = env.CAPLETS_CONFIG?.trim() ? env.CAPLETS_CONFIG.trim() : resolveConfigPath();
5882
+ const projectConfigPath = env.CAPLETS_PROJECT_CONFIG?.trim() ? env.CAPLETS_PROJECT_CONFIG.trim() : resolveProjectConfigPath();
5883
+ try {
5884
+ const config = loadConfig(configPath, projectConfigPath);
5885
+ const service = createNativeCapletsService({
5886
+ mode: "local",
5887
+ configPath,
5888
+ projectConfigPath,
5889
+ watch: false,
5890
+ writeErr: () => void 0
5891
+ });
5892
+ try {
5893
+ const nativeTools = service.listTools();
5894
+ const callableIds = new Set(nativeTools.map((tool) => tool.caplet));
5895
+ return {
5896
+ ok: true,
5897
+ default: config.options.exposure,
5898
+ discoveryTimeoutMs: config.options.exposureDiscoveryTimeoutMs,
5899
+ discoveryConcurrency: config.options.exposureDiscoveryConcurrency,
5900
+ callableNativeToolCount: nativeTools.length,
5901
+ caplets: allCaplets(config).map((caplet) => {
5902
+ const exposure = resolveExposure(caplet.exposure, config.options.exposure);
5903
+ const callable = callableIds.has(caplet.server) || [...callableIds].some((id) => id.startsWith(`${caplet.server}__`));
5904
+ return {
5905
+ id: caplet.server,
5906
+ exposure: exposure.value,
5907
+ callable,
5908
+ ...callable ? {} : { hiddenReason: hiddenReasonFor(caplet) }
5909
+ };
5910
+ })
5911
+ };
5912
+ } finally {
5913
+ await service.close();
5914
+ }
5915
+ } catch (error) {
5916
+ return {
5917
+ ok: true,
5918
+ configLoaded: false,
5919
+ message: error instanceof Error ? error.message : String(error)
5920
+ };
5921
+ }
5922
+ }
5304
5923
  function resolveServerSection(env) {
5305
5924
  try {
5306
5925
  const server = resolveCapletsServer({}, env);
@@ -5337,6 +5956,134 @@ function resolveRemoteSection(env) {
5337
5956
  function yesNo(value) {
5338
5957
  return value ? "yes" : "no";
5339
5958
  }
5959
+ async function resolveCodeModeSection(options, env) {
5960
+ const emptyDeclaration = generateCodeModeDeclarations({ caplets: [] });
5961
+ const diagnostics = diagnoseCodeModeTypeScript({
5962
+ declaration: emptyDeclaration,
5963
+ code: "return 1;"
5964
+ });
5965
+ const tempDir = mkdtempSync(join(tmpdir(), "caplets-code-mode-doctor-"));
5966
+ try {
5967
+ const logStore = new CodeModeLogStore({ stateDir: tempDir });
5968
+ const stored = await logStore.store([{
5969
+ level: "log",
5970
+ message: "doctor smoke",
5971
+ timestamp: (/* @__PURE__ */ new Date(0)).toISOString()
5972
+ }]);
5973
+ const read = await logStore.read({ logRef: stored.logRef });
5974
+ const sandboxSmoke = await runCodeMode({
5975
+ code: "return 1;",
5976
+ service: emptyCodeModeDoctorService(),
5977
+ logStore
5978
+ });
5979
+ return {
5980
+ typesGeneration: { ok: emptyDeclaration.includes("declare const caplets") },
5981
+ diagnostics: { ok: diagnostics.every((diagnostic) => diagnostic.severity !== "error") },
5982
+ sandboxSmoke: { ok: sandboxSmoke.ok },
5983
+ logStorage: { ok: read.entries.length === 1 },
5984
+ callableIndex: await resolveCallableIndexDoctor(env),
5985
+ observedOutputShapes: await resolveObservedOutputShapesDoctor(options)
5986
+ };
5987
+ } catch (error) {
5988
+ return {
5989
+ typesGeneration: { ok: true },
5990
+ diagnostics: { ok: diagnostics.every((diagnostic) => diagnostic.severity !== "error") },
5991
+ sandboxSmoke: {
5992
+ ok: false,
5993
+ error: error instanceof Error ? error.message : String(error)
5994
+ },
5995
+ logStorage: {
5996
+ ok: false,
5997
+ error: error instanceof Error ? error.message : String(error)
5998
+ },
5999
+ callableIndex: {
6000
+ ok: false,
6001
+ error: error instanceof Error ? error.message : String(error)
6002
+ },
6003
+ observedOutputShapes: await resolveObservedOutputShapesDoctor(options)
6004
+ };
6005
+ } finally {
6006
+ rmSync(tempDir, {
6007
+ recursive: true,
6008
+ force: true
6009
+ });
6010
+ }
6011
+ }
6012
+ async function resolveObservedOutputShapesDoctor(options) {
6013
+ const store = new FileObservedOutputShapeStore(options.observedOutputShapeCacheDir ?? DEFAULT_OBSERVED_OUTPUT_SHAPE_CACHE_DIR);
6014
+ if (!store.health) return {
6015
+ ok: false,
6016
+ error: "store health unavailable"
6017
+ };
6018
+ const health = await store.health();
6019
+ return {
6020
+ ok: health.readable && health.writable,
6021
+ path: health.path,
6022
+ readable: health.readable,
6023
+ writable: health.writable,
6024
+ entryCount: health.entryCount ?? null,
6025
+ prune: health.prune ?? null,
6026
+ ...health.error ? { error: health.error } : {}
6027
+ };
6028
+ }
6029
+ async function resolveCallableIndexDoctor(env) {
6030
+ try {
6031
+ const service = createNativeCapletsService({
6032
+ mode: "local",
6033
+ ...env.CAPLETS_CONFIG?.trim() ? { configPath: env.CAPLETS_CONFIG.trim() } : {},
6034
+ ...env.CAPLETS_PROJECT_CONFIG?.trim() ? { projectConfigPath: env.CAPLETS_PROJECT_CONFIG.trim() } : {},
6035
+ watch: false,
6036
+ writeErr: () => void 0
6037
+ });
6038
+ try {
6039
+ return {
6040
+ ok: true,
6041
+ callableCount: listCodeModeCallableCaplets(service).length
6042
+ };
6043
+ } finally {
6044
+ await service.close();
6045
+ }
6046
+ } catch (error) {
6047
+ return {
6048
+ ok: true,
6049
+ callableCount: 0,
6050
+ configLoaded: false,
6051
+ message: error instanceof Error ? error.message : String(error)
6052
+ };
6053
+ }
6054
+ }
6055
+ function emptyCodeModeDoctorService() {
6056
+ return {
6057
+ listTools: () => [],
6058
+ execute: async () => void 0,
6059
+ reload: async () => true,
6060
+ onToolsChanged: () => () => void 0,
6061
+ close: async () => void 0
6062
+ };
6063
+ }
6064
+ function doctorOk(value) {
6065
+ return value && typeof value === "object" && value.ok === true ? "ok" : "failed";
6066
+ }
6067
+ function observedOutputShapePath(value) {
6068
+ return value && typeof value === "object" && typeof value.path === "string" ? value.path : void 0;
6069
+ }
6070
+ function allCaplets(config) {
6071
+ const typed = config;
6072
+ return [
6073
+ ...Object.values(typed.mcpServers ?? {}),
6074
+ ...Object.values(typed.openapiEndpoints ?? {}),
6075
+ ...Object.values(typed.graphqlEndpoints ?? {}),
6076
+ ...Object.values(typed.httpApis ?? {}),
6077
+ ...Object.values(typed.cliTools ?? {}),
6078
+ ...Object.values(typed.capletSets ?? {})
6079
+ ];
6080
+ }
6081
+ function hiddenReasonFor(caplet) {
6082
+ if (caplet.disabled) return "disabled";
6083
+ if (caplet.setup) return "setup_required";
6084
+ if (caplet.projectBinding?.required) return "project_binding_required";
6085
+ return "not_exposed";
6086
+ }
5340
6087
  //#endregion
5341
6088
  //#region src/cloud-auth/open-url.ts
5342
6089
  async function openBrowserUrl(url, options = {}) {
@@ -6002,27 +6749,55 @@ const localMcpConfig = `{
6002
6749
  `;
6003
6750
  function formatSetupMenu() {
6004
6751
  return [
6005
- "Usage: caplets setup <integration>",
6752
+ "Usage: caplets setup [integration]",
6006
6753
  "",
6007
6754
  "Supported integrations:",
6008
- " codex Run Codex plugin marketplace and plugin install commands",
6009
- " claude-code Run Claude Code plugin marketplace and plugin install commands",
6755
+ " codex Add Caplets to Codex MCP config",
6756
+ " claude-code Add Caplets to Claude Code MCP config",
6010
6757
  " opencode Run OpenCode native plugin install",
6011
6758
  " pi Run Pi extension install",
6012
6759
  " mcp-client Write a generic MCP client config with --output",
6013
6760
  "",
6014
6761
  "Examples:",
6762
+ " caplets setup",
6015
6763
  " caplets setup codex",
6016
6764
  " caplets setup opencode --dry-run",
6017
6765
  " caplets setup mcp-client --output ./caplets.mcp.json",
6018
6766
  ""
6019
6767
  ].join("\n");
6020
6768
  }
6769
+ function formatSetupPrompt() {
6770
+ return [
6771
+ "Select integrations to set up:",
6772
+ " 1. Codex",
6773
+ " 2. Claude Code",
6774
+ " 3. OpenCode",
6775
+ " 4. Pi",
6776
+ " 5. Any MCP client",
6777
+ "",
6778
+ "Enter numbers, ids, or all, separated by commas (default: codex): "
6779
+ ].join("\n");
6780
+ }
6781
+ async function runInteractiveSetup(options) {
6782
+ if (options.format === "json") throw new CapletsError("REQUEST_INVALID", "interactive caplets setup only supports plain output; pass an integration with --format json");
6783
+ const selected = parseInteractiveSetupSelection(await options.readPrompt(formatSetupPrompt()));
6784
+ const chunks = [];
6785
+ for (const integration of selected) {
6786
+ const setupOptions = { ...options };
6787
+ if (integration === "mcp-client" && !setupOptions.output) {
6788
+ const output = nonEmpty$1(await options.readPrompt("Path to write generic MCP config (--output): "));
6789
+ if (!output) throw new CapletsError("REQUEST_INVALID", "mcp-client setup requires an output path");
6790
+ setupOptions.output = output;
6791
+ }
6792
+ chunks.push(await runSetup(integration, setupOptions));
6793
+ }
6794
+ return chunks.join("\n");
6795
+ }
6021
6796
  async function runSetup(integration, options = {}) {
6022
6797
  if (!setupIntegrationIds.includes(integration)) return await runCapletSetupCli(integration, {
6023
6798
  ...options.yes === void 0 ? {} : { yes: options.yes },
6024
6799
  target: resolveSetupTargetKind(options),
6025
- ...options.remote === void 0 ? {} : { remote: options.remote }
6800
+ ...options.remote === void 0 && !isRemoteSetup(options) ? {} : { remote: isRemoteSetup(options) }
6026
6801
  });
6027
6802
  const result = await executeSetup(integration, options);
6028
6803
  if (options.format === "json") return `${JSON.stringify(result, null, 2)}\n`;
@@ -6066,7 +6841,7 @@ async function executeSetup(integration, options) {
6066
6841
  return {
6067
6842
  integration: id,
6068
6843
  name: definition.name,
6069
- mode: options.remote ? "remote" : "local",
6844
+ mode: isRemoteSetup(options) ? "remote" : "local",
6070
6845
  targetKind: resolveSetupTargetKind(options),
6071
6846
  dryRun: Boolean(options.dryRun),
6072
6847
  actions,
@@ -6074,55 +6849,31 @@ async function executeSetup(integration, options) {
6074
6849
  };
6075
6850
  }
6076
6851
  function setupDefinition(id, options) {
6077
- if (options.remote) return remoteSetupDefinition(id, options);
6852
+ if (isRemoteSetup(options)) return remoteSetupDefinition(id, options);
6078
6853
  switch (id) {
6079
6854
  case "codex": return {
6080
6855
  name: "Codex",
6081
6856
  actions: [{
6082
6857
  type: "command",
6083
- label: "Add Caplets marketplace to Codex",
6858
+ label: "Add Caplets MCP server to Codex",
6084
6859
  command: "codex",
6085
- args: [
6086
- "plugin",
6087
- "marketplace",
6088
- "add",
6089
- "spiritledsoftware/caplets"
6090
- ]
6091
- }, {
6092
- type: "command",
6093
- label: "Install Caplets Codex plugin",
6094
- command: "codex",
6095
- args: [
6096
- "plugin",
6097
- "add",
6098
- "caplets@caplets"
6099
- ]
6860
+ args: codexMcpAddArgs(["serve"])
6100
6861
  }],
6101
- nextSteps: ["Try a premade Caplet: caplets install spiritledsoftware/caplets github", "Ask Codex: codex \"try using the github caplet\""]
6862
+ nextSteps: [
6863
+ "In Codex, run /mcp to confirm the caplets server is connected.",
6864
+ "Try a premade Caplet: caplets install spiritledsoftware/caplets github",
6865
+ "Ask Codex: codex \"try using the github caplet\""
6866
+ ]
6102
6867
  };
6103
6868
  case "claude-code": return {
6104
6869
  name: "Claude Code",
6105
6870
  actions: [{
6106
6871
  type: "command",
6107
- label: "Add Caplets marketplace to Claude Code",
6108
- command: "claude",
6109
- args: [
6110
- "plugin",
6111
- "marketplace",
6112
- "add",
6113
- "spiritledsoftware/caplets"
6114
- ]
6115
- }, {
6116
- type: "command",
6117
- label: "Install Caplets Claude Code plugin",
6872
+ label: "Add Caplets MCP server to Claude Code",
6118
6873
  command: "claude",
6119
- args: [
6120
- "plugin",
6121
- "install",
6122
- "caplets@caplets"
6123
- ]
6874
+ args: claudeMcpAddArgs(["serve"])
6124
6875
  }],
6125
- nextSteps: ["Restart Claude Code if it was already running.", "Try a premade Caplet: caplets install spiritledsoftware/caplets github"]
6876
+ nextSteps: ["In Claude Code, run /mcp to confirm the caplets server is connected.", "Try a premade Caplet: caplets install spiritledsoftware/caplets github"]
6126
6877
  };
6127
6878
  case "opencode": return {
6128
6879
  name: "OpenCode",
@@ -6163,7 +6914,7 @@ function setupDefinition(id, options) {
6163
6914
  }
6164
6915
  }
6165
6916
  function remoteSetupDefinition(id, options) {
6166
- const serverUrl = nonEmpty$1(options.serverUrl) ?? nonEmpty$1(options.env?.CAPLETS_SERVER_URL) ?? "https://caplets.example.com/caplets";
6917
+ const serverUrl = nonEmpty$1(options.remoteUrl) ?? nonEmpty$1(options.serverUrl) ?? nonEmpty$1(options.env?.CAPLETS_REMOTE_URL) ?? nonEmpty$1(options.env?.CAPLETS_SERVER_URL) ?? "https://caplets.example.com/caplets";
6167
6918
  if (id === "opencode") return {
6168
6919
  name: "OpenCode",
6169
6920
  actions: [{
@@ -6188,9 +6939,37 @@ function remoteSetupDefinition(id, options) {
6188
6939
  }],
6189
6940
  nextSteps: [`Start Pi with CAPLETS_MODE=remote and CAPLETS_SERVER_URL=${serverUrl}.`, "Keep CAPLETS_SERVER_PASSWORD in your shell or secret manager."]
6190
6941
  };
6942
+ if (id === "codex") return {
6943
+ name: "Codex",
6944
+ actions: [{
6945
+ type: "command",
6946
+ label: "Add remote-backed Caplets MCP server to Codex",
6947
+ command: "codex",
6948
+ args: codexMcpAddArgs([
6949
+ "attach",
6950
+ "--remote-url",
6951
+ serverUrl
6952
+ ])
6953
+ }],
6954
+ nextSteps: ["In Codex, run /mcp to confirm the caplets server is connected.", "Keep remote credentials in your shell or secret manager; do not hardcode them in config."]
6955
+ };
6956
+ if (id === "claude-code") return {
6957
+ name: "Claude Code",
6958
+ actions: [{
6959
+ type: "command",
6960
+ label: "Add remote-backed Caplets MCP server to Claude Code",
6961
+ command: "claude",
6962
+ args: claudeMcpAddArgs([
6963
+ "attach",
6964
+ "--remote-url",
6965
+ serverUrl
6966
+ ])
6967
+ }],
6968
+ nextSteps: ["In Claude Code, run /mcp to confirm the caplets server is connected.", "Keep remote credentials in your shell or secret manager; do not hardcode them in config."]
6969
+ };
6191
6970
  if (!options.output) throw new CapletsError("REQUEST_INVALID", "remote MCP-backed setup requires --output <path> so Caplets can write a client config without guessing your agent's secret storage");
6192
6971
  return {
6193
- name: id === "codex" ? "Codex" : id === "claude-code" ? "Claude Code" : "Any MCP client",
6972
+ name: "Any MCP client",
6194
6973
  actions: [{
6195
6974
  type: "writeFile",
6196
6975
  label: "Write remote MCP config",
@@ -6204,6 +6983,23 @@ function parseSetupIntegrationId(value) {
6204
6983
  if (setupIntegrationIds.includes(value)) return value;
6205
6984
  throw new CapletsError("REQUEST_INVALID", `setup integration must be one of: ${setupIntegrationIds.join(", ")}`);
6206
6985
  }
6986
+ function parseInteractiveSetupSelection(value) {
6987
+ const rawSelections = value.split(",").map((part) => part.trim()).filter(Boolean);
6988
+ const ids = (rawSelections.length > 0 ? rawSelections : ["codex"]).flatMap((selection) => normalizedInteractiveSetupToken(selection) === "all" ? setupIntegrationIds : [parseInteractiveSetupToken(selection)]);
6989
+ return [...new Set(ids)];
6990
+ }
6991
+ function parseInteractiveSetupToken(value) {
6992
+ const normalized = normalizedInteractiveSetupToken(value);
6993
+ if (normalized === "1" || normalized === "codex") return "codex";
6994
+ if (normalized === "2" || normalized === "claude" || normalized === "claude-code" || normalized === "claudecode") return "claude-code";
6995
+ if (normalized === "3" || normalized === "opencode" || normalized === "open-code") return "opencode";
6996
+ if (normalized === "4" || normalized === "pi") return "pi";
6997
+ if (normalized === "5" || normalized === "mcp" || normalized === "mcp-client" || normalized === "any-mcp-client" || normalized === "generic" || normalized === "generic-mcp") return "mcp-client";
6998
+ throw new CapletsError("REQUEST_INVALID", `unknown setup integration selection: ${value}`);
6999
+ }
7000
+ function normalizedInteractiveSetupToken(value) {
7001
+ return value.trim().toLowerCase().replace(/[\s_]+/gu, "-");
7002
+ }
6207
7003
  async function defaultSetupCommandRunner(command, args) {
6208
7004
  const { stdout, stderr } = await execFileAsync(command, args, {
6209
7005
  encoding: "utf8",
@@ -6230,10 +7026,37 @@ function formatSetupResult(result) {
6230
7026
  function formatCommand(command, args) {
6231
7027
  return [command, ...args].join(" ");
6232
7028
  }
7029
+ function codexMcpAddArgs(capletsArgs) {
7030
+ return [
7031
+ "mcp",
7032
+ "add",
7033
+ "caplets",
7034
+ "--",
7035
+ "caplets",
7036
+ ...capletsArgs
7037
+ ];
7038
+ }
7039
+ function claudeMcpAddArgs(capletsArgs) {
7040
+ return [
7041
+ "mcp",
7042
+ "add",
7043
+ "--transport",
7044
+ "stdio",
7045
+ "--scope",
7046
+ "user",
7047
+ "caplets",
7048
+ "--",
7049
+ "caplets",
7050
+ ...capletsArgs
7051
+ ];
7052
+ }
6233
7053
  function nonEmpty$1(value) {
6234
7054
  const trimmed = value?.trim();
6235
7055
  return trimmed ? trimmed : void 0;
6236
7056
  }
7057
+ function isRemoteSetup(options) {
7058
+ return Boolean(options.remote ?? nonEmpty$1(options.remoteUrl) ?? nonEmpty$1(options.serverUrl));
7059
+ }
6237
7060
  function resolveSetupTargetKind(options) {
6238
7061
  if (options.target !== void 0) {
6239
7062
  if (isSetupTargetKind(options.target)) return options.target;
@@ -6242,7 +7065,7 @@ function resolveSetupTargetKind(options) {
6242
7065
  if (options.target === "cloud" || options.target === "hosted_worker") return "hosted_sandbox";
6243
7066
  throw new CapletsError("REQUEST_INVALID", "setup target must be one of: local_host, remote_host, hosted_sandbox");
6244
7067
  }
6245
- return options.remote ? "remote_host" : "local_host";
7068
+ return isRemoteSetup(options) ? "remote_host" : "local_host";
6246
7069
  }
6247
7070
  //#endregion
6248
7071
  //#region src/serve/options.ts
@@ -9747,16 +10570,16 @@ var logger = (fn = console.log) => {
9747
10570
  //#region src/remote-control/dispatch.ts
9748
10571
  const ENGINE_COMMANDS = new Set([
9749
10572
  "inspect",
9750
- "check_backend",
9751
- "list_tools",
10573
+ "check",
10574
+ "tools",
9752
10575
  "search_tools",
9753
- "get_tool",
10576
+ "describe_tool",
9754
10577
  "call_tool",
9755
- "list_resources",
10578
+ "resources",
9756
10579
  "search_resources",
9757
- "list_resource_templates",
10580
+ "resource_templates",
9758
10581
  "read_resource",
9759
- "list_prompts",
10582
+ "prompts",
9760
10583
  "search_prompts",
9761
10584
  "get_prompt",
9762
10585
  "complete"
@@ -11013,8 +11836,17 @@ async function serveStdio(options = {}) {
11013
11836
  process.once("SIGINT", sigintHandler);
11014
11837
  process.once("SIGTERM", sigtermHandler);
11015
11838
  }
11839
+ const transport = new StdioServerTransport();
11840
+ const transportClosed = new Promise((resolve) => {
11841
+ const previousOnClose = transport.onclose;
11842
+ transport.onclose = () => {
11843
+ previousOnClose?.();
11844
+ resolve();
11845
+ };
11846
+ });
11016
11847
  try {
11017
- await session.connect(new StdioServerTransport());
11848
+ await session.connect(transport);
11849
+ await transportClosed;
11018
11850
  } finally {
11019
11851
  if (sigintHandler) process.off("SIGINT", sigintHandler);
11020
11852
  if (sigtermHandler) process.off("SIGTERM", sigtermHandler);
@@ -11460,6 +12292,16 @@ function cloudAuthStore(env) {
11460
12292
  function cloudAuthStatus(credentials) {
11461
12293
  return redactedCloudAuthStatus(credentials);
11462
12294
  }
12295
+ function compactCloudCaplet(value) {
12296
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
12297
+ const record = value;
12298
+ return {
12299
+ ...typeof record.id === "string" ? { id: record.id } : {},
12300
+ ...typeof record.name === "string" ? { name: record.name } : {},
12301
+ ...typeof record.description === "string" ? { description: record.description } : {},
12302
+ ...typeof record.readinessState === "string" ? { readinessState: record.readinessState } : {}
12303
+ };
12304
+ }
11463
12305
  function isProjectBindingWebSocketUnavailable(error) {
11464
12306
  return error instanceof CapletsError && error.code === "SERVER_UNAVAILABLE" && error.message.includes("Project Binding WebSocket unavailable");
11465
12307
  }
@@ -11497,6 +12339,32 @@ function numberEnv(value, fallback) {
11497
12339
  const parsed = Number(value);
11498
12340
  return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
11499
12341
  }
12342
+ function createSetupPromptHandle(io, writeOut) {
12343
+ if (io.readStdin) {
12344
+ const readStdin = io.readStdin;
12345
+ let input;
12346
+ let lines;
12347
+ let lineIndex = 0;
12348
+ return {
12349
+ readPrompt: async (prompt) => {
12350
+ writeOut(prompt);
12351
+ input ??= readStdin();
12352
+ lines ??= (await input).split(/\r?\n/u);
12353
+ return lines[lineIndex++] ?? "";
12354
+ },
12355
+ close: () => {}
12356
+ };
12357
+ }
12358
+ if (io.writeOut || io.writeErr || !process.stdin.isTTY || !process.stdout.isTTY) return;
12359
+ const readline = createInterface({
12360
+ input: process.stdin,
12361
+ output: process.stdout
12362
+ });
12363
+ return {
12364
+ readPrompt: (prompt) => readline.question(prompt),
12365
+ close: () => readline.close()
12366
+ };
12367
+ }
11500
12368
  async function sleep(ms) {
11501
12369
  if (ms <= 0) return;
11502
12370
  await new Promise((resolve) => setTimeout(resolve, ms));
@@ -11552,6 +12420,31 @@ function createProgram(io = {}) {
11552
12420
  }
11553
12421
  if (suggestions.length > 0) writeOut(`${suggestions.join("\n")}\n`);
11554
12422
  });
12423
+ program.command(cliCommands$1.codeMode).description("Run, inspect, and debug Caplets Code Mode.").argument("[code]", "inline TypeScript code to run").option("--file <path>", "read TypeScript code from a file relative to the current directory").option("--timeout-ms <ms>", "execution timeout in milliseconds", parsePositiveInteger).option("--json", "print the structured run envelope").action(async (code, options) => {
12424
+ await runCodeModeCli({
12425
+ env,
12426
+ ...currentConfigPath() ? { configPath: currentConfigPath() } : {},
12427
+ projectConfigPath: envProjectConfigPath(env),
12428
+ ...io.authDir ? { authDir: io.authDir } : {},
12429
+ ...code === void 0 ? {} : { inlineCode: code },
12430
+ ...options.file === void 0 ? {} : { file: options.file },
12431
+ ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs },
12432
+ ...options.json === void 0 ? {} : { json: options.json },
12433
+ ...io.readStdin ? { readStdin: io.readStdin } : {},
12434
+ writeOut,
12435
+ setExitCode
12436
+ });
12437
+ }).command("types").description("Print the generated Code Mode TypeScript declarations.").option("--json", "print declaration metadata as JSON").action(async (options, command) => {
12438
+ const parentOptions = command.parent?.opts() ?? {};
12439
+ await codeModeTypesCli({
12440
+ env,
12441
+ ...currentConfigPath() ? { configPath: currentConfigPath() } : {},
12442
+ projectConfigPath: envProjectConfigPath(env),
12443
+ ...io.authDir ? { authDir: io.authDir } : {},
12444
+ ...options.json === void 0 && parentOptions.json === void 0 ? {} : { json: options.json ?? parentOptions.json },
12445
+ writeOut
12446
+ });
12447
+ });
11555
12448
  const serve = program.command(cliCommands$1.serve).description("Serve configured Caplets as an MCP server.").option("--transport <transport>", "server transport: stdio or http").option("--host <host>", "HTTP bind host").option("--port <port>", "HTTP bind port").option("--path <path>", "HTTP service base path").option("--user <user>", "HTTP Basic Auth username").option("--password <password>", "HTTP Basic Auth password").option("--allow-unauthenticated-http", "allow unauthenticated HTTP serving on non-loopback hosts").option("--trust-proxy", "trust X-Forwarded-* headers from a reverse proxy").action(async (options) => {
11556
12449
  const resolved = resolveServeOptions(options);
11557
12450
  const configPath = currentConfigPath();
@@ -11667,7 +12560,8 @@ function createProgram(io = {}) {
11667
12560
  throw error;
11668
12561
  }
11669
12562
  });
11670
- const cloudAuth = program.command(cliCommands$1.cloud).description("Manage hosted Caplets Cloud.").command("auth").description("Authenticate this Caplets client to hosted Caplets Cloud.");
12563
+ const cloud = program.command(cliCommands$1.cloud).description("Manage hosted Caplets Cloud.");
12564
+ const cloudAuth = cloud.command("auth").description("Authenticate this Caplets client to hosted Caplets Cloud.");
11671
12565
  cloudAuth.command("login").description("Log in to hosted Caplets Cloud.").option("--cloud-url <url>", "hosted Caplets Cloud URL").option("--workspace <workspace>", "workspace ID or slug to select").option("--device-name <name>", "device label for this Cloud Auth credential").option("--no-open", "print the login URL without opening a browser").option("--json", "print JSON output").action(async (options) => {
11672
12566
  const client = new CloudAuthClient({
11673
12567
  cloudUrl: options.cloudUrl ?? env.CAPLETS_CLOUD_URL ?? "https://cloud.caplets.dev",
@@ -11786,6 +12680,29 @@ function createProgram(io = {}) {
11786
12680
  }
11787
12681
  writeOut(`Selected workspace ${next.workspaceSlug ?? next.workspaceId}.\n`);
11788
12682
  });
12683
+ cloud.command("add").description("Upload local caplet-files to the selected hosted Caplets Cloud workspace.").argument("[path]", "directory containing caplet-files", ".").option("--cloud-url <url>", "hosted Caplets Cloud URL").option("--workspace <workspace>", "workspace ID or slug").option("--json", "print JSON output").action(async (pathInput, options) => {
12684
+ const credentials = await cloudAuthStore(env).load();
12685
+ if (!credentials) throw new CapletsError("AUTH_REQUIRED", "Run caplets cloud auth login first.");
12686
+ const cloudUrl = options.cloudUrl ?? credentials.cloudUrl;
12687
+ const workspace = options.workspace ?? credentials.workspaceSlug ?? credentials.workspaceId;
12688
+ const bundle = buildCloudCapletBundle(pathInput);
12689
+ const caplets = (await new CloudAuthClient({
12690
+ cloudUrl,
12691
+ ...io.fetch ? { fetch: io.fetch } : {}
12692
+ }).addCaplets({
12693
+ accessToken: credentials.accessToken,
12694
+ workspace,
12695
+ bundle
12696
+ })).caplets.map(compactCloudCaplet);
12697
+ if (options.json) {
12698
+ writeOut(`${JSON.stringify({
12699
+ caplets,
12700
+ workspace
12701
+ }, null, 2)}\n`);
12702
+ return;
12703
+ }
12704
+ for (const caplet of caplets) writeOut(`Added ${caplet.name ?? caplet.id ?? "Caplet"} to ${workspace}.\n`);
12705
+ });
11789
12706
  program.command(cliCommands$1.init).description("Create a starter Caplets config file.").option("--project", "create the project Caplets config").option("-g, --global", "create the user Caplets config").option("--remote", "create the remote Caplets config").option("--force", "overwrite an existing config file").action(async (options) => {
11790
12707
  const target = parseMutationTarget(options);
11791
12708
  if (target === "remote") {
@@ -11798,16 +12715,28 @@ function createProgram(io = {}) {
11798
12715
  });
11799
12716
  writeOut(`Created ${localMutationTargetLabel(target, io)}Caplets config at ${path}\n`);
11800
12717
  });
11801
- program.command(cliCommands$1.setup).description("Install or configure an agent integration for Caplets.").argument("[integration]", "integration: codex, claude-code, opencode, pi, or mcp-client").option("--remote", "configure for a remote Caplets server").option("--server-url <url>", "remote Caplets service base URL").option("--output <path>", "config path to write for generic MCP setup").option("--dry-run", "print actions without running commands or writing files").option("--yes", "approve Caplet setup commands for the exact current content hash").option("--target <target>", "Caplet setup target: local, remote, or cloud", parseSetupTarget).option("--format <format>", "output format: plain or json", parseSetupFormat).action(async (integration, options) => {
11802
- if (!integration) {
11803
- writeOut(formatSetupMenu());
11804
- return;
11805
- }
12718
+ program.command(cliCommands$1.setup).description("Install or configure an agent integration for Caplets.").argument("[integration]", "integration: codex, claude-code, opencode, pi, or mcp-client").option("--remote", "configure for a remote Caplets server").option("--remote-url <url>", "remote Caplets service base URL").option("--server-url <url>", "remote Caplets service base URL").option("--output <path>", "config path to write for generic MCP setup").option("--dry-run", "print actions without running commands or writing files").option("--yes", "approve Caplet setup commands for the exact current content hash").option("--target <target>", "Caplet setup target: local, remote, or cloud", parseSetupTarget).option("--format <format>", "output format: plain or json", parseSetupFormat).action(async (integration, options) => {
11806
12719
  const setupOptions = {
11807
12720
  ...options,
11808
12721
  env
11809
12722
  };
11810
12723
  if (io.runSetupCommand) setupOptions.runCommand = io.runSetupCommand;
12724
+ if (!integration) {
12725
+ const promptHandle = createSetupPromptHandle(io, writeOut);
12726
+ if (!promptHandle) {
12727
+ writeOut(formatSetupMenu());
12728
+ return;
12729
+ }
12730
+ try {
12731
+ writeOut(await runInteractiveSetup({
12732
+ ...setupOptions,
12733
+ readPrompt: promptHandle.readPrompt
12734
+ }));
12735
+ } finally {
12736
+ promptHandle.close();
12737
+ }
12738
+ return;
12739
+ }
11811
12740
  writeOut(await runSetup(integration, setupOptions));
11812
12741
  });
11813
12742
  program.command(cliCommands$1.doctor).description("Diagnose Caplets local, remote, and project-sync configuration.").option("--json", "print JSON output").action(async (options) => {
@@ -11954,7 +12883,7 @@ function createProgram(io = {}) {
11954
12883
  });
11955
12884
  });
11956
12885
  program.command(cliCommands$1.checkBackend).description("Check backend availability for a configured Caplet.").argument("<caplet>", "configured Caplet ID").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => {
11957
- await executeOperation(caplet, { operation: "check_backend" }, {
12886
+ await executeOperation(caplet, { operation: "check" }, {
11958
12887
  writeOut,
11959
12888
  writeErr,
11960
12889
  setExitCode,
@@ -11965,7 +12894,7 @@ function createProgram(io = {}) {
11965
12894
  });
11966
12895
  });
11967
12896
  program.command(cliCommands$1.listTools).description("List downstream tools for a configured Caplet.").argument("<caplet>", "configured Caplet ID").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => {
11968
- await executeOperation(caplet, { operation: "list_tools" }, {
12897
+ await executeOperation(caplet, { operation: "tools" }, {
11969
12898
  writeOut,
11970
12899
  writeErr,
11971
12900
  setExitCode,
@@ -11996,8 +12925,8 @@ function createProgram(io = {}) {
11996
12925
  program.command(cliCommands$1.getTool).description("Print one downstream tool schema.").argument("<caplet-or-target>", "Caplet ID or qualified <caplet.tool> target").argument("[tool]", "downstream tool name when caplet is provided separately").option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (capletOrTarget, toolArgument, options) => {
11997
12926
  const { caplet, tool } = parseQualifiedTarget(capletOrTarget, toolArgument);
11998
12927
  await executeOperation(caplet, {
11999
- operation: "get_tool",
12000
- tool
12928
+ operation: "describe_tool",
12929
+ name: tool
12001
12930
  }, {
12002
12931
  writeOut,
12003
12932
  writeErr,
@@ -12012,8 +12941,8 @@ function createProgram(io = {}) {
12012
12941
  const { caplet, tool } = parseQualifiedTarget(capletOrTarget, toolArgument);
12013
12942
  await executeOperation(caplet, {
12014
12943
  operation: "call_tool",
12015
- tool,
12016
- arguments: parseCallToolArgs(options.args),
12944
+ name: tool,
12945
+ args: parseCallToolArgs(options.args),
12017
12946
  ...options.field && options.field.length > 0 ? { fields: options.field } : {}
12018
12947
  }, {
12019
12948
  writeOut,
@@ -12025,8 +12954,8 @@ function createProgram(io = {}) {
12025
12954
  format: options.format
12026
12955
  });
12027
12956
  });
12028
- program.command(cliCommands$1.listResources).description("List MCP resources for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of resources to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "list_resources" } : {
12029
- operation: "list_resources",
12957
+ program.command(cliCommands$1.listResources).description("List MCP resources for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of resources to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "resources" } : {
12958
+ operation: "resources",
12030
12959
  limit: options.limit
12031
12960
  }, {
12032
12961
  writeOut,
@@ -12053,8 +12982,8 @@ function createProgram(io = {}) {
12053
12982
  remote: remoteClientForCli(io),
12054
12983
  format: options.format
12055
12984
  }));
12056
- program.command(cliCommands$1.listResourceTemplates).description("List MCP resource templates for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of templates to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "list_resource_templates" } : {
12057
- operation: "list_resource_templates",
12985
+ program.command(cliCommands$1.listResourceTemplates).description("List MCP resource templates for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of templates to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "resource_templates" } : {
12986
+ operation: "resource_templates",
12058
12987
  limit: options.limit
12059
12988
  }, {
12060
12989
  writeOut,
@@ -12077,8 +13006,8 @@ function createProgram(io = {}) {
12077
13006
  remote: remoteClientForCli(io),
12078
13007
  format: options.format
12079
13008
  }));
12080
- program.command(cliCommands$1.listPrompts).description("List MCP prompts for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of prompts to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "list_prompts" } : {
12081
- operation: "list_prompts",
13009
+ program.command(cliCommands$1.listPrompts).description("List MCP prompts for a configured MCP Caplet.").argument("<caplet>").option("--limit <n>", "maximum number of prompts to return", parsePositiveInteger).option("--format <format>", "output format: markdown, md, plain, or json", parseOutputFormat).action(async (caplet, options) => executeOperation(caplet, options.limit === void 0 ? { operation: "prompts" } : {
13010
+ operation: "prompts",
12082
13011
  limit: options.limit
12083
13012
  }, {
12084
13013
  writeOut,
@@ -12109,8 +13038,8 @@ function createProgram(io = {}) {
12109
13038
  const { caplet, tool: prompt } = parseQualifiedTarget(capletOrTarget, promptArgument);
12110
13039
  await executeOperation(caplet, {
12111
13040
  operation: "get_prompt",
12112
- prompt,
12113
- arguments: parseJsonObjectOption(options.args, "get-prompt --args")
13041
+ name: prompt,
13042
+ args: parseJsonObjectOption(options.args, "get-prompt --args")
12114
13043
  }, {
12115
13044
  writeOut,
12116
13045
  writeErr,
@@ -12229,16 +13158,16 @@ async function openBrowser(url) {
12229
13158
  function remoteCommandForOperation(operation) {
12230
13159
  switch (operation) {
12231
13160
  case "inspect":
12232
- case "check_backend":
12233
- case "list_tools":
13161
+ case "check":
13162
+ case "tools":
12234
13163
  case "search_tools":
12235
- case "get_tool":
13164
+ case "describe_tool":
12236
13165
  case "call_tool":
12237
- case "list_resources":
13166
+ case "resources":
12238
13167
  case "search_resources":
12239
- case "list_resource_templates":
13168
+ case "resource_templates":
12240
13169
  case "read_resource":
12241
- case "list_prompts":
13170
+ case "prompts":
12242
13171
  case "search_prompts":
12243
13172
  case "get_prompt":
12244
13173
  case "complete": return operation;
@@ -12623,7 +13552,7 @@ function markdownSummaryForOperation(result, request) {
12623
13552
  `- List tools: \`caplets list-tools ${id}\``,
12624
13553
  `- Search tools: \`caplets search-tools ${id} <query>\``
12625
13554
  ].filter((line) => line !== void 0).join("\n");
12626
- case "check_backend": return [
13555
+ case "check": return [
12627
13556
  `## Backend \`${id}\``,
12628
13557
  "",
12629
13558
  `- Status: ${String(payload.status ?? "unknown")}`,
@@ -12633,8 +13562,8 @@ function markdownSummaryForOperation(result, request) {
12633
13562
  "Next:",
12634
13563
  `- List tools: \`caplets list-tools ${id}\``
12635
13564
  ].filter((line) => line !== void 0).join("\n");
12636
- case "list_tools": {
12637
- const tools = Array.isArray(payload.tools) ? payload.tools : [];
13565
+ case "tools": {
13566
+ const tools = pageItemsFromPayload(payload);
12638
13567
  return [
12639
13568
  `## Tools for \`${id}\``,
12640
13569
  "",
@@ -12649,7 +13578,7 @@ function markdownSummaryForOperation(result, request) {
12649
13578
  ].join("\n");
12650
13579
  }
12651
13580
  case "search_tools": {
12652
- const tools = Array.isArray(payload.tools) ? payload.tools : [];
13581
+ const tools = pageItemsFromPayload(payload);
12653
13582
  return [
12654
13583
  `## Matches for ${JSON.stringify(String(payload.query ?? ""))} in \`${id}\``,
12655
13584
  "",
@@ -12661,7 +13590,7 @@ function markdownSummaryForOperation(result, request) {
12661
13590
  tools.length > 0 ? `- Inspect the first match: \`caplets get-tool ${id}.${firstToolName(tools) ?? "<tool>"}\`` : `- Try a broader query or list tools: \`caplets list-tools ${id}\``
12662
13591
  ].join("\n");
12663
13592
  }
12664
- case "get_tool": {
13593
+ case "describe_tool": {
12665
13594
  const tool = isPlainObject(payload.tool) ? payload.tool : {};
12666
13595
  const target = `${id}.${String(tool.name ?? "<tool>")}`;
12667
13596
  return [
@@ -12681,7 +13610,7 @@ function markdownSummaryForOperation(result, request) {
12681
13610
  ].filter((line) => line !== void 0).join("\n");
12682
13611
  }
12683
13612
  case "call_tool": return [
12684
- `## Call \`${`${String(request.caplet ?? "<caplet>")}.${String(request.tool ?? "unknown")}`}\``,
13613
+ `## Call \`${`${String(request.caplet ?? "<caplet>")}.${String(request.name ?? "unknown")}`}\``,
12685
13614
  "",
12686
13615
  `- Status: ${payload.isError === true ? "failed" : "succeeded"}`,
12687
13616
  callStatusLine(payload) ? `- ${callStatusLine(payload)}` : void 0,
@@ -12689,11 +13618,9 @@ function markdownSummaryForOperation(result, request) {
12689
13618
  "",
12690
13619
  "Use `--format json` to inspect the full structured result."
12691
13620
  ].filter((line) => line !== void 0).join("\n");
12692
- case "list_resources":
13621
+ case "resources":
12693
13622
  case "search_resources": {
12694
- const resources = Array.isArray(payload.resources) ? payload.resources : [];
12695
- const templates = Array.isArray(payload.resourceTemplates) ? payload.resourceTemplates : [];
12696
- const matches = Array.isArray(payload.matches) ? payload.matches : [...resources, ...templates];
13623
+ const matches = pageItemsFromPayload(payload);
12697
13624
  return [
12698
13625
  `## MCP resources for \`${id}\``,
12699
13626
  "",
@@ -12702,8 +13629,8 @@ function markdownSummaryForOperation(result, request) {
12702
13629
  ...formatResourceLines(matches, "markdown")
12703
13630
  ].join("\n");
12704
13631
  }
12705
- case "list_resource_templates": {
12706
- const templates = Array.isArray(payload.resourceTemplates) ? payload.resourceTemplates : [];
13632
+ case "resource_templates": {
13633
+ const templates = pageItemsFromPayload(payload);
12707
13634
  return [
12708
13635
  `## MCP resource templates for \`${id}\``,
12709
13636
  "",
@@ -12717,9 +13644,9 @@ function markdownSummaryForOperation(result, request) {
12717
13644
  "",
12718
13645
  "Use `--format json` to inspect all contents."
12719
13646
  ].join("\n");
12720
- case "list_prompts":
13647
+ case "prompts":
12721
13648
  case "search_prompts": {
12722
- const prompts = Array.isArray(payload.prompts) ? payload.prompts : [];
13649
+ const prompts = pageItemsFromPayload(payload);
12723
13650
  return [
12724
13651
  `## MCP prompts for \`${id}\``,
12725
13652
  "",
@@ -12727,7 +13654,7 @@ function markdownSummaryForOperation(result, request) {
12727
13654
  ].join("\n");
12728
13655
  }
12729
13656
  case "get_prompt": return [
12730
- `## Prompt \`${String(request.caplet)}.${String(request.prompt)}\``,
13657
+ `## Prompt \`${String(request.caplet)}.${String(request.name)}\``,
12731
13658
  "",
12732
13659
  summarizePromptResult(payload),
12733
13660
  "",
@@ -12754,14 +13681,14 @@ function plainSummaryForOperation(result, request) {
12754
13681
  payload.backend ? `Backend: ${backendType(payload.backend)}` : void 0,
12755
13682
  `Next: caplets list-tools ${id} or caplets search-tools ${id} <query>`
12756
13683
  ].filter((line) => Boolean(line)).join("\n");
12757
- case "check_backend": return [
13684
+ case "check": return [
12758
13685
  `Backend: ${id} is ${String(payload.status ?? "unknown")}`,
12759
13686
  typeof payload.toolCount === "number" ? `Tools: ${payload.toolCount}` : void 0,
12760
13687
  typeof payload.elapsedMs === "number" ? `Elapsed: ${payload.elapsedMs}ms` : void 0,
12761
13688
  `Next: caplets list-tools ${id}`
12762
13689
  ].filter((line) => Boolean(line)).join("\n");
12763
- case "list_tools": {
12764
- const tools = Array.isArray(payload.tools) ? payload.tools : [];
13690
+ case "tools": {
13691
+ const tools = pageItemsFromPayload(payload);
12765
13692
  return [
12766
13693
  `Tools for ${id} (${tools.length}):`,
12767
13694
  ...formatToolLines(tools, "plain"),
@@ -12769,14 +13696,14 @@ function plainSummaryForOperation(result, request) {
12769
13696
  ].join("\n");
12770
13697
  }
12771
13698
  case "search_tools": {
12772
- const tools = Array.isArray(payload.tools) ? payload.tools : [];
13699
+ const tools = pageItemsFromPayload(payload);
12773
13700
  return [
12774
13701
  `Matches for ${JSON.stringify(String(payload.query ?? ""))} in ${id} (${tools.length}):`,
12775
13702
  ...formatToolLines(tools, "plain"),
12776
13703
  tools.length > 0 ? `Next: caplets get-tool ${id}.${firstToolName(tools) ?? "<tool>"}` : `Next: try caplets list-tools ${id} or a broader query.`
12777
13704
  ].join("\n");
12778
13705
  }
12779
- case "get_tool": {
13706
+ case "describe_tool": {
12780
13707
  const tool = isPlainObject(payload.tool) ? payload.tool : {};
12781
13708
  const target = `${id}.${String(tool.name ?? "<tool>")}`;
12782
13709
  return [
@@ -12789,20 +13716,18 @@ function plainSummaryForOperation(result, request) {
12789
13716
  ].filter((line) => Boolean(line)).join("\n");
12790
13717
  }
12791
13718
  case "call_tool": return [
12792
- `Call ${`${String(request.caplet ?? "<caplet>")}.${String(request.tool ?? "unknown")}`} ${payload.isError === true ? "failed" : "succeeded"}.`,
13719
+ `Call ${`${String(request.caplet ?? "<caplet>")}.${String(request.name ?? "unknown")}`} ${payload.isError === true ? "failed" : "succeeded"}.`,
12793
13720
  callStatusLine(payload),
12794
13721
  `Result: ${summarizeCallResult(payload)}`,
12795
13722
  "Use --format json to inspect the full structured result."
12796
13723
  ].filter((line) => Boolean(line)).join("\n");
12797
- case "list_resources":
13724
+ case "resources":
12798
13725
  case "search_resources": {
12799
- const resources = Array.isArray(payload.resources) ? payload.resources : [];
12800
- const templates = Array.isArray(payload.resourceTemplates) ? payload.resourceTemplates : [];
12801
- const matches = Array.isArray(payload.matches) ? payload.matches : [...resources, ...templates];
13726
+ const matches = pageItemsFromPayload(payload);
12802
13727
  return [`MCP resources for ${id} (${matches.length}):`, ...formatResourceLines(matches, "plain")].join("\n");
12803
13728
  }
12804
- case "list_resource_templates": {
12805
- const templates = Array.isArray(payload.resourceTemplates) ? payload.resourceTemplates : [];
13729
+ case "resource_templates": {
13730
+ const templates = pageItemsFromPayload(payload);
12806
13731
  return [`MCP resource templates for ${id}:`, ...formatResourceLines(templates, "plain")].join("\n");
12807
13732
  }
12808
13733
  case "read_resource": return [
@@ -12810,13 +13735,13 @@ function plainSummaryForOperation(result, request) {
12810
13735
  summarizeResourceRead(payload),
12811
13736
  "Use --format json to inspect all contents."
12812
13737
  ].join("\n");
12813
- case "list_prompts":
13738
+ case "prompts":
12814
13739
  case "search_prompts": {
12815
- const prompts = Array.isArray(payload.prompts) ? payload.prompts : [];
13740
+ const prompts = pageItemsFromPayload(payload);
12816
13741
  return [`MCP prompts for ${id}:`, ...formatPromptLines(prompts, "plain")].join("\n");
12817
13742
  }
12818
13743
  case "get_prompt": return [
12819
- `Prompt ${String(request.caplet)}.${String(request.prompt)}`,
13744
+ `Prompt ${String(request.caplet)}.${String(request.name)}`,
12820
13745
  summarizePromptResult(payload),
12821
13746
  "Use --format json to inspect all messages."
12822
13747
  ].join("\n");
@@ -12827,6 +13752,17 @@ function plainSummaryForOperation(result, request) {
12827
13752
  function payloadId(payload) {
12828
13753
  return String(payload.id ?? payload.caplet ?? payload.server ?? "<caplet>");
12829
13754
  }
13755
+ function pageItemsFromPayload(payload) {
13756
+ if (Array.isArray(payload.items)) return payload.items;
13757
+ for (const key of [
13758
+ "tools",
13759
+ "resources",
13760
+ "resourceTemplates",
13761
+ "prompts",
13762
+ "matches"
13763
+ ]) if (Array.isArray(payload[key])) return payload[key];
13764
+ return [];
13765
+ }
12830
13766
  function formatToolLines(tools, format) {
12831
13767
  if (tools.length === 0) return ["- none"];
12832
13768
  return tools.map((tool) => {
@@ -13116,6 +14052,12 @@ const rank = {
13116
14052
  large: 2,
13117
14053
  heavy: 3
13118
14054
  };
14055
+ function resourceClassRank(value) {
14056
+ return rank[value] ?? 0;
14057
+ }
14058
+ function isRuntimeResourceClassAllowed(requested, maximum) {
14059
+ return resourceClassRank(requested) <= resourceClassRank(maximum);
14060
+ }
13119
14061
  function resolveRuntimeResources(inputOrCaplet, features, policy) {
13120
14062
  const caplet = inputOrCaplet;
13121
14063
  const input = features === void 0 ? inputOrCaplet : {
@@ -13150,7 +14092,7 @@ function explicitResourceClass$1(caplet) {
13150
14092
  }
13151
14093
  function capClass(requested, maxClass) {
13152
14094
  if (!maxClass) return requested;
13153
- return (rank[requested] ?? 0) > (rank[maxClass] ?? 0) ? maxClass : requested;
14095
+ return isRuntimeResourceClassAllowed(requested, maxClass) ? requested : maxClass;
13154
14096
  }
13155
14097
  //#endregion
13156
14098
  //#region src/runtime-plan/planner.ts
@@ -13673,4 +14615,4 @@ function isRecord(value) {
13673
14615
  return typeof value === "object" && value !== null;
13674
14616
  }
13675
14617
  //#endregion
13676
- export { BundleCapletSource, CapletsRuntime, CloudAuthClient, CloudAuthStore, DEFAULT_SYNC_LIMITS, FilesystemCapletSource, LocalSetupStore, ManagedMutagenProjectSync, PROJECT_BINDINGS_CONTROL_PATH, PROJECT_BINDING_CONNECT_PATH, PROJECT_BINDING_ERROR_CODES, PROJECT_BINDING_STATES, PROJECT_BINDING_SYNC_STATES, ProjectBindingError, ProjectBindingWorkspaceStore, ServerRegistry, attachProjectOnce, attachProjectSession, buildProjectSyncManifest, capabilityDescription, capletSetupContentHash, classifyCapletRuntimeRoute, cloudAuthPath, createProgram, defaultProjectBindingWebSocketFactory, enforceProjectSyncSizeLimits, generatedToolInputSchema, handleServerTool, hasRenderableStructuredContent, loadConfig, markdownCallToolResultContent, markdownStructuredContent, migrateCredentials, mutagenProjectSyncDoctorData, mutagenSyncName, openBrowserUrl, parseCapletSource, parseConfig, parseMutagenVersionOutput as parseManagedMutagenVersionOutput, planCapletRuntimeRoute, planCapletRuntimeRoutes, planMutagenSyncCreateCommand, planMutagenSyncListCommand, planMutagenSyncTerminateCommand, planMutagenVersionCommand, projectBindingConnectPath, projectBindingConnectUrl, projectBindingError, projectBindingRecovery, projectBindingStatusPath, projectBindingStatusUrl, projectBindingWorkspacePaths, projectBindingWorkspaceRoot, redactedCloudAuthStatus, resolveAttachOptions, runCapletSetup, runCli, runProjectBindingSession, serveCaplets, serveHttp, serveResolvedCaplets, serveStdio, stableJson };
14618
+ export { BundleCapletSource, CapletsRuntime, CloudAuthClient, CloudAuthStore, CodeModeLogStore, DEFAULT_SYNC_LIMITS, FileObservedOutputShapeStore, FilesystemCapletSource, LocalSetupStore, ManagedMutagenProjectSync, PROJECT_BINDINGS_CONTROL_PATH, PROJECT_BINDING_CONNECT_PATH, PROJECT_BINDING_ERROR_CODES, PROJECT_BINDING_STATES, PROJECT_BINDING_SYNC_STATES, ProjectBindingError, ProjectBindingWorkspaceStore, QuickJsCodeModeSandbox, ServerRegistry, attachProjectOnce, attachProjectSession, buildProjectSyncManifest, capabilityDescription, capletSetupContentHash, classifyCapletRuntimeRoute, cloudAuthPath, codeModeDeclarationHash, createCodeModeCapletsApi, createProgram, defaultProjectBindingWebSocketFactory, diagnoseCodeModeTypeScript, enforceProjectSyncSizeLimits, generateCodeModeDeclarations, generateCodeModeRunToolDescription, generatedToolInputSchema, handleServerTool, hasRenderableStructuredContent, listCodeModeCallableCaplets, loadConfig, markdownCallToolResultContent, markdownStructuredContent, migrateCredentials, minifyCodeModeDeclarationText, mutagenProjectSyncDoctorData, mutagenSyncName, observeOutputShape, observedOutputShapeKey, openBrowserUrl, parseCapletSource, parseConfig, parseMutagenVersionOutput as parseManagedMutagenVersionOutput, planCapletRuntimeRoute, planCapletRuntimeRoutes, planMutagenSyncCreateCommand, planMutagenSyncListCommand, planMutagenSyncTerminateCommand, planMutagenVersionCommand, projectBindingConnectPath, projectBindingConnectUrl, projectBindingError, projectBindingRecovery, projectBindingStatusPath, projectBindingStatusUrl, projectBindingWorkspacePaths, projectBindingWorkspaceRoot, redactCodeModeLogText, redactedCloudAuthStatus, resolveAttachOptions, runCapletSetup, runCli, runCodeMode, runProjectBindingSession, serveCaplets, serveHttp, serveResolvedCaplets, serveStdio, stableJson };