@zhin.js/core 1.1.33 → 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 (380) hide show
  1. package/README.md +140 -61
  2. package/lib/adapter.d.ts +72 -23
  3. package/lib/adapter.js +222 -58
  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 +9 -0
  63. package/lib/built/html-segment-fallback.js +49 -0
  64. package/lib/built/html-to-text.d.ts +4 -1
  65. package/lib/built/html-to-text.js +47 -16
  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 +67 -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 -21
  209. package/lib/index.js +53 -28
  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 -85
  269. package/lib/types.js +0 -1
  270. package/lib/utils.d.ts +68 -1
  271. package/lib/utils.js +73 -11
  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-to-text.d.ts.map +0 -1
  306. package/lib/built/html-to-text.js.map +0 -1
  307. package/lib/built/inbound-runner.d.ts.map +0 -1
  308. package/lib/built/inbound-runner.js.map +0 -1
  309. package/lib/built/login-assist.d.ts.map +0 -1
  310. package/lib/built/login-assist.js.map +0 -1
  311. package/lib/built/message-filter.d.ts.map +0 -1
  312. package/lib/built/message-filter.js.map +0 -1
  313. package/lib/built/permission.d.ts.map +0 -1
  314. package/lib/built/permission.js.map +0 -1
  315. package/lib/built/prepend-quote-context.d.ts +0 -33
  316. package/lib/built/prepend-quote-context.d.ts.map +0 -1
  317. package/lib/built/prepend-quote-context.js +0 -129
  318. package/lib/built/prepend-quote-context.js.map +0 -1
  319. package/lib/built/queue-im-field-contract.d.ts.map +0 -1
  320. package/lib/built/queue-im-field-contract.js.map +0 -1
  321. package/lib/built/roles.d.ts.map +0 -1
  322. package/lib/built/roles.js.map +0 -1
  323. package/lib/built/runtime-io.d.ts.map +0 -1
  324. package/lib/built/runtime-io.js.map +0 -1
  325. package/lib/built/schema-feature.d.ts.map +0 -1
  326. package/lib/built/schema-feature.js.map +0 -1
  327. package/lib/built/skill.d.ts.map +0 -1
  328. package/lib/built/skill.js.map +0 -1
  329. package/lib/built/tool.d.ts.map +0 -1
  330. package/lib/built/tool.js.map +0 -1
  331. package/lib/command.d.ts.map +0 -1
  332. package/lib/command.js.map +0 -1
  333. package/lib/component.d.ts.map +0 -1
  334. package/lib/component.js.map +0 -1
  335. package/lib/errors.d.ts.map +0 -1
  336. package/lib/errors.js.map +0 -1
  337. package/lib/index.d.ts.map +0 -1
  338. package/lib/index.js.map +0 -1
  339. package/lib/jsx-dev-runtime.d.ts.map +0 -1
  340. package/lib/jsx-dev-runtime.js.map +0 -1
  341. package/lib/jsx-runtime.d.ts.map +0 -1
  342. package/lib/jsx-runtime.js.map +0 -1
  343. package/lib/jsx.d.ts.map +0 -1
  344. package/lib/jsx.js.map +0 -1
  345. package/lib/message-quote.d.ts +0 -11
  346. package/lib/message-quote.d.ts.map +0 -1
  347. package/lib/message-quote.js +0 -91
  348. package/lib/message-quote.js.map +0 -1
  349. package/lib/message.d.ts.map +0 -1
  350. package/lib/message.js.map +0 -1
  351. package/lib/models/system-log.d.ts.map +0 -1
  352. package/lib/models/system-log.js.map +0 -1
  353. package/lib/models/user.d.ts.map +0 -1
  354. package/lib/models/user.js.map +0 -1
  355. package/lib/notice.d.ts.map +0 -1
  356. package/lib/notice.js.map +0 -1
  357. package/lib/plugin.d.ts.map +0 -1
  358. package/lib/plugin.js.map +0 -1
  359. package/lib/prompt.d.ts.map +0 -1
  360. package/lib/prompt.js.map +0 -1
  361. package/lib/request.d.ts.map +0 -1
  362. package/lib/request.js.map +0 -1
  363. package/lib/scheduler/scheduler.d.ts +0 -49
  364. package/lib/scheduler/scheduler.d.ts.map +0 -1
  365. package/lib/scheduler/scheduler.js +0 -352
  366. package/lib/scheduler/scheduler.js.map +0 -1
  367. package/lib/scheduler/types.d.ts +0 -71
  368. package/lib/scheduler/types.d.ts.map +0 -1
  369. package/lib/scheduler/types.js +0 -8
  370. package/lib/scheduler/types.js.map +0 -1
  371. package/lib/tool-zod.d.ts.map +0 -1
  372. package/lib/tool-zod.js.map +0 -1
  373. package/lib/types-generator.d.ts +0 -6
  374. package/lib/types-generator.d.ts.map +0 -1
  375. package/lib/types-generator.js +0 -72
  376. package/lib/types-generator.js.map +0 -1
  377. package/lib/types.d.ts.map +0 -1
  378. package/lib/types.js.map +0 -1
  379. package/lib/utils.d.ts.map +0 -1
  380. package/lib/utils.js.map +0 -1
