@tool-bridge/server 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/dist/{airtable-NOSOMOVB.js → airtable-23JBIM6X.js} +4 -4
  2. package/dist/{alt_text_generator_ai-BHIJ4LW5.js → alt_text_generator_ai-ADWBTCIH.js} +4 -4
  3. package/dist/{amap-QRLP4TWZ.js → amap-CYQCYW2Z.js} +4 -4
  4. package/dist/{anthropic-IEOI36EV.js → anthropic-5P62HDNR.js} +4 -4
  5. package/dist/{apify-3CCYTQVK.js → apify-54RZUAGW.js} +4 -4
  6. package/dist/{brave_search-PZNYDQG7.js → brave_search-AHJ6FTD5.js} +4 -4
  7. package/dist/{chunk-YASUMV2K.js → chunk-B4P6YZFS.js} +1 -1
  8. package/dist/{chunk-TLNUIPFZ.js → chunk-CLEZ6YQ6.js} +2117 -190
  9. package/dist/{chunk-RVWZN3CI.js → chunk-OKRZPQ3R.js} +443 -139
  10. package/dist/{chunk-U5UHT7CX.js → chunk-SWBNHIO4.js} +1 -1
  11. package/dist/{chunk-WW2IMPQK.js → chunk-VLOIDU5U.js} +3 -3
  12. package/dist/{circleci-VSJ4O5FC.js → circleci-UM3NSQJ3.js} +4 -4
  13. package/dist/{clerk-CC2JZBZI.js → clerk-FE5LQ2CZ.js} +4 -4
  14. package/dist/{cloudflare_dns-PJEBSEYQ.js → cloudflare_dns-KEZABKUT.js} +4 -4
  15. package/dist/{cohere-KBACYSPF.js → cohere-4IPJADXP.js} +4 -4
  16. package/dist/{confluence-2PX3O7G5.js → confluence-56QEKNQI.js} +4 -4
  17. package/dist/{convertapi-BVOTD2PJ.js → convertapi-3QRM5K5T.js} +3 -3
  18. package/dist/{currencyapi-6ZQ2VNQ7.js → currencyapi-L6G4OND5.js} +4 -4
  19. package/dist/{deepseek-MB3WVVTB.js → deepseek-LGC6HBFG.js} +4 -4
  20. package/dist/{docker_hub-7CLQL2IJ.js → docker_hub-XDMK3BIU.js} +4 -4
  21. package/dist/{dropbox-VFYDVUNK.js → dropbox-4QARMFZU.js} +4 -4
  22. package/dist/{dub-QN3EETJY.js → dub-C6JSJKOT.js} +4 -4
  23. package/dist/{e2b-NKC3Y776.js → e2b-6A6TVACJ.js} +4 -4
  24. package/dist/{exa-KKZ6F25K.js → exa-SIWWW6AA.js} +4 -4
  25. package/dist/{fal_ai-25LYJD2O.js → fal_ai-3IJXOKSP.js} +4 -4
  26. package/dist/{feishu-NRT55B3Q.js → feishu-L4KDA4DC.js} +2 -2
  27. package/dist/{feishu_custom_bot-3W3XXUG4.js → feishu_custom_bot-SDM75H4P.js} +3 -3
  28. package/dist/{figma-4FLP35TC.js → figma-6DD436DN.js} +4 -4
  29. package/dist/{firehydrant-BLXPLZ3X.js → firehydrant-SYSGYB3R.js} +4 -4
  30. package/dist/{fixer-4OR62TGE.js → fixer-FZG7ASTF.js} +4 -4
  31. package/dist/{fly-MYCKOZZK.js → fly-HMRCZBUC.js} +4 -4
  32. package/dist/{front-3DFYVMF3.js → front-FAFSD7I3.js} +4 -4
  33. package/dist/{geocodio-CXMD6VKA.js → geocodio-4D3TWENM.js} +4 -4
  34. package/dist/{ghost-4UUE737W.js → ghost-OSO2FOZS.js} +4 -4
  35. package/dist/{github-WFS2ON2N.js → github-OR4I4RHE.js} +4 -4
  36. package/dist/{gmail-KW7FXA7A.js → gmail-5AOPJ63E.js} +4 -4
  37. package/dist/{googlecalendar-AMH5JQMC.js → googlecalendar-SOJIJUWH.js} +4 -4
  38. package/dist/{googledocs-R5VA6CKD.js → googledocs-QSKN5TLN.js} +3 -3
  39. package/dist/{grafana-IT6DWIVB.js → grafana-R3AIZM7M.js} +4 -4
  40. package/dist/{graphhopper-TYFDJZWC.js → graphhopper-4CR3QOAX.js} +4 -4
  41. package/dist/index.d.ts +53 -8
  42. package/dist/index.js +3 -3
  43. package/dist/{ip2proxy-GJ4HXVXO.js → ip2proxy-OBCG6X6J.js} +4 -4
  44. package/dist/{ipgeolocation_io-OAGR6PRF.js → ipgeolocation_io-NHH3DTQW.js} +4 -4
  45. package/dist/{ipqualityscore-BCKAMDGL.js → ipqualityscore-7POMCBEC.js} +4 -4
  46. package/dist/{jina_ai-N3NXRVIZ.js → jina_ai-YXVKROV4.js} +4 -4
  47. package/dist/{jira-CHLBKWLO.js → jira-LADO3VJU.js} +4 -4
  48. package/dist/{langsmith-OIKOTPY3.js → langsmith-XZ6UAQFU.js} +4 -4
  49. package/dist/{lemlist-VAKYPKS3.js → lemlist-P74GLNE7.js} +4 -4
  50. package/dist/{linear-Q6QTPJ5R.js → linear-CXJ7D37A.js} +3 -3
  51. package/dist/{logsnag-SQOQBTES.js → logsnag-EVVHWFLK.js} +4 -4
  52. package/dist/main.js +102 -102
  53. package/dist/{mattermost-G2KBEICM.js → mattermost-WG2MRGBD.js} +4 -4
  54. package/dist/{mem0-D2FPLYDX.js → mem0-HQWUKG6U.js} +4 -4
  55. package/dist/{memos-76PTWV5V.js → memos-SQMJIFOE.js} +4 -4
  56. package/dist/{metabase-TWSIDVBM.js → metabase-E27G2DZI.js} +4 -4
  57. package/dist/{mistral_ai-TP7TQUEJ.js → mistral_ai-MIL63NIT.js} +4 -4
  58. package/dist/{mother_duck-UXY5THYU.js → mother_duck-AIZVCBNR.js} +4 -4
  59. package/dist/{ngrok-RZW2ISJK.js → ngrok-XS4DVIQS.js} +4 -4
  60. package/dist/{notes-B2I6FWK2.js → notes-JEOUSL2Y.js} +1 -1
  61. package/dist/{notion-QOKRUE6M.js → notion-U4EZVDW2.js} +4 -4
  62. package/dist/{open_exchange_rates-ODLFWEJ7.js → open_exchange_rates-AZSQEYEJ.js} +4 -4
  63. package/dist/{openai-ZPBPPPGT.js → openai-HW3SYMTQ.js} +4 -4
  64. package/dist/{opengraph_io-EOI5UJKT.js → opengraph_io-QX74MAEL.js} +4 -4
  65. package/dist/{openrouter-BUWLF3BG.js → openrouter-OXSKYL6N.js} +4 -4
  66. package/dist/{outline-NXS3QRXO.js → outline-CCQAPDSW.js} +4 -4
  67. package/dist/{paddle-T4MSKQ76.js → paddle-6KQPSSCK.js} +4 -4
  68. package/dist/{perplexity-WW5N2LW7.js → perplexity-2TXO7IQE.js} +4 -4
  69. package/dist/{pinecone-RY5AZPQM.js → pinecone-YOO7NULI.js} +4 -4
  70. package/dist/{pipedrive-OHYQNZTU.js → pipedrive-Q6RIFIFP.js} +4 -4
  71. package/dist/{polar-XZIAHXS5.js → polar-KUMGCES3.js} +4 -4
  72. package/dist/{posthog-DTPTWORY.js → posthog-VXQHBSMB.js} +4 -4
  73. package/dist/{postmark-F4UCQKC3.js → postmark-YLIPF52S.js} +4 -4
  74. package/dist/{prerender-P3Y2MLIC.js → prerender-CRY7UJN5.js} +4 -4
  75. package/dist/{pubmed-RHU3GXFB.js → pubmed-3Z4T5AM7.js} +3 -3
  76. package/dist/{railway-VB6SRLI6.js → railway-BP37IGFL.js} +3 -3
  77. package/dist/{readwise-DIMSKJZR.js → readwise-HTKICF4K.js} +4 -4
  78. package/dist/{render-XCCDCEEK.js → render-WIVTUXJH.js} +4 -4
  79. package/dist/{replicate-IUEOQ4JC.js → replicate-JJYPA43D.js} +4 -4
  80. package/dist/{resend-N5MJZH5E.js → resend-TKHZVG7A.js} +4 -4
  81. package/dist/{rootly-25T4NBTU.js → rootly-FRSZLG5U.js} +4 -4
  82. package/dist/{scrapfly-PK4XFXUA.js → scrapfly-M5WXGQWE.js} +4 -4
  83. package/dist/{scrapingbee-ITPBMWQU.js → scrapingbee-PMXNLLBK.js} +4 -4
  84. package/dist/{screenshot_fyi-5U6ZYPKR.js → screenshot_fyi-HFW4TAOH.js} +4 -4
  85. package/dist/{semantic_scholar-BJGCI2MU.js → semantic_scholar-KXVH2VZQ.js} +4 -4
  86. package/dist/{sentry-63IC263P.js → sentry-WWOT2LRX.js} +4 -4
  87. package/dist/{shodan-2WBIFHFN.js → shodan-FY635H35.js} +4 -4
  88. package/dist/{shopify-XLLJRAGM.js → shopify-HQLBVSA5.js} +4 -4
  89. package/dist/{stripe-WLVCY3UN.js → stripe-GJN2GOHB.js} +3 -3
  90. package/dist/{supabase-BKNZ35ER.js → supabase-BBNZGQU6.js} +4 -4
  91. package/dist/{tavily-YFSDEUTL.js → tavily-DPENIBOG.js} +4 -4
  92. package/dist/{telegram-FC35W74G.js → telegram-L4NONG6H.js} +4 -4
  93. package/dist/{telnyx-MI32XZUG.js → telnyx-H67MAEZS.js} +4 -4
  94. package/dist/{todoist-4ZFJKZC6.js → todoist-G2BSP4DX.js} +4 -4
  95. package/dist/{trello-UOGFNMK4.js → trello-7WMVFDG2.js} +4 -4
  96. package/dist/{turso-YTSTW3ZS.js → turso-ZUAESFC2.js} +4 -4
  97. package/dist/{twilio-XAJDFUQH.js → twilio-EYFYIX3B.js} +3 -3
  98. package/dist/{umami-ZVIUBPAI.js → umami-AXAUDUVF.js} +4 -4
  99. package/dist/{unsplash-IU3PLDNS.js → unsplash-UCQAWPLR.js} +4 -4
  100. package/dist/{upstash_redis-3EYJW7SY.js → upstash_redis-ZPZ4ASU6.js} +4 -4
  101. package/dist/{uptimerobot-PJG2ASRU.js → uptimerobot-4QVKKUD5.js} +3 -3
  102. package/dist/{v2ex-KFQWWGFC.js → v2ex-VGEFJTYC.js} +4 -4
  103. package/dist/{vercel-I2ZDOQRL.js → vercel-JME4TSCN.js} +4 -4
  104. package/dist/{wolfram_alpha_api-BNXOJMB6.js → wolfram_alpha_api-TRGU2MDG.js} +4 -4
  105. package/dist/{wordpress-36D7BSMP.js → wordpress-WRUKLCZR.js} +4 -4
  106. package/dist/{workos-6X4JJRRC.js → workos-ZDW4EHS4.js} +4 -4
  107. package/dist/{zhihu-CIXKCHIU.js → zhihu-4VI67CWU.js} +4 -4
  108. package/package.json +5 -5
