@zhin.js/core 1.3.1 → 1.3.3

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 (358) hide show
  1. package/README.md +66 -11
  2. package/lib/adapter.d.ts +41 -3
  3. package/lib/adapter.js +110 -6
  4. package/lib/agent-prompt.d.ts +0 -1
  5. package/lib/agent-prompt.js +0 -1
  6. package/lib/built/adapter-process.d.ts +11 -2
  7. package/lib/built/adapter-process.js +43 -2
  8. package/lib/built/agent-preset.d.ts +0 -1
  9. package/lib/built/agent-preset.js +0 -1
  10. package/lib/built/ai-access.d.ts +36 -0
  11. package/lib/built/ai-access.js +46 -0
  12. package/lib/built/ai-outbound/adapter-access.d.ts +3 -0
  13. package/lib/built/ai-outbound/adapter-access.js +9 -0
  14. package/lib/built/ai-outbound/extensions/onebot-keyboard.d.ts +2 -0
  15. package/lib/built/ai-outbound/extensions/onebot-keyboard.js +67 -0
  16. package/lib/built/ai-outbound/extensions/qq-message.d.ts +3 -0
  17. package/lib/built/ai-outbound/extensions/qq-message.js +23 -0
  18. package/lib/built/ai-outbound/index.d.ts +9 -0
  19. package/lib/built/ai-outbound/index.js +9 -0
  20. package/lib/built/ai-outbound/parse.d.ts +13 -0
  21. package/lib/built/ai-outbound/parse.js +94 -0
  22. package/lib/built/ai-outbound/plain-mention-rewrite.d.ts +6 -0
  23. package/lib/built/ai-outbound/plain-mention-rewrite.js +37 -0
  24. package/lib/built/ai-outbound/prompt.d.ts +11 -0
  25. package/lib/built/ai-outbound/prompt.js +44 -0
  26. package/lib/built/ai-outbound/resolve.d.ts +4 -0
  27. package/lib/built/ai-outbound/resolve.js +64 -0
  28. package/lib/built/ai-outbound/structured-detect.d.ts +3 -0
  29. package/lib/built/ai-outbound/structured-detect.js +7 -0
  30. package/lib/built/ai-outbound/types.d.ts +60 -0
  31. package/lib/built/ai-outbound/types.js +5 -0
  32. package/lib/built/ai-trigger.d.ts +5 -1
  33. package/lib/built/ai-trigger.js +3 -7
  34. package/lib/built/authorization.d.ts +0 -1
  35. package/lib/built/authorization.js +0 -1
  36. package/lib/built/command.d.ts +2 -1
  37. package/lib/built/command.js +14 -4
  38. package/lib/built/common-adapter-tools.d.ts +25 -26
  39. package/lib/built/common-adapter-tools.js +48 -49
  40. package/lib/built/component.d.ts +0 -1
  41. package/lib/built/component.js +1 -3
  42. package/lib/built/config.d.ts +4 -1
  43. package/lib/built/config.js +26 -5
  44. package/lib/built/connect-endpoint-instance.d.ts +0 -1
  45. package/lib/built/connect-endpoint-instance.js +3 -2
  46. package/lib/built/database.d.ts +0 -1
  47. package/lib/built/database.js +1 -3
  48. package/lib/built/dispatcher.d.ts +6 -6
  49. package/lib/built/dispatcher.js +20 -8
  50. package/lib/built/endpoint-commands.d.ts +3 -0
  51. package/lib/built/endpoint-commands.js +99 -0
  52. package/lib/built/endpoint-lifecycle-service.d.ts +28 -0
  53. package/lib/built/endpoint-lifecycle-service.js +241 -0
  54. package/lib/built/endpoint-lifecycle.d.ts +0 -1
  55. package/lib/built/endpoint-lifecycle.js +0 -1
  56. package/lib/built/endpoint-manager.d.ts +34 -0
  57. package/lib/built/endpoint-manager.js +1 -0
  58. package/lib/built/generated-qrcode.d.ts +24 -0
  59. package/lib/built/generated-qrcode.js +45 -0
  60. package/lib/built/generic-segment-mapper.d.ts +6 -0
  61. package/lib/built/generic-segment-mapper.js +232 -0
  62. package/lib/built/html-renderer-loader.d.ts +13 -0
  63. package/lib/built/html-renderer-loader.js +33 -0
  64. package/lib/built/html-segment-fallback.d.ts +2 -2
  65. package/lib/built/html-segment-fallback.js +0 -1
  66. package/lib/built/html-to-text.d.ts +0 -1
  67. package/lib/built/html-to-text.js +0 -1
  68. package/lib/built/inbound-pipeline.d.ts +0 -1
  69. package/lib/built/inbound-pipeline.js +0 -1
  70. package/lib/built/inbound-runner.d.ts +0 -1
  71. package/lib/built/inbound-runner.js +0 -1
  72. package/lib/built/interactive-segment-contract.d.ts +6 -0
  73. package/lib/built/interactive-segment-contract.js +9 -0
  74. package/lib/built/interactive-segments/action.d.ts +17 -0
  75. package/lib/built/interactive-segments/action.js +54 -0
  76. package/lib/built/interactive-segments/button-spec.d.ts +10 -0
  77. package/lib/built/interactive-segments/button-spec.js +21 -0
  78. package/lib/built/interactive-segments/handlers.d.ts +9 -0
  79. package/lib/built/interactive-segments/handlers.js +58 -0
  80. package/lib/built/interactive-segments/index.d.ts +7 -0
  81. package/lib/built/interactive-segments/index.js +7 -0
  82. package/lib/built/interactive-segments/keyboard-segment.d.ts +12 -0
  83. package/lib/built/interactive-segments/keyboard-segment.js +13 -0
  84. package/lib/built/interactive-segments/onebot-keyboard.d.ts +10 -0
  85. package/lib/built/interactive-segments/onebot-keyboard.js +53 -0
  86. package/lib/built/interactive-segments/resolve.d.ts +9 -0
  87. package/lib/built/interactive-segments/resolve.js +84 -0
  88. package/lib/built/interactive-segments/types.d.ts +62 -0
  89. package/lib/built/interactive-segments/types.js +13 -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 +1 -2
  93. package/lib/built/login-assist.js +0 -1
  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 +0 -1
  97. package/lib/built/message-enrich.js +0 -1
  98. package/lib/built/message-filter.d.ts +0 -1
  99. package/lib/built/message-filter.js +1 -3
  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 +0 -1
  107. package/lib/built/permission.js +1 -3
  108. package/lib/built/permit-check.d.ts +0 -1
  109. package/lib/built/permit-check.js +0 -1
  110. package/lib/built/permit-parse.d.ts +0 -1
  111. package/lib/built/permit-parse.js +0 -1
  112. package/lib/built/platform-permit.d.ts +5 -6
  113. package/lib/built/platform-permit.js +11 -12
  114. package/lib/built/prepend-quote-context.d.ts +0 -1
  115. package/lib/built/prepend-quote-context.js +0 -1
  116. package/lib/built/qrcode-segment.d.ts +18 -0
  117. package/lib/built/qrcode-segment.js +78 -0
  118. package/lib/built/queue-im-field-contract.d.ts +6 -1
  119. package/lib/built/queue-im-field-contract.js +10 -1
  120. package/lib/built/rich-segments/adapter-policies.d.ts +9 -0
  121. package/lib/built/rich-segments/adapter-policies.js +27 -0
  122. package/lib/built/rich-segments/base.d.ts +11 -0
  123. package/lib/built/rich-segments/base.js +24 -0
  124. package/lib/built/rich-segments/builtins.d.ts +4 -0
  125. package/lib/built/rich-segments/builtins.js +40 -0
  126. package/lib/built/rich-segments/capabilities.d.ts +6 -0
  127. package/lib/built/rich-segments/capabilities.js +39 -0
  128. package/lib/built/rich-segments/html-segment.d.ts +15 -0
  129. package/lib/built/rich-segments/html-segment.js +65 -0
  130. package/lib/built/rich-segments/index.d.ts +13 -0
  131. package/lib/built/rich-segments/index.js +13 -0
  132. package/lib/built/rich-segments/markdown-segment.d.ts +14 -0
  133. package/lib/built/rich-segments/markdown-segment.js +61 -0
  134. package/lib/built/rich-segments/markdown-to-text.d.ts +3 -0
  135. package/lib/built/rich-segments/markdown-to-text.js +27 -0
  136. package/lib/built/rich-segments/qrcode-segment.d.ts +18 -0
  137. package/lib/built/rich-segments/qrcode-segment.js +73 -0
  138. package/lib/built/rich-segments/registry.d.ts +16 -0
  139. package/lib/built/rich-segments/registry.js +52 -0
  140. package/lib/built/rich-segments/resolve.d.ts +5 -0
  141. package/lib/built/rich-segments/resolve.js +87 -0
  142. package/lib/built/rich-segments/tts-segment.d.ts +13 -0
  143. package/lib/built/rich-segments/tts-segment.js +51 -0
  144. package/lib/built/rich-segments/types.d.ts +84 -0
  145. package/lib/built/rich-segments/types.js +17 -0
  146. package/lib/built/roles.d.ts +0 -1
  147. package/lib/built/roles.js +0 -1
  148. package/lib/built/runtime-io.d.ts +0 -1
  149. package/lib/built/runtime-io.js +0 -1
  150. package/lib/built/schedule.d.ts +55 -0
  151. package/lib/built/schedule.js +112 -0
  152. package/lib/built/schema-endpoint-manager.d.ts +17 -0
  153. package/lib/built/schema-endpoint-manager.js +73 -0
  154. package/lib/built/schema-feature.d.ts +0 -1
  155. package/lib/built/schema-feature.js +1 -3
  156. package/lib/built/segment-contract/assert.d.ts +4 -0
  157. package/lib/built/segment-contract/assert.js +30 -0
  158. package/lib/built/segment-contract/delivery.d.ts +5 -0
  159. package/lib/built/segment-contract/delivery.js +40 -0
  160. package/lib/built/segment-contract/image.d.ts +5 -0
  161. package/lib/built/segment-contract/image.js +10 -0
  162. package/lib/built/segment-contract/index.d.ts +8 -0
  163. package/lib/built/segment-contract/index.js +7 -0
  164. package/lib/built/segment-contract/media.d.ts +8 -0
  165. package/lib/built/segment-contract/media.js +39 -0
  166. package/lib/built/segment-contract/mention.d.ts +10 -0
  167. package/lib/built/segment-contract/mention.js +26 -0
  168. package/lib/built/segment-contract/preview.d.ts +3 -0
  169. package/lib/built/segment-contract/preview.js +159 -0
  170. package/lib/built/segment-contract/types.d.ts +70 -0
  171. package/lib/built/segment-contract/types.js +5 -0
  172. package/lib/built/segment-contract/validate.d.ts +138 -0
  173. package/lib/built/segment-contract/validate.js +124 -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 +0 -1
  179. package/lib/built/tool.js +1 -3
  180. package/lib/command.d.ts +12 -7
  181. package/lib/command.js +38 -16
  182. package/lib/component.d.ts +0 -1
  183. package/lib/component.js +0 -1
  184. package/lib/endpoint-capabilities.d.ts +3 -1
  185. package/lib/endpoint-capabilities.js +0 -1
  186. package/lib/endpoint.d.ts +0 -1
  187. package/lib/endpoint.js +0 -1
  188. package/lib/errors.d.ts +0 -1
  189. package/lib/errors.js +0 -1
  190. package/lib/host-plugin-registry.d.ts +0 -1
  191. package/lib/host-plugin-registry.js +0 -1
  192. package/lib/im-scene.d.ts +29 -0
  193. package/lib/im-scene.js +77 -0
  194. package/lib/im-session-id.d.ts +25 -12
  195. package/lib/im-session-id.js +35 -17
  196. package/lib/index.d.ts +25 -5
  197. package/lib/index.js +22 -4
  198. package/lib/jsx-dev-runtime.d.ts +0 -1
  199. package/lib/jsx-dev-runtime.js +0 -1
  200. package/lib/jsx-runtime.d.ts +0 -1
  201. package/lib/jsx-runtime.js +0 -1
  202. package/lib/jsx.d.ts +0 -1
  203. package/lib/jsx.js +0 -1
  204. package/lib/message-quote.d.ts +1 -2
  205. package/lib/message-quote.js +2 -3
  206. package/lib/message.d.ts +12 -2
  207. package/lib/message.js +16 -1
  208. package/lib/models/system-log.d.ts +0 -1
  209. package/lib/models/system-log.js +0 -1
  210. package/lib/models/user.d.ts +0 -1
  211. package/lib/models/user.js +0 -1
  212. package/lib/notice.d.ts +0 -1
  213. package/lib/notice.js +0 -1
  214. package/lib/plugin-context.d.ts +0 -1
  215. package/lib/plugin-context.js +0 -1
  216. package/lib/plugin.d.ts +11 -2
  217. package/lib/plugin.js +22 -23
  218. package/lib/prompt.d.ts +0 -1
  219. package/lib/prompt.js +1 -2
  220. package/lib/request.d.ts +0 -1
  221. package/lib/request.js +0 -1
  222. package/lib/tool-zod.d.ts +0 -1
  223. package/lib/tool-zod.js +0 -1
  224. package/lib/types-generator.d.ts +0 -1
  225. package/lib/types-generator.js +0 -1
  226. package/lib/types.d.ts +30 -11
  227. package/lib/types.js +0 -1
  228. package/lib/utils.d.ts +57 -12
  229. package/lib/utils.js +54 -19
  230. package/package.json +18 -9
  231. package/lib/adapter.d.ts.map +0 -1
  232. package/lib/adapter.js.map +0 -1
  233. package/lib/agent-prompt.d.ts.map +0 -1
  234. package/lib/agent-prompt.js.map +0 -1
  235. package/lib/built/adapter-process.d.ts.map +0 -1
  236. package/lib/built/adapter-process.js.map +0 -1
  237. package/lib/built/agent-preset.d.ts.map +0 -1
  238. package/lib/built/agent-preset.js.map +0 -1
  239. package/lib/built/ai-trigger.d.ts.map +0 -1
  240. package/lib/built/ai-trigger.js.map +0 -1
  241. package/lib/built/authorization.d.ts.map +0 -1
  242. package/lib/built/authorization.js.map +0 -1
  243. package/lib/built/command.d.ts.map +0 -1
  244. package/lib/built/command.js.map +0 -1
  245. package/lib/built/common-adapter-tools.d.ts.map +0 -1
  246. package/lib/built/common-adapter-tools.js.map +0 -1
  247. package/lib/built/component.d.ts.map +0 -1
  248. package/lib/built/component.js.map +0 -1
  249. package/lib/built/config.d.ts.map +0 -1
  250. package/lib/built/config.js.map +0 -1
  251. package/lib/built/connect-endpoint-instance.d.ts.map +0 -1
  252. package/lib/built/connect-endpoint-instance.js.map +0 -1
  253. package/lib/built/cron.d.ts +0 -75
  254. package/lib/built/cron.d.ts.map +0 -1
  255. package/lib/built/cron.js +0 -122
  256. package/lib/built/cron.js.map +0 -1
  257. package/lib/built/database.d.ts.map +0 -1
  258. package/lib/built/database.js.map +0 -1
  259. package/lib/built/dispatcher.d.ts.map +0 -1
  260. package/lib/built/dispatcher.js.map +0 -1
  261. package/lib/built/endpoint-lifecycle.d.ts.map +0 -1
  262. package/lib/built/endpoint-lifecycle.js.map +0 -1
  263. package/lib/built/html-segment-fallback.d.ts.map +0 -1
  264. package/lib/built/html-segment-fallback.js.map +0 -1
  265. package/lib/built/html-to-text.d.ts.map +0 -1
  266. package/lib/built/html-to-text.js.map +0 -1
  267. package/lib/built/inbound-pipeline.d.ts.map +0 -1
  268. package/lib/built/inbound-pipeline.js.map +0 -1
  269. package/lib/built/inbound-runner.d.ts.map +0 -1
  270. package/lib/built/inbound-runner.js.map +0 -1
  271. package/lib/built/login-assist.d.ts.map +0 -1
  272. package/lib/built/login-assist.js.map +0 -1
  273. package/lib/built/mcp-mesh-registrar.d.ts +0 -9
  274. package/lib/built/mcp-mesh-registrar.d.ts.map +0 -1
  275. package/lib/built/mcp-mesh-registrar.js +0 -17
  276. package/lib/built/mcp-mesh-registrar.js.map +0 -1
  277. package/lib/built/message-enrich.d.ts.map +0 -1
  278. package/lib/built/message-enrich.js.map +0 -1
  279. package/lib/built/message-filter.d.ts.map +0 -1
  280. package/lib/built/message-filter.js.map +0 -1
  281. package/lib/built/permission.d.ts.map +0 -1
  282. package/lib/built/permission.js.map +0 -1
  283. package/lib/built/permit-check.d.ts.map +0 -1
  284. package/lib/built/permit-check.js.map +0 -1
  285. package/lib/built/permit-parse.d.ts.map +0 -1
  286. package/lib/built/permit-parse.js.map +0 -1
  287. package/lib/built/platform-permit.d.ts.map +0 -1
  288. package/lib/built/platform-permit.js.map +0 -1
  289. package/lib/built/prepend-quote-context.d.ts.map +0 -1
  290. package/lib/built/prepend-quote-context.js.map +0 -1
  291. package/lib/built/queue-im-field-contract.d.ts.map +0 -1
  292. package/lib/built/queue-im-field-contract.js.map +0 -1
  293. package/lib/built/roles.d.ts.map +0 -1
  294. package/lib/built/roles.js.map +0 -1
  295. package/lib/built/runtime-io.d.ts.map +0 -1
  296. package/lib/built/runtime-io.js.map +0 -1
  297. package/lib/built/schema-feature.d.ts.map +0 -1
  298. package/lib/built/schema-feature.js.map +0 -1
  299. package/lib/built/skill.d.ts.map +0 -1
  300. package/lib/built/skill.js.map +0 -1
  301. package/lib/built/tool.d.ts.map +0 -1
  302. package/lib/built/tool.js.map +0 -1
  303. package/lib/command.d.ts.map +0 -1
  304. package/lib/command.js.map +0 -1
  305. package/lib/component.d.ts.map +0 -1
  306. package/lib/component.js.map +0 -1
  307. package/lib/endpoint-capabilities.d.ts.map +0 -1
  308. package/lib/endpoint-capabilities.js.map +0 -1
  309. package/lib/endpoint.d.ts.map +0 -1
  310. package/lib/endpoint.js.map +0 -1
  311. package/lib/errors.d.ts.map +0 -1
  312. package/lib/errors.js.map +0 -1
  313. package/lib/host-plugin-registry.d.ts.map +0 -1
  314. package/lib/host-plugin-registry.js.map +0 -1
  315. package/lib/im-session-id.d.ts.map +0 -1
  316. package/lib/im-session-id.js.map +0 -1
  317. package/lib/index.d.ts.map +0 -1
  318. package/lib/index.js.map +0 -1
  319. package/lib/jsx-dev-runtime.d.ts.map +0 -1
  320. package/lib/jsx-dev-runtime.js.map +0 -1
  321. package/lib/jsx-runtime.d.ts.map +0 -1
  322. package/lib/jsx-runtime.js.map +0 -1
  323. package/lib/jsx.d.ts.map +0 -1
  324. package/lib/jsx.js.map +0 -1
  325. package/lib/message-quote.d.ts.map +0 -1
  326. package/lib/message-quote.js.map +0 -1
  327. package/lib/message.d.ts.map +0 -1
  328. package/lib/message.js.map +0 -1
  329. package/lib/models/system-log.d.ts.map +0 -1
  330. package/lib/models/system-log.js.map +0 -1
  331. package/lib/models/user.d.ts.map +0 -1
  332. package/lib/models/user.js.map +0 -1
  333. package/lib/notice.d.ts.map +0 -1
  334. package/lib/notice.js.map +0 -1
  335. package/lib/plugin-context.d.ts.map +0 -1
  336. package/lib/plugin-context.js.map +0 -1
  337. package/lib/plugin.d.ts.map +0 -1
  338. package/lib/plugin.js.map +0 -1
  339. package/lib/prompt.d.ts.map +0 -1
  340. package/lib/prompt.js.map +0 -1
  341. package/lib/request.d.ts.map +0 -1
  342. package/lib/request.js.map +0 -1
  343. package/lib/scheduler/scheduler.d.ts +0 -49
  344. package/lib/scheduler/scheduler.d.ts.map +0 -1
  345. package/lib/scheduler/scheduler.js +0 -352
  346. package/lib/scheduler/scheduler.js.map +0 -1
  347. package/lib/scheduler/types.d.ts +0 -71
  348. package/lib/scheduler/types.d.ts.map +0 -1
  349. package/lib/scheduler/types.js +0 -8
  350. package/lib/scheduler/types.js.map +0 -1
  351. package/lib/tool-zod.d.ts.map +0 -1
  352. package/lib/tool-zod.js.map +0 -1
  353. package/lib/types-generator.d.ts.map +0 -1
  354. package/lib/types-generator.js.map +0 -1
  355. package/lib/types.d.ts.map +0 -1
  356. package/lib/types.js.map +0 -1
  357. package/lib/utils.d.ts.map +0 -1
  358. package/lib/utils.js.map +0 -1