@@ -0,0 +1,32 @@
1
+ import { createWarnOnce, resetWarnOnceForTests } from '@zhin.js/logger';
2
+ import { importOptionalPeerPackage } from './optional-peer-import.js';
3
+ /** 动态 import 时使用的包名(与 @zhin.js/speech package.json 一致) */
4
+ export const SPEECH_PACKAGE = '@zhin.js/speech';
5
+ let cached;
6
+ const speechPeerWarnOnce = createWarnOnce('speech');
7
+ /** zhin 启动时已创建 pipeline 时注入 */
8
+ export function seedSpeechPipeline(pipeline) {
9
+ cached = pipeline;
10
+ }
11
+ /** 动态加载 @zhin.js/speech;未安装时 warn 一次并返回 undefined */
12
+ export async function loadSpeechPipeline(opts) {
13
+ if (cached !== undefined) {
14
+ return cached ?? undefined;
15
+ }
16
+ try {
17
+ const mod = await importOptionalPeerPackage(SPEECH_PACKAGE);
18
+ const speechConfig = opts?.getConfig?.()?.speech;
19
+ cached = mod.createSpeechPipeline(speechConfig);
20
+ return cached;
21
+ }
22
+ catch {
23
+ speechPeerWarnOnce(opts?.warn, `未安装 ${SPEECH_PACKAGE},STT/TTS 已降级。安装: pnpm add ${SPEECH_PACKAGE}`);
24
+ cached = null;
25
+ return undefined;
26
+ }
27
+ }
28
+ /** 测试用:重置加载缓存 */
29
+ export function resetSpeechLoaderForTests() {
30
+ cached = undefined;
31
+ resetWarnOnceForTests('speech');
32
+ }
@@ -3,11 +3,14 @@
3
3
  * 工具仅面向 AI(通过 MCP 注册),不再与 Command 互转
4
4
  */
5
5
  import { Feature, FeatureJSON } from "@zhin.js/kernel";
6
- import type { Tool, ToolContext, ToolJsonSchema, ToolParametersSchema, PropertySchema, MaybePromise, ToolScope } from "../types.js";
6
+ import type { Tool, ToolJsonSchema, ToolParametersSchema, PropertySchema, MaybePromise, ToolScope } from "../types.js";
7
+ import type { Message } from "../message.js";
8
+ import { type PermissionHost } from '@zhin.js/permission';
7
9
  /**
8
- * 检查工具是否可被当前上下文访问
10
+ * 检查工具是否可被当前 Message 通讯上下文访问。
11
+ * `host` 为 PermissionHost 实例;无 host 且有 permissions → deny。
9
12
  */
10
- export declare function canAccessTool(tool: Tool, context: ToolContext): boolean;
13
+ export declare function canAccessTool(tool: Tool, message?: Message<any>, host?: PermissionHost | null): Promise<boolean>;
11
14
  /**
12
15
  * 从参数定义中提取参数信息
13
16
  */
