@tool-bridge/server 0.5.0 → 0.10.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.
- package/dist/{airtable-7TFNLFIF.js → airtable-5W6SJMSM.js} +4 -4
- package/dist/{alt_text_generator_ai-VJSAHBJM.js → alt_text_generator_ai-YYVJM3RG.js} +4 -4
- package/dist/{amap-KZMUDGK6.js → amap-EREMQZHQ.js} +4 -4
- package/dist/{anthropic-C6FCUSY7.js → anthropic-53H7WGSE.js} +4 -4
- package/dist/{apify-MUCWNIWU.js → apify-CMRNU7VZ.js} +4 -4
- package/dist/{brave_search-NRVZ4ZNY.js → brave_search-AFZVZ3QK.js} +4 -4
- package/dist/{chunk-FHYFPPBZ.js → chunk-2DA2UI37.js} +2 -2
- package/dist/{chunk-B4ZA7EGO.js → chunk-Q44CYUSI.js} +1 -1
- package/dist/{chunk-3C3J36GT.js → chunk-Q7YHZ2SD.js} +683 -54
- package/dist/{chunk-7GP7DRES.js → chunk-SBJMMSPA.js} +1 -1
- package/dist/{chunk-7PM4FD5K.js → chunk-TPGTA43F.js} +291 -55
- package/dist/{circleci-QY36SZIM.js → circleci-JG7RV2RU.js} +4 -4
- package/dist/{clerk-ECH23XL5.js → clerk-U7OS5ALG.js} +4 -4
- package/dist/{cloudflare_dns-F6DN2F3X.js → cloudflare_dns-ADCTFMMI.js} +4 -4
- package/dist/{cohere-HD4XZOPJ.js → cohere-Z7ZEC2YV.js} +4 -4
- package/dist/{confluence-J4AZ2KYL.js → confluence-FT22JGYQ.js} +4 -4
- package/dist/{convertapi-BXBII5Z6.js → convertapi-UQQCWVWP.js} +4 -4
- package/dist/{currencyapi-HEEQ7EQJ.js → currencyapi-Y63O7JTP.js} +4 -4
- package/dist/{deepseek-RKRGIFPM.js → deepseek-7TSAMZJ6.js} +4 -4
- package/dist/{docker_hub-YFSTEZVP.js → docker_hub-AJYTVI25.js} +4 -4
- package/dist/{dropbox-VGK634PO.js → dropbox-CNGGNR5J.js} +4 -4
- package/dist/{dub-GEXD3XK6.js → dub-WTADKHA7.js} +4 -4
- package/dist/{e2b-LPTZQEDV.js → e2b-75EKXMN5.js} +4 -4
- package/dist/{exa-VJENLTKN.js → exa-OFLA5XND.js} +4 -4
- package/dist/{fal_ai-75O63LLP.js → fal_ai-5542HB7N.js} +4 -4
- package/dist/{feishu-FATBHGEJ.js → feishu-QQIZ7G24.js} +3 -3
- package/dist/{feishu_custom_bot-QFSYPOLI.js → feishu_custom_bot-EVDKIZCR.js} +4 -4
- package/dist/{figma-JED3Q56H.js → figma-ZEBDUMWI.js} +4 -4
- package/dist/{firehydrant-7JDKFJTB.js → firehydrant-CTBNY6FL.js} +4 -4
- package/dist/{fixer-ZI2JS5GU.js → fixer-ITDYMRBW.js} +4 -4
- package/dist/{fly-3RA7ETFP.js → fly-IBFMSAAO.js} +4 -4
- package/dist/{front-X2CJXBYS.js → front-AZQLLUJQ.js} +4 -4
- package/dist/{geocodio-C6NHG5UJ.js → geocodio-XHZHEWQW.js} +4 -4
- package/dist/{ghost-ZBFOMWQF.js → ghost-RTIKXD3T.js} +4 -4
- package/dist/{github-6QM2NIP4.js → github-WRJBJ5N7.js} +4 -4
- package/dist/{gmail-ST3MS32S.js → gmail-527RVDXV.js} +4 -4
- package/dist/{googlecalendar-SAUTUJ3Q.js → googlecalendar-WZJSK2MR.js} +4 -4
- package/dist/{googledocs-2SJKS2SC.js → googledocs-LFBVIHIK.js} +4 -4
- package/dist/{grafana-RP7DOS3A.js → grafana-3JEKO7NT.js} +4 -4
- package/dist/{graphhopper-XSDTLJTE.js → graphhopper-TOJN6K2Q.js} +4 -4
- package/dist/index.d.ts +400 -26
- package/dist/index.js +14 -2
- package/dist/{ip2proxy-IKV5IWUI.js → ip2proxy-KOA2JUNV.js} +4 -4
- package/dist/{ipgeolocation_io-NSUWUF5X.js → ipgeolocation_io-KNOQD7R7.js} +4 -4
- package/dist/{ipqualityscore-ZQKL3WLC.js → ipqualityscore-GF2MQKXI.js} +4 -4
- package/dist/{jina_ai-F4Y7V5AS.js → jina_ai-GB3CQPJ4.js} +4 -4
- package/dist/{jira-CYDY44ZO.js → jira-35XYV6G4.js} +4 -4
- package/dist/{langsmith-74JSSJNY.js → langsmith-W5234OE7.js} +4 -4
- package/dist/{lemlist-C3LKIPVN.js → lemlist-QB6W2G7N.js} +4 -4
- package/dist/{linear-YYGRHKJC.js → linear-MHBD6A7X.js} +4 -4
- package/dist/{logsnag-YBMDJ6DO.js → logsnag-RN57XIJS.js} +4 -4
- package/dist/main.js +113 -106
- package/dist/{mattermost-NDID4TAL.js → mattermost-QRXSZMZA.js} +4 -4
- package/dist/{mem0-ASBAEBWR.js → mem0-K63NN3LA.js} +4 -4
- package/dist/{memos-76I27HCW.js → memos-4IOUOFKH.js} +4 -4
- package/dist/{metabase-LCPIP2DL.js → metabase-IOE44EKL.js} +4 -4
- package/dist/{mistral_ai-YVBQ6QKO.js → mistral_ai-X7ASGV5I.js} +4 -4
- package/dist/{mother_duck-J2MPBIFO.js → mother_duck-CNN3QWQH.js} +4 -4
- package/dist/{ngrok-UJC2ORDH.js → ngrok-QNE4AHEH.js} +4 -4
- package/dist/{notes-6VWWD6RW.js → notes-Q6OLBS2L.js} +2 -2
- package/dist/{notion-6LBO2KHR.js → notion-ADDRQTCE.js} +4 -4
- package/dist/{open_exchange_rates-OGDH4ZBX.js → open_exchange_rates-WR5PJQTG.js} +4 -4
- package/dist/{openai-IKGD5M66.js → openai-UZBNNAAH.js} +4 -4
- package/dist/{opengraph_io-CIILQ7VK.js → opengraph_io-2JNEXCPJ.js} +4 -4
- package/dist/{openrouter-IYG5CPG5.js → openrouter-EF62BDIH.js} +4 -4
- package/dist/{outline-R2UMBY4M.js → outline-O4TIRWJT.js} +4 -4
- package/dist/{paddle-IYWA7DOV.js → paddle-SEFKNENH.js} +4 -4
- package/dist/{perplexity-3TGYQWHT.js → perplexity-FZYOIPDS.js} +4 -4
- package/dist/{pinecone-TEBOW4LJ.js → pinecone-EXDPYDY7.js} +4 -4
- package/dist/{pipedrive-ZXDY753U.js → pipedrive-EDO4C3AM.js} +4 -4
- package/dist/{polar-BVZV5A4O.js → polar-QJXHVFIP.js} +4 -4
- package/dist/{posthog-DXKAS4PJ.js → posthog-U6QEXJE2.js} +4 -4
- package/dist/{postmark-6RWFC3TD.js → postmark-PFZIWXMP.js} +4 -4
- package/dist/{prerender-YIXOTM3K.js → prerender-SK2AXNJY.js} +4 -4
- package/dist/{pubmed-2RHSZB4E.js → pubmed-CB7OJNBH.js} +4 -4
- package/dist/{railway-IF64BUE2.js → railway-BMMNQ6XH.js} +4 -4
- package/dist/{readwise-5XKQZNOM.js → readwise-YQY7O5QR.js} +4 -4
- package/dist/{render-Q2Z66LTA.js → render-7CRNEEJ3.js} +4 -4
- package/dist/{replicate-SOI65IJO.js → replicate-V6AX7WFC.js} +4 -4
- package/dist/{resend-O2BGONOO.js → resend-ZBH56UAQ.js} +4 -4
- package/dist/{rootly-WPQKTVU3.js → rootly-C4FIXIF7.js} +4 -4
- package/dist/{scrapfly-GLMBVNPG.js → scrapfly-UE434KD7.js} +4 -4
- package/dist/{scrapingbee-TUER54CY.js → scrapingbee-PQCNKALD.js} +4 -4
- package/dist/{screenshot_fyi-4J4W5EKY.js → screenshot_fyi-U6QGI6ZH.js} +4 -4
- package/dist/{semantic_scholar-4PITOANV.js → semantic_scholar-PSMUOG2W.js} +4 -4
- package/dist/{sentry-4WURPLIE.js → sentry-F5CNVQA2.js} +4 -4
- package/dist/{shodan-G3M3LFEW.js → shodan-NOWG7NV5.js} +4 -4
- package/dist/{shopify-72AIELMS.js → shopify-GGPLJIGC.js} +4 -4
- package/dist/{stripe-7C7XVPMU.js → stripe-72K2UMK3.js} +4 -4
- package/dist/{supabase-N4Y3YC23.js → supabase-H7NRCSAO.js} +4 -4
- package/dist/{tavily-GGLSWERP.js → tavily-ISP24QUX.js} +4 -4
- package/dist/{telegram-4RH36WYP.js → telegram-POII6NKE.js} +4 -4
- package/dist/{telnyx-I2KUITFV.js → telnyx-3D7TOVNA.js} +4 -4
- package/dist/{todoist-A3NX6X2Y.js → todoist-LKYPKRKB.js} +4 -4
- package/dist/{trello-2GJYN7GR.js → trello-WW74UYIQ.js} +4 -4
- package/dist/{turso-WKUXMTZ5.js → turso-SUFRHBHW.js} +4 -4
- package/dist/{twilio-SSXDBOK4.js → twilio-QB7PBL2B.js} +4 -4
- package/dist/{umami-SBDB4GXK.js → umami-CAHHP3SV.js} +4 -4
- package/dist/{unsplash-4AVC4ZGP.js → unsplash-ZCGEPHGQ.js} +4 -4
- package/dist/{upstash_redis-7XY3UHBO.js → upstash_redis-DZ4AKZWT.js} +4 -4
- package/dist/{uptimerobot-QVQP3QYG.js → uptimerobot-KVEQJGTZ.js} +4 -4
- package/dist/{v2ex-ASVTIKO7.js → v2ex-BCYYBPH7.js} +4 -4
- package/dist/{vercel-ZQXZCGWY.js → vercel-GH4G7EUS.js} +4 -4
- package/dist/{wolfram_alpha_api-RVBWQSEF.js → wolfram_alpha_api-XFG2MQBL.js} +4 -4
- package/dist/{wordpress-SOWKVNCX.js → wordpress-DZ2TVNAA.js} +4 -4
- package/dist/{workos-F45INANB.js → workos-EHUAGTGN.js} +4 -4
- package/dist/{zhihu-5VODAGAP.js → zhihu-OJJW3ZIH.js} +4 -4
- package/package.json +6 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import * as http from 'node:http';
|
|
3
|
+
import { Sql } from 'postgres';
|
|
3
4
|
import { Hono } from 'hono';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -84,6 +85,29 @@ interface StateStore {
|
|
|
84
85
|
}>;
|
|
85
86
|
}>;
|
|
86
87
|
put(key: string, value: unknown): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* 可选原子原语:key 不存在则写入并返回 true;已存在则不覆盖并返回 false。
|
|
90
|
+
* 用途是多副本/多 isolate 并发引导的 winner-takes-all 去重(如 Admin SK 铸造)。
|
|
91
|
+
* SQL 后端原子实现;Workers KV 最终一致且无 CAS,**不实现**此方法——调用方必须
|
|
92
|
+
* 容忍回退到非原子的 get-miss→put,并保证重复写幂等或后果可接受。
|
|
93
|
+
* 可选而非必选:必选会破坏 SDK 消费者已实现的自定义 StateStore。
|
|
94
|
+
*/
|
|
95
|
+
putIfAbsent?(key: string, value: unknown): Promise<boolean>;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* TBError:平台统一错误类型与 TBError↔HTTP 映射。
|
|
100
|
+
*
|
|
101
|
+
* core 是纯逻辑内核,不依赖任何运行时(Workers / Node)——错误的 HTTP 呈现
|
|
102
|
+
* 由网关层读取此处的 `httpStatus` 与 `toJSON()` 完成,core 只定义契约。
|
|
103
|
+
*/
|
|
104
|
+
/** 7 个规范错误码。 */
|
|
105
|
+
type TBErrorCode = 'not_found' | 'permission_denied' | 'invalid_argument' | 'conflict' | 'unavailable' | 'rate_limited' | 'internal';
|
|
106
|
+
/** 线上 body 形状:~help、返回值、错误响应统一用它。 */
|
|
107
|
+
interface TBErrorBody {
|
|
108
|
+
code: TBErrorCode;
|
|
109
|
+
message: string;
|
|
110
|
+
retryable: boolean;
|
|
87
111
|
}
|
|
88
112
|
|
|
89
113
|
/**
|
|
@@ -461,6 +485,54 @@ interface ObjectStore {
|
|
|
461
485
|
put(key: string, body: ObjectBody, opts?: ObjectPutOptions): Promise<ObjectMeta>;
|
|
462
486
|
}
|
|
463
487
|
|
|
488
|
+
/**
|
|
489
|
+
* DeviceFrame:设备 WS 帧协议的类型与编解码。
|
|
490
|
+
*
|
|
491
|
+
* JSON 文本帧、`type` 区分;decode 拒绝非 JSON / 未知 type / 缺字段(invalid_argument),
|
|
492
|
+
* encode 产出紧凑 JSON。ping/pong 序列化为稳定字面量(PING_FRAME_JSON/PONG_FRAME_JSON)——
|
|
493
|
+
* DO 的 setWebSocketAutoResponse 按字符串精确匹配,设备侧心跳帧不得有其他序列化形态。
|
|
494
|
+
*/
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* 网关鉴权后为本次 call 生成的调用方来源与权威期限。
|
|
498
|
+
* 全部由网关签发,不接受来自调用 arguments;设备只消费不自造,且不做授权裁决
|
|
499
|
+
* (scope 判定在网关侧已完成)。故意不含 scopes / SK / 敏感参数。
|
|
500
|
+
*/
|
|
501
|
+
interface DeviceCallContext {
|
|
502
|
+
caller: {
|
|
503
|
+
displayName?: string;
|
|
504
|
+
/** 本次调用使用的 SK id(非明文,审计用)。 */
|
|
505
|
+
keyId: string;
|
|
506
|
+
owner: OwnerRef;
|
|
507
|
+
};
|
|
508
|
+
/** 网关签发时刻(网关时钟,非设备本地时钟)。 */
|
|
509
|
+
createdAt: Timestamp;
|
|
510
|
+
/** 本次调用的权威失效时刻;设备复检一律以此比对,不信任设备本地时钟。 */
|
|
511
|
+
expiresAt: Timestamp;
|
|
512
|
+
/** 全链路观测,与 call id 同源。 */
|
|
513
|
+
traceId: string;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* 网关侧设备会话状态机(纯逻辑,I/O 与时间注入,DO 只做胶水)。
|
|
518
|
+
*
|
|
519
|
+
* - awaiting-hello → ready:hello 经 io.onHello 交胶水层做 Check(register),
|
|
520
|
+
* 通过则 accept(mountPath)(回 ready 帧),否则 reject(error)(拒绝帧 + close(1008))。
|
|
521
|
+
* - 未 hello 先发非 hello 帧 / hello 重复 / 设备发出网关方向帧 → 拒绝帧 + 关闭。
|
|
522
|
+
* - call:requestId 幂等表——已有结果的重复 id 立即以首次结果应答;结果未到的重复 id
|
|
523
|
+
* 挂到同一待决项,不重复下发 call 帧。
|
|
524
|
+
* - 超时(DEVICE_CALL_TIMEOUT_MS):给调用方 unavailable(retryable:true),给设备 cancel 帧;
|
|
525
|
+
* 迟到的 result 仅入幂等表(后续重复 id 以它应答)。
|
|
526
|
+
*/
|
|
527
|
+
|
|
528
|
+
type DeviceCallResult = {
|
|
529
|
+
ok: true;
|
|
530
|
+
value: unknown;
|
|
531
|
+
} | {
|
|
532
|
+
error: TBErrorBody;
|
|
533
|
+
ok: false;
|
|
534
|
+
};
|
|
535
|
+
|
|
464
536
|
/**
|
|
465
537
|
* Tool Layer 的中立类型。
|
|
466
538
|
*
|
|
@@ -579,6 +651,52 @@ interface SqlSearchStatement {
|
|
|
579
651
|
readonly params: readonly unknown[];
|
|
580
652
|
readonly sql: string;
|
|
581
653
|
}
|
|
654
|
+
/**
|
|
655
|
+
* 固定形态语句:参数个数与语义在 core 编排里写死,方言只提供 SQL 文本。
|
|
656
|
+
* 占位符语法(`?` / `$n`)与字符串函数由各方言自行决定。
|
|
657
|
+
*/
|
|
658
|
+
interface SqlSearchStatements {
|
|
659
|
+
readonly bumpRevision: string;
|
|
660
|
+
readonly completeRebuild: string;
|
|
661
|
+
readonly deleteAllSnapshots: string;
|
|
662
|
+
readonly deleteAllTools: string;
|
|
663
|
+
readonly deleteSnapshot: string;
|
|
664
|
+
readonly deleteSnapshotPrefix: string;
|
|
665
|
+
readonly deleteTools: string;
|
|
666
|
+
readonly deleteToolsPrefix: string;
|
|
667
|
+
/** 单 path 的 path→digest 快照插入(replace 内联使用)。 */
|
|
668
|
+
readonly insertSnapshot: string;
|
|
669
|
+
/** 读 meta 单例(revision/seeded/cursor_secret)。 */
|
|
670
|
+
readonly meta: string;
|
|
671
|
+
/** replace 前置探测:本 path 的 digest、是否残留 source 行、已用节点数。 */
|
|
672
|
+
readonly pathState: string;
|
|
673
|
+
/** 单 path 是否存在 source 行。 */
|
|
674
|
+
readonly present: string;
|
|
675
|
+
/** path 或其子树是否存在 source 行。 */
|
|
676
|
+
readonly presentPrefix: string;
|
|
677
|
+
/** 全量快照 digest,按 path 升序。 */
|
|
678
|
+
readonly snapshotDigests: string;
|
|
679
|
+
}
|
|
680
|
+
/**
|
|
681
|
+
* SQL 方言:把与具体引擎绑定的 SQL 文本从数据库无关的编排里分出来。
|
|
682
|
+
*
|
|
683
|
+
* `SqlSearchIndex` 只认识本接口——候选查询 + 一组固定语句 + 建表 DDL。
|
|
684
|
+
* D1 与 better-sqlite3 同为 SQLite,共用 {@link sqliteSearchDialect};其它引擎
|
|
685
|
+
* (如 Postgres)实现自己的方言,替换全文检索与占位符语法。方言只管 SQL 文本,
|
|
686
|
+
* 具体驱动的同步/异步、批量预算、结果整形仍由 {@link SqlSearchDriver} 吸收。
|
|
687
|
+
*/
|
|
688
|
+
interface SqlSearchDialect {
|
|
689
|
+
/**
|
|
690
|
+
* 把已 normalize 的 query 变成候选查询语句(含排序与分页)。
|
|
691
|
+
* prepare(分词、短/长词切分、方言专属语法)由各方言自理——SQLite 走 trigram
|
|
692
|
+
* FTS + 短词 LIKE,PG 走 ILIKE 子串;编排层只给 normalized query,不预设方言。
|
|
693
|
+
*/
|
|
694
|
+
candidateStatement(query: string, limit: number, offset: number): SqlSearchStatement;
|
|
695
|
+
/** 建表(幂等),元素不带尾分号。 */
|
|
696
|
+
readonly schemaStatements: readonly string[];
|
|
697
|
+
/** 编排直接下发的固定语句。 */
|
|
698
|
+
readonly statements: SqlSearchStatements;
|
|
699
|
+
}
|
|
582
700
|
/**
|
|
583
701
|
* 宿主驱动:把 `SqlSearchStatement` 落到具体数据库上。
|
|
584
702
|
*
|
|
@@ -607,7 +725,8 @@ interface SqlSearchDriver {
|
|
|
607
725
|
declare class SqlSearchIndex implements MutableSearchIndex {
|
|
608
726
|
protected readonly driver: SqlSearchDriver;
|
|
609
727
|
readonly capabilities: readonly SearchCapability[];
|
|
610
|
-
|
|
728
|
+
protected readonly dialect: SqlSearchDialect;
|
|
729
|
+
constructor(driver: SqlSearchDriver, dialect?: SqlSearchDialect);
|
|
611
730
|
/** 容量 trigger 的 ABORT 在各驱动里错误形状不同,统一按标记串归一。 */
|
|
612
731
|
private writeOrCapacity;
|
|
613
732
|
private meta;
|
|
@@ -694,6 +813,8 @@ interface RemoteSettings {
|
|
|
694
813
|
/** 帧协议 call 转发的入参(id 由调用点生成,幂等键)。 */
|
|
695
814
|
interface DeviceInvokeRequest {
|
|
696
815
|
arguments: Record<string, unknown>;
|
|
816
|
+
/** 网关鉴权后的调用方来源与权威期限;缺省则不写入 call 帧。 */
|
|
817
|
+
context?: DeviceCallContext;
|
|
697
818
|
id: string;
|
|
698
819
|
path: string;
|
|
699
820
|
tool: string;
|
|
@@ -712,6 +833,18 @@ interface LocalProviderHooks {
|
|
|
712
833
|
/** kind:'tool' 节点按路径取进程内工具源;undefined → 走 plugin 解析。 */
|
|
713
834
|
tool?(nodePath: TreePath): UpstreamProvider | undefined;
|
|
714
835
|
}
|
|
836
|
+
/**
|
|
837
|
+
* 就绪探测报告(GET /readyz 的响应体)。checks 逐后端给出连通结果;
|
|
838
|
+
* ready=false → 503,编排器(k8s readiness / LB)据此摘除流量。
|
|
839
|
+
* detail 只放短语级原因(如 "timeout after 1000ms"),不放凭证或拓扑细节。
|
|
840
|
+
*/
|
|
841
|
+
interface ReadinessReport {
|
|
842
|
+
checks: Record<string, {
|
|
843
|
+
detail?: string;
|
|
844
|
+
ok: boolean;
|
|
845
|
+
}>;
|
|
846
|
+
ready: boolean;
|
|
847
|
+
}
|
|
715
848
|
/**
|
|
716
849
|
* tb app 的宿主注入面(五注入点 + 解析后的部署配置)。
|
|
717
850
|
* 核心业务逻辑零分叉:Workers 适配层(app.ts)与 SDK(packages/sdk)都注入此形状。
|
|
@@ -753,6 +886,12 @@ interface TbAppDeps {
|
|
|
753
886
|
* 那个插件解析不出 export;反之则解析得出但调不动(unavailable)。宿主该两者同源装配。
|
|
754
887
|
*/
|
|
755
888
|
pluginCatalog?: BuiltinCatalog;
|
|
889
|
+
/**
|
|
890
|
+
* 后端连通性探测(GET /readyz;k8s readiness)。宿主注入闭包,自行探测其长连接
|
|
891
|
+
* 后端(PG 池 / Redis)并叠加 draining 状态。缺省 → /readyz 恒 200:请求期绑定
|
|
892
|
+
* 宿主(Workers 的 KV/D1/R2)无"断连"态,嵌入宿主自理。
|
|
893
|
+
*/
|
|
894
|
+
readiness?: () => Promise<ReadinessReport>;
|
|
756
895
|
/** context Get 的 $ref 内联阈值(字节,缺省 1 MiB)。 */
|
|
757
896
|
refThresholdBytes?: number;
|
|
758
897
|
/** $ref URL(presign 与 /~ref 中转)有效期秒(缺省 900)。 */
|
|
@@ -785,7 +924,8 @@ declare function createTbApp(deps: TbAppDeps): Hono<{
|
|
|
785
924
|
|
|
786
925
|
/**
|
|
787
926
|
* Node 宿主的 env 配置面。变量名与语义对齐 CF 宿主(gateway/src/app.ts 的 Env),
|
|
788
|
-
* 仅新增宿主形态相关的 TB_PORT / TB_HOST / TB_DATA_DIR / TB_UI_DIR。
|
|
927
|
+
* 仅新增宿主形态相关的 TB_PORT / TB_HOST / TB_DATA_DIR / TB_UI_DIR / TB_DATABASE_URL。
|
|
928
|
+
* 端口额外兜底平台注入的 PORT(PaaS 通行约定)。
|
|
789
929
|
* 解析函数镜像 app.ts 的 allowInsecure / remoteSettingsFromEnv / positiveIntEnv。
|
|
790
930
|
*/
|
|
791
931
|
|
|
@@ -804,6 +944,11 @@ interface ServerConfig {
|
|
|
804
944
|
* configFromEnv 抛错,进程拒绝启动(fail closed,不静默回退到请求期 origin)。
|
|
805
945
|
*/
|
|
806
946
|
canonicalOrigin?: string;
|
|
947
|
+
/**
|
|
948
|
+
* Postgres 连接串(TB_DATABASE_URL)。给出则 StateStore 与 SearchIndex 都走 PG
|
|
949
|
+
* (ILIKE 子串检索,无扩展依赖);缺省回退到 dataDir 下的 SQLite。
|
|
950
|
+
*/
|
|
951
|
+
databaseUrl?: string;
|
|
807
952
|
/** SQLite 库与 fs 对象根所在目录(state.sqlite3 + objects/)。 */
|
|
808
953
|
dataDir: string;
|
|
809
954
|
/** 设备断线后未重连的回收秒数(缺省 24h)。 */
|
|
@@ -811,6 +956,18 @@ interface ServerConfig {
|
|
|
811
956
|
/** SecretStore 主密钥 + $ref 中转 token 签名密钥(base64url 32B)。 */
|
|
812
957
|
encryptionKey?: string;
|
|
813
958
|
host: string;
|
|
959
|
+
/**
|
|
960
|
+
* 平台对象存储(context `$ref` 大对象落点)。给出则用 S3/R2 兼容端点,
|
|
961
|
+
* 缺省回退 dataDir 下的本地 FS。配 S3 后容器可无状态横向扩容 —— FS 落点
|
|
962
|
+
* 在多副本间互不可见、容器重建即丢。
|
|
963
|
+
*/
|
|
964
|
+
objectStore?: {
|
|
965
|
+
accessKeyId: string;
|
|
966
|
+
bucket: string;
|
|
967
|
+
endpoint: string;
|
|
968
|
+
region?: string;
|
|
969
|
+
secretAccessKey: string;
|
|
970
|
+
};
|
|
814
971
|
/**
|
|
815
972
|
* 进程内插件装配表(binding 名 → fetch handler)。缺省时 bin 入口装配**全量内置目录**
|
|
816
973
|
* (见 `main.ts`);程序化嵌入方可给自己的表来覆盖或裁剪。
|
|
@@ -822,6 +979,14 @@ interface ServerConfig {
|
|
|
822
979
|
*/
|
|
823
980
|
pluginCatalog?: BuiltinCatalog;
|
|
824
981
|
port: number;
|
|
982
|
+
/**
|
|
983
|
+
* 多副本设备通道路由的 Redis 连接串(TB_REDIS_URL)。
|
|
984
|
+
*
|
|
985
|
+
* 设备的 WebSocket 是活 socket、只存在于接受它的进程里,故多副本时打给"连在别的
|
|
986
|
+
* 副本上的设备"的调用必须跨副本转发。配上即启用路由表 + pub/sub 转发;
|
|
987
|
+
* 单副本部署不需要配(本地直连恒命中)。
|
|
988
|
+
*/
|
|
989
|
+
redisUrl?: string;
|
|
825
990
|
refThresholdBytes?: number;
|
|
826
991
|
refTtlSec?: number;
|
|
827
992
|
remote: {
|
|
@@ -830,12 +995,110 @@ interface ServerConfig {
|
|
|
830
995
|
instanceId?: string;
|
|
831
996
|
maxHops: number;
|
|
832
997
|
};
|
|
998
|
+
/**
|
|
999
|
+
* 本副本标识(TB_REPLICA_ID),路由表的 value。缺省用 hostname —— 容器平台上
|
|
1000
|
+
* 每个副本的 hostname 天然唯一;同机多进程需显式区分。
|
|
1001
|
+
*/
|
|
1002
|
+
replicaId?: string;
|
|
1003
|
+
/**
|
|
1004
|
+
* SIGTERM 后先置 draining(/readyz 转 503)再关停的等待秒数(TB_SHUTDOWN_DRAIN_SEC,
|
|
1005
|
+
* 缺省 0)。k8s 滚动更新时 endpoint 摘除有传播延迟,不等一拍就关会把仍被路由过来的
|
|
1006
|
+
* 请求吃闭门羹;单机/本地开发保持 0,关停立即进行。
|
|
1007
|
+
*/
|
|
1008
|
+
shutdownDrainSec?: number;
|
|
833
1009
|
toolCacheTtlSec?: number;
|
|
834
1010
|
/** Dashboard 静态资源目录覆盖(缺省经 @tool-bridge/dashboard 包解析)。 */
|
|
835
1011
|
uiDir?: string;
|
|
836
1012
|
}
|
|
837
1013
|
declare function configFromEnv(env?: NodeJS.ProcessEnv): ServerConfig;
|
|
838
1014
|
|
|
1015
|
+
/**
|
|
1016
|
+
* DeviceRouter:多副本部署下的设备调用路由。
|
|
1017
|
+
*
|
|
1018
|
+
* 为什么不能只换个存储 —— 设备的 WebSocket 是**活 socket**,只存在于接受它的那个
|
|
1019
|
+
* 进程里,不可序列化。副本 B 收到打给"连在副本 A 上的设备"的 HTTP 调用时,B 手里
|
|
1020
|
+
* 没有那个 socket,必须把调用**转发**给 A、再把结果收回来。所以这里是两件事:
|
|
1021
|
+
*
|
|
1022
|
+
* 1. 路由表(Redis string,带 TTL):deviceId → 持有者副本 ID。TTL + 周期续期让
|
|
1023
|
+
* 副本崩溃后条目自动过期,不需要墓碑清理。
|
|
1024
|
+
* 2. 请求/响应转发(Redis pub/sub):B 往 A 的频道发 call、A 执行完往 B 的回执
|
|
1025
|
+
* 频道发 result。跨副本的请求-响应用 correlationId 关联,并有独立超时兜底 ——
|
|
1026
|
+
* A 在执行途中崩溃时 B 不能永久挂起。
|
|
1027
|
+
*
|
|
1028
|
+
* 本副本自己持有连接时**完全不经这里**(DeviceHub 先查本地 Map),故单副本部署零额外
|
|
1029
|
+
* 开销、也不需要配 Redis。
|
|
1030
|
+
*
|
|
1031
|
+
* 与 CF 宿主的对照:那边用 Durable Object,天然"每设备一个单点",不存在这个问题。
|
|
1032
|
+
* 本模块是 Node 多副本的等价物。
|
|
1033
|
+
*/
|
|
1034
|
+
|
|
1035
|
+
/** 路由条目 TTL;续期周期取其 1/3,保证正常情况下不会因抖动过期。 */
|
|
1036
|
+
declare const DEVICE_ROUTE_TTL_SEC = 30;
|
|
1037
|
+
/** 跨副本转发的等待上限(毫秒)。持有者副本崩溃时靠它兜底,不能永久挂起。 */
|
|
1038
|
+
declare const DEVICE_FORWARD_TIMEOUT_MS = 65000;
|
|
1039
|
+
/**
|
|
1040
|
+
* DeviceHub 需要的 Redis 能力子集。
|
|
1041
|
+
*
|
|
1042
|
+
* 抽成接口而非直接用 ioredis:让 DeviceHub 不依赖具体客户端,单测可注入内存实现,
|
|
1043
|
+
* 也便于将来换 Valkey / 其它 pub/sub 后端。
|
|
1044
|
+
*/
|
|
1045
|
+
interface DeviceRouterBackend {
|
|
1046
|
+
/** 删除本副本持有的路由条目(仅当当前值仍是自己,避免删掉已顶替者的条目)。 */
|
|
1047
|
+
clearRoute(deviceId: string, replicaId: string): Promise<void>;
|
|
1048
|
+
close(): Promise<void>;
|
|
1049
|
+
/** 查 deviceId 的持有者副本;无则 null。 */
|
|
1050
|
+
lookupRoute(deviceId: string): Promise<string | null>;
|
|
1051
|
+
/** 向某副本的频道发布消息。 */
|
|
1052
|
+
publish(channel: string, payload: string): Promise<void>;
|
|
1053
|
+
/** 声明/续期:deviceId 由本副本持有,TTL 秒后过期。 */
|
|
1054
|
+
setRoute(deviceId: string, replicaId: string, ttlSec: number): Promise<void>;
|
|
1055
|
+
/** 订阅频道;handler 收到原始 payload。 */
|
|
1056
|
+
subscribe(channel: string, handler: (payload: string) => void): Promise<void>;
|
|
1057
|
+
}
|
|
1058
|
+
/**
|
|
1059
|
+
* 跨副本调用的发起侧与接收侧编排。
|
|
1060
|
+
*
|
|
1061
|
+
* DeviceHub 只跟本类打交道:`invoke` 时若本地无连接就问 `forward`,
|
|
1062
|
+
* 并把"本副本能否执行某设备调用"的能力通过 `onLocalCall` 交回来。
|
|
1063
|
+
*/
|
|
1064
|
+
declare class DeviceRouter {
|
|
1065
|
+
readonly replicaId: string;
|
|
1066
|
+
private readonly backend;
|
|
1067
|
+
private readonly opts;
|
|
1068
|
+
private readonly pending;
|
|
1069
|
+
private renewTimer;
|
|
1070
|
+
/** 本副本当前持有的设备(需周期续期路由条目)。 */
|
|
1071
|
+
private readonly owned;
|
|
1072
|
+
constructor(replicaId: string, backend: DeviceRouterBackend, opts: {
|
|
1073
|
+
forwardTimeoutMs?: number;
|
|
1074
|
+
/** 收到转发来的调用时,在本副本执行(本地无该连接则返回 offline)。 */
|
|
1075
|
+
onLocalCall: (deviceId: string, req: DeviceInvokeRequest) => Promise<DeviceCallResult>;
|
|
1076
|
+
ttlSec?: number;
|
|
1077
|
+
});
|
|
1078
|
+
private get ttlSec();
|
|
1079
|
+
/** 订阅本副本的两个频道并启动路由续期。 */
|
|
1080
|
+
start(): Promise<void>;
|
|
1081
|
+
/** 本副本接受了某设备的连接:声明所有权。 */
|
|
1082
|
+
claim(deviceId: string): Promise<void>;
|
|
1083
|
+
/** 本副本失去某设备的连接:释放所有权。 */
|
|
1084
|
+
release(deviceId: string): Promise<void>;
|
|
1085
|
+
/** 某设备当前是否在**任一**副本上在线(reclaim 判定用,不能只看本副本)。 */
|
|
1086
|
+
isOnlineAnywhere(deviceId: string): Promise<boolean>;
|
|
1087
|
+
/**
|
|
1088
|
+
* 把调用转发给持有该设备的副本并等结果。
|
|
1089
|
+
* 无人持有 → null(调用方按 deviceOffline 处理)。
|
|
1090
|
+
*/
|
|
1091
|
+
forward(deviceId: string, req: DeviceInvokeRequest): Promise<DeviceCallResult | null>;
|
|
1092
|
+
close(): Promise<void>;
|
|
1093
|
+
/** correlationId 的进程内序号(与 replicaId 组合后全局唯一)。 */
|
|
1094
|
+
private static seq;
|
|
1095
|
+
private renewOwned;
|
|
1096
|
+
/** 作为持有者:执行本地调用并回执。 */
|
|
1097
|
+
private handleForwardedCall;
|
|
1098
|
+
/** 作为发起方:收到回执,唤醒等待者。 */
|
|
1099
|
+
private handleReply;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
839
1102
|
/**
|
|
840
1103
|
* DeviceHub:Node 宿主的设备通道(DeviceChannel 实现,对位 CF 的 DeviceSession DO)。
|
|
841
1104
|
*
|
|
@@ -852,6 +1115,8 @@ declare function configFromEnv(env?: NodeJS.ProcessEnv): ServerConfig;
|
|
|
852
1115
|
* 探活(isAlive + 周期 ping + terminate)踢半开死连接,避免调用一律吃 60s 超时。
|
|
853
1116
|
*/
|
|
854
1117
|
|
|
1118
|
+
/** router 回调本副本执行设备调用的签名。 */
|
|
1119
|
+
type DeviceLocalCall = (deviceId: string, req: DeviceInvokeRequest) => Promise<DeviceCallResult>;
|
|
855
1120
|
declare const DEVICE_WS_PATH = "/system/device/ws";
|
|
856
1121
|
declare class DeviceHub {
|
|
857
1122
|
private readonly store;
|
|
@@ -862,16 +1127,38 @@ declare class DeviceHub {
|
|
|
862
1127
|
private readonly connections;
|
|
863
1128
|
private readonly reclaimTimers;
|
|
864
1129
|
private heartbeat;
|
|
1130
|
+
/** 多副本路由;缺省(单副本)时所有跨副本逻辑短路,行为与之前完全一致。 */
|
|
1131
|
+
private router;
|
|
865
1132
|
constructor(opts: {
|
|
866
1133
|
heartbeatMs?: number;
|
|
867
1134
|
reclaimSec: number;
|
|
1135
|
+
/** 多副本部署的调用路由工厂;拿到 onLocalCall 回调后构造(避免循环依赖)。 */
|
|
1136
|
+
router?: (onLocalCall: DeviceLocalCall) => DeviceRouter;
|
|
868
1137
|
search?: MutableSearchIndex;
|
|
869
1138
|
store: StateStore;
|
|
870
1139
|
});
|
|
1140
|
+
/**
|
|
1141
|
+
* 启动多副本路由(订阅本副本频道 + 路由续期)。单副本时是 no-op。
|
|
1142
|
+
* 必须在开始服务前完成:订阅没建好时转发进来的调用会丢。
|
|
1143
|
+
*/
|
|
1144
|
+
startRouter(): Promise<void>;
|
|
871
1145
|
/** 挂到 http.Server 的 'upgrade' 事件(仅处理 DEVICE_WS_PATH,其余 404)。 */
|
|
872
1146
|
attach(server: http.Server): void;
|
|
873
|
-
/**
|
|
1147
|
+
/**
|
|
1148
|
+
* DeviceChannel.invoke:HTTP→WS 调用转发。
|
|
1149
|
+
*
|
|
1150
|
+
* 本副本持有该设备 → 直接走本地 socket(单副本部署恒走这条,零额外开销)。
|
|
1151
|
+
* 本地没有但配了 router → 问路由表并转发给持有者副本(socket 不可序列化,
|
|
1152
|
+
* 只能把调用送到 socket 所在进程)。都没有 → deviceOffline。
|
|
1153
|
+
*/
|
|
874
1154
|
invoke(deviceId: string, req: DeviceInvokeRequest): Promise<unknown>;
|
|
1155
|
+
/**
|
|
1156
|
+
* 只走本副本 socket 的调用执行。
|
|
1157
|
+
*
|
|
1158
|
+
* router 收到转发来的调用时回调这里 —— **不能**回调 `invoke`:本地连接刚断时
|
|
1159
|
+
* 那会再次查路由并转发,在两个副本间弹来弹去。这里没有连接就直接 offline。
|
|
1160
|
+
*/
|
|
1161
|
+
private invokeLocal;
|
|
875
1162
|
/** DeviceChannel.ws:Node 宿主的升级在 http 层处理,永不应命中此路由。 */
|
|
876
1163
|
ws(): Promise<Response>;
|
|
877
1164
|
/**
|
|
@@ -905,6 +1192,114 @@ declare class DeviceHub {
|
|
|
905
1192
|
|
|
906
1193
|
declare function createDataObjectStore(dataDir: string): ObjectStore;
|
|
907
1194
|
|
|
1195
|
+
/**
|
|
1196
|
+
* PgSearchIndex:postgres.js 驱动的 SearchIndex(ILIKE 子串检索)。
|
|
1197
|
+
*
|
|
1198
|
+
* 方言(SQL 文本、$n 占位符、ILIKE 检索)在 core 的 pgSearchDialect;
|
|
1199
|
+
* 本文件只吸收 postgres.js 的驱动差异:全异步、写入走 sql.begin() 事务、多行 VALUES
|
|
1200
|
+
* 批量插入(PG 无 D1 的 50 查询预算,故不实现 assertInsertBudget)。
|
|
1201
|
+
*
|
|
1202
|
+
* 不需要任何 PG 扩展:检索是纯 ILIKE,cursor_secret 用内置 gen_random_uuid()。
|
|
1203
|
+
* 因此连接角色无需建扩展权限(受限托管环境常不给),只要能建表。
|
|
1204
|
+
*/
|
|
1205
|
+
|
|
1206
|
+
/** Node 自托管宿主的 postgres.js SearchIndex。 */
|
|
1207
|
+
declare class PgSearchIndex extends SqlSearchIndex {
|
|
1208
|
+
constructor(sql: Sql);
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/**
|
|
1212
|
+
* PgStateStore:postgres.js 实现的 StateStore(自托管 Node 宿主的 PG 后端)。
|
|
1213
|
+
*
|
|
1214
|
+
* 与 SqliteStateStore 同形:单表 kv(key text primary key, value jsonb),值以
|
|
1215
|
+
* JSON 存取,强一致。list 用 key 范围扫描(>= prefix AND < successor(prefix)),
|
|
1216
|
+
* 不用 LIKE——key 里的路径段可含 '_'/'%',通配符转义是坑。
|
|
1217
|
+
*
|
|
1218
|
+
* 关键差异——排序 collation:PG 默认按 libc locale 排序,`<` 与 `ORDER BY` 的
|
|
1219
|
+
* 顺序会和 JS(UTF-16 code unit)/SQLite(UTF-8 字节)不一致,直接让前缀范围扫描和
|
|
1220
|
+
* cursor 分页错行漏行。故 key 列显式 `COLLATE "C"`(纯字节序),与 core
|
|
1221
|
+
* MemoryStateStore / SqliteStateStore 的 cursor 语义对齐。防御性地对返回行再做
|
|
1222
|
+
* startsWith 过滤。
|
|
1223
|
+
*/
|
|
1224
|
+
|
|
1225
|
+
declare class PgStateStore implements StateStore {
|
|
1226
|
+
private readonly sql;
|
|
1227
|
+
constructor(sql: Sql);
|
|
1228
|
+
/** 建表(幂等)。key COLLATE "C" 是字节序正确性的前提,不能省。 */
|
|
1229
|
+
ensureSchema(): Promise<void>;
|
|
1230
|
+
get(key: string): Promise<unknown | null>;
|
|
1231
|
+
getMany(keys: readonly string[]): Promise<Map<string, unknown>>;
|
|
1232
|
+
put(key: string, value: unknown): Promise<void>;
|
|
1233
|
+
putIfAbsent(key: string, value: unknown): Promise<boolean>;
|
|
1234
|
+
delete(key: string): Promise<void>;
|
|
1235
|
+
list(prefix: string, opts?: {
|
|
1236
|
+
cursor?: string;
|
|
1237
|
+
limit?: number;
|
|
1238
|
+
}): Promise<{
|
|
1239
|
+
cursor?: string;
|
|
1240
|
+
items: Array<{
|
|
1241
|
+
key: string;
|
|
1242
|
+
value: unknown;
|
|
1243
|
+
}>;
|
|
1244
|
+
}>;
|
|
1245
|
+
}
|
|
1246
|
+
|
|
1247
|
+
/**
|
|
1248
|
+
* DeviceRouterBackend 的 Redis(ioredis)实现。
|
|
1249
|
+
*
|
|
1250
|
+
* 两条连接是**必须**的:Redis 连接一旦进入 subscribe 模式就不能再发普通命令,
|
|
1251
|
+
* 而本副本既要订阅自己的频道、又要 GET/SET 路由并向别人 publish。
|
|
1252
|
+
*
|
|
1253
|
+
* clearRoute 用 Lua 做「值匹配才删」:设备刚从副本 A 迁到 B 时,A 的收尾不能删掉
|
|
1254
|
+
* B 刚写入的条目 —— 否则设备明明在线却被判离线。GET+DEL 两步做不到原子,故用脚本。
|
|
1255
|
+
*/
|
|
1256
|
+
|
|
1257
|
+
declare class RedisDeviceRouterBackend implements DeviceRouterBackend {
|
|
1258
|
+
/** 命令连接(GET/SET/DEL/PUBLISH)。 */
|
|
1259
|
+
private readonly commands;
|
|
1260
|
+
/** 订阅连接(进入 subscribe 模式后不能发普通命令)。 */
|
|
1261
|
+
private readonly subscriber;
|
|
1262
|
+
private readonly handlers;
|
|
1263
|
+
constructor(url: string);
|
|
1264
|
+
setRoute(deviceId: string, replicaId: string, ttlSec: number): Promise<void>;
|
|
1265
|
+
lookupRoute(deviceId: string): Promise<string | null>;
|
|
1266
|
+
clearRoute(deviceId: string, replicaId: string): Promise<void>;
|
|
1267
|
+
publish(channel: string, payload: string): Promise<void>;
|
|
1268
|
+
/** 就绪探测(/readyz):命令连接 PING 一次。断连时 ioredis 会抛/挂起,由调用方限时。 */
|
|
1269
|
+
ping(): Promise<void>;
|
|
1270
|
+
subscribe(channel: string, handler: (payload: string) => void): Promise<void>;
|
|
1271
|
+
close(): Promise<void>;
|
|
1272
|
+
}
|
|
1273
|
+
|
|
1274
|
+
/**
|
|
1275
|
+
* createTbServer:Node 宿主装配(对位 gateway/src/app.ts 的 depsFromEnv)。
|
|
1276
|
+
*
|
|
1277
|
+
* StateStore/SearchIndex 后端二选一:给 TB_DATABASE_URL 走 Postgres,
|
|
1278
|
+
* 否则走 dataDir 下的 SQLite。ObjectStore 始终是 fs。HTTP 用 @hono/node-server;
|
|
1279
|
+
* 引导在 start() 时直调宿主中立 runBootstrap(Node 有真实启动点,不需要 Workers 的
|
|
1280
|
+
* per-request once,故不注入 deps.ensureReady)。设备通道(DeviceHub)与 /ui 静态托管
|
|
1281
|
+
* 由后续装配点注入(deps.device / deps.assets)。
|
|
1282
|
+
*/
|
|
1283
|
+
|
|
1284
|
+
interface TbServer {
|
|
1285
|
+
app: ReturnType<typeof createTbApp>;
|
|
1286
|
+
close(): Promise<void>;
|
|
1287
|
+
deviceHub: DeviceHub;
|
|
1288
|
+
search: MutableSearchIndex;
|
|
1289
|
+
/** 引导(幂等)+ 孤儿设备回收排程 + 监听;返回实际端口(config.port=0 时由系统分配)。 */
|
|
1290
|
+
start(): Promise<{
|
|
1291
|
+
port: number;
|
|
1292
|
+
}>;
|
|
1293
|
+
/**
|
|
1294
|
+
* 进入 draining:/readyz 立即转 503(编排器摘流量),但继续服务既有与新到请求。
|
|
1295
|
+
* SIGTERM 处理器先调它、等一拍(TB_SHUTDOWN_DRAIN_SEC)再 close(),避免 k8s
|
|
1296
|
+
* endpoint 摘除传播期间仍被路由过来的请求吃闭门羹。幂等。
|
|
1297
|
+
*/
|
|
1298
|
+
startDraining(): void;
|
|
1299
|
+
state: StateStore;
|
|
1300
|
+
}
|
|
1301
|
+
declare function createTbServer(config: ServerConfig): TbServer;
|
|
1302
|
+
|
|
908
1303
|
/** Node 宿主的 better-sqlite3 FTS5/trigram SearchIndex。 */
|
|
909
1304
|
declare class SqliteSearchIndex extends SqlSearchIndex {
|
|
910
1305
|
private readonly db;
|
|
@@ -937,6 +1332,7 @@ declare class SqliteStateStore implements StateStore {
|
|
|
937
1332
|
get(key: string): Promise<unknown | null>;
|
|
938
1333
|
getMany(keys: readonly string[]): Promise<Map<string, unknown>>;
|
|
939
1334
|
put(key: string, value: unknown): Promise<void>;
|
|
1335
|
+
putIfAbsent(key: string, value: unknown): Promise<boolean>;
|
|
940
1336
|
delete(key: string): Promise<void>;
|
|
941
1337
|
list(prefix: string, opts?: {
|
|
942
1338
|
cursor?: string;
|
|
@@ -951,26 +1347,4 @@ declare class SqliteStateStore implements StateStore {
|
|
|
951
1347
|
close(): void;
|
|
952
1348
|
}
|
|
953
1349
|
|
|
954
|
-
|
|
955
|
-
* createTbServer:Node 宿主装配(对位 gateway/src/app.ts 的 depsFromEnv)。
|
|
956
|
-
*
|
|
957
|
-
* SQLite StateStore + fs ObjectStore + @hono/node-server;引导在 start() 时
|
|
958
|
-
* 直调宿主中立 runBootstrap(Node 有真实启动点,不需要 Workers 的 per-request once,
|
|
959
|
-
* 故不注入 deps.ensureReady)。设备通道(DeviceHub)与 /ui 静态托管由后续
|
|
960
|
-
* 装配点注入(deps.device / deps.assets)。
|
|
961
|
-
*/
|
|
962
|
-
|
|
963
|
-
interface TbServer {
|
|
964
|
-
app: ReturnType<typeof createTbApp>;
|
|
965
|
-
close(): Promise<void>;
|
|
966
|
-
deviceHub: DeviceHub;
|
|
967
|
-
search: SqliteSearchIndex;
|
|
968
|
-
/** 引导(幂等)+ 孤儿设备回收排程 + 监听;返回实际端口(config.port=0 时由系统分配)。 */
|
|
969
|
-
start(): Promise<{
|
|
970
|
-
port: number;
|
|
971
|
-
}>;
|
|
972
|
-
state: SqliteStateStore;
|
|
973
|
-
}
|
|
974
|
-
declare function createTbServer(config: ServerConfig): TbServer;
|
|
975
|
-
|
|
976
|
-
export { DEVICE_WS_PATH, DeviceHub, type ServerConfig, SqliteSearchIndex, SqliteStateStore, type TbServer, configFromEnv, createDataObjectStore, createTbServer };
|
|
1350
|
+
export { DEVICE_FORWARD_TIMEOUT_MS, DEVICE_ROUTE_TTL_SEC, DEVICE_WS_PATH, DeviceHub, type DeviceLocalCall, DeviceRouter, type DeviceRouterBackend, PgSearchIndex, PgStateStore, RedisDeviceRouterBackend, type ServerConfig, SqliteSearchIndex, SqliteStateStore, type TbServer, configFromEnv, createDataObjectStore, createTbServer };
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
import {
|
|
2
|
+
DEVICE_FORWARD_TIMEOUT_MS,
|
|
3
|
+
DEVICE_ROUTE_TTL_SEC,
|
|
2
4
|
DEVICE_WS_PATH,
|
|
3
5
|
DeviceHub,
|
|
6
|
+
DeviceRouter,
|
|
7
|
+
PgSearchIndex,
|
|
8
|
+
PgStateStore,
|
|
9
|
+
RedisDeviceRouterBackend,
|
|
4
10
|
SqliteSearchIndex,
|
|
5
11
|
SqliteStateStore,
|
|
6
12
|
configFromEnv,
|
|
7
13
|
createDataObjectStore,
|
|
8
14
|
createTbServer
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
15
|
+
} from "./chunk-Q7YHZ2SD.js";
|
|
16
|
+
import "./chunk-TPGTA43F.js";
|
|
11
17
|
import "./chunk-MLKGABMK.js";
|
|
12
18
|
export {
|
|
19
|
+
DEVICE_FORWARD_TIMEOUT_MS,
|
|
20
|
+
DEVICE_ROUTE_TTL_SEC,
|
|
13
21
|
DEVICE_WS_PATH,
|
|
14
22
|
DeviceHub,
|
|
23
|
+
DeviceRouter,
|
|
24
|
+
PgSearchIndex,
|
|
25
|
+
PgStateStore,
|
|
26
|
+
RedisDeviceRouterBackend,
|
|
15
27
|
SqliteSearchIndex,
|
|
16
28
|
SqliteStateStore,
|
|
17
29
|
configFromEnv,
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
createProviderPlugin,
|
|
3
3
|
requireApiKey,
|
|
4
4
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2DA2UI37.js";
|
|
6
6
|
import {
|
|
7
7
|
guardedFetch
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-SBJMMSPA.js";
|
|
9
|
+
import "./chunk-Q44CYUSI.js";
|
|
10
10
|
import {
|
|
11
11
|
TBError,
|
|
12
12
|
external_exports
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-TPGTA43F.js";
|
|
14
14
|
import "./chunk-MLKGABMK.js";
|
|
15
15
|
|
|
16
16
|
// ../plugins/src/ip2proxy/schema.ts
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
createProviderPlugin,
|
|
3
3
|
requireApiKey,
|
|
4
4
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2DA2UI37.js";
|
|
6
6
|
import {
|
|
7
7
|
guardedFetch
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-SBJMMSPA.js";
|
|
9
|
+
import "./chunk-Q44CYUSI.js";
|
|
10
10
|
import {
|
|
11
11
|
TBError,
|
|
12
12
|
external_exports
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-TPGTA43F.js";
|
|
14
14
|
import "./chunk-MLKGABMK.js";
|
|
15
15
|
|
|
16
16
|
// ../plugins/src/ipgeolocation_io/api.ts
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
createProviderPlugin,
|
|
3
3
|
requireApiKey,
|
|
4
4
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2DA2UI37.js";
|
|
6
6
|
import {
|
|
7
7
|
guardedFetch
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-SBJMMSPA.js";
|
|
9
|
+
import "./chunk-Q44CYUSI.js";
|
|
10
10
|
import {
|
|
11
11
|
TBError,
|
|
12
12
|
external_exports
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-TPGTA43F.js";
|
|
14
14
|
import "./chunk-MLKGABMK.js";
|
|
15
15
|
|
|
16
16
|
// ../plugins/src/ipqualityscore/api.ts
|
|
@@ -2,15 +2,15 @@ import {
|
|
|
2
2
|
createProviderPlugin,
|
|
3
3
|
requireApiKey,
|
|
4
4
|
upstreamError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2DA2UI37.js";
|
|
6
6
|
import {
|
|
7
7
|
guardedFetch
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import "./chunk-
|
|
8
|
+
} from "./chunk-SBJMMSPA.js";
|
|
9
|
+
import "./chunk-Q44CYUSI.js";
|
|
10
10
|
import {
|
|
11
11
|
TBError,
|
|
12
12
|
external_exports
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-TPGTA43F.js";
|
|
14
14
|
import "./chunk-MLKGABMK.js";
|
|
15
15
|
|
|
16
16
|
// ../plugins/src/jina_ai/api.ts
|