package/README.md CHANGED
@@ -13,7 +13,7 @@ Zhin.js **IM/多通道运行时**包:Plugin、Adapter、**Endpoint**、Message
13
13
  ```typescript
14
14
  import { usePlugin, MessageCommand } from '@zhin.js/core'
15
15
 
16
- const { addCommand, addTool, addCron, onMounted, onDispose } = usePlugin()
16
+ const { addCommand, addTool, addSchedule, onMounted, onDispose } = usePlugin()
17
17
 
18
18
  onMounted(() => console.log('插件已挂载'))
19
19
  onDispose(() => console.log('插件已卸载'))
@@ -55,7 +55,7 @@ Feature (抽象基类)
55
55
  ├── CommandFeature — 消息命令 addCommand()
56
56
  ├── ToolFeature — AI 可调用工具 addTool()
57
57
  ├── SkillFeature — 技能记录 Agent 从 SKILL.md 注入
58
- ├── CronFeature 定时任务 addCron()
58
+ ├── ScheduleFeature 调度任务 addSchedule()
59
59
  ├── DatabaseFeature — 数据模型 defineModel()
60
60
  ├── ComponentFeature — 消息组件 addComponent()
61
61
  ├── ConfigFeature — 插件配置 addConfig()
@@ -90,11 +90,56 @@ return segment.html({
90
90
  backgroundColor: '#d8dce3',
91
91
  fileName: 'card.png',
92
92
  })
93
+
94
+ // Markdown 段(QQ 等平台 policy 为 origin 时透传)
95
+ return segment.markdown('# Title\n\nBody')
96
+ ```
97
+
98
+ 出站富媒体段(`qrcode` / `html` / `markdown`)在 **`Adapter.renderSendMessage` 首步** 按各 Adapter 的 **`outboundRichSegmentPolicy`** 统一渲染为 `image` / `text` / `origin`:
99
+
100
+ | 渲染模式 | 含义 |
101
+ |---------|------|
102
+ | `image` | 转为 `image` 段(qrcode 生成 PNG;html/markdown 经 `@zhin.js/html-renderer` 动态转图,未安装则降级 text) |
103
+ | `text` | 剥离为纯文本段 |
104
+ | `origin` | 原样透传,由 Endpoint 解释(如 QQ markdown、process 终端二维码) |
105
+
106
+ 默认策略:`qrcode: image`,`html: text`,`markdown: text`。QQ / KOOK 等适配器 override static policy。
107
+
108
+ - 安装 **`@zhin.js/html-renderer`** 且 policy 为 `html: 'image'` 时,core 在首步动态 import 并转 PNG。
109
+ - policy 为 `html: 'text'` 时等价于 **`coerceHtmlSegmentsToText`** / **`htmlToFallbackText`**。
110
+ - 日志预览:`[html-card]`、`[qrcode]`、`[markdown]` + 摘要(前 80 字)。
111
+
112
+ #### 扩展新 Rich Segment(长期方案)
113
+
114
+ 内置 kind 通过 **`richSegmentRegistry`** 注册;optional 能力通过 **`registerRichSegmentCapabilityLoader`** 注入(与 `@zhin.js/html-renderer` 同模式)。
115
+
116
+ ```typescript
117
+ import {
118
+ RichSegment,
119
+ registerRichSegmentKind,
120
+ registerRichSegmentCapabilityLoader,
121
+ RICH_SEGMENT_MODE,
122
+ segment,
123
+ } from '@zhin.js/core';
124
+
125
+ // 1. 内置 capability:speech(@zhin.js/speech)已注册,tts kind 已内置
126
+ // 可选:注册 ffmpeg 等
127
+ registerRichSegmentCapabilityLoader('media-pipeline', async (opts) => {
128
+ const { createMediaPipeline } = await import('@zhin.js/media-pipeline');
129
+ return createMediaPipeline(opts.getConfig?.());
130
+ });
131
+
132
+ // 2. 使用内置 segment.tts(Adapter policy 决定 audio/text/origin)
133
+ // segment.tts({ text: '你好' })
134
+ class MyAdapter extends Adapter {
135
+ static override outboundRichSegmentPolicy = {
136
+ tts: 'audio',
137
+ qrcode: 'image', // 其余 kind 用 registry 默认值
138
+ };
139
+ }
93
140
  ```