@@ -38,7 +41,6 @@ export declare class ZhinTool {
38
41
  param(name: string, schema: PropertySchema, required?: boolean): this;
39
42
  platform(...platforms: string[]): this;
40
43
  scope(...scopes: ToolScope[]): this;
41
- requireAnyRole(...roles: import('./roles.js').SenderRole[]): this;
42
44
  permit(...permissions: string[]): this;
43
45
  tag(...tags: string[]): this;
44
46
  keyword(...keywords: string[]): this;
@@ -51,7 +53,7 @@ export declare class ZhinTool {
51
53
  preExec(value?: boolean): this;
52
54
  /** 设置工具分类(如 file / shell / web),用于展示与 TOOLS.md 协同 */
53
55
  kind(value: string): this;
54
- execute(callback: (args: Record<string, any>, context?: ToolContext) => MaybePromise<any>): this;
56
+ execute(callback: (args: Record<string, any>, message?: Message<any>) => MaybePromise<any>): this;
55
57
  toTool(): Tool;
56
58
  toJSON(): {
57
59
  name: string;
@@ -59,7 +61,7 @@ export declare class ZhinTool {
59
61
  parameters: ToolParametersSchema;
60
62
  platforms?: string[];
61
63
  scopes?: ToolScope[];
62
- requiredAnyRole?: import('./roles.js').SenderRole[];
64
+ permissions?: string[];
63
65
  tags?: string[];
64
66
  };
65
67
  get help(): string;
@@ -71,15 +73,15 @@ export declare function isZhinTool(obj: any): obj is ZhinTool;
71
73
  */
72
74
  export type ToolInput = Tool | ZhinTool;
73
75
  /**
74
- * ToolContext 扩展方法类型
76
+ * Message 工具扩展方法类型
75
77
  */
76
- export interface ToolContextExtensions {
78
+ export interface MessageToolExtensions {
77
79
  /** 添加工具 */
78
80
  addTool(tool: ToolInput): () => void;
79
81
  }
80
82
  declare module "../plugin.js" {
81
83
  namespace Plugin {
82
- interface Extensions extends ToolContextExtensions {
84
+ interface Extensions extends MessageToolExtensions {
83
85
  }
84
86
  interface Contexts {
85
87
  tool: ToolFeature;
@@ -118,11 +120,11 @@ export declare class ToolFeature extends Feature<Tool> {
118
120
  /**
119
121
  * 执行工具
120
122
  */
121
- execute(name: string, args: Record<string, any>, context?: ToolContext): Promise<any>;
123
+ execute(name: string, args: Record<string, any>, message?: Message<any>): Promise<any>;
122
124
  /**
123
- * 根据上下文过滤工具
125
+ * 根据 Message 通讯上下文过滤工具
124
126
  */
125
- filterByContext(tools: Tool[], context: ToolContext): Tool[];
127
+ filterByContext(tools: Tool[], message?: Message<any>, host?: PermissionHost | null): Promise<Tool[]>;
126
128
  /**
127
129
  * 按插件名获取工具
128
130
  */
@@ -147,4 +149,3 @@ export declare class ToolFeature extends Feature<Tool> {
147
149
  };
148
150
  }
149
151
  export {};
150
- //# sourceMappingURL=tool.d.ts.map
package/lib/built/tool.js CHANGED
@@ -3,19 +3,28 @@
3
3
  * 工具仅面向 AI(通过 MCP 注册),不再与 Command 互转
4
4
  */
5
5
  import { Feature } from "@zhin.js/kernel";
6
- import { getPlugin } from "../plugin.js";
7
- import { roleSatisfies, resolveRolesFromContext } from './roles.js';
6
+ import { toPermissionSubject } from '@zhin.js/permission';
8
7
  /**
9
- * 检查工具是否可被当前上下文访问
8
+ * 检查工具是否可被当前 Message 通讯上下文访问。
9
+ * `host` 为 PermissionHost 实例;无 host 且有 permissions → deny。
10
10
  */
11
- export function canAccessTool(tool, context) {
12
- if (tool.platforms?.length && (!context.platform || !tool.platforms.includes(context.platform))) {
11
+ export async function canAccessTool(tool, message, host) {
12
+ if (!message)
13
+ return !tool.platforms?.length && !tool.scopes?.length && !tool.permissions?.length;
14
+ const adapter = String(message.$adapter);
15
+ const scope = (message.$channel?.type || 'private');
16
+ if (tool.platforms?.length && !tool.platforms.includes(adapter)) {
13
17
  return false;
14
18
  }
15
- if (tool.scopes?.length && (!context.scope || !tool.scopes.includes(context.scope))) {
19
+ if (tool.scopes?.length && !tool.scopes.includes(scope)) {
16
20
  return false;
17
21
  }
18
- return roleSatisfies(resolveRolesFromContext(context), tool.requiredAnyRole);
22
+ if (!tool.permissions?.length)
23
+ return true;
24
+ if (!host)
25
+ return false;
26
+ const subject = toPermissionSubject(message);
27
+ return host.checkAll(tool.permissions, subject);
19
28
  }
20
29
  // ============================================================================
21
30
  // Tool 工具函数
@@ -54,7 +63,6 @@ export class ZhinTool {
54
63
  #execute;
55
64
  #platforms = [];
56
65
  #scopes = [];
57
- #requiredAnyRole = [];
58
66
  #permissions = [];
59
67
  #tags = [];
60
68
  #keywords = [];
@@ -96,10 +104,6 @@ export class ZhinTool {
96
104
  this.#scopes.push(...scopes);
97
105
  return this;
98
106
  }
99
- requireAnyRole(...roles) {
100
- this.#requiredAnyRole = [...roles];
101
- return this;
102
- }
103
107
  permit(...permissions) {
104
108
  this.#permissions.push(...permissions);
105
109
  return this;
@@ -170,8 +174,6 @@ export class ZhinTool {
170
174
  tool.platforms = this.#platforms;
171
175
  if (this.#scopes.length > 0)
172
176
  tool.scopes = this.#scopes;
173
- if (this.#requiredAnyRole.length > 0)
174
- tool.requiredAnyRole = [...this.#requiredAnyRole];
175
177
  if (this.#permissions.length > 0)
176
178
  tool.permissions = this.#permissions;
177
179
  if (this.#tags.length > 0)
@@ -198,8 +200,8 @@ export class ZhinTool {
198
200
  json.platforms = this.#platforms;
199
201
  if (this.#scopes.length > 0)
200
202
  json.scopes = this.#scopes;
201
- if (this.#requiredAnyRole.length > 0)
202
- json.requiredAnyRole = [...this.#requiredAnyRole];
203
+ if (this.#permissions.length > 0)
204
+ json.permissions = [...this.#permissions];
203
205
  if (this.#tags.length > 0)
204
206
  json.tags = this.#tags;
205
207
  return json;
@@ -216,8 +218,8 @@ export class ZhinTool {
216
218
  lines.push(` ${param.name}: ${param.schema.type} ${required} ${desc}`);
217
219
  }
218
220
  }
219
- if (this.#requiredAnyRole.length > 0) {
220
- lines.push(` 角色: ${this.#requiredAnyRole.join(', ')}`);
221
+ if (this.#permissions.length > 0) {
222
+ lines.push(` 权限: ${this.#permissions.join(', ')}`);
221
223
  }
222
224
  if (this.#platforms.length > 0) {
223
225
  lines.push(` 平台: ${this.#platforms.join(', ')}`);
@@ -305,18 +307,22 @@ export class ToolFeature extends Feature {
305
307
  /**
306
308
  * 执行工具
307
309
  */
308
- async execute(name, args, context) {
310
+ async execute(name, args, message) {
309
311
  const tool = this.byName.get(name);
310
312
  if (!tool) {
311
313
  throw new Error(`Tool "${name}" not found`);
312
314
  }
313
- return tool.execute(args, context);
315
+ return tool.execute(args, message);
314
316
  }
315
317
  /**
316
- * 根据上下文过滤工具
318
+ * 根据 Message 通讯上下文过滤工具
317
319
  */
318
- filterByContext(tools, context) {
319
- return tools.filter(tool => canAccessTool(tool, context));
320
+ async filterByContext(tools, message, host) {
321
+ const results = await Promise.all(tools.map(async (tool) => ({
322
+ tool,
323
+ allowed: await canAccessTool(tool, message, host),
324
+ })));
325
+ return results.filter((r) => r.allowed).map((r) => r.tool);
320
326
  }
321
327
  /**
322
328
  * 按插件名获取工具
@@ -370,7 +376,7 @@ export class ToolFeature extends Feature {
370
376
  const feature = this;
371
377
  return {
372
378
  addTool(tool) {
373
- const plugin = getPlugin();
379
+ const plugin = this;
374
380
  const toolObj = isZhinTool(tool) ? tool.toTool() : tool;
375
381
  const dispose = feature.addTool(tool, plugin.name);
376
382
  plugin.recordFeatureContribution(feature.name, toolObj.name);
@@ -380,4 +386,3 @@ export class ToolFeature extends Feature {
380
386
  };
381
387
  }
382
388
  }
383
- //# sourceMappingURL=tool.js.map
@@ -0,0 +1,30 @@
1
+ import type { UserInteractionContent, UserInteractionRequest } from '@zhin.js/interaction';
2
+ import type { SendContent } from '../plugin-runtime/im/contracts.js';
3
+ import type { ButtonStyle } from './interactive-segments/types.js';
4
+ export interface UserInteractionAction {
5
+ readonly label: string;
6
+ readonly value: string;
7
+ readonly style?: ButtonStyle;
8
+ }
9
+ export interface UserInteractionView extends UserInteractionContent {
10
+ readonly actions?: readonly UserInteractionAction[];
11
+ }
12
+ export interface UserInteractionProgress extends UserInteractionContent {
13
+ readonly index: number;
14
+ readonly total: number;
15
+ }
16
+ export type UserInteractionParseResult = Readonly<{
17
+ ok: true;
18
+ value: unknown;
19
+ }> | Readonly<{
20
+ ok: false;
21
+ message: string;
22
+ }>;
23
+ /** Fail early for interaction definitions that could never produce an unambiguous answer. */
24
+ export declare function assertUserInteractionRequest(request: UserInteractionRequest): void;
25
+ /** Project semantic content into canonical Markdown + keyboard segments. */
26
+ export declare function renderUserInteraction(view: UserInteractionView): SendContent;
27
+ /** Derive presentation and controls from one discriminated request. */
28
+ export declare function projectUserInteraction(request: UserInteractionRequest, progress?: UserInteractionProgress): UserInteractionView;
29
+ /** Parse and validate one user reply without transport knowledge. */
30
+ export declare function parseUserInteractionAnswer(request: UserInteractionRequest, rawInput: string): UserInteractionParseResult;
@@ -0,0 +1,248 @@
1
+ /** Fail early for interaction definitions that could never produce an unambiguous answer. */
2
+ export function assertUserInteractionRequest(request) {
3
+ if (!request.title.trim())
4
+ throw new TypeError('User interaction title must not be empty');
5
+ if (request.timeout !== undefined && (!Number.isFinite(request.timeout) || request.timeout <= 0)) {
6
+ throw new RangeError('User interaction timeout must be a positive finite number');
7
+ }
8
+ if (request.type === 'text' && !validRange(request.minLength, request.maxLength)) {
9
+ throw new RangeError('User interaction text length range is invalid');
10
+ }
11
+ if (request.type === 'number' && !validBounds(request.min, request.max)) {
12
+ throw new RangeError('User interaction number range is invalid');
13
+ }
14
+ if (request.type === 'select' || request.type === 'multiselect') {
15
+ if (request.options.length === 0)
16
+ throw new TypeError('User interaction options must not be empty');
17
+ const labels = new Set();
18
+ for (const option of request.options) {
19
+ const label = option.label.trim().toLocaleLowerCase();
20
+ if (!label)
21
+ throw new TypeError('User interaction option label must not be empty');
22
+ if (labels.has(label))
23
+ throw new TypeError(`Duplicate user interaction option label: ${option.label}`);
24
+ labels.add(label);
25
+ }
26
+ }
27
+ if (request.type === 'multiselect') {
28
+ if (request.separator === '')
29
+ throw new TypeError('User interaction separator must not be empty');
30
+ if (!validRange(request.minSelections, request.maxSelections)) {
31
+ throw new RangeError('User interaction selection range is invalid');
32
+ }
33
+ }
34
+ if (request.type === 'list') {
35
+ if (request.separator === '')
36
+ throw new TypeError('User interaction separator must not be empty');
37
+ if (!validRange(request.minItems, request.maxItems)) {
38
+ throw new RangeError('User interaction list length range is invalid');
39
+ }
40
+ }
41
+ }
42
+ /** Project semantic content into canonical Markdown + keyboard segments. */
43
+ export function renderUserInteraction(view) {
44
+ const markdown = [
45
+ `### ${view.title}`,
46
+ view.description?.trim(),
47
+ view.tip?.trim() ? quoteTip(view.tip.trim()) : undefined,
48
+ ].filter((part) => !!part).join('\n\n');
49
+ const actions = view.actions ?? [];
50
+ if (actions.length === 0) {
51
+ return [{ type: 'markdown', data: { content: markdown } }];
52
+ }
53
+ const buttons = actions.map((action, index) => ({
54
+ id: `interaction-${index + 1}`,
55
+ label: action.label,
56
+ payload: action.value,
57
+ ...(action.style ? { style: action.style } : {}),
58
+ mode: 'command',
59
+ command: { enter: true, reply: false },
60
+ }));
61
+ return [
62
+ { type: 'markdown', data: { content: markdown } },
63
+ {
64
+ type: 'keyboard',
65
+ data: {
66
+ rows: chunk(buttons, 5),
67
+ fallback: {
68
+ hint: '也可以直接回复对应内容。',
69
+ map: Object.fromEntries(actions.map((action, index) => [String(index + 1), action.value])),
70
+ },
71
+ },
72
+ },
73
+ ];
74
+ }
75
+ /** Derive presentation and controls from one discriminated request. */
76
+ export function projectUserInteraction(request, progress) {
77
+ const instruction = instructionFor(request);
78
+ const optionList = request.type === 'select' || request.type === 'multiselect'
79
+ ? renderOptions(request.options)
80
+ : undefined;
81
+ const optionsHaveDescriptions = request.type === 'select' || request.type === 'multiselect'
82
+ ? request.options.some((option) => !!option.description)
83
+ : false;
84
+ const actions = actionsFor(request);
85
+ const stepDescription = [
86
+ progress ? `**${progress.index}/${progress.total} · ${request.title}**` : undefined,
87
+ request.description,
88
+ optionList && (!actions || optionsHaveDescriptions) ? optionList : undefined,
89
+ ].filter((part) => !!part).join('\n\n');
90
+ return Object.freeze({
91
+ title: progress?.title ?? request.title,
92
+ description: progress
93
+ ? [progress.description, stepDescription].filter(Boolean).join('\n\n')
94
+ : stepDescription || undefined,
95
+ tip: [request.tip, instruction, progress?.tip].filter(Boolean).join('\n'),
96
+ ...(actions ? { actions: Object.freeze(actions) } : {}),
97
+ });
98
+ }
99
+ /** Parse and validate one user reply without transport knowledge. */
100
+ export function parseUserInteractionAnswer(request, rawInput) {
101
+ const raw = rawInput.trim();
102
+ switch (request.type) {
103
+ case 'text': {
104
+ if (raw.length < (request.minLength ?? 0))
105
+ return invalid(`请至少输入 ${request.minLength} 个字符`);
106
+ if (request.maxLength !== undefined && raw.length > request.maxLength) {
107
+ return invalid(`请不要超过 ${request.maxLength} 个字符`);
108
+ }
109
+ if (request.pattern) {
110
+ request.pattern.lastIndex = 0;
111
+ if (!request.pattern.test(raw))
112
+ return invalid('输入格式不正确');
113
+ }
114
+ return valid(raw);
115
+ }
116
+ case 'number': {
117
+ const value = Number(raw);
118
+ if (!raw || !Number.isFinite(value))
119
+ return invalid('请输入有效数字');
120
+ if (request.integer && !Number.isInteger(value))
121
+ return invalid('请输入整数');
122
+ if (request.min !== undefined && value < request.min)
123
+ return invalid(`请输入不小于 ${request.min} 的数字`);
124
+ if (request.max !== undefined && value > request.max)
125
+ return invalid(`请输入不大于 ${request.max} 的数字`);
126
+ return valid(value);
127
+ }
128
+ case 'confirm': {
129
+ const normalized = raw.toLocaleLowerCase();
130
+ const confirmLabel = request.confirmLabel?.trim().toLocaleLowerCase();
131
+ const cancelLabel = request.cancelLabel?.trim().toLocaleLowerCase();
132
+ if (CONFIRM_VALUES.has(normalized) || (confirmLabel && normalized === confirmLabel))
133
+ return valid(true);
134
+ if (CANCEL_VALUES.has(normalized) || (cancelLabel && normalized === cancelLabel))
135
+ return valid(false);
136
+ return invalid('请选择确认或取消');
137
+ }
138
+ case 'select': {
139
+ const option = resolveOption(request.options, raw);
140
+ return option ? valid(option.value) : invalid('请选择一个有效选项');
141
+ }
142
+ case 'multiselect': {
143
+ const separator = request.separator ?? ',';
144
+ const tokens = raw.split(separator).map((token) => token.trim()).filter(Boolean);
145
+ const selected = uniqueOptions(tokens.map((token) => resolveOption(request.options, token)));
146
+ if (selected.length !== tokens.length)
147
+ return invalid('多选中包含无效选项');
148
+ if (selected.length < (request.minSelections ?? 0))
149
+ return invalid(`请至少选择 ${request.minSelections} 项`);
150
+ if (request.maxSelections !== undefined && selected.length > request.maxSelections) {
151
+ return invalid(`请最多选择 ${request.maxSelections} 项`);
152
+ }
153
+ return valid(Object.freeze(selected.map((option) => option.value)));
154
+ }
155
+ case 'list': {
156
+ const separator = request.separator ?? ',';
157
+ const tokens = raw.split(separator).map((token) => token.trim()).filter(Boolean);
158
+ if (tokens.length < (request.minItems ?? 0))
159
+ return invalid(`请至少输入 ${request.minItems} 项`);
160
+ if (request.maxItems !== undefined && tokens.length > request.maxItems)
161
+ return invalid(`请最多输入 ${request.maxItems} 项`);
162
+ if (request.valueType === 'number') {
163
+ const values = tokens.map(Number);
164
+ return values.every(Number.isFinite) ? valid(Object.freeze(values)) : invalid('列表中包含无效数字');
165
+ }
166
+ if (request.valueType === 'boolean') {
167
+ const values = tokens.map(parseBoolean);
168
+ return values.every((value) => value !== undefined)
169
+ ? valid(Object.freeze(values))
170
+ : invalid('布尔列表只接受 true/false、yes/no 或 是/否');
171
+ }
172
+ return valid(Object.freeze(tokens));
173
+ }
174
+ }
175
+ }
176
+ function actionsFor(request) {
177
+ if (request.type === 'confirm') {
178
+ return [
179
+ { label: request.confirmLabel ?? '确认', value: 'yes', style: 'primary' },
180
+ { label: request.cancelLabel ?? '取消', value: 'no', style: 'danger' },
181
+ ];
182
+ }
183
+ if (request.type === 'select' && request.options.length <= 10) {
184
+ return request.options.map((option, index) => ({ label: option.label, value: String(index + 1), style: 'secondary' }));
185
+ }
186
+ return undefined;
187
+ }
188
+ function instructionFor(request) {
189
+ switch (request.type) {
190
+ case 'confirm': return '请选择确认或取消。';
191
+ case 'select': return '可以点击按钮,或回复序号/选项名称。';
192
+ case 'multiselect': return `回复序号或选项名称,多项用“${request.separator ?? ','}”分隔。`;
193
+ case 'list': return `多项用“${request.separator ?? ','}”分隔。`;
194
+ default: return undefined;
195
+ }
196
+ }
197
+ function renderOptions(options) {
198
+ return options.map((option, index) => `${index + 1}. ${option.label}${option.description ? ` — ${option.description}` : ''}`).join('\n');
199
+ }
200
+ function resolveOption(options, raw) {
201
+ const index = Number(raw);
202
+ if (Number.isInteger(index) && index >= 1 && index <= options.length)
203
+ return options[index - 1];
204
+ const normalized = raw.toLocaleLowerCase();
205
+ return options.find((option) => option.label.trim().toLocaleLowerCase() === normalized);
206
+ }
207
+ function uniqueOptions(options) {
208
+ const result = [];
209
+ for (const option of options)
210
+ if (option && !result.includes(option))
211
+ result.push(option);
212
+ return result;
213
+ }
214
+ function parseBoolean(raw) {
215
+ const normalized = raw.toLocaleLowerCase();
216
+ if (CONFIRM_VALUES.has(normalized))
217
+ return true;
218
+ if (CANCEL_VALUES.has(normalized))
219
+ return false;
220
+ return undefined;
221
+ }
222
+ function quoteTip(tip) {
223
+ return tip.split('\n').map((line) => `> 💡 ${line}`).join('\n');
224
+ }
225
+ function valid(value) {
226
+ return Object.freeze({ ok: true, value });
227
+ }
228
+ function invalid(message) {
229
+ return Object.freeze({ ok: false, message });
230
+ }
231
+ function validRange(minimum, maximum) {
232
+ return (minimum === undefined || (Number.isFinite(minimum) && minimum >= 0))
233
+ && (maximum === undefined || (Number.isFinite(maximum) && maximum >= 0))
234
+ && (minimum === undefined || maximum === undefined || minimum <= maximum);
235
+ }
236
+ function validBounds(minimum, maximum) {
237
+ return (minimum === undefined || Number.isFinite(minimum))
238
+ && (maximum === undefined || Number.isFinite(maximum))
239
+ && (minimum === undefined || maximum === undefined || minimum <= maximum);
240
+ }
241
+ const CONFIRM_VALUES = new Set(['1', 'y', 'yes', 'true', '是', '确认', '同意']);
242
+ const CANCEL_VALUES = new Set(['2', 'n', 'no', 'false', '否', '取消', '拒绝']);
243
+ function chunk(items, size) {
244
+ const rows = [];
245
+ for (let index = 0; index < items.length; index += size)
246
+ rows.push(items.slice(index, index + size));
247
+ return rows;
248
+ }
package/lib/command.d.ts CHANGED
@@ -1,16 +1,20 @@
1
- import { MatchResult, SegmentMatcher } from "segment-matcher";
2
- import { AdapterMessage, SendContent } from "./types.js";
3
- import { RegisteredAdapter } from "./types.js";
4
- import type { Message } from "./message.js";
5
- import { MaybePromise } from "./types.js";
6
- import { Plugin } from "./plugin.js";
1
+ import { MatchResult, SegmentMatcher } from 'segment-matcher';
2
+ import { AdapterMessage, SendContent, RegisteredAdapter, MaybePromise } from './types.js';
3
+ import type { Message } from './message.js';
4
+ import { type PermissionHost } from '@zhin.js/permission';
5
+ type ConstructFirstParam<T extends new (...args: any[]) => any> = T extends new (...args: [infer U, ...any[]]) => any ? U : never;
6
+ type ConstructSecondParam<T extends new (...args: any[]) => any> = T extends new (...args: [any, infer V, ...any[]]) => any ? V : never;
7
7
  /**
8
- * MessageCommand类:命令系统核心,基于segment-matcher实现。
9
- * 支持多平台命令注册、作用域限制、参数解析、异步处理等。
8
+ * MessageCommand类:经典命令系统(segment-matcher)。
9
+ *
10
+ * @deprecated 新插件请用 `defineCommand`(`zhin.js/command`)+ `commands/` 约定目录。
11
+ * 本类仍供 Agent init / game-kit hub / legacy `CommandFeature` 使用;计划随经典
12
+ * Plugin 路径一并退役。见 `docs/contributing/public-api-surface.md`。
10
13
  */
11
14
  export declare class MessageCommand<T extends RegisteredAdapter = RegisteredAdapter> extends SegmentMatcher {
12
15
  #private;
13
16
  get helpInfo(): MessageCommand.HelpInfo;
17
+ constructor(C: ConstructFirstParam<typeof SegmentMatcher>, P?: ConstructSecondParam<typeof SegmentMatcher>);
14
18
  get help(): string;
15
19
  desc(...desc: string[]): MessageCommand<T>;
16
20
  usage(...usage: string[]): MessageCommand<T>;
@@ -21,13 +25,17 @@ export declare class MessageCommand<T extends RegisteredAdapter = RegisteredAdap
21
25
  */
22
26
  action(callback: MessageCommand.Callback<T>): MessageCommand<T>;
23
27
  permit(...permissions: string[]): MessageCommand<T>;
28
+ /** 命令要求的 permit 列表(空表示所有人可用) */
29
+ get requiredPermits(): readonly string[];
30
+ /** 与 handle 一致的 permit 校验,供帮助菜单等场景过滤不可见命令 */
31
+ checkPermits(message: Message<AdapterMessage<T>>, host: PermissionHost | null): Promise<boolean>;
24
32
  /**
25
33
  * 处理消息,自动匹配命令并执行回调
26
34
  * @param message 消息对象
27
- * @param plugin 插件实例
35
+ * @param host PermissionHost(null 时有 permit 的命令 fail-closed)
28
36
  * @returns 命令返回内容或undefined
29
37
  */
30
- handle(message: Message<AdapterMessage<T>>, plugin: Plugin): Promise<SendContent | undefined>;
38
+ handle(message: Message<AdapterMessage<T>>, host: PermissionHost | null): Promise<SendContent | undefined>;
31
39
  }
32
40
  export declare namespace MessageCommand {
33
41
  type Callback<T extends RegisteredAdapter> = (message: Message<AdapterMessage<T>>, result: MatchResult) => SendContent | undefined | Promise<SendContent | undefined>;
@@ -39,4 +47,4 @@ export declare namespace MessageCommand {
39
47
  examples: string[];
40
48
  };
41
49
  }
42
- //# sourceMappingURL=command.d.ts.map
50
+ export {};
package/lib/command.js CHANGED
@@ -1,7 +1,11 @@
1
- import { SegmentMatcher } from "segment-matcher";
1
+ import { SegmentMatcher } from 'segment-matcher';
2
+ import { toPermissionSubject } from '@zhin.js/permission';
2
3
  /**
3
- * MessageCommand类:命令系统核心,基于segment-matcher实现。
4
- * 支持多平台命令注册、作用域限制、参数解析、异步处理等。
4
+ * MessageCommand类:经典命令系统(segment-matcher)。
5
+ *
6
+ * @deprecated 新插件请用 `defineCommand`(`zhin.js/command`)+ `commands/` 约定目录。
7
+ * 本类仍供 Agent init / game-kit hub / legacy `CommandFeature` 使用;计划随经典
8
+ * Plugin 路径一并退役。见 `docs/contributing/public-api-surface.md`。
5
9
  */
6
10
  export class MessageCommand extends SegmentMatcher {
7
11
  #callbacks = [];
@@ -17,6 +21,24 @@ export class MessageCommand extends SegmentMatcher {
17
21
  examples: this.#examples
18
22
  };
19
23
  }
24
+ constructor(C, P = {}) {
25
+ super(C, {
26
+ at: ['qq', 'user_id'],
27
+ face: ['id'],
28
+ mention: ['qq', 'user_id'],
29
+ html: ['content'],
30
+ markdown: ['content'],
31
+ image: ['file', 'src', 'url'],
32
+ video: ['file', 'src', 'url'],
33
+ audio: ['file', 'src', 'url'],
34
+ file: ['file', 'src', 'url'],
35
+ reply: ['id', 'reply_id', 'message_id'],
36
+ quote: ['id', 'reply_id', 'message_id'],
37
+ forward: ['id', 'res_id', 'message_id'],
38
+ location: ['latitude', 'longitude'],
39
+ ...P,
40
+ });
41
+ }
20
42
  get help() {
21
43
  return [
22
44
  this.pattern,
@@ -49,18 +71,28 @@ export class MessageCommand extends SegmentMatcher {
49
71
  this.#permissions.push(...permissions);
50
72
  return this;
51
73
  }
74
+ /** 命令要求的 permit 列表(空表示所有人可用) */
75
+ get requiredPermits() {
76
+ return this.#permissions;
77
+ }
78
+ /** 与 handle 一致的 permit 校验,供帮助菜单等场景过滤不可见命令 */
79
+ async checkPermits(message, host) {
80
+ if (!this.#permissions.length)
81
+ return true;
82
+ if (!host)
83
+ return false;
84
+ const subject = toPermissionSubject(message);
85
+ return host.checkAll(this.#permissions, subject);
86
+ }
52
87
  /**
53
88
  * 处理消息,自动匹配命令并执行回调
54
89
  * @param message 消息对象
55
- * @param plugin 插件实例
90
+ * @param host PermissionHost(null 时有 permit 的命令 fail-closed)
56
91
  * @returns 命令返回内容或undefined
57
92
  */
58
- async handle(message, plugin) {
59
- const auth = plugin.contextIsReady('permission') ? plugin.inject('permission') : null;
60
- for (const permit of this.#permissions) {
61
- const passed = await auth?.check(permit, message);
62
- if (!passed)
63
- return;
93
+ async handle(message, host) {
94
+ if (!(await this.checkPermits(message, host))) {
95
+ return;
64
96
  }
65
97
  const matched = this.match(message.$content);
66
98
  if (!matched)
@@ -72,4 +104,3 @@ export class MessageCommand extends SegmentMatcher {
72
104
  }
73
105
  }
74
106
  }
75
- //# sourceMappingURL=command.js.map
@@ -24,4 +24,3 @@ export declare const Fragment: Component<{
24
24
  children?: SendContent;
25
25
  }>;
26
26
  export declare const Fetch: Component<any>;
27
- //# sourceMappingURL=component.d.ts.map