@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
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chat channel SDK 基类与内置 channel 实现。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - channel 对象是 ChatPlugin 的运行态配置单元。
|
|
6
|
+
* - env 由 channel 自己读取,ChatPlugin 不理解平台字段。
|
|
7
|
+
* - channelAccountId 仅作为账号池绑定能力保留,不再是 ChatPlugin 顶层配置。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
|
|
11
|
+
import type { StoredChannelAccount } from "@downcity/agent/internal/types/platform/Store.js";
|
|
12
|
+
import type { ChatChannelName } from "@/chat/types/ChannelStatus.js";
|
|
13
|
+
import type {
|
|
14
|
+
ChatChannel,
|
|
15
|
+
ChatChannelRuntimePatch,
|
|
16
|
+
} from "@/chat/types/ChatPluginOptions.js";
|
|
17
|
+
import { getStoredChannelAccountSync } from "@/chat/accounts/Store.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* env 字典。
|
|
21
|
+
*/
|
|
22
|
+
export type ChatChannelEnv = Record<string, string | undefined>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Chat channel 基础配置。
|
|
26
|
+
*/
|
|
27
|
+
export interface BaseChatChannelOptions {
|
|
28
|
+
/**
|
|
29
|
+
* 是否启用该 channel。
|
|
30
|
+
*
|
|
31
|
+
* 说明(中文)
|
|
32
|
+
* - 默认值为 `true`,因为传入 channel 对象通常表示希望启用它。
|
|
33
|
+
* - 可通过 chat.open / chat.close 在运行态修改。
|
|
34
|
+
*/
|
|
35
|
+
enabled?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* channel 专属 env。
|
|
38
|
+
*
|
|
39
|
+
* 说明(中文)
|
|
40
|
+
* - 这里面放面向人类可读的环境变量名,例如 `TELEGRAM_BOT_TOKEN`。
|
|
41
|
+
* - channel 会自行读取所需字段。
|
|
42
|
+
*/
|
|
43
|
+
env?: ChatChannelEnv;
|
|
44
|
+
/**
|
|
45
|
+
* 可选账号池绑定 ID。
|
|
46
|
+
*
|
|
47
|
+
* 说明(中文)
|
|
48
|
+
* - 仅在需要复用全局账号池时使用。
|
|
49
|
+
* - SDK 主路径推荐直接通过 `env` 传入凭据。
|
|
50
|
+
*/
|
|
51
|
+
channelAccountId?: string;
|
|
52
|
+
/**
|
|
53
|
+
* 运行态展示名称。
|
|
54
|
+
*/
|
|
55
|
+
name?: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
abstract class BaseRuntimeChatChannel implements ChatChannel {
|
|
59
|
+
/**
|
|
60
|
+
* channel 名称。
|
|
61
|
+
*/
|
|
62
|
+
abstract readonly name: ChatChannelName;
|
|
63
|
+
|
|
64
|
+
protected enabled: boolean;
|
|
65
|
+
protected env: ChatChannelEnv;
|
|
66
|
+
protected channelAccountId: string;
|
|
67
|
+
protected displayName: string;
|
|
68
|
+
|
|
69
|
+
protected constructor(options: BaseChatChannelOptions = {}) {
|
|
70
|
+
this.enabled = options.enabled !== false;
|
|
71
|
+
this.env = options.env || {};
|
|
72
|
+
this.channelAccountId = String(options.channelAccountId || "").trim();
|
|
73
|
+
this.displayName = String(options.name || "").trim();
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
isEnabled(_context: AgentContext): boolean {
|
|
77
|
+
return this.enabled;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
getChannelAccountId(_context: AgentContext): string {
|
|
81
|
+
return this.channelAccountId;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
applyRuntimePatch(patch: ChatChannelRuntimePatch): void {
|
|
85
|
+
if (typeof patch.enabled === "boolean") {
|
|
86
|
+
this.enabled = patch.enabled;
|
|
87
|
+
}
|
|
88
|
+
if (Object.prototype.hasOwnProperty.call(patch, "channelAccountId")) {
|
|
89
|
+
this.channelAccountId = String(patch.channelAccountId || "").trim();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
protected getStoredAccount(): StoredChannelAccount | null {
|
|
94
|
+
if (!this.channelAccountId) return null;
|
|
95
|
+
const account = getStoredChannelAccountSync(this.channelAccountId);
|
|
96
|
+
if (!account || account.channel !== this.name) return null;
|
|
97
|
+
return account;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
protected nowIso(): string {
|
|
101
|
+
return new Date().toISOString();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
abstract getAccount(context: AgentContext): StoredChannelAccount | null;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Telegram channel 配置。
|
|
109
|
+
*/
|
|
110
|
+
export interface TelegramChannelOptions extends BaseChatChannelOptions {
|
|
111
|
+
/**
|
|
112
|
+
* Telegram bot token。
|
|
113
|
+
*
|
|
114
|
+
* 说明(中文)
|
|
115
|
+
* - 优先级高于 `env.TELEGRAM_BOT_TOKEN`。
|
|
116
|
+
*/
|
|
117
|
+
botToken?: string;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Telegram channel。
|
|
122
|
+
*/
|
|
123
|
+
export class TelegramChannel extends BaseRuntimeChatChannel {
|
|
124
|
+
readonly name = "telegram" as const;
|
|
125
|
+
private readonly botToken?: string;
|
|
126
|
+
|
|
127
|
+
constructor(options: TelegramChannelOptions = {}) {
|
|
128
|
+
super(options);
|
|
129
|
+
this.botToken = String(options.botToken || "").trim() || undefined;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
getAccount(_context: AgentContext): StoredChannelAccount | null {
|
|
133
|
+
const storedAccount = this.getStoredAccount();
|
|
134
|
+
if (storedAccount) return storedAccount;
|
|
135
|
+
|
|
136
|
+
const token = String(this.botToken || this.env.TELEGRAM_BOT_TOKEN || "").trim();
|
|
137
|
+
if (!token) return null;
|
|
138
|
+
const now = this.nowIso();
|
|
139
|
+
return {
|
|
140
|
+
id: this.channelAccountId || "chat-sdk-telegram",
|
|
141
|
+
channel: "telegram",
|
|
142
|
+
name: this.displayName || "telegram",
|
|
143
|
+
botToken: token,
|
|
144
|
+
createdAt: now,
|
|
145
|
+
updatedAt: now,
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Feishu channel 配置。
|
|
152
|
+
*/
|
|
153
|
+
export interface FeishuChannelOptions extends BaseChatChannelOptions {
|
|
154
|
+
/**
|
|
155
|
+
* Feishu / Lark App ID。
|
|
156
|
+
*/
|
|
157
|
+
appId?: string;
|
|
158
|
+
/**
|
|
159
|
+
* Feishu / Lark App Secret。
|
|
160
|
+
*/
|
|
161
|
+
appSecret?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Feishu / Lark Open API 域名。
|
|
164
|
+
*/
|
|
165
|
+
domain?: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Feishu channel。
|
|
170
|
+
*/
|
|
171
|
+
export class FeishuChannel extends BaseRuntimeChatChannel {
|
|
172
|
+
readonly name = "feishu" as const;
|
|
173
|
+
private readonly appId?: string;
|
|
174
|
+
private readonly appSecret?: string;
|
|
175
|
+
private readonly domain?: string;
|
|
176
|
+
|
|
177
|
+
constructor(options: FeishuChannelOptions = {}) {
|
|
178
|
+
super(options);
|
|
179
|
+
this.appId = String(options.appId || "").trim() || undefined;
|
|
180
|
+
this.appSecret = String(options.appSecret || "").trim() || undefined;
|
|
181
|
+
this.domain = String(options.domain || "").trim() || undefined;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
getAccount(_context: AgentContext): StoredChannelAccount | null {
|
|
185
|
+
const storedAccount = this.getStoredAccount();
|
|
186
|
+
if (storedAccount) return storedAccount;
|
|
187
|
+
|
|
188
|
+
const appId = String(this.appId || this.env.FEISHU_APP_ID || "").trim();
|
|
189
|
+
const appSecret = String(
|
|
190
|
+
this.appSecret || this.env.FEISHU_APP_SECRET || "",
|
|
191
|
+
).trim();
|
|
192
|
+
const domain = String(this.domain || this.env.FEISHU_DOMAIN || "").trim();
|
|
193
|
+
if (!appId || !appSecret) return null;
|
|
194
|
+
const now = this.nowIso();
|
|
195
|
+
return {
|
|
196
|
+
id: this.channelAccountId || "chat-sdk-feishu",
|
|
197
|
+
channel: "feishu",
|
|
198
|
+
name: this.displayName || "feishu",
|
|
199
|
+
appId,
|
|
200
|
+
appSecret,
|
|
201
|
+
...(domain ? { domain } : {}),
|
|
202
|
+
createdAt: now,
|
|
203
|
+
updatedAt: now,
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* QQ channel 配置。
|
|
210
|
+
*/
|
|
211
|
+
export interface QqChannelOptions extends BaseChatChannelOptions {
|
|
212
|
+
/**
|
|
213
|
+
* QQ Bot App ID。
|
|
214
|
+
*/
|
|
215
|
+
appId?: string;
|
|
216
|
+
/**
|
|
217
|
+
* QQ Bot App Secret。
|
|
218
|
+
*/
|
|
219
|
+
appSecret?: string;
|
|
220
|
+
/**
|
|
221
|
+
* 是否使用 QQ 沙箱模式。
|
|
222
|
+
*/
|
|
223
|
+
sandbox?: boolean;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* QQ channel。
|
|
228
|
+
*/
|
|
229
|
+
export class QqChannel extends BaseRuntimeChatChannel {
|
|
230
|
+
readonly name = "qq" as const;
|
|
231
|
+
private readonly appId?: string;
|
|
232
|
+
private readonly appSecret?: string;
|
|
233
|
+
private readonly sandbox?: boolean;
|
|
234
|
+
|
|
235
|
+
constructor(options: QqChannelOptions = {}) {
|
|
236
|
+
super(options);
|
|
237
|
+
this.appId = String(options.appId || "").trim() || undefined;
|
|
238
|
+
this.appSecret = String(options.appSecret || "").trim() || undefined;
|
|
239
|
+
this.sandbox = options.sandbox === true;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
getAccount(_context: AgentContext): StoredChannelAccount | null {
|
|
243
|
+
const storedAccount = this.getStoredAccount();
|
|
244
|
+
if (storedAccount) return storedAccount;
|
|
245
|
+
|
|
246
|
+
const appId = String(this.appId || this.env.QQ_APP_ID || "").trim();
|
|
247
|
+
const appSecret = String(this.appSecret || this.env.QQ_APP_SECRET || "").trim();
|
|
248
|
+
const sandbox =
|
|
249
|
+
this.sandbox === true ||
|
|
250
|
+
String(this.env.QQ_SANDBOX || "").trim().toLowerCase() === "true";
|
|
251
|
+
if (!appId || !appSecret) return null;
|
|
252
|
+
const now = this.nowIso();
|
|
253
|
+
return {
|
|
254
|
+
id: this.channelAccountId || "chat-sdk-qq",
|
|
255
|
+
channel: "qq",
|
|
256
|
+
name: this.displayName || "qq",
|
|
257
|
+
appId,
|
|
258
|
+
appSecret,
|
|
259
|
+
...(sandbox ? { sandbox: true } : {}),
|
|
260
|
+
createdAt: now,
|
|
261
|
+
updatedAt: now,
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ChatAuthorizationRuntime:ChatPlugin 内置授权能力。
|
|
3
|
+
*
|
|
4
|
+
* 关键点(中文)
|
|
5
|
+
* - 授权能力归属于 ChatPlugin,不再作为独立 plugin 注册。
|
|
6
|
+
* - chat runtime 仍通过通用 plugin hook / resolve 点调用,保持执行链路统一。
|
|
7
|
+
* - action 名称统一带 `authorization-` 前缀,避免和 chat 会话动作混淆。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
PluginActions,
|
|
12
|
+
PluginHooks,
|
|
13
|
+
PluginResolves,
|
|
14
|
+
} from "@downcity/agent/internal/plugin/types/Plugin.js";
|
|
15
|
+
import type { JsonValue } from "@downcity/agent/internal/types/common/Json.js";
|
|
16
|
+
import { CHAT_PLUGIN_POINTS } from "@/chat/runtime/PluginPoints.js";
|
|
17
|
+
import type { ChatDispatchChannel } from "@/chat/types/ChatDispatcher.js";
|
|
18
|
+
import {
|
|
19
|
+
CHAT_AUTHORIZATION_ACTIONS,
|
|
20
|
+
CHAT_AUTHORIZATION_CATALOG,
|
|
21
|
+
type ChatAuthorizationConfig,
|
|
22
|
+
type ChatAuthorizationEvaluateInput,
|
|
23
|
+
type ChatAuthorizationObservePrincipalPayload,
|
|
24
|
+
type ChatAuthorizationSetUserRolePayload,
|
|
25
|
+
type ChatAuthorizationSnapshot,
|
|
26
|
+
type ChatAuthorizationWriteConfigPayload,
|
|
27
|
+
} from "@/auth/types/AuthPlugin.js";
|
|
28
|
+
import {
|
|
29
|
+
readChatAuthorizationConfig,
|
|
30
|
+
setChatAuthorizationUserRole,
|
|
31
|
+
writeChatAuthorizationConfig,
|
|
32
|
+
} from "@/auth/runtime/AuthorizationConfig.js";
|
|
33
|
+
import {
|
|
34
|
+
evaluateIncomingChatAuthorization,
|
|
35
|
+
resolveAuthorizedUserRole,
|
|
36
|
+
} from "@/auth/runtime/AuthorizationPolicy.js";
|
|
37
|
+
import {
|
|
38
|
+
readAuthorizationSnapshot,
|
|
39
|
+
recordObservedAuthorizationPrincipal,
|
|
40
|
+
} from "@/auth/runtime/AuthorizationStore.js";
|
|
41
|
+
|
|
42
|
+
function toChannel(value: unknown): ChatDispatchChannel | null {
|
|
43
|
+
const text = String(value || "").trim().toLowerCase();
|
|
44
|
+
if (text === "telegram" || text === "feishu" || text === "qq") return text;
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function toRecord(value: unknown): Record<string, unknown> {
|
|
49
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return {};
|
|
50
|
+
return value as Record<string, unknown>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function toEvaluateInput(payload: Record<string, unknown>): ChatAuthorizationEvaluateInput {
|
|
54
|
+
const channel = toChannel(payload.channel);
|
|
55
|
+
if (!channel) {
|
|
56
|
+
throw new Error("chat.authorizeIncoming requires a valid channel");
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
channel,
|
|
60
|
+
chatId: String(payload.chatId || "").trim(),
|
|
61
|
+
...(typeof payload.chatType === "string" ? { chatType: payload.chatType.trim() } : {}),
|
|
62
|
+
...(typeof payload.userId === "string" ? { userId: payload.userId.trim() } : {}),
|
|
63
|
+
...(typeof payload.username === "string" ? { username: payload.username.trim() } : {}),
|
|
64
|
+
...(typeof payload.chatTitle === "string" ? { chatTitle: payload.chatTitle.trim() } : {}),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function toSnapshotData(snapshot: ChatAuthorizationSnapshot): JsonValue {
|
|
69
|
+
return {
|
|
70
|
+
catalog: CHAT_AUTHORIZATION_CATALOG as unknown as JsonValue,
|
|
71
|
+
config: snapshot.config as unknown as JsonValue,
|
|
72
|
+
users: snapshot.users as unknown as JsonValue,
|
|
73
|
+
chats: snapshot.chats as unknown as JsonValue,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* 创建 ChatPlugin 内置授权 hooks。
|
|
79
|
+
*/
|
|
80
|
+
export function createChatAuthorizationHooks(): PluginHooks {
|
|
81
|
+
return {
|
|
82
|
+
guard: {
|
|
83
|
+
[CHAT_PLUGIN_POINTS.authorizeIncoming]: [
|
|
84
|
+
async ({ context, value }) => {
|
|
85
|
+
const input =
|
|
86
|
+
value && typeof value === "object" && !Array.isArray(value)
|
|
87
|
+
? (value as Record<string, unknown>)
|
|
88
|
+
: {};
|
|
89
|
+
const evaluateInput = toEvaluateInput(input);
|
|
90
|
+
const authorizationConfig = readChatAuthorizationConfig(context);
|
|
91
|
+
const result = evaluateIncomingChatAuthorization({
|
|
92
|
+
config: context.config,
|
|
93
|
+
channel: evaluateInput.channel,
|
|
94
|
+
input: evaluateInput,
|
|
95
|
+
authorizationConfig,
|
|
96
|
+
});
|
|
97
|
+
if (result.decision !== "allow") {
|
|
98
|
+
throw new Error(result.reason || "chat authorization blocked");
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
effect: {
|
|
104
|
+
[CHAT_PLUGIN_POINTS.observePrincipal]: [
|
|
105
|
+
async ({ context, value }) => {
|
|
106
|
+
const input = toRecord(
|
|
107
|
+
value,
|
|
108
|
+
) as unknown as ChatAuthorizationObservePrincipalPayload;
|
|
109
|
+
const channel = toChannel(input.channel);
|
|
110
|
+
if (!channel) {
|
|
111
|
+
throw new Error("chat.observePrincipal requires a valid channel");
|
|
112
|
+
}
|
|
113
|
+
await recordObservedAuthorizationPrincipal({
|
|
114
|
+
context,
|
|
115
|
+
channel,
|
|
116
|
+
chatId: String(input.chatId || "").trim(),
|
|
117
|
+
...(typeof input.chatType === "string"
|
|
118
|
+
? { chatType: input.chatType.trim() }
|
|
119
|
+
: {}),
|
|
120
|
+
...(typeof input.chatTitle === "string"
|
|
121
|
+
? { chatTitle: input.chatTitle.trim() }
|
|
122
|
+
: {}),
|
|
123
|
+
...(typeof input.userId === "string"
|
|
124
|
+
? { userId: input.userId.trim() }
|
|
125
|
+
: {}),
|
|
126
|
+
...(typeof input.username === "string"
|
|
127
|
+
? { username: input.username.trim() }
|
|
128
|
+
: {}),
|
|
129
|
+
});
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 创建 ChatPlugin 内置授权 resolve 点。
|
|
138
|
+
*/
|
|
139
|
+
export function createChatAuthorizationResolves(): PluginResolves {
|
|
140
|
+
return {
|
|
141
|
+
[CHAT_PLUGIN_POINTS.resolveUserRole]: async ({ context, value }) => {
|
|
142
|
+
const input =
|
|
143
|
+
value && typeof value === "object" && !Array.isArray(value)
|
|
144
|
+
? (value as Record<string, unknown>)
|
|
145
|
+
: {};
|
|
146
|
+
const channel = toChannel(input.channel);
|
|
147
|
+
if (!channel) {
|
|
148
|
+
throw new Error("chat.resolveUserRole requires a valid channel");
|
|
149
|
+
}
|
|
150
|
+
const role = resolveAuthorizedUserRole({
|
|
151
|
+
channel,
|
|
152
|
+
userId: String(input.userId || "").trim(),
|
|
153
|
+
rootPath: context.rootPath,
|
|
154
|
+
});
|
|
155
|
+
return ((role || null) as unknown) as JsonValue;
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* 创建 ChatPlugin 内置授权 actions。
|
|
162
|
+
*/
|
|
163
|
+
export function createChatAuthorizationActions(): PluginActions {
|
|
164
|
+
return {
|
|
165
|
+
[CHAT_AUTHORIZATION_ACTIONS.snapshot]: {
|
|
166
|
+
execute: async ({ context }) => {
|
|
167
|
+
const snapshot = await readAuthorizationSnapshot({
|
|
168
|
+
context,
|
|
169
|
+
});
|
|
170
|
+
return {
|
|
171
|
+
success: true,
|
|
172
|
+
data: toSnapshotData(snapshot),
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
[CHAT_AUTHORIZATION_ACTIONS.readConfig]: {
|
|
177
|
+
execute: async ({ context }) => {
|
|
178
|
+
return {
|
|
179
|
+
success: true,
|
|
180
|
+
data: readChatAuthorizationConfig(context) as unknown as JsonValue,
|
|
181
|
+
};
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
[CHAT_AUTHORIZATION_ACTIONS.writeConfig]: {
|
|
185
|
+
execute: async ({ context, payload }) => {
|
|
186
|
+
const body = toRecord(
|
|
187
|
+
payload,
|
|
188
|
+
) as unknown as ChatAuthorizationWriteConfigPayload;
|
|
189
|
+
const nextConfig =
|
|
190
|
+
body.config && typeof body.config === "object" && !Array.isArray(body.config)
|
|
191
|
+
? (body.config as ChatAuthorizationConfig)
|
|
192
|
+
: {};
|
|
193
|
+
await writeChatAuthorizationConfig({
|
|
194
|
+
context,
|
|
195
|
+
nextConfig,
|
|
196
|
+
});
|
|
197
|
+
return {
|
|
198
|
+
success: true,
|
|
199
|
+
data: readChatAuthorizationConfig(context) as unknown as JsonValue,
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
[CHAT_AUTHORIZATION_ACTIONS.setUserRole]: {
|
|
204
|
+
execute: async ({ context, payload }) => {
|
|
205
|
+
const body = toRecord(
|
|
206
|
+
payload,
|
|
207
|
+
) as unknown as ChatAuthorizationSetUserRolePayload;
|
|
208
|
+
const channel = toChannel(body.channel);
|
|
209
|
+
if (!channel) {
|
|
210
|
+
return {
|
|
211
|
+
success: false,
|
|
212
|
+
error: "authorization-set-user-role requires a valid channel",
|
|
213
|
+
message: "authorization-set-user-role requires a valid channel",
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
await setChatAuthorizationUserRole({
|
|
217
|
+
context,
|
|
218
|
+
channel,
|
|
219
|
+
userId: String(body.userId || "").trim(),
|
|
220
|
+
roleId: String(body.roleId || "").trim(),
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
success: true,
|
|
224
|
+
data: readChatAuthorizationConfig(context) as unknown as JsonValue,
|
|
225
|
+
};
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
};
|
|
229
|
+
}
|
|
@@ -25,11 +25,11 @@ import {
|
|
|
25
25
|
getChatChannelStatus,
|
|
26
26
|
listChatChannelConfigurationDescriptions,
|
|
27
27
|
normalizeChatChannelConfigPatch,
|
|
28
|
-
setChatChannelConfig,
|
|
29
|
-
setChatChannelEnabled,
|
|
30
28
|
} from "./ChatChannelConfig.js";
|
|
31
29
|
import {
|
|
30
|
+
type ChatRuntimeBindings,
|
|
32
31
|
getChatChannelBot,
|
|
32
|
+
resolveChatPluginBindings,
|
|
33
33
|
resolveTargetChannels,
|
|
34
34
|
} from "./ChatChannelCore.js";
|
|
35
35
|
import {
|
|
@@ -37,6 +37,18 @@ import {
|
|
|
37
37
|
stopSingleChatChannel,
|
|
38
38
|
} from "./ChatChannelLifecycle.js";
|
|
39
39
|
|
|
40
|
+
type ChatRuntimeControlBindings = ChatRuntimeBindings & {
|
|
41
|
+
applyChannelRuntimePatch: NonNullable<ChatRuntimeBindings["applyChannelRuntimePatch"]>;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
function getChatRuntimeBindings(context: AgentContext): ChatRuntimeControlBindings {
|
|
45
|
+
const plugin = resolveChatPluginBindings(context);
|
|
46
|
+
if (!plugin?.applyChannelRuntimePatch) {
|
|
47
|
+
throw new Error("ChatPlugin runtime instance is not available");
|
|
48
|
+
}
|
|
49
|
+
return plugin as ChatRuntimeControlBindings;
|
|
50
|
+
}
|
|
51
|
+
|
|
40
52
|
/**
|
|
41
53
|
* 执行 `chat.status` action。
|
|
42
54
|
*/
|
|
@@ -163,9 +175,9 @@ export async function executeChatOpenAction(params: {
|
|
|
163
175
|
payload: ChatOpenActionPayload;
|
|
164
176
|
}) {
|
|
165
177
|
const targets = resolveTargetChannels(params.payload.channel);
|
|
178
|
+
const plugin = getChatRuntimeBindings(params.context);
|
|
166
179
|
for (const channel of targets) {
|
|
167
|
-
|
|
168
|
-
context: params.context,
|
|
180
|
+
plugin.applyChannelRuntimePatch({
|
|
169
181
|
channel,
|
|
170
182
|
enabled: true,
|
|
171
183
|
});
|
|
@@ -198,10 +210,10 @@ export async function executeChatCloseAction(params: {
|
|
|
198
210
|
payload: ChatCloseActionPayload;
|
|
199
211
|
}) {
|
|
200
212
|
const targets = resolveTargetChannels(params.payload.channel);
|
|
213
|
+
const plugin = getChatRuntimeBindings(params.context);
|
|
201
214
|
for (const channel of targets) {
|
|
202
215
|
await stopSingleChatChannel(params.state, channel);
|
|
203
|
-
|
|
204
|
-
context: params.context,
|
|
216
|
+
plugin.applyChannelRuntimePatch({
|
|
205
217
|
channel,
|
|
206
218
|
enabled: false,
|
|
207
219
|
});
|
|
@@ -280,10 +292,13 @@ export async function executeChatConfigureAction(params: {
|
|
|
280
292
|
}
|
|
281
293
|
}
|
|
282
294
|
|
|
283
|
-
|
|
284
|
-
|
|
295
|
+
const plugin = getChatRuntimeBindings(params.context);
|
|
296
|
+
plugin.applyChannelRuntimePatch({
|
|
285
297
|
channel,
|
|
286
|
-
patch,
|
|
298
|
+
...(typeof patch.enabled === "boolean" ? { enabled: patch.enabled } : {}),
|
|
299
|
+
...(Object.prototype.hasOwnProperty.call(patch, "channelAccountId")
|
|
300
|
+
? { channelAccountId: String(patch.channelAccountId || "").trim() || null }
|
|
301
|
+
: {}),
|
|
287
302
|
});
|
|
288
303
|
|
|
289
304
|
// 关键点(中文):默认重载一次目标渠道,让新配置立刻生效。
|
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
* ChatChannelConfig:chat 渠道配置与状态快照模块。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - 渠道配置摘要、状态快照、patch
|
|
6
|
-
* -
|
|
5
|
+
* - 渠道配置摘要、状态快照、patch 归一化都收敛在这里。
|
|
6
|
+
* - chat.configure 的运行态写入由 ChatPlugin 实例承载,不再落盘到 downcity.json。
|
|
7
7
|
* - 该模块不直接负责 action 流程控制,只提供可复用的底层能力。
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import fs from "node:fs/promises";
|
|
11
|
-
import path from "node:path";
|
|
12
10
|
import type { JsonObject, JsonValue } from "@downcity/agent/internal/types/common/Json.js";
|
|
13
11
|
import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
|
|
14
12
|
import type { StoredChannelAccount } from "@downcity/agent/internal/types/platform/Store.js";
|
|
@@ -109,47 +107,6 @@ export function getChatChannelStatus(
|
|
|
109
107
|
};
|
|
110
108
|
}
|
|
111
109
|
|
|
112
|
-
/**
|
|
113
|
-
* 更新内存配置与 downcity.json 中的 channel enabled 状态。
|
|
114
|
-
*/
|
|
115
|
-
export async function setChatChannelEnabled(params: {
|
|
116
|
-
context: AgentContext;
|
|
117
|
-
channel: ChatChannelName;
|
|
118
|
-
enabled: boolean;
|
|
119
|
-
}): Promise<void> {
|
|
120
|
-
const { context, channel, enabled } = params;
|
|
121
|
-
|
|
122
|
-
const configPlugins = ((context.config.plugins ??= {}) as {
|
|
123
|
-
chat?: {
|
|
124
|
-
channels?: Record<string, Record<string, unknown>>;
|
|
125
|
-
};
|
|
126
|
-
});
|
|
127
|
-
const chatConfig = (configPlugins.chat ??= {});
|
|
128
|
-
const channelConfigs = (chatConfig.channels ??= {});
|
|
129
|
-
const channelConfig = (channelConfigs[channel] ??= {});
|
|
130
|
-
channelConfig.enabled = enabled;
|
|
131
|
-
|
|
132
|
-
const shipPath = path.join(context.rootPath, "downcity.json");
|
|
133
|
-
let shipJson: Record<string, unknown> = {};
|
|
134
|
-
try {
|
|
135
|
-
const raw = await fs.readFile(shipPath, "utf-8");
|
|
136
|
-
const parsed = JSON.parse(raw) as unknown;
|
|
137
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
138
|
-
shipJson = parsed as Record<string, unknown>;
|
|
139
|
-
}
|
|
140
|
-
} catch {
|
|
141
|
-
shipJson = {};
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const shipPlugins = ((shipJson.plugins ??= {}) as Record<string, unknown>);
|
|
145
|
-
const shipChat = ((shipPlugins.chat ??= {}) as Record<string, unknown>);
|
|
146
|
-
const shipChannels = ((shipChat.channels ??= {}) as Record<string, unknown>);
|
|
147
|
-
const shipChannel = ((shipChannels[channel] ??= {}) as Record<string, unknown>);
|
|
148
|
-
shipChannel.enabled = enabled;
|
|
149
|
-
|
|
150
|
-
await fs.writeFile(shipPath, `${JSON.stringify(shipJson, null, 2)}\n`, "utf-8");
|
|
151
|
-
}
|
|
152
|
-
|
|
153
110
|
function isJsonObject(value: JsonValue): value is JsonObject {
|
|
154
111
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
155
112
|
}
|
|
@@ -253,61 +210,6 @@ export function normalizeChatChannelConfigPatch(params: {
|
|
|
253
210
|
return patch;
|
|
254
211
|
}
|
|
255
212
|
|
|
256
|
-
function applyChannelPatch(
|
|
257
|
-
target: Record<string, unknown>,
|
|
258
|
-
patch: Record<string, string | number | boolean | null>,
|
|
259
|
-
): void {
|
|
260
|
-
for (const [key, value] of Object.entries(patch)) {
|
|
261
|
-
if (value === null) {
|
|
262
|
-
delete target[key];
|
|
263
|
-
continue;
|
|
264
|
-
}
|
|
265
|
-
target[key] = value;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* 更新单个 channel 配置(内存 + downcity.json)。
|
|
271
|
-
*/
|
|
272
|
-
export async function setChatChannelConfig(params: {
|
|
273
|
-
context: AgentContext;
|
|
274
|
-
channel: ChatChannelName;
|
|
275
|
-
patch: Record<string, string | number | boolean | null>;
|
|
276
|
-
}): Promise<void> {
|
|
277
|
-
const { context, channel, patch } = params;
|
|
278
|
-
if (Object.keys(patch).length === 0) return;
|
|
279
|
-
|
|
280
|
-
const configPlugins = ((context.config.plugins ??= {}) as {
|
|
281
|
-
chat?: {
|
|
282
|
-
channels?: Record<string, Record<string, unknown>>;
|
|
283
|
-
};
|
|
284
|
-
});
|
|
285
|
-
const chatConfig = (configPlugins.chat ??= {});
|
|
286
|
-
const channelConfigs = (chatConfig.channels ??= {});
|
|
287
|
-
const channelConfig = (channelConfigs[channel] ??= {});
|
|
288
|
-
applyChannelPatch(channelConfig, patch);
|
|
289
|
-
|
|
290
|
-
const shipPath = path.join(context.rootPath, "downcity.json");
|
|
291
|
-
let shipJson: Record<string, unknown> = {};
|
|
292
|
-
try {
|
|
293
|
-
const raw = await fs.readFile(shipPath, "utf-8");
|
|
294
|
-
const parsed = JSON.parse(raw) as unknown;
|
|
295
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
296
|
-
shipJson = parsed as Record<string, unknown>;
|
|
297
|
-
}
|
|
298
|
-
} catch {
|
|
299
|
-
shipJson = {};
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
const shipPlugins = ((shipJson.plugins ??= {}) as Record<string, unknown>);
|
|
303
|
-
const shipChat = ((shipPlugins.chat ??= {}) as Record<string, unknown>);
|
|
304
|
-
const shipChannels = ((shipChat.channels ??= {}) as Record<string, unknown>);
|
|
305
|
-
const shipChannel = ((shipChannels[channel] ??= {}) as Record<string, unknown>);
|
|
306
|
-
applyChannelPatch(shipChannel, patch);
|
|
307
|
-
|
|
308
|
-
await fs.writeFile(shipPath, `${JSON.stringify(shipJson, null, 2)}\n`, "utf-8");
|
|
309
|
-
}
|
|
310
|
-
|
|
311
213
|
/**
|
|
312
214
|
* 读取渠道 configuration 描述。
|
|
313
215
|
*/
|