@downcity/plugins 1.0.56 → 1.0.59

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 (318) hide show
  1. package/bin/BuiltinPlugins.d.ts.map +1 -1
  2. package/bin/BuiltinPlugins.js +0 -6
  3. package/bin/BuiltinPlugins.js.map +1 -1
  4. package/bin/asr/Plugin.d.ts +67 -7
  5. package/bin/asr/Plugin.d.ts.map +1 -1
  6. package/bin/asr/Plugin.js +229 -461
  7. package/bin/asr/Plugin.js.map +1 -1
  8. package/bin/asr/types/AsrPlugin.d.ts +114 -0
  9. package/bin/asr/types/AsrPlugin.d.ts.map +1 -0
  10. package/bin/asr/types/AsrPlugin.js +10 -0
  11. package/bin/asr/types/AsrPlugin.js.map +1 -0
  12. package/bin/auth/types/AuthPlugin.d.ts +12 -16
  13. package/bin/auth/types/AuthPlugin.d.ts.map +1 -1
  14. package/bin/auth/types/AuthPlugin.js +9 -13
  15. package/bin/auth/types/AuthPlugin.js.map +1 -1
  16. package/bin/chat/ChatPlugin.d.ts +37 -6
  17. package/bin/chat/ChatPlugin.d.ts.map +1 -1
  18. package/bin/chat/ChatPlugin.js +58 -80
  19. package/bin/chat/ChatPlugin.js.map +1 -1
  20. package/bin/chat/Index.d.ts +4 -1
  21. package/bin/chat/Index.d.ts.map +1 -1
  22. package/bin/chat/Index.js +2 -1
  23. package/bin/chat/Index.js.map +1 -1
  24. package/bin/chat/channels/Configuration.d.ts +1 -1
  25. package/bin/chat/channels/Configuration.js +1 -1
  26. package/bin/chat/channels/RuntimeChannel.d.ts +145 -0
  27. package/bin/chat/channels/RuntimeChannel.d.ts.map +1 -0
  28. package/bin/chat/channels/RuntimeChannel.js +148 -0
  29. package/bin/chat/channels/RuntimeChannel.js.map +1 -0
  30. package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts +22 -0
  31. package/bin/chat/runtime/ChatAuthorizationRuntime.d.ts.map +1 -0
  32. package/bin/chat/runtime/ChatAuthorizationRuntime.js +189 -0
  33. package/bin/chat/runtime/ChatAuthorizationRuntime.js.map +1 -0
  34. package/bin/chat/runtime/ChatChannelActions.d.ts.map +1 -1
  35. package/bin/chat/runtime/ChatChannelActions.js +19 -9
  36. package/bin/chat/runtime/ChatChannelActions.js.map +1 -1
  37. package/bin/chat/runtime/ChatChannelConfig.d.ts +2 -18
  38. package/bin/chat/runtime/ChatChannelConfig.d.ts.map +1 -1
  39. package/bin/chat/runtime/ChatChannelConfig.js +2 -73
  40. package/bin/chat/runtime/ChatChannelConfig.js.map +1 -1
  41. package/bin/chat/runtime/ChatChannelCore.d.ts +22 -1
  42. package/bin/chat/runtime/ChatChannelCore.d.ts.map +1 -1
  43. package/bin/chat/runtime/ChatChannelCore.js +5 -5
  44. package/bin/chat/runtime/ChatChannelCore.js.map +1 -1
  45. package/bin/chat/runtime/ChatPluginActionRegistry.js +1 -1
  46. package/bin/chat/runtime/ChatPluginActionRegistry.js.map +1 -1
  47. package/bin/chat/runtime/PluginPoints.d.ts +3 -3
  48. package/bin/chat/runtime/PluginPoints.js +3 -3
  49. package/bin/chat/types/ChannelStatus.d.ts +1 -1
  50. package/bin/chat/types/ChatPluginOptions.d.ts +76 -0
  51. package/bin/chat/types/ChatPluginOptions.d.ts.map +1 -0
  52. package/bin/chat/types/ChatPluginOptions.js +10 -0
  53. package/bin/chat/types/ChatPluginOptions.js.map +1 -0
  54. package/bin/image/ImagePlugin.d.ts +1 -1
  55. package/bin/image/ImagePlugin.d.ts.map +1 -1
  56. package/bin/image/ImagePlugin.js +23 -5
  57. package/bin/image/ImagePlugin.js.map +1 -1
  58. package/bin/index.d.ts +6 -3
  59. package/bin/index.d.ts.map +1 -1
  60. package/bin/index.js +2 -2
  61. package/bin/index.js.map +1 -1
  62. package/bin/skill/Action.d.ts.map +1 -1
  63. package/bin/skill/Action.js +2 -2
  64. package/bin/skill/Action.js.map +1 -1
  65. package/bin/skill/Command.js +5 -5
  66. package/bin/skill/Command.js.map +1 -1
  67. package/bin/skill/Plugin.js +1 -1
  68. package/bin/skill/Plugin.js.map +1 -1
  69. package/bin/skill/runtime/Discovery.d.ts +4 -4
  70. package/bin/skill/runtime/Discovery.d.ts.map +1 -1
  71. package/bin/skill/runtime/Discovery.js +5 -5
  72. package/bin/skill/runtime/Discovery.js.map +1 -1
  73. package/bin/skill/runtime/Paths.d.ts +1 -5
  74. package/bin/skill/runtime/Paths.d.ts.map +1 -1
  75. package/bin/skill/runtime/Paths.js +1 -9
  76. package/bin/skill/runtime/Paths.js.map +1 -1
  77. package/bin/skill/runtime/Prompt.d.ts +2 -2
  78. package/bin/skill/runtime/Prompt.d.ts.map +1 -1
  79. package/bin/skill/runtime/Prompt.js +3 -3
  80. package/bin/skill/runtime/Prompt.js.map +1 -1
  81. package/bin/skill/runtime/Store.d.ts +2 -2
  82. package/bin/skill/runtime/Store.d.ts.map +1 -1
  83. package/bin/skill/runtime/Store.js.map +1 -1
  84. package/bin/skill/runtime/SystemProvider.js +4 -4
  85. package/bin/skill/runtime/SystemProvider.js.map +1 -1
  86. package/bin/skill/runtime/Types.d.ts +3 -3
  87. package/bin/skill/runtime/Types.d.ts.map +1 -1
  88. package/bin/skill/types/{ClaudeSkill.d.ts → SkillDefinition.d.ts} +4 -4
  89. package/bin/skill/types/SkillDefinition.d.ts.map +1 -0
  90. package/bin/skill/types/{ClaudeSkill.js → SkillDefinition.js} +2 -2
  91. package/bin/skill/types/SkillDefinition.js.map +1 -0
  92. package/bin/skill/types/SkillPlugin.d.ts +2 -2
  93. package/bin/skill/types/SkillPlugin.d.ts.map +1 -1
  94. package/bin/tts/Plugin.d.ts +53 -6
  95. package/bin/tts/Plugin.d.ts.map +1 -1
  96. package/bin/tts/Plugin.js +197 -474
  97. package/bin/tts/Plugin.js.map +1 -1
  98. package/bin/tts/types/TtsPlugin.d.ts +63 -102
  99. package/bin/tts/types/TtsPlugin.d.ts.map +1 -1
  100. package/bin/tts/types/TtsPlugin.js +4 -3
  101. package/bin/tts/types/TtsPlugin.js.map +1 -1
  102. package/bin/web/PROMPT.d.ts +1 -1
  103. package/bin/web/PROMPT.d.ts.map +1 -1
  104. package/bin/web/PROMPT.js +1 -1
  105. package/bin/web/PROMPT.js.map +1 -1
  106. package/bin/web/Plugin.d.ts +66 -5
  107. package/bin/web/Plugin.d.ts.map +1 -1
  108. package/bin/web/Plugin.js +126 -450
  109. package/bin/web/Plugin.js.map +1 -1
  110. package/bin/web/WebPromptAssets.d.ts +1 -9
  111. package/bin/web/WebPromptAssets.d.ts.map +1 -1
  112. package/bin/web/WebPromptAssets.js +1 -11
  113. package/bin/web/WebPromptAssets.js.map +1 -1
  114. package/bin/web/runtime/Install.d.ts +19 -0
  115. package/bin/web/runtime/Install.d.ts.map +1 -0
  116. package/bin/web/runtime/Install.js +178 -0
  117. package/bin/web/runtime/Install.js.map +1 -0
  118. package/bin/web/types/WebPlugin.d.ts +38 -109
  119. package/bin/web/types/WebPlugin.d.ts.map +1 -1
  120. package/bin/web/types/WebPlugin.js +5 -7
  121. package/bin/web/types/WebPlugin.js.map +1 -1
  122. package/bin/workboard/Plugin.d.ts +23 -3
  123. package/bin/workboard/Plugin.d.ts.map +1 -1
  124. package/bin/workboard/Plugin.js +66 -85
  125. package/bin/workboard/Plugin.js.map +1 -1
  126. package/package.json +2 -2
  127. package/src/BuiltinPlugins.ts +0 -6
  128. package/src/asr/Plugin.ts +264 -483
  129. package/src/asr/types/AsrPlugin.ts +118 -0
  130. package/src/auth/types/AuthPlugin.ts +12 -17
  131. package/src/chat/ChatPlugin.ts +92 -89
  132. package/src/chat/Index.ts +18 -1
  133. package/src/chat/channels/Configuration.ts +1 -1
  134. package/src/chat/channels/RuntimeChannel.ts +264 -0
  135. package/src/chat/runtime/ChatAuthorizationRuntime.ts +229 -0
  136. package/src/chat/runtime/ChatChannelActions.ts +24 -9
  137. package/src/chat/runtime/ChatChannelConfig.ts +2 -100
  138. package/src/chat/runtime/ChatChannelCore.ts +20 -8
  139. package/src/chat/runtime/ChatPluginActionRegistry.ts +1 -1
  140. package/src/chat/runtime/PluginPoints.ts +3 -3
  141. package/src/chat/types/ChannelStatus.ts +1 -1
  142. package/src/chat/types/ChatPluginOptions.ts +79 -0
  143. package/src/image/ImagePlugin.ts +23 -5
  144. package/src/index.ts +29 -6
  145. package/src/skill/Action.ts +10 -7
  146. package/src/skill/Command.ts +5 -5
  147. package/src/skill/Plugin.ts +1 -1
  148. package/src/skill/runtime/Discovery.ts +14 -11
  149. package/src/skill/runtime/Paths.ts +1 -13
  150. package/src/skill/runtime/Prompt.ts +5 -5
  151. package/src/skill/runtime/Store.ts +6 -3
  152. package/src/skill/runtime/SystemProvider.ts +4 -4
  153. package/src/skill/runtime/Types.ts +3 -3
  154. package/src/skill/types/{ClaudeSkill.ts → SkillDefinition.ts} +3 -3
  155. package/src/skill/types/SkillPlugin.ts +2 -2
  156. package/src/tts/Plugin.ts +225 -492
  157. package/src/tts/types/TtsPlugin.ts +67 -102
  158. package/src/web/PROMPT.ts +1 -1
  159. package/src/web/PROMPT.ts.txt +32 -6
  160. package/src/web/Plugin.ts +119 -453
  161. package/src/web/WebPromptAssets.ts +1 -13
  162. package/src/web/runtime/Install.ts +241 -0
  163. package/src/web/types/WebPlugin.ts +38 -114
  164. package/src/workboard/Plugin.ts +80 -95
  165. package/bin/asr/Config.d.ts +0 -43
  166. package/bin/asr/Config.d.ts.map +0 -1
  167. package/bin/asr/Config.js +0 -107
  168. package/bin/asr/Config.js.map +0 -1
  169. package/bin/asr/Dependency.d.ts +0 -77
  170. package/bin/asr/Dependency.d.ts.map +0 -1
  171. package/bin/asr/Dependency.js +0 -238
  172. package/bin/asr/Dependency.js.map +0 -1
  173. package/bin/asr/InboundAugment.d.ts +0 -17
  174. package/bin/asr/InboundAugment.d.ts.map +0 -1
  175. package/bin/asr/InboundAugment.js +0 -47
  176. package/bin/asr/InboundAugment.js.map +0 -1
  177. package/bin/asr/ModelCatalog.d.ts +0 -29
  178. package/bin/asr/ModelCatalog.d.ts.map +0 -1
  179. package/bin/asr/ModelCatalog.js +0 -25
  180. package/bin/asr/ModelCatalog.js.map +0 -1
  181. package/bin/auth/Plugin.d.ts +0 -17
  182. package/bin/auth/Plugin.d.ts.map +0 -1
  183. package/bin/auth/Plugin.js +0 -199
  184. package/bin/auth/Plugin.js.map +0 -1
  185. package/bin/chat/ChatPluginTypes.d.ts +0 -122
  186. package/bin/chat/ChatPluginTypes.d.ts.map +0 -1
  187. package/bin/chat/ChatPluginTypes.js +0 -10
  188. package/bin/chat/ChatPluginTypes.js.map +0 -1
  189. package/bin/skill/types/ClaudeSkill.d.ts.map +0 -1
  190. package/bin/skill/types/ClaudeSkill.js.map +0 -1
  191. package/bin/tts/Dependency.d.ts +0 -90
  192. package/bin/tts/Dependency.d.ts.map +0 -1
  193. package/bin/tts/Dependency.js +0 -344
  194. package/bin/tts/Dependency.js.map +0 -1
  195. package/bin/tts/PluginSupport.d.ts +0 -25
  196. package/bin/tts/PluginSupport.d.ts.map +0 -1
  197. package/bin/tts/PluginSupport.js +0 -72
  198. package/bin/tts/PluginSupport.js.map +0 -1
  199. package/bin/tts/runtime/Catalog.d.ts +0 -21
  200. package/bin/tts/runtime/Catalog.d.ts.map +0 -1
  201. package/bin/tts/runtime/Catalog.js +0 -90
  202. package/bin/tts/runtime/Catalog.js.map +0 -1
  203. package/bin/tts/runtime/DependencyInstaller.d.ts +0 -143
  204. package/bin/tts/runtime/DependencyInstaller.d.ts.map +0 -1
  205. package/bin/tts/runtime/DependencyInstaller.js +0 -261
  206. package/bin/tts/runtime/DependencyInstaller.js.map +0 -1
  207. package/bin/tts/runtime/Installer.d.ts +0 -89
  208. package/bin/tts/runtime/Installer.d.ts.map +0 -1
  209. package/bin/tts/runtime/Installer.js +0 -188
  210. package/bin/tts/runtime/Installer.js.map +0 -1
  211. package/bin/tts/runtime/Paths.d.ts +0 -20
  212. package/bin/tts/runtime/Paths.d.ts.map +0 -1
  213. package/bin/tts/runtime/Paths.js +0 -32
  214. package/bin/tts/runtime/Paths.js.map +0 -1
  215. package/bin/tts/runtime/Synthesizer.d.ts +0 -44
  216. package/bin/tts/runtime/Synthesizer.d.ts.map +0 -1
  217. package/bin/tts/runtime/Synthesizer.js +0 -363
  218. package/bin/tts/runtime/Synthesizer.js.map +0 -1
  219. package/bin/tts/types/Tts.d.ts +0 -91
  220. package/bin/tts/types/Tts.d.ts.map +0 -1
  221. package/bin/tts/types/Tts.js +0 -9
  222. package/bin/tts/types/Tts.js.map +0 -1
  223. package/bin/voice/Config.d.ts +0 -43
  224. package/bin/voice/Config.d.ts.map +0 -1
  225. package/bin/voice/Config.js +0 -104
  226. package/bin/voice/Config.js.map +0 -1
  227. package/bin/voice/Dependency.d.ts +0 -77
  228. package/bin/voice/Dependency.d.ts.map +0 -1
  229. package/bin/voice/Dependency.js +0 -237
  230. package/bin/voice/Dependency.js.map +0 -1
  231. package/bin/voice/InboundAugment.d.ts +0 -17
  232. package/bin/voice/InboundAugment.d.ts.map +0 -1
  233. package/bin/voice/InboundAugment.js +0 -47
  234. package/bin/voice/InboundAugment.js.map +0 -1
  235. package/bin/voice/ModelCatalog.d.ts +0 -29
  236. package/bin/voice/ModelCatalog.d.ts.map +0 -1
  237. package/bin/voice/ModelCatalog.js +0 -25
  238. package/bin/voice/ModelCatalog.js.map +0 -1
  239. package/bin/voice/runtime/Catalog.d.ts +0 -18
  240. package/bin/voice/runtime/Catalog.d.ts.map +0 -1
  241. package/bin/voice/runtime/Catalog.js +0 -61
  242. package/bin/voice/runtime/Catalog.js.map +0 -1
  243. package/bin/voice/runtime/DependencyInstaller.d.ts +0 -145
  244. package/bin/voice/runtime/DependencyInstaller.d.ts.map +0 -1
  245. package/bin/voice/runtime/DependencyInstaller.js +0 -309
  246. package/bin/voice/runtime/DependencyInstaller.js.map +0 -1
  247. package/bin/voice/runtime/Installer.d.ts +0 -94
  248. package/bin/voice/runtime/Installer.d.ts.map +0 -1
  249. package/bin/voice/runtime/Installer.js +0 -200
  250. package/bin/voice/runtime/Installer.js.map +0 -1
  251. package/bin/voice/runtime/Paths.d.ts +0 -8
  252. package/bin/voice/runtime/Paths.d.ts.map +0 -1
  253. package/bin/voice/runtime/Paths.js +0 -26
  254. package/bin/voice/runtime/Paths.js.map +0 -1
  255. package/bin/voice/runtime/Transcriber.d.ts +0 -57
  256. package/bin/voice/runtime/Transcriber.d.ts.map +0 -1
  257. package/bin/voice/runtime/Transcriber.js +0 -329
  258. package/bin/voice/runtime/Transcriber.js.map +0 -1
  259. package/bin/voice/types/Voice.d.ts +0 -58
  260. package/bin/voice/types/Voice.d.ts.map +0 -1
  261. package/bin/voice/types/Voice.js +0 -9
  262. package/bin/voice/types/Voice.js.map +0 -1
  263. package/bin/voice/types/VoicePlugin.d.ts +0 -190
  264. package/bin/voice/types/VoicePlugin.d.ts.map +0 -1
  265. package/bin/voice/types/VoicePlugin.js +0 -9
  266. package/bin/voice/types/VoicePlugin.js.map +0 -1
  267. package/bin/web/Dependency.d.ts +0 -10
  268. package/bin/web/Dependency.d.ts.map +0 -1
  269. package/bin/web/Dependency.js +0 -10
  270. package/bin/web/Dependency.js.map +0 -1
  271. package/bin/web/PROMPT.agent-browser.d.ts +0 -7
  272. package/bin/web/PROMPT.agent-browser.d.ts.map +0 -1
  273. package/bin/web/PROMPT.agent-browser.js +0 -8
  274. package/bin/web/PROMPT.agent-browser.js.map +0 -1
  275. package/bin/web/PROMPT.web-access.d.ts +0 -7
  276. package/bin/web/PROMPT.web-access.d.ts.map +0 -1
  277. package/bin/web/PROMPT.web-access.js +0 -8
  278. package/bin/web/PROMPT.web-access.js.map +0 -1
  279. package/bin/web/runtime/Config.d.ts +0 -21
  280. package/bin/web/runtime/Config.d.ts.map +0 -1
  281. package/bin/web/runtime/Config.js +0 -79
  282. package/bin/web/runtime/Config.js.map +0 -1
  283. package/bin/web/runtime/Source.d.ts +0 -29
  284. package/bin/web/runtime/Source.d.ts.map +0 -1
  285. package/bin/web/runtime/Source.js +0 -209
  286. package/bin/web/runtime/Source.js.map +0 -1
  287. package/src/asr/Config.ts +0 -138
  288. package/src/asr/Dependency.ts +0 -336
  289. package/src/asr/InboundAugment.ts +0 -59
  290. package/src/asr/ModelCatalog.ts +0 -43
  291. package/src/auth/Plugin.ts +0 -237
  292. package/src/chat/ChatPluginTypes.ts +0 -126
  293. package/src/tts/Dependency.ts +0 -473
  294. package/src/tts/PluginSupport.ts +0 -85
  295. package/src/tts/runtime/Catalog.ts +0 -97
  296. package/src/tts/runtime/DependencyInstaller.ts +0 -436
  297. package/src/tts/runtime/Installer.ts +0 -297
  298. package/src/tts/runtime/Paths.ts +0 -39
  299. package/src/tts/runtime/Synthesizer.ts +0 -480
  300. package/src/tts/types/Tts.ts +0 -99
  301. package/src/voice/Config.ts +0 -135
  302. package/src/voice/Dependency.ts +0 -329
  303. package/src/voice/InboundAugment.ts +0 -59
  304. package/src/voice/ModelCatalog.ts +0 -43
  305. package/src/voice/runtime/Catalog.ts +0 -68
  306. package/src/voice/runtime/DependencyInstaller.ts +0 -505
  307. package/src/voice/runtime/Installer.ts +0 -324
  308. package/src/voice/runtime/Paths.ts +0 -26
  309. package/src/voice/runtime/Transcriber.ts +0 -467
  310. package/src/voice/types/Voice.ts +0 -68
  311. package/src/voice/types/VoicePlugin.ts +0 -194
  312. package/src/web/Dependency.ts +0 -17
  313. package/src/web/PROMPT.agent-browser.ts +0 -9
  314. package/src/web/PROMPT.agent-browser.ts.txt +0 -17
  315. package/src/web/PROMPT.web-access.ts +0 -9
  316. package/src/web/PROMPT.web-access.ts.txt +0 -13
  317. package/src/web/runtime/Config.ts +0 -105
  318. package/src/web/runtime/Source.ts +0 -257
