@ken-jo/agent-connector 0.4.92 → 0.4.93

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 (164) hide show
  1. package/README.md +44 -22
  2. package/dist/{action-CVIEPX4U.js → action-DOWHWEDZ.js} +9 -9
  3. package/dist/{amazon-q-TIT7FIW3.js → amazon-q-ETMAGY3D.js} +3 -3
  4. package/dist/{amp-NF3OAAUG.js → amp-67BZONGF.js} +3 -3
  5. package/dist/{antigravity-7LPK7QOY.js → antigravity-VXLDLTO7.js} +4 -4
  6. package/dist/{antigravity-cli-MDEMPPAH.js → antigravity-cli-OM6SC3PE.js} +4 -4
  7. package/dist/{chunk-7UT6OB52.js → chunk-2RIFORQS.js} +2 -2
  8. package/dist/{chunk-JFXL4HYA.js → chunk-6WZODR3Z.js} +2 -2
  9. package/dist/{chunk-IBLYVAWH.js → chunk-B5W3RHTI.js} +48 -20
  10. package/dist/{chunk-IBLYVAWH.js.map → chunk-B5W3RHTI.js.map} +1 -1
  11. package/dist/{chunk-447JWFZO.js → chunk-EHP7WISI.js} +5 -5
  12. package/dist/{chunk-FBCBHEGB.js → chunk-I5TO42QC.js} +3 -3
  13. package/dist/{chunk-3C5AASHM.js → chunk-JKKU2WKG.js} +2 -2
  14. package/dist/{chunk-AY3VFNOH.js → chunk-KJLFGQQM.js} +178 -8
  15. package/dist/chunk-KJLFGQQM.js.map +1 -0
  16. package/dist/{chunk-JVO6NBTT.js → chunk-KSPMSRVU.js} +26 -14
  17. package/dist/chunk-KSPMSRVU.js.map +1 -0
  18. package/dist/{chunk-WFEHWTLM.js → chunk-MGTDQLJJ.js} +2 -2
  19. package/dist/{chunk-5Z36KVU2.js → chunk-OEADFFKO.js} +18 -18
  20. package/dist/{chunk-L26PSQTY.js → chunk-P23RVIUY.js} +4 -4
  21. package/dist/{chunk-KA55FISM.js → chunk-SILKSP2Y.js} +43 -43
  22. package/dist/{chunk-JO2IM2JL.js → chunk-TTKSYJRY.js} +6 -6
  23. package/dist/{chunk-M2H7JURF.js → chunk-UMQ6NBQR.js} +2 -2
  24. package/dist/chunk-UMQ6NBQR.js.map +1 -0
  25. package/dist/{chunk-DI5S6TXJ.js → chunk-XC5SJ35F.js} +2 -2
  26. package/dist/{chunk-FO5CEXXN.js → chunk-ZMAJ2XFD.js} +2 -2
  27. package/dist/{claude-code-7RS4YVGZ.js → claude-code-DUZNOAS2.js} +6 -6
  28. package/dist/cli/sdk.js +5 -5
  29. package/dist/cli.js +1 -1
  30. package/dist/{cline-BZQAUYPC.js → cline-25KW25IN.js} +3 -3
  31. package/dist/{codebuddy-G42IKGKB.js → codebuddy-ZNYQACMF.js} +3 -3
  32. package/dist/{codebuff-5RLTLZAU.js → codebuff-VR6JUDIY.js} +3 -3
  33. package/dist/{codex-XHAMJILX.js → codex-CPNKTXG3.js} +3 -3
  34. package/dist/{continue-JLIB7R7X.js → continue-WU2IB5KS.js} +3 -3
  35. package/dist/{copilot-cli-XZSUYNQZ.js → copilot-cli-PAP377OM.js} +3 -3
  36. package/dist/{crush-ESERLVLT.js → crush-3AVQA4YU.js} +3 -3
  37. package/dist/{cursor-FUDOV5VK.js → cursor-GSLUET3V.js} +4 -4
  38. package/dist/define-connector-LQFJL_at.d.ts +89 -0
  39. package/dist/{detect-Z5BDTY6B.js → detect-DYQNUMXL.js} +4 -4
  40. package/dist/{devin-Y7PWKVHY.js → devin-QMEM3OFA.js} +3 -3
  41. package/dist/{doctor-GAP27PP2.js → doctor-H6XXAR63.js} +14 -14
  42. package/dist/{droid-DTO5POTK.js → droid-MOKV53J4.js} +3 -3
  43. package/dist/{gemini-cli-RBIG6U2F.js → gemini-cli-47ZHCOZR.js} +3 -3
  44. package/dist/{goose-VGNOP5J2.js → goose-4EI5MYTI.js} +3 -3
  45. package/dist/{grok-cli-2RFBK6J3.js → grok-cli-QYQPDSVB.js} +3 -3
  46. package/dist/{hermes-NUKFWZI5.js → hermes-F75OSK3Y.js} +3 -3
  47. package/dist/{hook-XPR3AHDI.js → hook-GIQTUDMN.js} +9 -9
  48. package/dist/index.d.ts +15 -88
  49. package/dist/index.js +13 -5
  50. package/dist/{install-O32TDIZP.js → install-T27662FW.js} +11 -11
  51. package/dist/{introspect-BkId4LGP.d.ts → introspect-D4fEGuhN.d.ts} +1 -1
  52. package/dist/{jetbrains-copilot-FXZ5AOTS.js → jetbrains-copilot-ZGIWI6YV.js} +3 -3
  53. package/dist/{junie-TSXIZSCE.js → junie-DIFN2P22.js} +3 -3
  54. package/dist/{kilo-JLH3KVZJ.js → kilo-EMZJBEBB.js} +3 -3
  55. package/dist/{kilo-cli-5W36VJQZ.js → kilo-cli-S3GXBPAE.js} +3 -3
  56. package/dist/{kimi-R62W7HKZ.js → kimi-IQJOIY6B.js} +3 -3
  57. package/dist/{kiro-AUJMGIBL.js → kiro-BYX4HEAJ.js} +3 -3
  58. package/dist/{leaderboard-YWMOSJBC.js → leaderboard-CIMQBOUS.js} +2 -2
  59. package/dist/{mimo-code-PGLFFVER.js → mimo-code-7R53QDHB.js} +3 -3
  60. package/dist/{mistral-vibe-36CZVQNQ.js → mistral-vibe-LHJ55FSB.js} +3 -3
  61. package/dist/{mux-HWL4N5KH.js → mux-NYCNGL43.js} +3 -3
  62. package/dist/{nemoclaw-QPHETUXM.js → nemoclaw-WSIPSE7U.js} +4 -4
  63. package/dist/{omp-3TFMTJ5U.js → omp-562NK5BJ.js} +3 -3
  64. package/dist/{open-interpreter-UTBKE2EH.js → open-interpreter-I2CNOEXY.js} +3 -3
  65. package/dist/{openclaw-RYFO5TLY.js → openclaw-7EYBQS4R.js} +4 -4
  66. package/dist/{opencode-JX7GBE5Q.js → opencode-YS4WX2E2.js} +3 -3
  67. package/dist/{openhands-AZW4PXJ3.js → openhands-QMYIKNOS.js} +3 -3
  68. package/dist/{package-2KKUGZFS.js → package-LIPZKHAQ.js} +9 -9
  69. package/dist/{pi-MRI3EBWU.js → pi-644FIN3A.js} +3 -3
  70. package/dist/{qwen-code-ISR6BEET.js → qwen-code-STDMX7EM.js} +3 -3
  71. package/dist/{roo-code-6TSCME4R.js → roo-code-DLPIHHQ6.js} +3 -3
  72. package/dist/runtime/index.d.ts +1 -1
  73. package/dist/runtime/index.js +7 -7
  74. package/dist/sdk/index.d.ts +4 -4
  75. package/dist/sdk/index.js +4 -4
  76. package/dist/sdk/test.d.ts +2 -2
  77. package/dist/sdk/test.js +7 -7
  78. package/dist/{serve-EPRN7F2X.js → serve-ABTO2NA2.js} +9 -9
  79. package/dist/{status-B2PG6YKR.js → status-J7SOUH7O.js} +7 -7
  80. package/dist/{statusline-5ERFMYSM.js → statusline-QF4G724E.js} +8 -8
  81. package/dist/{telemetry-ZMCAWBWB.js → telemetry-EICCFEIF.js} +6 -6
  82. package/dist/{trae-7KDCYIMN.js → trae-UOYD6JZZ.js} +3 -3
  83. package/dist/{types-D0RqWxT8.d.ts → types-BhcUEIJJ.d.ts} +39 -3
  84. package/dist/{uninstall-M76BHLTH.js → uninstall-NJNNZZZY.js} +11 -11
  85. package/dist/{upgrade-JLSCNAQA.js → upgrade-TIBUOQNM.js} +11 -11
  86. package/dist/{usage-5I72HWCR.js → usage-VEVBWPLS.js} +2 -2
  87. package/dist/{usage-event-HIX4ZI45.js → usage-event-GRQE7XWT.js} +8 -8
  88. package/dist/{vscode-copilot-LILHAPJI.js → vscode-copilot-NIMH2DGU.js} +3 -3
  89. package/dist/{warp-KJUCWEA3.js → warp-QYJGKURM.js} +3 -3
  90. package/dist/{windsurf-5TGGQR5I.js → windsurf-75LLZ37C.js} +3 -3
  91. package/dist/{zed-EL3JCZ25.js → zed-HKAZXEJW.js} +3 -3
  92. package/package.json +1 -1
  93. package/dist/chunk-AY3VFNOH.js.map +0 -1
  94. package/dist/chunk-JVO6NBTT.js.map +0 -1
  95. package/dist/chunk-M2H7JURF.js.map +0 -1
  96. /package/dist/{action-CVIEPX4U.js.map → action-DOWHWEDZ.js.map} +0 -0
  97. /package/dist/{amazon-q-TIT7FIW3.js.map → amazon-q-ETMAGY3D.js.map} +0 -0
  98. /package/dist/{amp-NF3OAAUG.js.map → amp-67BZONGF.js.map} +0 -0
  99. /package/dist/{antigravity-7LPK7QOY.js.map → antigravity-VXLDLTO7.js.map} +0 -0
  100. /package/dist/{antigravity-cli-MDEMPPAH.js.map → antigravity-cli-OM6SC3PE.js.map} +0 -0
  101. /package/dist/{chunk-7UT6OB52.js.map → chunk-2RIFORQS.js.map} +0 -0
  102. /package/dist/{chunk-JFXL4HYA.js.map → chunk-6WZODR3Z.js.map} +0 -0
  103. /package/dist/{chunk-447JWFZO.js.map → chunk-EHP7WISI.js.map} +0 -0
  104. /package/dist/{chunk-FBCBHEGB.js.map → chunk-I5TO42QC.js.map} +0 -0
  105. /package/dist/{chunk-3C5AASHM.js.map → chunk-JKKU2WKG.js.map} +0 -0
  106. /package/dist/{chunk-WFEHWTLM.js.map → chunk-MGTDQLJJ.js.map} +0 -0
  107. /package/dist/{chunk-5Z36KVU2.js.map → chunk-OEADFFKO.js.map} +0 -0
  108. /package/dist/{chunk-L26PSQTY.js.map → chunk-P23RVIUY.js.map} +0 -0
  109. /package/dist/{chunk-KA55FISM.js.map → chunk-SILKSP2Y.js.map} +0 -0
  110. /package/dist/{chunk-JO2IM2JL.js.map → chunk-TTKSYJRY.js.map} +0 -0
  111. /package/dist/{chunk-DI5S6TXJ.js.map → chunk-XC5SJ35F.js.map} +0 -0
  112. /package/dist/{chunk-FO5CEXXN.js.map → chunk-ZMAJ2XFD.js.map} +0 -0
  113. /package/dist/{claude-code-7RS4YVGZ.js.map → claude-code-DUZNOAS2.js.map} +0 -0
  114. /package/dist/{cline-BZQAUYPC.js.map → cline-25KW25IN.js.map} +0 -0
  115. /package/dist/{codebuddy-G42IKGKB.js.map → codebuddy-ZNYQACMF.js.map} +0 -0
  116. /package/dist/{codebuff-5RLTLZAU.js.map → codebuff-VR6JUDIY.js.map} +0 -0
  117. /package/dist/{codex-XHAMJILX.js.map → codex-CPNKTXG3.js.map} +0 -0
  118. /package/dist/{continue-JLIB7R7X.js.map → continue-WU2IB5KS.js.map} +0 -0
  119. /package/dist/{copilot-cli-XZSUYNQZ.js.map → copilot-cli-PAP377OM.js.map} +0 -0
  120. /package/dist/{crush-ESERLVLT.js.map → crush-3AVQA4YU.js.map} +0 -0
  121. /package/dist/{cursor-FUDOV5VK.js.map → cursor-GSLUET3V.js.map} +0 -0
  122. /package/dist/{detect-Z5BDTY6B.js.map → detect-DYQNUMXL.js.map} +0 -0
  123. /package/dist/{devin-Y7PWKVHY.js.map → devin-QMEM3OFA.js.map} +0 -0
  124. /package/dist/{doctor-GAP27PP2.js.map → doctor-H6XXAR63.js.map} +0 -0
  125. /package/dist/{droid-DTO5POTK.js.map → droid-MOKV53J4.js.map} +0 -0
  126. /package/dist/{gemini-cli-RBIG6U2F.js.map → gemini-cli-47ZHCOZR.js.map} +0 -0
  127. /package/dist/{goose-VGNOP5J2.js.map → goose-4EI5MYTI.js.map} +0 -0
  128. /package/dist/{grok-cli-2RFBK6J3.js.map → grok-cli-QYQPDSVB.js.map} +0 -0
  129. /package/dist/{hermes-NUKFWZI5.js.map → hermes-F75OSK3Y.js.map} +0 -0
  130. /package/dist/{hook-XPR3AHDI.js.map → hook-GIQTUDMN.js.map} +0 -0
  131. /package/dist/{install-O32TDIZP.js.map → install-T27662FW.js.map} +0 -0
  132. /package/dist/{jetbrains-copilot-FXZ5AOTS.js.map → jetbrains-copilot-ZGIWI6YV.js.map} +0 -0
  133. /package/dist/{junie-TSXIZSCE.js.map → junie-DIFN2P22.js.map} +0 -0
  134. /package/dist/{kilo-JLH3KVZJ.js.map → kilo-EMZJBEBB.js.map} +0 -0
  135. /package/dist/{kilo-cli-5W36VJQZ.js.map → kilo-cli-S3GXBPAE.js.map} +0 -0
  136. /package/dist/{kimi-R62W7HKZ.js.map → kimi-IQJOIY6B.js.map} +0 -0
  137. /package/dist/{kiro-AUJMGIBL.js.map → kiro-BYX4HEAJ.js.map} +0 -0
  138. /package/dist/{leaderboard-YWMOSJBC.js.map → leaderboard-CIMQBOUS.js.map} +0 -0
  139. /package/dist/{mimo-code-PGLFFVER.js.map → mimo-code-7R53QDHB.js.map} +0 -0
  140. /package/dist/{mistral-vibe-36CZVQNQ.js.map → mistral-vibe-LHJ55FSB.js.map} +0 -0
  141. /package/dist/{mux-HWL4N5KH.js.map → mux-NYCNGL43.js.map} +0 -0
  142. /package/dist/{nemoclaw-QPHETUXM.js.map → nemoclaw-WSIPSE7U.js.map} +0 -0
  143. /package/dist/{omp-3TFMTJ5U.js.map → omp-562NK5BJ.js.map} +0 -0
  144. /package/dist/{open-interpreter-UTBKE2EH.js.map → open-interpreter-I2CNOEXY.js.map} +0 -0
  145. /package/dist/{openclaw-RYFO5TLY.js.map → openclaw-7EYBQS4R.js.map} +0 -0
  146. /package/dist/{opencode-JX7GBE5Q.js.map → opencode-YS4WX2E2.js.map} +0 -0
  147. /package/dist/{openhands-AZW4PXJ3.js.map → openhands-QMYIKNOS.js.map} +0 -0
  148. /package/dist/{package-2KKUGZFS.js.map → package-LIPZKHAQ.js.map} +0 -0
  149. /package/dist/{pi-MRI3EBWU.js.map → pi-644FIN3A.js.map} +0 -0
  150. /package/dist/{qwen-code-ISR6BEET.js.map → qwen-code-STDMX7EM.js.map} +0 -0
  151. /package/dist/{roo-code-6TSCME4R.js.map → roo-code-DLPIHHQ6.js.map} +0 -0
  152. /package/dist/{serve-EPRN7F2X.js.map → serve-ABTO2NA2.js.map} +0 -0
  153. /package/dist/{status-B2PG6YKR.js.map → status-J7SOUH7O.js.map} +0 -0
  154. /package/dist/{statusline-5ERFMYSM.js.map → statusline-QF4G724E.js.map} +0 -0
  155. /package/dist/{telemetry-ZMCAWBWB.js.map → telemetry-EICCFEIF.js.map} +0 -0
  156. /package/dist/{trae-7KDCYIMN.js.map → trae-UOYD6JZZ.js.map} +0 -0
  157. /package/dist/{uninstall-M76BHLTH.js.map → uninstall-NJNNZZZY.js.map} +0 -0
  158. /package/dist/{upgrade-JLSCNAQA.js.map → upgrade-TIBUOQNM.js.map} +0 -0
  159. /package/dist/{usage-5I72HWCR.js.map → usage-VEVBWPLS.js.map} +0 -0
  160. /package/dist/{usage-event-HIX4ZI45.js.map → usage-event-GRQE7XWT.js.map} +0 -0
  161. /package/dist/{vscode-copilot-LILHAPJI.js.map → vscode-copilot-NIMH2DGU.js.map} +0 -0
  162. /package/dist/{warp-KJUCWEA3.js.map → warp-QYJGKURM.js.map} +0 -0
  163. /package/dist/{windsurf-5TGGQR5I.js.map → windsurf-75LLZ37C.js.map} +0 -0
  164. /package/dist/{zed-EL3JCZ25.js.map → zed-HKAZXEJW.js.map} +0 -0
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  REGISTERED_PLATFORM_IDS
4
- } from "./chunk-KA55FISM.js";
4
+ } from "./chunk-SILKSP2Y.js";
5
5
  import {
6
6
  CONFIG_PATCH_SEGMENT_RE,
7
7
  configPatchNamespaceViolation,
@@ -12,12 +12,162 @@ import {
12
12
  MANAGED_BLOCK_BEGIN_TOKEN,
13
13
  MANAGED_BLOCK_END_TOKEN,
14
14
  MEMORY_CONTENT_HARD_CAP_BYTES
15
- } from "./chunk-M2H7JURF.js";
15
+ } from "./chunk-UMQ6NBQR.js";
16
16
  import {
17
17
  CONNECTOR_ID_RE,
18
18
  isValidConnectorId
19
19
  } from "./chunk-GZGLCCEE.js";