@@ -14873,6 +14873,10 @@ function secretRefsInConfig(config2) {
14873
14873
  const refs = [];
14874
14874
  const oauthMcp = c.kind === "mcp" && c.auth === "oauth";
14875
14875
  if (!oauthMcp && typeof c.authRef === "string" && c.authRef.length > 0) refs.push(c.authRef);
14876
+ if (oauthMcp && c.oauthClient !== null && typeof c.oauthClient === "object") {
14877
+ const secretRef = c.oauthClient.clientSecretRef;
14878
+ if (typeof secretRef === "string" && secretRef.length > 0) refs.push(secretRef);
14879
+ }
14876
14880
  if (typeof c.skRef === "string" && c.skRef.length > 0) refs.push(c.skRef);
14877
14881
  return refs;
14878
14882
  }
@@ -15589,7 +15593,8 @@ var contextCommands = new HtbpCommandRegistry().register(
15589
15593
  opts: HTBP_LIST_OPTIONS_SCHEMA.optional()
15590
15594
  }),
15591
15595
  returns: "Page<ContextEntryMeta>",
15592
- scope: "read"
15596
+ scope: "read",
15597
+ effect: "read"
15593
15598
  },
15594
15599
  ({ opts, path }, { provider }) => provider.list(path ?? "", opts)
15595
15600
  ).register(
@@ -15600,7 +15605,8 @@ var contextCommands = new HtbpCommandRegistry().register(
15600
15605
  path: external_exports.string().describe("entry path inside the namespace")
15601
15606
  }),
15602
15607
  returns: "ContextEntry",
15603
- scope: "read"
15608
+ scope: "read",
15609
+ effect: "read"
15604
15610
  },
15605
15611
  ({ path }, { provider }) => provider.get(path)
15606
15612
  ).register(
@@ -15612,7 +15618,8 @@ var contextCommands = new HtbpCommandRegistry().register(
15612
15618
  entry: entrySchema
15613
15619
  }),
15614
15620
  returns: "ContextEntryMeta",
15615
- scope: "write"
15621
+ scope: "write",
15622
+ effect: "write"
15616
15623
  },
15617
15624
  ({ entry, path }, { provider }) => provider.write(path, entry)
15618
15625
  ).register(
@@ -15624,7 +15631,8 @@ var contextCommands = new HtbpCommandRegistry().register(
15624
15631
  patch: patchSchema
15625
15632
  }),
15626
15633
  returns: "ContextEntryMeta",
15627
- scope: "write"
15634
+ scope: "write",
15635
+ effect: "write"
15628
15636
  },
15629
15637
  ({ patch, path }, { provider }) => provider.update(path, patch)
15630
15638
  ).register(
@@ -15647,7 +15655,8 @@ var contextCommands = new HtbpCommandRegistry().register(
15647
15655
  opts: searchOptionsSchema.optional()
15648
15656
  }),
15649
15657
  returns: "Page<ContextEntryMeta>",
15650
- scope: "read"
15658
+ scope: "read",
15659
+ effect: "read"
15651
15660
  },
15652
15661
  ({ opts, query }, { provider }) => provider.search(query, opts)