package/bin/asr/Plugin.js CHANGED
@@ -1,481 +1,249 @@
1
1
  /**
2
- * ASR Plugin。
2
+ * AsrPlugin:语音转写插件。
3
3
  *
4
4
  * 关键点(中文)
5
- * - ASR Plugin 现在自己内聚转写依赖,不再暴露独立依赖端口心智。
6
- * - 具体模型、依赖安装、命令模板等实现细节全部收敛到 plugin 内部 dependency helper。
7
- * - 当前作为 chat 入站消息增强中间件接入语音转写。
5
+ * - ASR 能力通过 constructor 注入,推荐传入 `city.ai.asr`。
6
+ * - plugin 不负责本地模型、Python 依赖、provider 或项目配置。
7
+ * - `auto: true` 时会在 chat 入站阶段自动转写 voice/audio 附件,并把结果写入正文。
8
8
  */
9
+ import path from "node:path";
9
10
  import { BasePlugin } from "@downcity/agent/internal/plugin/core/BasePlugin.js";
10
11
  import { CHAT_PLUGIN_POINTS } from "../chat/runtime/PluginPoints.js";
11
- import { isPluginEnabled } from "@downcity/agent/internal/plugin/core/Activation.js";
12
- import { writeProjectPluginEnabled } from "@downcity/agent/internal/plugin/core/ProjectConfigStore.js";
13
- import { listVoiceModels, resolveVoicePluginModelId, } from "../asr/ModelCatalog.js";
14
- import { getBooleanOpt, getStringOpt, readVoicePluginConfig, toJsonObject, writeVoicePluginConfig, } from "../asr/Config.js";
15
- import { augmentAsrInboundMessage } from "../asr/InboundAugment.js";
16
- import { checkVoiceTranscriber, installVoiceTranscriber, readVoiceTranscriberConfig, transcribeWithVoiceDependency, writeVoiceTranscriberConfig, } from "../asr/Dependency.js";
17
- function createAsrPluginDefinition(plugin) {
12
+ const DEFAULT_ASR_PLUGIN_NAME = "asr";
13
+ const DEFAULT_ASR_PLUGIN_TITLE = "ASR";
14
+ const DEFAULT_ASR_PLUGIN_DESCRIPTION = "Transcribe voice and audio attachments through an injected ASR function.";
15
+ /**
16
+ * 判断值是否为普通对象。
17
+ */
18
+ function to_record(value) {
19
+ if (!value || typeof value !== "object" || Array.isArray(value))
20
+ return null;
21
+ return value;
22
+ }
23
+ /**
24
+ * XML 文本转义。
25
+ */
26
+ function escape_xml_text(value) {
27
+ return String(value || "")
28
+ .replace(/&/g, "&")
29
+ .replace(/</g, "&lt;")
30
+ .replace(/>/g, "&gt;");
31
+ }
32
+ /**
33
+ * XML 属性转义。
34
+ */
35
+ function escape_xml_attr(value) {
36
+ return escape_xml_text(value).replace(/"/g, "&quot;");
37
+ }
38
+ /**
39
+ * 归一化 action payload。
40
+ */
41
+ function normalize_asr_payload(payload) {
42
+ const record = to_record(payload ?? {});
43
+ if (!record) {
44
+ throw new TypeError("AsrPlugin.transcribe payload must be an object");
45
+ }
46
+ const audio_path = typeof record.audio_path === "string"
47
+ ? record.audio_path.trim()
48
+ : "";
49
+ const url = typeof record.url === "string" ? record.url.trim() : "";
50
+ const data_url = typeof record.data_url === "string" ? record.data_url.trim() : "";
51
+ if (!audio_path && !url && !data_url) {
52
+ throw new Error("AsrPlugin.transcribe requires audio_path, url, or data_url");
53
+ }
18
54
  return {
19
- name: "asr",
20
- title: "Automatic Speech Recognition",
21
- description: "Detects voice and audio attachments in inbound chat messages, runs transcription through the configured ASR dependency, and appends readable text so the agent can work with spoken input like normal message content.",
22
- config: {
23
- plugin: "asr",
24
- scope: "project",
25
- defaultValue: {
26
- injectPrompt: true,
27
- augmentMessage: true,
28
- provider: "local",
29
- modelId: "SenseVoiceSmall",
30
- },
31
- },
32
- setup: {
33
- mode: "install-configure",
34
- title: "安装语音识别",
35
- description: "选择模型后即可完成依赖安装与当前配置写入。",
36
- fields: [
37
- {
38
- key: "modelId",
39
- label: "模型",
40
- type: "select",
41
- required: true,
42
- sourceAction: "models",
43
- },
44
- {
45
- key: "installDeps",
46
- label: "安装 Python 依赖",
47
- type: "checkbox",
48
- },
49
- ],
50
- primaryAction: "install",
51
- statusAction: "status",
52
- },
53
- usage: {
54
- title: "配置语音识别",
55
- description: "设置当前 agent 如何把语音内容转成文本并注入对话链路。",
56
- fields: [
57
- {
58
- key: "injectPrompt",
59
- label: "注入 Prompt 提示",
60
- type: "boolean",
61
- trueLabel: "开启",
62
- falseLabel: "关闭",
63
- description: "开启后会把 ASR 使用约束注入到 agent 的系统提示词。",
64
- },
65
- {
66
- key: "augmentMessage",
67
- label: "自动增强消息",
68
- type: "boolean",
69
- trueLabel: "开启",
70
- falseLabel: "关闭",
71
- description: "开启后,入站语音消息会先自动转写再交给 agent。",
72
- },
73
- {
74
- key: "modelId",
75
- label: "默认模型",
76
- type: "select",
77
- sourceAction: "models",
78
- },
79
- {
80
- key: "language",
81
- label: "默认语言提示",
82
- type: "string",
83
- placeholder: "auto / zh / en",
84
- },
85
- {
86
- key: "timeoutMs",
87
- label: "超时(毫秒)",
88
- type: "number",
89
- placeholder: "60000",
55
+ ...record,
56
+ ...(audio_path ? { audio_path } : {}),
57
+ ...(url ? { url } : {}),
58
+ ...(data_url ? { data_url } : {}),
59
+ };
60
+ }
61
+ /**
62
+ * 校验 ASR 返回结果。
63
+ */
64
+ function normalize_asr_result(result) {
65
+ const record = to_record(result);
66
+ if (!record || typeof record.text !== "string") {
67
+ throw new TypeError("AsrPlugin asr function must return { text: string }");
68
+ }
69
+ return {
70
+ ...record,
71
+ text: record.text.trim(),
72
+ };
73
+ }
74
+ /**
75
+ * 生成相对展示路径。
76
+ */
77
+ function to_display_src(root_path, attachment) {
78
+ const raw = typeof attachment.path === "string" && attachment.path.trim()
79
+ ? attachment.path.trim()
80
+ : attachment.fileName || attachment.attachmentId || attachment.kind;
81
+ const normalized_root = path.resolve(root_path);
82
+ const normalized_raw = path.isAbsolute(raw) ? path.resolve(raw) : raw;
83
+ if (path.isAbsolute(normalized_raw) && normalized_raw.startsWith(`${normalized_root}${path.sep}`)) {
84
+ return normalized_raw.slice(normalized_root.length + 1);
85
+ }
86
+ return raw;
87
+ }
88
+ /**
89
+ * 把语音转写结果写入 bodyText。
90
+ */
91
+ function append_voice_text(input, voice_blocks) {
92
+ const current = String(input.bodyText || "").trim();
93
+ const addition = voice_blocks.map((item) => item.trim()).filter(Boolean).join("\n\n");
94
+ if (!addition)
95
+ return input;
96
+ return {
97
+ ...input,
98
+ bodyText: [current, addition].filter(Boolean).join("\n\n"),
99
+ };
100
+ }
101
+ /**
102
+ * Agent ASR 插件。
103
+ */
104
+ export class AsrPlugin extends BasePlugin {
105
+ /**
106
+ * 当前 plugin 稳定名称。
107
+ */
108
+ name;
109
+ /**
110
+ * 插件标题。
111
+ */
112
+ title;
113
+ /**
114
+ * 插件说明。
115
+ */
116
+ description;
117
+ asr;
118
+ auto;
119
+ language;
120
+ constructor(options) {
121
+ super();
122
+ const name = String(options.name || DEFAULT_ASR_PLUGIN_NAME).trim();
123
+ if (!name) {
124
+ throw new Error("AsrPlugin requires a non-empty name");
125
+ }
126
+ if (typeof options.asr !== "function") {
127
+ throw new Error("AsrPlugin requires an asr function");
128
+ }
129
+ this.name = name;
130
+ this.title = String(options.title || DEFAULT_ASR_PLUGIN_TITLE).trim();
131
+ this.description = String(options.description || DEFAULT_ASR_PLUGIN_DESCRIPTION).trim();
132
+ this.asr = options.asr;
133
+ this.auto = options.auto === true;
134
+ this.language =
135
+ typeof options.language === "string" && options.language.trim()
136
+ ? options.language.trim()
137
+ : undefined;
138
+ }
139
+ /**
140
+ * ASR 插件给模型的使用说明。
141
+ */
142
+ system(_context) {
143
+ return [
144
+ "# ASR Plugin",
145
+ "",
146
+ "Use this plugin when the user asks to transcribe, recognize, or understand voice/audio content.",
147
+ this.auto
148
+ ? "Inbound voice/audio chat attachments are automatically transcribed into `<voice src=\"...\">...</voice>` blocks in the user text."
149
+ : "Automatic inbound voice transcription is disabled; call the plugin explicitly when transcription is needed.",
150
+ "",
151
+ "Call through `plugin_call`:",
152
+ "",
153
+ "```ts",
154
+ "plugin_call({",
155
+ ` plugin: "${this.name}",`,
156
+ ' action: "transcribe",',
157
+ " payload: {",
158
+ ' audio_path: "...",',
159
+ " },",
160
+ "});",
161
+ "```",
162
+ "",
163
+ "Payload rules:",
164
+ "- Provide one of `audio_path`, `url`, or `data_url`.",
165
+ "- Optional fields: `language`, `media_type`, `file_name`, `provider_options`.",
166
+ "- Do not invent transcript text. If transcription fails, report the failure clearly.",
167
+ ].join("\n");
168
+ }
169
+ /**
170
+ * 执行一次 ASR 转写。
171
+ */
172
+ async transcribe(input) {
173
+ const result = await this.asr({
174
+ ...(this.language ? { language: this.language } : {}),
175
+ ...input,
176
+ });
177
+ return normalize_asr_result(result);
178
+ }
179
+ /**
180
+ * 自动增强 chat 入站消息。
181
+ */
182
+ async auto_transcribe_inbound(params) {
183
+ if (!this.auto)
184
+ return params.value;
185
+ const input = params.value;
186
+ const voice_attachments = (Array.isArray(input.attachments) ? input.attachments : []).filter((item) => (item.kind === "voice" || item.kind === "audio") &&
187
+ typeof item.path === "string" &&
188
+ item.path.trim());
189
+ if (voice_attachments.length === 0) {
190
+ return input;
191
+ }
192
+ const voice_blocks = [];
193
+ for (const attachment of voice_attachments) {
194
+ try {
195
+ const result = await this.transcribe({
196
+ audio_path: String(attachment.path || "").trim(),
197
+ ...(attachment.contentType ? { media_type: attachment.contentType } : {}),
198
+ ...(attachment.fileName ? { file_name: attachment.fileName } : {}),
199
+ });
200
+ if (!result.text)
201
+ continue;
202
+ const src = to_display_src(params.context.rootPath, attachment);
203
+ voice_blocks.push(`<voice src="${escape_xml_attr(src)}">${escape_xml_text(result.text)}</voice>`);
204
+ }
205
+ catch {
206
+ // 关键点(中文):自动转写失败不阻塞主消息链路。
207
+ }
208
+ }
209
+ return append_voice_text(input, voice_blocks);
210
+ }
211
+ /**
212
+ * pipeline / action 扩展点。
213
+ */
214
+ hooks = {
215
+ pipeline: {
216
+ [CHAT_PLUGIN_POINTS.augmentInbound]: [
217
+ async ({ context, value }) => {
218
+ return await this.auto_transcribe_inbound({ context, value });
90
219
  },
91
220
  ],
92
- saveAction: "configure",
93
- statusAction: "status",
94
- },
95
- async availability(context) {
96
- if (!isPluginEnabled({ plugin, context })) {
97
- return {
98
- enabled: false,
99
- available: false,
100
- reasons: ["asr plugin disabled in project config"],
101
- };
102
- }
103
- const dependencyStatus = await checkVoiceTranscriber(context);
104
- return {
105
- enabled: true,
106
- available: dependencyStatus.available,
107
- reasons: dependencyStatus.reasons,
108
- };
109
221
  },
110
- hooks: {
111
- pipeline: {
112
- [CHAT_PLUGIN_POINTS.augmentInbound]: [
113
- async ({ context, value }) => {
114
- return await augmentAsrInboundMessage({ context, value });
115
- },
116
- ],
117
- },
118
- },
119
- actions: {
120
- status: {
121
- allowWhenDisabled: true,
122
- command: {
123
- description: "查看 asr plugin 当前状态",
124
- mapInput() {
125
- return {};
126
- },
127
- },
128
- execute: async ({ context }) => {
129
- const config = readVoicePluginConfig(context);
130
- const availability = await plugin.availability(context);
131
- const transcriberConfig = readVoiceTranscriberConfig(context);
132
- return {
133
- success: true,
134
- data: {
135
- plugin: toJsonObject(config) || {},
136
- availability: {
137
- enabled: availability.enabled,
138
- available: availability.available,
139
- reasons: availability.reasons,
140
- },
141
- transcriber: toJsonObject((transcriberConfig || null)),
142
- },
143
- };
144
- },
145
- },
146
- install: {
147
- allowWhenDisabled: true,
148
- command: {
149
- description: "安装 asr 转写依赖",
150
- configure(command) {
151
- command
152
- .argument("[models...]")
153
- .option("--active-model <modelId>", "安装完成后设为当前模型")
154
- .option("--models-dir <path>", "模型目录(可选)")
155
- .option("--python <bin>", "Python 可执行文件(默认 python3)")
156
- .option("--no-install-deps", "跳过依赖安装")
157
- .option("--force", "强制覆盖已存在资源")
158
- .option("--hf-token <token>", "HuggingFace token(可选)");
159
- },
160
- mapInput({ args, opts }) {
161
- return {
162
- modelIds: args,
163
- ...(getStringOpt(opts, "activeModel")
164
- ? { activeModel: getStringOpt(opts, "activeModel") }
165
- : {}),
166
- ...(getStringOpt(opts, "modelsDir")
167
- ? { modelsDir: getStringOpt(opts, "modelsDir") }
168
- : {}),
169
- ...(getStringOpt(opts, "python")
170
- ? { pythonBin: getStringOpt(opts, "python") }
171
- : {}),
172
- installDeps: getBooleanOpt(opts, "installDeps", true),
173
- force: getBooleanOpt(opts, "force", false),
174
- ...(getStringOpt(opts, "hfToken")
175
- ? { hfToken: getStringOpt(opts, "hfToken") }
176
- : {}),
177
- };
178
- },
179
- },
180
- execute: async ({ context, payload }) => {
181
- const result = await installVoiceTranscriber({
182
- context,
183
- input: payload && typeof payload === "object" && !Array.isArray(payload)
184
- ? payload
185
- : undefined,
186
- });
187
- return {
188
- success: result.success,
189
- ...(result.message ? { message: result.message } : {}),
190
- ...(result.details !== undefined ? { data: result.details } : {}),
191
- ...(result.success ? {} : { error: result.message || "install failed" }),
192
- };
193
- },
194
- },
195
- configure: {
196
- allowWhenDisabled: true,
197
- execute: async ({ context, payload }) => {
198
- const payloadObject = payload && typeof payload === "object" && !Array.isArray(payload)
199
- ? payload
200
- : {};
201
- const { enabled: _ignoredEnabled, ...patch } = payloadObject;
202
- const current = readVoicePluginConfig(context);
203
- const next = {
204
- ...current,
205
- ...patch,
206
- };
207
- await writeVoicePluginConfig({
208
- agentState: context,
209
- value: next,
210
- });
211
- return {
212
- success: true,
213
- data: {
214
- plugin: toJsonObject(next) || {},
215
- },
216
- };
217
- },
218
- },
219
- on: {
220
- allowWhenDisabled: true,
221
- command: {
222
- description: "启用 asr plugin,并可选安装转写依赖",
223
- configure(command) {
224
- command
225
- .argument("[models...]")
226
- .option("--active-model <modelId>", "安装完成后设为当前模型")
227
- .option("--models-dir <path>", "模型目录(可选)")
228
- .option("--python <bin>", "Python 可执行文件(默认 python3)")
229
- .option("--no-install", "仅启用 plugin,不安装依赖")
230
- .option("--no-install-deps", "跳过依赖安装")
231
- .option("--force", "强制覆盖已存在资源")
232
- .option("--hf-token <token>", "HuggingFace token(可选)")
233
- .option("--no-inject-prompt", "关闭 prompt 注入")
234
- .option("--no-augment-message", "关闭消息增强");
235
- },
236
- mapInput({ args, opts }) {
237
- return {
238
- modelIds: args,
239
- ...(getStringOpt(opts, "activeModel")
240
- ? { activeModel: getStringOpt(opts, "activeModel") }
241
- : {}),
242
- ...(getStringOpt(opts, "modelsDir")
243
- ? { modelsDir: getStringOpt(opts, "modelsDir") }
244
- : {}),
245
- ...(getStringOpt(opts, "python")
246
- ? { pythonBin: getStringOpt(opts, "python") }
247
- : {}),
248
- install: getBooleanOpt(opts, "install", true),
249
- installDeps: getBooleanOpt(opts, "installDeps", true),
250
- force: getBooleanOpt(opts, "force", false),
251
- injectPrompt: getBooleanOpt(opts, "injectPrompt", true),
252
- augmentMessage: getBooleanOpt(opts, "augmentMessage", true),
253
- ...(getStringOpt(opts, "hfToken")
254
- ? { hfToken: getStringOpt(opts, "hfToken") }
255
- : {}),
256
- };
257
- },
258
- },
259
- execute: async ({ context, payload }) => {
260
- await writeProjectPluginEnabled({
261
- pluginName: "asr",
262
- enabled: true,
263
- context,
264
- });
265
- const nextConfig = {
266
- ...readVoicePluginConfig(context),
267
- injectPrompt: typeof payload.injectPrompt === "boolean"
268
- ? payload.injectPrompt
269
- : true,
270
- augmentMessage: typeof payload.augmentMessage === "boolean"
271
- ? payload.augmentMessage
272
- : true,
273
- };
274
- await writeVoicePluginConfig({
275
- agentState: context,
276
- value: nextConfig,
277
- });
278
- if (payload.install !== false) {
279
- const installResult = await installVoiceTranscriber({
280
- context,
281
- input: payload && typeof payload === "object" && !Array.isArray(payload)
282
- ? payload
283
- : undefined,
284
- });
285
- if (!installResult.success) {
286
- return {
287
- success: false,
288
- error: installResult.message || "asr dependency install failed",
289
- message: installResult.message || "asr dependency install failed",
290
- };
291
- }
292
- }
293
- return {
294
- success: true,
295
- data: {
296
- plugin: toJsonObject(nextConfig) || {},
297
- transcriber: toJsonObject(readVoiceTranscriberConfig(context)) || {},
298
- },
299
- };
300
- },
301
- },
302
- off: {
303
- command: {
304
- description: "关闭 asr plugin",
305
- mapInput() {
306
- return {};
307
- },
308
- },
309
- execute: async ({ context }) => {
310
- await writeProjectPluginEnabled({
311
- pluginName: "asr",
312
- enabled: false,
313
- context,
314
- });
315
- return {
316
- success: true,
317
- data: {
318
- plugin: toJsonObject(readVoicePluginConfig(context)) || {},
319
- },
320
- };
321
- },
322
- },
323
- use: {
324
- command: {
325
- description: "切换 asr 当前转写模型",
326
- configure(command) {
327
- command.argument("<modelId>");
328
- },
329
- mapInput({ args }) {
330
- const modelId = String(args[0] || "").trim();
331
- if (!modelId) {
332
- throw new Error("modelId is required");
333
- }
334
- return {
335
- modelId,
336
- };
337
- },
338
- },
339
- execute: async ({ context, payload }) => {
340
- const modelId = String(payload.modelId || "").trim();
341
- const resolvedModelId = resolveVoicePluginModelId(modelId);
342
- if (!resolvedModelId) {
343
- return {
344
- success: false,
345
- error: `Unsupported asr model: ${modelId}`,
346
- message: `Unsupported asr model: ${modelId}`,
347
- };
348
- }
349
- const transcriberConfig = await writeVoiceTranscriberConfig({
350
- context,
351
- value: {
352
- ...readVoiceTranscriberConfig(context),
353
- modelId: resolvedModelId,
354
- },
355
- });
222
+ };
223
+ /**
224
+ * 显式 action 集合。
225
+ */
226
+ actions = {
227
+ transcribe: {
228
+ execute: async ({ payload }) => {
229
+ try {
230
+ const input = normalize_asr_payload(payload);
231
+ const result = await this.transcribe(input);
356
232
  return {
357
233
  success: true,
358
- data: {
359
- transcriber: toJsonObject(transcriberConfig) || {},
360
- },
361
- };
362
- },
363
- },
364
- transcribe: {
365
- command: {
366
- description: "转写本地音频文件",
367
- configure(command) {
368
- command
369
- .argument("<audioPath>")
370
- .option("--language <code>", "语言提示(可选,例如 zh / en)");
371
- },
372
- mapInput({ args, opts }) {
373
- const audioPath = String(args[0] || "").trim();
374
- if (!audioPath) {
375
- throw new Error("audioPath is required");
376
- }
377
- return {
378
- audioPath,
379
- ...(getStringOpt(opts, "language")
380
- ? { language: getStringOpt(opts, "language") }
381
- : {}),
382
- };
383
- },
384
- },
385
- execute: async ({ context, payload }) => {
386
- const pluginStatus = await plugin.availability(context);
387
- if (!pluginStatus.enabled || !pluginStatus.available) {
388
- return {
389
- success: false,
390
- error: pluginStatus.reasons.join("; "),
391
- message: pluginStatus.reasons.join("; "),
392
- };
393
- }
394
- const result = await transcribeWithVoiceDependency({
395
- context,
396
- audioPath: String(payload.audioPath || ""),
397
- language: typeof payload.language === "string"
398
- ? String(payload.language || "")
399
- : undefined,
400
- });
401
- return {
402
- success: result.success,
403
- ...(result !== undefined ? { data: result } : {}),
404
- ...(result.success ? {} : { error: result.error || "transcribe failed" }),
405
- ...(result.success ? {} : { message: result.error || "transcribe failed" }),
234
+ data: result,
235
+ message: "audio transcribed",
406
236
  };
407
- },
408
- },
409
- models: {
410
- allowWhenDisabled: true,
411
- command: {
412
- description: "列出内置 asr 支持的模型目录",
413
- mapInput() {
414
- return {};
415
- },
416
- },
417
- execute: async () => {
237
+ }
238
+ catch (error) {
418
239
  return {
419
- success: true,
420
- data: {
421
- models: listVoiceModels(),
422
- },
240
+ success: false,
241
+ error: String(error),
242
+ message: String(error),
423
243
  };
424
- },
244
+ }
425
245
  },
426
- doctor: {
427
- command: {
428
- description: "检查 asr plugin 与转写依赖可用性",
429
- mapInput() {
430
- return {};
431
- },
432
- },
433
- execute: async ({ context }) => {
434
- const availability = await plugin.availability(context);
435
- const dependencyStatus = await checkVoiceTranscriber(context);
436
- return {
437
- success: true,
438
- data: {
439
- availability: {
440
- enabled: availability.enabled,
441
- available: availability.available,
442
- reasons: availability.reasons,
443
- },
444
- transcriberStatus: {
445
- available: dependencyStatus.available,
446
- reasons: dependencyStatus.reasons,
447
- ...(dependencyStatus.details !== undefined
448
- ? { details: dependencyStatus.details }
449
- : {}),
450
- },
451
- },
452
- message: availability.available
453
- ? "asr plugin is available"
454
- : availability.reasons.join("; ") || "asr plugin is not available",
455
- };
456
- },
457
- },
458
- },
459
- system(context) {
460
- const config = readVoicePluginConfig(context);
461
- if (!isPluginEnabled({ plugin, context }) || config.injectPrompt !== true) {
462
- return "";
463
- }
464
- return [
465
- "# ASR Plugin",
466
- "Audio attachments may be transcribed before agent execution.",
467
- ].join("\n");
468
246
  },
469
247
  };
470
248
  }
471
- /**
472
- * AsrPlugin:语音识别插件。
473
- */
474
- export class AsrPlugin extends BasePlugin {
475
- name = "asr";
476
- constructor() {
477
- super();
478
- Object.assign(this, createAsrPluginDefinition(this));
479
- }
480
- }
481
249
  //# sourceMappingURL=Plugin.js.map