@tool-bridge/server 0.10.1 → 0.13.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-SLT4UDB3.js → airtable-E2TJFCGB.js} +4 -4
  2. package/dist/{alt_text_generator_ai-HCFYQNEN.js → alt_text_generator_ai-UBV5H2N3.js} +4 -4
  3. package/dist/{amap-ZOOTZCI2.js → amap-ASVRIYPW.js} +4 -4
  4. package/dist/{anthropic-IUWXKV76.js → anthropic-LQSJWGV3.js} +4 -4
  5. package/dist/{apify-HQXUP3ZL.js → apify-CL4YK6HT.js} +4 -4
  6. package/dist/{brave_search-HG5PMEDZ.js → brave_search-WZQF2QWE.js} +4 -4
  7. package/dist/{chunk-AWXZMW6M.js → chunk-4U5OQW7F.js} +126 -111
  8. package/dist/{chunk-V4VHC3Q6.js → chunk-BK2ZIWLD.js} +2 -2
  9. package/dist/{chunk-WIH5OHFG.js → chunk-HIROW6TB.js} +36 -35
  10. package/dist/{chunk-EMUJLM32.js → chunk-M4LHMRRY.js} +210 -154
  11. package/dist/{chunk-THDEI7S7.js → chunk-P4TQJHBO.js} +1 -1
  12. package/dist/{circleci-XA4GXPOT.js → circleci-EHGI2HKR.js} +4 -4
  13. package/dist/{clerk-MUAETUIY.js → clerk-OUN4SX22.js} +4 -4
  14. package/dist/{cloudflare_dns-BRYRH55W.js → cloudflare_dns-DMU3WOPG.js} +4 -4
  15. package/dist/{cohere-XKVGQJQH.js → cohere-3HDSCQIB.js} +4 -4
  16. package/dist/{confluence-SWP6UUEK.js → confluence-YPZXKQTQ.js} +4 -4
  17. package/dist/{convertapi-42FNXPAS.js → convertapi-47ENNUBY.js} +4 -4
  18. package/dist/{currencyapi-7IECLAKK.js → currencyapi-IX4ICDZA.js} +4 -4
  19. package/dist/{deepseek-VD3VY3D2.js → deepseek-SCOPJSA6.js} +4 -4
  20. package/dist/{docker_hub-YCEWCV5D.js → docker_hub-2DXJVAP4.js} +4 -4
  21. package/dist/{dropbox-KCAEQENT.js → dropbox-LE2OM2SR.js} +4 -4
  22. package/dist/{dub-AVLJI73G.js → dub-7LKKJADI.js} +4 -4
  23. package/dist/{e2b-NZPEKNY3.js → e2b-P3EOM65Q.js} +4 -4
  24. package/dist/{exa-MHHTRY4Y.js → exa-AETANJQ3.js} +4 -4
  25. package/dist/{fal_ai-VKVUKXE2.js → fal_ai-VWAMTEZE.js} +4 -4
  26. package/dist/{feishu-AFLX4VZX.js → feishu-VQMM3APW.js} +3 -3
  27. package/dist/{feishu_custom_bot-S4XJYZVB.js → feishu_custom_bot-HEK63AP3.js} +4 -4
  28. package/dist/{figma-6LBMPYPL.js → figma-7JMV3B5O.js} +4 -4
  29. package/dist/{firehydrant-JRAJ4CMG.js → firehydrant-SOU4P7SE.js} +4 -4
  30. package/dist/{fixer-BTWM3K4Z.js → fixer-KELXNOIQ.js} +4 -4
  31. package/dist/{fly-FUY25D36.js → fly-Y26QH6AC.js} +4 -4
  32. package/dist/{front-SFQD4V63.js → front-2RUHP54Y.js} +4 -4
  33. package/dist/{geocodio-JZTFWKOE.js → geocodio-BTSXWU55.js} +4 -4
  34. package/dist/{ghost-HNZTH6AR.js → ghost-BA55ISIU.js} +4 -4
  35. package/dist/{github-3J6ZYHGY.js → github-VUYFDSHK.js} +4 -4
  36. package/dist/{gmail-Y4GWZ2UJ.js → gmail-3Z2WCVLT.js} +4 -4
  37. package/dist/{googlecalendar-JK6B3ZCO.js → googlecalendar-LZKRUXHY.js} +4 -4
  38. package/dist/{googledocs-VERSNFGF.js → googledocs-RBK2HMPZ.js} +4 -4
  39. package/dist/{grafana-WABWHNKT.js → grafana-E626W3N3.js} +4 -4
  40. package/dist/{graphhopper-PWZOVQQF.js → graphhopper-YNURJCFZ.js} +4 -4
  41. package/dist/index.d.ts +7 -7
  42. package/dist/index.js +2 -2
  43. package/dist/{ip2proxy-IJKSNZVR.js → ip2proxy-4DAJUOUR.js} +4 -4
  44. package/dist/{ipgeolocation_io-I27LWP7M.js → ipgeolocation_io-3BUSFLVD.js} +4 -4
  45. package/dist/{ipqualityscore-THLB64L6.js → ipqualityscore-7DKMRMEQ.js} +4 -4
  46. package/dist/{jina_ai-KHC4WQAK.js → jina_ai-NXXZRPT6.js} +4 -4
  47. package/dist/{jira-NAGZYZLK.js → jira-UG7ZIKSW.js} +4 -4
  48. package/dist/{langsmith-5BZ4CAWL.js → langsmith-66IP4KJ6.js} +4 -4
  49. package/dist/{lemlist-4D5DLIWT.js → lemlist-MVB4EQMS.js} +4 -4
  50. package/dist/{linear-5A6IZTNW.js → linear-6UC3AFY3.js} +4 -4
  51. package/dist/{logsnag-Q7CU4J7A.js → logsnag-NFJM6O4U.js} +4 -4
  52. package/dist/main.js +102 -102
  53. package/dist/{mattermost-36YSAHMQ.js → mattermost-FTJER2B6.js} +4 -4
  54. package/dist/{mem0-EVJ7KY5E.js → mem0-RR5ALUKD.js} +4 -4
  55. package/dist/{memos-KDNZATPM.js → memos-WOAY3T76.js} +4 -4
  56. package/dist/{metabase-MRBJG473.js → metabase-ZYG7NBPU.js} +4 -4
  57. package/dist/{mistral_ai-PDT25XCR.js → mistral_ai-FTCSXHJ5.js} +4 -4
  58. package/dist/{mother_duck-MN3OHZDF.js → mother_duck-ZMIGT5ZK.js} +4 -4
  59. package/dist/{ngrok-PEGRSO2H.js → ngrok-TEDZ4WUB.js} +4 -4
  60. package/dist/{notes-UUDL64JP.js → notes-4KZGQBRF.js} +2 -2
  61. package/dist/{notion-XRTFGM3Q.js → notion-ERLC3SKM.js} +4 -4
  62. package/dist/{open_exchange_rates-TLNDRZ54.js → open_exchange_rates-GBBHZLUS.js} +4 -4
  63. package/dist/{openai-EUDWNNU6.js → openai-24N26QWI.js} +4 -4
  64. package/dist/{opengraph_io-MKH5AUR3.js → opengraph_io-MTN4TTXP.js} +4 -4
  65. package/dist/{openrouter-YMGWGPI3.js → openrouter-BK6BL7EH.js} +4 -4
  66. package/dist/{outline-MTH7SZBU.js → outline-O3LF5SNM.js} +4 -4
  67. package/dist/{paddle-PWSGQPO6.js → paddle-IEDD5BMW.js} +4 -4
  68. package/dist/{perplexity-NBUHF5Z6.js → perplexity-HGPLFK72.js} +4 -4
  69. package/dist/{pinecone-5FVBDTET.js → pinecone-FTWR4JVG.js} +4 -4
  70. package/dist/{pipedrive-IJUNMGFQ.js → pipedrive-DDMA36AB.js} +4 -4
  71. package/dist/{polar-L72J7ISM.js → polar-YFGTOQYM.js} +4 -4
  72. package/dist/{posthog-4GDGMSSQ.js → posthog-GFEFPIH3.js} +4 -4
  73. package/dist/{postmark-25TFX6LC.js → postmark-N7YCE2DZ.js} +4 -4
  74. package/dist/{prerender-ZY7S5S4R.js → prerender-B77XIKL7.js} +4 -4
  75. package/dist/{pubmed-KCPFV76N.js → pubmed-XAFQSOCJ.js} +4 -4
  76. package/dist/{railway-IWOCVOXL.js → railway-DJ4P5DAJ.js} +4 -4
  77. package/dist/{readwise-JCN5J4ON.js → readwise-UNBGXBYC.js} +4 -4
  78. package/dist/{render-FUM4QWKI.js → render-Z43FLDJ3.js} +4 -4
  79. package/dist/{replicate-V5VIAEYB.js → replicate-BZAMQO7R.js} +4 -4
  80. package/dist/{resend-F3XQOI24.js → resend-MFUW2LNU.js} +4 -4
  81. package/dist/{rootly-XEDRHK66.js → rootly-5CHCWRPM.js} +4 -4
  82. package/dist/{scrapfly-PXDWBCOD.js → scrapfly-36O4IJDA.js} +4 -4
  83. package/dist/{scrapingbee-X5QCNZSS.js → scrapingbee-JK6HZA75.js} +4 -4
  84. package/dist/{screenshot_fyi-V6CE6WQS.js → screenshot_fyi-BDEL4D53.js} +4 -4
  85. package/dist/{semantic_scholar-NHEQ5J72.js → semantic_scholar-QHHG7RWT.js} +4 -4
  86. package/dist/{sentry-XDLPYMQI.js → sentry-OCUW4KNC.js} +4 -4
  87. package/dist/{shodan-H2YTSK7R.js → shodan-5UBQ6RKP.js} +4 -4
  88. package/dist/{shopify-Q5YDMDAD.js → shopify-OXIMRVHL.js} +4 -4
  89. package/dist/{stripe-ZXSIKY6A.js → stripe-W5XRW7WG.js} +4 -4
  90. package/dist/{supabase-TV2ZEVH5.js → supabase-DIC7ZIG7.js} +4 -4
  91. package/dist/{tavily-KKBMTUW6.js → tavily-NVWQPGF3.js} +4 -4
  92. package/dist/{telegram-JM4VE5FR.js → telegram-S755MPMM.js} +4 -4
  93. package/dist/{telnyx-NOXAAP6B.js → telnyx-MXRX75AP.js} +4 -4
  94. package/dist/{todoist-ATYSMZ2W.js → todoist-MNVUPHIF.js} +4 -4
  95. package/dist/{trello-BWRSV7VZ.js → trello-T7JLVYU4.js} +4 -4
  96. package/dist/{turso-P7Z4X5C5.js → turso-JDBW2RN4.js} +4 -4
  97. package/dist/{twilio-YL7NUXCX.js → twilio-EGYNUGMZ.js} +4 -4
  98. package/dist/{umami-JPWFBAPI.js → umami-QF2V23Z5.js} +4 -4
  99. package/dist/{unsplash-CJBI3UGZ.js → unsplash-VWTABYWL.js} +4 -4
  100. package/dist/{upstash_redis-J5IGSHWB.js → upstash_redis-FKUGE73T.js} +4 -4
  101. package/dist/{uptimerobot-HEFFBT3N.js → uptimerobot-55LTBUWA.js} +4 -4
  102. package/dist/{v2ex-MRYW7RM6.js → v2ex-LGG6X53N.js} +4 -4
  103. package/dist/{vercel-RNY4ZRTH.js → vercel-VAZGWMOZ.js} +4 -4
  104. package/dist/{wolfram_alpha_api-AF346YID.js → wolfram_alpha_api-YLVVZTPP.js} +4 -4
  105. package/dist/{wordpress-YWKGCQA5.js → wordpress-6LDTITVV.js} +4 -4
  106. package/dist/{workos-Y7AORGEG.js → workos-ML6NIEEP.js} +4 -4
  107. package/dist/{zhihu-X4FAKOAQ.js → zhihu-CACG2ZNY.js} +4 -4
  108. package/package.json +5 -5
