@tool-bridge/server 0.5.0 → 0.7.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-7TFNLFIF.js → airtable-BNVPDLF2.js} +4 -4
  2. package/dist/{alt_text_generator_ai-VJSAHBJM.js → alt_text_generator_ai-RMQPHK2Y.js} +4 -4
  3. package/dist/{amap-KZMUDGK6.js → amap-PRNZPQ34.js} +4 -4
  4. package/dist/{anthropic-C6FCUSY7.js → anthropic-A76VIXR7.js} +4 -4
  5. package/dist/{apify-MUCWNIWU.js → apify-2Q2CTLKE.js} +4 -4
  6. package/dist/{brave_search-NRVZ4ZNY.js → brave_search-5YJJVPXH.js} +4 -4
  7. package/dist/{chunk-7PM4FD5K.js → chunk-76YX7XSX.js} +63 -7
  8. package/dist/{chunk-3C3J36GT.js → chunk-7ASYWVYP.js} +61 -20
  9. package/dist/{chunk-FHYFPPBZ.js → chunk-BUHY4IE6.js} +2 -2
  10. package/dist/{chunk-7GP7DRES.js → chunk-EBO6Q4NR.js} +1 -1
  11. package/dist/{chunk-B4ZA7EGO.js → chunk-GMHELPK3.js} +1 -1
  12. package/dist/{circleci-QY36SZIM.js → circleci-TDXP3CPQ.js} +4 -4
  13. package/dist/{clerk-ECH23XL5.js → clerk-JRSGMXMS.js} +4 -4
  14. package/dist/{cloudflare_dns-F6DN2F3X.js → cloudflare_dns-G4CHNLO7.js} +4 -4
  15. package/dist/{cohere-HD4XZOPJ.js → cohere-3KN27F2B.js} +4 -4
  16. package/dist/{confluence-J4AZ2KYL.js → confluence-QV6J2PBV.js} +4 -4
  17. package/dist/{convertapi-BXBII5Z6.js → convertapi-HETITAHL.js} +4 -4
  18. package/dist/{currencyapi-HEEQ7EQJ.js → currencyapi-647DEY6G.js} +4 -4
  19. package/dist/{deepseek-RKRGIFPM.js → deepseek-G63RUHM6.js} +4 -4
  20. package/dist/{docker_hub-YFSTEZVP.js → docker_hub-RH72CRWO.js} +4 -4
  21. package/dist/{dropbox-VGK634PO.js → dropbox-T4Y5KSZW.js} +4 -4
  22. package/dist/{dub-GEXD3XK6.js → dub-ECKQT3DC.js} +4 -4
  23. package/dist/{e2b-LPTZQEDV.js → e2b-N5SRTPLF.js} +4 -4
  24. package/dist/{exa-VJENLTKN.js → exa-525ZDM7G.js} +4 -4
  25. package/dist/{fal_ai-75O63LLP.js → fal_ai-BFMVHAUW.js} +4 -4
  26. package/dist/{feishu-FATBHGEJ.js → feishu-NIDOD7EW.js} +3 -3
  27. package/dist/{feishu_custom_bot-QFSYPOLI.js → feishu_custom_bot-V5RGAIUH.js} +4 -4
  28. package/dist/{figma-JED3Q56H.js → figma-GH7TXJMP.js} +4 -4
  29. package/dist/{firehydrant-7JDKFJTB.js → firehydrant-5T3UHAQM.js} +4 -4
  30. package/dist/{fixer-ZI2JS5GU.js → fixer-3RMJLMFO.js} +4 -4
  31. package/dist/{fly-3RA7ETFP.js → fly-NPHJC5MH.js} +4 -4
  32. package/dist/{front-X2CJXBYS.js → front-PYGXJAQK.js} +4 -4
  33. package/dist/{geocodio-C6NHG5UJ.js → geocodio-T6G3FVIF.js} +4 -4
  34. package/dist/{ghost-ZBFOMWQF.js → ghost-L3XIF4SJ.js} +4 -4
  35. package/dist/{github-6QM2NIP4.js → github-7YDUB6N6.js} +4 -4
  36. package/dist/{gmail-ST3MS32S.js → gmail-RY2ZDG3B.js} +4 -4
  37. package/dist/{googlecalendar-SAUTUJ3Q.js → googlecalendar-EHOFMXHE.js} +4 -4
  38. package/dist/{googledocs-2SJKS2SC.js → googledocs-BA3OAMKA.js} +4 -4
  39. package/dist/{grafana-RP7DOS3A.js → grafana-PYZQ4CKI.js} +4 -4
  40. package/dist/{graphhopper-XSDTLJTE.js → graphhopper-3P4YU45N.js} +4 -4
  41. package/dist/index.d.ts +30 -0
  42. package/dist/index.js +2 -2
  43. package/dist/{ip2proxy-IKV5IWUI.js → ip2proxy-GQO6VF4P.js} +4 -4
  44. package/dist/{ipgeolocation_io-NSUWUF5X.js → ipgeolocation_io-VOZU6E7H.js} +4 -4
  45. package/dist/{ipqualityscore-ZQKL3WLC.js → ipqualityscore-XDJ3TTMM.js} +4 -4
  46. package/dist/{jina_ai-F4Y7V5AS.js → jina_ai-ELXPSTUJ.js} +4 -4
  47. package/dist/{jira-CYDY44ZO.js → jira-INDXWO4I.js} +4 -4
  48. package/dist/{langsmith-74JSSJNY.js → langsmith-PMCQBCIK.js} +4 -4
  49. package/dist/{lemlist-C3LKIPVN.js → lemlist-VWZXIHJX.js} +4 -4
  50. package/dist/{linear-YYGRHKJC.js → linear-YXG4KZR4.js} +4 -4
  51. package/dist/{logsnag-YBMDJ6DO.js → logsnag-XENBYHHK.js} +4 -4
  52. package/dist/main.js +101 -101
  53. package/dist/{mattermost-NDID4TAL.js → mattermost-BHVJP5MA.js} +4 -4
  54. package/dist/{mem0-ASBAEBWR.js → mem0-7AP5UBJV.js} +4 -4
  55. package/dist/{memos-76I27HCW.js → memos-MNVRYSLG.js} +4 -4
  56. package/dist/{metabase-LCPIP2DL.js → metabase-NSXM7EID.js} +4 -4
  57. package/dist/{mistral_ai-YVBQ6QKO.js → mistral_ai-HXN625YX.js} +4 -4
  58. package/dist/{mother_duck-J2MPBIFO.js → mother_duck-46VQ3V3D.js} +4 -4
  59. package/dist/{ngrok-UJC2ORDH.js → ngrok-BWCVMS3T.js} +4 -4
  60. package/dist/{notes-6VWWD6RW.js → notes-AVHKCFLU.js} +2 -2
  61. package/dist/{notion-6LBO2KHR.js → notion-BSEN3KSU.js} +4 -4
  62. package/dist/{open_exchange_rates-OGDH4ZBX.js → open_exchange_rates-DWO4T5TF.js} +4 -4
  63. package/dist/{openai-IKGD5M66.js → openai-HPZYRS3M.js} +4 -4
  64. package/dist/{opengraph_io-CIILQ7VK.js → opengraph_io-OLUAYD5P.js} +4 -4
  65. package/dist/{openrouter-IYG5CPG5.js → openrouter-4DQYZIG3.js} +4 -4
  66. package/dist/{outline-R2UMBY4M.js → outline-ZDNMKXZ6.js} +4 -4
  67. package/dist/{paddle-IYWA7DOV.js → paddle-HCOOYW3F.js} +4 -4
  68. package/dist/{perplexity-3TGYQWHT.js → perplexity-2GJJPDA7.js} +4 -4
  69. package/dist/{pinecone-TEBOW4LJ.js → pinecone-ZPOBKL5T.js} +4 -4
  70. package/dist/{pipedrive-ZXDY753U.js → pipedrive-3WN2RFMB.js} +4 -4
  71. package/dist/{polar-BVZV5A4O.js → polar-DJFGBTXW.js} +4 -4
  72. package/dist/{posthog-DXKAS4PJ.js → posthog-G4OXNEXP.js} +4 -4
  73. package/dist/{postmark-6RWFC3TD.js → postmark-NJMGDQKO.js} +4 -4
  74. package/dist/{prerender-YIXOTM3K.js → prerender-2TUPKRK5.js} +4 -4
  75. package/dist/{pubmed-2RHSZB4E.js → pubmed-CCXZZT34.js} +4 -4
  76. package/dist/{railway-IF64BUE2.js → railway-ZUUY5YYR.js} +4 -4
  77. package/dist/{readwise-5XKQZNOM.js → readwise-PYSRGJ4J.js} +4 -4
  78. package/dist/{render-Q2Z66LTA.js → render-SFA3EMGM.js} +4 -4
  79. package/dist/{replicate-SOI65IJO.js → replicate-KGZHYBPK.js} +4 -4
  80. package/dist/{resend-O2BGONOO.js → resend-HENMZC5U.js} +4 -4
  81. package/dist/{rootly-WPQKTVU3.js → rootly-HV2PXIDP.js} +4 -4
  82. package/dist/{scrapfly-GLMBVNPG.js → scrapfly-FOZFHUN3.js} +4 -4
  83. package/dist/{scrapingbee-TUER54CY.js → scrapingbee-VHUMSO2J.js} +4 -4
  84. package/dist/{screenshot_fyi-4J4W5EKY.js → screenshot_fyi-FFDXAKHD.js} +4 -4
  85. package/dist/{semantic_scholar-4PITOANV.js → semantic_scholar-GHO37BZF.js} +4 -4
  86. package/dist/{sentry-4WURPLIE.js → sentry-MZVZW3YE.js} +4 -4
  87. package/dist/{shodan-G3M3LFEW.js → shodan-IDICOPGU.js} +4 -4
  88. package/dist/{shopify-72AIELMS.js → shopify-WQLO23JO.js} +4 -4
  89. package/dist/{stripe-7C7XVPMU.js → stripe-XOAKLAKU.js} +4 -4
  90. package/dist/{supabase-N4Y3YC23.js → supabase-6DKGSLST.js} +4 -4
  91. package/dist/{tavily-GGLSWERP.js → tavily-76QZGEHM.js} +4 -4
  92. package/dist/{telegram-4RH36WYP.js → telegram-O536CLFR.js} +4 -4
  93. package/dist/{telnyx-I2KUITFV.js → telnyx-XOPYXF3K.js} +4 -4
  94. package/dist/{todoist-A3NX6X2Y.js → todoist-YXHVWPP3.js} +4 -4
  95. package/dist/{trello-2GJYN7GR.js → trello-WMTM3WA2.js} +4 -4
  96. package/dist/{turso-WKUXMTZ5.js → turso-CG7PR5HM.js} +4 -4
  97. package/dist/{twilio-SSXDBOK4.js → twilio-ZW4SD36D.js} +4 -4
  98. package/dist/{umami-SBDB4GXK.js → umami-IJQ5VH77.js} +4 -4
  99. package/dist/{unsplash-4AVC4ZGP.js → unsplash-JBQY7NKO.js} +4 -4
  100. package/dist/{upstash_redis-7XY3UHBO.js → upstash_redis-2BAO776T.js} +4 -4
  101. package/dist/{uptimerobot-QVQP3QYG.js → uptimerobot-BRIHMPB3.js} +4 -4
  102. package/dist/{v2ex-ASVTIKO7.js → v2ex-HWIHF4HX.js} +4 -4
  103. package/dist/{vercel-ZQXZCGWY.js → vercel-MGMRY2DJ.js} +4 -4
  104. package/dist/{wolfram_alpha_api-RVBWQSEF.js → wolfram_alpha_api-JG6JD33L.js} +4 -4
  105. package/dist/{wordpress-SOWKVNCX.js → wordpress-ZSYJERWV.js} +4 -4
  106. package/dist/{workos-F45INANB.js → workos-QFEOSJAN.js} +4 -4
  107. package/dist/{zhihu-5VODAGAP.js → zhihu-5RF7BBFV.js} +4 -4
  108. package/package.json +3 -3
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/airtable/api.ts
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/alt_text_generator_ai/schema.ts
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/amap/api.ts
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/anthropic/api.ts
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/apify/api.ts
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/brave_search/api.ts
@@ -17255,6 +17255,7 @@ var deviceNodeCmdSchema = external_exports.object({
17255
17255
  name: external_exports.string().min(1),
17256
17256
  description: external_exports.string().optional(),
17257
17257
  inputSchema: external_exports.unknown().optional(),
17258
+ outputSchema: external_exports.unknown().optional(),
17258
17259
  effect: external_exports.string().optional(),
17259
17260
  confirm: external_exports.boolean().optional()
17260
17261
  }).passthrough();
