@nitrostack/core 1.0.17 → 1.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/dist/core/app-decorator.d.ts +5 -0
  2. package/dist/core/app-decorator.d.ts.map +1 -1
  3. package/dist/core/app-decorator.js +2 -1
  4. package/dist/core/app-decorator.js.map +1 -1
  5. package/dist/core/builders.d.ts.map +1 -1
  6. package/dist/core/builders.js +2 -0
  7. package/dist/core/builders.js.map +1 -1
  8. package/dist/core/decorators.d.ts +11 -0
  9. package/dist/core/decorators.d.ts.map +1 -1
  10. package/dist/core/decorators.js.map +1 -1
  11. package/dist/core/health/health-checks.resource.d.ts +4 -3
  12. package/dist/core/health/health-checks.resource.d.ts.map +1 -1
  13. package/dist/core/health/health-checks.resource.js +35 -8
  14. package/dist/core/health/health-checks.resource.js.map +1 -1
  15. package/dist/core/health/health.interface.d.ts +40 -0
  16. package/dist/core/health/health.interface.d.ts.map +1 -0
  17. package/dist/core/health/health.interface.js +2 -0
  18. package/dist/core/health/health.interface.js.map +1 -0
  19. package/dist/core/index.d.ts +11 -2
  20. package/dist/core/index.d.ts.map +1 -1
  21. package/dist/core/index.js +9 -1
  22. package/dist/core/index.js.map +1 -1
  23. package/dist/core/interceptors/data-spillover.interceptor.d.ts +30 -0
  24. package/dist/core/interceptors/data-spillover.interceptor.d.ts.map +1 -0
  25. package/dist/core/interceptors/data-spillover.interceptor.js +174 -0
  26. package/dist/core/interceptors/data-spillover.interceptor.js.map +1 -0
  27. package/dist/core/interceptors/interceptor.decorator.d.ts +17 -8
  28. package/dist/core/interceptors/interceptor.decorator.d.ts.map +1 -1
  29. package/dist/core/interceptors/interceptor.decorator.js +36 -11
  30. package/dist/core/interceptors/interceptor.decorator.js.map +1 -1
  31. package/dist/core/interceptors/interceptor.interface.d.ts +4 -0
  32. package/dist/core/interceptors/interceptor.interface.d.ts.map +1 -1
  33. package/dist/core/interceptors/spillover/fs-spillover.store.d.ts +54 -0
  34. package/dist/core/interceptors/spillover/fs-spillover.store.d.ts.map +1 -0
  35. package/dist/core/interceptors/spillover/fs-spillover.store.js +302 -0
  36. package/dist/core/interceptors/spillover/fs-spillover.store.js.map +1 -0
  37. package/dist/core/interceptors/spillover/index.d.ts +6 -0
  38. package/dist/core/interceptors/spillover/index.d.ts.map +1 -0
  39. package/dist/core/interceptors/spillover/index.js +6 -0
  40. package/dist/core/interceptors/spillover/index.js.map +1 -0
  41. package/dist/core/interceptors/spillover/memory-spillover.store.d.ts +25 -0
  42. package/dist/core/interceptors/spillover/memory-spillover.store.d.ts.map +1 -0
  43. package/dist/core/interceptors/spillover/memory-spillover.store.js +115 -0
  44. package/dist/core/interceptors/spillover/memory-spillover.store.js.map +1 -0
  45. package/dist/core/interceptors/spillover/preview-generator.d.ts +7 -0
  46. package/dist/core/interceptors/spillover/preview-generator.d.ts.map +1 -0
  47. package/dist/core/interceptors/spillover/preview-generator.js +79 -0
  48. package/dist/core/interceptors/spillover/preview-generator.js.map +1 -0
  49. package/dist/core/interceptors/spillover/spillover-store.interface.d.ts +20 -0
  50. package/dist/core/interceptors/spillover/spillover-store.interface.d.ts.map +1 -0
  51. package/dist/core/interceptors/spillover/spillover-store.interface.js +2 -0
  52. package/dist/core/interceptors/spillover/spillover-store.interface.js.map +1 -0
  53. package/dist/core/interceptors/spillover/types.d.ts +71 -0
  54. package/dist/core/interceptors/spillover/types.d.ts.map +1 -0
  55. package/dist/core/interceptors/spillover/types.js +12 -0
  56. package/dist/core/interceptors/spillover/types.js.map +1 -0
  57. package/dist/core/protocol/adapter.d.ts +7 -1
  58. package/dist/core/protocol/adapter.d.ts.map +1 -1
  59. package/dist/core/protocol/modern-v2.adapter.d.ts +95 -2
  60. package/dist/core/protocol/modern-v2.adapter.d.ts.map +1 -1
  61. package/dist/core/protocol/modern-v2.adapter.js +703 -165
  62. package/dist/core/protocol/modern-v2.adapter.js.map +1 -1
  63. package/dist/core/server.d.ts +104 -4
  64. package/dist/core/server.d.ts.map +1 -1
  65. package/dist/core/server.js +465 -52
  66. package/dist/core/server.js.map +1 -1
  67. package/dist/core/task.d.ts.map +1 -1
  68. package/dist/core/task.js +8 -7
  69. package/dist/core/task.js.map +1 -1
  70. package/dist/core/tool.d.ts +12 -3
  71. package/dist/core/tool.d.ts.map +1 -1
  72. package/dist/core/tool.js +21 -3
  73. package/dist/core/tool.js.map +1 -1
  74. package/dist/core/transforms/catalog.transform.d.ts +40 -0
  75. package/dist/core/transforms/catalog.transform.d.ts.map +1 -0
  76. package/dist/core/transforms/catalog.transform.js +52 -0
  77. package/dist/core/transforms/catalog.transform.js.map +1 -0
  78. package/dist/core/transforms/code-mode/code-mode.transform.d.ts +75 -0
  79. package/dist/core/transforms/code-mode/code-mode.transform.d.ts.map +1 -0
  80. package/dist/core/transforms/code-mode/code-mode.transform.js +226 -0
  81. package/dist/core/transforms/code-mode/code-mode.transform.js.map +1 -0
  82. package/dist/core/transforms/code-mode/destructive-guard.d.ts +7 -0
  83. package/dist/core/transforms/code-mode/destructive-guard.d.ts.map +1 -0
  84. package/dist/core/transforms/code-mode/destructive-guard.js +18 -0
  85. package/dist/core/transforms/code-mode/destructive-guard.js.map +1 -0
  86. package/dist/core/transforms/code-mode/guest-evaluator.d.ts +17 -0
  87. package/dist/core/transforms/code-mode/guest-evaluator.d.ts.map +1 -0
  88. package/dist/core/transforms/code-mode/guest-evaluator.js +277 -0
  89. package/dist/core/transforms/code-mode/guest-evaluator.js.map +1 -0
  90. package/dist/core/transforms/code-mode/index.d.ts +11 -0
  91. package/dist/core/transforms/code-mode/index.d.ts.map +1 -0
  92. package/dist/core/transforms/code-mode/index.js +11 -0
  93. package/dist/core/transforms/code-mode/index.js.map +1 -0
  94. package/dist/core/transforms/code-mode/ipc-messages.d.ts +31 -0
  95. package/dist/core/transforms/code-mode/ipc-messages.d.ts.map +1 -0
  96. package/dist/core/transforms/code-mode/ipc-messages.js +2 -0
  97. package/dist/core/transforms/code-mode/ipc-messages.js.map +1 -0
  98. package/dist/core/transforms/code-mode/legible-error.d.ts +8 -0
  99. package/dist/core/transforms/code-mode/legible-error.d.ts.map +1 -0
  100. package/dist/core/transforms/code-mode/legible-error.js +17 -0
  101. package/dist/core/transforms/code-mode/legible-error.js.map +1 -0
  102. package/dist/core/transforms/code-mode/quickjs-wasm.provider.d.ts +25 -0
  103. package/dist/core/transforms/code-mode/quickjs-wasm.provider.d.ts.map +1 -0
  104. package/dist/core/transforms/code-mode/quickjs-wasm.provider.js +31 -0
  105. package/dist/core/transforms/code-mode/quickjs-wasm.provider.js.map +1 -0
  106. package/dist/core/transforms/code-mode/sandbox.interface.d.ts +10 -0
  107. package/dist/core/transforms/code-mode/sandbox.interface.d.ts.map +1 -0
  108. package/dist/core/transforms/code-mode/sandbox.interface.js +2 -0
  109. package/dist/core/transforms/code-mode/sandbox.interface.js.map +1 -0
  110. package/dist/core/transforms/code-mode/sandbox.worker.d.ts +2 -0
  111. package/dist/core/transforms/code-mode/sandbox.worker.d.ts.map +1 -0
  112. package/dist/core/transforms/code-mode/sandbox.worker.js +69 -0
  113. package/dist/core/transforms/code-mode/sandbox.worker.js.map +1 -0
  114. package/dist/core/transforms/code-mode/synthetic-tools.d.ts +23 -0
  115. package/dist/core/transforms/code-mode/synthetic-tools.d.ts.map +1 -0
  116. package/dist/core/transforms/code-mode/synthetic-tools.js +112 -0
  117. package/dist/core/transforms/code-mode/synthetic-tools.js.map +1 -0
  118. package/dist/core/transforms/code-mode/types.d.ts +32 -0
  119. package/dist/core/transforms/code-mode/types.d.ts.map +1 -0
  120. package/dist/core/transforms/code-mode/types.js +2 -0
  121. package/dist/core/transforms/code-mode/types.js.map +1 -0
  122. package/dist/core/transforms/code-mode/worker-pool.d.ts +71 -0
  123. package/dist/core/transforms/code-mode/worker-pool.d.ts.map +1 -0
  124. package/dist/core/transforms/code-mode/worker-pool.js +435 -0
  125. package/dist/core/transforms/code-mode/worker-pool.js.map +1 -0
  126. package/dist/core/transforms/index.d.ts +6 -0
  127. package/dist/core/transforms/index.d.ts.map +1 -0
  128. package/dist/core/transforms/index.js +6 -0
  129. package/dist/core/transforms/index.js.map +1 -0
  130. package/dist/core/transforms/search/base-search.transform.d.ts +59 -0
  131. package/dist/core/transforms/search/base-search.transform.d.ts.map +1 -0
  132. package/dist/core/transforms/search/base-search.transform.js +169 -0
  133. package/dist/core/transforms/search/base-search.transform.js.map +1 -0
  134. package/dist/core/transforms/search/bm25-search.transform.d.ts +27 -0
  135. package/dist/core/transforms/search/bm25-search.transform.d.ts.map +1 -0
  136. package/dist/core/transforms/search/bm25-search.transform.js +37 -0
  137. package/dist/core/transforms/search/bm25-search.transform.js.map +1 -0
  138. package/dist/core/transforms/search/bm25.engine.d.ts +46 -0
  139. package/dist/core/transforms/search/bm25.engine.d.ts.map +1 -0
  140. package/dist/core/transforms/search/bm25.engine.js +160 -0
  141. package/dist/core/transforms/search/bm25.engine.js.map +1 -0
  142. package/dist/core/transforms/search/index.d.ts +9 -0
  143. package/dist/core/transforms/search/index.d.ts.map +1 -0
  144. package/dist/core/transforms/search/index.js +9 -0
  145. package/dist/core/transforms/search/index.js.map +1 -0
  146. package/dist/core/transforms/search/regex-match.worker.d.ts +2 -0
  147. package/dist/core/transforms/search/regex-match.worker.d.ts.map +1 -0
  148. package/dist/core/transforms/search/regex-match.worker.js +19 -0
  149. package/dist/core/transforms/search/regex-match.worker.js.map +1 -0
  150. package/dist/core/transforms/search/regex-search.transform.d.ts +41 -0
  151. package/dist/core/transforms/search/regex-search.transform.d.ts.map +1 -0
  152. package/dist/core/transforms/search/regex-search.transform.js +237 -0
  153. package/dist/core/transforms/search/regex-search.transform.js.map +1 -0
  154. package/dist/core/transforms/search/synthetic-tools.d.ts +11 -0
  155. package/dist/core/transforms/search/synthetic-tools.d.ts.map +1 -0
  156. package/dist/core/transforms/search/synthetic-tools.js +76 -0
  157. package/dist/core/transforms/search/synthetic-tools.js.map +1 -0
  158. package/dist/core/transforms/search/tokenizer.d.ts +11 -0
  159. package/dist/core/transforms/search/tokenizer.d.ts.map +1 -0
  160. package/dist/core/transforms/search/tokenizer.js +38 -0
  161. package/dist/core/transforms/search/tokenizer.js.map +1 -0
  162. package/dist/core/transforms/search/tool-serializer.d.ts +6 -0
  163. package/dist/core/transforms/search/tool-serializer.d.ts.map +1 -0
  164. package/dist/core/transforms/search/tool-serializer.js +41 -0
  165. package/dist/core/transforms/search/tool-serializer.js.map +1 -0
  166. package/dist/core/transforms/search/types.d.ts +36 -0
  167. package/dist/core/transforms/search/types.d.ts.map +1 -0
  168. package/dist/core/transforms/search/types.js +2 -0
  169. package/dist/core/transforms/search/types.js.map +1 -0
  170. package/dist/core/transforms/tool-cache-key.d.ts +15 -0
  171. package/dist/core/transforms/tool-cache-key.d.ts.map +1 -0
  172. package/dist/core/transforms/tool-cache-key.js +61 -0
  173. package/dist/core/transforms/tool-cache-key.js.map +1 -0
  174. package/dist/core/transforms/transform.interface.d.ts +34 -0
  175. package/dist/core/transforms/transform.interface.d.ts.map +1 -0
  176. package/dist/core/transforms/transform.interface.js +2 -0
  177. package/dist/core/transforms/transform.interface.js.map +1 -0
  178. package/dist/core/transforms/validate-tool-arguments.d.ts +10 -0
  179. package/dist/core/transforms/validate-tool-arguments.d.ts.map +1 -0
  180. package/dist/core/transforms/validate-tool-arguments.js +62 -0
  181. package/dist/core/transforms/validate-tool-arguments.js.map +1 -0
  182. package/dist/core/transforms/visibility/index.d.ts +3 -0
  183. package/dist/core/transforms/visibility/index.d.ts.map +1 -0
  184. package/dist/core/transforms/visibility/index.js +3 -0
  185. package/dist/core/transforms/visibility/index.js.map +1 -0
  186. package/dist/core/transforms/visibility/session-store.d.ts +132 -0
  187. package/dist/core/transforms/visibility/session-store.d.ts.map +1 -0
  188. package/dist/core/transforms/visibility/session-store.js +330 -0
  189. package/dist/core/transforms/visibility/session-store.js.map +1 -0
  190. package/dist/core/transforms/visibility/visibility.transform.d.ts +42 -0
  191. package/dist/core/transforms/visibility/visibility.transform.d.ts.map +1 -0
  192. package/dist/core/transforms/visibility/visibility.transform.js +109 -0
  193. package/dist/core/transforms/visibility/visibility.transform.js.map +1 -0
  194. package/dist/core/types.d.ts +60 -0
  195. package/dist/core/types.d.ts.map +1 -1
  196. package/dist/testing/index.d.ts.map +1 -1
  197. package/dist/testing/index.js +3 -0
  198. package/dist/testing/index.js.map +1 -1
  199. package/package.json +8 -2
