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