@zhin.js/core 1.1.34 → 1.1.35

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 (386) hide show
  1. package/README.md +121 -65
  2. package/lib/adapter.d.ts +72 -23
  3. package/lib/adapter.js +222 -62
  4. package/lib/built/adapter-process.d.ts +20 -5
  5. package/lib/built/adapter-process.js +54 -7
  6. package/lib/built/agent-preset.d.ts +1 -2
  7. package/lib/built/agent-preset.js +1 -2
  8. package/lib/built/ai-access.d.ts +36 -0
  9. package/lib/built/ai-access.js +46 -0
  10. package/lib/built/ai-outbound/adapter-access.d.ts +3 -0
  11. package/lib/built/ai-outbound/adapter-access.js +9 -0
  12. package/lib/built/ai-outbound/extensions/onebot-keyboard.d.ts +2 -0
  13. package/lib/built/ai-outbound/extensions/onebot-keyboard.js +67 -0
  14. package/lib/built/ai-outbound/extensions/qq-message.d.ts +3 -0
  15. package/lib/built/ai-outbound/extensions/qq-message.js +23 -0
  16. package/lib/built/ai-outbound/index.d.ts +9 -0
  17. package/lib/built/ai-outbound/index.js +9 -0
  18. package/lib/built/ai-outbound/parse.d.ts +13 -0
  19. package/lib/built/ai-outbound/parse.js +104 -0
  20. package/lib/built/ai-outbound/plain-mention-rewrite.d.ts +6 -0
  21. package/lib/built/ai-outbound/plain-mention-rewrite.js +37 -0
  22. package/lib/built/ai-outbound/prompt.d.ts +11 -0
  23. package/lib/built/ai-outbound/prompt.js +44 -0
  24. package/lib/built/ai-outbound/resolve.d.ts +4 -0
  25. package/lib/built/ai-outbound/resolve.js +64 -0
  26. package/lib/built/ai-outbound/structured-detect.d.ts +3 -0
  27. package/lib/built/ai-outbound/structured-detect.js +6 -0
  28. package/lib/built/ai-outbound/types.d.ts +58 -0
  29. package/lib/built/ai-outbound/types.js +5 -0
  30. package/lib/built/ai-trigger.d.ts +17 -17
  31. package/lib/built/ai-trigger.js +65 -70
  32. package/lib/built/authorization.d.ts +10 -0
  33. package/lib/built/authorization.js +76 -0
  34. package/lib/built/command.d.ts +9 -5
  35. package/lib/built/command.js +20 -7
  36. package/lib/built/common-adapter-tools.d.ts +35 -29
  37. package/lib/built/common-adapter-tools.js +83 -67
  38. package/lib/built/component.d.ts +1 -3
  39. package/lib/built/component.js +2 -4
  40. package/lib/built/config.d.ts +4 -5
  41. package/lib/built/config.js +26 -9
  42. package/lib/built/connect-endpoint-instance.d.ts +17 -0
  43. package/lib/built/connect-endpoint-instance.js +42 -0
  44. package/lib/built/database.d.ts +5 -3
  45. package/lib/built/database.js +10 -4
  46. package/lib/built/dispatcher.d.ts +10 -8
  47. package/lib/built/dispatcher.js +31 -9
  48. package/lib/built/endpoint-commands.d.ts +3 -0
  49. package/lib/built/endpoint-commands.js +99 -0
  50. package/lib/built/endpoint-lifecycle-service.d.ts +28 -0
  51. package/lib/built/endpoint-lifecycle-service.js +242 -0
  52. package/lib/built/endpoint-lifecycle.d.ts +27 -0
  53. package/lib/built/endpoint-lifecycle.js +36 -0
  54. package/lib/built/endpoint-manager.d.ts +34 -0
  55. package/lib/built/endpoint-manager.js +1 -0
  56. package/lib/built/generated-qrcode.d.ts +24 -0
  57. package/lib/built/generated-qrcode.js +45 -0
  58. package/lib/built/generic-segment-mapper.d.ts +4 -0
  59. package/lib/built/generic-segment-mapper.js +190 -0
  60. package/lib/built/html-renderer-loader.d.ts +13 -0
  61. package/lib/built/html-renderer-loader.js +33 -0
  62. package/lib/built/html-segment-fallback.d.ts +2 -2
  63. package/lib/built/html-segment-fallback.js +0 -1
  64. package/lib/built/html-to-text.d.ts +0 -1
  65. package/lib/built/html-to-text.js +15 -15
  66. package/lib/built/inbound-pipeline.d.ts +37 -0
  67. package/lib/built/inbound-pipeline.js +63 -0
  68. package/lib/built/inbound-runner.d.ts +0 -1
  69. package/lib/built/inbound-runner.js +0 -3
  70. package/lib/built/interactive-segment-contract.d.ts +6 -0
  71. package/lib/built/interactive-segment-contract.js +9 -0
  72. package/lib/built/interactive-segments/action.d.ts +17 -0
  73. package/lib/built/interactive-segments/action.js +69 -0
  74. package/lib/built/interactive-segments/button-spec.d.ts +10 -0
  75. package/lib/built/interactive-segments/button-spec.js +21 -0
  76. package/lib/built/interactive-segments/fallback-store.d.ts +29 -0
  77. package/lib/built/interactive-segments/fallback-store.js +63 -0
  78. package/lib/built/interactive-segments/handlers.d.ts +16 -0
  79. package/lib/built/interactive-segments/handlers.js +74 -0
  80. package/lib/built/interactive-segments/index.d.ts +8 -0
  81. package/lib/built/interactive-segments/index.js +8 -0
  82. package/lib/built/interactive-segments/keyboard-segment.d.ts +11 -0
  83. package/lib/built/interactive-segments/keyboard-segment.js +12 -0
  84. package/lib/built/interactive-segments/onebot-keyboard.d.ts +7 -0
  85. package/lib/built/interactive-segments/onebot-keyboard.js +51 -0
  86. package/lib/built/interactive-segments/resolve.d.ts +15 -0
  87. package/lib/built/interactive-segments/resolve.js +110 -0
  88. package/lib/built/interactive-segments/types.d.ts +50 -0
  89. package/lib/built/interactive-segments/types.js +9 -0
  90. package/lib/built/introspection-format.d.ts +10 -0
  91. package/lib/built/introspection-format.js +28 -0
  92. package/lib/built/login-assist.d.ts +43 -9
  93. package/lib/built/login-assist.js +113 -11
  94. package/lib/built/management-command-guard.d.ts +15 -0
  95. package/lib/built/management-command-guard.js +25 -0
  96. package/lib/built/message-enrich.d.ts +38 -0
  97. package/lib/built/message-enrich.js +75 -0
  98. package/lib/built/message-filter.d.ts +4 -5
  99. package/lib/built/message-filter.js +5 -7
  100. package/lib/built/optional-peer-import.d.ts +3 -0
  101. package/lib/built/optional-peer-import.js +33 -0
  102. package/lib/built/outbound-media-contract.d.ts +22 -0
  103. package/lib/built/outbound-media-contract.js +10 -0
  104. package/lib/built/outbound-media-utils.d.ts +9 -0
  105. package/lib/built/outbound-media-utils.js +62 -0
  106. package/lib/built/permission.d.ts +3 -7
  107. package/lib/built/permission.js +39 -52
  108. package/lib/built/permit-check.d.ts +7 -0
  109. package/lib/built/permit-check.js +35 -0
  110. package/lib/built/permit-parse.d.ts +16 -0
  111. package/lib/built/permit-parse.js +32 -0
  112. package/lib/built/platform-permit.d.ts +20 -0
  113. package/lib/built/platform-permit.js +91 -0
  114. package/lib/built/queue-im-field-contract.d.ts +7 -2
  115. package/lib/built/queue-im-field-contract.js +13 -4
  116. package/lib/built/rich-segments/adapter-policies.d.ts +9 -0
  117. package/lib/built/rich-segments/adapter-policies.js +27 -0
  118. package/lib/built/rich-segments/base.d.ts +11 -0
  119. package/lib/built/rich-segments/base.js +24 -0
  120. package/lib/built/rich-segments/builtins.d.ts +4 -0
  121. package/lib/built/rich-segments/builtins.js +40 -0
  122. package/lib/built/rich-segments/capabilities.d.ts +6 -0
  123. package/lib/built/rich-segments/capabilities.js +38 -0
  124. package/lib/built/rich-segments/html-segment.d.ts +15 -0
  125. package/lib/built/rich-segments/html-segment.js +62 -0
  126. package/lib/built/rich-segments/index.d.ts +13 -0
  127. package/lib/built/rich-segments/index.js +13 -0
  128. package/lib/built/rich-segments/markdown-segment.d.ts +14 -0
  129. package/lib/built/rich-segments/markdown-segment.js +58 -0
  130. package/lib/built/rich-segments/markdown-to-text.d.ts +3 -0
  131. package/lib/built/rich-segments/markdown-to-text.js +27 -0
  132. package/lib/built/rich-segments/qrcode-segment.d.ts +18 -0
  133. package/lib/built/rich-segments/qrcode-segment.js +73 -0
  134. package/lib/built/rich-segments/registry.d.ts +16 -0
  135. package/lib/built/rich-segments/registry.js +52 -0
  136. package/lib/built/rich-segments/resolve.d.ts +5 -0
  137. package/lib/built/rich-segments/resolve.js +87 -0
  138. package/lib/built/rich-segments/tts-segment.d.ts +13 -0
  139. package/lib/built/rich-segments/tts-segment.js +51 -0
  140. package/lib/built/rich-segments/types.d.ts +79 -0
  141. package/lib/built/rich-segments/types.js +17 -0
  142. package/lib/built/roles.d.ts +4 -5
  143. package/lib/built/roles.js +4 -5
  144. package/lib/built/runtime-io.d.ts +0 -1
  145. package/lib/built/runtime-io.js +0 -1
  146. package/lib/built/schedule.d.ts +54 -0
  147. package/lib/built/schedule.js +112 -0
  148. package/lib/built/schema-endpoint-manager.d.ts +17 -0
  149. package/lib/built/schema-endpoint-manager.js +73 -0
  150. package/lib/built/schema-feature.d.ts +0 -1
  151. package/lib/built/schema-feature.js +1 -3
  152. package/lib/built/segment-contract/assert.d.ts +7 -0
  153. package/lib/built/segment-contract/assert.js +39 -0
  154. package/lib/built/segment-contract/delivery.d.ts +5 -0
  155. package/lib/built/segment-contract/delivery.js +40 -0
  156. package/lib/built/segment-contract/image.d.ts +5 -0
  157. package/lib/built/segment-contract/image.js +10 -0
  158. package/lib/built/segment-contract/index.d.ts +10 -0
  159. package/lib/built/segment-contract/index.js +9 -0
  160. package/lib/built/segment-contract/json-schema.d.ts +28 -0
  161. package/lib/built/segment-contract/json-schema.js +128 -0
  162. package/lib/built/segment-contract/media.d.ts +12 -0
  163. package/lib/built/segment-contract/media.js +22 -0
  164. package/lib/built/segment-contract/mention.d.ts +10 -0
  165. package/lib/built/segment-contract/mention.js +26 -0
  166. package/lib/built/segment-contract/preview.d.ts +3 -0
  167. package/lib/built/segment-contract/preview.js +159 -0
  168. package/lib/built/segment-contract/text.d.ts +7 -0
  169. package/lib/built/segment-contract/text.js +34 -0
  170. package/lib/built/segment-contract/types.d.ts +58 -0
  171. package/lib/built/segment-contract/types.js +1 -0
  172. package/lib/built/segment-contract/validate.d.ts +229 -0
  173. package/lib/built/segment-contract/validate.js +174 -0
  174. package/lib/built/skill.d.ts +0 -1
  175. package/lib/built/skill.js +0 -1
  176. package/lib/built/speech-loader.d.ts +14 -0
  177. package/lib/built/speech-loader.js +32 -0
  178. package/lib/built/tool.d.ts +14 -13
  179. package/lib/built/tool.js +30 -25
  180. package/lib/built/user-interaction.d.ts +30 -0
  181. package/lib/built/user-interaction.js +248 -0
  182. package/lib/command.d.ts +19 -11
  183. package/lib/command.js +42 -11
  184. package/lib/component.d.ts +0 -1
  185. package/lib/component.js +30 -14
  186. package/lib/endpoint-capabilities.d.ts +46 -0
  187. package/lib/endpoint-capabilities.js +55 -0
  188. package/lib/endpoint.d.ts +19 -0
  189. package/lib/endpoint.js +3 -0
  190. package/lib/errors.d.ts +2 -3
  191. package/lib/errors.js +4 -5
  192. package/lib/feature/adapter.d.ts +2 -0
  193. package/lib/feature/adapter.js +2 -0
  194. package/lib/feature/command.d.ts +2 -0
  195. package/lib/feature/command.js +2 -0
  196. package/lib/feature/component.d.ts +2 -0
  197. package/lib/feature/component.js +2 -0
  198. package/lib/feature/handler.d.ts +52 -0
  199. package/lib/feature/handler.js +26 -0
  200. package/lib/feature/middleware.d.ts +2 -0
  201. package/lib/feature/middleware.js +2 -0
  202. package/lib/host-plugin-registry.d.ts +8 -0
  203. package/lib/host-plugin-registry.js +12 -0
  204. package/lib/im-scene.d.ts +29 -0
  205. package/lib/im-scene.js +75 -0
  206. package/lib/im-session-id.d.ts +39 -0
  207. package/lib/im-session-id.js +47 -0
  208. package/lib/index.d.ts +59 -25
  209. package/lib/index.js +53 -31
  210. package/lib/jsx-dev-runtime.d.ts +0 -1
  211. package/lib/jsx-dev-runtime.js +0 -1
  212. package/lib/jsx-runtime.d.ts +1 -1
  213. package/lib/jsx-runtime.js +0 -1
  214. package/lib/jsx.d.ts +19 -22
  215. package/lib/jsx.js +0 -1
  216. package/lib/message.d.ts +16 -10
  217. package/lib/message.js +16 -13
  218. package/lib/models/system-log.d.ts +0 -1
  219. package/lib/models/system-log.js +0 -1
  220. package/lib/models/user.d.ts +0 -1
  221. package/lib/models/user.js +0 -1
  222. package/lib/notice.d.ts +16 -59
  223. package/lib/notice.js +1 -4
  224. package/lib/plugin-context.d.ts +27 -0
  225. package/lib/plugin-context.js +64 -0
  226. package/lib/plugin-runtime/im/contracts.d.ts +191 -0
  227. package/lib/plugin-runtime/im/contracts.js +169 -0
  228. package/lib/plugin-runtime/im/im-runtime.d.ts +177 -0
  229. package/lib/plugin-runtime/im/im-runtime.js +1204 -0
  230. package/lib/plugin-runtime/im/index.d.ts +9 -0
  231. package/lib/plugin-runtime/im/index.js +9 -0
  232. package/lib/plugin-runtime/im/interactive.d.ts +26 -0
  233. package/lib/plugin-runtime/im/interactive.js +46 -0
  234. package/lib/plugin-runtime/im/login-assist-host.d.ts +6 -0
  235. package/lib/plugin-runtime/im/login-assist-host.js +6 -0
  236. package/lib/plugin-runtime/im/message-bus.d.ts +38 -0
  237. package/lib/plugin-runtime/im/message-bus.js +40 -0
  238. package/lib/plugin-runtime/im/message-dispatcher.d.ts +18 -0
  239. package/lib/plugin-runtime/im/message-dispatcher.js +107 -0
  240. package/lib/plugin-runtime/im/outbound-renderer.d.ts +7 -0
  241. package/lib/plugin-runtime/im/outbound-renderer.js +70 -0
  242. package/lib/plugin-runtime/im/outbound-segments.d.ts +72 -0
  243. package/lib/plugin-runtime/im/outbound-segments.js +220 -0
  244. package/lib/plugin-runtime/im/public-api.d.ts +6 -0
  245. package/lib/plugin-runtime/im/public-api.js +6 -0
  246. package/lib/plugin-runtime/im/service-tokens.d.ts +18 -0
  247. package/lib/plugin-runtime/im/service-tokens.js +13 -0
  248. package/lib/plugin.d.ts +34 -24
  249. package/lib/plugin.js +119 -224
  250. package/lib/request.d.ts +17 -61
  251. package/lib/request.js +0 -4
  252. package/lib/{prompt.d.ts → schema-interaction.d.ts} +6 -7
  253. package/lib/{prompt.js → schema-interaction.js} +20 -17
  254. package/lib/side-event/base.d.ts +52 -0
  255. package/lib/side-event/base.js +30 -0
  256. package/lib/side-event/dispatch.d.ts +15 -0
  257. package/lib/side-event/dispatch.js +140 -0
  258. package/lib/side-event/index.d.ts +4 -0
  259. package/lib/side-event/index.js +4 -0
  260. package/lib/side-event/normalize.d.ts +42 -0
  261. package/lib/side-event/normalize.js +121 -0
  262. package/lib/side-event/types.d.ts +23 -0
  263. package/lib/side-event/types.js +55 -0
  264. package/lib/system-event.d.ts +15 -0
  265. package/lib/system-event.js +7 -0
  266. package/lib/tool-zod.d.ts +18 -3
  267. package/lib/tool-zod.js +140 -54
  268. package/lib/types.d.ts +44 -95
  269. package/lib/types.js +0 -1
  270. package/lib/utils.d.ts +61 -13
  271. package/lib/utils.js +66 -25
  272. package/package.json +98 -10
  273. package/lib/adapter.d.ts.map +0 -1
  274. package/lib/adapter.js.map +0 -1
  275. package/lib/agent-prompt.d.ts +0 -37
  276. package/lib/agent-prompt.d.ts.map +0 -1
  277. package/lib/agent-prompt.js +0 -2
  278. package/lib/agent-prompt.js.map +0 -1
  279. package/lib/bot.d.ts +0 -38
  280. package/lib/bot.d.ts.map +0 -1
  281. package/lib/bot.js +0 -2
  282. package/lib/bot.js.map +0 -1
  283. package/lib/built/adapter-process.d.ts.map +0 -1
  284. package/lib/built/adapter-process.js.map +0 -1
  285. package/lib/built/agent-preset.d.ts.map +0 -1
  286. package/lib/built/agent-preset.js.map +0 -1
  287. package/lib/built/ai-trigger.d.ts.map +0 -1
  288. package/lib/built/ai-trigger.js.map +0 -1
  289. package/lib/built/command.d.ts.map +0 -1
  290. package/lib/built/command.js.map +0 -1
  291. package/lib/built/common-adapter-tools.d.ts.map +0 -1
  292. package/lib/built/common-adapter-tools.js.map +0 -1
  293. package/lib/built/component.d.ts.map +0 -1
  294. package/lib/built/component.js.map +0 -1
  295. package/lib/built/config.d.ts.map +0 -1
  296. package/lib/built/config.js.map +0 -1
  297. package/lib/built/cron.d.ts +0 -75
  298. package/lib/built/cron.d.ts.map +0 -1
  299. package/lib/built/cron.js +0 -122
  300. package/lib/built/cron.js.map +0 -1
  301. package/lib/built/database.d.ts.map +0 -1
  302. package/lib/built/database.js.map +0 -1
  303. package/lib/built/dispatcher.d.ts.map +0 -1
  304. package/lib/built/dispatcher.js.map +0 -1
  305. package/lib/built/html-segment-fallback.d.ts.map +0 -1
  306. package/lib/built/html-segment-fallback.js.map +0 -1
  307. package/lib/built/html-to-text.d.ts.map +0 -1
  308. package/lib/built/html-to-text.js.map +0 -1
  309. package/lib/built/inbound-runner.d.ts.map +0 -1
  310. package/lib/built/inbound-runner.js.map +0 -1
  311. package/lib/built/login-assist.d.ts.map +0 -1
  312. package/lib/built/login-assist.js.map +0 -1
  313. package/lib/built/mcp-mesh-registrar.d.ts +0 -9
  314. package/lib/built/mcp-mesh-registrar.d.ts.map +0 -1
  315. package/lib/built/mcp-mesh-registrar.js +0 -17
  316. package/lib/built/mcp-mesh-registrar.js.map +0 -1
  317. package/lib/built/message-filter.d.ts.map +0 -1
  318. package/lib/built/message-filter.js.map +0 -1
  319. package/lib/built/permission.d.ts.map +0 -1
  320. package/lib/built/permission.js.map +0 -1
  321. package/lib/built/prepend-quote-context.d.ts +0 -35
  322. package/lib/built/prepend-quote-context.d.ts.map +0 -1
  323. package/lib/built/prepend-quote-context.js +0 -131
  324. package/lib/built/prepend-quote-context.js.map +0 -1
  325. package/lib/built/queue-im-field-contract.d.ts.map +0 -1
  326. package/lib/built/queue-im-field-contract.js.map +0 -1
  327. package/lib/built/roles.d.ts.map +0 -1
  328. package/lib/built/roles.js.map +0 -1
  329. package/lib/built/runtime-io.d.ts.map +0 -1
  330. package/lib/built/runtime-io.js.map +0 -1
  331. package/lib/built/schema-feature.d.ts.map +0 -1
  332. package/lib/built/schema-feature.js.map +0 -1
  333. package/lib/built/skill.d.ts.map +0 -1
  334. package/lib/built/skill.js.map +0 -1
  335. package/lib/built/tool.d.ts.map +0 -1
  336. package/lib/built/tool.js.map +0 -1
  337. package/lib/command.d.ts.map +0 -1
  338. package/lib/command.js.map +0 -1
  339. package/lib/component.d.ts.map +0 -1
  340. package/lib/component.js.map +0 -1
  341. package/lib/errors.d.ts.map +0 -1
  342. package/lib/errors.js.map +0 -1
  343. package/lib/index.d.ts.map +0 -1
  344. package/lib/index.js.map +0 -1
  345. package/lib/jsx-dev-runtime.d.ts.map +0 -1
  346. package/lib/jsx-dev-runtime.js.map +0 -1
  347. package/lib/jsx-runtime.d.ts.map +0 -1
  348. package/lib/jsx-runtime.js.map +0 -1
  349. package/lib/jsx.d.ts.map +0 -1
  350. package/lib/jsx.js.map +0 -1
  351. package/lib/message-quote.d.ts +0 -11
  352. package/lib/message-quote.d.ts.map +0 -1
  353. package/lib/message-quote.js +0 -91
  354. package/lib/message-quote.js.map +0 -1
  355. package/lib/message.d.ts.map +0 -1
  356. package/lib/message.js.map +0 -1
  357. package/lib/models/system-log.d.ts.map +0 -1
  358. package/lib/models/system-log.js.map +0 -1
  359. package/lib/models/user.d.ts.map +0 -1
  360. package/lib/models/user.js.map +0 -1
  361. package/lib/notice.d.ts.map +0 -1
  362. package/lib/notice.js.map +0 -1
  363. package/lib/plugin.d.ts.map +0 -1
  364. package/lib/plugin.js.map +0 -1
  365. package/lib/prompt.d.ts.map +0 -1
  366. package/lib/prompt.js.map +0 -1
  367. package/lib/request.d.ts.map +0 -1
  368. package/lib/request.js.map +0 -1
  369. package/lib/scheduler/scheduler.d.ts +0 -49
  370. package/lib/scheduler/scheduler.d.ts.map +0 -1
  371. package/lib/scheduler/scheduler.js +0 -352
  372. package/lib/scheduler/scheduler.js.map +0 -1
  373. package/lib/scheduler/types.d.ts +0 -71
  374. package/lib/scheduler/types.d.ts.map +0 -1
  375. package/lib/scheduler/types.js +0 -8
  376. package/lib/scheduler/types.js.map +0 -1
  377. package/lib/tool-zod.d.ts.map +0 -1
  378. package/lib/tool-zod.js.map +0 -1
  379. package/lib/types-generator.d.ts +0 -6
  380. package/lib/types-generator.d.ts.map +0 -1
  381. package/lib/types-generator.js +0 -72
  382. package/lib/types-generator.js.map +0 -1
  383. package/lib/types.d.ts.map +0 -1
  384. package/lib/types.js.map +0 -1
  385. package/lib/utils.d.ts.map +0 -1
  386. package/lib/utils.js.map +0 -1