94
141
 
95
- - 安装 **`@zhin.js/plugin-html-renderer`** 时,`before.sendMessage` 自动将 `html` 转为 PNG。
96
- - 未安装或转图失败时,`Adapter.renderSendMessage` 链尾调用 **`coerceHtmlSegmentsToText`**,用 **`htmlToFallbackText`** 剥离纯文本。
97
- - 日志预览为 `[html-card]` + 自动剥离摘要(前 80 字),不 dump 完整 HTML。
142
+ **分工**:Rich Segment 负责「语义段 标准 IM 段」;Endpoint `materializeOutboundMedia` 负责「已有 audio/video/file → 平台上传」。
98
143
 
99
144
  ### Adapter(适配器)
100
145
 
@@ -105,9 +150,9 @@ return segment.html({
105
150
  Adapter.register('my-platform', MyAdapter)
106
151
  ```
107
152
 
108
- 每个适配器可以通过 `addTool()` 注册平台特有工具,标准群管操作通过覆写 `IGroupManagement` 方法自动注册。
153
+ 每个适配器可以通过 `addTool()` 注册平台特有工具,标准群管操作通过覆写 `ISceneManagement` 方法自动注册。
109
154
 
110
- **群管理能力自动检测:** 适配器基类声明了 `IGroupManagement` 接口中的可选方法(`kickMember`、`muteMember`、`banMember` 等),子类只需覆写自己平台支持的方法,`start()` 会自动检测哪些方法已实现,生成对应的 Tool 并注册为"群聊管理"Skill。目前所有 9 个 IM 适配器(ICQQ、OneBot11、QQ 官方、Telegram、Discord、KOOK、Slack、钉钉、飞书)均已采用此模式:
155
+ **群管理能力自动检测:** 适配器基类声明了 `ISceneManagement` 接口中的可选方法(`kickMember`、`muteMember`、`banMember` 等),子类只需覆写自己平台支持的方法,`start()` 会自动检测哪些方法已实现,生成对应的 Tool 并注册为"群聊管理"Skill。目前所有 9 个 IM 适配器(ICQQ、OneBot11、QQ 官方、Telegram、Discord、KOOK、Slack、钉钉、飞书)均已采用此模式:
111
156
 
112
157
  ```typescript
113
158
  class IcqqAdapter extends Adapter<IcqqEndpoint> {
@@ -152,7 +197,7 @@ Core **不包含** ZhinAgent 实现。IM 侧的 AI 对话、工具收集、执
152
197
  |------|----------|
153
198
  | Provider | `OpenAIProvider`、`OllamaProvider`、`AnthropicProvider` 等 |
154
199
  | Agent 原语 | `Agent`、`createAgent`、`ModelRegistry` |
155
- | 会话 / 上下文 | `SessionManager`(遗留)、`ContextRepository`、`ImTranscriptStore`、`ContextManager`、`ConversationMemory` |
200
+ | 会话 / 上下文 | `ContextRepository`、`ImTranscriptStore`、`ContextManager`、`ConversationMemory` |
156
201
  | 压缩 / 限流 / 输出 | `compactSession`、`RateLimiter`、`parseOutput`、`CostTracker` |
157
202
 
158
203
  完整 Agent 能力与配置见 [`@zhin.js/agent`](../agent/README.md) 与 [AI 模块](https://zhin.js.org/advanced/ai)。
@@ -167,7 +212,7 @@ export { Plugin, usePlugin, getPlugin, definePlugin } from './plugin.js'
167
212
 
168
213
  // Feature 体系(Cron / Scheduler 来自 @zhin.js/kernel)
169
214
  export { Feature, Cron, Scheduler } from '@zhin.js/kernel'
170
- export { CommandFeature, ToolFeature, SkillFeature, CronFeature, DatabaseFeature, ... } from './built/*.js'
215
+ export { CommandFeature, ToolFeature, SkillFeature, ScheduleFeature, DatabaseFeature, ... } from './built/*.js'
171
216
 
172
217
  // 消息路由
173
218
  export { createMessageDispatcher } from './built/dispatcher.js'
@@ -175,13 +220,23 @@ export { createMessageDispatcher } from './built/dispatcher.js'
175
220
  // 适配器与消息
176
221
  export { Adapter, Message, MessageCommand, Endpoint, segment, ... } from './'
177
222
 
178
- // HTML 出站回退
223
+ // 富媒体出站段
224
+ export {
225
+ resolveRichSegments,
226
+ DEFAULT_OUTBOUND_RICH_SEGMENT_POLICY,
227
+ QrcodeSegment,
228
+ HtmlSegment,
229
+ MarkdownSegment,
230
+ } from './built/rich-segments/index.js'
231
+ export type { RichSegmentKind, RichRenderMode, OutboundRichSegmentPolicy } from './built/rich-segments/types.js'
232
+
233
+ // HTML 出站回退(legacy;policy html:'text' 时等价)
179
234
  export { htmlToFallbackText, coerceHtmlSegmentsToText, registerHtmlSegmentFallback } from './built/*.js'
180
235
 
181
236
  // AI 原语(来自 @zhin.js/ai,非 ZhinAgent)
182
237
  export {
183
238
  OpenAIProvider, OllamaProvider, Agent, createAgent, ModelRegistry,
184
- SessionManager, ContextManager, ConversationMemory, compactSession, ...
239
+ ContextRepository, ContextManager, ConversationMemory, compactSession, ...
185
240
  } from '@zhin.js/ai'
186
241
  ```
187
242
 
package/lib/adapter.d.ts CHANGED
@@ -1,11 +1,16 @@
1
1
  import { Endpoint } from "./endpoint.js";
2
2
  import { DEFAULT_ENDPOINT_CAPABILITIES, type EndpointCapability } from "./endpoint-capabilities.js";
3
+ import type { EndpointManager } from "./built/endpoint-manager.js";
3
4
  import { Plugin } from "./plugin.js";
4
5
  import { EventEmitter } from "node:events";
5
6
  import { Message } from "./message.js";
6
7
  import { Notice } from "./notice.js";
7
8
  import { Request } from "./request.js";
8
- import { SendOptions } from "./types.js";
9
+ import { EditMessageOptions, SendOptions } from "./types.js";
10
+ import { type OutboundRichSegmentPolicy } from "./built/rich-segments/index.js";
11
+ import { type InteractivePolicy } from "./built/interactive-segments/index.js";
12
+ import { type AiOutboundCapabilities, type AiOutboundExtensionDefinition } from "./built/ai-outbound/index.js";
13
+ import type { Schema } from '@zhin.js/schema';
9
14
  /**
10
15
  * Adapter类:适配器抽象,管理多平台Bot实例。
11
16
  * 负责根据配置启动/关闭各平台机器人,统一异常处理。
@@ -21,6 +26,15 @@ export declare abstract class Adapter<R extends Endpoint = Endpoint, const Caps
21
26
  private recallMessageHandler;
22
27
  /** Adapter 支持的能力上限(子类覆盖) */
23
28
  static readonly capabilities: readonly EndpointCapability[];
29
+ /** 出站富媒体段渲染策略(子类 override static) */
30
+ static outboundRichSegmentPolicy: OutboundRichSegmentPolicy;
31
+ /** 交互段出站策略:native 保留按钮段,text 降级为编号文本 */
32
+ static interactivePolicy: InteractivePolicy;
33
+ /** AI 结构化出站能力声明(mentions / richSegments / interactive) */
34
+ static aiOutboundCapabilities: AiOutboundCapabilities;
35
+ /** 平台特有 extensions schema + 解析(对齐各 SDK 文档子集) */
36
+ static aiOutboundExtensions?: readonly AiOutboundExtensionDefinition[];
37
+ protected getInteractivePolicy(): InteractivePolicy;
24
38
  /** 并发上限,0 表示不限制(默认) */
25
39
  static DEFAULT_MAX_CONCURRENT_MESSAGES: number;
26
40
  get maxConcurrentMessages(): number;
@@ -42,6 +56,17 @@ export declare abstract class Adapter<R extends Endpoint = Endpoint, const Caps
42
56
  abstract createEndpoint(config: Adapter.EndpointConfig<R>): R;
43
57
  get logger(): import("@zhin.js/logger").Logger;
44
58
  binding(plugin: Plugin): void;
59
+ /**
60
+ * 同步等待入站管线结束(middleware → dispatcher → 生命周期 → 观察者)。
61
+ * 用于 QQ 等需在被动回复完成后再 ack 交互的平台事件。
62
+ */
63
+ receiveMessageAwait(message: Message): Promise<boolean>;
64
+ /** 运行时 Endpoint 管理(add/remove/edit/start/stop);未实现则 core 尝试 endpointConfigSchema 通用向导 */
65
+ getEndpointManager?(): EndpointManager | null;
66
+ /** 通用 schema 驱动 add/edit 时的字段定义 */
67
+ getEndpointConfigSchema?(): Schema | undefined;
68
+ /** 热连接失败时是否建议重启进程 */
69
+ getEndpointNeedsRestart?(): boolean;
45
70
  /**
46
71
  * 出站富媒体能力(Publisher 按此过滤/降级;各 adapter 可覆盖)。
47
72
  */
@@ -52,8 +77,22 @@ export declare abstract class Adapter<R extends Endpoint = Endpoint, const Caps
52
77
  file?: boolean;
53
78
  maxAttachmentBytes?: number;
54
79
  };
55
- private renderSendMessage;
80
+ protected getOutboundRichSegmentPolicy(): OutboundRichSegmentPolicy;
81
+ /**
82
+ * 出站两阶段:
83
+ * 1. resolveRichSegments — 语义段 → 标准 IM 段(image/audio/text)
84
+ * 2. Endpoint materializeOutboundMedia — base64/本地路径 → 平台 URL(各 adapter 可选)
85
+ * @see docs/essentials/rich-segment-adapters.md
86
+ */
87
+ protected renderSendMessage(options: SendOptions): Promise<SendOptions>;
56
88
  sendMessage(options: SendOptions): Promise<string>;
89
+ /**
90
+ * 编辑已发送的消息。
91
+ * - 如果 Endpoint 实现了 $editMessage,调用平台编辑 API
92
+ * - 否则 fallback 到发送新消息
93
+ * @returns 消息 ID(编辑时返回原 ID,fallback 时返回新消息 ID)
94
+ */
95
+ editMessage(options: EditMessageOptions): Promise<string>;
57
96
  start(): Promise<void>;
58
97
  /**
59
98
  * 停止适配器,断开并移除所有 Endpoint 实例
@@ -95,4 +134,3 @@ export declare namespace Adapter {
95
134
  */
96
135
  function register(name: string, factory: Factory): void;
97
136
  }
98
- //# sourceMappingURL=adapter.d.ts.map
package/lib/adapter.js CHANGED
@@ -2,10 +2,14 @@ import { assertOutbound, DEFAULT_ENDPOINT_CAPABILITIES, hasInbound, } from "./en
2
2
  import { connectEndpointInstance, disconnectEndpointInstance } from "./built/connect-endpoint-instance.js";
3
3
  import { EventEmitter } from "node:events";
4
4
  import { getOutboundReplyStore } from "./built/dispatcher.js";
5
- import { coerceHtmlSegmentsToText } from "./built/html-segment-fallback.js";
5
+ import { DEFAULT_OUTBOUND_RICH_SEGMENT_POLICY, resolveRichSegments, } from "./built/rich-segments/index.js";
6
+ import { DEFAULT_INTERACTIVE_POLICY, resolveInteractiveSegments, } from "./built/interactive-segments/index.js";
7
+ import { DEFAULT_AI_OUTBOUND_CAPABILITIES, } from "./built/ai-outbound/index.js";
8
+ import { createRichSegmentRenderContext } from "./built/rich-segments/capabilities.js";
9
+ import { collectOutboundMediaKinds } from "./built/outbound-media-utils.js";
6
10
  import { segment } from "./utils.js";
7
11
  import { InboundMessagePipeline } from "./built/inbound-pipeline.js";
8
- import { formatCompact, truncatePreview } from '@zhin.js/logger';
12
+ import { formatCompact, truncatePreview, formatContentChainLog, CONTENT_CHAIN_STAGE } from '@zhin.js/logger';
9
13
  /**
10
14
  * Adapter类:适配器抽象,管理多平台Bot实例。
11
15
  * 负责根据配置启动/关闭各平台机器人,统一异常处理。
@@ -20,6 +24,17 @@ export class Adapter extends EventEmitter {
20
24
  recallMessageHandler;
21
25
  /** Adapter 支持的能力上限(子类覆盖) */
22
26
  static capabilities = DEFAULT_ENDPOINT_CAPABILITIES;
27
+ /** 出站富媒体段渲染策略(子类 override static) */
28
+ static outboundRichSegmentPolicy = DEFAULT_OUTBOUND_RICH_SEGMENT_POLICY;
29
+ /** 交互段出站策略:native 保留按钮段,text 降级为编号文本 */
30
+ static interactivePolicy = DEFAULT_INTERACTIVE_POLICY;
31
+ /** AI 结构化出站能力声明(mentions / richSegments / interactive) */
32
+ static aiOutboundCapabilities = DEFAULT_AI_OUTBOUND_CAPABILITIES;
33
+ /** 平台特有 extensions schema + 解析(对齐各 SDK 文档子集) */
34
+ static aiOutboundExtensions;
35
+ getInteractivePolicy() {
36
+ return this.constructor.interactivePolicy;
37
+ }
23
38
  /** 入站消息并发计数 */
24
39
  #pendingMessages = 0;
25
40
  /** 并发上限,0 表示不限制(默认) */
@@ -100,6 +115,21 @@ export class Adapter extends EventEmitter {
100
115
  binding(plugin) {
101
116
  this.plugin = plugin;
102
117
  }
118
+ /**
119
+ * 同步等待入站管线结束(middleware → dispatcher → 生命周期 → 观察者)。
120
+ * 用于 QQ 等需在被动回复完成后再 ack 交互的平台事件。
121
+ */
122
+ async receiveMessageAwait(message) {
123
+ if (this.inboundPipeline.shouldDropDueToBackpressure()) {
124
+ this.logger.warn(formatCompact({ drop: 'concurrency', limit: this.maxConcurrentMessages }));
125
+ return false;
126
+ }
127
+ this.#pendingMessages++;
128
+ await this.inboundPipeline.receive(message, () => {
129
+ EventEmitter.prototype.emit.call(this, 'message.receive', message);
130
+ });
131
+ return true;
132
+ }
103
133
  /**
104
134
  * 出站富媒体能力(Publisher 按此过滤/降级;各 adapter 可覆盖)。
105
135
  */
@@ -112,16 +142,50 @@ export class Adapter extends EventEmitter {
112
142
  maxAttachmentBytes: 26_214_400,
113
143
  };
114
144
  }
145
+ getOutboundRichSegmentPolicy() {
146
+ return this.constructor.outboundRichSegmentPolicy;
147
+ }
148
+ /**
149
+ * 出站两阶段:
150
+ * 1. resolveRichSegments — 语义段 → 标准 IM 段(image/audio/text)
151
+ * 2. Endpoint materializeOutboundMedia — base64/本地路径 → 平台 URL(各 adapter 可选)
152
+ * @see docs/essentials/rich-segment-adapters.md
153
+ */
115
154
  async renderSendMessage(options) {
155
+ if (options.content != null) {
156
+ options = {
157
+ ...options,
158
+ content: await resolveRichSegments(options.content, this.getOutboundRichSegmentPolicy(), createRichSegmentRenderContext({
159
+ getConfig: () => {
160
+ const cfg = this.plugin.root.inject('config')?.getPrimary();
161
+ return cfg;
162
+ },
163
+ warn: (msg) => this.logger.warn(msg),
164
+ logContentChain: (fields) => {
165
+ this.logger.debug(formatContentChainLog({ ...fields, adapter: this.name }));
166
+ },
167
+ })),
168
+ };
169
+ options = {
170
+ ...options,
171
+ content: resolveInteractiveSegments(options.content, this.getInteractivePolicy()),
172
+ };
173
+ const mediaKinds = collectOutboundMediaKinds(options.content);
174
+ if (mediaKinds.length > 0) {
175
+ this.logger.debug(formatContentChainLog({
176
+ stage: CONTENT_CHAIN_STAGE.OUTBOUND,
177
+ adapter: this.name,
178
+ endpoint: options.endpoint,
179
+ media: mediaKinds.join(','),
180
+ }));
181
+ }
182
+ }
116
183
  const fns = this.plugin.root.listeners('before.sendMessage');
117
184
  for (const fn of fns) {
118
185
  const result = await fn(options);
119
186
  if (result)
120
187
  options = result;
121
188
  }
122
- if (options.content != null) {
123
- options = { ...options, content: coerceHtmlSegmentsToText(options.content) };
124
- }
125
189
  return options;
126
190
  }
127
191
  async sendMessage(options) {
@@ -146,6 +210,47 @@ export class Adapter extends EventEmitter {
146
210
  });
147
211
  return messageId;
148
212
  }
213
+ /**
214
+ * 编辑已发送的消息。
215
+ * - 如果 Endpoint 实现了 $editMessage,调用平台编辑 API
216
+ * - 否则 fallback 到发送新消息
217
+ * @returns 消息 ID(编辑时返回原 ID,fallback 时返回新消息 ID)
218
+ */
219
+ async editMessage(options) {
220
+ const endpoint = this.endpoints.get(options.endpoint);
221
+ if (!endpoint)
222
+ throw new Error(`Endpoint ${options.endpoint} not found`);
223
+ assertOutbound(endpoint);
224
+ const editable = endpoint;
225
+ if (editable.$editMessage) {
226
+ const rendered = await this.renderSendMessage({
227
+ context: options.context,
228
+ endpoint: options.endpoint,
229
+ id: options.id,
230
+ type: options.type,
231
+ content: options.content,
232
+ });
233
+ await editable.$editMessage({ ...options, content: rendered.content });
234
+ this.logger.info(formatCompact({
235
+ edit: `${options.type}(${options.id})`,
236
+ endpoint: options.endpoint,
237
+ messageId: options.messageId,
238
+ }));
239
+ return options.messageId;
240
+ }
241
+ this.logger.debug(formatCompact({
242
+ editFallback: 'sendMessage',
243
+ endpoint: options.endpoint,
244
+ reason: '$editMessage not implemented',
245
+ }));
246
+ return this.sendMessage({
247
+ context: options.context,
248
+ endpoint: options.endpoint,
249
+ id: options.id,
250
+ type: options.type,
251
+ content: options.content,
252
+ });
253
+ }
149
254
  async start() {
150
255
  if (this.endpoints.size > 0) {
151
256
  await this.stop();
@@ -230,4 +335,3 @@ export class Adapter extends EventEmitter {
230
335
  }
231
336
  Adapter.register = register;
232
337
  })(Adapter || (Adapter = {}));
233
- //# sourceMappingURL=adapter.js.map
@@ -38,4 +38,3 @@ export interface AgentPromptContributor {
38
38
  /** Non-null replaces default TF-IDF deferred tool selection. */
39
39
  selectDeferredTools?(query: string, goal: string, catalog: DeferredToolCatalogItem[], maxTools: number): DeferredToolCatalogItem[] | null;
40
40
  }
41
- //# sourceMappingURL=agent-prompt.d.ts.map
@@ -1,2 +1 @@
1
1
  export {};
2
- //# sourceMappingURL=agent-prompt.js.map
@@ -1,4 +1,9 @@
1
- import { Adapter, Plugin, Endpoint, SendOptions, Message } from "@zhin.js/core";
1
+ import { Adapter } from "../adapter.js";
2
+ import { Plugin } from "../plugin.js";
3
+ import { Endpoint } from "../endpoint.js";
4
+ import { Message } from "../message.js";
5
+ import type { SendOptions } from "../types.js";
6
+ import type { OutboundRichSegmentPolicy } from "./rich-segments/types.js";
2
7
  export declare class ProcessEndpoint implements Endpoint<{
3
8
  owner?: string;
4
9
  }, {
@@ -33,7 +38,12 @@ export declare class ProcessEndpoint implements Endpoint<{
33
38
  }
34
39
  export declare class ProcessAdapter extends Adapter<ProcessEndpoint> {
35
40
  static readonly capabilities: readonly ["inbound", "outbound"];
41
+ static outboundRichSegmentPolicy: OutboundRichSegmentPolicy;
36
42
  constructor(plugin: Plugin);
43
+ /**
44
+ * process 出站由 $sendMessage 写入 stdout;父类 INFO preview 会与终端输出重复,故仅 debug 元数据。
45
+ */
46
+ sendMessage(options: SendOptions): Promise<string>;
37
47
  createEndpoint(config: Adapter.EndpointConfig<ProcessEndpoint>): ProcessEndpoint;
38
48
  }
39
49
  declare module '../adapter.js' {
@@ -41,4 +51,3 @@ declare module '../adapter.js' {
41
51
  process: ProcessAdapter;
42
52
  }
43
53
  }
44
- //# sourceMappingURL=adapter-process.d.ts.map
@@ -1,5 +1,11 @@
1
- import { Adapter, Message } from "@zhin.js/core";
1
+ import { formatCompact } from "@zhin.js/logger";
2
+ import { Adapter } from "../adapter.js";
3
+ import { Message } from "../message.js";
4
+ import { segment } from "../utils.js";
5
+ import { assertOutbound } from "../endpoint-capabilities.js";
6
+ import { getOutboundReplyStore } from "./dispatcher.js";
2
7
  import { bindStdin, runtimePid, runtimeUser } from "./runtime-io.js";
8
+ import { interpretOriginQrcodeForProcess } from "./rich-segments/qrcode-segment.js";
3
9
  export class ProcessEndpoint {
4
10
  adapter;
5
11
  $config;
@@ -59,6 +65,13 @@ export class ProcessEndpoint {
59
65
  async $recallMessage(id) {
60
66
  }
61
67
  async $sendMessage(options) {
68
+ const content = await interpretOriginQrcodeForProcess(options.content ?? '');
69
+ if (content != null) {
70
+ const preview = segment.raw(content);
71
+ if (preview) {
72
+ process.stdout.write(`${preview}\n`);
73
+ }
74
+ }
62
75
  return `${Date.now()}`;
63
76
  }
64
77
  async $connect() {
@@ -72,11 +85,39 @@ export class ProcessEndpoint {
72
85
  }
73
86
  export class ProcessAdapter extends Adapter {
74
87
  static capabilities = ['inbound', 'outbound'];
88
+ static outboundRichSegmentPolicy = {
89
+ qrcode: 'origin',
90
+ html: 'text',
91
+ markdown: 'text',
92
+ };
75
93
  constructor(plugin) {
76
94
  super(plugin, 'process', [{ owner: runtimePid() }]);
77
95
  }
96
+ /**
97
+ * process 出站由 $sendMessage 写入 stdout;父类 INFO preview 会与终端输出重复,故仅 debug 元数据。
98
+ */
99
+ async sendMessage(options) {
100
+ options = await this.renderSendMessage(options);
101
+ const endpoint = this.endpoints.get(options.endpoint);
102
+ if (!endpoint)
103
+ throw new Error(`Endpoint ${options.endpoint} not found`);
104
+ assertOutbound(endpoint);
105
+ this.logger.debug(formatCompact({
106
+ send: `${options.type}(${options.id})`,
107
+ endpoint: options.endpoint,
108
+ }));
109
+ const messageId = await endpoint.$sendMessage(options);
110
+ const replyStore = getOutboundReplyStore();
111
+ this.plugin.root.dispatch('message.send', {
112
+ adapter: this.name,
113
+ options,
114
+ messageId,
115
+ replySource: replyStore?.source,
116
+ replyMessage: replyStore?.message,
117
+ });
118
+ return messageId;
119
+ }
78
120
  createEndpoint(config) {
79
121
  return new ProcessEndpoint(this, config);
80
122
  }
81
123
  }
82
- //# sourceMappingURL=adapter-process.js.map
@@ -62,4 +62,3 @@ export declare class AgentPresetFeature extends Feature<AgentPreset> {
62
62
  }): AgentPreset[];
63
63
  toJSON(pluginName?: string): FeatureJSON;
64
64
  }
65
- //# sourceMappingURL=agent-preset.d.ts.map
@@ -77,4 +77,3 @@ export class AgentPresetFeature extends Feature {
77
77
  };
78
78
  }
79
79
  }
80
- //# sourceMappingURL=agent-preset.js.map
@@ -0,0 +1,36 @@
1
+ /**
2
+ * AI Access Gate — 控制 LLM 回复路径是否对当前会话开放(平台 AIGC 合规等)
3
+ */
4
+ import type { Message } from '../message.js';
5
+ export type AIAccessMode = 'open' | 'closed' | 'whitelist';
6
+ /** Endpoint 或全局 ai.access 配置块 */
7
+ export interface AIAccessScopeConfig {
8
+ mode?: AIAccessMode;
9
+ /** 允许触发 AI 的 sender.id */
10
+ users?: string[];
11
+ /** 允许触发 AI 的 group/channel id */
12
+ groups?: string[];
13
+ /** 私聊拒绝时的回复文案 */
14
+ denyMessage?: string;
15
+ }
16
+ /** 全局 ai.access 配置(与 AIAccessScopeConfig 同形) */
17
+ export type AIAccessConfig = AIAccessScopeConfig;
18
+ export interface ResolvedAIAccessConfig {
19
+ mode: AIAccessMode;
20
+ users: string[];
21
+ groups: string[];
22
+ denyMessage: string;
23
+ }
24
+ export interface AIAccessResult {
25
+ allowed: boolean;
26
+ reason: string;
27
+ /** 私聊拒绝时返回;群/频道拒绝为 undefined(静默) */
28
+ replyMessage?: string;
29
+ }
30
+ export declare const DEFAULT_AI_ACCESS_DENY_MESSAGE = "\u5F53\u524D\u4F1A\u8BDD\u672A\u5F00\u653E AI \u529F\u80FD\u3002";
31
+ export declare function resolveAIAccessConfig(global: AIAccessConfig | undefined, endpointScope?: AIAccessScopeConfig): ResolvedAIAccessConfig;
32
+ /**
33
+ * 判定当前消息是否允许进入 AI Handler(LLM 回复路径)。
34
+ * 不影响命令、游戏等其它 Dispatcher 分支。
35
+ */
36
+ export declare function checkAIAccess(message: Message<any>, globalConfig: AIAccessConfig | undefined, endpointScope?: AIAccessScopeConfig): AIAccessResult;
@@ -0,0 +1,46 @@
1
+ export const DEFAULT_AI_ACCESS_DENY_MESSAGE = '当前会话未开放 AI 功能。';
2
+ const DEFAULT_MODE = 'open';
3
+ export function resolveAIAccessConfig(global, endpointScope) {
4
+ const base = global ?? {};
5
+ const endpoint = endpointScope ?? {};
6
+ return {
7
+ mode: endpoint.mode ?? base.mode ?? DEFAULT_MODE,
8
+ users: endpoint.users ?? base.users ?? [],
9
+ groups: endpoint.groups ?? base.groups ?? [],
10
+ denyMessage: endpoint.denyMessage ?? base.denyMessage ?? DEFAULT_AI_ACCESS_DENY_MESSAGE,
11
+ };
12
+ }
13
+ function isWhitelisted(message, config) {
14
+ const userId = String(message.$sender?.id ?? '');
15
+ if (userId && config.users.includes(userId))
16
+ return true;
17
+ const scope = message.$channel?.type;
18
+ if (scope === 'group' || scope === 'channel') {
19
+ const channelId = String(message.$channel?.id ?? '');
20
+ if (channelId && config.groups.includes(channelId))
21
+ return true;
22
+ }
23
+ return false;
24
+ }
25
+ function denyResult(message, config, reason) {
26
+ const scope = message.$channel?.type;
27
+ const replyMessage = scope === 'private' ? config.denyMessage : undefined;
28
+ return { allowed: false, reason, replyMessage };
29
+ }
30
+ /**
31
+ * 判定当前消息是否允许进入 AI Handler(LLM 回复路径)。
32
+ * 不影响命令、游戏等其它 Dispatcher 分支。
33
+ */
34
+ export function checkAIAccess(message, globalConfig, endpointScope) {
35
+ const config = resolveAIAccessConfig(globalConfig, endpointScope);
36
+ if (config.mode === 'open') {
37
+ return { allowed: true, reason: 'mode: open' };
38
+ }
39
+ if (config.mode === 'closed') {
40
+ return denyResult(message, config, 'mode: closed');
41
+ }
42
+ if (isWhitelisted(message, config)) {
43
+ return { allowed: true, reason: 'whitelist: matched' };
44
+ }
45
+ return denyResult(message, config, 'whitelist: not matched');
46
+ }
@@ -0,0 +1,3 @@
1
+ import { type AiOutboundCapabilities, type AiOutboundExtensionDefinition } from './types.js';
2
+ export declare function getAdapterAiOutboundCapabilities(adapterInstance: object): AiOutboundCapabilities;
3
+ export declare function getAdapterAiOutboundExtensions(adapterInstance: object): readonly AiOutboundExtensionDefinition[];
@@ -0,0 +1,9 @@
1
+ import { DEFAULT_AI_OUTBOUND_CAPABILITIES, } from './types.js';
2
+ export function getAdapterAiOutboundCapabilities(adapterInstance) {
3
+ const ctor = adapterInstance.constructor;
4
+ return ctor.aiOutboundCapabilities ?? DEFAULT_AI_OUTBOUND_CAPABILITIES;
5
+ }
6
+ export function getAdapterAiOutboundExtensions(adapterInstance) {
7
+ const ctor = adapterInstance.constructor;
8
+ return ctor.aiOutboundExtensions ?? [];
9
+ }
@@ -0,0 +1,2 @@
1
+ import type { AiOutboundExtensionDefinition } from '../types.js';
2
+ export declare const ONEBOT_KEYBOARD_AI_OUTBOUND_EXTENSION: AiOutboundExtensionDefinition;
@@ -0,0 +1,67 @@
1
+ import { KeyboardSegment } from '../../interactive-segments/keyboard-segment.js';
2
+ const ONEBOT_KEYBOARD_SCHEMA = {
3
+ type: 'object',
4
+ properties: {
5
+ rows: {
6
+ type: 'array',
7
+ items: {
8
+ type: 'array',
9
+ items: {
10
+ type: 'object',
11
+ properties: {
12
+ label: { type: 'string' },
13
+ payload: { type: 'string' },
14
+ id: { type: 'string' },
15
+ },
16
+ required: ['label', 'payload'],
17
+ },
18
+ },
19
+ },
20
+ },
21
+ required: ['rows'],
22
+ };
23
+ function toKeyboardSegment(ext) {
24
+ if (!ext || typeof ext !== 'object')
25
+ return null;
26
+ const obj = ext;
27
+ const rowsRaw = obj.rows;
28
+ if (!Array.isArray(rowsRaw))
29
+ return null;
30
+ const rows = [];
31
+ for (const row of rowsRaw) {
32
+ if (!Array.isArray(row))
33
+ continue;
34
+ const buttons = [];
35
+ for (const btn of row) {
36
+ if (!btn || typeof btn !== 'object')
37
+ continue;
38
+ const b = btn;
39
+ const label = typeof b.label === 'string' ? b.label : '';
40
+ const payload = typeof b.payload === 'string' ? b.payload : '';
41
+ if (!label || !payload)
42
+ continue;
43
+ buttons.push({
44
+ id: typeof b.id === 'string' ? b.id : payload,
45
+ label,
46
+ payload,
47
+ disabled: b.disabled === true,
48
+ });
49
+ }
50
+ if (buttons.length)
51
+ rows.push(buttons);
52
+ }
53
+ if (!rows.length)
54
+ return null;
55
+ return new KeyboardSegment({ rows }).toElement();
56
+ }
57
+ export const ONEBOT_KEYBOARD_AI_OUTBOUND_EXTENSION = {
58
+ key: 'onebot.keyboard',
59
+ schema: ONEBOT_KEYBOARD_SCHEMA,
60
+ examples: [
61
+ '{"extensions":{"onebot.keyboard":{"rows":[[{"label":"确认","payload":"ok","id":"ok"}]]}}}',
62
+ ],
63
+ toMessageElements(ext, _ctx) {
64
+ const seg = toKeyboardSegment(ext);
65
+ return seg ? [seg] : [];
66
+ },
67
+ };