20
20
 
21
+ // src/core/package-metadata.ts
22
+ import { AsyncLocalStorage } from "async_hooks";
23
+ import { existsSync, readFileSync } from "fs";
24
+ import { dirname, join, resolve } from "path";
25
+ var GENERIC_PACKAGE_BASENAMES = /* @__PURE__ */ new Set([
26
+ "mcp",
27
+ "server",
28
+ "mcp-server",
29
+ "connector",
30
+ "tool",
31
+ "tools",
32
+ "cli"
33
+ ]);
34
+ var PACKAGE_METADATA_CONTEXT = new AsyncLocalStorage();
35
+ function kebab(raw) {
36
+ return raw.trim().replace(/^@/, "").replace(/[\\/_.\s]+/g, "-").replace(/[^a-zA-Z0-9-]+/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
37
+ }
38
+ function scopedPackageParts(packageName) {
39
+ const raw = packageName.trim();
40
+ if (raw.startsWith("@")) {
41
+ const [scope, basename] = raw.slice(1).split("/");
42
+ return { scope: scope ? kebab(scope) : void 0, basename: basename ?? "" };
43
+ }
44
+ return { basename: raw };
45
+ }
46
+ function cleanMcpBasename(raw) {
47
+ let name = kebab(raw);
48
+ name = name.replace(/^mcp-server-/, "");
49
+ name = name.replace(/^server-/, "");
50
+ name = name.replace(/-mcp-server$/, "");
51
+ name = name.replace(/-mcp$/, "");
52
+ name = name.replace(/-server$/, "");
53
+ return kebab(name);
54
+ }
55
+ function isGeneric(name) {
56
+ return !name || GENERIC_PACKAGE_BASENAMES.has(name);
57
+ }
58
+ function cleanString(value) {
59
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
60
+ }
61
+ function objectKeys(value) {
62
+ if (!value || typeof value !== "object" || Array.isArray(value)) return [];
63
+ return Object.keys(value).filter((key) => key.trim());
64
+ }
65
+ function packageBinName(bin, packageName) {
66
+ if (typeof bin === "string") {
67
+ return packageName ? deriveHostAliasFromPackageName(packageName) : void 0;
68
+ }
69
+ const keys = objectKeys(bin);
70
+ if (keys.length === 0) return void 0;
71
+ if (keys.length === 1) return keys[0];
72
+ const packageAlias = packageName ? deriveHostAliasFromPackageName(packageName) : void 0;
73
+ if (packageAlias && keys.includes(packageAlias)) return packageAlias;
74
+ const unscoped = packageName?.startsWith("@") ? packageName.split("/")[1] : packageName;
75
+ const cleanUnscoped = unscoped ? cleanMcpBasename(unscoped) : void 0;
76
+ if (cleanUnscoped && keys.includes(cleanUnscoped)) return cleanUnscoped;
77
+ return void 0;
78
+ }
79
+ function currentConnectorPackageMetadata() {
80
+ return PACKAGE_METADATA_CONTEXT.getStore();
81
+ }
82
+ async function withConnectorPackageMetadata(metadata, run) {
83
+ if (!metadata || Object.keys(metadata).length === 0) return run();
84
+ return PACKAGE_METADATA_CONTEXT.run(metadata, run);
85
+ }
86
+ function findNearestPackageJson(startDir) {
87
+ let dir = resolve(startDir);
88
+ for (; ; ) {
89
+ const candidate = join(dir, "package.json");
90
+ if (existsSync(candidate)) return candidate;
91
+ const parent = dirname(dir);
92
+ if (parent === dir) return void 0;
93
+ dir = parent;
94
+ }
95
+ }
96
+ function readConnectorPackageMetadataFromPackageJson(packageJsonPath) {
97
+ const parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
98
+ const packageName = cleanString(parsed.name);
99
+ const version = cleanString(parsed.version);
100
+ const mcp = parsed.mcp && typeof parsed.mcp === "object" && !Array.isArray(parsed.mcp) ? parsed.mcp : void 0;
101
+ const mcpName = cleanString(parsed.mcpName) ?? cleanString(mcp?.mcpName) ?? cleanString(mcp?.name);
102
+ const bin = packageBinName(parsed.bin, packageName);
103
+ const identity = {
104
+ ...packageName ? { packageName } : {},
105
+ ...mcpName ? { mcpName } : {},
106
+ ...bin ? { bin } : {}
107
+ };
108
+ return {
109
+ ...Object.keys(identity).length > 0 ? { mcp: identity } : {},
110
+ ...version ? { version } : {}
111
+ };
112
+ }
113
+ function readConnectorPackageMetadataNearFile(filePath) {
114
+ const packageJsonPath = findNearestPackageJson(dirname(filePath));
115
+ if (!packageJsonPath) return void 0;
116
+ try {
117
+ const metadata = readConnectorPackageMetadataFromPackageJson(packageJsonPath);
118
+ return Object.keys(metadata).length > 0 ? metadata : void 0;
119
+ } catch {
120
+ return void 0;
121
+ }
122
+ }
123
+ function deriveHostAliasFromPackageName(packageName) {
124
+ const { scope, basename } = scopedPackageParts(packageName);
125
+ const fromBasename = cleanMcpBasename(basename);
126
+ if (!isGeneric(fromBasename)) return fromBasename;
127
+ const fromScope = scope ? cleanMcpBasename(scope) : void 0;
128
+ return isGeneric(fromScope) ? void 0 : fromScope;
129
+ }
130
+ function deriveHostAliasFromMcpName(mcpName) {
131
+ const [namespace, name] = mcpName.trim().split("/");
132
+ const fromName = cleanMcpBasename(name ?? namespace ?? "");
133
+ if (!isGeneric(fromName)) return fromName;
134
+ const namespaceParts = (namespace ?? "").split(".").filter(Boolean);
135
+ const fromNamespace = cleanMcpBasename(namespaceParts.at(-1) ?? "");
136
+ return isGeneric(fromNamespace) ? void 0 : fromNamespace;
137
+ }
138
+ function inferNpmPackageFromServer(server) {
139
+ if (!server || server.transport !== "stdio") return void 0;
140
+ if (typeof server.command !== "string" || server.command.trim() === "") {
141
+ return void 0;
142
+ }
143
+ const runner = kebab(server.command.split(/[\\/]/).pop() ?? server.command);
144
+ if (!["npx", "npm", "pnpm", "yarn", "bun"].includes(runner)) return void 0;
145
+ const args = server.args ?? [];
146
+ for (let i = 0; i < args.length; i += 1) {
147
+ const arg = args[i];
148
+ if (arg === "--") continue;
149
+ if (arg === "exec" || arg === "dlx" || arg === "x") continue;
150
+ if (arg === "-y" || arg === "--yes" || arg === "--no-install") continue;
151
+ if (arg === "--package" || arg === "-p") {
152
+ i += 1;
153
+ continue;
154
+ }
155
+ if (arg.startsWith("-")) continue;
156
+ return arg;
157
+ }
158
+ return void 0;
159
+ }
160
+ function resolveMcpPackageIdentity(input) {
161
+ const packageName = input.mcp?.packageName ?? inferNpmPackageFromServer(input.server);
162
+ const hostAlias = input.mcp?.hostAlias ?? (packageName ? deriveHostAliasFromPackageName(packageName) : void 0) ?? (input.mcp?.mcpName ? deriveHostAliasFromMcpName(input.mcp.mcpName) : void 0) ?? (input.mcp?.bin ? cleanMcpBasename(input.mcp.bin) : void 0);
163
+ return {
164
+ ...packageName ? { packageName } : {},
165
+ ...input.mcp?.mcpName ? { mcpName: input.mcp.mcpName } : {},
166
+ ...input.mcp?.bin ? { bin: input.mcp.bin } : {},
167
+ ...hostAlias ? { hostAlias } : {}
168
+ };
169
+ }
170
+
21
171
  // src/core/define-connector.ts
22
172
  import { isAbsolute, normalize } from "path";
23
173
 
@@ -79,9 +229,22 @@ function defineConnector(config) {
79
229
  if (!config || typeof config !== "object") {
80
230
  throw new ConnectorConfigError("config must be an object");
81
231
  }
82
- if (!isValidConnectorId(config.id)) {
232
+ const packageMetadata = currentConnectorPackageMetadata();
233
+ const packageIdentity = packageMetadata?.mcp;
234
+ if (packageIdentity && Object.keys(packageIdentity).length > 0) {
235
+ config = {
236
+ ...config,
237
+ mcp: {
238
+ ...packageIdentity,
239
+ ...config.mcp
240
+ }
241
+ };
242
+ }
243
+ const mcpIdentity = resolveMcpPackageIdentity(config);
244
+ const connectorId = config.id ?? mcpIdentity.hostAlias;
245
+ if (!isValidConnectorId(connectorId)) {
83
246
  throw new ConnectorConfigError(
84
- `id must be kebab-case matching ${CONNECTOR_ID_RE} (got ${JSON.stringify(config.id)})`
247
+ `id must be kebab-case matching ${CONNECTOR_ID_RE} or derivable from mcp/package metadata (got ${JSON.stringify(config.id)})`
85
248
  );
86
249
  }
87
250
  const hasCommands = Array.isArray(config.commands) && config.commands.length > 0;
@@ -136,9 +299,10 @@ function defineConnector(config) {
136
299
  const actions = normalizeActions(config.actions);
137
300
  const t = config.telemetry ?? {};
138
301
  const resolved = {
139
- id: config.id,
140
- displayName: config.displayName ?? config.id,
141
- version: config.version ?? "0.0.0",
302
+ id: connectorId,
303
+ ...Object.keys(mcpIdentity).length > 0 ? { mcp: mcpIdentity } : {},
304
+ displayName: config.displayName ?? connectorId,
305
+ version: config.version ?? packageMetadata?.version ?? "0.0.0",
142
306
  ...config.server ? { server: normalizeServer(config.server) } : {},
143
307
  hooks: config.hooks ?? {},
144
308
  hookEvents: declaredEvents(config.hooks),
@@ -478,6 +642,12 @@ function normalizeServer(server) {
478
642
  }
479
643
 
480
644
  export {
645
+ withConnectorPackageMetadata,
646
+ readConnectorPackageMetadataNearFile,
647
+ deriveHostAliasFromPackageName,
648
+ deriveHostAliasFromMcpName,
649
+ inferNpmPackageFromServer,
650
+ resolveMcpPackageIdentity,
481
651
  MCP_SERVER_SCHEMA_URL,
482
652
  MCPB_MANIFEST_VERSION,
483
653
  MCP_PROTOCOL_VERSION,
@@ -498,4 +668,4 @@ export {
498
668
  defineConfigPatch,
499
669
  defineNativeHook
500
670
  };
501
- //# sourceMappingURL=chunk-AY3VFNOH.js.map
671
+ //# sourceMappingURL=chunk-KJLFGQQM.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/package-metadata.ts","../src/core/define-connector.ts","../src/core/mcp-standard.ts"],"sourcesContent":["import { AsyncLocalStorage } from \"node:async_hooks\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nimport type {\n McpPackageIdentity,\n ResolvedMcpPackageIdentity,\n ServerDef,\n} from \"./types.js\";\n\nconst GENERIC_PACKAGE_BASENAMES = new Set([\n \"mcp\",\n \"server\",\n \"mcp-server\",\n \"connector\",\n \"tool\",\n \"tools\",\n \"cli\",\n]);\n\nexport interface ConnectorPackageMetadata {\n /** Package-derived MCP identity used to derive host aliases and install ids. */\n mcp?: McpPackageIdentity;\n /** package.json version used as the connector version default. */\n version?: string;\n}\n\nconst PACKAGE_METADATA_CONTEXT = new AsyncLocalStorage<ConnectorPackageMetadata>();\n\nfunction kebab(raw: string): string {\n return raw\n .trim()\n .replace(/^@/, \"\")\n .replace(/[\\\\/_.\\s]+/g, \"-\")\n .replace(/[^a-zA-Z0-9-]+/g, \"-\")\n .replace(/-{2,}/g, \"-\")\n .replace(/^-+|-+$/g, \"\")\n .toLowerCase();\n}\n\nfunction scopedPackageParts(packageName: string): {\n scope?: string;\n basename: string;\n} {\n const raw = packageName.trim();\n if (raw.startsWith(\"@\")) {\n const [scope, basename] = raw.slice(1).split(\"/\");\n return { scope: scope ? kebab(scope) : undefined, basename: basename ?? \"\" };\n }\n return { basename: raw };\n}\n\nfunction cleanMcpBasename(raw: string): string {\n let name = kebab(raw);\n name = name.replace(/^mcp-server-/, \"\");\n name = name.replace(/^server-/, \"\");\n name = name.replace(/-mcp-server$/, \"\");\n name = name.replace(/-mcp$/, \"\");\n name = name.replace(/-server$/, \"\");\n return kebab(name);\n}\n\nfunction isGeneric(name: string | undefined): boolean {\n return !name || GENERIC_PACKAGE_BASENAMES.has(name);\n}\n\nfunction cleanString(value: unknown): string | undefined {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction objectKeys(value: unknown): string[] {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return [];\n return Object.keys(value).filter((key) => key.trim());\n}\n\nfunction packageBinName(bin: unknown, packageName: string | undefined): string | undefined {\n if (typeof bin === \"string\") {\n return packageName ? deriveHostAliasFromPackageName(packageName) : undefined;\n }\n\n const keys = objectKeys(bin);\n if (keys.length === 0) return undefined;\n if (keys.length === 1) return keys[0];\n\n const packageAlias = packageName ? deriveHostAliasFromPackageName(packageName) : undefined;\n if (packageAlias && keys.includes(packageAlias)) return packageAlias;\n\n const unscoped = packageName?.startsWith(\"@\") ? packageName.split(\"/\")[1] : packageName;\n const cleanUnscoped = unscoped ? cleanMcpBasename(unscoped) : undefined;\n if (cleanUnscoped && keys.includes(cleanUnscoped)) return cleanUnscoped;\n\n return undefined;\n}\n\nexport function currentMcpPackageIdentity(): McpPackageIdentity | undefined {\n return currentConnectorPackageMetadata()?.mcp;\n}\n\nexport function currentConnectorPackageMetadata():\n | ConnectorPackageMetadata\n | undefined {\n return PACKAGE_METADATA_CONTEXT.getStore();\n}\n\nexport async function withConnectorPackageMetadata<T>(\n metadata: ConnectorPackageMetadata | undefined,\n run: () => Promise<T>,\n): Promise<T> {\n if (!metadata || Object.keys(metadata).length === 0) return run();\n return PACKAGE_METADATA_CONTEXT.run(metadata, run);\n}\n\nexport async function withMcpPackageIdentity<T>(\n identity: McpPackageIdentity | undefined,\n run: () => Promise<T>,\n): Promise<T> {\n if (!identity || Object.keys(identity).length === 0) return run();\n return withConnectorPackageMetadata({ mcp: identity }, run);\n}\n\nexport function findNearestPackageJson(startDir: string): string | undefined {\n let dir = resolve(startDir);\n for (;;) {\n const candidate = join(dir, \"package.json\");\n if (existsSync(candidate)) return candidate;\n\n const parent = dirname(dir);\n if (parent === dir) return undefined;\n dir = parent;\n }\n}\n\nexport function readMcpPackageIdentityFromPackageJson(\n packageJsonPath: string,\n): McpPackageIdentity {\n return readConnectorPackageMetadataFromPackageJson(packageJsonPath).mcp ?? {};\n}\n\nexport function readConnectorPackageMetadataFromPackageJson(\n packageJsonPath: string,\n): ConnectorPackageMetadata {\n const parsed = JSON.parse(readFileSync(packageJsonPath, \"utf8\")) as {\n name?: unknown;\n version?: unknown;\n mcpName?: unknown;\n mcp?: unknown;\n bin?: unknown;\n };\n const packageName = cleanString(parsed.name);\n const version = cleanString(parsed.version);\n const mcp =\n parsed.mcp && typeof parsed.mcp === \"object\" && !Array.isArray(parsed.mcp)\n ? (parsed.mcp as { name?: unknown; mcpName?: unknown })\n : undefined;\n const mcpName =\n cleanString(parsed.mcpName) ??\n cleanString(mcp?.mcpName) ??\n cleanString(mcp?.name);\n const bin = packageBinName(parsed.bin, packageName);\n\n const identity: McpPackageIdentity = {\n ...(packageName ? { packageName } : {}),\n ...(mcpName ? { mcpName } : {}),\n ...(bin ? { bin } : {}),\n };\n\n return {\n ...(Object.keys(identity).length > 0 ? { mcp: identity } : {}),\n ...(version ? { version } : {}),\n };\n}\n\nexport function readMcpPackageIdentityNearFile(\n filePath: string,\n): McpPackageIdentity | undefined {\n return readConnectorPackageMetadataNearFile(filePath)?.mcp;\n}\n\nexport function readConnectorPackageMetadataNearFile(\n filePath: string,\n): ConnectorPackageMetadata | undefined {\n const packageJsonPath = findNearestPackageJson(dirname(filePath));\n if (!packageJsonPath) return undefined;\n try {\n const metadata = readConnectorPackageMetadataFromPackageJson(packageJsonPath);\n return Object.keys(metadata).length > 0 ? metadata : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Derive the host-facing MCP server key from a package name. */\nexport function deriveHostAliasFromPackageName(\n packageName: string,\n): string | undefined {\n const { scope, basename } = scopedPackageParts(packageName);\n const fromBasename = cleanMcpBasename(basename);\n if (!isGeneric(fromBasename)) return fromBasename;\n const fromScope = scope ? cleanMcpBasename(scope) : undefined;\n return isGeneric(fromScope) ? undefined : fromScope;\n}\n\n/** Derive the host-facing MCP server key from an MCP registry name. */\nexport function deriveHostAliasFromMcpName(\n mcpName: string,\n): string | undefined {\n const [namespace, name] = mcpName.trim().split(\"/\");\n const fromName = cleanMcpBasename(name ?? namespace ?? \"\");\n if (!isGeneric(fromName)) return fromName;\n\n const namespaceParts = (namespace ?? \"\").split(\".\").filter(Boolean);\n const fromNamespace = cleanMcpBasename(namespaceParts.at(-1) ?? \"\");\n return isGeneric(fromNamespace) ? undefined : fromNamespace;\n}\n\n/** Infer an npm package from common npx-style stdio server definitions. */\nexport function inferNpmPackageFromServer(\n server: ServerDef | undefined,\n): string | undefined {\n if (!server || server.transport !== \"stdio\") return undefined;\n if (typeof server.command !== \"string\" || server.command.trim() === \"\") {\n return undefined;\n }\n const runner = kebab(server.command.split(/[\\\\/]/).pop() ?? server.command);\n if (![\"npx\", \"npm\", \"pnpm\", \"yarn\", \"bun\"].includes(runner)) return undefined;\n\n const args = server.args ?? [];\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i]!;\n if (arg === \"--\") continue;\n if (arg === \"exec\" || arg === \"dlx\" || arg === \"x\") continue;\n if (arg === \"-y\" || arg === \"--yes\" || arg === \"--no-install\") continue;\n if (arg === \"--package\" || arg === \"-p\") {\n i += 1;\n continue;\n }\n if (arg.startsWith(\"-\")) continue;\n return arg;\n }\n return undefined;\n}\n\nexport function resolveMcpPackageIdentity(input: {\n id?: string;\n mcp?: McpPackageIdentity;\n server?: ServerDef;\n}): ResolvedMcpPackageIdentity {\n const packageName =\n input.mcp?.packageName ?? inferNpmPackageFromServer(input.server);\n const hostAlias =\n input.mcp?.hostAlias ??\n (packageName ? deriveHostAliasFromPackageName(packageName) : undefined) ??\n (input.mcp?.mcpName\n ? deriveHostAliasFromMcpName(input.mcp.mcpName)\n : undefined) ??\n (input.mcp?.bin ? cleanMcpBasename(input.mcp.bin) : undefined);\n\n return {\n ...(packageName ? { packageName } : {}),\n ...(input.mcp?.mcpName ? { mcpName: input.mcp.mcpName } : {}),\n ...(input.mcp?.bin ? { bin: input.mcp.bin } : {}),\n ...(hostAlias ? { hostAlias } : {}),\n };\n}\n","/**\n * core/define-connector — the public write-once entry point.\n *\n * Validates a ConnectorConfig and normalizes it into a ResolvedConnector with\n * every optional field resolved to a default. Validation is intentionally\n * dependency-free (no zod) to keep the single-binary install lean.\n */\n\nimport { isAbsolute, normalize } from \"node:path\";\n\nimport type {\n ActionDef,\n CommandDef,\n ConfigPatchDef,\n ConnectorConfig,\n HookDefinition,\n HookEventName,\n HooksConfig,\n MemoryDef,\n NativeHookDef,\n PlatformId,\n PublishConfig,\n ResolvedConnector,\n SkillDef,\n StatuslineDef,\n SubagentDef,\n} from \"./types.js\";\nimport { REGISTERED_PLATFORM_IDS } from \"../adapters/registry.js\";\nimport { REGISTRY_NAMESPACE_RE } from \"./mcp-standard.js\";\nimport { CONNECTOR_ID_RE, isValidConnectorId } from \"./ids.js\";\nimport {\n currentConnectorPackageMetadata,\n resolveMcpPackageIdentity,\n} from \"./package-metadata.js\";\nimport {\n MANAGED_BLOCK_BEGIN_TOKEN,\n MANAGED_BLOCK_END_TOKEN,\n MEMORY_CONTENT_HARD_CAP_BYTES,\n} from \"./managed-block.js\";\nimport {\n CONFIG_PATCH_SEGMENT_RE,\n configPatchNamespaceViolation,\n isJsonValue,\n isValidConfigPatchKey,\n} from \"./config-patch-ledger.js\";\n\n/** kebab-case name regex shared by command/skill/subagent names. */\nconst SURFACE_NAME_RE = /^[a-z0-9][a-z0-9-]*$/;\n\n/** Max length of a skill description (Agent Skills open standard). */\nconst SKILL_DESCRIPTION_MAX = 1024;\n\n// NOTE: canonical ordering — append new events at the END (hookEvents ordering\n// is pinned by tests and feeds install-file ordering). Exported so the\n// hook-dispatch gate + Claude-bundle event sets can be drift-tested against it.\nexport const ALL_EVENTS: HookEventName[] = [\n \"SessionStart\",\n \"SessionEnd\",\n \"UserPromptSubmit\",\n \"PreToolUse\",\n \"PostToolUse\",\n \"PreCompact\",\n \"Stop\",\n \"Notification\",\n \"PermissionRequest\",\n \"PostToolUseFailure\",\n \"SubagentStart\",\n \"SubagentStop\",\n \"PostCompact\",\n];\n\n/** Thrown on an invalid connector configuration. */\nexport class ConnectorConfigError extends Error {\n constructor(message: string) {\n super(`Invalid connector config: ${message}`);\n this.name = \"ConnectorConfigError\";\n }\n}\n\nfunction declaredEvents(hooks: HooksConfig | undefined): HookEventName[] {\n if (!hooks) return [];\n return ALL_EVENTS.filter((e) => typeof hooks[e]?.handler === \"function\");\n}\n\n/**\n * Validate + normalize a connector definition.\n * Returns a ResolvedConnector that adapters and the CLI consume directly.\n */\nexport function defineConnector(config: ConnectorConfig): ResolvedConnector {\n if (!config || typeof config !== \"object\") {\n throw new ConnectorConfigError(\"config must be an object\");\n }\n\n const packageMetadata = currentConnectorPackageMetadata();\n const packageIdentity = packageMetadata?.mcp;\n if (packageIdentity && Object.keys(packageIdentity).length > 0) {\n config = {\n ...config,\n mcp: {\n ...packageIdentity,\n ...config.mcp,\n },\n };\n }\n\n const mcpIdentity = resolveMcpPackageIdentity(config);\n const connectorId = config.id ?? mcpIdentity.hostAlias;\n if (!isValidConnectorId(connectorId)) {\n throw new ConnectorConfigError(\n `id must be kebab-case matching ${CONNECTOR_ID_RE} or derivable from mcp/package metadata (got ${JSON.stringify(config.id)})`,\n );\n }\n const hasCommands = Array.isArray(config.commands) && config.commands.length > 0;\n const hasSkills = Array.isArray(config.skills) && config.skills.length > 0;\n const hasSubagents = Array.isArray(config.subagents) && config.subagents.length > 0;\n const hasMemory = Array.isArray(config.memory) && config.memory.length > 0;\n // A statusline (a HUD) is a legitimate sole payload — a connector whose whole\n // job is rendering a status line. SINGULAR (one per connector), so a plain\n // presence check (object with a render handler — validated in normalizeStatusline).\n const hasStatusline = config.statusline != null;\n // Actions (each a user-invokable run handler) are a legitimate sole payload —\n // a connector whose whole job is shipping dispatchable actions.\n const hasActions = Array.isArray(config.actions) && config.actions.length > 0;\n // A platform-scoped nativeHooks declaration is a legitimate sole payload\n // (a hooks-only connector wired entirely through native passthrough events).\n const hasNativeHooks = Object.values(config.platforms ?? {}).some(\n (override) =>\n override?.nativeHooks != null && Object.keys(override.nativeHooks).length > 0,\n );\n // Likewise a platform-scoped configPatch declaration (a connector whose whole\n // job is asserting a host config key, e.g. an experimental feature flag).\n const hasConfigPatch = Object.values(config.platforms ?? {}).some(\n (override) => Array.isArray(override?.configPatch) && override.configPatch.length > 0,\n );\n if (\n !config.server &&\n !config.hooks &&\n !hasCommands &&\n !hasSkills &&\n !hasSubagents &&\n !hasMemory &&\n !hasStatusline &&\n !hasActions &&\n !hasNativeHooks &&\n !hasConfigPatch\n ) {\n throw new ConnectorConfigError(\n \"a connector must declare at least one of `server`, `hooks`, `commands`, `skills`, `subagents`, `memory`, `statusline`, `actions`, \" +\n \"or a per-platform `nativeHooks` / `configPatch` declaration\",\n );\n }\n\n if (config.server) {\n const s = config.server;\n if (s.transport === \"stdio\") {\n if (!s.command || typeof s.command !== \"string\") {\n throw new ConnectorConfigError(\n \"server.command is required for stdio transport\",\n );\n }\n } else {\n if (!s.url || typeof s.url !== \"string\") {\n throw new ConnectorConfigError(\n `server.url is required for ${s.transport} transport`,\n );\n }\n }\n }\n\n // Validate hook handlers are functions, plus any per-host override map.\n if (config.hooks) {\n for (const ev of ALL_EVENTS) {\n const def = config.hooks[ev];\n if (def != null && typeof def.handler !== \"function\") {\n throw new ConnectorConfigError(`hooks.${ev}.handler must be a function`);\n }\n // Per-host override map: every key must be a registered platform id and\n // every entry's handler a function (author-time hard error, not skip-warn).\n validateHostsMap(def?.hosts, `hooks.${ev}.hosts`, \"handler\");\n }\n }\n\n // Validate per-platform native passthrough hooks (handlers live in this same\n // config module, exactly like normalized hooks — the resolved connector keeps\n // `platforms` verbatim, so live handlers survive resolution and are recovered\n // at runtime by re-importing the module via the registry's modulePath).\n validateNativeHooks(config.platforms);\n\n // Validate per-platform declarative config patches (pure JSON — persisted\n // whole; semantics are FIXED set-if-absent/skip-warn, so only the shape is\n // validated here; the host adapter enforces its sensitive-key denylist).\n validateConfigPatches(config.platforms);\n\n const commands = normalizeCommands(config.commands);\n const skills = normalizeSkills(config.skills);\n const subagents = normalizeSubagents(config.subagents);\n const memory = normalizeMemory(config.memory);\n const statusline = normalizeStatusline(config.statusline);\n const actions = normalizeActions(config.actions);\n\n const t = config.telemetry ?? {};\n\n const resolved: ResolvedConnector = {\n id: connectorId,\n ...(Object.keys(mcpIdentity).length > 0 ? { mcp: mcpIdentity } : {}),\n displayName: config.displayName ?? connectorId,\n version: config.version ?? packageMetadata?.version ?? \"0.0.0\",\n ...(config.server ? { server: normalizeServer(config.server) } : {}),\n hooks: config.hooks ?? {},\n hookEvents: declaredEvents(config.hooks),\n telemetry: {\n enabled: t.enabled ?? true,\n modelFamilyHint: t.modelFamilyHint ?? \"auto\",\n measureToolDefs: t.measureToolDefs ?? true,\n // OPT-IN: host-native turn-usage capture is OFF unless explicitly enabled\n // in config (or forced on at install via AGENT_CONNECTOR_HOST_NATIVE=1).\n hostNativeUsage: t.hostNativeUsage ?? false,\n store: t.store ?? \"ndjson\",\n calibration: {\n anthropicCountTokens: t.calibration?.anthropicCountTokens ?? false,\n },\n },\n commands,\n skills,\n subagents,\n memory,\n ...(statusline ? { statusline } : {}),\n actions,\n platforms: config.platforms ?? {},\n targets: config.targets ?? \"auto\",\n ...(config.publish ? { publish: normalizePublish(config.publish) } : {}),\n };\n\n return resolved;\n}\n\n/** The 13 normalized event names, for the nativeHooks collision check. */\nconst NORMALIZED_EVENT_SET: ReadonlySet<string> = new Set(ALL_EVENTS);\n\n/**\n * Validate a per-host override map (`hosts?:`) declared on a hook definition or\n * on the statusline. Shared by the hook-validation loop and normalizeStatusline:\n * - the value must be a plain object keyed by platform id;\n * - every key MUST be a REGISTERED platform id (REGISTERED_PLATFORM_IDS) —\n * an unknown id is an author-time ConnectorConfigError (NOT a skip-warn:\n * a typo'd host would otherwise silently never fire);\n * - every entry's implementation field (`handler` for hooks, `render` for\n * statusline, `run` for actions) MUST be a function (it is re-imported from\n * the connector module at runtime, like the top-level handler/render/run).\n * `undefined` (no map) is valid and skipped.\n */\nfunction validateHostsMap(\n map: unknown,\n surfaceLabel: string,\n implField: \"handler\" | \"render\" | \"run\",\n): void {\n if (map == null) return;\n if (typeof map !== \"object\" || Array.isArray(map)) {\n throw new ConnectorConfigError(\n `${surfaceLabel} must be an object keyed by platform id`,\n );\n }\n for (const [platformId, entry] of Object.entries(map as Record<string, unknown>)) {\n if (!REGISTERED_PLATFORM_IDS.has(platformId as PlatformId)) {\n const valid = [...REGISTERED_PLATFORM_IDS].sort().join(\", \");\n throw new ConnectorConfigError(\n `unknown platform id \"${platformId}\" in hosts map for ${surfaceLabel}; valid ids: ${valid}`,\n );\n }\n if (\n entry == null ||\n typeof entry !== \"object\" ||\n typeof (entry as Record<string, unknown>)[implField] !== \"function\"\n ) {\n throw new ConnectorConfigError(\n `${surfaceLabel}.${platformId}.${implField} must be a function`,\n );\n }\n }\n}\n\n/**\n * Validate every `platforms[<id>].nativeHooks` declaration:\n * - the value must be an object keyed by HOST-NATIVE event name;\n * - an event name must NOT collide with the normalized {@link HookEventName}\n * union (those belong in the cross-platform `hooks` API, which gets\n * normalization, matcher evaluation, and HookResponse mapping);\n * - each handler must be a function (it is re-imported from the config module\n * at runtime, like normalized hook handlers);\n * - `matcher`, when present, must be a string (written verbatim into the\n * host's hook config — the host evaluates it).\n */\nfunction validateNativeHooks(platforms: ConnectorConfig[\"platforms\"]): void {\n if (platforms == null) return;\n for (const [platformId, override] of Object.entries(platforms)) {\n const native = override?.nativeHooks;\n if (native == null) continue;\n const where = `platforms.${platformId}.nativeHooks`;\n if (typeof native !== \"object\" || Array.isArray(native)) {\n throw new ConnectorConfigError(\n `${where} must be an object keyed by host-native event name`,\n );\n }\n for (const [event, def] of Object.entries(native)) {\n if (NORMALIZED_EVENT_SET.has(event)) {\n throw new ConnectorConfigError(\n `${where}.${event} collides with the normalized hook event \"${event}\"; ` +\n `declare it under \\`hooks.${event}\\` (the normalized, cross-platform hooks API) instead`,\n );\n }\n if (def == null || typeof def !== \"object\" || typeof def.handler !== \"function\") {\n throw new ConnectorConfigError(`${where}.${event}.handler must be a function`);\n }\n if (def.matcher !== undefined && typeof def.matcher !== \"string\") {\n throw new ConnectorConfigError(`${where}.${event}.matcher must be a string`);\n }\n }\n }\n}\n\n/**\n * Validate every `platforms[<id>].configPatch` declaration:\n * - the value must be an array of patch objects;\n * - `key` must be a dotted LEAF path whose segments match\n * {@link CONFIG_PATCH_SEGMENT_RE} — no dots-in-key, no array indices;\n * - `key` must not collide with the agent-connector-modeled namespace\n * (`hooks*` → hooks/nativeHooks; `mcpServers*` & friends → server/extra);\n * - duplicate keys within one platform's list are rejected (a duplicate\n * would double-apply / fight itself on refcounts);\n * - `value` must be JSON-serializable data (it is persisted whole in the\n * connector record and in the ownership ledger);\n * - `reason` is REQUIRED (printed in the install diff and every skip-warn);\n * - `docsUrl`, when present, must be a string.\n * The HOST-side sensitive-key denylist is deliberately NOT validated here —\n * it lives in (and is documented by) each supporting adapter.\n */\nfunction validateConfigPatches(platforms: ConnectorConfig[\"platforms\"]): void {\n if (platforms == null) return;\n for (const [platformId, override] of Object.entries(platforms)) {\n const patches = override?.configPatch;\n if (patches == null) continue;\n const where = `platforms.${platformId}.configPatch`;\n if (!Array.isArray(patches)) {\n throw new ConnectorConfigError(`${where} must be an array of patch objects`);\n }\n const seen = new Set<string>();\n patches.forEach((patch, i) => {\n if (patch == null || typeof patch !== \"object\" || Array.isArray(patch)) {\n throw new ConnectorConfigError(`${where}[${i}] must be an object`);\n }\n if (!isValidConfigPatchKey(patch.key)) {\n throw new ConnectorConfigError(\n `${where}[${i}].key must be a dotted LEAF path whose segments match ` +\n `${CONFIG_PATCH_SEGMENT_RE} (no dots-in-key, no array indices); ` +\n `got ${JSON.stringify(patch.key)}`,\n );\n }\n const violation = configPatchNamespaceViolation(patch.key);\n if (violation) {\n throw new ConnectorConfigError(`${where}[${i}].key ${violation}`);\n }\n if (seen.has(patch.key)) {\n throw new ConnectorConfigError(\n `${where}[${i}] duplicate key \"${patch.key}\"`,\n );\n }\n seen.add(patch.key);\n if (!isJsonValue(patch.value)) {\n throw new ConnectorConfigError(\n `${where}[${i}].value must be JSON-serializable data ` +\n `(string/finite number/boolean/null/array/plain object)`,\n );\n }\n if (typeof patch.reason !== \"string\" || patch.reason.trim() === \"\") {\n throw new ConnectorConfigError(\n `${where}[${i}].reason is required (a human-readable why, printed in ` +\n `the install diff and every skip-warn)`,\n );\n }\n if (patch.docsUrl !== undefined && typeof patch.docsUrl !== \"string\") {\n throw new ConnectorConfigError(`${where}[${i}].docsUrl must be a string`);\n }\n });\n }\n}\n\n/**\n * Validate the optional `publish` block (registry server.json + MCPB bundle\n * distribution metadata). Light, dependency-free: we only reject shapes that\n * would emit a clearly INVALID standard artifact. The per-format required-field\n * checks (e.g. server.json needs registryNamespace, mcpb needs author.name)\n * live in the emitters so a connector that never publishes pays nothing.\n */\nfunction normalizePublish(publish: PublishConfig): PublishConfig {\n if (typeof publish !== \"object\" || Array.isArray(publish)) {\n throw new ConnectorConfigError(\"publish must be an object\");\n }\n if (publish.registryNamespace !== undefined) {\n const ns = publish.registryNamespace;\n if (typeof ns !== \"string\" || !REGISTRY_NAMESPACE_RE.test(ns)) {\n throw new ConnectorConfigError(\n `publish.registryNamespace must be a reverse-DNS namespace matching ${REGISTRY_NAMESPACE_RE} ` +\n `(e.g. \"io.github.acme\" or \"com.acme\"); got ${JSON.stringify(ns)}`,\n );\n }\n }\n if (publish.packageName !== undefined && typeof publish.packageName !== \"string\") {\n throw new ConnectorConfigError(\"publish.packageName must be a string\");\n }\n if (publish.author !== undefined) {\n const a = publish.author;\n if (typeof a !== \"object\" || a == null || typeof a.name !== \"string\" || a.name === \"\") {\n throw new ConnectorConfigError(\"publish.author.name must be a non-empty string\");\n }\n }\n return { ...publish };\n}\n\n/** Validate a surface name (kebab-case) or throw a ConnectorConfigError. */\nfunction assertSurfaceName(\n surface: string,\n name: unknown,\n index: number,\n field = \"name\",\n): string {\n if (typeof name !== \"string\" || !SURFACE_NAME_RE.test(name)) {\n throw new ConnectorConfigError(\n `${surface}[${index}].${field} must be kebab-case matching ${SURFACE_NAME_RE} (got ${JSON.stringify(name)})`,\n );\n }\n return name;\n}\n\n/** Require a non-empty string field on a surface entry. */\nfunction assertNonEmptyString(\n surface: string,\n index: number,\n field: string,\n value: unknown,\n): string {\n if (typeof value !== \"string\" || value.length === 0) {\n throw new ConnectorConfigError(`${surface}[${index}].${field} must be a non-empty string`);\n }\n return value;\n}\n\n/** Detect a duplicate surface name within one array, throwing on collision. */\nfunction assertNoDuplicate(\n surface: string,\n seen: Set<string>,\n name: string,\n index: number,\n field = \"name\",\n): void {\n if (seen.has(name)) {\n throw new ConnectorConfigError(`${surface}[${index}] duplicate ${field} \"${name}\"`);\n }\n seen.add(name);\n}\n\nfunction normalizeCommands(input: CommandDef[] | undefined): CommandDef[] {\n if (input == null) return [];\n if (!Array.isArray(input)) {\n throw new ConnectorConfigError(\"commands must be an array\");\n }\n const seen = new Set<string>();\n return input.map((cmd, i) => {\n if (!cmd || typeof cmd !== \"object\") {\n throw new ConnectorConfigError(`commands[${i}] must be an object`);\n }\n const name = assertSurfaceName(\"commands\", cmd.name, i);\n assertNoDuplicate(\"commands\", seen, name, i);\n assertNonEmptyString(\"commands\", i, \"prompt\", cmd.prompt);\n // Pass through verbatim (content); arrays are content, not handlers.\n return { ...cmd, name };\n });\n}\n\nfunction normalizeSkills(input: SkillDef[] | undefined): SkillDef[] {\n if (input == null) return [];\n if (!Array.isArray(input)) {\n throw new ConnectorConfigError(\"skills must be an array\");\n }\n const seen = new Set<string>();\n return input.map((skill, i) => {\n if (!skill || typeof skill !== \"object\") {\n throw new ConnectorConfigError(`skills[${i}] must be an object`);\n }\n const name = assertSurfaceName(\"skills\", skill.name, i);\n assertNoDuplicate(\"skills\", seen, name, i);\n const description = assertNonEmptyString(\"skills\", i, \"description\", skill.description);\n if (description.length > SKILL_DESCRIPTION_MAX) {\n throw new ConnectorConfigError(\n `skills[${i}].description exceeds ${SKILL_DESCRIPTION_MAX} chars (got ${description.length})`,\n );\n }\n assertNonEmptyString(\"skills\", i, \"body\", skill.body);\n assertSafeResourceKeys(\"skills\", i, skill.resources);\n return { ...skill, name };\n });\n}\n\n/**\n * Validate every `skill.resources` key as a SAFE relative path that stays inside\n * the skill dir. Each resource is later written/removed via join(skillDir, rel)\n * by every adapter, so an unvalidated key like \"../../settings.json\" would\n * escape the skill dir → arbitrary file write/delete. Reject (throw) when a key\n * is empty/\".\", absolute, or normalizes to a path that begins with \"..\" or\n * contains a \"/..\" (or platform-sep) traversal segment.\n */\nfunction assertSafeResourceKeys(\n surface: string,\n index: number,\n resources: Record<string, string> | undefined,\n): void {\n if (resources == null) return;\n if (typeof resources !== \"object\" || Array.isArray(resources)) {\n throw new ConnectorConfigError(`${surface}[${index}].resources must be an object`);\n }\n for (const rel of Object.keys(resources)) {\n if (rel === \"\" || rel === \".\" || rel.trim() === \"\") {\n throw new ConnectorConfigError(\n `${surface}[${index}].resources key must be a non-empty relative path (got ${JSON.stringify(rel)})`,\n );\n }\n if (isAbsolute(rel)) {\n throw new ConnectorConfigError(\n `${surface}[${index}].resources key must be a relative path inside the skill dir, not absolute (got ${JSON.stringify(rel)})`,\n );\n }\n // Normalize with BOTH posix and native separators flattened so a Windows\n // \"..\\\\x\" or a posix \"../x\" is caught regardless of the host OS.\n const norm = normalize(rel.replace(/\\\\/g, \"/\"));\n const segs = norm.split(/[/\\\\]/);\n if (norm === \"..\" || norm.startsWith(\"../\") || norm.startsWith(\"..\\\\\") || segs.includes(\"..\")) {\n throw new ConnectorConfigError(\n `${surface}[${index}].resources key must not escape the skill dir via \"..\" (got ${JSON.stringify(rel)})`,\n );\n }\n }\n}\n\n/** Default name for a single-entry memory declaration. */\nconst MEMORY_DEFAULT_NAME = \"memory\";\n\n/**\n * Validate + normalize `memory` entries (the managed-block content surface).\n * - `name` defaults to \"memory\", then must be kebab-case and unique — it is\n * half of the block marker id (`<connectorId>/<name>`) and must stay stable;\n * - `content` must be a non-empty string, ≤ 16 KiB (hard cap — memory files\n * are injected into every prompt of every session on the host), and must\n * NOT contain the literal marker tokens `agent-connector:begin` /\n * `agent-connector:end` (they would corrupt marker scanning in the shared\n * file — rephrase the guidance instead). The 4 KiB SOFT budget is reported\n * at install time as a `warn` ChangeRecord, not a config error\n * (defineConnector has no warning channel).\n */\nfunction normalizeMemory(input: MemoryDef[] | undefined): MemoryDef[] {\n if (input == null) return [];\n if (!Array.isArray(input)) {\n throw new ConnectorConfigError(\"memory must be an array\");\n }\n const seen = new Set<string>();\n return input.map((entry, i) => {\n if (!entry || typeof entry !== \"object\" || Array.isArray(entry)) {\n throw new ConnectorConfigError(`memory[${i}] must be an object`);\n }\n const name =\n entry.name === undefined\n ? MEMORY_DEFAULT_NAME\n : assertSurfaceName(\"memory\", entry.name, i);\n assertNoDuplicate(\"memory\", seen, name, i);\n const content = assertNonEmptyString(\"memory\", i, \"content\", entry.content);\n const bytes = Buffer.byteLength(content, \"utf8\");\n if (bytes > MEMORY_CONTENT_HARD_CAP_BYTES) {\n throw new ConnectorConfigError(\n `memory[${i}].content exceeds the ${MEMORY_CONTENT_HARD_CAP_BYTES}-byte hard cap ` +\n `(got ${bytes} bytes); memory is inlined into every prompt of every targeted host — keep it terse`,\n );\n }\n for (const token of [MANAGED_BLOCK_BEGIN_TOKEN, MANAGED_BLOCK_END_TOKEN]) {\n if (content.includes(token)) {\n throw new ConnectorConfigError(\n `memory[${i}].content must not contain the literal marker token \"${token}\" ` +\n `(it would corrupt managed-block scanning in the shared memory file); rephrase the guidance`,\n );\n }\n }\n if (entry.description !== undefined && typeof entry.description !== \"string\") {\n throw new ConnectorConfigError(`memory[${i}].description must be a string`);\n }\n return { ...entry, name };\n });\n}\n\n/** Default name for the (singular) statusline declaration. */\nconst STATUSLINE_DEFAULT_NAME = \"statusline\";\n\n/**\n * Validate + normalize the SINGULAR `statusline` (a HUD handler surface):\n * - `render` MUST be a function (it is the renderer, re-imported at runtime\n * like a hook handler);\n * - `name` defaults to \"statusline\", then must be kebab-case (the shared\n * surface-name validator);\n * - `description`, when present, must be a string.\n * Returns undefined when no statusline is declared (it is optional and singular,\n * unlike the memory[] array).\n */\nfunction normalizeStatusline(\n input: StatuslineDef | undefined,\n): StatuslineDef | undefined {\n if (input == null) return undefined;\n if (typeof input !== \"object\" || Array.isArray(input)) {\n throw new ConnectorConfigError(\"statusline must be an object\");\n }\n if (typeof input.render !== \"function\") {\n throw new ConnectorConfigError(\"statusline.render must be a function\");\n }\n const name =\n input.name === undefined\n ? STATUSLINE_DEFAULT_NAME\n : assertSurfaceName(\"statusline\", input.name, 0);\n if (input.description !== undefined && typeof input.description !== \"string\") {\n throw new ConnectorConfigError(\"statusline.description must be a string\");\n }\n // Per-host render override map: registered platform ids only, each render a\n // function (author-time hard error, mirroring the hook hosts-map validation).\n validateHostsMap(input.hosts, \"statusline.hosts\", \"render\");\n return { ...input, name };\n}\n\n/**\n * Validate + normalize `actions` (the user-invokable action handler surface):\n * - the value must be an array;\n * - each entry's `id` must be kebab-case (the shared surface-name validator)\n * and UNIQUE within the connector (ConnectorConfigError on dup — the id is\n * the verb's positional arg, so a duplicate would be ambiguous);\n * - `run` MUST be a function (it is the handler, re-imported at runtime like a\n * hook handler / statusline render);\n * - `description`, when present, must be a string;\n * - the per-host `hosts:` override map is validated via the shared\n * validateHostsMap (registered platform ids only, each `run` a function).\n * Returns [] when no actions are declared (defaults applied, like the other\n * array surfaces).\n */\nfunction normalizeActions(input: ActionDef[] | undefined): ActionDef[] {\n if (input == null) return [];\n if (!Array.isArray(input)) {\n throw new ConnectorConfigError(\"actions must be an array\");\n }\n const seen = new Set<string>();\n return input.map((action, i) => {\n if (!action || typeof action !== \"object\" || Array.isArray(action)) {\n throw new ConnectorConfigError(`actions[${i}] must be an object`);\n }\n const id = assertSurfaceName(\"actions\", action.id, i, \"id\");\n assertNoDuplicate(\"actions\", seen, id, i, \"id\");\n if (typeof action.run !== \"function\") {\n throw new ConnectorConfigError(`actions[${i}].run must be a function`);\n }\n if (action.description !== undefined && typeof action.description !== \"string\") {\n throw new ConnectorConfigError(`actions[${i}].description must be a string`);\n }\n // Per-host run override map: registered platform ids only, each run a\n // function (author-time hard error, mirroring the statusline/hook hosts-map).\n validateHostsMap(action.hosts, `actions.${id}.hosts`, \"run\");\n return { ...action, id };\n });\n}\n\n/**\n * Typed identity helper for authoring a status line in its own module:\n * export const myStatusline = defineStatusline({ render: (ctx) => \"…\" });\n * Mirrors the (informal) defineX helpers; gives the developer full type\n * inference on {@link StatuslineContext} without importing the type by hand.\n */\nexport const defineStatusline = (def: StatuslineDef): StatuslineDef => def;\n\n// ─────────────────────────────────────────────────────────────────────────\n// Typed identity helpers (the `define*` authoring family)\n//\n// Each is a one-line identity function: it returns its argument UNCHANGED and\n// does NOT validate or mutate (validation still happens centrally in\n// defineConnector). Their only job is ergonomics — authoring a surface in its\n// own module with full type inference + autocomplete on the *Def shape, and a\n// single import site — mirroring the existing {@link defineStatusline}.\n// ─────────────────────────────────────────────────────────────────────────\n\n/**\n * Typed identity helper for authoring ONE normalized lifecycle hook in its own\n * module, EVENT-PARAMETERIZED so the handler's payload narrows to that event:\n *\n * export const onPre = defineHook(\"PreToolUse\", {\n * handler(evt) { evt.toolName // ← typed as a PreToolUseEvent, not the union\n * return { decision: \"deny\", reason: \"no\" };\n * },\n * });\n *\n * The leading `event` argument exists ONLY to infer `E`; the def is returned\n * unchanged (identity — validation still happens in defineConnector). Passing\n * `HookDefinition` without an event would widen the handler param to the full\n * {@link HookEventName} union and lose per-event narrowing, so the event tag is\n * required.\n */\nexport const defineHook = <E extends HookEventName>(\n event: E,\n def: HookDefinition<E>,\n): HookDefinition<E> => {\n void event; // tag-only: used solely to infer E (the def carries no event field)\n return def;\n};\n\n/**\n * Typed identity helper for authoring a slash {@link CommandDef} in its own\n * module. Returns the def unchanged (kebab-case name + prompt are validated by\n * defineConnector when the connector is assembled).\n */\nexport const defineCommand = (def: CommandDef): CommandDef => def;\n\n/**\n * Typed identity helper for authoring an Agent {@link SkillDef} in its own\n * module. Returns the def unchanged (name/description/body + safe resource keys\n * are validated by defineConnector).\n */\nexport const defineSkill = (def: SkillDef): SkillDef => def;\n\n/**\n * Typed identity helper for authoring a {@link SubagentDef} in its own module.\n * Returns the def unchanged (name/description/prompt validated by defineConnector).\n */\nexport const defineSubagent = (def: SubagentDef): SubagentDef => def;\n\n/**\n * Typed identity helper for authoring a {@link MemoryDef} (standing-guidance\n * managed block) in its own module. Returns the def unchanged (name/content +\n * byte budget + marker-token guard validated by defineConnector).\n */\nexport const defineMemory = (def: MemoryDef): MemoryDef => def;\n\n/**\n * Typed identity helper for authoring a user-invokable {@link ActionDef} in its\n * own module. Returns the def unchanged (kebab-case unique id + run-is-function\n * + the per-host hosts map validated by defineConnector when the connector is\n * assembled).\n */\nexport const defineAction = (def: ActionDef): ActionDef => def;\n\n/**\n * Typed identity helper for authoring a declarative {@link ConfigPatchDef}\n * (set-if-absent host-config key patch) in its own module. Returns the def\n * unchanged (leaf-path grammar + namespace guard + required reason validated by\n * defineConnector when it appears under `platforms[<id>].configPatch`).\n */\nexport const defineConfigPatch = (def: ConfigPatchDef): ConfigPatchDef => def;\n\n/**\n * Typed identity helper for authoring a {@link NativeHookDef} (host-native\n * passthrough hook) in its own module. Returns the def unchanged (event-name\n * collision + handler-is-function validated by defineConnector when it appears\n * under `platforms[<id>].nativeHooks`).\n */\nexport const defineNativeHook = (def: NativeHookDef): NativeHookDef => def;\n\nfunction normalizeSubagents(input: SubagentDef[] | undefined): SubagentDef[] {\n if (input == null) return [];\n if (!Array.isArray(input)) {\n throw new ConnectorConfigError(\"subagents must be an array\");\n }\n const seen = new Set<string>();\n return input.map((agent, i) => {\n if (!agent || typeof agent !== \"object\") {\n throw new ConnectorConfigError(`subagents[${i}] must be an object`);\n }\n const name = assertSurfaceName(\"subagents\", agent.name, i);\n assertNoDuplicate(\"subagents\", seen, name, i);\n assertNonEmptyString(\"subagents\", i, \"description\", agent.description);\n assertNonEmptyString(\"subagents\", i, \"prompt\", agent.prompt);\n return { ...agent, name };\n });\n}\n\nfunction normalizeServer(server: ConnectorConfig[\"server\"]): ResolvedConnector[\"server\"] {\n if (!server) return undefined;\n const wrapDefault = server.transport === \"stdio\";\n return {\n ...server,\n enabled: server.enabled ?? true,\n tools: server.tools ?? { include: [\"*\"] },\n wrapForTelemetry: server.wrapForTelemetry ?? wrapDefault,\n };\n}\n","/**\n * core/mcp-standard — pinned literals + guards for the official MCP standards\n * agent-connector EMITS (registry server.json, MCPB bundle) or SPEAKS (the\n * connection-lifecycle wire used by `doctor --probe`).\n *\n * Each pinned constant is the CURRENT released value verified 2026-06-05 against\n * the upstream spec/schema. They are deliberately centralized + annotated\n * MUST-VERIFY-AT-IMPLEMENTATION: a newer spec revision can supersede any of them\n * without breaking us, so the bump is a one-line change here, never scattered.\n *\n * Sources:\n * • server.schema.json 2025-12-11 — https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\n * • MCPB manifest 0.3 — github.com/anthropics/mcpb (MANIFEST.md)\n * • MCP protocol 2025-11-25 — modelcontextprotocol.io/specification/2025-11-25\n * (latest RELEASED revision. 2026-07-28 is a release-candidate only — do NOT\n * advance to it until it publishes as a stable dated revision. The probe\n * offers this version but ACCEPTS whatever a server negotiates, so the\n * offered literal being stale never breaks interop — only this constant.)\n */\n\nimport type { Transport } from \"./types.js\";\n\n/** Registry server.json JSON Schema URL (released 2025-12-11). MUST-VERIFY on bump. */\nexport const MCP_SERVER_SCHEMA_URL =\n \"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json\";\n\n/** Current MCPB bundle manifest_version (anthropics/mcpb). MUST-VERIFY on bump. */\nexport const MCPB_MANIFEST_VERSION = \"0.3\";\n\n/**\n * Latest RELEASED MCP protocol revision `doctor --probe` offers in `initialize`.\n * Current = 2025-11-25. MUST-VERIFY on bump; stay on the latest *released*\n * revision (2026-07-28 is RC-only as of 2026-06). Negotiation accepts whatever\n * the server returns, so this is the offered value, not a hard requirement.\n */\nexport const MCP_PROTOCOL_VERSION = \"2025-11-25\";\n\n/** Default npm registry base URL stamped into server.json npm packages. */\nexport const NPM_REGISTRY_BASE_URL = \"https://registry.npmjs.org\";\n\n/**\n * server.json transport.type enum — the EXACT values the 2025-12-11 schema\n * accepts (packages[].transport.type and remotes[].type). Our `http` Transport\n * maps to the spec slug \"streamable-http\"; \"ws\" is non-spec (see below).\n */\nexport type RegistryTransportType = \"stdio\" | \"streamable-http\" | \"sse\";\n\n/**\n * Map our {@link Transport} union to the registry/server.json transport slug.\n * Returns null for \"ws\" — WebSocket is NOT a spec transport (it can only exist\n * as a vendor custom transport, e.g. Claude Code's non-spec type:\"ws\"), so a\n * conformant artifact must REJECT it rather than emit an invalid type. The spec\n * defines exactly stdio + streamable-http, with sse the deprecated HTTP+SSE.\n */\nexport function registryTransportType(transport: Transport): RegistryTransportType | null {\n switch (transport) {\n case \"stdio\":\n return \"stdio\";\n case \"http\":\n return \"streamable-http\";\n case \"sse\":\n return \"sse\";\n case \"ws\":\n return null;\n }\n}\n\n/**\n * Is `v` a CONCRETE version the MCP Registry accepts? The registry rejects\n * ranges (\"^1.2.3\", \"~1.2.3\", \">=1.2.3\", \"1.x\", \"1.*\"); only a pinned SemVer\n * (optionally with a -prerelease / +build suffix) is valid. \"0.0.0\" is concrete\n * (so it passes this guard) but is the unset placeholder — callers warn on it\n * separately via {@link isPlaceholderVersion}.\n */\nexport function isConcreteSemver(v: string): boolean {\n return /^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$/.test(v);\n}\n\n/** The unset default version a connector ships with until the dev sets a real one. */\nexport function isPlaceholderVersion(v: string): boolean {\n return v === \"0.0.0\";\n}\n\n/**\n * Reverse-DNS registry namespace pattern (the part BEFORE the \"/\" in a\n * server.json `name`). The full name regex is\n * `^[a-zA-Z0-9.-]+/[a-zA-Z0-9._-]+$`; the namespace side allows letters, digits,\n * dots and hyphens (NO underscore) — e.g. \"io.github.acme\" or \"com.acme\".\n */\nexport const REGISTRY_NAMESPACE_RE = /^[a-zA-Z0-9.-]+$/;\n\n/** The full server.json `name` regex (namespace \"/\" server-name), per the schema. */\nexport const REGISTRY_NAME_RE = /^[a-zA-Z0-9.-]+\\/[a-zA-Z0-9._-]+$/;\n"],"mappings":"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","names":[]}
@@ -1,7 +1,9 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- defineConnector
4
- } from "./chunk-AY3VFNOH.js";
3
+ defineConnector,
4
+ readConnectorPackageMetadataNearFile,
5
+ withConnectorPackageMetadata
6
+ } from "./chunk-KJLFGQQM.js";
5
7
  import {
6
8
  assertNoSymlinkInPath,
7
9
  connectorDir,
@@ -43,21 +45,29 @@ async function loadConnectorFromPath(path) {
43
45
  if (modulePath.endsWith(".json")) {
44
46
  const text = readFileSync(modulePath, "utf8");
45
47
  const config = JSON.parse(text);
46
- const connector2 = defineConnector(config);
48
+ const connector2 = await withConnectorPackageMetadata(
49
+ readConnectorPackageMetadataNearFile(modulePath),
50
+ async () => defineConnector(config)
51
+ );
47
52
  return { connector: connector2, modulePath };
48
53
  }
49
54
  const moduleUrl = pathToFileURL(modulePath).href;
50
- const mod = await import(
51
- /* @vite-ignore */
52
- moduleUrl
55
+ const connector = await withConnectorPackageMetadata(
56
+ readConnectorPackageMetadataNearFile(modulePath),
57
+ async () => {
58
+ const mod = await import(
59
+ /* @vite-ignore */
60
+ moduleUrl
61
+ );
62
+ const exported = mod.default;
63
+ if (exported == null) {
64
+ throw new Error(
65
+ `Connector module has no default export: ${modulePath}`
66
+ );
67
+ }
68
+ return isResolvedConnector(exported) ? exported : defineConnector(exported);
69
+ }
53
70
  );
54
- const exported = mod.default;
55
- if (exported == null) {
56
- throw new Error(
57
- `Connector module has no default export: ${modulePath}`
58
- );
59
- }
60
- const connector = isResolvedConnector(exported) ? exported : defineConnector(exported);
61
71
  return { connector, modulePath };
62
72
  }
63
73
  function serializablePlatforms(platforms) {
@@ -83,6 +93,7 @@ function registerConnector(connector, modulePath, scope) {
83
93
  id: connector.id,
84
94
  displayName: connector.displayName,
85
95
  version: connector.version,
96
+ ...connector.mcp ? { mcp: connector.mcp } : {},
86
97
  modulePath: resolve(modulePath),
87
98
  telemetry: connector.telemetry,
88
99
  hookEvents: connector.hookEvents,
@@ -143,6 +154,7 @@ function connectorFromMeta(meta) {
143
154
  id: meta.id,
144
155
  displayName: meta.displayName,
145
156
  version: meta.version,
157
+ ...meta.mcp ? { mcp: meta.mcp } : {},
146
158
  ...meta.server ? { server: meta.server } : {},
147
159
  hooks: {},
148
160
  hookEvents: meta.hookEvents ?? [],
@@ -181,4 +193,4 @@ export {
181
193
  connectorFromMeta,
182
194
  listRegisteredConnectors
183
195
  };
184
- //# sourceMappingURL=chunk-JVO6NBTT.js.map
196
+ //# sourceMappingURL=chunk-KSPMSRVU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/load-connector.ts"],"sourcesContent":["/**\n * core/load-connector — discover, load, and register connector definitions.\n *\n * Responsibilities:\n * 1. Locate the developer's `agent-connector.config.{mjs,js,json}` by walking\n * upward from a start directory (the project root convention).\n * 2. Load a config from a path into a LIVE ResolvedConnector (with handlers).\n * 3. Register a connector by persisting SERIALIZABLE metadata (no functions)\n * to `connectorDir(id)/connector.json`, pointing at the source module so\n * live handlers can be re-imported at runtime from a stable record.\n *\n * Why split live vs. serialized? Hook handlers are functions and cannot survive\n * JSON. The registry stores only what JSON can hold plus an absolute\n * `modulePath`; the runtime re-imports that module to recover the live handlers.\n */\n\nimport { existsSync, readdirSync, readFileSync, realpathSync, rmSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\n\nimport type {\n CommandDef,\n HookEventName,\n InstallScope,\n MemoryDef,\n PlatformId,\n PlatformOverride,\n ResolvedConnector,\n ServerDef,\n SkillDef,\n SubagentDef,\n} from \"./types.js\";\nimport { defineConnector } from \"./define-connector.js\";\nimport { assertNoSymlinkInPath, connectorDir, connectorsDir, ensureDir } from \"./paths.js\";\nimport {\n readConnectorPackageMetadataNearFile,\n withConnectorPackageMetadata,\n} from \"./package-metadata.js\";\n\n/** Candidate config filenames, in resolution-precedence order. */\nconst CONFIG_FILENAMES = [\n \"agent-connector.config.mjs\",\n \"agent-connector.config.js\",\n \"agent-connector.config.json\",\n] as const;\n\n/**\n * The serializable subset of a connector persisted to `connector.json`.\n * Hook handler functions are intentionally absent — only the absolute\n * `modulePath` is stored so the live ResolvedConnector can be re-imported.\n */\nexport interface RegisteredMeta {\n id: string;\n displayName: string;\n version: string;\n /** Package-derived identity, when available from config or package.json. */\n mcp?: ResolvedConnector[\"mcp\"];\n /** Absolute path to the source module that produced this connector. */\n modulePath: string;\n telemetry: ResolvedConnector[\"telemetry\"];\n /** Canonical event names the connector handles (handlers themselves stripped). */\n hookEvents: HookEventName[];\n hasServer: boolean;\n server: ServerDef | null;\n /**\n * Content surfaces (commands/skills/subagents). These are JSON-serializable\n * (no functions) so they persist cleanly and let uninstall locate the files\n * to remove even when the source module is gone.\n */\n commands: CommandDef[];\n skills: SkillDef[];\n subagents: SubagentDef[];\n /**\n * Memory entries (managed-block content surface). Plain content, persisted\n * whole so uninstall normally has the full entry list even when the source\n * module is gone (the marker prefix-scan is the fallback beyond that).\n */\n memory: MemoryDef[];\n targets: ResolvedConnector[\"targets\"];\n /** Per-platform overrides with any hook handler functions stripped. */\n platforms: Partial<Record<PlatformId, PlatformOverride>>;\n /**\n * The install scope this connector was registered under, persisted so the\n * runtime entrypoints (hook/statusline/action) can recover it cheaply (sync)\n * and stamp it onto the HostCtx/event — scope is an install-time property the\n * runtime otherwise has no access to. OPTIONAL: absent for an ad-hoc register\n * that passed no scope, or a record written before this field existed.\n * This is the install's RUN-WIDE DEFAULT scope; it can differ from the\n * effective per-host scope when a `platforms[host].scope` override is set (the\n * record is keyed by connector id only and holds no per-host scope map).\n */\n scope?: InstallScope;\n}\n\n/**\n * Search `startDir` and each ancestor for a connector config file. Returns the\n * absolute path to the first match (filesystem-root-stopping), or null.\n */\nexport function findConnectorConfig(startDir: string): string | null {\n let dir = resolve(startDir);\n // Walk upward until `dirname(dir) === dir` (filesystem root).\n for (;;) {\n for (const name of CONFIG_FILENAMES) {\n const candidate = join(dir, name);\n if (existsSync(candidate)) return candidate;\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return null;\n}\n\n/** True if a value already looks like a ResolvedConnector (vs. a raw config). */\nfunction isResolvedConnector(value: unknown): value is ResolvedConnector {\n return (\n typeof value === \"object\" &&\n value !== null &&\n Array.isArray((value as { hookEvents?: unknown }).hookEvents)\n );\n}\n\n/**\n * Load a connector from an absolute or relative path.\n * - `.json` → JSON.parse, then defineConnector().\n * - `.mjs` / `.js` → dynamic import (via pathToFileURL, Windows-safe),\n * take the default export. If it already looks like a\n * ResolvedConnector use it as-is; otherwise treat it as\n * a ConnectorConfig and run it through defineConnector().\n * Returns the live connector plus the absolute module path it came from.\n */\nexport async function loadConnectorFromPath(\n path: string,\n): Promise<{ connector: ResolvedConnector; modulePath: string }> {\n let modulePath = isAbsolute(path) ? path : resolve(path);\n // Canonicalize before building the file:// URL for dynamic import. On Windows a\n // short (8.3) temp path like C:\\Users\\RUNNER~1\\...\\x.mjs round-trips the \"~\" as\n // %7E and fails to load; realpathSync.native expands it to the real long path.\n // It also resolves symlinked temp roots (e.g. macOS /var -> /private/var).\n // If the file does not exist yet, fall through with the resolve()'d path so the\n // subsequent read/import throws the real not-found error.\n try {\n modulePath = realpathSync.native(modulePath);\n } catch {\n /* keep the resolve()'d path */\n }\n\n if (modulePath.endsWith(\".json\")) {\n const text = readFileSync(modulePath, \"utf8\");\n const config = JSON.parse(text) as unknown;\n const connector = await withConnectorPackageMetadata(\n readConnectorPackageMetadataNearFile(modulePath),\n async () => defineConnector(config as Parameters<typeof defineConnector>[0]),\n );\n return { connector, modulePath };\n }\n\n // .mjs / .js — dynamic ESM import. pathToFileURL keeps Windows paths valid.\n const moduleUrl = pathToFileURL(modulePath).href;\n const connector = await withConnectorPackageMetadata(\n readConnectorPackageMetadataNearFile(modulePath),\n async () => {\n const mod = (await import(/* @vite-ignore */ moduleUrl)) as {\n default?: unknown;\n };\n const exported = mod.default;\n if (exported == null) {\n throw new Error(\n `Connector module has no default export: ${modulePath}`,\n );\n }\n return isResolvedConnector(exported)\n ? exported\n : defineConnector(exported as Parameters<typeof defineConnector>[0]);\n },\n );\n return { connector, modulePath };\n}\n\n/**\n * Strip any function-valued `hooks` from per-platform overrides so the result\n * is JSON-serializable. A boolean `hooks` override is preserved; an object\n * override is dropped (it can only carry handler functions, which are not\n * serializable). `nativeHooks` declarations are persisted HANDLER-LESS (event\n * name + matcher only) so meta-based inspection (doctor / health checks / the\n * hook CLI) can still see WHICH native events were declared — the live handlers\n * are re-imported from `modulePath` at runtime, exactly like normalized hooks.\n * Everything else on the override is kept verbatim — notably `configPatch`\n * declarations, which are pure JSON (key/value/reason/docsUrl, no functions)\n * and persist WHOLE so uninstall/doctor can reason about them even when the\n * source module is gone.\n */\nfunction serializablePlatforms(\n platforms: Partial<Record<PlatformId, PlatformOverride>>,\n): Partial<Record<PlatformId, PlatformOverride>> {\n const out: Partial<Record<PlatformId, PlatformOverride>> = {};\n for (const [id, override] of Object.entries(platforms) as [\n PlatformId,\n PlatformOverride | undefined,\n ][]) {\n if (!override) continue;\n const { hooks, nativeHooks, ...rest } = override;\n const clean: PlatformOverride = { ...rest };\n // Keep only a boolean hooks flag; object hooks carry handler functions.\n if (typeof hooks === \"boolean\") clean.hooks = hooks;\n if (nativeHooks && typeof nativeHooks === \"object\") {\n const stripped: Record<string, { matcher?: string }> = {};\n for (const [event, def] of Object.entries(nativeHooks)) {\n stripped[event] =\n typeof def?.matcher === \"string\" ? { matcher: def.matcher } : {};\n }\n // Cast: the persisted record deliberately omits the (non-serializable)\n // handler; consumers of meta-derived connectors never dispatch handlers.\n clean.nativeHooks = stripped as PlatformOverride[\"nativeHooks\"];\n }\n out[id] = clean;\n }\n return out;\n}\n\n/**\n * Persist a connector's serializable metadata to `connectorDir(id)/connector.json`.\n * Handlers are NOT serialized — they are re-imported from `modulePath` at runtime.\n * The optional `scope` (the install scope the caller deployed under) is persisted\n * so the runtime entrypoints can recover it and stamp it onto the HostCtx/event.\n * Returns the absolute path of the written record.\n */\nexport function registerConnector(\n connector: ResolvedConnector,\n modulePath: string,\n scope?: InstallScope,\n): string {\n const meta: RegisteredMeta = {\n id: connector.id,\n displayName: connector.displayName,\n version: connector.version,\n ...(connector.mcp ? { mcp: connector.mcp } : {}),\n modulePath: resolve(modulePath),\n telemetry: connector.telemetry,\n hookEvents: connector.hookEvents,\n hasServer: !!connector.server,\n server: connector.server ?? null,\n commands: connector.commands,\n skills: connector.skills,\n subagents: connector.subagents,\n memory: connector.memory,\n targets: connector.targets,\n platforms: serializablePlatforms(connector.platforms),\n // Persist the install scope when the caller supplied one (the installer\n // passes its install scope). Omitted from the record when undefined so an\n // ad-hoc register stays minimal and round-trips as \"no scope known\".\n ...(scope !== undefined ? { scope } : {}),\n };\n\n const dir = connectorDir(connector.id);\n const outPath = join(dir, \"connector.json\");\n assertNoSymlinkInPath(outPath);\n ensureDir(dir);\n writeFileSync(outPath, `${JSON.stringify(meta, null, 2)}\\n`, \"utf8\");\n return outPath;\n}\n\n/**\n * Deregister a connector by removing its DATA-dir record directory\n * (`connectorDir(id)`) recursively. This is the inverse of {@link registerConnector}:\n * registerConnector writes `connectorDir(id)/connector.json`, but per-target\n * uninstall only strips host-native registrations — it never removes this record,\n * leaving an orphan behind. Best-effort + guarded: returns the directory path and\n * whether it existed before removal.\n */\nexport function deregisterConnector(id: string): {\n removed: boolean;\n path: string;\n} {\n const dir = connectorDir(id);\n assertNoSymlinkInPath(dir);\n const existed = existsSync(dir);\n if (existed) rmSync(dir, { recursive: true, force: true });\n return { removed: existed, path: dir };\n}\n\n/**\n * Read the registered metadata record for `id`, or null if not registered or\n * the record is unreadable/corrupt.\n */\nexport function readRegisteredMeta(id: string): RegisteredMeta | null {\n const recordPath = join(connectorDir(id), \"connector.json\");\n if (!existsSync(recordPath)) return null;\n try {\n return JSON.parse(readFileSync(recordPath, \"utf8\")) as RegisteredMeta;\n } catch {\n return null;\n }\n}\n\n/**\n * Load the LIVE ResolvedConnector (with hook handlers) for a registered id by\n * re-importing its source module. Throws a clear error when the connector is\n * not registered or its source module no longer resolves to it.\n */\nexport async function loadRegisteredConnector(\n id: string,\n): Promise<ResolvedConnector> {\n const meta = readRegisteredMeta(id);\n if (!meta) {\n throw new Error(\n `Connector \"${id}\" is not registered (no record at ${join(connectorDir(id), \"connector.json\")}). ` +\n `Run an install/register step first.`,\n );\n }\n if (!meta.modulePath || !existsSync(meta.modulePath)) {\n throw new Error(\n `Connector \"${id}\" record points at a missing module: ${meta.modulePath}`,\n );\n }\n const { connector } = await loadConnectorFromPath(meta.modulePath);\n return connector;\n}\n\n/**\n * Build a handler-less ResolvedConnector from stored metadata. Suitable for\n * inspection/doctor where live hook handlers are not needed (and where the\n * source module may even be gone). `hooks` is empty; `hookEvents` is preserved.\n */\nexport function connectorFromMeta(meta: RegisteredMeta): ResolvedConnector {\n return {\n id: meta.id,\n displayName: meta.displayName,\n version: meta.version,\n ...(meta.mcp ? { mcp: meta.mcp } : {}),\n ...(meta.server ? { server: meta.server } : {}),\n hooks: {},\n hookEvents: meta.hookEvents ?? [],\n telemetry: meta.telemetry,\n commands: meta.commands ?? [],\n skills: meta.skills ?? [],\n subagents: meta.subagents ?? [],\n memory: meta.memory ?? [],\n // Actions carry live `run` handlers, so they are NOT serialized into the\n // record (like the statusline render). A handler-less meta-derived connector\n // gets [] — inspection/uninstall never dispatch action handlers, and the\n // BaseAdapter action default already tolerates an empty list.\n actions: [],\n platforms: meta.platforms ?? {},\n targets: meta.targets,\n };\n}\n\n/**\n * List every registered connector as a handler-less ResolvedConnector (read\n * from `connectorsDir()`). Used by doctor to health-check what is actually\n * installed, rather than guessing from the local working directory.\n */\nexport function listRegisteredConnectors(): ResolvedConnector[] {\n const dir = connectorsDir();\n if (!existsSync(dir)) return [];\n const out: ResolvedConnector[] = [];\n for (const entry of readdirSync(dir)) {\n const meta = readRegisteredMeta(entry);\n if (meta) out.push(connectorFromMeta(meta));\n }\n return out;\n}\n"],"mappings":"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","names":["connector"]}
@@ -11,7 +11,7 @@ import {
11
11
  removeManagedBlocksFile,
12
12
  saveMemoryLedger,
13
13
  upsertManagedBlockFile
14
- } from "./chunk-M2H7JURF.js";
14
+ } from "./chunk-UMQ6NBQR.js";
15
15
  import {
16
16
  backupsDir,
17
17
  ensureDir,
@@ -1265,4 +1265,4 @@ export {
1265
1265
  renderOpenCodeSubagentMd,
1266
1266
  BaseAdapter
1267
1267
  };
1268
- //# sourceMappingURL=chunk-WFEHWTLM.js.map
1268
+ //# sourceMappingURL=chunk-MGTDQLJJ.js.map
@@ -460,36 +460,36 @@ function renderInstallResult(result, verb) {
460
460
  return lines.join("\n");
461
461
  }
462
462
  var COMMANDS = {
463
- detect: () => import("./detect-Z5BDTY6B.js"),
464
- install: () => import("./install-O32TDIZP.js"),
465
- uninstall: () => import("./uninstall-M76BHLTH.js"),
463
+ detect: () => import("./detect-DYQNUMXL.js"),
464
+ install: () => import("./install-T27662FW.js"),
465
+ uninstall: () => import("./uninstall-NJNNZZZY.js"),
466
466
  // `upgrade` is the single "bring everything current" verb (re-render host
467
467
  // config + refresh the home pointer + managed channel guidance). `sync` and
468
468
  // `update` are kept as back-compat aliases that route to the same module so
469
469
  // existing scripts/docs keep working without a second concept to learn.
470
- upgrade: () => import("./upgrade-JLSCNAQA.js"),
471
- sync: () => import("./upgrade-JLSCNAQA.js"),
472
- update: () => import("./upgrade-JLSCNAQA.js"),
473
- package: () => import("./package-2KKUGZFS.js"),
474
- doctor: () => import("./doctor-GAP27PP2.js"),
475
- status: () => import("./status-B2PG6YKR.js"),
476
- telemetry: () => import("./telemetry-ZMCAWBWB.js"),
477
- usage: () => import("./usage-5I72HWCR.js"),
478
- leaderboard: () => import("./leaderboard-YWMOSJBC.js"),
479
- hook: () => import("./hook-XPR3AHDI.js"),
470
+ upgrade: () => import("./upgrade-TIBUOQNM.js"),
471
+ sync: () => import("./upgrade-TIBUOQNM.js"),
472
+ update: () => import("./upgrade-TIBUOQNM.js"),
473
+ package: () => import("./package-LIPZKHAQ.js"),
474
+ doctor: () => import("./doctor-H6XXAR63.js"),
475
+ status: () => import("./status-J7SOUH7O.js"),
476
+ telemetry: () => import("./telemetry-EICCFEIF.js"),
477
+ usage: () => import("./usage-VEVBWPLS.js"),
478
+ leaderboard: () => import("./leaderboard-CIMQBOUS.js"),
479
+ hook: () => import("./hook-GIQTUDMN.js"),
480
480
  // Internal (omitted from USAGE): the statusline (HUD) entrypoint a host's
481
481
  // status line config points at. Fail-safe: always exits 0 with at most a
482
482
  // rendered line. See cli/commands/statusline.ts.
483
- statusline: () => import("./statusline-5ERFMYSM.js"),
483
+ statusline: () => import("./statusline-QF4G724E.js"),
484
484
  // Internal (omitted from USAGE): the user-invokable action entrypoint a future
485
485
  // host affordance points at. USER-TRIGGERED: surfaces errors (exit 1 + stderr),
486
486
  // unlike the fail-open hook / fail-safe statusline. See cli/commands/action.ts.
487
- action: () => import("./action-CVIEPX4U.js"),
488
- serve: () => import("./serve-EPRN7F2X.js"),
487
+ action: () => import("./action-DOWHWEDZ.js"),
488
+ serve: () => import("./serve-ABTO2NA2.js"),
489
489
  // Hidden (omitted from USAGE): the opt-in host-native turn-usage entrypoint an
490
490
  // AfterModel / PostInvocation hook points at. Always exits 0; records a
491
491
  // distinct `model_turn` row. See cli/commands/usage-event.ts.
492
- "usage-event": () => import("./usage-event-HIX4ZI45.js")
492
+ "usage-event": () => import("./usage-event-GRQE7XWT.js")
493
493
  };
494
494
  var DEFAULT_PROGRAM_NAME = "agent-connector";
495
495
  var COMMAND_USAGE = {
@@ -587,4 +587,4 @@ export {
587
587
  renderInstallResult,
588
588
  main
589
589
  };
590
- //# sourceMappingURL=chunk-5Z36KVU2.js.map
590
+ //# sourceMappingURL=chunk-OEADFFKO.js.map
@@ -2,15 +2,15 @@
2
2
  import {
3
3
  compileMatcher,
4
4
  eventMatcherSubject
5
- } from "./chunk-FBCBHEGB.js";
5
+ } from "./chunk-I5TO42QC.js";
6
6
  import {
7
7
  SURFACE_PREDICATES,
8
8
  hostCanFireEvent
9
- } from "./chunk-7UT6OB52.js";
9
+ } from "./chunk-2RIFORQS.js";
10
10
  import {
11
11
  allAdapters,
12
12
  loadAdapter
13
- } from "./chunk-KA55FISM.js";
13
+ } from "./chunk-SILKSP2Y.js";
14
14
 
15
15
  // src/sdk/test-harness.ts
16
16
  function declaredGlobalSurfaces(connector) {
@@ -383,4 +383,4 @@ export {
383
383
  simulate,
384
384
  explainHooks
385
385
  };
386
- //# sourceMappingURL=chunk-L26PSQTY.js.map
386
+ //# sourceMappingURL=chunk-P23RVIUY.js.map