@@ -141,7 +141,7 @@ import {
141
141
  url,
142
142
  validatePath,
143
143
  virtualizeTools
144
- } from "./chunk-AWXZMW6M.js";
144
+ } from "./chunk-4U5OQW7F.js";
145
145
 
146
146
  // src/config.ts
147
147
  var DEFAULT_PORT = 8787;
@@ -19103,16 +19103,16 @@ function createMcpProvider(config, secrets, opts) {
19103
19103
  function createPluginToolProvider(opts) {
19104
19104
  return {
19105
19105
  list: async () => {
19106
- const value = await callPlugin(opts, "List", {});
19106
+ const value = await callPlugin(opts, "list", {});
19107
19107
  if (!Array.isArray(value)) {
19108
- throw new TBError("unavailable", `plugin '${opts.manifest.id}' \u7684 List \u672A\u8FD4\u56DE\u5DE5\u5177\u6570\u7EC4`, {
19108
+ throw new TBError("unavailable", `plugin '${opts.manifest.id}' \u7684 list \u672A\u8FD4\u56DE\u5DE5\u5177\u6570\u7EC4`, {
19109
19109
  retryable: false
19110
19110
  });
19111
19111
  }
19112
19112
  return value;
19113
19113
  },
19114
19114
  call: async (name, args) => {
19115
- const value = await callPlugin(opts, "Call", { name, args });
19115
+ const value = await callPlugin(opts, "call", { name, args });
19116
19116
  if (value !== null && typeof value === "object" && "content" in value) {
19117
19117
  return value;
19118
19118
  }
@@ -19738,23 +19738,23 @@ async function skillhubProviderFor(node, cfg, deps, requestUrl) {
19738
19738
  return createSkillhubProvider(objects, opts);
19739
19739
  }
19740
19740
  async function dispatchSkillhubCmd(provider, tool, args) {
19741
- switch (tool) {
19742
- case "List":
19743
- return await provider.List(args.opts);
19744
- case "Get":
19745
- return typeof args.file === "string" ? await provider.GetFile(args.id, args.file) : await provider.Get(args.id);
19746
- case "Search":
19747
- return await provider.Search(args.query, args.opts);
19748
- case "Publish":
19741
+ switch (tool.toLowerCase()) {
19742
+ case "list":
19743
+ return await provider.list(args.opts);
19744
+ case "get":
19745
+ return typeof args.file === "string" ? await provider.get_file(args.id, args.file) : await provider.get(args.id);
19746
+ case "search":
19747
+ return await provider.search(args.query, args.opts);
19748
+ case "publish":
19749
19749
  if (!Array.isArray(args.files)) {
19750
- throw new TBError("invalid_argument", "Publish \u9700\u8981\u6570\u7EC4 'files'");
19750
+ throw new TBError("invalid_argument", "publish \u9700\u8981\u6570\u7EC4 'files'");
19751
19751
  }
19752
- return await provider.Publish({
19752
+ return await provider.publish({
19753
19753
  ...typeof args.id === "string" ? { id: args.id } : {},
19754
19754
  files: args.files
19755
19755
  });
19756
- case "Remove":
19757
- return await provider.Remove(args.id);
19756
+ case "remove":
19757
+ return await provider.remove(args.id);
19758
19758
  default:
19759
19759
  throw new TBError("invalid_argument", `unknown cmd '${tool}'`);
19760
19760
  }
@@ -19763,31 +19763,31 @@ async function dispatchContextCmd(provider, tool, args) {
19763
19763
  const unimplemented = () => {
19764
19764
  throw new TBError("invalid_argument", `unknown cmd '${tool}'(provider \u672A\u5B9E\u73B0)`);
19765
19765
  };
19766
- switch (tool) {
19767
- case "List":
19768
- if (provider.List === void 0) return unimplemented();
19769
- return await provider.List(args.path ?? "", args.opts);
19770
- case "Get":
19771
- if (provider.Get === void 0) return unimplemented();
19772
- return await provider.Get(args.path);
19773
- case "Write":
19774
- if (provider.Write === void 0) return unimplemented();
19766
+ switch (tool.toLowerCase()) {
19767
+ case "list":
19768
+ if (provider.list === void 0) return unimplemented();
19769
+ return await provider.list(args.path ?? "", args.opts);
19770
+ case "get":
19771
+ if (provider.get === void 0) return unimplemented();
19772
+ return await provider.get(args.path);
19773
+ case "write":
19774
+ if (provider.write === void 0) return unimplemented();
19775
19775
  if (typeof args.entry !== "object" || args.entry === null) {
19776
- throw new TBError("invalid_argument", "Write \u9700\u8981\u5BF9\u8C61 'entry'");
19776
+ throw new TBError("invalid_argument", "write \u9700\u8981\u5BF9\u8C61 'entry'");
19777
19777
  }
19778
- return await provider.Write(args.path, args.entry);
19779
- case "Update":
19780
- if (provider.Update === void 0) return unimplemented();
19778
+ return await provider.write(args.path, args.entry);
19779
+ case "update":
19780
+ if (provider.update === void 0) return unimplemented();
19781
19781
  if (typeof args.patch !== "object" || args.patch === null) {
19782
- throw new TBError("invalid_argument", "Update \u9700\u8981\u5BF9\u8C61 'patch'");
19783
- }
19784
- return await provider.Update(args.path, args.patch);
19785
- case "Delete":
19786
- if (provider.Delete === void 0) return unimplemented();
19787
- return await provider.Delete(args.path);
19788
- case "Search":
19789
- if (provider.Search === void 0) return unimplemented();
19790
- return await provider.Search(args.query, args.opts);
19782
+ throw new TBError("invalid_argument", "update \u9700\u8981\u5BF9\u8C61 'patch'");
19783
+ }
19784
+ return await provider.update(args.path, args.patch);
19785
+ case "delete":
19786
+ if (provider.delete === void 0) return unimplemented();
19787
+ return await provider.delete(args.path);
19788
+ case "search":
19789
+ if (provider.search === void 0) return unimplemented();
19790
+ return await provider.search(args.query, args.opts);
19791
19791
  default:
19792
19792
  throw new TBError("invalid_argument", `unknown cmd '${tool}'`);
19793
19793
  }
@@ -35583,8 +35583,8 @@ var CfWorkerJsonSchemaValidator2 = class {
35583
35583
  function hex(bytes) {
35584
35584
  return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
35585
35585
  }
35586
- function mcpToolIdentity(invokePath, toolName, invokeWithEnvelope) {
35587
- return JSON.stringify([invokePath, toolName, invokeWithEnvelope ? "envelope" : "flat"]);
35586
+ function mcpToolIdentity(invokePath, toolName) {
35587
+ return JSON.stringify([invokePath, toolName]);
35588
35588
  }
35589
35589
  async function mcpToolName(identity) {
35590
35590
  const encoded = [...new TextEncoder().encode(identity)].map((byte) => {
@@ -35794,33 +35794,33 @@ async function handleMcpRequest(request, version, bridge, listTtlMs) {
35794
35794
  }
35795
35795
 
35796
35796
  // ../app/src/providers/pluginContext.ts
35797
- var CORE_METHODS = ["List", "Get", "Write", "Update"];
35797
+ var CORE_METHODS = ["list", "get", "write", "update"];
35798
35798
  function createPluginContextProvider(opts) {
35799
35799
  const call = (method, args) => callPlugin(opts, method, args);
35800
35800
  const declared = opts.methods !== void 0 ? new Set(opts.methods) : /* @__PURE__ */ new Set([...CORE_METHODS, ...optionalMethodsForCapabilities(opts.capabilities)]);
35801
35801
  const provider = {};
35802
- if (declared.has("List")) {
35803
- provider.List = (path, listOpts) => call("List", { path, ...listOpts !== void 0 ? { opts: listOpts } : {} });
35802
+ if (declared.has("list")) {
35803
+ provider.list = (path, listOpts) => call("list", { path, ...listOpts !== void 0 ? { opts: listOpts } : {} });
35804
35804
  }
35805
- if (declared.has("Get")) {
35806
- provider.Get = (path) => call("Get", { path });
35805
+ if (declared.has("get")) {
35806
+ provider.get = (path) => call("get", { path });
35807
35807
  }
35808
- if (declared.has("Update")) {
35809
- provider.Update = (path, patch) => call("Update", { path, patch });
35808
+ if (declared.has("update")) {
35809
+ provider.update = (path, patch) => call("update", { path, patch });
35810
35810
  }
35811
- if (declared.has("Write")) {
35812
- provider.Write = (path, entry) => call("Write", { path, entry });
35811
+ if (declared.has("write")) {
35812
+ provider.write = (path, entry) => call("write", { path, entry });
35813
35813
  }
35814
35814
  const optional2 = optionalMethodsForCapabilities(opts.capabilities);
35815
- if (declared.has("Search") && optional2.has("Search")) {
35816
- provider.Search = (query, searchOpts) => call("Search", {
35815
+ if (declared.has("search") && optional2.has("search")) {
35816
+ provider.search = (query, searchOpts) => call("search", {
35817
35817
  query,
35818
35818
  ...searchOpts !== void 0 ? { opts: searchOpts } : {}
35819
35819
  });
35820
35820
  }
35821
- if (declared.has("Delete") && optional2.has("Delete")) {
35822
- provider.Delete = async (path) => {
35823
- await call("Delete", { path });
35821
+ if (declared.has("delete") && optional2.has("delete")) {
35822
+ provider.delete = async (path) => {
35823
+ await call("delete", { path });
35824
35824
  };
35825
35825
  }
35826
35826
  return provider;
@@ -36579,10 +36579,15 @@ function registerPublicRoutes(app, env) {
36579
36579
  return tbErrorResponse(TBError.notFound("dashboard assets not deployed"));
36580
36580
  }
36581
36581
  const url2 = new URL(c.req.url);
36582
+ const fwd = new Headers();
36583
+ const ae = c.req.header("accept-encoding");
36584
+ if (ae) fwd.set("accept-encoding", ae);
36585
+ const inm = c.req.header("if-none-match");
36586
+ if (inm) fwd.set("if-none-match", inm);
36582
36587
  const sub = url2.pathname.slice("/ui".length) || "/";
36583
- const res = await assets(new Request(new URL(sub, url2.origin)));
36588
+ const res = await assets(new Request(new URL(sub, url2.origin), { headers: fwd }));
36584
36589
  if (res.status !== 404) return res;
36585
- return await assets(new Request(new URL("/", url2.origin)));
36590
+ return await assets(new Request(new URL("/", url2.origin), { headers: fwd }));
36586
36591
  };
36587
36592
  app.get("/ui", (c) => c.redirect("/ui/", 302));
36588
36593
  app.get("/ui/*", serveUi);
@@ -36861,10 +36866,10 @@ async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
36861
36866
  node.config.export
36862
36867
  );
36863
36868
  const declared = exported.methods !== void 0 ? new Set(exported.methods) : /* @__PURE__ */ new Set([
36864
- "List",
36865
- "Get",
36866
- "Write",
36867
- "Update",
36869
+ "list",
36870
+ "get",
36871
+ "write",
36872
+ "update",
36868
36873
  ...optionalMethodsForCapabilities(exported.capabilities ?? [])
36869
36874
  ]);
36870
36875
  return { ...model, cmds: model.cmds.filter((c) => declared.has(c.name)) };
@@ -36877,23 +36882,40 @@ async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
36877
36882
  }
36878
36883
  throw TBError.unimplemented(`~help for kind '${node.kind}' not implemented yet`);
36879
36884
  }
36885
+ async function commandHelpModelFor(registry, ctx, builtins, deps, path, opts) {
36886
+ const resolved = await registry.resolve(path).catch(() => null);
36887
+ if (resolved === null || resolved.rest === "" || resolved.rest.includes("/")) return null;
36888
+ const { node, rest: command } = resolved;
36889
+ if (!(node.kind === "builtin" || node.kind === "context" || node.kind === "skillhub")) {
36890
+ return null;
36891
+ }
36892
+ const full = await helpModelFor(node, registry, ctx, builtins, deps, {
36893
+ refresh: opts.refresh,
36894
+ schemas: true,
36895
+ now: (/* @__PURE__ */ new Date()).toISOString()
36896
+ });
36897
+ const cmd = full.cmds.find((c) => c.name === command);
36898
+ if (cmd === void 0) return null;
36899
+ return {
36900
+ node: { path: `${node.path}/${command}`, kind: node.kind, description: cmd.h ?? full.node.description },
36901
+ cmds: [cmd]
36902
+ };
36903
+ }
36880
36904
 
36881
36905
  // ../app/src/routes/mcp.ts
36882
36906
  var MCP_REMOTE_MAX_REQUESTS = 32;
36883
36907
  var mcpCommand = (nodePath, nodeDescription, command) => {
36884
36908
  const modelPath = nodePath.replace(/^\/+|\/+$/g, "");
36885
36909
  const commandPath = command.path.replace(/^\/+|\/+$/g, "");
36886
- if (commandPath !== modelPath && !commandPath.startsWith(`${modelPath}/`)) {
36910
+ if (!commandPath.startsWith(`${modelPath}/`)) {
36887
36911
  throw new TBError("internal", `command path '${command.path}' escapes node '${nodePath}'`);
36888
36912
  }
36889
36913
  const invokePath = `/${commandPath}`;
36890
- const invokeWithEnvelope = commandPath === modelPath;
36891
36914
  return {
36892
- identity: mcpToolIdentity(invokePath, command.name, invokeWithEnvelope),
36915
+ identity: mcpToolIdentity(invokePath, command.name),
36893
36916
  sourcePath: nodePath,
36894
36917
  toolName: command.name,
36895
36918
  invokePath,
36896
- invokeWithEnvelope,
36897
36919
  description: command.h ?? nodeDescription,
36898
36920
  ...command.inputSchema !== void 0 ? { inputSchema: command.inputSchema } : {},
36899
36921
  ...command.effect !== void 0 ? { effect: command.effect } : {},
@@ -36901,13 +36923,12 @@ var mcpCommand = (nodePath, nodeDescription, command) => {
36901
36923
  };
36902
36924
  };
36903
36925
  var toolSpecCommand = (node, tool, providerBacked = false) => {
36904
- const path = `/${node.path}`;
36926
+ const invokePath = `/${node.path}/${tool.name}`;
36905
36927
  return {
36906
- identity: mcpToolIdentity(path, tool.name, true),
36928
+ identity: mcpToolIdentity(invokePath, tool.name),
36907
36929
  sourcePath: node.path,
36908
36930
  toolName: tool.name,
36909
- invokePath: path,
36910
- invokeWithEnvelope: true,
36931
+ invokePath,
36911
36932
  ...providerBacked ? { providerBacked: true } : {},
36912
36933
  description: tool.description ?? node.description,
36913
36934
  ...tool.inputSchema !== void 0 ? { inputSchema: tool.inputSchema } : {},
@@ -36922,12 +36943,9 @@ var remoteCommand = (localNodePath, model, command) => {
36922
36943
  throw new TBError("unavailable", "remote ~help returned a command outside its node");
36923
36944
  }
36924
36945
  const suffix = remoteCommandPath.slice(remoteNodePath.length);
36925
- const directTool = suffix.startsWith("/");
36926
36946
  return mcpCommand(localNodePath, model.node.description, {
36927
36947
  ...command,
36928
- // Tool-layer nodes retain the envelope entrypoint. It keeps authorization on the
36929
- // node path instead of requiring callers to hold an exact scope for the tool suffix.
36930
- path: directTool ? `/${localNodePath}` : `/${localNodePath}${suffix}`
36948
+ path: `/${localNodePath}${suffix}`
36931
36949
  });
36932
36950
  };
36933
36951
  function mcpBridgeFor(c, env, app) {
@@ -36941,7 +36959,6 @@ function mcpBridgeFor(c, env, app) {
36941
36959
  sourcePath: "",
36942
36960
  toolName: "Search",
36943
36961
  invokePath: "/~search",
36944
- invokeWithEnvelope: false,
36945
36962
  mcpName: "tb_search",
36946
36963
  operation: "search",
36947
36964
  description: "Search visible tools across the Tool Bridge tree.",
@@ -36963,7 +36980,6 @@ function mcpBridgeFor(c, env, app) {
36963
36980
  sourcePath: "",
36964
36981
  toolName: "Help",
36965
36982
  invokePath: "/~help",
36966
- invokeWithEnvelope: false,
36967
36983
  mcpName: "tb_help",
36968
36984
  operation: "help",
36969
36985
  description: "Describe a visible Tool Bridge node or one of its tools.",
@@ -36983,7 +36999,6 @@ function mcpBridgeFor(c, env, app) {
36983
36999
  sourcePath: "",
36984
37000
  toolName: "List",
36985
37001
  invokePath: "/~tree",
36986
- invokeWithEnvelope: false,
36987
37002
  mcpName: "tb_list_nodes",
36988
37003
  operation: "listNodes",
36989
37004
  description: "List the visible Tool Bridge node tree from a path.",
@@ -37227,9 +37242,8 @@ function mcpBridgeFor(c, env, app) {
37227
37242
  "authorization": c.req.header("authorization") ?? "",
37228
37243
  "content-type": "application/json"
37229
37244
  });
37230
- const body = tool.invokeWithEnvelope ? { tool: tool.toolName, arguments: args } : args;
37231
37245
  const response = await app.request(
37232
- new Request(url2, { method: "POST", headers, body: JSON.stringify(body) })
37246
+ new Request(url2, { method: "POST", headers, body: JSON.stringify(args) })
37233
37247
  );
37234
37248
  return await resultFromResponse(response);
37235
37249
  }
@@ -37254,35 +37268,24 @@ async function handleInvoke(c, env) {
37254
37268
  const ctx = c.get("ctx");
37255
37269
  const store = c.get("store");
37256
37270
  const registry = new NodeRegistryStore(store);
37257
- if (!check(ctx, raw, "read").allow) throw TBError.notFound("not found");
37258
- const remote = await remotePassthroughIfMatch(c, ctx, registry, raw, null, deps);
37259
- if (remote) return remote;
37260
- let node;
37261
- let directTool = null;
37262
- try {
37263
- node = await registry.get(raw);
37264
- } catch {
37265
- const resolved = await registry.resolve(raw).catch(() => null);
37266
- if (resolved === null || resolved.node.kind !== "mcp" && resolved.node.kind !== "http" && resolved.node.kind !== "tool" || resolved.node.config === void 0 || resolved.rest === "" || resolved.rest.includes("/")) {
37267
- throw TBError.notFound("not found");
37268
- }
37269
- if (!check(ctx, resolved.node.path, "read").allow) throw TBError.notFound("not found");
37270
- node = resolved.node;
37271
- directTool = resolved.rest;
37271
+ const remoteVisible = check(ctx, raw, "read").allow;
37272
+ if (remoteVisible) {
37273
+ const remote = await remotePassthroughIfMatch(c, ctx, registry, raw, null, deps);
37274
+ if (remote) return remote;
37272
37275
  }
37276
+ const resolved = await registry.resolve(raw).catch(() => null);
37277
+ if (resolved === null || resolved.rest === "" || resolved.rest.includes("/")) {
37278
+ throw TBError.notFound("not found");
37279
+ }
37280
+ const node = resolved.node;
37281
+ const command = resolved.rest;
37282
+ if (!check(ctx, node.path, "read").allow) throw TBError.notFound("not found");
37273
37283
  const readInvokeBody = async () => {
37274
37284
  const parsed = await c.req.json().catch(() => null);
37275
- if (directTool !== null) {
37276
- if (parsed !== null && (typeof parsed !== "object" || Array.isArray(parsed))) {
37277
- throw new TBError("invalid_argument", "body must be a JSON object (tool arguments)");
37278
- }
37279
- return { tool: directTool, args: parsed ?? {} };
37285
+ if (parsed !== null && (typeof parsed !== "object" || Array.isArray(parsed))) {
37286
+ throw new TBError("invalid_argument", "body must be a JSON object (command arguments)");
37280
37287
  }
37281
- const body2 = parsed;
37282
- if (!body2 || typeof body2.tool !== "string") {
37283
- throw new TBError("invalid_argument", "body must be {tool, arguments}");
37284
- }
37285
- return { tool: body2.tool, args: body2.arguments ?? {} };
37288
+ return { tool: command, args: parsed ?? {} };
37286
37289
  };
37287
37290
  const toolMarker = deviceToolMarker(node);
37288
37291
  if (toolMarker !== null) {
@@ -37291,8 +37294,8 @@ async function handleInvoke(c, env) {
37291
37294
  }
37292
37295
  const { tool, args: args2 } = await readInvokeBody();
37293
37296
  const result2 = await invokeDevice(deps, toolMarker.deviceId, {
37294
- path: relativeDevicePath(node.path, toolMarker.mountPath),
37295
- tool,
37297
+ // path 含命令叶子段:<mount 相对路径>/<命令>。
37298
+ path: `${relativeDevicePath(node.path, toolMarker.mountPath)}/${tool}`,
37296
37299
  arguments: args2,
37297
37300
  context: deviceCallContextFrom(ctx)
37298
37301
  });
@@ -37313,17 +37316,13 @@ async function handleInvoke(c, env) {
37313
37316
  if (!check(ctx, node.path, "call").allow) {
37314
37317
  throw new TBError("permission_denied", `no scope grants 'call' on '${node.path}'`);
37315
37318
  }
37316
- const body2 = await c.req.json().catch(() => null);
37317
- if (!body2 || typeof body2.tool !== "string") {
37318
- throw new TBError("invalid_argument", "body must be {tool, arguments}");
37319
- }
37320
- if (body2.tool !== "exec") {
37321
- throw new TBError("invalid_argument", `unknown cmd '${body2.tool}' on '${node.path}'`);
37319
+ const { tool, args: args2 } = await readInvokeBody();
37320
+ if (tool !== "exec") {
37321
+ throw new TBError("invalid_argument", `unknown cmd '${tool}' on '${node.path}'`);
37322
37322
  }
37323
37323
  const result2 = await invokeDevice(deps, node.config.deviceId, {
37324
- path: "shell",
37325
- tool: body2.tool,
37326
- arguments: body2.arguments ?? {},
37324
+ path: "shell/exec",
37325
+ arguments: args2,
37327
37326
  context: deviceCallContextFrom(ctx)
37328
37327
  });
37329
37328
  return renderResult(result2, negotiate(c.req.header("accept")));
@@ -37331,25 +37330,20 @@ async function handleInvoke(c, env) {
37331
37330
  if (node.kind === "context" && node.config?.kind === "context") {
37332
37331
  const cfg = node.config;
37333
37332
  await assertContextAlive(node, cfg, registry);
37334
- const body2 = await c.req.json().catch(() => null);
37335
- if (!body2 || typeof body2.tool !== "string") {
37336
- throw new TBError("invalid_argument", "body must be {tool, arguments}");
37337
- }
37338
- const scope = contextScopeForCmd(body2.tool);
37333
+ const { tool, args: args2 } = await readInvokeBody();
37334
+ const scope = contextScopeForCmd(tool);
37339
37335
  if (scope === null) {
37340
- throw new TBError("invalid_argument", `unknown cmd '${body2.tool}' on '${node.path}'`);
37336
+ throw new TBError("invalid_argument", `unknown cmd '${tool}' on '${node.path}'`);
37341
37337
  }
37342
37338
  if (!check(ctx, node.path, scope).allow) {
37343
37339
  throw new TBError("permission_denied", `no scope grants '${scope}' on '${node.path}'`);
37344
37340
  }
37345
37341
  if (cfg.readOnly === true && scope === "write") {
37346
- throw new TBError("permission_denied", `readOnly \u6302\u8F7D\u62D2\u7EDD '${body2.tool}'`);
37342
+ throw new TBError("permission_denied", `readOnly \u6302\u8F7D\u62D2\u7EDD '${tool}'`);
37347
37343
  }
37348
- const args2 = body2.arguments ?? {};
37349
37344
  if (cfg.provider === "device-fs") {
37350
37345
  const result3 = await invokeDevice(deps, deviceIdForDeviceFs(cfg), {
37351
- path: "fs",
37352
- tool: body2.tool,
37346
+ path: `fs/${tool}`,
37353
37347
  arguments: args2,
37354
37348
  context: deviceCallContextFrom(ctx)
37355
37349
  });
@@ -37358,8 +37352,7 @@ async function handleInvoke(c, env) {
37358
37352
  const contextMarker = deviceMarkerOf(cfg.providerConfig);
37359
37353
  if (cfg.provider !== "r2" && cfg.provider !== "s3" && contextMarker !== null) {
37360
37354
  const result3 = await invokeDevice(deps, contextMarker.deviceId, {
37361
- path: relativeDevicePath(node.path, contextMarker.mountPath),
37362
- tool: body2.tool,
37355
+ path: `${relativeDevicePath(node.path, contextMarker.mountPath)}/${tool}`,
37363
37356
  arguments: args2,
37364
37357
  context: deviceCallContextFrom(ctx)
37365
37358
  });
@@ -37368,7 +37361,7 @@ async function handleInvoke(c, env) {
37368
37361
  if (cfg.provider !== "r2" && cfg.provider !== "s3") {
37369
37362
  const local = localContext(deps, node);
37370
37363
  if (local !== null) {
37371
- const result4 = await dispatchContextCmd(local, body2.tool, args2);
37364
+ const result4 = await dispatchContextCmd(local, tool, args2);
37372
37365
  return renderResult(result4, negotiate(c.req.header("accept")));
37373
37366
  }
37374
37367
  const { manifest, export: exported } = await requirePluginExport(
@@ -37388,33 +37381,29 @@ async function handleInvoke(c, env) {
37388
37381
  ...cfg.authRef !== void 0 ? { upstreamAuthRef: cfg.authRef } : {},
37389
37382
  ...deps.pluginBindings !== void 0 ? { bindings: deps.pluginBindings } : {}
37390
37383
  });
37391
- const result3 = await dispatchContextCmd(provider2, body2.tool, args2);
37384
+ const result3 = await dispatchContextCmd(provider2, tool, args2);
37392
37385
  return renderResult(result3, negotiate(c.req.header("accept")));
37393
37386
  }
37394
37387
  const provider = await contextProviderFor(node, cfg, deps, c.req.url);
37395
- const result2 = await dispatchContextCmd(provider, body2.tool, args2);
37388
+ const result2 = await dispatchContextCmd(provider, tool, args2);
37396
37389
  return renderResult(result2, negotiate(c.req.header("accept")));
37397
37390
  }
37398
37391
  if (node.kind === "skillhub" && node.config?.kind === "skillhub") {
37399
37392
  const cfg = node.config;
37400
37393
  await assertContextAlive(node, cfg, registry);
37401
- const body2 = await c.req.json().catch(() => null);
37402
- if (!body2 || typeof body2.tool !== "string") {
37403
- throw new TBError("invalid_argument", "body must be {tool, arguments}");
37404
- }
37405
- const scope = skillhubScopeForCmd(body2.tool);
37394
+ const { tool, args: args2 } = await readInvokeBody();
37395
+ const scope = skillhubScopeForCmd(tool);
37406
37396
  if (scope === null) {
37407
- throw new TBError("invalid_argument", `unknown cmd '${body2.tool}' on '${node.path}'`);
37397
+ throw new TBError("invalid_argument", `unknown cmd '${tool}' on '${node.path}'`);
37408
37398
  }
37409
37399
  if (!check(ctx, node.path, scope).allow) {
37410
37400
  throw new TBError("permission_denied", `no scope grants '${scope}' on '${node.path}'`);
37411
37401
  }
37412
37402
  if (cfg.readOnly === true && scope === "write") {
37413
- throw new TBError("permission_denied", `readOnly \u6302\u8F7D\u62D2\u7EDD '${body2.tool}'`);
37403
+ throw new TBError("permission_denied", `readOnly \u6302\u8F7D\u62D2\u7EDD '${tool}'`);
37414
37404
  }
37415
- const args2 = body2.arguments ?? {};
37416
37405
  const provider = await skillhubProviderFor(node, cfg, deps, c.req.url);
37417
- const result2 = await dispatchSkillhubCmd(provider, body2.tool, args2);
37406
+ const result2 = await dispatchSkillhubCmd(provider, tool, args2);
37418
37407
  return renderResult(result2, negotiate(c.req.header("accept")));
37419
37408
  }
37420
37409
  if (node.kind !== "builtin" || node.config?.kind !== "builtin") {
@@ -37423,12 +37412,7 @@ async function handleInvoke(c, env) {
37423
37412
  const builtins = builtinsOf(store);
37424
37413
  const mod = builtins.get(node.config.module);
37425
37414
  if (!mod) throw TBError.unimplemented(`builtin module '${node.config.module}' not available`);
37426
- const body = await c.req.json().catch(() => null);
37427
- if (!body || typeof body.tool !== "string") {
37428
- throw new TBError("invalid_argument", "body must be {tool, arguments}");
37429
- }
37430
- const cmd = body.tool;
37431
- const args = body.arguments ?? {};
37415
+ const { tool: cmd, args } = await readInvokeBody();
37432
37416
  const spec = scopeForCmd(mod, node.path, cmd);
37433
37417
  if (!spec) throw new TBError("invalid_argument", `unknown cmd '${cmd}' on '${node.path}'`);
37434
37418
  if (!check(ctx, node.path, spec.scope).allow) {
@@ -37577,17 +37561,22 @@ async function handleHelp(c, env) {
37577
37561
  if (!check(ctx, path, "read").allow) throw TBError.notFound("not found");
37578
37562
  const remote = await remotePassthroughIfMatch(c, ctx, registry, path, "~help", deps);
37579
37563
  if (remote) return remote;
37564
+ const builtins = builtinsOf(store);
37565
+ const refresh = c.req.query("refresh") === "1";
37566
+ const schemas = c.req.query("schemas") === "1";
37580
37567
  let node;
37581
37568
  try {
37582
37569
  node = await registry.get(path);
37583
37570
  } catch {
37584
37571
  const toolModel = await toolHelpModelFor(c, ctx, registry, path, deps);
37585
37572
  if (toolModel !== null) return renderHelp(await enrichHelp(toolModel, path, store), rep);
37573
+ const cmdModel = await commandHelpModelFor(registry, ctx, builtins, deps, path, {
37574
+ refresh,
37575
+ schemas
37576
+ });
37577
+ if (cmdModel !== null) return renderHelp(await enrichHelp(cmdModel, path, store), rep);
37586
37578
  throw TBError.notFound("not found");
37587
37579
  }
37588
- const builtins = builtinsOf(store);
37589
- const refresh = c.req.query("refresh") === "1";
37590
- const schemas = c.req.query("schemas") === "1";
37591
37580
  const model = await helpModelFor(node, registry, ctx, builtins, deps, {
37592
37581
  refresh,
37593
37582
  schemas,
@@ -38826,7 +38815,7 @@ import { join as join4 } from "path";
38826
38815
  // package.json
38827
38816
  var package_default = {
38828
38817
  name: "@tool-bridge/server",
38829
- version: "0.10.1",
38818
+ version: "0.13.0",
38830
38819
  description: "tool-bridge self-hosted server: run the HTBP gateway on Node with SQLite or PostgreSQL persistence, filesystem object storage and WebSocket device channel \u2014 single container via docker run",
38831
38820
  type: "module",
38832
38821
  license: "MIT",
@@ -38898,10 +38887,33 @@ var package_default = {
38898
38887
  };
38899
38888
 
38900
38889
  // src/assets.ts
38890
+ import { brotliCompressSync, gzipSync, constants as zlibConstants } from "zlib";
38901
38891
  import { dirname as dirname2, join as join3, resolve as resolve2, sep as sep2 } from "path";
38902
38892
  import { readFile as readFile2 } from "fs/promises";
38903
38893
  import { createRequire } from "module";
38904
38894
  import { existsSync } from "fs";
38895
+ var COMPRESSIBLE = /^(?:text\/|application\/(?:javascript|json|manifest\+json|wasm)|image\/svg\+xml)/;
38896
+ var MIN_COMPRESS_BYTES = 1024;
38897
+ function cacheControlFor(pathname) {
38898
+ return pathname.startsWith("/assets/") ? "public, max-age=31536000, immutable" : "no-cache";
38899
+ }
38900
+ function acceptsEncoding(accept, enc) {
38901
+ if (!accept) return false;
38902
+ for (const part of accept.split(",")) {
38903
+ const [tokenRaw = "", ...params] = part.trim().split(";");
38904
+ const token = tokenRaw.trim().toLowerCase();
38905
+ if (token !== enc && token !== "*") continue;
38906
+ const q = params.map((p) => p.trim()).find((p) => p.startsWith("q="));
38907
+ if (q && Number(q.slice(2)) === 0) return false;
38908
+ return true;
38909
+ }
38910
+ return false;
38911
+ }
38912
+ function pickEncoding(accept) {
38913
+ if (acceptsEncoding(accept, "br")) return "br";
38914
+ if (acceptsEncoding(accept, "gzip")) return "gzip";
38915
+ return void 0;
38916
+ }
38905
38917
  function resolveUiDir(uiDirOverride) {
38906
38918
  if (uiDirOverride !== void 0) {
38907
38919
  return existsSync(join3(uiDirOverride, "index.html")) ? resolve2(uiDirOverride) : void 0;
@@ -38915,8 +38927,22 @@ function resolveUiDir(uiDirOverride) {
38915
38927
  return void 0;
38916
38928
  }
38917
38929
  }
38930
+ function toBytes(buf) {
38931
+ const out = new Uint8Array(new ArrayBuffer(buf.byteLength));
38932
+ out.set(buf);
38933
+ return out;
38934
+ }
38935
+ function weakEtag(data) {
38936
+ let hash = 2166136261;
38937
+ for (let i = 0; i < data.length; i++) {
38938
+ hash ^= data[i];
38939
+ hash = Math.imul(hash, 16777619);
38940
+ }
38941
+ return `W/"${(hash >>> 0).toString(16)}-${data.length.toString(16)}"`;
38942
+ }
38918
38943
  function uiAssetsFetcher(uiDir) {
38919
38944
  const root = resolve2(uiDir);
38945
+ const cache = /* @__PURE__ */ new Map();
38920
38946
  return async (request) => {
38921
38947
  const url2 = new URL(request.url);
38922
38948
  let pathname = decodeURIComponent(url2.pathname);
@@ -38925,14 +38951,44 @@ function uiAssetsFetcher(uiDir) {
38925
38951
  if (full !== root && !full.startsWith(root + sep2)) {
38926
38952
  return new Response("not found", { status: 404 });
38927
38953
  }
38928
- try {
38929
- const data = await readFile2(full);
38930
- return new Response(new Uint8Array(data), {
38931
- headers: { "content-type": fsContentTypeOf(full) }
38932
- });
38933
- } catch {
38934
- return new Response("not found", { status: 404 });
38954
+ let asset = cache.get(full);
38955
+ if (asset === void 0) {
38956
+ let data;
38957
+ try {
38958
+ data = await readFile2(full);
38959
+ } catch {
38960
+ return new Response("not found", { status: 404 });
38961
+ }
38962
+ const body = toBytes(data);
38963
+ asset = { body, contentType: fsContentTypeOf(full), etag: weakEtag(body) };
38964
+ cache.set(full, asset);
38965
+ }
38966
+ const headers = new Headers({
38967
+ "content-type": asset.contentType,
38968
+ "cache-control": cacheControlFor(pathname),
38969
+ "etag": asset.etag
38970
+ });
38971
+ if (request.headers.get("if-none-match") === asset.etag) {
38972
+ return new Response(null, { status: 304, headers });
38973
+ }
38974
+ const canCompress = COMPRESSIBLE.test(asset.contentType) && asset.body.length >= MIN_COMPRESS_BYTES;
38975
+ const encoding = canCompress ? pickEncoding(request.headers.get("accept-encoding")) : void 0;
38976
+ if (canCompress) headers.set("vary", "Accept-Encoding");
38977
+ if (encoding === "br") {
38978
+ asset.br ??= toBytes(
38979
+ brotliCompressSync(asset.body, {
38980
+ params: { [zlibConstants.BROTLI_PARAM_QUALITY]: 11 }
38981
+ })
38982
+ );
38983
+ headers.set("content-encoding", "br");
38984
+ return new Response(asset.br, { headers });
38985
+ }
38986
+ if (encoding === "gzip") {
38987
+ asset.gzip ??= toBytes(gzipSync(asset.body, { level: 9 }));
38988
+ headers.set("content-encoding", "gzip");
38989
+ return new Response(asset.gzip, { headers });
38935
38990
  }
38991
+ return new Response(asset.body, { headers });
38936
38992
  };
38937
38993
  }
38938
38994
  function resolveUiAssets(uiDirOverride) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TBError
3
- } from "./chunk-AWXZMW6M.js";
3
+ } from "./chunk-4U5OQW7F.js";
4
4
 
5
5
  // ../plugins/src/_runtime/ipPolicy.ts
6
6
  function parseIpv4(value) {