15653
15662
  ).register(
@@ -16620,7 +16629,7 @@ var tbErrorBodySchema = external_exports.object({
16620
16629
  var actionSchema = external_exports.enum(ACTIONS);
16621
16630
  var nodeKindSchema = external_exports.enum(NODE_KINDS);
16622
16631
  var nodeInputConfigSchema = external_exports.record(external_exports.string(), external_exports.unknown()).optional().describe(
16623
- "kind-specific config, e.g. mcp: { url, auth?, authRef? } / http: { endpoint, tools } / context: { provider, bucket, \u2026 } / remote: { baseUrl, skRef }; credentials go by authRef/skRef name, never inline"
16632
+ "kind-specific config, e.g. mcp: { url, auth?, authRef?, oauthClient?: { clientId, clientSecretRef? } } / http: { endpoint, tools } / context: { provider, bucket, \u2026 } / remote: { baseUrl, skRef }; credentials go by SecretStore reference name, never inline"
16624
16633
  );
16625
16634
  var nodeInputVirtualizeSchema = external_exports.strictObject({
16626
16635
  prefix: external_exports.string().optional(),
@@ -16693,22 +16702,55 @@ var toolSpecSchema = external_exports.object({
16693
16702
  name: external_exports.string(),
16694
16703
  outputSchema: external_exports.unknown().optional()
16695
16704
  });
16696
- var toolSearchItemSchema = external_exports.object({
16705
+ var toolSearchRelevanceSchema = external_exports.strictObject({
16706
+ coverage: external_exports.number().min(0).max(1),
16707
+ matchedTermCount: external_exports.number().int().nonnegative(),
16708
+ rankingVersion: external_exports.literal("keyword-v2"),
16709
+ totalTermCount: external_exports.number().int().positive()
16710
+ }).refine(
16711
+ (value) => value.matchedTermCount <= value.totalTermCount && value.coverage === value.matchedTermCount / value.totalTermCount,
16712
+ { message: "coverage must equal matchedTermCount / totalTermCount" }
16713
+ );
16714
+ var toolSearchSourceSchema = external_exports.strictObject({
16715
+ path: external_exports.string()
16716
+ });
16717
+ var toolSearchSourceResultSchema = external_exports.strictObject({
16718
+ path: external_exports.string(),
16719
+ status: external_exports.enum([
16720
+ "ok",
16721
+ "unsupported",
16722
+ "timed_out",
16723
+ "unavailable",
16724
+ "cycle",
16725
+ "hop_limit",
16726
+ "budget_exhausted",
16727
+ "invalid_response"
16728
+ ])
16729
+ });
16730
+ var toolSearchItemSchema = external_exports.strictObject({
16697
16731
  path: external_exports.string(),
16732
+ relevance: toolSearchRelevanceSchema,
16733
+ source: toolSearchSourceSchema.optional(),
16698
16734
  tool: toolSpecSchema
16699
16735
  });
16700
- function pageSchema(itemSchema) {
16701
- return external_exports.object({
16702
- cursor: external_exports.string().optional(),
16703
- items: external_exports.array(itemSchema)
16704
- });
16705
- }
16706
- var toolSearchPageSchema = pageSchema(toolSearchItemSchema);
16736
+ var toolSearchPageSchema = external_exports.strictObject({
16737
+ cursor: external_exports.string().optional(),
16738
+ items: external_exports.array(toolSearchItemSchema),
16739
+ partial: external_exports.boolean().optional(),
16740
+ snapshot: external_exports.string().optional(),
16741
+ sources: external_exports.array(toolSearchSourceResultSchema).optional()
16742
+ });
16707
16743
  var toolSearchRequestSchema = external_exports.strictObject({
16708
16744
  opts: external_exports.strictObject({
16709
16745
  cursor: external_exports.string().optional(),
16746
+ detail: external_exports.enum(["compact", "full"]).optional(),
16747
+ effects: external_exports.array(external_exports.enum(["read", "write", "destructive", "unknown"])).min(1).optional(),
16748
+ federation: external_exports.enum(["local", "recursive"]).optional(),
16710
16749
  limit: external_exports.number().int().optional(),
16711
- mode: external_exports.enum(["keyword", "semantic"]).optional()
16750
+ matching: external_exports.enum(["best", "all"]).optional(),
16751
+ minCoverage: external_exports.number().gt(0).max(1).optional(),
16752
+ mode: external_exports.enum(["keyword", "semantic"]).optional(),
16753
+ pathPrefix: external_exports.string().optional()
16712
16754
  }).optional(),
16713
16755
  query: external_exports.string().trim().min(1)
16714
16756
  });
@@ -17669,7 +17711,7 @@ function deviceShellHelpModel(nodePath, shell = {}) {
17669
17711
  timeoutMs: { type: "number", description: "kill the command after this many ms" }
17670
17712
  }
17671
17713
  },
17672
- returns: "{ stdout, stderr, exitCode }",
17714
+ returns: "{ stdout, stderr, exitCode, startedAt, completedAt, outcome, signal?, stdoutTruncated, stderrTruncated }",
17673
17715
  scope: "call",
17674
17716
  effect: "destructive",
17675
17717
  confirm: true
@@ -20000,6 +20042,13 @@ var positiveEnvKeys = [
20000
20042
  "TB_MAX_HOPS",
20001
20043
  "TB_REF_THRESHOLD_BYTES",
20002
20044
  "TB_REF_TTL_SEC",
20045
+ "TB_SEARCH_FEDERATION_CONCURRENCY",
20046
+ "TB_SEARCH_FEDERATION_DEADLINE_MS",
20047
+ "TB_SEARCH_FEDERATION_MAX_RESPONSE_BYTES",
20048
+ "TB_SEARCH_FEDERATION_MAX_SOURCES",
20049
+ "TB_SEARCH_FEDERATION_MIN_CHILD_WORK_MS",
20050
+ "TB_SEARCH_FEDERATION_RETURN_RESERVE_MS",
20051
+ "TB_SEARCH_FEDERATION_SESSION_TTL_SEC",
20003
20052
  "TB_STORE_CALL_MAX_BYTES",
20004
20053
  "TB_STORE_CALL_MAX_OBJECT_BYTES",
20005
20054
  "TB_STORE_CALL_MAX_OBJECTS",
@@ -20047,6 +20096,15 @@ function parseRuntimeEnv(env) {
20047
20096
  remote: {
20048
20097
  allowInsecure: allowInsecureHttp,
20049
20098
  allowlist,
20099
+ federatedSearch: {
20100
+ ...parsed.TB_SEARCH_FEDERATION_CONCURRENCY === void 0 ? {} : { maxConcurrency: parsed.TB_SEARCH_FEDERATION_CONCURRENCY },
20101
+ ...parsed.TB_SEARCH_FEDERATION_DEADLINE_MS === void 0 ? {} : { totalDeadlineMs: parsed.TB_SEARCH_FEDERATION_DEADLINE_MS },
20102
+ ...parsed.TB_SEARCH_FEDERATION_MAX_RESPONSE_BYTES === void 0 ? {} : { maxResponseBodyBytes: parsed.TB_SEARCH_FEDERATION_MAX_RESPONSE_BYTES },
20103
+ ...parsed.TB_SEARCH_FEDERATION_MAX_SOURCES === void 0 ? {} : { maxSources: parsed.TB_SEARCH_FEDERATION_MAX_SOURCES },
20104
+ ...parsed.TB_SEARCH_FEDERATION_MIN_CHILD_WORK_MS === void 0 ? {} : { minChildWorkMs: parsed.TB_SEARCH_FEDERATION_MIN_CHILD_WORK_MS },
20105
+ ...parsed.TB_SEARCH_FEDERATION_RETURN_RESERVE_MS === void 0 ? {} : { perHopReturnReserveMs: parsed.TB_SEARCH_FEDERATION_RETURN_RESERVE_MS },
20106
+ ...parsed.TB_SEARCH_FEDERATION_SESSION_TTL_SEC === void 0 ? {} : { sessionTtlMs: parsed.TB_SEARCH_FEDERATION_SESSION_TTL_SEC * 1e3 }
20107
+ },
20050
20108
  maxHops: parsed.TB_MAX_HOPS ?? DEFAULT_MAX_HOPS,
20051
20109
  ...parsed.TB_INSTANCE_ID ? { instanceId: parsed.TB_INSTANCE_ID } : {}
20052
20110
  }
@@ -20095,22 +20153,33 @@ var TOOL_SEARCH_SNAPSHOT_CHUNKS_MAX = Math.ceil(
20095
20153
  var TOOL_SEARCH_REBUILD_CHUNKS_MAX = TOOL_SEARCH_SOURCE_CHUNKS_MAX + TOOL_SEARCH_SNAPSHOT_CHUNKS_MAX;
20096
20154
  var TOOL_SEARCH_TERM_LIMIT = 32;
20097
20155
  var TOOL_SEARCH_UNIT_LIMIT = 98;
20156
+ var TOOL_SEARCH_LIMIT_DEFAULT = 10;
20098
20157
  var TOOL_SEARCH_LIKE_PATTERN_BYTES_MAX = 50;
20099
20158
  var TOOL_SEARCH_QUERY_MAX = 1024;
20159
+ var TOOL_SEARCH_RANKING_VERSION = "keyword-v2";
20100
20160
  var TOOL_SEARCH_CURSOR_OFFSET_MAX = 1e6;
20161
+ var TOOL_SEARCH_EFFECTS = [
20162
+ "read",
20163
+ "write",
20164
+ "destructive",
20165
+ "unknown"
20166
+ ];
20101
20167
  function assertKeywordToolSearchMode(opts) {
20102
20168
  if (opts?.mode !== void 0 && opts.mode !== "keyword") {
20103
20169
  throw new TBError("invalid_argument", `SearchIndex \u4E0D\u652F\u6301 mode '${String(opts.mode)}'`);
20104
20170
  }
20105
20171
  }
20106
20172
  function normalizeToolSearchLimit(limit) {
20107
- if (limit === void 0) return LIST_LIMIT_DEFAULT;
20173
+ if (limit === void 0) return TOOL_SEARCH_LIMIT_DEFAULT;
20108
20174
  if (typeof limit !== "number" || !Number.isFinite(limit) || !Number.isInteger(limit)) {
20109
20175
  throw new TBError("invalid_argument", "opts.limit \u5FC5\u987B\u662F\u6574\u6570");
20110
20176
  }
20111
- if (limit < 1) return LIST_LIMIT_DEFAULT;
20177
+ if (limit < 1) return TOOL_SEARCH_LIMIT_DEFAULT;
20112
20178
  return Math.min(limit, LIST_LIMIT_MAX);
20113
20179
  }
20180
+ function searchUnitAllowsPath(unit) {
20181
+ return !/^%[A-Za-z0-9]{1,2}%$/u.test(unit.pattern);
20182
+ }
20114
20183
  function stableDigest(value) {
20115
20184
  const bytes = new TextEncoder().encode(JSON.stringify(value));
20116
20185
  let hash2 = 0xcbf29ce484222325n;
@@ -20154,6 +20223,7 @@ function serializedRecord(path, tool, feedback) {
20154
20223
  }
20155
20224
  const record2 = {
20156
20225
  description: truncateUtf8(tool.description ?? "", TOOL_SEARCH_DESCRIPTION_BYTES_MAX),
20226
+ effect: TOOL_SEARCH_EFFECTS.includes(tool.effect) ? tool.effect : "unknown",
20157
20227
  feedback,
20158
20228
  name: tool.name,
20159
20229
  path,
@@ -20164,17 +20234,70 @@ function serializedRecord(path, tool, feedback) {
20164
20234
  function jsonPayload(record2) {
20165
20235
  return {
20166
20236
  description: record2.description,
20237
+ effect: record2.effect,
20167
20238
  feedback: record2.feedback,
20168
20239
  name: record2.name,
20169
20240
  path: record2.path
20170
20241
  };
20171
20242
  }
20172
20243
  function normalizeToolSearchPath(path) {
20173
- const canonical = normalizePath(path);
20244
+ const canonical = canonicalizePath(path);
20174
20245
  const pathError = validatePath(canonical);
20175
20246
  if (pathError !== null) throw pathError;
20176
20247
  return canonical;
20177
20248
  }
20249
+ function normalizeToolSearchOptions(opts) {
20250
+ let effects;
20251
+ if (opts?.effects !== void 0) {
20252
+ if (!Array.isArray(opts.effects) || opts.effects.length === 0) {
20253
+ throw new TBError("invalid_argument", "opts.effects \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4");
20254
+ }
20255
+ const selected = /* @__PURE__ */ new Set();
20256
+ for (const effect of opts.effects) {
20257
+ if (!TOOL_SEARCH_EFFECTS.includes(effect)) {
20258
+ throw new TBError("invalid_argument", `opts.effects \u542B\u975E\u6CD5 effect '${String(effect)}'`);
20259
+ }
20260
+ selected.add(effect);
20261
+ }
20262
+ effects = TOOL_SEARCH_EFFECTS.filter((effect) => selected.has(effect));
20263
+ }
20264
+ const matching = opts?.matching ?? "best";
20265
+ if (matching !== "best" && matching !== "all") {
20266
+ throw new TBError("invalid_argument", `opts.matching '${String(matching)}' \u975E\u6CD5`);
20267
+ }
20268
+ let minCoverage = opts?.minCoverage;
20269
+ if (minCoverage !== void 0 && (typeof minCoverage !== "number" || !Number.isFinite(minCoverage) || minCoverage <= 0 || minCoverage > 1)) {
20270
+ throw new TBError("invalid_argument", "opts.minCoverage \u5FC5\u987B\u5927\u4E8E 0 \u4E14\u4E0D\u8D85\u8FC7 1");
20271
+ }
20272
+ if (matching === "all") {
20273
+ if (minCoverage !== void 0 && minCoverage !== 1) {
20274
+ throw new TBError("invalid_argument", "opts.matching='all' \u53EA\u5141\u8BB8 minCoverage=1");
20275
+ }
20276
+ minCoverage = 1;
20277
+ }
20278
+ let pathPrefix;
20279
+ if (opts?.pathPrefix !== void 0) {
20280
+ if (typeof opts.pathPrefix !== "string") {
20281
+ throw new TBError("invalid_argument", "opts.pathPrefix \u5FC5\u987B\u662F\u8DEF\u5F84\u5B57\u7B26\u4E32");
20282
+ }
20283
+ pathPrefix = normalizeToolSearchPath(opts.pathPrefix);
20284
+ }
20285
+ return {
20286
+ ...effects === void 0 ? {} : { effects },
20287
+ matching,
20288
+ ...minCoverage === void 0 ? {} : { minCoverage },
20289
+ ...pathPrefix === void 0 ? {} : { pathPrefix }
20290
+ };
20291
+ }
20292
+ function toolSearchOptionsFingerprint(opts) {
20293
+ const normalized = normalizeToolSearchOptions(opts);
20294
+ return stableDigest([
20295
+ normalized.effects ?? null,
20296
+ normalized.matching,
20297
+ normalized.minCoverage ?? null,
20298
+ normalized.pathPrefix ?? null
20299
+ ]);
20300
+ }
20178
20301
  function serializeToolSearchSnapshot(path, tools, feedback = "") {
20179
20302
  const canonical = normalizeToolSearchPath(path);
20180
20303
  const names = /* @__PURE__ */ new Set();
@@ -20230,6 +20353,7 @@ function toolSearchSnapshotDigest(records) {
20230
20353
  record2.path,
20231
20354
  record2.name,
20232
20355
  record2.description,
20356
+ record2.effect,
20233
20357
  record2.feedback,
20234
20358
  record2.toolDigest
20235
20359
  ]));
@@ -20279,54 +20403,93 @@ function scriptRuns(term) {
20279
20403
  }
20280
20404
  return runs;
20281
20405
  }
20282
- function addSearchUnit(units, value, tier) {
20406
+ function addSearchUnit(units, value, tier, logicalTermId) {
20283
20407
  const pattern = likePattern(value);
20284
20408
  if (new TextEncoder().encode(pattern).length > TOOL_SEARCH_LIKE_PATTERN_BYTES_MAX) return false;
20285
- const existing = units.get(pattern);
20409
+ const key = `${logicalTermId}\0${pattern}`;
20410
+ const existing = units.get(key);
20286
20411
  if (existing === void 0 || tier > existing.tier) {
20287
- units.set(pattern, { pattern, tier });
20412
+ units.set(key, { logicalTermId, pattern, tier });
20288
20413
  }
20289
20414
  return true;
20290
20415
  }
20291
- function addChunkedSearchUnits(units, value, tier) {
20416
+ function addChunkedSearchUnits(units, value, tier, logicalTermId) {
20292
20417
  let chunk = "";
20293
20418
  for (const codePoint of value) {
20294
20419
  if (likePatternBytes(chunk + codePoint) <= TOOL_SEARCH_LIKE_PATTERN_BYTES_MAX) {
20295
20420
  chunk += codePoint;
20296
20421
  continue;
20297
20422
  }
20298
- if (chunk.length > 0) addSearchUnit(units, chunk, tier);
20423
+ if (chunk.length > 0) addSearchUnit(units, chunk, tier, logicalTermId);
20299
20424
  chunk = codePoint;
20300
20425
  }
20301
- if (chunk.length > 0) addSearchUnit(units, chunk, tier);
20426
+ if (chunk.length > 0) addSearchUnit(units, chunk, tier, logicalTermId);
20302
20427
  }
20303
- function prepareToolSearchUnits(query) {
20304
- const terms = normalizeToolSearchQuery(query).split(/\s+/u);
20305
- if (terms.length > TOOL_SEARCH_TERM_LIMIT) {
20428
+ function prepareToolSearchQuery(query, unitLimit = TOOL_SEARCH_UNIT_LIMIT) {
20429
+ if (!Number.isInteger(unitLimit) || unitLimit < 1 || unitLimit > TOOL_SEARCH_UNIT_LIMIT) {
20430
+ throw new TBError("invalid_argument", "\u5DE5\u5177\u641C\u7D22 unit limit \u975E\u6CD5");
20431
+ }
20432
+ const rawTerms = normalizeToolSearchQuery(query).split(/\s+/u);
20433
+ if (rawTerms.length > TOOL_SEARCH_TERM_LIMIT) {
20306
20434
  throw new TBError("invalid_argument", `\u641C\u7D22 query \u6700\u591A ${TOOL_SEARCH_TERM_LIMIT} \u4E2A terms`);
20307
20435
  }
20436
+ const seenTerms = /* @__PURE__ */ new Set();
20437
+ const terms = rawTerms.filter((term) => {
20438
+ const key = term.replace(/[A-Z]/g, (char) => char.toLowerCase());
20439
+ if (seenTerms.has(key)) return false;
20440
+ seenTerms.add(key);
20441
+ return true;
20442
+ });
20443
+ if (terms.length > unitLimit) {
20444
+ throw new TBError("invalid_argument", "\u5DE5\u5177\u641C\u7D22 unit limit \u65E0\u6CD5\u8986\u76D6\u5168\u90E8 logical terms");
20445
+ }
20308
20446
  const units = /* @__PURE__ */ new Map();
20309
- for (const term of terms) {
20310
- const wholeAdded = addSearchUnit(units, term, 4);
20447
+ for (const [logicalTermId, term] of terms.entries()) {
20448
+ const wholeAdded = addSearchUnit(units, term, 4, logicalTermId);
20311
20449
  const runs = scriptRuns(term);
20312
20450
  if (runs.length > 1) {
20313
20451
  for (const run of runs) {
20314
20452
  const value = run.codePoints.join("");
20315
- if (run.cjk) addSearchUnit(units, value, 2);
20316
- else addChunkedSearchUnits(units, value, 2);
20453
+ if (run.cjk) addSearchUnit(units, value, 2, logicalTermId);
20454
+ else addChunkedSearchUnits(units, value, 2, logicalTermId);
20317
20455
  }
20318
20456
  } else if (!wholeAdded && runs[0]?.cjk === false) {
20319
- addChunkedSearchUnits(units, term, 2);
20457
+ addChunkedSearchUnits(units, term, 2, logicalTermId);
20320
20458
  }
20321
20459
  for (const run of runs) {
20322
20460
  if (!run.cjk) continue;
20323
20461
  for (let index = 0; index < run.codePoints.length - 1; index += 1) {
20324
- addSearchUnit(units, run.codePoints.slice(index, index + 2).join(""), 2);
20462
+ addSearchUnit(
20463
+ units,
20464
+ run.codePoints.slice(index, index + 2).join(""),
20465
+ 2,
20466
+ logicalTermId
20467
+ );
20468
+ }
20469
+ for (const codePoint of run.codePoints) {
20470
+ addSearchUnit(units, codePoint, 1, logicalTermId);
20325
20471
  }
20326
- for (const codePoint of run.codePoints) addSearchUnit(units, codePoint, 1);
20327
20472
  }
20328
20473
  }
20329
- return [...units.values()].sort((left, right) => right.tier - left.tier).slice(0, TOOL_SEARCH_UNIT_LIMIT);
20474
+ const ordered = [...units.values()].sort((left, right) => right.tier - left.tier);
20475
+ if (ordered.length <= unitLimit) {
20476
+ return { totalTermCount: terms.length, units: ordered };
20477
+ }
20478
+ const selected = /* @__PURE__ */ new Set();
20479
+ const represented = /* @__PURE__ */ new Set();
20480
+ for (const unit of ordered) {
20481
+ if (represented.has(unit.logicalTermId)) continue;
20482
+ represented.add(unit.logicalTermId);
20483
+ selected.add(unit);
20484
+ }
20485
+ for (const unit of ordered) {
20486
+ if (selected.size >= unitLimit) break;
20487
+ selected.add(unit);
20488
+ }
20489
+ return {
20490
+ totalTermCount: terms.length,
20491
+ units: ordered.filter((unit) => selected.has(unit))
20492
+ };
20330
20493
  }
20331
20494
  function cursorBase64UrlDecode(value) {
20332
20495
  if (value.length === 0 || value.length > 4096) {
@@ -20353,13 +20516,15 @@ async function cursorCryptoKey(secret) {
20353
20516
  ["encrypt", "decrypt"]
20354
20517
  );
20355
20518
  }
20356
- async function encodeToolSearchCursor(query, mode, revision, offset, secret) {
20519
+ async function sealToolSearchCursor(query, mode, revision, offset, secret, optionsFingerprint) {
20357
20520
  const payload = {
20521
+ f: optionsFingerprint,
20358
20522
  h: stableDigest(normalizeToolSearchQuery(query)),
20523
+ k: TOOL_SEARCH_RANKING_VERSION,
20359
20524
  m: mode,
20360
20525
  o: offset,
20361
20526
  r: revision,
20362
- v: 1
20527
+ v: 2
20363
20528
  };
20364
20529
  const iv = crypto.getRandomValues(new Uint8Array(12));
20365
20530
  const ciphertext = new Uint8Array(await crypto.subtle.encrypt(
@@ -20372,7 +20537,17 @@ async function encodeToolSearchCursor(query, mode, revision, offset, secret) {
20372
20537
  sealed.set(ciphertext, iv.length);
20373
20538
  return base64urlEncode(sealed);
20374
20539
  }
20375
- async function decodeToolSearchCursor(cursor, query, mode, revision, secret) {
20540
+ async function encodeToolSearchCursor(query, mode, revision, offset, secret, opts) {
20541
+ return await sealToolSearchCursor(
20542
+ query,
20543
+ mode,
20544
+ revision,
20545
+ offset,
20546
+ secret,
20547
+ toolSearchOptionsFingerprint(opts)
20548
+ );
20549
+ }
20550
+ async function decodeToolSearchCursor(cursor, query, mode, revision, secret, opts) {
20376
20551
  if (cursor === void 0) return 0;
20377
20552
  let value;
20378
20553
  try {
@@ -20393,115 +20568,199 @@ async function decodeToolSearchCursor(cursor, query, mode, revision, secret) {
20393
20568
  }
20394
20569
  const payload = value;
20395
20570
  const keys = Object.keys(payload).sort().join(",");
20396
- if (keys !== "h,m,o,r,v" || payload.v !== 1 || payload.h !== stableDigest(normalizeToolSearchQuery(query)) || payload.m !== mode || payload.r !== revision || !Number.isSafeInteger(payload.o) || (payload.o ?? -1) < 0 || (payload.o ?? 0) > TOOL_SEARCH_CURSOR_OFFSET_MAX) {
20571
+ if (keys !== "f,h,k,m,o,r,v" || payload.v !== 2 || payload.k !== TOOL_SEARCH_RANKING_VERSION || payload.f !== toolSearchOptionsFingerprint(opts) || payload.h !== stableDigest(normalizeToolSearchQuery(query)) || payload.m !== mode || payload.r !== revision || !Number.isSafeInteger(payload.o) || (payload.o ?? -1) < 0 || (payload.o ?? 0) > TOOL_SEARCH_CURSOR_OFFSET_MAX) {
20397
20572
  throw new TBError("invalid_argument", "\u641C\u7D22 cursor \u5DF2\u5931\u6548\u6216\u4E0E\u5F53\u524D\u67E5\u8BE2\u4E0D\u5339\u914D");
20398
20573
  }
20399
20574
  return payload.o ?? 0;
20400
20575
  }
20576
+ async function encodeToolSearchCursorForCandidate(query, mode, candidate, secret) {
20577
+ const fingerprint = candidate.searchOptionsFingerprint ?? toolSearchOptionsFingerprint();
20578
+ if (!/^[a-f0-9]{16}$/.test(fingerprint)) {
20579
+ throw new TBError("invalid_argument", "\u5DE5\u5177\u641C\u7D22\u5019\u9009\u7684 options fingerprint \u975E\u6CD5");
20580
+ }
20581
+ return await sealToolSearchCursor(
20582
+ query,
20583
+ mode,
20584
+ candidate.revision,
20585
+ candidate.resumeOffset,
20586
+ secret,
20587
+ fingerprint
20588
+ );
20589
+ }
20401
20590
 
20402
20591
  // ../core/src/search/sqlSearchIndex.ts
20403
20592
  var TOOL_SEARCH_SCHEMA_STATEMENTS = [
20404
- `CREATE TABLE IF NOT EXISTS tb_search_tools_v4 (
20593
+ `CREATE TABLE IF NOT EXISTS tb_search_tools_v5 (
20405
20594
  id INTEGER PRIMARY KEY,
20406
20595
  path TEXT NOT NULL,
20407
20596
  name TEXT NOT NULL,
20408
20597
  description TEXT NOT NULL DEFAULT '',
20598
+ effect TEXT NOT NULL CHECK (effect IN ('read', 'write', 'destructive', 'unknown')),
20409
20599
  feedback TEXT NOT NULL DEFAULT '',
20410
20600
  UNIQUE(path, name)
20411
20601
  )`,
20412
- `CREATE TABLE IF NOT EXISTS tb_search_meta_v4 (
20602
+ `CREATE TABLE IF NOT EXISTS tb_search_meta_v5 (
20413
20603
  singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
20414
20604
  revision INTEGER NOT NULL DEFAULT 0,
20415
20605
  seeded INTEGER NOT NULL DEFAULT 0,
20416
20606
  cursor_secret TEXT NOT NULL
20417
20607
  )`,
20418
- `INSERT OR IGNORE INTO tb_search_meta_v4(
20608
+ `INSERT OR IGNORE INTO tb_search_meta_v5(
20419
20609
  singleton, revision, seeded, cursor_secret
20420
20610
  ) VALUES (1, 0, 0, lower(hex(randomblob(32))))`,
20421
- `CREATE TABLE IF NOT EXISTS tb_search_snapshots_v4 (
20611
+ `CREATE TABLE IF NOT EXISTS tb_search_snapshots_v5 (
20422
20612
  path TEXT PRIMARY KEY,
20423
20613
  digest TEXT NOT NULL
20424
20614
  )`,
20425
- `CREATE TRIGGER IF NOT EXISTS tb_search_snapshots_v4_capacity
20426
- BEFORE INSERT ON tb_search_snapshots_v4
20615
+ `CREATE TRIGGER IF NOT EXISTS tb_search_snapshots_v5_capacity
20616
+ BEFORE INSERT ON tb_search_snapshots_v5
20427
20617
  WHEN NOT EXISTS (
20428
- SELECT 1 FROM tb_search_snapshots_v4 WHERE path = new.path
20429
- ) AND (SELECT COUNT(*) FROM tb_search_snapshots_v4) >= ${TOOL_SEARCH_AUDIT_NODE_LIMIT}
20618
+ SELECT 1 FROM tb_search_snapshots_v5 WHERE path = new.path
20619
+ ) AND (SELECT COUNT(*) FROM tb_search_snapshots_v5) >= ${TOOL_SEARCH_AUDIT_NODE_LIMIT}
20430
20620
  BEGIN
20431
20621
  SELECT RAISE(ABORT, 'tb_search_path_capacity');
20432
20622
  END`
20433
20623
  ];
20434
20624
  var TOOL_SEARCH_CAPACITY_MARKER = "tb_search_path_capacity";
20435
20625
  var TOOL_SEARCH_INSERT_SQL = `
20436
- INSERT INTO tb_search_tools_v4 (path, name, description, feedback)
20437
- VALUES (?, ?, ?, ?)
20626
+ INSERT INTO tb_search_tools_v5 (path, name, description, effect, feedback)
20627
+ VALUES (?, ?, ?, ?, ?)
20438
20628
  `;
20439
- var TOOL_SEARCH_INSERT_SNAPSHOT_SQL = "INSERT INTO tb_search_snapshots_v4(path, digest) VALUES (?, ?)";
20440
- var META_SQL = "SELECT revision, seeded, cursor_secret FROM tb_search_meta_v4 WHERE singleton = 1";
20441
- var SNAPSHOT_DIGESTS_SQL = "SELECT path, digest FROM tb_search_snapshots_v4 ORDER BY path";
20629
+ var TOOL_SEARCH_INSERT_SNAPSHOT_SQL = "INSERT INTO tb_search_snapshots_v5(path, digest) VALUES (?, ?)";
20630
+ var META_SQL = "SELECT revision, seeded, cursor_secret FROM tb_search_meta_v5 WHERE singleton = 1";
20631
+ var SNAPSHOT_DIGESTS_SQL = "SELECT path, digest FROM tb_search_snapshots_v5 ORDER BY path";
20442
20632
  var PATH_STATE_SQL = `
20443
20633
  SELECT snapshots.digest,
20444
- EXISTS(SELECT 1 FROM tb_search_tools_v4 WHERE path = ?) AS has_tools,
20445
- (SELECT COUNT(*) FROM tb_search_snapshots_v4) AS path_count
20634
+ EXISTS(SELECT 1 FROM tb_search_tools_v5 WHERE path = ?) AS has_tools,
20635
+ (SELECT COUNT(*) FROM tb_search_snapshots_v5) AS path_count
20446
20636
  FROM (SELECT 1) AS singleton
20447
- LEFT JOIN tb_search_snapshots_v4 AS snapshots ON snapshots.path = ?
20637
+ LEFT JOIN tb_search_snapshots_v5 AS snapshots ON snapshots.path = ?
20448
20638
  `;
20449
- var PRESENT_SQL = "SELECT 1 AS present FROM tb_search_tools_v4 WHERE path = ? LIMIT 1";
20639
+ var PRESENT_SQL = "SELECT 1 AS present FROM tb_search_tools_v5 WHERE path = ? LIMIT 1";
20450
20640
  var PRESENT_PREFIX_SQL = `
20451
- SELECT 1 AS present FROM tb_search_tools_v4
20641
+ SELECT 1 AS present FROM tb_search_tools_v5
20452
20642
  WHERE path = ? OR substr(path, 1, length(?) + 1) = ? || '/'
20453
20643
  LIMIT 1
20454
20644
  `;
20455
- var DELETE_TOOLS_SQL = "DELETE FROM tb_search_tools_v4 WHERE path = ?";
20456
- var DELETE_SNAPSHOT_SQL = "DELETE FROM tb_search_snapshots_v4 WHERE path = ?";
20645
+ var DELETE_TOOLS_SQL = "DELETE FROM tb_search_tools_v5 WHERE path = ?";
20646
+ var DELETE_SNAPSHOT_SQL = "DELETE FROM tb_search_snapshots_v5 WHERE path = ?";
20457
20647
  var DELETE_TOOLS_PREFIX_SQL = `
20458
- DELETE FROM tb_search_tools_v4
20648
+ DELETE FROM tb_search_tools_v5
20459
20649
  WHERE path = ? OR substr(path, 1, length(?) + 1) = ? || '/'
20460
20650
  `;
20461
20651
  var DELETE_SNAPSHOT_PREFIX_SQL = `
20462
- DELETE FROM tb_search_snapshots_v4
20652
+ DELETE FROM tb_search_snapshots_v5
20463
20653
  WHERE path = ? OR substr(path, 1, length(?) + 1) = ? || '/'
20464
20654
  `;
20465
- var DELETE_ALL_TOOLS_SQL = "DELETE FROM tb_search_tools_v4";
20466
- var DELETE_ALL_SNAPSHOTS_SQL = "DELETE FROM tb_search_snapshots_v4";
20467
- var BUMP_REVISION_SQL = "UPDATE tb_search_meta_v4 SET revision = revision + 1 WHERE singleton = 1";
20468
- var COMPLETE_REBUILD_SQL = "UPDATE tb_search_meta_v4 SET seeded = 1, revision = revision + 1 WHERE singleton = 1";
20469
- function toolSearchCandidateStatement(units, limit, offset, syntax) {
20470
- const values = units.map((unit, index) => `(${syntax.placeholder(index + 1)}, ${unit.tier})`).join(", ");
20471
- const limitParam = syntax.placeholder(units.length + 1);
20472
- const offsetParam = syntax.placeholder(units.length + 2);
20655
+ var DELETE_ALL_TOOLS_SQL = "DELETE FROM tb_search_tools_v5";
20656
+ var DELETE_ALL_SNAPSHOTS_SQL = "DELETE FROM tb_search_snapshots_v5";
20657
+ var BUMP_REVISION_SQL = "UPDATE tb_search_meta_v5 SET revision = revision + 1 WHERE singleton = 1";
20658
+ var COMPLETE_REBUILD_SQL = "UPDATE tb_search_meta_v5 SET seeded = 1, revision = revision + 1 WHERE singleton = 1";
20659
+ function toolSearchEffectSql(effect) {
20660
+ switch (effect) {
20661
+ case "read":
20662
+ return "'read'";
20663
+ case "write":
20664
+ return "'write'";
20665
+ case "destructive":
20666
+ return "'destructive'";
20667
+ case "unknown":
20668
+ return "'unknown'";
20669
+ default:
20670
+ throw new TBError("invalid_argument", `\u5DE5\u5177\u641C\u7D22 effect '${String(effect)}' \u975E\u6CD5`);
20671
+ }
20672
+ }
20673
+ function toolSearchCandidateStatement(units, totalTermCount, limit, offset, constraints, syntax) {
20674
+ if (!Number.isInteger(totalTermCount) || totalTermCount < 1 || units.some((unit) => !Number.isInteger(unit.logicalTermId) || unit.logicalTermId < 0 || unit.logicalTermId >= totalTermCount)) {
20675
+ throw new TBError("invalid_argument", "\u5DE5\u5177\u641C\u7D22 logical term \u8BA1\u5212\u975E\u6CD5");
20676
+ }
20677
+ const values = units.map((unit, index) => `(${unit.logicalTermId}, ${syntax.placeholder(index + 1)}, ${unit.tier}, ${searchUnitAllowsPath(unit) ? 1 : 0})`).join(", ");
20678
+ const hasPrefix = constraints.pathPrefix !== void 0;
20679
+ const prefixParam = hasPrefix ? syntax.placeholder(units.length + 1) : void 0;
20680
+ const trailingStart = units.length + (hasPrefix ? 2 : 1);
20681
+ const limitParam = syntax.placeholder(trailingStart);
20682
+ const offsetParam = syntax.placeholder(trailingStart + 1);
20683
+ const requiredMatchedTerms = constraints.minCoverage === void 0 ? 1 : Math.ceil(constraints.minCoverage * totalTermCount);
20473
20684
  const like = syntax.likeOperator;
20685
+ const effectLiterals = constraints.effects?.map(toolSearchEffectSql);
20686
+ const prefixCte = hasPrefix ? `, prefix_filter(value) AS (VALUES (${prefixParam}))` : "";
20687
+ const filterPredicates = [
20688
+ ...hasPrefix ? [
20689
+ `(
20690
+ tools.path = prefix_filter.value
20691
+ OR substr(tools.path, 1, length(prefix_filter.value) + 1)
20692
+ = prefix_filter.value || '/'
20693
+ )`
20694
+ ] : [],
20695
+ ...effectLiterals === void 0 ? [] : [`tools.effect IN (${effectLiterals.join(", ")})`]
20696
+ ];
20697
+ const filteredToolsCte = filterPredicates.length > 0 ? `,
20698
+ filtered_tools AS (
20699
+ SELECT tools.*
20700
+ FROM tb_search_tools_v5 AS tools
20701
+ ${hasPrefix ? "CROSS JOIN prefix_filter" : ""}
20702
+ WHERE ${filterPredicates.join("\n AND ")}
20703
+ )` : "";
20704
+ const candidateTable = filterPredicates.length > 0 ? "filtered_tools" : "tb_search_tools_v5";
20474
20705
  return {
20475
- params: [...units.map((unit) => unit.pattern), limit + 1, offset],
20706
+ params: [
20707
+ ...units.map((unit) => unit.pattern),
20708
+ ...hasPrefix ? [constraints.pathPrefix] : [],
20709
+ limit + 1,
20710
+ offset
20711
+ ],
20476
20712
  sql: `
20477
- WITH units(pattern, tier) AS (VALUES ${values})
20478
- SELECT * FROM (
20479
- SELECT tools.id, tools.path, tools.name,
20480
- (
20481
- SELECT COALESCE(SUM(units.tier * CASE
20482
- WHEN tools.name ${like} units.pattern ESCAPE '!' THEN 10
20483
- WHEN tools.path ${like} units.pattern ESCAPE '!' THEN 5
20484
- WHEN tools.description ${like} units.pattern ESCAPE '!' THEN 3
20485
- WHEN tools.feedback ${like} units.pattern ESCAPE '!' THEN 1
20486
- ELSE 0
20487
- END), 0)
20488
- FROM units
20489
- ) AS score
20490
- FROM tb_search_tools_v4 AS tools
20491
- ) AS scored_tools
20492
- WHERE score > 0
20493
- ORDER BY score DESC, path, name
20713
+ WITH units(logical_term_id, pattern, tier, path_allowed) AS (VALUES ${values})${prefixCte}${filteredToolsCte},
20714
+ unit_matches AS (
20715
+ SELECT tools.id, tools.path, tools.name, units.logical_term_id,
20716
+ units.tier * CASE
20717
+ WHEN tools.name ${like} units.pattern ESCAPE '!' THEN 10
20718
+ WHEN units.path_allowed = 1
20719
+ AND tools.path ${like} units.pattern ESCAPE '!' THEN 5
20720
+ WHEN tools.description ${like} units.pattern ESCAPE '!' THEN 3
20721
+ WHEN tools.feedback ${like} units.pattern ESCAPE '!' THEN 1
20722
+ ELSE 0
20723
+ END AS unit_score
20724
+ FROM ${candidateTable} AS tools
20725
+ CROSS JOIN units
20726
+ ),
20727
+ term_matches AS (
20728
+ SELECT id, path, name, logical_term_id, MAX(unit_score) AS term_score
20729
+ FROM unit_matches
20730
+ WHERE unit_score > 0
20731
+ GROUP BY id, path, name, logical_term_id
20732
+ ),
20733
+ scored_tools AS (
20734
+ SELECT id, path, name,
20735
+ CAST(COUNT(*) AS INTEGER) AS matched_term_count,
20736
+ CAST(SUM(term_score) AS INTEGER) AS score
20737
+ FROM term_matches
20738
+ GROUP BY id, path, name
20739
+ )
20740
+ SELECT id, path, name, matched_term_count, ${totalTermCount} AS total_term_count
20741
+ FROM scored_tools
20742
+ WHERE matched_term_count >= ${requiredMatchedTerms}
20743
+ ORDER BY matched_term_count DESC, score DESC, path, name
20494
20744
  LIMIT ${limitParam} OFFSET ${offsetParam}
20495
20745
  `
20496
20746
  };
20497
20747
  }
20498
20748
  var sqliteSearchDialect = {
20499
- candidateStatement: (query, limit, offset) => toolSearchCandidateStatement(
20500
- prepareToolSearchUnits(query),
20501
- limit,
20502
- offset,
20503
- { likeOperator: "LIKE", placeholder: () => "?" }
20504
- ),
20749
+ candidateStatement: (query, limit, offset, rawConstraints) => {
20750
+ const constraints = normalizeToolSearchOptions(rawConstraints);
20751
+ const prepared = prepareToolSearchQuery(
20752
+ query,
20753
+ constraints.pathPrefix === void 0 ? TOOL_SEARCH_UNIT_LIMIT : TOOL_SEARCH_UNIT_LIMIT - 1
20754
+ );
20755
+ return toolSearchCandidateStatement(
20756
+ prepared.units,
20757
+ prepared.totalTermCount,
20758
+ limit,
20759
+ offset,
20760
+ constraints,
20761
+ { likeOperator: "LIKE", placeholder: () => "?" }
20762
+ );
20763
+ },
20505
20764
  schemaStatements: TOOL_SEARCH_SCHEMA_STATEMENTS,
20506
20765
  statements: {
20507
20766
  bumpRevision: BUMP_REVISION_SQL,
@@ -20555,6 +20814,10 @@ var SqlSearchIndex = class {
20555
20814
  await this.driver.ensureSchema();
20556
20815
  return (await this.meta()).seeded === 1;
20557
20816
  }
20817
+ async revision() {
20818
+ await this.driver.ensureSchema();
20819
+ return (await this.meta()).revision;
20820
+ }
20558
20821
  async replace(path, tools, opts = {}) {
20559
20822
  const canonical = normalizeToolSearchPath(path);
20560
20823
  const records = serializeToolSearchSnapshot(canonical, tools, opts.feedback ?? "");
@@ -20633,6 +20896,8 @@ var SqlSearchIndex = class {
20633
20896
  async search(query, opts) {
20634
20897
  assertKeywordToolSearchMode(opts);
20635
20898
  const normalized = normalizeToolSearchQuery(query);
20899
+ const constraints = normalizeToolSearchOptions(opts);
20900
+ const optionsFingerprint = toolSearchOptionsFingerprint(constraints);
20636
20901
  const mode = opts?.mode ?? "keyword";
20637
20902
  await this.driver.ensureSchema();
20638
20903
  const meta3 = await this.meta();
@@ -20642,20 +20907,28 @@ var SqlSearchIndex = class {
20642
20907
  normalized,
20643
20908
  mode,
20644
20909
  revision,
20645
- meta3.cursor_secret
20910
+ meta3.cursor_secret,
20911
+ constraints
20646
20912
  );
20647
20913
  const limit = Math.min(normalizeToolSearchLimit(opts?.limit), TOOL_SEARCH_BATCH_LIMIT);
20648
20914
  const rows = await this.driver.all(
20649
- this.dialect.candidateStatement(normalized, limit, offset)
20915
+ this.dialect.candidateStatement(normalized, limit, offset, constraints)
20650
20916
  );
20651
- const hasMore = rows.length > limit;
20652
- const page = hasMore ? rows.slice(0, limit) : rows;
20917
+ const firstBand = rows[0]?.matched_term_count;
20918
+ const bandEnd = constraints.matching === "best" && firstBand !== void 0 ? rows.findIndex((row) => row.matched_term_count !== firstBand) : -1;
20919
+ const pageLength = bandEnd >= 0 ? Math.min(limit, bandEnd) : Math.min(limit, rows.length);
20920
+ const page = rows.slice(0, pageLength);
20921
+ const hasMore = rows.length > page.length;
20653
20922
  const items = page.map((row, index) => ({
20923
+ coverage: row.matched_term_count / row.total_term_count,
20924
+ matchedTermCount: row.matched_term_count,
20654
20925
  name: row.name,
20655
20926
  path: row.path,
20656
20927
  ref: String(row.id),
20657
20928
  resumeOffset: offset + index + 1,
20658
- revision
20929
+ revision,
20930
+ searchOptionsFingerprint: optionsFingerprint,
20931
+ totalTermCount: row.total_term_count
20659
20932
  }));
20660
20933
  const last = items[items.length - 1];
20661
20934
  return hasMore && last !== void 0 ? {
@@ -20665,7 +20938,8 @@ var SqlSearchIndex = class {
20665
20938
  mode,
20666
20939
  revision,
20667
20940
  last.resumeOffset,
20668
- meta3.cursor_secret
20941
+ meta3.cursor_secret,
20942
+ constraints
20669
20943
  )
20670
20944
  } : { items };
20671
20945
  }
@@ -20675,11 +20949,10 @@ var SqlSearchIndex = class {
20675
20949
  if (candidate.revision !== meta3.revision) {
20676
20950
  throw new TBError("invalid_argument", "\u641C\u7D22 cursor \u5DF2\u5931\u6548");
20677
20951
  }
20678
- return await encodeToolSearchCursor(
20952
+ return await encodeToolSearchCursorForCandidate(
20679
20953
  query,
20680
20954
  mode,
20681
- meta3.revision,
20682
- candidate.resumeOffset,
20955
+ candidate,
20683
20956
  meta3.cursor_secret
20684
20957
  );
20685
20958
  }
@@ -20687,11 +20960,12 @@ var SqlSearchIndex = class {
20687
20960
 
20688
20961
  // ../core/src/search/pgSearchDialect.ts
20689
20962
  var PG_SEARCH_SCHEMA_STATEMENTS = [
20690
- `CREATE TABLE IF NOT EXISTS tb_search_tools_v4 (
20963
+ `CREATE TABLE IF NOT EXISTS tb_search_tools_v5 (
20691
20964
  id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
20692
20965
  path text NOT NULL,
20693
20966
  name text NOT NULL,
20694
20967
  description text NOT NULL DEFAULT '',
20968
+ effect text NOT NULL CHECK (effect IN ('read', 'write', 'destructive', 'unknown')),
20695
20969
  feedback text NOT NULL DEFAULT '',
20696
20970
  UNIQUE(path, name)
20697
20971
  )`,
@@ -20699,7 +20973,7 @@ var PG_SEARCH_SCHEMA_STATEMENTS = [
20699
20973
  // 样本上对单 unit 多列 ILIKE 一律选 Seq Scan;GIN 让写入和体积显著增加却未改善
20700
20974
  // 检索。4000 行只是代表样本,不是严格工具行上限(节点内还受 20KB JSON 约束);
20701
20975
  // 查询单元数或容量边界变化时,应重跑 searchBench 并重新评估查询形状与索引。
20702
- `CREATE TABLE IF NOT EXISTS tb_search_meta_v4 (
20976
+ `CREATE TABLE IF NOT EXISTS tb_search_meta_v5 (
20703
20977
  singleton integer PRIMARY KEY CHECK (singleton = 1),
20704
20978
  revision bigint NOT NULL DEFAULT 0,
20705
20979
  seeded integer NOT NULL DEFAULT 0,
@@ -20707,32 +20981,32 @@ var PG_SEARCH_SCHEMA_STATEMENTS = [
20707
20981
  )`,
20708
20982
  // cursor_secret 需 64 hex(32 字节)。两个内置 gen_random_uuid() 去连字符正好 64
20709
20983
  // hex,避免依赖 pgcrypto 的 gen_random_bytes(自托管 PG 未必预装 pgcrypto)。
20710
- `INSERT INTO tb_search_meta_v4(singleton, revision, seeded, cursor_secret)
20984
+ `INSERT INTO tb_search_meta_v5(singleton, revision, seeded, cursor_secret)
20711
20985
  VALUES (
20712
20986
  1, 0, 0,
20713
20987
  replace(gen_random_uuid()::text, '-', '') || replace(gen_random_uuid()::text, '-', '')
20714
20988
  )
20715
20989
  ON CONFLICT (singleton) DO NOTHING`,
20716
- `CREATE TABLE IF NOT EXISTS tb_search_snapshots_v4 (
20990
+ `CREATE TABLE IF NOT EXISTS tb_search_snapshots_v5 (
20717
20991
  path text PRIMARY KEY,
20718
20992
  digest text NOT NULL
20719
20993
  )`,
20720
- `CREATE OR REPLACE FUNCTION tb_search_snapshots_v4_capacity()
20994
+ `CREATE OR REPLACE FUNCTION tb_search_snapshots_v5_capacity()
20721
20995
  RETURNS trigger AS $$
20722
20996
  BEGIN
20723
- IF (SELECT COUNT(*) FROM tb_search_snapshots_v4) >= ${TOOL_SEARCH_AUDIT_NODE_LIMIT} THEN
20997
+ IF (SELECT COUNT(*) FROM tb_search_snapshots_v5) >= ${TOOL_SEARCH_AUDIT_NODE_LIMIT} THEN
20724
20998
  RAISE EXCEPTION '${TOOL_SEARCH_CAPACITY_MARKER}';
20725
20999
  END IF;
20726
21000
  RETURN NEW;
20727
21001
  END;
20728
21002
  $$ LANGUAGE plpgsql`,
20729
- `DROP TRIGGER IF EXISTS tb_search_snapshots_v4_capacity_trg ON tb_search_snapshots_v4`,
20730
- `CREATE TRIGGER tb_search_snapshots_v4_capacity_trg
20731
- BEFORE INSERT ON tb_search_snapshots_v4
20732
- FOR EACH ROW EXECUTE FUNCTION tb_search_snapshots_v4_capacity()`
21003
+ `DROP TRIGGER IF EXISTS tb_search_snapshots_v5_capacity_trg ON tb_search_snapshots_v5`,
21004
+ `CREATE TRIGGER tb_search_snapshots_v5_capacity_trg
21005
+ BEFORE INSERT ON tb_search_snapshots_v5
21006
+ FOR EACH ROW EXECUTE FUNCTION tb_search_snapshots_v5_capacity()`
20733
21007
  ];
20734
21008
  var PG_SEARCH_WRITE_LOCK_KEY = 2069799624;
20735
- var PG_SEARCH_INSERT_SNAPSHOT_SQL = "INSERT INTO tb_search_snapshots_v4(path, digest) VALUES ($1, $2)";
21009
+ var PG_SEARCH_INSERT_SNAPSHOT_SQL = "INSERT INTO tb_search_snapshots_v5(path, digest) VALUES ($1, $2)";
20736
21010
  function pgBulkInsertSql(table, columns, rows) {
20737
21011
  const tuples = [];
20738
21012
  for (let r = 0; r < rows; r++) {
@@ -20741,50 +21015,65 @@ function pgBulkInsertSql(table, columns, rows) {
20741
21015
  }
20742
21016
  return `INSERT INTO ${table} (${columns.join(", ")}) VALUES ${tuples.join(", ")}`;
20743
21017
  }
20744
- var PG_SEARCH_TOOLS_TABLE = "tb_search_tools_v4";
20745
- var PG_SEARCH_TOOLS_COLUMNS = ["path", "name", "description", "feedback"];
20746
- var PG_SEARCH_SNAPSHOTS_TABLE = "tb_search_snapshots_v4";
21018
+ var PG_SEARCH_TOOLS_TABLE = "tb_search_tools_v5";
21019
+ var PG_SEARCH_TOOLS_COLUMNS = [
21020
+ "path",
21021
+ "name",
21022
+ "description",
21023
+ "effect",
21024
+ "feedback"
21025
+ ];
21026
+ var PG_SEARCH_SNAPSHOTS_TABLE = "tb_search_snapshots_v5";
20747
21027
  var PG_SEARCH_SNAPSHOTS_COLUMNS = ["path", "digest"];
20748
21028
  var PG_SEARCH_INSERT_ROWS_MAX = 1e3;
20749
21029
  var META_SQL2 = `
20750
21030
  SELECT revision::int AS revision, seeded::int AS seeded, cursor_secret
20751
- FROM tb_search_meta_v4 WHERE singleton = 1
21031
+ FROM tb_search_meta_v5 WHERE singleton = 1
20752
21032
  `;
20753
- var SNAPSHOT_DIGESTS_SQL2 = "SELECT path, digest FROM tb_search_snapshots_v4 ORDER BY path";
21033
+ var SNAPSHOT_DIGESTS_SQL2 = "SELECT path, digest FROM tb_search_snapshots_v5 ORDER BY path";
20754
21034
  var PATH_STATE_SQL2 = `
20755
21035
  SELECT snapshots.digest,
20756
- EXISTS(SELECT 1 FROM tb_search_tools_v4 WHERE path = $1)::int AS has_tools,
20757
- (SELECT COUNT(*) FROM tb_search_snapshots_v4)::int AS path_count
21036
+ EXISTS(SELECT 1 FROM tb_search_tools_v5 WHERE path = $1)::int AS has_tools,
21037
+ (SELECT COUNT(*) FROM tb_search_snapshots_v5)::int AS path_count
20758
21038
  FROM (SELECT 1) AS singleton
20759
- LEFT JOIN tb_search_snapshots_v4 AS snapshots ON snapshots.path = $2
21039
+ LEFT JOIN tb_search_snapshots_v5 AS snapshots ON snapshots.path = $2
20760
21040
  `;
20761
- var PRESENT_SQL2 = "SELECT 1 AS present FROM tb_search_tools_v4 WHERE path = $1 LIMIT 1";
21041
+ var PRESENT_SQL2 = "SELECT 1 AS present FROM tb_search_tools_v5 WHERE path = $1 LIMIT 1";
20762
21042
  var PRESENT_PREFIX_SQL2 = `
20763
- SELECT 1 AS present FROM tb_search_tools_v4
21043
+ SELECT 1 AS present FROM tb_search_tools_v5
20764
21044
  WHERE path = $1 OR substr(path, 1, length($2) + 1) = $3 || '/'
20765
21045
  LIMIT 1
20766
21046
  `;
20767
- var DELETE_TOOLS_SQL2 = "DELETE FROM tb_search_tools_v4 WHERE path = $1";
20768
- var DELETE_SNAPSHOT_SQL2 = "DELETE FROM tb_search_snapshots_v4 WHERE path = $1";
21047
+ var DELETE_TOOLS_SQL2 = "DELETE FROM tb_search_tools_v5 WHERE path = $1";
21048
+ var DELETE_SNAPSHOT_SQL2 = "DELETE FROM tb_search_snapshots_v5 WHERE path = $1";
20769
21049
  var DELETE_TOOLS_PREFIX_SQL2 = `
20770
- DELETE FROM tb_search_tools_v4
21050
+ DELETE FROM tb_search_tools_v5
20771
21051
  WHERE path = $1 OR substr(path, 1, length($2) + 1) = $3 || '/'
20772
21052
  `;
20773
21053
  var DELETE_SNAPSHOT_PREFIX_SQL2 = `
20774
- DELETE FROM tb_search_snapshots_v4
21054
+ DELETE FROM tb_search_snapshots_v5
20775
21055
  WHERE path = $1 OR substr(path, 1, length($2) + 1) = $3 || '/'
20776
21056
  `;
20777
- var DELETE_ALL_TOOLS_SQL2 = "DELETE FROM tb_search_tools_v4";
20778
- var DELETE_ALL_SNAPSHOTS_SQL2 = "DELETE FROM tb_search_snapshots_v4";
20779
- var BUMP_REVISION_SQL2 = "UPDATE tb_search_meta_v4 SET revision = revision + 1 WHERE singleton = 1";
20780
- var COMPLETE_REBUILD_SQL2 = "UPDATE tb_search_meta_v4 SET seeded = 1, revision = revision + 1 WHERE singleton = 1";
21057
+ var DELETE_ALL_TOOLS_SQL2 = "DELETE FROM tb_search_tools_v5";
21058
+ var DELETE_ALL_SNAPSHOTS_SQL2 = "DELETE FROM tb_search_snapshots_v5";
21059
+ var BUMP_REVISION_SQL2 = "UPDATE tb_search_meta_v5 SET revision = revision + 1 WHERE singleton = 1";
21060
+ var COMPLETE_REBUILD_SQL2 = "UPDATE tb_search_meta_v5 SET seeded = 1, revision = revision + 1 WHERE singleton = 1";
20781
21061
  var pgSearchDialect = {
20782
- candidateStatement: (query, limit, offset) => toolSearchCandidateStatement(
20783
- prepareToolSearchUnits(query),
20784
- limit,
20785
- offset,
20786
- { likeOperator: "ILIKE", placeholder: (index) => `$${index}` }
20787
- ),
21062
+ candidateStatement: (query, limit, offset, rawConstraints) => {
21063
+ const constraints = normalizeToolSearchOptions(rawConstraints);
21064
+ const prepared = prepareToolSearchQuery(
21065
+ query,
21066
+ constraints.pathPrefix === void 0 ? TOOL_SEARCH_UNIT_LIMIT : TOOL_SEARCH_UNIT_LIMIT - 1
21067
+ );
21068
+ return toolSearchCandidateStatement(
21069
+ prepared.units,
21070
+ prepared.totalTermCount,
21071
+ limit,
21072
+ offset,
21073
+ constraints,
21074
+ { likeOperator: "ILIKE", placeholder: (index) => `$${index}` }
21075
+ );
21076
+ },
20788
21077
  schemaStatements: PG_SEARCH_SCHEMA_STATEMENTS,
20789
21078
  statements: {
20790
21079
  bumpRevision: BUMP_REVISION_SQL2,
@@ -21494,7 +21783,15 @@ function virtualizeTools(v, upstream) {
21494
21783
  const hidden = new Set(v?.hide ?? []);
21495
21784
  for (const tool of upstream) {
21496
21785
  if (hidden.has(tool.name)) continue;
21497
- const name = v ? virtualName(v, tool.name) : tool.name;
21786
+ const projectedName = v ? virtualName(v, tool.name) : tool.name;
21787
+ const name = canonicalizeSegment(projectedName);
21788
+ const previous = reverse.get(name);
21789
+ if (previous !== void 0) {
21790
+ throw new TBError(
21791
+ "invalid_argument",
21792
+ `\u5DE5\u5177\u540D '${previous}' \u4E0E '${tool.name}' \u89C4\u8303\u5316\u540E\u51B2\u7A81:'${name}',\u8BF7\u663E\u5F0F rename`
21793
+ );
21794
+ }
21498
21795
  const description = v?.describe?.[tool.name] ?? tool.description;
21499
21796
  exposed.push({ ...tool, name, description });
21500
21797
  reverse.set(name, tool.name);
@@ -22252,6 +22549,9 @@ export {
22252
22549
  nodeInputSchema,
22253
22550
  helpJsonSchema,
22254
22551
  treeJsonSchema,
22552
+ toolSearchRelevanceSchema,
22553
+ toolSearchSourceSchema,
22554
+ toolSearchSourceResultSchema,
22255
22555
  toolSearchPageSchema,
22256
22556
  toolSearchRequestSchema,
22257
22557
  registryNodeSchema,
@@ -22320,11 +22620,15 @@ export {
22320
22620
  TOOL_SEARCH_BATCH_LIMIT,
22321
22621
  TOOL_SEARCH_WORK_LIMIT,
22322
22622
  TOOL_SEARCH_AUDIT_NODE_LIMIT,
22623
+ TOOL_SEARCH_DESCRIPTION_BYTES_MAX,
22323
22624
  TOOL_SEARCH_PAGE_BYTES,
22625
+ TOOL_SEARCH_RANKING_VERSION,
22324
22626
  normalizeToolSearchLimit,
22325
22627
  normalizeToolSearchPath,
22628
+ normalizeToolSearchOptions,
22326
22629
  serializeToolSearchSnapshot,
22327
22630
  toolSearchSnapshotDigest,
22631
+ prepareToolSearchQuery,
22328
22632
  TOOL_SEARCH_SCHEMA_STATEMENTS,
22329
22633
  TOOL_SEARCH_INSERT_SQL,
22330
22634
  TOOL_SEARCH_INSERT_SNAPSHOT_SQL,