@@ -27,7 +27,7 @@
27
27
  * 默认路由为 exclusive(命令与 AI 互斥);需双轨时请显式 dualRoute.mode: 'dual'。
28
28
  */
29
29
  import { AsyncLocalStorage } from 'node:async_hooks';
30
- import { getPlugin } from '../plugin.js';
30
+ import { isActionMessage } from './interactive-segments/action.js';
31
31
  /** Dispatcher 管理的「会话回复」异步上下文,供 `before.sendMessage` 内读取(与 Adapter.renderSendMessage 同链) */
32
32
  const outboundReplyAls = new AsyncLocalStorage();
33
33
  export function getOutboundReplyStore() {
@@ -52,6 +52,7 @@ export function createMessageDispatcher(options) {
52
52
  const guardrails = [];
53
53
  /** mounted 前注册的润色,在 mounted 时挂到 root.before.sendMessage */
54
54
  const pendingOutboundPolish = [];
55
+ const flushedOutboundPolish = new Map();
55
56
  let aiHandler = null;
56
57
  let aiTriggerMatcher = null;
57
58
  let groupPassiveContextHandler = null;
@@ -193,18 +194,34 @@ export function createMessageDispatcher(options) {
193
194
  for (const mw of pendingOutboundPolish) {
194
195
  const fn = wrapPolishAsBeforeSend(mw);
195
196
  root.on('before.sendMessage', fn);
197
+ flushedOutboundPolish.set(mw, fn);
196
198
  }
197
199
  pendingOutboundPolish.length = 0;
198
200
  }
199
201
  async function replyWithPolishInternal(message, source, content, options) {
200
202
  const quote = options?.quote;
203
+ if (!message.$reply) {
204
+ throw new Error(`Cannot reply: endpoint ${message.$endpoint} on adapter ${String(message.$adapter)} has no outbound capability`);
205
+ }
201
206
  if (!rootPlugin) {
202
207
  return quote ? message.$reply(content, quote) : message.$reply(content);
203
208
  }
204
- return outboundReplyAls.run({ message, source }, () => quote ? message.$reply(content, quote) : message.$reply(content));
209
+ return outboundReplyAls.run({
210
+ message,
211
+ source,
212
+ trigger: 'inbound',
213
+ }, () => quote ? message.$reply(content, quote) : message.$reply(content));
214
+ }
215
+ async function runWithOutboundPolish(store, fn) {
216
+ return outboundReplyAls.run({
217
+ message: store.message,
218
+ source: store.source ?? 'proactive',
219
+ trigger: store.trigger,
220
+ proactiveSource: store.proactiveSource,
221
+ }, fn);
205
222
  }
206
223
  async function maybeRecordGroupPassiveContext(message) {
207
- if (!groupPassiveContextHandler)
224
+ if (!groupPassiveContextHandler || isActionMessage(message))
208
225
  return;
209
226
  const scope = message.$channel?.type;
210
227
  if (scope !== 'group' && scope !== 'channel')
@@ -222,7 +239,7 @@ export function createMessageDispatcher(options) {
222
239
  const commandService = rootPlugin.inject('command');
223
240
  if (!commandService)
224
241
  return;
225
- const response = await commandService.handle(message, rootPlugin);
242
+ const response = await commandService.handle(message, options?.permissionHost ?? null);
226
243
  if (response !== undefined && response !== null) {
227
244
  await replyWithPolishInternal(message, 'command', response);
228
245
  }
@@ -321,11 +338,19 @@ export function createMessageDispatcher(options) {
321
338
  const i = pendingOutboundPolish.indexOf(handler);
322
339
  if (i !== -1)
323
340
  pendingOutboundPolish.splice(i, 1);
341
+ const flushed = flushedOutboundPolish.get(handler);
342
+ if (flushed && rootPlugin) {
343
+ rootPlugin.root.off('before.sendMessage', flushed);
344
+ flushedOutboundPolish.delete(handler);
345
+ }
324
346
  };
325
347
  },
326
348
  replyWithPolish(message, source, content, options) {
327
349
  return replyWithPolishInternal(message, source, content, options);
328
350
  },
351
+ runWithOutboundPolish(store, fn) {
352
+ return runWithOutboundPolish(store, fn);
353
+ },
329
354
  matchCommand(message) {
330
355
  return matchCommandInternal(message);
331
356
  },
@@ -344,18 +369,15 @@ export function createMessageDispatcher(options) {
344
369
  },
345
370
  extensions: {
346
371
  addGuardrail(guardrail) {
347
- const plugin = getPlugin();
348
372
  const dispose = service.addGuardrail(guardrail);
349
- plugin.onDispose(dispose);
373
+ rootPlugin?.onDispose(dispose);
350
374
  return dispose;
351
375
  },
352
376
  addOutboundPolish(handler) {
353
- const plugin = getPlugin();
354
377
  const dispose = service.addOutboundPolish(handler);
355
- plugin.onDispose(dispose);
378
+ rootPlugin?.onDispose(dispose);
356
379
  return dispose;
357
380
  },
358
381
  },
359
382
  };
360
383
  }
361
- //# sourceMappingURL=dispatcher.js.map
@@ -0,0 +1,3 @@
1
+ import type { CommandFeature } from './command.js';
2
+ import type { Plugin } from '../plugin.js';
3
+ export declare function registerEndpointManagementCommands(plugin: Plugin, commandService: CommandFeature): () => void;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * IM Endpoint 管理与 /endpoints 内省命令(@zhin.js/core)
3
+ */
4
+ import { Adapter } from '../adapter.js';
5
+ import { MessageCommand } from '../command.js';
6
+ import { MANAGEMENT_OPERATOR_PERMIT } from './management-command-guard.js';
7
+ import { createEndpointLifecycleService } from './endpoint-lifecycle-service.js';
8
+ import { endpointHelpText, formatEndpointsList } from './introspection-format.js';
9
+ function collectRuntimeEndpoints(root) {
10
+ const rows = [];
11
+ for (const adapterName of root.adapters) {
12
+ const adapter = root.inject(adapterName);
13
+ if (!(adapter instanceof Adapter))
14
+ continue;
15
+ for (const [endpointKey, endpoint] of adapter.endpoints.entries()) {
16
+ rows.push({
17
+ adapter: String(adapterName),
18
+ name: endpointKey,
19
+ online: !!endpoint.$connected,
20
+ });
21
+ }
22
+ }
23
+ return rows;
24
+ }
25
+ export function registerEndpointManagementCommands(plugin, commandService) {
26
+ const root = plugin.root;
27
+ const disposers = [];
28
+ const service = () => createEndpointLifecycleService(root);
29
+ const register = (pattern, desc, handler) => {
30
+ const cmd = new MessageCommand(pattern)
31
+ .desc(desc)
32
+ .permit(MANAGEMENT_OPERATOR_PERMIT)
33
+ .action(async (message, match) => {
34
+ try {
35
+ return await handler(message, match);
36
+ }
37
+ catch (err) {
38
+ return `❌ ${err instanceof Error ? err.message : String(err)}`;
39
+ }
40
+ });
41
+ commandService.add(cmd, plugin.name);
42
+ disposers.push(() => commandService.remove(cmd));
43
+ };
44
+ register('/endpoint help', 'Endpoint 管理帮助', () => endpointHelpText());
45
+ register('/endpoint add [adapter:word]', '添加 Endpoint', async (message, match) => {
46
+ const adapterKey = typeof match?.params?.adapter === 'string' ? match.params.adapter.trim() : '';
47
+ if (!adapterKey) {
48
+ const list = service().listProvisionableAdapters();
49
+ if (list.length === 0) {
50
+ return '当前没有支持运行时添加的适配器(需 EndpointManager 或 endpointConfigSchema)。';
51
+ }
52
+ return [
53
+ '可用适配器:',
54
+ ...list.map((a) => ` • ${a} — /endpoint add ${a}`),
55
+ ].join('\n');
56
+ }
57
+ const result = await service().add(adapterKey, message);
58
+ return result.message;
59
+ });
60
+ register('/endpoint remove <adapter:word> <name:word>', '从配置移除 Endpoint', async (_message, match) => {
61
+ const adapterKey = String(match?.params?.adapter ?? '');
62
+ const name = String(match?.params?.name ?? '');
63
+ const result = await service().remove(adapterKey, name);
64
+ return result.message;
65
+ });
66
+ register('/endpoint edit <adapter:word> <name:word>', '编辑 Endpoint 配置', async (message, match) => {
67
+ const adapterKey = String(match?.params?.adapter ?? '');
68
+ const name = String(match?.params?.name ?? '');
69
+ const result = await service().edit(adapterKey, name, message);
70
+ return result.message;
71
+ });
72
+ register('/endpoint start <adapter:word> <name:word>', '连接 Endpoint', async (message, match) => {
73
+ const adapterKey = String(match?.params?.adapter ?? '');
74
+ const name = String(match?.params?.name ?? '');
75
+ const result = await service().start(adapterKey, name, message);
76
+ return result.message;
77
+ });
78
+ register('/endpoint stop <adapter:word> <name:word>', '断开 Endpoint(保留配置)', async (_message, match) => {
79
+ const adapterKey = String(match?.params?.adapter ?? '');
80
+ const name = String(match?.params?.name ?? '');
81
+ const result = await service().stop(adapterKey, name);
82
+ return result.message;
83
+ });
84
+ register('/endpoint cancel', '取消进行中的 Endpoint 添加/绑定', () => {
85
+ if (!service().cancelProvision()) {
86
+ return '当前没有进行中的 Endpoint 绑定流程。';
87
+ }
88
+ return '已取消 Endpoint 绑定流程。';
89
+ });
90
+ register('/endpoint sync', '将内存中的 endpoint 配置写回 zhin.config', async () => {
91
+ const result = await service().syncToDisk();
92
+ return result.message;
93
+ });
94
+ register('/endpoints', '列出各适配器下的 Endpoint 及在线状态', () => formatEndpointsList(collectRuntimeEndpoints(root)));
95
+ return () => {
96
+ for (const d of disposers)
97
+ d();
98
+ };
99
+ }
@@ -0,0 +1,28 @@
1
+ import { Adapter } from '../adapter.js';
2
+ import type { Endpoint } from '../endpoint.js';
3
+ import type { Message } from '../message.js';
4
+ import type { Plugin } from '../plugin.js';
5
+ import type { EndpointConfigRecord, EndpointManager } from './endpoint-manager.js';
6
+ export interface EndpointLifecycleResult {
7
+ message: string;
8
+ config?: EndpointConfigRecord;
9
+ }
10
+ export declare class EndpointLifecycleService {
11
+ private readonly root;
12
+ constructor(root: Plugin);
13
+ resolveAdapter(adapterKey: string): Adapter;
14
+ resolveManager(adapterKey: string): EndpointManager;
15
+ listProvisionableAdapters(): string[];
16
+ persistEndpoints(endpoints: EndpointConfigRecord[]): Promise<void>;
17
+ /** 将内存中的 endpoints 写回 zhin.config(修复运行时与磁盘不一致) */
18
+ syncToDisk(): Promise<EndpointLifecycleResult>;
19
+ connectConfig(adapter: Adapter, config: EndpointConfigRecord): Promise<Endpoint>;
20
+ disconnectRuntime(adapter: Adapter, name: string): Promise<boolean>;
21
+ add(adapterKey: string, message: Message, initialReply?: string): Promise<EndpointLifecycleResult>;
22
+ edit(adapterKey: string, name: string, message: Message): Promise<EndpointLifecycleResult>;
23
+ remove(adapterKey: string, name: string): Promise<EndpointLifecycleResult>;
24
+ start(adapterKey: string, name: string, message: Message): Promise<EndpointLifecycleResult>;
25
+ stop(adapterKey: string, name: string): Promise<EndpointLifecycleResult>;
26
+ cancelProvision(): boolean;
27
+ }
28
+ export declare function createEndpointLifecycleService(root: Plugin): EndpointLifecycleService;
@@ -0,0 +1,242 @@
1
+ import { formatDisplayPath } from '@zhin.js/logger';
2
+ import { Adapter } from '../adapter.js';
3
+ import { segment } from '../utils.js';
4
+ import { connectEndpointInstance, disconnectEndpointInstance } from './connect-endpoint-instance.js';
5
+ import { adapterSupportsProvision, resolveEndpointManager } from './schema-endpoint-manager.js';
6
+ function getConfigService(root) {
7
+ const configService = root.inject('config');
8
+ if (!configService?.primaryFile) {
9
+ throw new Error('配置服务不可用');
10
+ }
11
+ const loader = configService.configs.get(configService.primaryFile);
12
+ if (!loader) {
13
+ throw new Error('配置文件未加载');
14
+ }
15
+ return configService;
16
+ }
17
+ function readAllEndpoints(root) {
18
+ const configService = getConfigService(root);
19
+ const raw = configService.getRaw(configService.primaryFile);
20
+ return [...(raw?.endpoints ?? [])];
21
+ }
22
+ function assertUniqueName(endpoints, context, name, replaceIndex) {
23
+ const conflict = endpoints.findIndex((e) => e.context === context && e.id === name);
24
+ if (conflict >= 0 && conflict !== replaceIndex) {
25
+ throw new Error(`zhin.config 中已存在 ${context}/${name}`);
26
+ }
27
+ }
28
+ function buildProvisionContext(root, message) {
29
+ return {
30
+ message,
31
+ root,
32
+ onStatusUpdate: async (status, extra) => {
33
+ if (message.$reply) {
34
+ let content = status;
35
+ if (extra?.qrcode && typeof extra.qrcode === 'string') {
36
+ content = [segment.qrcode(extra.qrcode), segment.text(status)];
37
+ }
38
+ await message.$reply(content);
39
+ }
40
+ },
41
+ };
42
+ }
43
+ export class EndpointLifecycleService {
44
+ root;
45
+ constructor(root) {
46
+ this.root = root;
47
+ }
48
+ resolveAdapter(adapterKey) {
49
+ const adapter = this.root.inject(adapterKey);
50
+ if (!(adapter instanceof Adapter)) {
51
+ throw new Error(`适配器 ${adapterKey} 未安装或未就绪`);
52
+ }
53
+ return adapter;
54
+ }
55
+ resolveManager(adapterKey) {
56
+ const adapter = this.resolveAdapter(adapterKey);
57
+ const manager = resolveEndpointManager(adapter);
58
+ if (!manager) {
59
+ throw new Error(`适配器 ${adapterKey} 不支持运行时 Endpoint 管理(无 EndpointManager 且未声明 endpointConfigSchema)`);
60
+ }
61
+ return manager;
62
+ }
63
+ listProvisionableAdapters() {
64
+ return this.root.adapters.filter((name) => {
65
+ try {
66
+ const adapter = this.resolveAdapter(String(name));
67
+ return adapterSupportsProvision(adapter);
68
+ }
69
+ catch {
70
+ return false;
71
+ }
72
+ });
73
+ }
74
+ async persistEndpoints(endpoints) {
75
+ const configService = getConfigService(this.root);
76
+ const loader = configService.configs.get(configService.primaryFile);
77
+ loader.patchKey('endpoints', endpoints);
78
+ }
79
+ /** 将内存中的 endpoints 写回 zhin.config(修复运行时与磁盘不一致) */
80
+ async syncToDisk() {
81
+ const configService = getConfigService(this.root);
82
+ const loader = configService.configs.get(configService.primaryFile);
83
+ const endpoints = readAllEndpoints(this.root);
84
+ await this.persistEndpoints(endpoints);
85
+ const configPath = formatDisplayPath(loader.resolvedPath);
86
+ const names = endpoints.map((e) => `${e.context}/${e.id}`).join(', ') || '(无)';
87
+ return {
88
+ message: `✅ 已将 ${endpoints.length} 个 endpoint 写入 \`${configPath}\`:${names}`,
89
+ };
90
+ }
91
+ async connectConfig(adapter, config) {
92
+ const name = config.id;
93
+ if (adapter.endpoints.has(name)) {
94
+ throw new Error(`Endpoint ${name} 已在线,请先 /endpoint stop ${String(adapter.name)} ${name}`);
95
+ }
96
+ const endpoint = await connectEndpointInstance({
97
+ plugin: this.root,
98
+ adapter,
99
+ config: config,
100
+ });
101
+ adapter.endpoints.set(endpoint.$id, endpoint);
102
+ return endpoint;
103
+ }
104
+ async disconnectRuntime(adapter, name) {
105
+ const endpoint = adapter.endpoints.get(name);
106
+ if (!endpoint)
107
+ return false;
108
+ if (endpoint.$connected) {
109
+ await disconnectEndpointInstance(this.root, adapter, endpoint);
110
+ }
111
+ adapter.endpoints.delete(name);
112
+ return true;
113
+ }
114
+ async add(adapterKey, message, initialReply) {
115
+ const adapter = this.resolveAdapter(adapterKey);
116
+ const manager = this.resolveManager(adapterKey);
117
+ const ctx = buildProvisionContext(this.root, message);
118
+ const config = await manager.addEndpoint(ctx);
119
+ if (!config.context)
120
+ config.context = adapterKey;
121
+ if (!config.id?.trim()) {
122
+ throw new Error('Endpoint id 不能为空');
123
+ }
124
+ const endpoints = readAllEndpoints(this.root);
125
+ try {
126
+ assertUniqueName(endpoints, config.context, config.id);
127
+ }
128
+ catch (err) {
129
+ if (err instanceof Error && err.message.includes('已存在')) {
130
+ const online = adapter.endpoints.has(config.id);
131
+ const hint = online
132
+ ? '该 Endpoint 已在运行时注册,无需重复扫码;可发 /endpoints 确认。若 zhin.config.yml 未更新,请 /endpoint sync。'
133
+ : '可用 /endpoint start 重试连接,或 /endpoint remove 后重新添加。';
134
+ throw new Error(`${err.message}。${hint}`);
135
+ }
136
+ throw err;
137
+ }
138
+ endpoints.push(config);
139
+ await this.persistEndpoints(endpoints);
140
+ try {
141
+ await this.connectConfig(adapter, config);
142
+ }
143
+ catch (err) {
144
+ const needsRestart = adapter.getEndpointNeedsRestart?.() ??
145
+ adapter.constructor.endpointNeedsRestart;
146
+ const hint = needsRestart
147
+ ? '配置已写入,请重启进程后连接。'
148
+ : `配置已写入,可用 /endpoint start ${adapterKey} ${config.id} 重试。`;
149
+ throw new Error(`${err instanceof Error ? err.message : String(err)}(${hint})`);
150
+ }
151
+ const prefix = initialReply ? `${initialReply}\n` : '';
152
+ return {
153
+ message: `${prefix}✅ 已添加并连接 endpoint \`${config.id}\`(${adapterKey}),已写入 zhin.config。`,
154
+ config,
155
+ };
156
+ }
157
+ async edit(adapterKey, name, message) {
158
+ const adapter = this.resolveAdapter(adapterKey);
159
+ const manager = this.resolveManager(adapterKey);
160
+ const endpoints = readAllEndpoints(this.root);
161
+ const index = endpoints.findIndex((e) => e.context === adapterKey && e.id === name);
162
+ if (index < 0) {
163
+ throw new Error(`zhin.config 中不存在 ${adapterKey}/${name}`);
164
+ }
165
+ if (adapter.endpoints.has(name)) {
166
+ await this.disconnectRuntime(adapter, name);
167
+ }
168
+ const ctx = buildProvisionContext(this.root, message);
169
+ const updated = await manager.editEndpoint(name, ctx);
170
+ updated.context = adapterKey;
171
+ updated.id = name;
172
+ endpoints[index] = updated;
173
+ await this.persistEndpoints(endpoints);
174
+ try {
175
+ await this.connectConfig(adapter, updated);
176
+ }
177
+ catch (err) {
178
+ throw new Error(`配置已更新,但连接失败:${err instanceof Error ? err.message : String(err)}。` +
179
+ `可用 /endpoint start ${adapterKey} ${name} 重试。`);
180
+ }
181
+ return {
182
+ message: `✅ 已更新并连接 endpoint \`${name}\`(${adapterKey})。`,
183
+ config: updated,
184
+ };
185
+ }
186
+ async remove(adapterKey, name) {
187
+ const adapter = this.resolveAdapter(adapterKey);
188
+ const manager = this.resolveManager(adapterKey);
189
+ await this.stop(adapterKey, name);
190
+ const ok = await manager.removeEndpoint(name);
191
+ if (!ok) {
192
+ throw new Error(`无法移除 ${adapterKey}/${name}`);
193
+ }
194
+ const endpoints = readAllEndpoints(this.root);
195
+ const next = endpoints.filter((e) => !(e.context === adapterKey && e.id === name));
196
+ if (next.length === endpoints.length) {
197
+ throw new Error(`zhin.config 中不存在 ${adapterKey}/${name}`);
198
+ }
199
+ await this.persistEndpoints(next);
200
+ return { message: `✅ 已从配置移除 endpoint \`${name}\`(${adapterKey})。` };
201
+ }
202
+ async start(adapterKey, name, message) {
203
+ const adapter = this.resolveAdapter(adapterKey);
204
+ const manager = this.resolveManager(adapterKey);
205
+ const endpoints = readAllEndpoints(this.root);
206
+ const config = endpoints.find((e) => e.context === adapterKey && e.id === name);
207
+ if (!config) {
208
+ throw new Error(`zhin.config 中不存在 ${adapterKey}/${name}`);
209
+ }
210
+ if (adapter.endpoints.has(name)) {
211
+ return { message: `Endpoint ${adapterKey}/${name} 已在线。` };
212
+ }
213
+ const ctx = buildProvisionContext(this.root, message);
214
+ await manager.startEndpoint(name, ctx);
215
+ await this.connectConfig(adapter, config);
216
+ return { message: `✅ 已连接 endpoint \`${name}\`(${adapterKey})。`, config };
217
+ }
218
+ async stop(adapterKey, name) {
219
+ const adapter = this.resolveAdapter(adapterKey);
220
+ const manager = this.resolveManager(adapterKey);
221
+ const stopped = await this.disconnectRuntime(adapter, name);
222
+ await manager.stopEndpoint(name);
223
+ if (!stopped) {
224
+ return { message: `Endpoint ${adapterKey}/${name} 当前未在线。` };
225
+ }
226
+ return { message: `✅ 已断开 endpoint \`${name}\`(${adapterKey}),配置仍保留。` };
227
+ }
228
+ cancelProvision() {
229
+ for (const adapterName of this.root.adapters) {
230
+ const adapter = this.root.inject(adapterName);
231
+ if (!(adapter instanceof Adapter))
232
+ continue;
233
+ const manager = resolveEndpointManager(adapter);
234
+ if (manager?.cancelProvision?.())
235
+ return true;
236
+ }
237
+ return false;
238
+ }
239
+ }
240
+ export function createEndpointLifecycleService(root) {
241
+ return new EndpointLifecycleService(root);
242
+ }
@@ -0,0 +1,27 @@
1
+ import type { Adapter } from '../adapter.js';
2
+ import type { Endpoint } from '../endpoint.js';
3
+ import type { Plugin } from '../plugin.js';
4
+ export type EndpointLifecycleKind = 'connect' | 'disconnect' | 'error';
5
+ export interface EndpointLifecyclePayload {
6
+ adapter: string;
7
+ endpointKey: string;
8
+ endpoint: Endpoint;
9
+ kind: EndpointLifecycleKind;
10
+ error?: string;
11
+ phase?: string;
12
+ detail?: Record<string, unknown>;
13
+ }
14
+ /** 可 JSON 序列化的生命周期载荷(不含 endpoint 实例引用) */
15
+ export declare function serializeEndpointLifecyclePayload(payload: Pick<EndpointLifecyclePayload, 'adapter' | 'endpointKey' | 'kind' | 'error' | 'phase' | 'detail'>): {
16
+ adapter: string;
17
+ endpointKey: string;
18
+ kind: EndpointLifecycleKind;
19
+ error: string | undefined;
20
+ phase: string | undefined;
21
+ detail: Record<string, unknown> | undefined;
22
+ };
23
+ export declare function emitEndpointLifecycle(plugin: Plugin, adapter: Adapter, endpoint: Endpoint, kind: EndpointLifecycleKind, detail?: {
24
+ error?: string;
25
+ phase?: string;
26
+ detail?: Record<string, unknown>;
27
+ }): Promise<void>;
@@ -0,0 +1,36 @@
1
+ import { Notice } from '../notice.js';
2
+ /** 可 JSON 序列化的生命周期载荷(不含 endpoint 实例引用) */
3
+ export function serializeEndpointLifecyclePayload(payload) {
4
+ return {
5
+ adapter: payload.adapter,
6
+ endpointKey: payload.endpointKey,
7
+ kind: payload.kind,
8
+ error: payload.error,
9
+ phase: payload.phase,
10
+ detail: payload.detail,
11
+ };
12
+ }
13
+ export async function emitEndpointLifecycle(plugin, adapter, endpoint, kind, detail) {
14
+ const payload = {
15
+ adapter: String(adapter.name),
16
+ endpointKey: endpoint.$id,
17
+ endpoint,
18
+ kind,
19
+ ...detail,
20
+ };
21
+ const eventName = kind === 'connect' ? 'endpoint.connect' : kind === 'disconnect' ? 'endpoint.disconnect' : 'endpoint.error';
22
+ await plugin.root.dispatch(eventName, payload);
23
+ const notice = Notice.from({
24
+ $raw: JSON.stringify(serializeEndpointLifecyclePayload(payload)),
25
+ }, {
26
+ $id: `endpoint-lifecycle:${endpoint.$id}:${kind}:${Date.now()}`,
27
+ $adapter: adapter.name,
28
+ $endpoint: endpoint.$id,
29
+ $type: 'notice',
30
+ $scene_id: endpoint.$id,
31
+ $scene_type: 'endpoint',
32
+ $sub_type: kind,
33
+ $timestamp: Date.now(),
34
+ });
35
+ adapter.emit('notice.receive', notice);
36
+ }
@@ -0,0 +1,34 @@
1
+ import type { Schema } from '@zhin.js/schema';
2
+ import type { Message } from '../message.js';
3
+ import type { Plugin } from '../plugin.js';
4
+ /** zhin.config.endpoints[] 单条记录 */
5
+ export type EndpointConfigRecord = Record<string, unknown> & {
6
+ context: string;
7
+ id: string;
8
+ };
9
+ export type EndpointStatusExtra = Record<string, unknown>;
10
+ export interface ProvisionContext {
11
+ message: Message;
12
+ root: Plugin;
13
+ /** 长连接 / 扫码 / 登录进度回调(由 core 转发到 message.$reply) */
14
+ onStatusUpdate: (status: string, extra?: EndpointStatusExtra) => void | Promise<void>;
15
+ }
16
+ export interface EndpointManager {
17
+ /** 是否支持运行时 add(含 schema 通用或自定义) */
18
+ supportsProvision(): boolean;
19
+ listEndpoints(): EndpointConfigRecord[];
20
+ addEndpoint(ctx: ProvisionContext): Promise<EndpointConfigRecord>;
21
+ editEndpoint(name: string, ctx: ProvisionContext): Promise<EndpointConfigRecord>;
22
+ removeEndpoint(name: string): Promise<boolean>;
23
+ startEndpoint(name: string, ctx: ProvisionContext): Promise<void>;
24
+ stopEndpoint(name: string): Promise<boolean>;
25
+ /** 取消进行中的 add/edit 交互(如 QQ 扫码);无则返回 false */
26
+ cancelProvision?(): boolean;
27
+ }
28
+ export interface EndpointManagerClass {
29
+ new (adapter: import('../adapter.js').Adapter): EndpointManager;
30
+ /** 热连接失败时是否建议重启进程 */
31
+ readonly needsRestart?: boolean;
32
+ /** 通用 schema 驱动 add/edit 时使用 */
33
+ readonly endpointConfigSchema?: Schema;
34
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ export interface GenerateQrCodeOptions {
2
+ width?: number;
3
+ margin?: number;
4
+ errorCorrectionLevel?: 'L' | 'M' | 'Q' | 'H';
5
+ }
6
+ export interface PrintQrCodeTerminalOptions {
7
+ small?: boolean;
8
+ }
9
+ /** 二维码实例:一次 generate,多种输出 */
10
+ export declare class GeneratedQrCode {
11
+ #private;
12
+ private constructor();
13
+ static generate(text: string, options?: GenerateQrCodeOptions): Promise<GeneratedQrCode>;
14
+ /** data URL,含 `data:image/png;base64,...` 前缀 */
15
+ toDataUrl(): string;
16
+ /**
17
+ * encoding === 'base64' → 纯 base64 载荷(无 data: 前缀)
18
+ */
19
+ toString(encoding: 'base64'): string;
20
+ /** 输出 ASCII 二维码到 process.stdout */
21
+ printToTerminal(options?: PrintQrCodeTerminalOptions): Promise<void>;
22
+ }
23
+ /** 便捷别名 */
24
+ export declare const generateQrCode: typeof GeneratedQrCode.generate;
@@ -0,0 +1,45 @@
1
+ import QRCode from 'qrcode';
2
+ /** 二维码实例:一次 generate,多种输出 */
3
+ export class GeneratedQrCode {
4
+ #text;
5
+ #dataUrl;
6
+ constructor(text, dataUrl) {
7
+ this.#text = text;
8
+ this.#dataUrl = dataUrl;
9
+ }
10
+ static async generate(text, options = {}) {
11
+ const dataUrl = await QRCode.toDataURL(text, {
12
+ width: options.width ?? 280,
13
+ margin: options.margin ?? 2,
14
+ errorCorrectionLevel: options.errorCorrectionLevel ?? 'M',
15
+ });
16
+ return new GeneratedQrCode(text, dataUrl);
17
+ }
18
+ /** data URL,含 `data:image/png;base64,...` 前缀 */
19
+ toDataUrl() {
20
+ return this.#dataUrl;
21
+ }
22
+ /**
23
+ * encoding === 'base64' → 纯 base64 载荷(无 data: 前缀)
24
+ */
25
+ toString(encoding) {
26
+ if (encoding !== 'base64') {
27
+ throw new Error(`GeneratedQrCode.toString: unsupported encoding "${encoding}"`);
28
+ }
29
+ const prefix = 'data:image/png;base64,';
30
+ if (!this.#dataUrl.startsWith(prefix)) {
31
+ throw new Error('GeneratedQrCode.toString: unexpected data URL format');
32
+ }
33
+ return this.#dataUrl.slice(prefix.length);
34
+ }
35
+ /** 输出 ASCII 二维码到 process.stdout */
36
+ async printToTerminal(options = {}) {
37
+ const terminalText = await QRCode.toString(this.#text, {
38
+ type: 'terminal',
39
+ small: options.small ?? true,
40
+ });
41
+ process.stdout.write(`${terminalText}\n`);
42
+ }
43
+ }
44
+ /** 便捷别名 */
45
+ export const generateQrCode = GeneratedQrCode.generate.bind(GeneratedQrCode);
@@ -0,0 +1,4 @@
1
+ import type { MessageElement } from '../types.js';
2
+ import type { Segment } from './segment-contract/types.js';
3
+ /** wire 段数组 → canonical Segment[](包括所有媒体的 `data.media` 归一)。 */
4
+ export declare function toCanonicalSegments(content: readonly MessageElement[] | readonly unknown[]): Segment[];