@@ -17276,6 +17277,16 @@ var deviceExposeSchema = external_exports.object({
17276
17277
  nodes: external_exports.array(nodeInputSchema).optional()
17277
17278
  });
17278
17279
  var idSchema = external_exports.string().min(1);
17280
+ var deviceCallContextSchema = external_exports.object({
17281
+ caller: external_exports.object({
17282
+ keyId: external_exports.string().min(1),
17283
+ owner: external_exports.string().min(1),
17284
+ displayName: external_exports.string().optional()
17285
+ }).passthrough(),
17286
+ traceId: external_exports.string().min(1),
17287
+ createdAt: external_exports.string().min(1),
17288
+ expiresAt: external_exports.string().min(1)
17289
+ }).passthrough();
17279
17290
  var schemaByType = {
17280
17291
  hello: external_exports.object({
17281
17292
  type: external_exports.literal("hello"),
@@ -17290,7 +17301,8 @@ var schemaByType = {
17290
17301
  id: idSchema,
17291
17302
  path: external_exports.string(),
17292
17303
  tool: external_exports.string().min(1),
17293
- arguments: external_exports.record(external_exports.string(), external_exports.unknown())
17304
+ arguments: external_exports.record(external_exports.string(), external_exports.unknown()),
17305
+ context: deviceCallContextSchema.optional()
17294
17306
  }),
17295
17307
  result: external_exports.discriminatedUnion("ok", [
17296
17308
  external_exports.object({ type: external_exports.literal("result"), id: idSchema, ok: external_exports.literal(true), value: external_exports.unknown() }),
@@ -17385,13 +17397,33 @@ function deviceDirectoryHelpModel(node, children = []) {
17385
17397
  node: {
17386
17398
  path: node.path,
17387
17399
  kind: "directory",
17388
- description: `${node.description} (${node.online ? "online" : "offline"})`
17400
+ description: `${node.description} (${node.presence.state})`
17389
17401
  },
17390
17402
  cmds: [],
17391
17403
  children
17392
17404
  };
17393
17405
  }
17394
17406
 
17407
+ // ../core/src/device/presence.ts
17408
+ var PRESENCE_STALE_AFTER_MS = 9e4;
17409
+ function derivePresence(input) {
17410
+ const lastSeenAt = input.lastSeenAt;
17411
+ const base = lastSeenAt !== void 0 ? { lastSeenAt } : {};
17412
+ if (input.online !== true) {
17413
+ return { state: "offline", ...base };
17414
+ }
17415
+ if (lastSeenAt === void 0) {
17416
+ return { state: "stale", ...base };
17417
+ }
17418
+ const seenMs = Date.parse(lastSeenAt);
17419
+ const nowMs = Date.parse(input.now);
17420
+ if (!Number.isFinite(seenMs) || !Number.isFinite(nowMs)) {
17421
+ return { state: "stale", ...base };
17422
+ }
17423
+ const ttl = input.staleAfterMs ?? PRESENCE_STALE_AFTER_MS;
17424
+ return { state: nowMs - seenMs <= ttl ? "online" : "stale", ...base };
17425
+ }
17426
+
17395
17427
  // ../core/src/device/session.ts
17396
17428
  var DEVICE_CALL_TIMEOUT_MS = 6e4;
17397
17429
  var DEVICE_REJECT_CLOSE_CODE = 1008;
@@ -17499,7 +17531,9 @@ var DeviceGatewaySession = class {
17499
17531
  id: req.id,
17500
17532
  path: req.path,
17501
17533
  tool: req.tool,
17502
- arguments: req.arguments
17534
+ arguments: req.arguments,
17535
+ // undefined 经 JSON.stringify 丢弃:老网关不带 context 时帧形状不变。
17536
+ ...req.context !== void 0 ? { context: req.context } : {}
17503
17537
  });
17504
17538
  }
17505
17539
  /** 幂等表回放种子(DO 从 ctx.storage 恢复时用);已有同 id 结果则忽略。 */
@@ -17999,7 +18033,7 @@ async function buildTree(opts) {
17999
18033
  visited.add(entry.path);
18000
18034
  count++;
18001
18035
  const node = { path: entry.path, kind: entry.kind, description: entry.description };
18002
- if (entry.online !== void 0) node.online = entry.online;
18036
+ if (entry.presence !== void 0) node.presence = entry.presence;
18003
18037
  if (depthLeft <= 0) {
18004
18038
  if (opts.opaqueKinds?.has(entry.kind)) {
18005
18039
  node.truncated = true;
@@ -18023,7 +18057,7 @@ async function buildTree(opts) {
18023
18057
  description: kid.description,
18024
18058
  truncated: true
18025
18059
  };
18026
- if (kid.online !== void 0) cyc.online = kid.online;
18060
+ if (kid.presence !== void 0) cyc.presence = kid.presence;
18027
18061
  count++;
18028
18062
  children.push(cyc);
18029
18063
  continue;
@@ -19913,6 +19947,7 @@ var NodeRegistryStore = class {
19913
19947
  ...node.config !== void 0 ? { config: node.config } : {},
19914
19948
  ...node.virtualize !== void 0 ? { virtualize: node.virtualize } : {},
19915
19949
  ...opts.online !== void 0 ? { online: opts.online } : {},
19950
+ ...opts.lastSeenAt !== void 0 ? { lastSeenAt: opts.lastSeenAt } : {},
19916
19951
  registeredBy,
19917
19952
  createdAt: existing?.createdAt ?? now,
19918
19953
  updatedAt: now
@@ -19941,15 +19976,34 @@ var NodeRegistryStore = class {
19941
19976
  await this.store.put(this.keyOf(norm), merged);
19942
19977
  return merged;
19943
19978
  }
19944
- /** 设备生命周期专用:只更新节点 online 状态,不存在 → not_found。 */
19979
+ /**
19980
+ * 设备生命周期专用:更新节点 online 状态,不存在 → not_found。
19981
+ * online 翻 true 时视为一次存活观察,同步把 `lastSeenAt` 刷到 now;翻 false 时保留原
19982
+ * `lastSeenAt`(用于展示"最后在线于")。
19983
+ */
19945
19984
  async setOnline(path, online, now) {
19946
19985
  const norm = normalizePath(path);
19947
19986
  const existing = await this.read(norm);
19948
19987
  if (!existing) throw new TBError("not_found", `\u8282\u70B9\u4E0D\u5B58\u5728:'${norm}'`);
19949
- const updated = { ...existing, online, updatedAt: now };
19988
+ const updated = {
19989
+ ...existing,
19990
+ online,
19991
+ ...online ? { lastSeenAt: now } : {},
19992
+ updatedAt: now
19993
+ };
19950
19994
  await this.store.put(this.keyOf(norm), updated);
19951
19995
  return updated;
19952
19996
  }
19997
+ /**
19998
+ * 设备心跳专用:只把 `lastSeenAt` 刷到 now,不改 online 也不动 updatedAt(心跳不是元数据变更,
19999
+ * 不该扰动 updatedAt 的语义)。节点不存在时静默返回——心跳晚于节点删除是正常竞态,不报错。
20000
+ */
20001
+ async touchSeen(path, now) {
20002
+ const norm = normalizePath(path);
20003
+ const existing = await this.read(norm);
20004
+ if (!existing) return;
20005
+ await this.store.put(this.keyOf(norm), { ...existing, lastSeenAt: now });
20006
+ }
19953
20007
  /**
19954
20008
  * 卸载;不存在 → not_found。删除后自底向上级联回收:
19955
20009
  * 仅回收 registeredBy=system:auto 且再无子节点的 directory,遇显式节点/仍有子节点即停。
@@ -20088,6 +20142,8 @@ export {
20088
20142
  deviceShellHelpModel,
20089
20143
  deviceFsHelpModel,
20090
20144
  deviceDirectoryHelpModel,
20145
+ derivePresence,
20146
+ DEVICE_CALL_TIMEOUT_MS,
20091
20147
  DeviceGatewaySession,
20092
20148
  FEEDBACK_HIDE_SCORE,
20093
20149
  selectFeedbackSearchText,
@@ -2,6 +2,7 @@ import {
2
2
  AnnotationStore,
3
3
  CONTEXT_CAPABILITIES,
4
4
  DEFAULT_MAX_NODES,
5
+ DEVICE_CALL_TIMEOUT_MS,
5
6
  DeviceGatewaySession,
6
7
  FEEDBACK_HIDE_SCORE,
7
8
  FeedbackStore,
@@ -68,6 +69,7 @@ import {
68
69
  createObjectContextProvider,
69
70
  createSkillhubProvider,
70
71
  decodeDeviceFrame,
72
+ derivePresence,
71
73
  deviceDirectoryHelpModel,
72
74
  deviceFsHelpModel,
73
75
  deviceShellHelpModel,
@@ -130,7 +132,7 @@ import {
130
132
  url,
131
133
  validatePath,
132
134
  virtualizeTools
133
- } from "./chunk-7PM4FD5K.js";
135
+ } from "./chunk-76YX7XSX.js";
134
136
 
135
137
  // src/config.ts
136
138
  var DEFAULT_PORT = 8787;
@@ -963,6 +965,15 @@ async function invokeDevice(deps, deviceId, req) {
963
965
  if (body.ok) return body.value;
964
966
  throw tbErrorFromBody(body.error);
965
967
  }
968
+ function deviceCallContextFrom(ctx) {
969
+ const now = Date.now();
970
+ return {
971
+ caller: { keyId: ctx.keyId, owner: ctx.owner },
972
+ traceId: ctx.traceId,
973
+ createdAt: new Date(now).toISOString(),
974
+ expiresAt: new Date(now + DEVICE_CALL_TIMEOUT_MS).toISOString()
975
+ };
976
+ }
966
977
  function deviceMarkerOf(pc) {
967
978
  if (pc === void 0 || typeof pc.deviceId !== "string" || typeof pc.mountPath !== "string") {
968
979
  return null;
@@ -19922,7 +19933,7 @@ async function processDeviceHello(opts) {
19922
19933
  input,
19923
19934
  authCtx.keyId,
19924
19935
  now,
19925
- input.path === mountPath ? { online: true } : {}
19936
+ input.path === mountPath ? { online: true, lastSeenAt: now } : {}
19926
19937
  );
19927
19938
  } catch (error) {
19928
19939
  await searchSync?.abort(marker);
@@ -19932,8 +19943,8 @@ async function processDeviceHello(opts) {
19932
19943
  throw error;
19933
19944
  }
19934
19945
  }
19935
- await searchSync?.rebuildAll(searchMarkers);
19936
- return { mountPath, keyId: authCtx.keyId };
19946
+ const searchIndexed = searchSync === void 0 ? true : await searchSync.rebuildAll(searchMarkers);
19947
+ return { mountPath, keyId: authCtx.keyId, searchIndexed };
19937
19948
  }
19938
19949
 
19939
19950
  // ../../node_modules/.pnpm/@modelcontextprotocol+server@2.0.0/node_modules/@modelcontextprotocol/server/dist/chunk-Br0eD_fh.mjs
@@ -35898,9 +35909,15 @@ async function assertRegisterPath2(registry, ctx, targetPath, action, deps) {
35898
35909
  });
35899
35910
  if (!res.allow) throw res.error;
35900
35911
  }
35901
- function toEntry(n) {
35912
+ function toEntry(n, now) {
35902
35913
  const e = { path: n.path, kind: n.kind, description: n.description };
35903
- if (n.online !== void 0) e.online = n.online;
35914
+ if (n.online !== void 0) {
35915
+ e.presence = derivePresence({
35916
+ online: n.online,
35917
+ ...n.lastSeenAt !== void 0 ? { lastSeenAt: n.lastSeenAt } : {},
35918
+ now
35919
+ });
35920
+ }
35904
35921
  return e;
35905
35922
  }
35906
35923
  function filterListVisible(nodes, scopes) {
@@ -36156,7 +36173,7 @@ function localizeRemoteEntry(mountPath, remoteParentPath, entry) {
36156
36173
  kind: entry.kind,
36157
36174
  description: entry.description
36158
36175
  };
36159
- if (entry.online !== void 0) out.online = entry.online;
36176
+ if (entry.presence !== void 0) out.presence = entry.presence;
36160
36177
  return out;
36161
36178
  }
36162
36179
  async function resolveRemoteSettings(state, base) {
@@ -36699,6 +36716,7 @@ function registerSearchRoute(app, env) {
36699
36716
 
36700
36717
  // ../app/src/helpModel.ts
36701
36718
  async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
36719
+ const index = opts.schemas !== true;
36702
36720
  if (node.kind === "builtin" && node.config?.kind === "builtin") {
36703
36721
  const mod = builtins.get(node.config.module);
36704
36722
  if (mod) return mod.help(node.path);
@@ -36710,8 +36728,13 @@ async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
36710
36728
  ctx.scopes
36711
36729
  );
36712
36730
  if (node.online !== void 0) {
36731
+ const presence = derivePresence({
36732
+ online: node.online,
36733
+ ...node.lastSeenAt !== void 0 ? { lastSeenAt: node.lastSeenAt } : {},
36734
+ now: opts.now
36735
+ });
36713
36736
  return deviceDirectoryHelpModel(
36714
- { path: node.path, description: node.description, online: node.online },
36737
+ { path: node.path, description: node.description, presence },
36715
36738
  children.map((n) => ({ path: n.path, kind: n.kind, description: n.description }))
36716
36739
  );
36717
36740
  }
@@ -36728,7 +36751,7 @@ async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
36728
36751
  node.path,
36729
36752
  { kind: node.kind, description: node.description },
36730
36753
  toolMarker.cmds ?? [],
36731
- { index: true }
36754
+ { index }
36732
36755
  );
36733
36756
  }
36734
36757
  if (node.kind === "mcp" || node.kind === "http" || node.kind === "tool") {
@@ -36739,9 +36762,7 @@ async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
36739
36762
  node.path,
36740
36763
  { kind: node.kind, description: node.description },
36741
36764
  exposed,
36742
- {
36743
- index: true
36744
- }
36765
+ { index }
36745
36766
  );
36746
36767
  }
36747
36768
  if (node.kind === "device" && node.config?.kind === "device") {
@@ -37207,7 +37228,8 @@ async function handleInvoke(c, env) {
37207
37228
  const result2 = await invokeDevice(deps, toolMarker.deviceId, {
37208
37229
  path: relativeDevicePath(node.path, toolMarker.mountPath),
37209
37230
  tool,
37210
- arguments: args2
37231
+ arguments: args2,
37232
+ context: deviceCallContextFrom(ctx)
37211
37233
  });
37212
37234
  return renderResult(result2, negotiate(c.req.header("accept")));
37213
37235
  }
@@ -37236,7 +37258,8 @@ async function handleInvoke(c, env) {
37236
37258
  const result2 = await invokeDevice(deps, node.config.deviceId, {
37237
37259
  path: "shell",
37238
37260
  tool: body2.tool,
37239
- arguments: body2.arguments ?? {}
37261
+ arguments: body2.arguments ?? {},
37262
+ context: deviceCallContextFrom(ctx)
37240
37263
  });
37241
37264
  return renderResult(result2, negotiate(c.req.header("accept")));
37242
37265
  }
@@ -37262,7 +37285,8 @@ async function handleInvoke(c, env) {
37262
37285
  const result3 = await invokeDevice(deps, deviceIdForDeviceFs(cfg), {
37263
37286
  path: "fs",
37264
37287
  tool: body2.tool,
37265
- arguments: args2
37288
+ arguments: args2,
37289
+ context: deviceCallContextFrom(ctx)
37266
37290
  });
37267
37291
  return renderResult(result3, negotiate(c.req.header("accept")));
37268
37292
  }
@@ -37271,7 +37295,8 @@ async function handleInvoke(c, env) {
37271
37295
  const result3 = await invokeDevice(deps, contextMarker.deviceId, {
37272
37296
  path: relativeDevicePath(node.path, contextMarker.mountPath),
37273
37297
  tool: body2.tool,
37274
- arguments: args2
37298
+ arguments: args2,
37299
+ context: deviceCallContextFrom(ctx)
37275
37300
  });
37276
37301
  return renderResult(result3, negotiate(c.req.header("accept")));
37277
37302
  }
@@ -37497,8 +37522,10 @@ async function handleHelp(c, env) {
37497
37522
  }
37498
37523
  const builtins = builtinsOf(store);
37499
37524
  const refresh = c.req.query("refresh") === "1";
37525
+ const schemas = c.req.query("schemas") === "1";
37500
37526
  const model = await helpModelFor(node, registry, ctx, builtins, deps, {
37501
37527
  refresh,
37528
+ schemas,
37502
37529
  now: (/* @__PURE__ */ new Date()).toISOString()
37503
37530
  });
37504
37531
  return renderHelp(await enrichHelp(model, path, store), rep);
@@ -37514,6 +37541,7 @@ async function handleTree(c, env) {
37514
37541
  const store = c.get("store");
37515
37542
  if (path !== "" && !check(ctx, path, "read").allow) throw TBError.notFound("not found");
37516
37543
  const registry = new NodeRegistryStore(store);
37544
+ const now = (/* @__PURE__ */ new Date()).toISOString();
37517
37545
  if (path !== "") {
37518
37546
  const remote = await remotePassthroughIfMatch(c, ctx, registry, path, "~tree", deps);
37519
37547
  if (remote) return remote;
@@ -37529,14 +37557,14 @@ async function handleTree(c, env) {
37529
37557
  if (rootNode.kind === "context" && rootNode.config?.kind === "context") {
37530
37558
  await assertContextAlive(rootNode, rootNode.config, registry);
37531
37559
  }
37532
- rootEntry = toEntry(rootNode);
37560
+ rootEntry = toEntry(rootNode, now);
37533
37561
  }
37534
37562
  const nodes = await pruneExpiredContext(await registry.subtree(path), registry);
37535
37563
  const byParent = indexByParent(nodes);
37536
37564
  const getChildren = async (p) => {
37537
37565
  const localKids = filterListVisible(byParent.get(p) ?? [], ctx.scopes);
37538
37566
  const remoteKids = await remoteTreeChildren(c, ctx, registry, p, deps);
37539
- return [...localKids.map((n) => toEntry(n)), ...remoteKids];
37567
+ return [...localKids.map((n) => toEntry(n, now)), ...remoteKids];
37540
37568
  };
37541
37569
  const depth = clampDepth(Number(c.req.query("depth")));
37542
37570
  const tree = await buildTree({
@@ -37743,6 +37771,10 @@ var DeviceHub = class {
37743
37771
  if (this.activeByDevice.has(meta.deviceId)) continue;
37744
37772
  if (meta.disconnectedAt === void 0) {
37745
37773
  const now = (/* @__PURE__ */ new Date()).toISOString();
37774
+ try {
37775
+ await new NodeRegistryStore(this.store).setOnline(meta.mountPath, false, now);
37776
+ } catch {
37777
+ }
37746
37778
  await this.store.put(KEY_DEVICE_META + meta.deviceId, { ...meta, disconnectedAt: now });
37747
37779
  this.scheduleReclaim(meta.deviceId, this.reclaimSec * 1e3);
37748
37780
  } else {
@@ -37807,6 +37839,10 @@ var DeviceHub = class {
37807
37839
  this.connections.add(conn);
37808
37840
  ws.on("pong", () => {
37809
37841
  conn.isAlive = true;
37842
+ if (conn.mountPath !== void 0) {
37843
+ void new NodeRegistryStore(this.store).touchSeen(conn.mountPath, (/* @__PURE__ */ new Date()).toISOString()).catch(() => {
37844
+ });
37845
+ }
37810
37846
  });
37811
37847
  ws.on("message", (data) => {
37812
37848
  try {
@@ -37823,7 +37859,7 @@ var DeviceHub = class {
37823
37859
  }
37824
37860
  async acceptHello(conn, hello) {
37825
37861
  const now = (/* @__PURE__ */ new Date()).toISOString();
37826
- const { mountPath, keyId } = await processDeviceHello({
37862
+ const { mountPath, keyId, searchIndexed } = await processDeviceHello({
37827
37863
  store: this.store,
37828
37864
  authorization: conn.authorization,
37829
37865
  deviceIdHint: conn.deviceId,
@@ -37831,6 +37867,11 @@ var DeviceHub = class {
37831
37867
  now,
37832
37868
  ...this.search === void 0 ? {} : { search: this.search }
37833
37869
  });
37870
+ if (!searchIndexed) {
37871
+ console.warn(
37872
+ `[tool-bridge] device '${conn.deviceId}' mounted at ${mountPath} but its tools are NOT in the search index: registry exceeds the tool-search capacity (TOOL_SEARCH_AUDIT_NODE_LIMIT). The device is callable but won't appear in \`tb search\` until capacity frees up.`
37873
+ );
37874
+ }
37834
37875
  const meta = { deviceId: conn.deviceId, mountPath, keyId, connectedAt: now };
37835
37876
  await this.store.put(KEY_DEVICE_META + conn.deviceId, meta);
37836
37877
  conn.keyId = keyId;
@@ -38336,7 +38377,7 @@ import { join as join4 } from "path";
38336
38377
  // package.json
38337
38378
  var package_default = {
38338
38379
  name: "@tool-bridge/server",
38339
- version: "0.5.0",
38380
+ version: "0.7.0",
38340
38381
  description: "tool-bridge self-hosted server: run the HTBP gateway on Node with SQLite persistence, filesystem object storage and WebSocket device channel \u2014 single container via docker run",
38341
38382
  type: "module",
38342
38383
  license: "MIT",
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  createPlugin
3
- } from "./chunk-B4ZA7EGO.js";
3
+ } from "./chunk-GMHELPK3.js";
4
4
  import {
5
5
  TBError
6
- } from "./chunk-7PM4FD5K.js";
6
+ } from "./chunk-76YX7XSX.js";
7
7
 
8
8
  // ../plugins/src/_runtime/plugin.ts
9
9
  function requireApiKey(ctx, service) {
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TBError
3
- } from "./chunk-7PM4FD5K.js";
3
+ } from "./chunk-76YX7XSX.js";
4
4
 
5
5
  // ../plugins/src/_runtime/ipPolicy.ts
6
6
  function parseIpv4(value) {
@@ -10,7 +10,7 @@ import {
10
10
  isTBError,
11
11
  parseCredentialValues,
12
12
  toToolResult
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
 
15
15
  // ../plugin-sdk/src/index.ts
16
16
  var CONTEXT_VERB_BY_HANDLER = {
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/circleci/api.ts
@@ -2,14 +2,14 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  external_exports
12
- } from "./chunk-7PM4FD5K.js";
12
+ } from "./chunk-76YX7XSX.js";
13
13
  import "./chunk-MLKGABMK.js";
14
14
 
15
15
  // ../plugins/src/clerk/api.ts
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/cloudflare_dns/api.ts
@@ -2,14 +2,14 @@ import {
2
2
  createProviderPlugin,
3
3
  requireApiKey,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  external_exports
12
- } from "./chunk-7PM4FD5K.js";
12
+ } from "./chunk-76YX7XSX.js";
13
13
  import "./chunk-MLKGABMK.js";
14
14
 
15
15
  // ../plugins/src/cohere/api.ts
@@ -2,15 +2,15 @@ import {
2
2
  createProviderPlugin,
3
3
  requireCredential,
4
4
  upstreamError
5
- } from "./chunk-FHYFPPBZ.js";
5
+ } from "./chunk-BUHY4IE6.js";
6
6
  import {
7
7
  guardedFetch
8
- } from "./chunk-7GP7DRES.js";
9
- import "./chunk-B4ZA7EGO.js";
8
+ } from "./chunk-EBO6Q4NR.js";
9
+ import "./chunk-GMHELPK3.js";
10
10
  import {
11
11
  TBError,
12
12
  external_exports
13
- } from "./chunk-7PM4FD5K.js";
13
+ } from "./chunk-76YX7XSX.js";
14
14
  import "./chunk-MLKGABMK.js";
15
15
 
16
16
  // ../plugins/src/confluence/api.ts