@darkiceinteractive/mcp-conductor 2.0.0-alpha.1 → 3.0.0-beta.2

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 (276) hide show
  1. package/README.md +35 -5
  2. package/dist/bin/cli.d.ts +20 -0
  3. package/dist/bin/cli.d.ts.map +1 -0
  4. package/dist/bin/cli.js +260 -0
  5. package/dist/bin/cli.js.map +1 -0
  6. package/dist/bridge/http-server.d.ts +35 -0
  7. package/dist/bridge/http-server.d.ts.map +1 -1
  8. package/dist/bridge/http-server.js +51 -2
  9. package/dist/bridge/http-server.js.map +1 -1
  10. package/dist/bridge/index.d.ts +1 -0
  11. package/dist/bridge/index.d.ts.map +1 -1
  12. package/dist/bridge/index.js +1 -0
  13. package/dist/bridge/index.js.map +1 -1
  14. package/dist/bridge/pool.d.ts +95 -0
  15. package/dist/bridge/pool.d.ts.map +1 -0
  16. package/dist/bridge/pool.js +384 -0
  17. package/dist/bridge/pool.js.map +1 -0
  18. package/dist/cache/cache.d.ts +64 -0
  19. package/dist/cache/cache.d.ts.map +1 -0
  20. package/dist/cache/cache.js +209 -0
  21. package/dist/cache/cache.js.map +1 -0
  22. package/dist/cache/delta.d.ts +32 -0
  23. package/dist/cache/delta.d.ts.map +1 -0
  24. package/dist/cache/delta.js +131 -0
  25. package/dist/cache/delta.js.map +1 -0
  26. package/dist/cache/disk.d.ts +65 -0
  27. package/dist/cache/disk.d.ts.map +1 -0
  28. package/dist/cache/disk.js +238 -0
  29. package/dist/cache/disk.js.map +1 -0
  30. package/dist/cache/index.d.ts +53 -0
  31. package/dist/cache/index.d.ts.map +1 -0
  32. package/dist/cache/index.js +12 -0
  33. package/dist/cache/index.js.map +1 -0
  34. package/dist/cache/key.d.ts +44 -0
  35. package/dist/cache/key.d.ts.map +1 -0
  36. package/dist/cache/key.js +83 -0
  37. package/dist/cache/key.js.map +1 -0
  38. package/dist/cache/lru.d.ts +57 -0
  39. package/dist/cache/lru.d.ts.map +1 -0
  40. package/dist/cache/lru.js +112 -0
  41. package/dist/cache/lru.js.map +1 -0
  42. package/dist/cache/policy.d.ts +34 -0
  43. package/dist/cache/policy.d.ts.map +1 -0
  44. package/dist/cache/policy.js +95 -0
  45. package/dist/cache/policy.js.map +1 -0
  46. package/dist/cli/commands/doctor.d.ts +33 -0
  47. package/dist/cli/commands/doctor.d.ts.map +1 -0
  48. package/dist/cli/commands/doctor.js +135 -0
  49. package/dist/cli/commands/doctor.js.map +1 -0
  50. package/dist/cli/commands/export-servers.d.ts +22 -0
  51. package/dist/cli/commands/export-servers.d.ts.map +1 -0
  52. package/dist/cli/commands/export-servers.js +45 -0
  53. package/dist/cli/commands/export-servers.js.map +1 -0
  54. package/dist/cli/commands/import-servers.d.ts +57 -0
  55. package/dist/cli/commands/import-servers.d.ts.map +1 -0
  56. package/dist/cli/commands/import-servers.js +137 -0
  57. package/dist/cli/commands/import-servers.js.map +1 -0
  58. package/dist/cli/commands/routing.d.ts +34 -0
  59. package/dist/cli/commands/routing.d.ts.map +1 -0
  60. package/dist/cli/commands/routing.js +60 -0
  61. package/dist/cli/commands/routing.js.map +1 -0
  62. package/dist/cli/commands/test-server.d.ts +34 -0
  63. package/dist/cli/commands/test-server.d.ts.map +1 -0
  64. package/dist/cli/commands/test-server.js +86 -0
  65. package/dist/cli/commands/test-server.js.map +1 -0
  66. package/dist/cli/daemon.d.ts +60 -0
  67. package/dist/cli/daemon.d.ts.map +1 -0
  68. package/dist/cli/daemon.js +244 -0
  69. package/dist/cli/daemon.js.map +1 -0
  70. package/dist/cli/replay.d.ts +16 -0
  71. package/dist/cli/replay.d.ts.map +1 -0
  72. package/dist/cli/replay.js +89 -0
  73. package/dist/cli/replay.js.map +1 -0
  74. package/dist/cli/wizard/setup.d.ts +12 -0
  75. package/dist/cli/wizard/setup.d.ts.map +1 -0
  76. package/dist/cli/wizard/setup.js +71 -0
  77. package/dist/cli/wizard/setup.js.map +1 -0
  78. package/dist/config/defaults.d.ts.map +1 -1
  79. package/dist/config/defaults.js +4 -1
  80. package/dist/config/defaults.js.map +1 -1
  81. package/dist/config/schema.d.ts +34 -0
  82. package/dist/config/schema.d.ts.map +1 -1
  83. package/dist/daemon/client.d.ts +99 -0
  84. package/dist/daemon/client.d.ts.map +1 -0
  85. package/dist/daemon/client.js +292 -0
  86. package/dist/daemon/client.js.map +1 -0
  87. package/dist/daemon/discovery.d.ts +50 -0
  88. package/dist/daemon/discovery.d.ts.map +1 -0
  89. package/dist/daemon/discovery.js +104 -0
  90. package/dist/daemon/discovery.js.map +1 -0
  91. package/dist/daemon/index.d.ts +16 -0
  92. package/dist/daemon/index.d.ts.map +1 -0
  93. package/dist/daemon/index.js +11 -0
  94. package/dist/daemon/index.js.map +1 -0
  95. package/dist/daemon/sandbox-api.d.ts +45 -0
  96. package/dist/daemon/sandbox-api.d.ts.map +1 -0
  97. package/dist/daemon/sandbox-api.js +74 -0
  98. package/dist/daemon/sandbox-api.js.map +1 -0
  99. package/dist/daemon/server.d.ts +65 -0
  100. package/dist/daemon/server.d.ts.map +1 -0
  101. package/dist/daemon/server.js +373 -0
  102. package/dist/daemon/server.js.map +1 -0
  103. package/dist/daemon/shared-kv.d.ts +81 -0
  104. package/dist/daemon/shared-kv.d.ts.map +1 -0
  105. package/dist/daemon/shared-kv.js +215 -0
  106. package/dist/daemon/shared-kv.js.map +1 -0
  107. package/dist/daemon/shared-lock.d.ts +71 -0
  108. package/dist/daemon/shared-lock.d.ts.map +1 -0
  109. package/dist/daemon/shared-lock.js +119 -0
  110. package/dist/daemon/shared-lock.js.map +1 -0
  111. package/dist/hub/mcp-hub.d.ts +23 -0
  112. package/dist/hub/mcp-hub.d.ts.map +1 -1
  113. package/dist/hub/mcp-hub.js +34 -1
  114. package/dist/hub/mcp-hub.js.map +1 -1
  115. package/dist/index.js +7 -0
  116. package/dist/index.js.map +1 -1
  117. package/dist/observability/anomaly.d.ts +67 -0
  118. package/dist/observability/anomaly.d.ts.map +1 -0
  119. package/dist/observability/anomaly.js +141 -0
  120. package/dist/observability/anomaly.js.map +1 -0
  121. package/dist/observability/cost-predictor.d.ts +49 -0
  122. package/dist/observability/cost-predictor.d.ts.map +1 -0
  123. package/dist/observability/cost-predictor.js +145 -0
  124. package/dist/observability/cost-predictor.js.map +1 -0
  125. package/dist/observability/hot-path.d.ts +49 -0
  126. package/dist/observability/hot-path.d.ts.map +1 -0
  127. package/dist/observability/hot-path.js +125 -0
  128. package/dist/observability/hot-path.js.map +1 -0
  129. package/dist/observability/index.d.ts +10 -0
  130. package/dist/observability/index.d.ts.map +1 -0
  131. package/dist/observability/index.js +10 -0
  132. package/dist/observability/index.js.map +1 -0
  133. package/dist/observability/replay.d.ts +104 -0
  134. package/dist/observability/replay.d.ts.map +1 -0
  135. package/dist/observability/replay.js +239 -0
  136. package/dist/observability/replay.js.map +1 -0
  137. package/dist/registry/built-in-recommendations.d.ts +54 -0
  138. package/dist/registry/built-in-recommendations.d.ts.map +1 -0
  139. package/dist/registry/built-in-recommendations.js +65 -0
  140. package/dist/registry/built-in-recommendations.js.map +1 -0
  141. package/dist/registry/events.d.ts +26 -0
  142. package/dist/registry/events.d.ts.map +1 -0
  143. package/dist/registry/events.js +22 -0
  144. package/dist/registry/events.js.map +1 -0
  145. package/dist/registry/index.d.ts +159 -0
  146. package/dist/registry/index.d.ts.map +1 -0
  147. package/dist/registry/index.js +12 -0
  148. package/dist/registry/index.js.map +1 -0
  149. package/dist/registry/registry.d.ts +87 -0
  150. package/dist/registry/registry.d.ts.map +1 -0
  151. package/dist/registry/registry.js +294 -0
  152. package/dist/registry/registry.js.map +1 -0
  153. package/dist/registry/snapshot.d.ts +42 -0
  154. package/dist/registry/snapshot.d.ts.map +1 -0
  155. package/dist/registry/snapshot.js +71 -0
  156. package/dist/registry/snapshot.js.map +1 -0
  157. package/dist/registry/typegen.d.ts +48 -0
  158. package/dist/registry/typegen.d.ts.map +1 -0
  159. package/dist/registry/typegen.js +200 -0
  160. package/dist/registry/typegen.js.map +1 -0
  161. package/dist/registry/validator.d.ts +23 -0
  162. package/dist/registry/validator.d.ts.map +1 -0
  163. package/dist/registry/validator.js +50 -0
  164. package/dist/registry/validator.js.map +1 -0
  165. package/dist/reliability/breaker.d.ts +57 -0
  166. package/dist/reliability/breaker.d.ts.map +1 -0
  167. package/dist/reliability/breaker.js +130 -0
  168. package/dist/reliability/breaker.js.map +1 -0
  169. package/dist/reliability/errors.d.ts +78 -0
  170. package/dist/reliability/errors.d.ts.map +1 -0
  171. package/dist/reliability/errors.js +160 -0
  172. package/dist/reliability/errors.js.map +1 -0
  173. package/dist/reliability/gateway.d.ts +88 -0
  174. package/dist/reliability/gateway.d.ts.map +1 -0
  175. package/dist/reliability/gateway.js +180 -0
  176. package/dist/reliability/gateway.js.map +1 -0
  177. package/dist/reliability/index.d.ts +20 -0
  178. package/dist/reliability/index.d.ts.map +1 -0
  179. package/dist/reliability/index.js +16 -0
  180. package/dist/reliability/index.js.map +1 -0
  181. package/dist/reliability/profile.d.ts +49 -0
  182. package/dist/reliability/profile.d.ts.map +1 -0
  183. package/dist/reliability/profile.js +58 -0
  184. package/dist/reliability/profile.js.map +1 -0
  185. package/dist/reliability/retry.d.ts +39 -0
  186. package/dist/reliability/retry.d.ts.map +1 -0
  187. package/dist/reliability/retry.js +51 -0
  188. package/dist/reliability/retry.js.map +1 -0
  189. package/dist/reliability/timeout.d.ts +34 -0
  190. package/dist/reliability/timeout.d.ts.map +1 -0
  191. package/dist/reliability/timeout.js +53 -0
  192. package/dist/reliability/timeout.js.map +1 -0
  193. package/dist/runtime/executor.d.ts.map +1 -1
  194. package/dist/runtime/executor.js +122 -14
  195. package/dist/runtime/executor.js.map +1 -1
  196. package/dist/runtime/findtool/embed.d.ts +28 -0
  197. package/dist/runtime/findtool/embed.d.ts.map +1 -0
  198. package/dist/runtime/findtool/embed.js +85 -0
  199. package/dist/runtime/findtool/embed.js.map +1 -0
  200. package/dist/runtime/findtool/index.d.ts +52 -0
  201. package/dist/runtime/findtool/index.d.ts.map +1 -0
  202. package/dist/runtime/findtool/index.js +78 -0
  203. package/dist/runtime/findtool/index.js.map +1 -0
  204. package/dist/runtime/findtool/vector-index.d.ts +53 -0
  205. package/dist/runtime/findtool/vector-index.d.ts.map +1 -0
  206. package/dist/runtime/findtool/vector-index.js +71 -0
  207. package/dist/runtime/findtool/vector-index.js.map +1 -0
  208. package/dist/runtime/helpers/budget.d.ts +27 -0
  209. package/dist/runtime/helpers/budget.d.ts.map +1 -0
  210. package/dist/runtime/helpers/budget.js +103 -0
  211. package/dist/runtime/helpers/budget.js.map +1 -0
  212. package/dist/runtime/helpers/compact.d.ts +32 -0
  213. package/dist/runtime/helpers/compact.d.ts.map +1 -0
  214. package/dist/runtime/helpers/compact.js +93 -0
  215. package/dist/runtime/helpers/compact.js.map +1 -0
  216. package/dist/runtime/helpers/delta.d.ts +45 -0
  217. package/dist/runtime/helpers/delta.d.ts.map +1 -0
  218. package/dist/runtime/helpers/delta.js +116 -0
  219. package/dist/runtime/helpers/delta.js.map +1 -0
  220. package/dist/runtime/helpers/index.d.ts +16 -0
  221. package/dist/runtime/helpers/index.d.ts.map +1 -0
  222. package/dist/runtime/helpers/index.js +13 -0
  223. package/dist/runtime/helpers/index.js.map +1 -0
  224. package/dist/runtime/helpers/summarize.d.ts +24 -0
  225. package/dist/runtime/helpers/summarize.d.ts.map +1 -0
  226. package/dist/runtime/helpers/summarize.js +124 -0
  227. package/dist/runtime/helpers/summarize.js.map +1 -0
  228. package/dist/runtime/helpers/worker-preload.d.ts +25 -0
  229. package/dist/runtime/helpers/worker-preload.d.ts.map +1 -0
  230. package/dist/runtime/helpers/worker-preload.js +223 -0
  231. package/dist/runtime/helpers/worker-preload.js.map +1 -0
  232. package/dist/runtime/index.d.ts +1 -0
  233. package/dist/runtime/index.d.ts.map +1 -1
  234. package/dist/runtime/index.js +1 -0
  235. package/dist/runtime/index.js.map +1 -1
  236. package/dist/runtime/pool/index.d.ts +11 -0
  237. package/dist/runtime/pool/index.d.ts.map +1 -0
  238. package/dist/runtime/pool/index.js +8 -0
  239. package/dist/runtime/pool/index.js.map +1 -0
  240. package/dist/runtime/pool/recycle.d.ts +44 -0
  241. package/dist/runtime/pool/recycle.d.ts.map +1 -0
  242. package/dist/runtime/pool/recycle.js +50 -0
  243. package/dist/runtime/pool/recycle.js.map +1 -0
  244. package/dist/runtime/pool/worker-pool.d.ts +77 -0
  245. package/dist/runtime/pool/worker-pool.d.ts.map +1 -0
  246. package/dist/runtime/pool/worker-pool.js +216 -0
  247. package/dist/runtime/pool/worker-pool.js.map +1 -0
  248. package/dist/runtime/pool/worker.d.ts +80 -0
  249. package/dist/runtime/pool/worker.d.ts.map +1 -0
  250. package/dist/runtime/pool/worker.js +324 -0
  251. package/dist/runtime/pool/worker.js.map +1 -0
  252. package/dist/server/mcp-server.d.ts +3 -0
  253. package/dist/server/mcp-server.d.ts.map +1 -1
  254. package/dist/server/mcp-server.js +457 -3
  255. package/dist/server/mcp-server.js.map +1 -1
  256. package/dist/server/passthrough-registrar.d.ts +123 -0
  257. package/dist/server/passthrough-registrar.d.ts.map +1 -0
  258. package/dist/server/passthrough-registrar.js +199 -0
  259. package/dist/server/passthrough-registrar.js.map +1 -0
  260. package/dist/skills/skills-engine.d.ts +9 -1
  261. package/dist/skills/skills-engine.d.ts.map +1 -1
  262. package/dist/skills/skills-engine.js +20 -3
  263. package/dist/skills/skills-engine.js.map +1 -1
  264. package/dist/utils/index.d.ts +1 -0
  265. package/dist/utils/index.d.ts.map +1 -1
  266. package/dist/utils/index.js +1 -0
  267. package/dist/utils/index.js.map +1 -1
  268. package/dist/utils/tokenize.d.ts +55 -0
  269. package/dist/utils/tokenize.d.ts.map +1 -0
  270. package/dist/utils/tokenize.js +205 -0
  271. package/dist/utils/tokenize.js.map +1 -0
  272. package/dist/version.d.ts +3 -3
  273. package/dist/version.d.ts.map +1 -1
  274. package/dist/version.js +3 -3
  275. package/dist/version.js.map +1 -1
  276. package/package.json +13 -3
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Lightweight embedding for findTool
3
+ *
4
+ * Uses a character-level TF-IDF-style embedding that runs entirely in-process
5
+ * with no ONNX runtime dependency. This keeps the package lightweight while
6
+ * providing meaningful semantic similarity for MCP tool search.
7
+ *
8
+ * The embedding is a fixed-dimensional Float32Array built from:
9
+ * 1. Unigram token frequencies (normalised)
10
+ * 2. Bigram token frequencies (normalised)
11
+ *
12
+ * This is sufficient for the findTool use case where queries are short phrases
13
+ * and tool descriptions are relatively short, structured text.
14
+ *
15
+ * If $MCP_CONDUCTOR_EMBED_MODEL=onnx is set and @xenova/transformers is
16
+ * installed, we will delegate to MiniLM-L6 at runtime. Otherwise we fall
17
+ * back to the in-process TF-IDF embedder.
18
+ *
19
+ * @module runtime/findtool/embed
20
+ */
21
+ // Embedding dimension for the in-process embedder
22
+ export const EMBED_DIM = 256;
23
+ // ─────────────────────────────────────────────────────────────────────────────
24
+ // Tokeniser
25
+ // ─────────────────────────────────────────────────────────────────────────────
26
+ function tokenise(text) {
27
+ return text
28
+ .toLowerCase()
29
+ .replace(/[^a-z0-9_\-. ]/g, ' ')
30
+ .split(/\s+/)
31
+ .filter(Boolean);
32
+ }
33
+ // Deterministic hash of a string to [0, EMBED_DIM)
34
+ function hashBucket(s) {
35
+ let h = 5381;
36
+ for (let i = 0; i < s.length; i++) {
37
+ h = ((h << 5) + h) ^ s.charCodeAt(i);
38
+ h = h >>> 0; // keep unsigned 32-bit
39
+ }
40
+ return h % EMBED_DIM;
41
+ }
42
+ /**
43
+ * Build a Float32Array embedding for a text string.
44
+ * The vector is L2-normalised for cosine similarity computation.
45
+ */
46
+ export function embed(text) {
47
+ const vec = new Float32Array(EMBED_DIM);
48
+ const tokens = tokenise(text);
49
+ if (tokens.length === 0)
50
+ return vec;
51
+ // Unigram features
52
+ for (const token of tokens) {
53
+ vec[hashBucket(token)] = (vec[hashBucket(token)] ?? 0) + 1;
54
+ }
55
+ // Bigram features
56
+ for (let i = 0; i < tokens.length - 1; i++) {
57
+ const ti = tokens[i] ?? '';
58
+ const ti1 = tokens[i + 1] ?? '';
59
+ const bigram = ti + '_' + ti1;
60
+ vec[hashBucket(bigram)] = (vec[hashBucket(bigram)] ?? 0) + 0.5;
61
+ }
62
+ // L2 normalise
63
+ let norm = 0;
64
+ for (let i = 0; i < EMBED_DIM; i++)
65
+ norm += (vec[i] ?? 0) * (vec[i] ?? 0);
66
+ norm = Math.sqrt(norm);
67
+ if (norm > 0) {
68
+ for (let i = 0; i < EMBED_DIM; i++) {
69
+ const v = vec[i] ?? 0;
70
+ vec[i] = v / norm;
71
+ }
72
+ }
73
+ return vec;
74
+ }
75
+ // ─────────────────────────────────────────────────────────────────────────────
76
+ // Cosine similarity
77
+ // ─────────────────────────────────────────────────────────────────────────────
78
+ export function cosineSimilarity(a, b) {
79
+ let dot = 0;
80
+ for (let i = 0; i < a.length; i++)
81
+ dot += (a[i] ?? 0) * (b[i] ?? 0);
82
+ // Vectors are already L2-normalised so dot product == cosine similarity
83
+ return dot;
84
+ }
85
+ //# sourceMappingURL=embed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.js","sourceRoot":"","sources":["../../../src/runtime/findtool/embed.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * findTool — semantic tool discovery
3
+ *
4
+ * Provides `findTool(query, options)` for sandbox code. Lazily initialises
5
+ * the vector index on first call and re-indexes whenever the registry
6
+ * publishes a hot-reload event.
7
+ *
8
+ * @module runtime/findtool
9
+ */
10
+ export type { SearchResult } from './vector-index.js';
11
+ export { embed, cosineSimilarity, EMBED_DIM } from './embed.js';
12
+ export interface FindToolOptions {
13
+ /** Number of results to return (default: 5) */
14
+ topK?: number;
15
+ /** Restrict search to these servers */
16
+ serverFilter?: string[];
17
+ }
18
+ export interface ToolEntry {
19
+ server: string;
20
+ tool: string;
21
+ description: string;
22
+ }
23
+ /**
24
+ * Register a tool loader callback. Called during system startup so the
25
+ * findTool module can lazily pull tool definitions from the registry.
26
+ */
27
+ export declare function registerToolLoader(loader: () => Promise<ToolEntry[]>): void;
28
+ /**
29
+ * Immediately re-index all tools. Call this when the registry hot-reloads.
30
+ */
31
+ export declare function reindex(): Promise<void>;
32
+ /**
33
+ * Find MCP tools semantically similar to `query`.
34
+ *
35
+ * @example
36
+ * const tools = await findTool('list github issues', { topK: 3 });
37
+ */
38
+ export declare function findTool(query: string, options?: FindToolOptions): Promise<Array<{
39
+ server: string;
40
+ tool: string;
41
+ description: string;
42
+ score: number;
43
+ }>>;
44
+ /**
45
+ * Seed the index directly (used in tests and worker bootstrap).
46
+ */
47
+ export declare function seedIndex(tools: ToolEntry[]): void;
48
+ /**
49
+ * Reset state (tests only).
50
+ */
51
+ export declare function resetFindTool(): void;
52
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/runtime/findtool/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,YAAY,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAMhE,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB;AAiBD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC,GAAG,IAAI,CAG3E;AAED;;GAEG;AACH,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAK7C;AAcD;;;;;GAKG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAGtF;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAGlD;AAED;;GAEG;AACH,wBAAgB,aAAa,IAAI,IAAI,CAIpC"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * findTool — semantic tool discovery
3
+ *
4
+ * Provides `findTool(query, options)` for sandbox code. Lazily initialises
5
+ * the vector index on first call and re-indexes whenever the registry
6
+ * publishes a hot-reload event.
7
+ *
8
+ * @module runtime/findtool
9
+ */
10
+ import { VectorIndex } from './vector-index.js';
11
+ export { embed, cosineSimilarity, EMBED_DIM } from './embed.js';
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ // Singleton index
14
+ // ─────────────────────────────────────────────────────────────────────────────
15
+ let _index = null;
16
+ let _initialised = false;
17
+ let _toolLoader = null;
18
+ function getIndex() {
19
+ if (!_index) {
20
+ _index = new VectorIndex();
21
+ }
22
+ return _index;
23
+ }
24
+ /**
25
+ * Register a tool loader callback. Called during system startup so the
26
+ * findTool module can lazily pull tool definitions from the registry.
27
+ */
28
+ export function registerToolLoader(loader) {
29
+ _toolLoader = loader;
30
+ _initialised = false; // force re-init on next search
31
+ }
32
+ /**
33
+ * Immediately re-index all tools. Call this when the registry hot-reloads.
34
+ */
35
+ export async function reindex() {
36
+ if (!_toolLoader)
37
+ return;
38
+ const tools = await _toolLoader();
39
+ getIndex().rebuild(tools);
40
+ _initialised = true;
41
+ }
42
+ async function ensureInitialised() {
43
+ if (_initialised)
44
+ return;
45
+ if (_toolLoader) {
46
+ await reindex();
47
+ }
48
+ _initialised = true;
49
+ }
50
+ // ─────────────────────────────────────────────────────────────────────────────
51
+ // Public API
52
+ // ─────────────────────────────────────────────────────────────────────────────
53
+ /**
54
+ * Find MCP tools semantically similar to `query`.
55
+ *
56
+ * @example
57
+ * const tools = await findTool('list github issues', { topK: 3 });
58
+ */
59
+ export async function findTool(query, options = {}) {
60
+ await ensureInitialised();
61
+ return getIndex().search(query, options.topK ?? 5, options.serverFilter);
62
+ }
63
+ /**
64
+ * Seed the index directly (used in tests and worker bootstrap).
65
+ */
66
+ export function seedIndex(tools) {
67
+ getIndex().rebuild(tools);
68
+ _initialised = true;
69
+ }
70
+ /**
71
+ * Reset state (tests only).
72
+ */
73
+ export function resetFindTool() {
74
+ _index = null;
75
+ _initialised = false;
76
+ _toolLoader = null;
77
+ }
78
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/runtime/findtool/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAmBhE,gFAAgF;AAChF,kBAAkB;AAClB,gFAAgF;AAEhF,IAAI,MAAM,GAAuB,IAAI,CAAC;AACtC,IAAI,YAAY,GAAG,KAAK,CAAC;AACzB,IAAI,WAAW,GAAwC,IAAI,CAAC;AAE5D,SAAS,QAAQ;IACf,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IAC7B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAAkC;IACnE,WAAW,GAAG,MAAM,CAAC;IACrB,YAAY,GAAG,KAAK,CAAC,CAAC,+BAA+B;AACvD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,IAAI,CAAC,WAAW;QAAE,OAAO;IACzB,MAAM,KAAK,GAAG,MAAM,WAAW,EAAE,CAAC;IAClC,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1B,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAED,KAAK,UAAU,iBAAiB;IAC9B,IAAI,YAAY;QAAE,OAAO;IACzB,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,OAAO,EAAE,CAAC;IAClB,CAAC;IACD,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAED,gFAAgF;AAChF,aAAa;AACb,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,KAAa,EACb,UAA2B,EAAE;IAE7B,MAAM,iBAAiB,EAAE,CAAC;IAC1B,OAAO,QAAQ,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;AAC3E,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,KAAkB;IAC1C,QAAQ,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1B,YAAY,GAAG,IAAI,CAAC;AACtB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,IAAI,CAAC;IACd,YAAY,GAAG,KAAK,CAAC;IACrB,WAAW,GAAG,IAAI,CAAC;AACrB,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * In-memory vector index for tool embeddings
3
+ *
4
+ * Stores Float32Array embeddings for each registered MCP tool and provides
5
+ * cosine-similarity nearest-neighbour search. Re-indexes on registry hot-reload.
6
+ *
7
+ * For large deployments (>10k tools) consider replacing with hnswlib-node or
8
+ * LanceDB (set $LANCEDB_URL to enable the remote backend).
9
+ *
10
+ * @module runtime/findtool/vector-index
11
+ */
12
+ export interface IndexedTool {
13
+ server: string;
14
+ tool: string;
15
+ description: string;
16
+ vector: Float32Array;
17
+ }
18
+ export interface SearchResult {
19
+ server: string;
20
+ tool: string;
21
+ description: string;
22
+ score: number;
23
+ }
24
+ export declare class VectorIndex {
25
+ private entries;
26
+ /**
27
+ * Add or replace all tools for a server. Existing entries for that
28
+ * server are removed first.
29
+ */
30
+ upsertServer(server: string, tools: Array<{
31
+ tool: string;
32
+ description: string;
33
+ }>): void;
34
+ /**
35
+ * Remove all entries for a server.
36
+ */
37
+ removeServer(server: string): void;
38
+ /**
39
+ * Rebuild the entire index from a flat list of tools.
40
+ */
41
+ rebuild(tools: Array<{
42
+ server: string;
43
+ tool: string;
44
+ description: string;
45
+ }>): void;
46
+ /**
47
+ * Search for tools similar to `query`.
48
+ */
49
+ search(query: string, topK?: number, serverFilter?: string[]): SearchResult[];
50
+ get size(): number;
51
+ clear(): void;
52
+ }
53
+ //# sourceMappingURL=vector-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-index.d.ts","sourceRoot":"","sources":["../../../src/runtime/findtool/vector-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAqB;IAEpC;;;OAGG;IACH,YAAY,CACV,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,GAClD,IAAI;IAWP;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIlC;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;IASlF;;OAEG;IACH,MAAM,CACJ,KAAK,EAAE,MAAM,EACb,IAAI,SAAI,EACR,YAAY,CAAC,EAAE,MAAM,EAAE,GACtB,YAAY,EAAE;IAmBjB,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,KAAK,IAAI,IAAI;CAGd"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * In-memory vector index for tool embeddings
3
+ *
4
+ * Stores Float32Array embeddings for each registered MCP tool and provides
5
+ * cosine-similarity nearest-neighbour search. Re-indexes on registry hot-reload.
6
+ *
7
+ * For large deployments (>10k tools) consider replacing with hnswlib-node or
8
+ * LanceDB (set $LANCEDB_URL to enable the remote backend).
9
+ *
10
+ * @module runtime/findtool/vector-index
11
+ */
12
+ import { embed, cosineSimilarity } from './embed.js';
13
+ export class VectorIndex {
14
+ entries = [];
15
+ /**
16
+ * Add or replace all tools for a server. Existing entries for that
17
+ * server are removed first.
18
+ */
19
+ upsertServer(server, tools) {
20
+ // Remove existing entries for this server
21
+ this.entries = this.entries.filter((e) => e.server !== server);
22
+ for (const { tool, description } of tools) {
23
+ const text = `${tool}\n${description}`;
24
+ const vector = embed(text);
25
+ this.entries.push({ server, tool, description, vector });
26
+ }
27
+ }
28
+ /**
29
+ * Remove all entries for a server.
30
+ */
31
+ removeServer(server) {
32
+ this.entries = this.entries.filter((e) => e.server !== server);
33
+ }
34
+ /**
35
+ * Rebuild the entire index from a flat list of tools.
36
+ */
37
+ rebuild(tools) {
38
+ this.entries = tools.map(({ server, tool, description }) => ({
39
+ server,
40
+ tool,
41
+ description,
42
+ vector: embed(`${tool}\n${description}`),
43
+ }));
44
+ }
45
+ /**
46
+ * Search for tools similar to `query`.
47
+ */
48
+ search(query, topK = 5, serverFilter) {
49
+ if (this.entries.length === 0)
50
+ return [];
51
+ const queryVec = embed(query);
52
+ const candidates = serverFilter
53
+ ? this.entries.filter((e) => serverFilter.includes(e.server))
54
+ : this.entries;
55
+ const scored = candidates.map((e) => ({
56
+ server: e.server,
57
+ tool: e.tool,
58
+ description: e.description,
59
+ score: cosineSimilarity(queryVec, e.vector),
60
+ }));
61
+ scored.sort((a, b) => b.score - a.score);
62
+ return scored.slice(0, topK);
63
+ }
64
+ get size() {
65
+ return this.entries.length;
66
+ }
67
+ clear() {
68
+ this.entries = [];
69
+ }
70
+ }
71
+ //# sourceMappingURL=vector-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"vector-index.js","sourceRoot":"","sources":["../../../src/runtime/findtool/vector-index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAgBrD,MAAM,OAAO,WAAW;IACd,OAAO,GAAkB,EAAE,CAAC;IAEpC;;;OAGG;IACH,YAAY,CACV,MAAc,EACd,KAAmD;QAEnD,0CAA0C;QAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QAE/D,KAAK,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,KAAK,EAAE,CAAC;YAC1C,MAAM,IAAI,GAAG,GAAG,IAAI,KAAK,WAAW,EAAE,CAAC;YACvC,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,MAAc;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;IACjE,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,KAAmE;QACzE,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;YAC3D,MAAM;YACN,IAAI;YACJ,WAAW;YACX,MAAM,EAAE,KAAK,CAAC,GAAG,IAAI,KAAK,WAAW,EAAE,CAAC;SACzC,CAAC,CAAC,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CACJ,KAAa,EACb,IAAI,GAAG,CAAC,EACR,YAAuB;QAEvB,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEzC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,UAAU,GAAG,YAAY;YAC7B,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC7D,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;QAEjB,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACpC,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,KAAK,EAAE,gBAAgB,CAAC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC;SAC5C,CAAC,CAAC,CAAC;QAEJ,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACzC,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;CACF"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * mcp.budget — Token budget enforcement helper
3
+ *
4
+ * Wraps an async function call and automatically trims the result to fit
5
+ * within a token budget. If the result cannot be trimmed below the budget,
6
+ * throws BudgetExceededError.
7
+ *
8
+ * Token estimation: 1 token ≈ 4 characters (conservative heuristic,
9
+ * same as summarize.ts).
10
+ *
11
+ * @module runtime/helpers/budget
12
+ */
13
+ export declare class BudgetExceededError extends Error {
14
+ readonly estimatedTokens: number;
15
+ readonly maxTokens: number;
16
+ constructor(estimatedTokens: number, maxTokens: number);
17
+ }
18
+ export declare function estimateTokens(data: unknown): number;
19
+ /**
20
+ * Execute `fn` and auto-trim its return value to fit within `maxTokens`.
21
+ * Throws `BudgetExceededError` if the result cannot be trimmed.
22
+ *
23
+ * @example
24
+ * const result = await budget(500, async () => mcp.github.list_issues({ repo: 'foo' }));
25
+ */
26
+ export declare function budget<T>(maxTokens: number, fn: () => T | Promise<T>): Promise<T>;
27
+ //# sourceMappingURL=budget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../../src/runtime/helpers/budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AASH,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;gBAEf,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;CAQvD;AAQD,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAOpD;AAqDD;;;;;;GAMG;AACH,wBAAsB,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CASvF"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * mcp.budget — Token budget enforcement helper
3
+ *
4
+ * Wraps an async function call and automatically trims the result to fit
5
+ * within a token budget. If the result cannot be trimmed below the budget,
6
+ * throws BudgetExceededError.
7
+ *
8
+ * Token estimation: 1 token ≈ 4 characters (conservative heuristic,
9
+ * same as summarize.ts).
10
+ *
11
+ * @module runtime/helpers/budget
12
+ */
13
+ import { compact } from './compact.js';
14
+ import { summarize } from './summarize.js';
15
+ // ─────────────────────────────────────────────────────────────────────────────
16
+ // Error type
17
+ // ─────────────────────────────────────────────────────────────────────────────
18
+ export class BudgetExceededError extends Error {
19
+ estimatedTokens;
20
+ maxTokens;
21
+ constructor(estimatedTokens, maxTokens) {
22
+ super(`Result exceeds token budget after trimming: estimated ${estimatedTokens} tokens, budget ${maxTokens} tokens`);
23
+ this.name = 'BudgetExceededError';
24
+ this.estimatedTokens = estimatedTokens;
25
+ this.maxTokens = maxTokens;
26
+ }
27
+ }
28
+ // ─────────────────────────────────────────────────────────────────────────────
29
+ // Token estimation
30
+ // ─────────────────────────────────────────────────────────────────────────────
31
+ const CHARS_PER_TOKEN = 4;
32
+ export function estimateTokens(data) {
33
+ try {
34
+ const serialized = JSON.stringify(data) ?? String(data);
35
+ return Math.ceil(serialized.length / CHARS_PER_TOKEN);
36
+ }
37
+ catch {
38
+ return Math.ceil(String(data).length / CHARS_PER_TOKEN);
39
+ }
40
+ }
41
+ // ─────────────────────────────────────────────────────────────────────────────
42
+ // Trimming strategy
43
+ // ─────────────────────────────────────────────────────────────────────────────
44
+ /**
45
+ * Attempt to trim `data` to fit within `maxTokens`.
46
+ * Strategy:
47
+ * 1. Try compact with progressive maxItems reduction (100 → 50 → 20 → 5)
48
+ * 2. Try summarize (list → paragraph)
49
+ * 3. If still over budget, throw BudgetExceededError
50
+ */
51
+ function tryTrim(data, maxTokens) {
52
+ const maxChars = maxTokens * CHARS_PER_TOKEN;
53
+ // Step 1: progressive compact on arrays
54
+ if (Array.isArray(data)) {
55
+ for (const maxItems of [100, 50, 20, 10, 5, 1]) {
56
+ const trimmed = compact(data, { maxItems, maxStringLength: 200 });
57
+ if (estimateTokens(trimmed) <= maxTokens)
58
+ return trimmed;
59
+ }
60
+ }
61
+ // Step 2: compact objects with depth restriction
62
+ if (typeof data === 'object' && data !== null) {
63
+ for (const maxDepth of [5, 3, 2, 1]) {
64
+ const trimmed = compact(data, { maxDepth, maxItems: 20, maxStringLength: 200 });
65
+ if (estimateTokens(trimmed) <= maxTokens)
66
+ return trimmed;
67
+ }
68
+ }
69
+ // Step 3: summarize as list
70
+ const listSummary = summarize(data, { maxTokens, style: 'list' });
71
+ if (estimateTokens(listSummary) <= maxTokens)
72
+ return listSummary;
73
+ // Step 4: summarize as paragraph (more aggressive)
74
+ const paraSummary = summarize(data, { maxTokens, style: 'paragraph' });
75
+ if (estimateTokens(paraSummary) <= maxTokens)
76
+ return paraSummary;
77
+ // Step 5: raw string clip
78
+ const raw = typeof data === 'string' ? data : JSON.stringify(data) ?? String(data);
79
+ const clipped = raw.slice(0, maxChars - 1) + '…';
80
+ if (estimateTokens(clipped) <= maxTokens)
81
+ return clipped;
82
+ // Untrimmable
83
+ throw new BudgetExceededError(estimateTokens(data), maxTokens);
84
+ }
85
+ // ─────────────────────────────────────────────────────────────────────────────
86
+ // Public API
87
+ // ─────────────────────────────────────────────────────────────────────────────
88
+ /**
89
+ * Execute `fn` and auto-trim its return value to fit within `maxTokens`.
90
+ * Throws `BudgetExceededError` if the result cannot be trimmed.
91
+ *
92
+ * @example
93
+ * const result = await budget(500, async () => mcp.github.list_issues({ repo: 'foo' }));
94
+ */
95
+ export async function budget(maxTokens, fn) {
96
+ const result = await fn();
97
+ const estimated = estimateTokens(result);
98
+ if (estimated <= maxTokens) {
99
+ return result;
100
+ }
101
+ return tryTrim(result, maxTokens);
102
+ }
103
+ //# sourceMappingURL=budget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget.js","sourceRoot":"","sources":["../../../src/runtime/helpers/budget.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * mcp.compact — Field selection and data trimming helper
3
+ *
4
+ * Zero-roundtrip sandbox helper. Reduces large data objects to only the
5
+ * fields the caller cares about, truncates arrays, clips strings, and
6
+ * limits nesting depth. All operations are synchronous and in-process.
7
+ *
8
+ * @module runtime/helpers/compact
9
+ */
10
+ export interface CompactOptions {
11
+ /**
12
+ * Dot-path field selectors to retain. Supports nested paths like
13
+ * 'labels.name'. If omitted, all fields are retained (only structural
14
+ * limits apply).
15
+ */
16
+ fields?: string[];
17
+ /** Maximum number of items to retain in any array. */
18
+ maxItems?: number;
19
+ /** Maximum object nesting depth (root = depth 0). */
20
+ maxDepth?: number;
21
+ /** Maximum character length for any string value. */
22
+ maxStringLength?: number;
23
+ }
24
+ /**
25
+ * Compact a data value by selecting fields, truncating arrays, clipping
26
+ * strings, and limiting nesting depth.
27
+ *
28
+ * @example
29
+ * const lean = compact(issues, { fields: ['id', 'title', 'labels.name'], maxItems: 20 });
30
+ */
31
+ export declare function compact<T>(data: T, options?: CompactOptions): T;
32
+ //# sourceMappingURL=compact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.d.ts","sourceRoot":"","sources":["../../../src/runtime/helpers/compact.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAuFD;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,GAAE,cAAmB,GAAG,CAAC,CAOnE"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * mcp.compact — Field selection and data trimming helper
3
+ *
4
+ * Zero-roundtrip sandbox helper. Reduces large data objects to only the
5
+ * fields the caller cares about, truncates arrays, clips strings, and
6
+ * limits nesting depth. All operations are synchronous and in-process.
7
+ *
8
+ * @module runtime/helpers/compact
9
+ */
10
+ // ─────────────────────────────────────────────────────────────────────────────
11
+ // Internal helpers
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ /**
14
+ * Parse a dot-path like "labels.name" into a nested selector tree.
15
+ * { labels: { name: true }, id: true }
16
+ */
17
+ function buildSelectorTree(fields) {
18
+ const tree = {};
19
+ for (const field of fields) {
20
+ const parts = field.split('.');
21
+ let node = tree;
22
+ for (let i = 0; i < parts.length; i++) {
23
+ const part = parts[i] ?? '';
24
+ if (i === parts.length - 1) {
25
+ node[part] = true;
26
+ }
27
+ else {
28
+ if (typeof node[part] !== 'object' || node[part] === null) {
29
+ node[part] = {};
30
+ }
31
+ node = node[part];
32
+ }
33
+ }
34
+ }
35
+ return tree;
36
+ }
37
+ function trimValue(value, selector, opts, depth) {
38
+ const maxDepth = opts.maxDepth ?? Infinity;
39
+ if (depth > maxDepth) {
40
+ return typeof value === 'object' && value !== null ? '[truncated]' : value;
41
+ }
42
+ if (typeof value === 'string') {
43
+ const max = opts.maxStringLength;
44
+ if (max !== undefined && value.length > max) {
45
+ return value.slice(0, max) + '…';
46
+ }
47
+ return value;
48
+ }
49
+ if (Array.isArray(value)) {
50
+ const maxItems = opts.maxItems;
51
+ const arr = maxItems !== undefined ? value.slice(0, maxItems) : value;
52
+ return arr.map((item) => trimValue(item, selector, opts, depth + 1));
53
+ }
54
+ if (typeof value === 'object' && value !== null) {
55
+ const obj = value;
56
+ const result = {};
57
+ if (selector && Object.keys(selector).length > 0) {
58
+ // Only keep selected keys
59
+ for (const key of Object.keys(selector)) {
60
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
61
+ const childSelector = selector[key];
62
+ const nextSelector = childSelector === true ? null : childSelector;
63
+ result[key] = trimValue(obj[key], nextSelector, opts, depth + 1);
64
+ }
65
+ }
66
+ }
67
+ else {
68
+ // No field filter — apply structural limits only
69
+ for (const key of Object.keys(obj)) {
70
+ result[key] = trimValue(obj[key], null, opts, depth + 1);
71
+ }
72
+ }
73
+ return result;
74
+ }
75
+ return value;
76
+ }
77
+ // ─────────────────────────────────────────────────────────────────────────────
78
+ // Public API
79
+ // ─────────────────────────────────────────────────────────────────────────────
80
+ /**
81
+ * Compact a data value by selecting fields, truncating arrays, clipping
82
+ * strings, and limiting nesting depth.
83
+ *
84
+ * @example
85
+ * const lean = compact(issues, { fields: ['id', 'title', 'labels.name'], maxItems: 20 });
86
+ */
87
+ export function compact(data, options = {}) {
88
+ const selector = options.fields && options.fields.length > 0
89
+ ? buildSelectorTree(options.fields)
90
+ : null;
91
+ return trimValue(data, selector, options, 0);
92
+ }
93
+ //# sourceMappingURL=compact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compact.js","sourceRoot":"","sources":["../../../src/runtime/helpers/compact.ts"],"names":[],"mappings":"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"}