@@ -0,0 +1,19 @@
1
+ import { parentPort, workerData } from 'node:worker_threads';
2
+ /**
3
+ * Off-thread regular expression match. The host terminates this worker if the
4
+ * match does not finish, so a catastrophic pattern cannot block the server.
5
+ */
6
+ const data = workerData;
7
+ try {
8
+ const pattern = String(data?.pattern ?? '');
9
+ const fields = Array.isArray(data?.fields) ? data.fields : [];
10
+ const regex = new RegExp(pattern, 'i');
11
+ parentPort?.postMessage({
12
+ ok: true,
13
+ hits: fields.map((field) => regex.test(String(field))),
14
+ });
15
+ }
16
+ catch {
17
+ parentPort?.postMessage({ ok: false });
18
+ }
19
+ //# sourceMappingURL=regex-match.worker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex-match.worker.js","sourceRoot":"","sources":["../../../../src/core/transforms/search/regex-match.worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;GAGG;AACH,MAAM,IAAI,GAAG,UAAsD,CAAC;AAEpE,IAAI,CAAC;IACH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAC9D,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACvC,UAAU,EAAE,WAAW,CAAC;QACtB,EAAE,EAAE,IAAI;QACR,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;KACvD,CAAC,CAAC;AACL,CAAC;AAAC,MAAM,CAAC;IACP,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,41 @@
1
+ import { Worker } from 'node:worker_threads';
2
+ import { Tool } from '../../tool.js';
3
+ import { BaseSearchTransform } from './base-search.transform.js';
4
+ import { SearchTransformOptions } from './types.js';
5
+ /** After this quiet period a disabled transform may use the worker again. */
6
+ export declare const REGEX_TIMEOUT_COOLDOWN_MS = 60000;
7
+ type RegexWorkerFactory = (filename: string, options: {
8
+ workerData: {
9
+ pattern: string;
10
+ fields: string[];
11
+ };
12
+ resourceLimits: {
13
+ maxOldGenerationSizeMb: number;
14
+ };
15
+ }) => Worker;
16
+ /** Test hook: replace worker construction. Pass undefined to restore the real Worker. */
17
+ export declare function setRegexWorkerFactoryForTests(factory?: RegexWorkerFactory): void;
18
+ /** Test hook: highest concurrent regex workers since the last reset. */
19
+ export declare function regexWorkerPeak(): number;
20
+ /** Test hook. */
21
+ export declare function resetRegexWorkerStats(): void;
22
+ export declare class RegexSearchTransform extends BaseSearchTransform {
23
+ readonly name = "RegexSearchTransform";
24
+ private toolsList;
25
+ private toolMetadata;
26
+ private consecutiveRegexTimeouts;
27
+ private regexDisabledUntil;
28
+ constructor(options?: SearchTransformOptions);
29
+ protected updateIndex(tools: Tool[], _hash: string): void;
30
+ protected search(query: string, limit: number): Promise<Tool[]>;
31
+ private regexMatchingDisabled;
32
+ /**
33
+ * The query reaches us straight from the MCP client. Compiling it on the server
34
+ * thread hands the caller an event-loop stall via catastrophic backtracking.
35
+ * Literal substring matching is the default. Opt-in regex runs in a worker and
36
+ * falls back to a literal match when the pattern is invalid or does not finish.
37
+ */
38
+ private matchFields;
39
+ }
40
+ export {};
41
+ //# sourceMappingURL=regex-search.transform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex-search.transform.d.ts","sourceRoot":"","sources":["../../../../src/core/transforms/search/regex-search.transform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAI7C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAUpD,6EAA6E;AAC7E,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAKhD,KAAK,kBAAkB,GAAG,CACxB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE;IAAE,UAAU,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAAC,cAAc,EAAE;QAAE,sBAAsB,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,KAC/G,MAAM,CAAC;AAIZ,yFAAyF;AACzF,wBAAgB,6BAA6B,CAAC,OAAO,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAEhF;AAED,wEAAwE;AACxE,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,iBAAiB;AACjB,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AA4GD,qBAAa,oBAAqB,SAAQ,mBAAmB;IAC3D,QAAQ,CAAC,IAAI,0BAA0B;IACvC,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,wBAAwB,CAAK;IACrC,OAAO,CAAC,kBAAkB,CAAK;gBAEnB,OAAO,GAAE,sBAA2B;IAIhD,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;cA2CzC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAqCrE,OAAO,CAAC,qBAAqB;IAU7B;;;;;OAKG;YACW,WAAW;CAwB1B"}
@@ -0,0 +1,237 @@
1
+ import { Worker } from 'node:worker_threads';
2
+ import { existsSync } from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { BaseSearchTransform } from './base-search.transform.js';
6
+ /** Upper bound on an opted-in regex query. */
7
+ const MAX_REGEX_PATTERN_LENGTH = 200;
8
+ /** A match that is still running after this is treated as catastrophic and abandoned. */
9
+ const REGEX_MATCH_TIMEOUT_MS = 50;
10
+ /** Concurrent off-thread matches. Further queries fall back to a literal search. */
11
+ const MAX_REGEX_WORKERS = 4;
12
+ /** Timeouts in a row after which opted-in regex stays literal until the cooldown. */
13
+ const REGEX_TIMEOUTS_BEFORE_LITERAL = 3;
14
+ /** After this quiet period a disabled transform may use the worker again. */
15
+ export const REGEX_TIMEOUT_COOLDOWN_MS = 60_000;
16
+ let regexWorkersInflight = 0;
17
+ let regexWorkersPeak = 0;
18
+ let regexWorkerFactory = (filename, options) => new Worker(filename, options);
19
+ /** Test hook: replace worker construction. Pass undefined to restore the real Worker. */
20
+ export function setRegexWorkerFactoryForTests(factory) {
21
+ regexWorkerFactory = factory ?? ((filename, options) => new Worker(filename, options));
22
+ }
23
+ /** Test hook: highest concurrent regex workers since the last reset. */
24
+ export function regexWorkerPeak() {
25
+ return regexWorkersPeak;
26
+ }
27
+ /** Test hook. */
28
+ export function resetRegexWorkerStats() {
29
+ regexWorkersPeak = 0;
30
+ }
31
+ function tryAcquireRegexWorker() {
32
+ if (regexWorkersInflight >= MAX_REGEX_WORKERS)
33
+ return false;
34
+ regexWorkersInflight += 1;
35
+ regexWorkersPeak = Math.max(regexWorkersPeak, regexWorkersInflight);
36
+ return true;
37
+ }
38
+ function releaseRegexWorker() {
39
+ regexWorkersInflight = Math.max(0, regexWorkersInflight - 1);
40
+ }
41
+ /**
42
+ * Runs `new RegExp(pattern, 'i')` against every field off the server event loop.
43
+ * Returns null when the pattern is invalid or the match does not finish in time,
44
+ * so the caller can fall back to a literal substring search.
45
+ */
46
+ function regexWorkerScript() {
47
+ const here = path.dirname(fileURLToPath(import.meta.url));
48
+ const candidates = [
49
+ path.join(here, 'regex-match.worker.js'),
50
+ path.resolve(process.cwd(), 'dist/core/transforms/search/regex-match.worker.js'),
51
+ ];
52
+ return candidates.find((candidate) => existsSync(candidate));
53
+ }
54
+ function matchRegexOffThread(pattern, fields) {
55
+ const script = regexWorkerScript();
56
+ if (!script)
57
+ return Promise.resolve({ status: 'skip' });
58
+ if (!tryAcquireRegexWorker())
59
+ return Promise.resolve({ status: 'skip' });
60
+ return new Promise((resolve) => {
61
+ let worker;
62
+ try {
63
+ worker = regexWorkerFactory(script, {
64
+ workerData: { pattern, fields },
65
+ resourceLimits: { maxOldGenerationSizeMb: 32 },
66
+ });
67
+ }
68
+ catch {
69
+ releaseRegexWorker();
70
+ resolve({ status: 'skip' });
71
+ return;
72
+ }
73
+ let settled = false;
74
+ let released = false;
75
+ let exitWatch;
76
+ const release = () => {
77
+ if (released)
78
+ return;
79
+ released = true;
80
+ if (exitWatch)
81
+ clearTimeout(exitWatch);
82
+ releaseRegexWorker();
83
+ };
84
+ // The slot stays taken until the thread is gone. Releasing on the timer
85
+ // lets the next query spawn another worker while this one is still matching.
86
+ worker.once('exit', () => release());
87
+ const resolveCaller = (outcome) => {
88
+ if (settled)
89
+ return;
90
+ settled = true;
91
+ clearTimeout(timer);
92
+ resolve(outcome);
93
+ };
94
+ const stopWorker = () => {
95
+ void worker.terminate().catch(() => undefined);
96
+ if (released || exitWatch)
97
+ return;
98
+ exitWatch = setTimeout(() => {
99
+ console.warn('Regex worker did not exit after terminate; its slot stays occupied until exit');
100
+ }, 1000);
101
+ };
102
+ const timer = setTimeout(() => {
103
+ resolveCaller({ status: 'timeout' });
104
+ stopWorker();
105
+ }, REGEX_MATCH_TIMEOUT_MS);
106
+ worker.once('message', (msg) => {
107
+ resolveCaller(msg?.ok && Array.isArray(msg.hits)
108
+ ? { status: 'hit', hits: msg.hits }
109
+ : { status: 'skip' });
110
+ stopWorker();
111
+ });
112
+ worker.once('error', () => {
113
+ resolveCaller({ status: 'skip' });
114
+ stopWorker();
115
+ });
116
+ });
117
+ }
118
+ export class RegexSearchTransform extends BaseSearchTransform {
119
+ name = 'RegexSearchTransform';
120
+ toolsList = [];
121
+ toolMetadata = new Map();
122
+ consecutiveRegexTimeouts = 0;
123
+ regexDisabledUntil = 0;
124
+ constructor(options = {}) {
125
+ super(options);
126
+ }
127
+ updateIndex(tools, _hash) {
128
+ const toolMetadata = new Map();
129
+ for (const tool of tools) {
130
+ let paramKeywords = '';
131
+ const schema = tool.inputSchema;
132
+ if (schema) {
133
+ if (schema.properties && typeof schema.properties === 'object') {
134
+ for (const [key, prop] of Object.entries(schema.properties)) {
135
+ paramKeywords += ` ${key}`;
136
+ if (prop && typeof prop === 'object' && prop.description) {
137
+ paramKeywords += ` ${prop.description}`;
138
+ }
139
+ }
140
+ }
141
+ else {
142
+ // Extract Zod schema shape properties if available
143
+ const shape = typeof schema._def?.shape === 'function'
144
+ ? schema._def.shape()
145
+ : schema.shape || schema._def?.shape;
146
+ if (shape && typeof shape === 'object') {
147
+ for (const [key, prop] of Object.entries(shape)) {
148
+ paramKeywords += ` ${key}`;
149
+ if (prop && typeof prop === 'object' && prop.description) {
150
+ paramKeywords += ` ${prop.description}`;
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ toolMetadata.set(tool.name, {
157
+ name: tool.name,
158
+ title: tool.title || '',
159
+ description: tool.description || '',
160
+ paramKeywords,
161
+ });
162
+ }
163
+ this.toolsList = tools;
164
+ this.toolMetadata = toolMetadata;
165
+ }
166
+ async search(query, limit) {
167
+ if (!query || query.trim().length === 0) {
168
+ return [];
169
+ }
170
+ const rows = [];
171
+ const fields = [];
172
+ for (const tool of this.toolsList) {
173
+ const meta = this.toolMetadata.get(tool.name);
174
+ if (!meta)
175
+ continue;
176
+ rows.push(meta);
177
+ fields.push(meta.name, meta.title, meta.description, meta.paramKeywords);
178
+ }
179
+ const hits = await this.matchFields(query, fields);
180
+ const matches = [];
181
+ for (let i = 0; i < rows.length; i++) {
182
+ const meta = rows[i];
183
+ const base = i * 4;
184
+ const hit = hits[base] ||
185
+ (meta.title ? hits[base + 1] : false) ||
186
+ hits[base + 2] ||
187
+ hits[base + 3];
188
+ if (hit) {
189
+ const tool = this.toolsList.find((candidate) => candidate.name === meta.name);
190
+ if (!tool)
191
+ continue;
192
+ matches.push(tool);
193
+ if (matches.length >= limit)
194
+ break;
195
+ }
196
+ }
197
+ return matches;
198
+ }
199
+ regexMatchingDisabled() {
200
+ if (this.consecutiveRegexTimeouts < REGEX_TIMEOUTS_BEFORE_LITERAL)
201
+ return false;
202
+ if (Date.now() >= this.regexDisabledUntil) {
203
+ this.consecutiveRegexTimeouts = 0;
204
+ this.regexDisabledUntil = 0;
205
+ return false;
206
+ }
207
+ return true;
208
+ }
209
+ /**
210
+ * The query reaches us straight from the MCP client. Compiling it on the server
211
+ * thread hands the caller an event-loop stall via catastrophic backtracking.
212
+ * Literal substring matching is the default. Opt-in regex runs in a worker and
213
+ * falls back to a literal match when the pattern is invalid or does not finish.
214
+ */
215
+ async matchFields(query, fields) {
216
+ if (this.options.allowRegex &&
217
+ !this.regexMatchingDisabled() &&
218
+ query.length > 0 &&
219
+ query.length <= MAX_REGEX_PATTERN_LENGTH) {
220
+ const timed = await matchRegexOffThread(query, fields);
221
+ if (timed.status === 'hit' && timed.hits.length === fields.length) {
222
+ this.consecutiveRegexTimeouts = 0;
223
+ this.regexDisabledUntil = 0;
224
+ return timed.hits;
225
+ }
226
+ if (timed.status === 'timeout') {
227
+ this.consecutiveRegexTimeouts += 1;
228
+ if (this.consecutiveRegexTimeouts >= REGEX_TIMEOUTS_BEFORE_LITERAL) {
229
+ this.regexDisabledUntil = Date.now() + REGEX_TIMEOUT_COOLDOWN_MS;
230
+ }
231
+ }
232
+ }
233
+ const needle = query.toLowerCase();
234
+ return fields.map((field) => field.toLowerCase().includes(needle));
235
+ }
236
+ }
237
+ //# sourceMappingURL=regex-search.transform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"regex-search.transform.js","sourceRoot":"","sources":["../../../../src/core/transforms/search/regex-search.transform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGjE,8CAA8C;AAC9C,MAAM,wBAAwB,GAAG,GAAG,CAAC;AACrC,yFAAyF;AACzF,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAClC,oFAAoF;AACpF,MAAM,iBAAiB,GAAG,CAAC,CAAC;AAC5B,qFAAqF;AACrF,MAAM,6BAA6B,GAAG,CAAC,CAAC;AACxC,6EAA6E;AAC7E,MAAM,CAAC,MAAM,yBAAyB,GAAG,MAAM,CAAC;AAEhD,IAAI,oBAAoB,GAAG,CAAC,CAAC;AAC7B,IAAI,gBAAgB,GAAG,CAAC,CAAC;AAOzB,IAAI,kBAAkB,GAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;AAElG,yFAAyF;AACzF,MAAM,UAAU,6BAA6B,CAAC,OAA4B;IACxE,kBAAkB,GAAG,OAAO,IAAI,CAAC,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AACzF,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,eAAe;IAC7B,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED,iBAAiB;AACjB,MAAM,UAAU,qBAAqB;IACnC,gBAAgB,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,qBAAqB;IAC5B,IAAI,oBAAoB,IAAI,iBAAiB;QAAE,OAAO,KAAK,CAAC;IAC5D,oBAAoB,IAAI,CAAC,CAAC;IAC1B,gBAAgB,GAAG,IAAI,CAAC,GAAG,CAAC,gBAAgB,EAAE,oBAAoB,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,kBAAkB;IACzB,oBAAoB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,GAAG,CAAC,CAAC,CAAC;AAC/D,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB;IACxB,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG;QACjB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,uBAAuB,CAAC;QACxC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mDAAmD,CAAC;KACjF,CAAC;IACF,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;AAC/D,CAAC;AAOD,SAAS,mBAAmB,CAAC,OAAe,EAAE,MAAgB;IAC5D,MAAM,MAAM,GAAG,iBAAiB,EAAE,CAAC;IACnC,IAAI,CAAC,MAAM;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACxD,IAAI,CAAC,qBAAqB,EAAE;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAEzE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,MAAc,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,GAAG,kBAAkB,CAAC,MAAM,EAAE;gBAClC,UAAU,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE;gBAC/B,cAAc,EAAE,EAAE,sBAAsB,EAAE,EAAE,EAAE;aAC/C,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,kBAAkB,EAAE,CAAC;YACrB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,SAAoD,CAAC;QAEzD,MAAM,OAAO,GAAG,GAAG,EAAE;YACnB,IAAI,QAAQ;gBAAE,OAAO;YACrB,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,SAAS;gBAAE,YAAY,CAAC,SAAS,CAAC,CAAC;YACvC,kBAAkB,EAAE,CAAC;QACvB,CAAC,CAAC;QAEF,wEAAwE;QACxE,6EAA6E;QAC7E,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAErC,MAAM,aAAa,GAAG,CAAC,OAAuB,EAAE,EAAE;YAChD,IAAI,OAAO;gBAAE,OAAO;YACpB,OAAO,GAAG,IAAI,CAAC;YACf,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,OAAO,CAAC,OAAO,CAAC,CAAC;QACnB,CAAC,CAAC;QAEF,MAAM,UAAU,GAAG,GAAG,EAAE;YACtB,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC/C,IAAI,QAAQ,IAAI,SAAS;gBAAE,OAAO;YAClC,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC1B,OAAO,CAAC,IAAI,CACV,+EAA+E,CAChF,CAAC;YACJ,CAAC,EAAE,IAAI,CAAC,CAAC;QACX,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,aAAa,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;YACrC,UAAU,EAAE,CAAC;QACf,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC3B,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,GAAuC,EAAE,EAAE;YACjE,aAAa,CACX,GAAG,EAAE,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;gBAChC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE;gBACnC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CACvB,CAAC;YACF,UAAU,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE;YACxB,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAClC,UAAU,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AASD,MAAM,OAAO,oBAAqB,SAAQ,mBAAmB;IAClD,IAAI,GAAG,sBAAsB,CAAC;IAC/B,SAAS,GAAW,EAAE,CAAC;IACvB,YAAY,GAAoC,IAAI,GAAG,EAAE,CAAC;IAC1D,wBAAwB,GAAG,CAAC,CAAC;IAC7B,kBAAkB,GAAG,CAAC,CAAC;IAE/B,YAAY,UAAkC,EAAE;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAES,WAAW,CAAC,KAAa,EAAE,KAAa;QAChD,MAAM,YAAY,GAAG,IAAI,GAAG,EAA8B,CAAC;QAE3D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,aAAa,GAAG,EAAE,CAAC;YACvB,MAAM,MAAM,GAAG,IAAI,CAAC,WAAkB,CAAC;YACvC,IAAI,MAAM,EAAE,CAAC;gBACX,IAAI,MAAM,CAAC,UAAU,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;oBAC/D,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;wBAC5D,aAAa,IAAI,IAAI,GAAG,EAAE,CAAC;wBAC3B,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAK,IAAY,CAAC,WAAW,EAAE,CAAC;4BAClE,aAAa,IAAI,IAAK,IAAY,CAAC,WAAW,EAAE,CAAC;wBACnD,CAAC;oBACH,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,mDAAmD;oBACnD,MAAM,KAAK,GACT,OAAO,MAAM,CAAC,IAAI,EAAE,KAAK,KAAK,UAAU;wBACtC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE;wBACrB,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;oBACzC,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;wBACvC,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;4BAChD,aAAa,IAAI,IAAI,GAAG,EAAE,CAAC;4BAC3B,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAK,IAAY,CAAC,WAAW,EAAE,CAAC;gCAClE,aAAa,IAAI,IAAK,IAAY,CAAC,WAAW,EAAE,CAAC;4BACnD,CAAC;wBACH,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;YAED,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE;gBAC1B,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,KAAK,EAAG,IAAY,CAAC,KAAK,IAAI,EAAE;gBAChC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,EAAE;gBACnC,aAAa;aACd,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC;QACvB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACnC,CAAC;IAES,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAAa;QACjD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,IAAI,GAAyB,EAAE,CAAC;QACtC,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,SAAS,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9C,IAAI,CAAC,IAAI;gBAAE,SAAS;YACpB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAW,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;YACnB,MAAM,GAAG,GACP,IAAI,CAAC,IAAI,CAAC;gBACV,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;gBACrC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;gBACd,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;YAEjB,IAAI,GAAG,EAAE,CAAC;gBACR,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC9E,IAAI,CAAC,IAAI;oBAAE,SAAS;gBACpB,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACnB,IAAI,OAAO,CAAC,MAAM,IAAI,KAAK;oBAAE,MAAM;YACrC,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,qBAAqB;QAC3B,IAAI,IAAI,CAAC,wBAAwB,GAAG,6BAA6B;YAAE,OAAO,KAAK,CAAC;QAChF,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1C,IAAI,CAAC,wBAAwB,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC;YAC5B,OAAO,KAAK,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,WAAW,CAAC,KAAa,EAAE,MAAgB;QACvD,IACE,IAAI,CAAC,OAAO,CAAC,UAAU;YACvB,CAAC,IAAI,CAAC,qBAAqB,EAAE;YAC7B,KAAK,CAAC,MAAM,GAAG,CAAC;YAChB,KAAK,CAAC,MAAM,IAAI,wBAAwB,EACxC,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;YACvD,IAAI,KAAK,CAAC,MAAM,KAAK,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;gBAClE,IAAI,CAAC,wBAAwB,GAAG,CAAC,CAAC;gBAClC,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC;gBAC5B,OAAO,KAAK,CAAC,IAAI,CAAC;YACpB,CAAC;YACD,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC/B,IAAI,CAAC,wBAAwB,IAAI,CAAC,CAAC;gBACnC,IAAI,IAAI,CAAC,wBAAwB,IAAI,6BAA6B,EAAE,CAAC;oBACnE,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,yBAAyB,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACnC,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IACrE,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ import { Tool } from '../../tool.js';
2
+ import { ExecutionContext } from '../../types.js';
3
+ import { DetailLevel } from './tool-serializer.js';
4
+ import { validateToolArguments } from '../validate-tool-arguments.js';
5
+ /** One search call cannot dump the whole catalog. */
6
+ export declare const MAX_SEARCH_RESULTS = 20;
7
+ export declare function clampSearchLimit(requested: unknown, fallback: number): number;
8
+ export { validateToolArguments };
9
+ export declare function buildSearchTool(name: string, searchFn: (query: string, limit: number, context?: ExecutionContext) => Promise<Tool[]>, defaultLimit?: number, defaultDetail?: DetailLevel): Tool;
10
+ export declare function buildCallTool(name: string, resolveFn: (name: string, context?: ExecutionContext) => Promise<Tool | undefined>, searchToolName?: string): Tool;
11
+ //# sourceMappingURL=synthetic-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthetic-tools.d.ts","sourceRoot":"","sources":["../../../../src/core/transforms/search/synthetic-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAkB,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK7E;AAED,OAAO,EAAE,qBAAqB,EAAE,CAAC;AAEjC,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,EAAE,CAAC,EACvF,YAAY,GAAE,MAAU,EACxB,aAAa,GAAE,WAAwB,GACtC,IAAI,CAiCN;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,GAAG,SAAS,CAAC,EAClF,cAAc,GAAE,MAAuB,GACtC,IAAI,CAyCN"}
@@ -0,0 +1,76 @@
1
+ import { Tool } from '../../tool.js';
2
+ import { CatalogTransform } from '../catalog.transform.js';
3
+ import { serializeTools } from './tool-serializer.js';
4
+ import { validateToolArguments } from '../validate-tool-arguments.js';
5
+ /** One search call cannot dump the whole catalog. */
6
+ export const MAX_SEARCH_RESULTS = 20;
7
+ export function clampSearchLimit(requested, fallback) {
8
+ if (typeof requested !== 'number' || !Number.isFinite(requested) || requested <= 0) {
9
+ return fallback;
10
+ }
11
+ return Math.min(Math.floor(requested), MAX_SEARCH_RESULTS);
12
+ }
13
+ export { validateToolArguments };
14
+ export function buildSearchTool(name, searchFn, defaultLimit = 5, defaultDetail = 'detailed') {
15
+ return new Tool({
16
+ name,
17
+ description: 'Searches available tools by natural language query or keywords. Returns matching tool names, descriptions, and parameter schemas.',
18
+ inputSchema: {
19
+ type: 'object',
20
+ properties: {
21
+ query: { type: 'string', description: 'Natural language search query or keywords' },
22
+ limit: {
23
+ type: 'number',
24
+ description: `Maximum number of tools to return (default: ${defaultLimit})`,
25
+ },
26
+ detail: {
27
+ type: 'string',
28
+ enum: ['brief', 'detailed', 'full'],
29
+ description: 'Level of detail: brief (name & 1-line summary), detailed (name, summary, and parameters list), full (complete JSON Schema)',
30
+ },
31
+ },
32
+ required: ['query'],
33
+ },
34
+ handler: async (args, ctx) => {
35
+ const limit = clampSearchLimit(args.limit, defaultLimit);
36
+ const detail = args.detail ?? defaultDetail;
37
+ const results = await searchFn(args.query, limit, ctx);
38
+ const text = await serializeTools(results, detail);
39
+ return { content: [{ type: 'text', text }] };
40
+ },
41
+ });
42
+ }
43
+ export function buildCallTool(name, resolveFn, searchToolName = 'search_tools') {
44
+ return new Tool({
45
+ name,
46
+ description: 'Executes a discovered tool by name with the specified arguments object.',
47
+ inputSchema: {
48
+ type: 'object',
49
+ properties: {
50
+ name: { type: 'string', description: 'Name of the tool to execute' },
51
+ arguments: {
52
+ type: 'object',
53
+ description: 'Arguments object matching the target tool parameters',
54
+ },
55
+ },
56
+ required: ['name'],
57
+ },
58
+ handler: async (args, ctx) => {
59
+ if (args.name === name || args.name === searchToolName) {
60
+ throw new Error(`'${args.name}' cannot be invoked through ${name}`);
61
+ }
62
+ const targetTool = await resolveFn(args.name, ctx);
63
+ if (!targetTool) {
64
+ throw new Error(`Tool '${args.name}' not found. Use ${searchToolName} to discover available tools.`);
65
+ }
66
+ const toolArgs = args.arguments ?? {};
67
+ // 1. Validate arguments against target tool's schema before execution.
68
+ // Zod defaults and coercions are applied; JSON Schema checks throw only.
69
+ const parsedArgs = validateToolArguments(targetTool, toolArgs);
70
+ // 2. Execute target tool through full NitroStack pipeline (guards, middleware, interceptors, pipes, handler).
71
+ // withBypass covers catalog listing inside the handler. Authorization already ran in resolveFn.
72
+ return await CatalogTransform.withBypass(() => targetTool.execute(parsedArgs, ctx));
73
+ },
74
+ });
75
+ }
76
+ //# sourceMappingURL=synthetic-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synthetic-tools.js","sourceRoot":"","sources":["../../../../src/core/transforms/search/synthetic-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Standard English stop words set for information retrieval.
3
+ * Preserves common API identifiers like 'id', 'get', 'set', etc.
4
+ */
5
+ export declare const STOP_WORDS: Set<string>;
6
+ /**
7
+ * Splits text into normalized alphanumeric tokens, handling camelCase,
8
+ * snake_case, kebab-case, punctuation, and stop-word filtration.
9
+ */
10
+ export declare function tokenize(text: string): string[];
11
+ //# sourceMappingURL=tokenizer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.d.ts","sourceRoot":"","sources":["../../../../src/core/transforms/search/tokenizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,eAAO,MAAM,UAAU,aAcrB,CAAC;AAEH;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAe/C"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Standard English stop words set for information retrieval.
3
+ * Preserves common API identifiers like 'id', 'get', 'set', etc.
4
+ */
5
+ export const STOP_WORDS = new Set([
6
+ 'a', 'about', 'above', 'after', 'again', 'against', 'all', 'am', 'an', 'and', 'any',
7
+ 'are', 'aren', 'as', 'at', 'be', 'because', 'been', 'before', 'being', 'below',
8
+ 'between', 'both', 'but', 'by', 'can', 'cannot', 'could', 'did', 'do', 'does',
9
+ 'doing', 'down', 'during', 'each', 'few', 'for', 'from', 'further', 'had', 'has',
10
+ 'have', 'having', 'he', 'her', 'here', 'hers', 'herself', 'him', 'himself', 'his',
11
+ 'how', 'if', 'in', 'into', 'is', 'isn', 'it', 'its', 'itself', 'me', 'more',
12
+ 'most', 'my', 'myself', 'no', 'nor', 'not', 'of', 'off', 'on', 'once', 'only',
13
+ 'or', 'other', 'our', 'ours', 'ourselves', 'out', 'over', 'own', 'same', 'she',
14
+ 'should', 'so', 'some', 'such', 'than', 'that', 'the', 'their', 'theirs', 'them',
15
+ 'themselves', 'then', 'there', 'these', 'they', 'this', 'those', 'through', 'to',
16
+ 'too', 'under', 'until', 'up', 'very', 'was', 'we', 'were', 'what', 'when',
17
+ 'where', 'which', 'while', 'who', 'whom', 'why', 'with', 'won', 'you', 'your',
18
+ 'yours', 'yourself', 'yourselves',
19
+ ]);
20
+ /**
21
+ * Splits text into normalized alphanumeric tokens, handling camelCase,
22
+ * snake_case, kebab-case, punctuation, and stop-word filtration.
23
+ */
24
+ export function tokenize(text) {
25
+ if (!text)
26
+ return [];
27
+ // 1. Separate camelCase and snake/kebab/punctuation transitions
28
+ const normalized = text
29
+ .replace(/([a-z])([A-Z])/g, '$1 $2')
30
+ .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
31
+ .replace(/[_\-.:/\\,;?!=+*~`'"`()\[\]{}|<>#@$%^&]+/g, ' ')
32
+ .toLowerCase();
33
+ // 2. Extract words >= 2 chars, including non-Latin letters.
34
+ const tokens = normalized.match(/[\p{L}\p{N}]+/gu) || [];
35
+ // 3. Filter common English stop words
36
+ return tokens.filter((t) => t.length >= 2 && !STOP_WORDS.has(t));
37
+ }
38
+ //# sourceMappingURL=tokenizer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenizer.js","sourceRoot":"","sources":["../../../../src/core/transforms/search/tokenizer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAS;IACxC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK;IACnF,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO;IAC9E,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM;IAC7E,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK;IAChF,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK;IACjF,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM;IAC3E,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM;IAC7E,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK;IAC9E,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM;IAChF,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI;IAChF,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAC1E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM;IAC7E,OAAO,EAAE,UAAU,EAAE,YAAY;CAClC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IAErB,gEAAgE;IAChE,MAAM,UAAU,GAAG,IAAI;SACpB,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,uBAAuB,EAAE,OAAO,CAAC;SACzC,OAAO,CAAC,2CAA2C,EAAE,GAAG,CAAC;SACzD,WAAW,EAAE,CAAC;IAEjB,4DAA4D;IAC5D,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC;IAEzD,sCAAsC;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { Tool } from '../../tool.js';
2
+ import { SearchDetailLevel } from './types.js';
3
+ export type DetailLevel = SearchDetailLevel;
4
+ export declare function serializeTool(tool: Tool, detail?: DetailLevel): Promise<string>;
5
+ export declare function serializeTools(tools: Tool[], detail?: DetailLevel): Promise<string>;
6
+ //# sourceMappingURL=tool-serializer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-serializer.d.ts","sourceRoot":"","sources":["../../../../src/core/transforms/search/tool-serializer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,MAAM,MAAM,WAAW,GAAG,iBAAiB,CAAC;AAE5C,wBAAsB,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,GAAE,WAAwB,GAAG,OAAO,CAAC,MAAM,CAAC,CAqCjG;AAED,wBAAsB,cAAc,CAClC,KAAK,EAAE,IAAI,EAAE,EACb,MAAM,GAAE,WAAwB,GAC/B,OAAO,CAAC,MAAM,CAAC,CAIjB"}
@@ -0,0 +1,41 @@
1
+ export async function serializeTool(tool, detail = 'detailed') {
2
+ const mcpTool = await tool.toMcpTool();
3
+ const schema = mcpTool.inputSchema || {};
4
+ const properties = schema?.properties || {};
5
+ const requiredSet = new Set(Array.isArray(schema?.required) ? schema.required : []);
6
+ switch (detail) {
7
+ case 'brief':
8
+ return `- **${tool.name}**: ${tool.description || 'No description'}`;
9
+ case 'detailed': {
10
+ const lines = [
11
+ `### ${tool.name}`,
12
+ tool.description || 'No description',
13
+ '**Parameters**:',
14
+ ];
15
+ const propKeys = Object.keys(properties);
16
+ if (propKeys.length === 0) {
17
+ lines.push(' *(none)*');
18
+ }
19
+ else {
20
+ for (const key of propKeys) {
21
+ const prop = properties[key] || {};
22
+ const isReq = requiredSet.has(key) ? 'required' : 'optional';
23
+ const type = prop.type || 'any';
24
+ const desc = prop.description ? `: ${prop.description}` : '';
25
+ const defaultVal = prop.default !== undefined ? ` (default: ${JSON.stringify(prop.default)})` : '';
26
+ lines.push(` - \`${key}\` (${type}, ${isReq})${defaultVal}${desc}`);
27
+ }
28
+ }
29
+ return lines.join('\n');
30
+ }
31
+ case 'full':
32
+ return `### ${tool.name}\n${tool.description || ''}\n\`\`\`json\n${JSON.stringify(schema, null, 2)}\n\`\`\``;
33
+ }
34
+ }
35
+ export async function serializeTools(tools, detail = 'detailed') {
36
+ if (tools.length === 0)
37
+ return 'No matching tools found.';
38
+ const serialized = await Promise.all(tools.map((t) => serializeTool(t, detail)));
39
+ return serialized.join('\n\n');
40
+ }
41
+ //# sourceMappingURL=tool-serializer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-serializer.js","sourceRoot":"","sources":["../../../../src/core/transforms/search/tool-serializer.ts"],"names":[],"mappings":"AAKA,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAU,EAAE,SAAsB,UAAU;IAC9E,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;IACvC,MAAM,MAAM,GAAI,OAAO,CAAC,WAAmC,IAAI,EAAE,CAAC;IAClE,MAAM,UAAU,GAAG,MAAM,EAAE,UAAU,IAAI,EAAE,CAAC;IAC5C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEpF,QAAQ,MAAM,EAAE,CAAC;QACf,KAAK,OAAO;YACV,OAAO,OAAO,IAAI,CAAC,IAAI,OAAO,IAAI,CAAC,WAAW,IAAI,gBAAgB,EAAE,CAAC;QAEvE,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,KAAK,GAAa;gBACtB,OAAO,IAAI,CAAC,IAAI,EAAE;gBAClB,IAAI,CAAC,WAAW,IAAI,gBAAgB;gBACpC,iBAAiB;aAClB,CAAC;YAEF,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACzC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAC3B,CAAC;iBAAM,CAAC;gBACN,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;oBAC3B,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;oBACnC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;oBAC7D,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;oBAChC,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC7D,MAAM,UAAU,GACd,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;oBAClF,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,OAAO,IAAI,KAAK,KAAK,IAAI,UAAU,GAAG,IAAI,EAAE,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;YACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;QAED,KAAK,MAAM;YACT,OAAO,OAAO,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,WAAW,IAAI,EAAE,iBAAiB,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC;IACjH,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,SAAsB,UAAU;IAEhC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,0BAA0B,CAAC;IAC1D,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IACjF,OAAO,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AACjC,CAAC"}
@@ -0,0 +1,36 @@
1
+ export type SearchDetailLevel = 'brief' | 'detailed' | 'full';
2
+ export interface SearchTransformOptions {
3
+ searchToolName?: string;
4
+ callToolName?: string;
5
+ defaultLimit?: number;
6
+ defaultDetail?: SearchDetailLevel;
7
+ alwaysVisible?: string[];
8
+ /**
9
+ * Interpret the search query as a regular expression instead of a literal substring
10
+ * (RegexSearchTransform only; default: false).
11
+ *
12
+ * The match runs in a worker and is abandoned if it does not finish quickly, so a
13
+ * catastrophic pattern cannot block the server event loop. On timeout or invalid
14
+ * syntax the query is treated as a literal substring.
15
+ */
16
+ allowRegex?: boolean;
17
+ }
18
+ export interface BM25Document<T> {
19
+ id: string;
20
+ item: T;
21
+ length: number;
22
+ termFrequencies: Map<string, number>;
23
+ }
24
+ export interface BM25SearchResult<T> {
25
+ item: T;
26
+ score: number;
27
+ }
28
+ export interface IndexDocumentInput<T> {
29
+ id: string;
30
+ name: string;
31
+ title?: string;
32
+ description?: string;
33
+ parametersText?: string;
34
+ item: T;
35
+ }
36
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/core/transforms/search/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,UAAU,GAAG,MAAM,CAAC;AAE9D,MAAM,WAAW,sBAAsB;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE,MAAM,CAAC;IACf,eAAe,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACtC;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB,CAAC,CAAC;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,IAAI,EAAE,CAAC,CAAC;CACT"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/core/transforms/search/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,15 @@
1
+ import { Tool } from '../tool.js';
2
+ /**
3
+ * Schema and visibility material for catalog cache keys.
4
+ * Name and description alone reuse a stale index when a parameter list changes.
5
+ */
6
+ export declare function toolCacheFields(tool: Tool): {
7
+ schema: string;
8
+ visibility: string;
9
+ };
10
+ /**
11
+ * Length-prefixed catalog fingerprint. Without a delimiter, ('ab','c') and ('a','bc')
12
+ * hash to the same key and a transform can serve a stale tool list.
13
+ */
14
+ export declare function catalogCacheKey(tools: Tool[], visibleNames: string[]): string;
15
+ //# sourceMappingURL=tool-cache-key.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tool-cache-key.d.ts","sourceRoot":"","sources":["../../../src/core/transforms/tool-cache-key.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAElC;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAKlF;AA0CD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,YAAY,EAAE,MAAM,EAAE,GAAG,MAAM,CAa7E"}