@downcity/plugins 1.0.57 → 1.0.60
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 +24 -2
- package/bin/BuiltinPlugins.d.ts.map +1 -1
- package/bin/BuiltinPlugins.js +18 -5
- package/bin/BuiltinPlugins.js.map +1 -1
- 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/contact/ContactPlugin.d.ts +6 -1
- package/bin/contact/ContactPlugin.d.ts.map +1 -1
- package/bin/contact/ContactPlugin.js +9 -8
- package/bin/contact/ContactPlugin.js.map +1 -1
- package/bin/contact/types/ContactPluginOptions.d.ts +29 -0
- package/bin/contact/types/ContactPluginOptions.d.ts.map +1 -0
- package/bin/contact/types/ContactPluginOptions.js +9 -0
- package/bin/contact/types/ContactPluginOptions.js.map +1 -0
- package/bin/index.d.ts +7 -4
- package/bin/index.d.ts.map +1 -1
- package/bin/index.js +3 -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/web/Plugin.js +1 -1
- package/bin/web/Plugin.js.map +1 -1
- package/bin/web/runtime/Install.js +2 -2
- package/bin/web/runtime/Install.js.map +1 -1
- package/bin/web/types/WebPlugin.d.ts +2 -1
- package/bin/web/types/WebPlugin.d.ts.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 +41 -5
- 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/contact/ContactPlugin.ts +17 -9
- package/src/contact/types/ContactPluginOptions.ts +30 -0
- package/src/index.ts +23 -7
- 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/web/Plugin.ts +1 -1
- package/src/web/runtime/Install.ts +3 -3
- package/src/web/types/WebPlugin.ts +2 -2
- package/src/workboard/Plugin.ts +80 -95
- 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/src/auth/Plugin.ts +0 -237
- package/src/chat/ChatPluginTypes.ts +0 -126
package/src/chat/ChatPlugin.ts
CHANGED
|
@@ -9,29 +9,47 @@
|
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
11
|
import { BasePlugin } from "@downcity/agent/internal/plugin/core/BasePlugin.js";
|
|
12
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
PluginActions,
|
|
14
|
+
PluginHooks,
|
|
15
|
+
PluginResolves,
|
|
16
|
+
} from "@downcity/agent/internal/plugin/types/Plugin.js";
|
|
13
17
|
import type { AgentContext } from "@downcity/agent/internal/types/runtime/agent/AgentContext.js";
|
|
14
18
|
import type { ChatChannelState } from "@/chat/types/ChatRuntime.js";
|
|
15
|
-
import type { StoredChannelAccount } from "@downcity/agent/internal/types/platform/Store.js";
|
|
16
19
|
import type { ChatQueueWorkerConfig } from "@/chat/types/ChatQueueWorker.js";
|
|
17
20
|
import type {
|
|
18
|
-
|
|
21
|
+
ChatChannel,
|
|
19
22
|
ChatPluginOptions,
|
|
20
|
-
|
|
21
|
-
ChatPluginTelegramOptions,
|
|
22
|
-
} from "@/chat/ChatPluginTypes.js";
|
|
23
|
+
} from "@/chat/types/ChatPluginOptions.js";
|
|
23
24
|
import type { ChatChannelName } from "@/chat/types/ChannelStatus.js";
|
|
25
|
+
import {
|
|
26
|
+
FeishuChannel,
|
|
27
|
+
QqChannel,
|
|
28
|
+
TelegramChannel,
|
|
29
|
+
} from "@/chat/channels/RuntimeChannel.js";
|
|
24
30
|
import {
|
|
25
31
|
createChatChannelState,
|
|
26
32
|
startChatChannels,
|
|
27
33
|
stopChatChannels,
|
|
28
34
|
} from "./runtime/ChatChannelFacade.js";
|
|
29
|
-
import { getStoredChannelAccountSync } from "./accounts/Store.js";
|
|
30
35
|
import { createChatPluginActions } from "./runtime/ChatPluginActions.js";
|
|
36
|
+
import {
|
|
37
|
+
createChatAuthorizationActions,
|
|
38
|
+
createChatAuthorizationHooks,
|
|
39
|
+
createChatAuthorizationResolves,
|
|
40
|
+
} from "./runtime/ChatAuthorizationRuntime.js";
|
|
31
41
|
import { ChatQueueWorker } from "./runtime/ChatQueueWorker.js";
|
|
32
42
|
import { buildChatPluginSystem } from "./runtime/ChatPluginSystem.js";
|
|
33
43
|
import { ChatQueueStore } from "./runtime/ChatQueueStore.js";
|
|
34
44
|
|
|
45
|
+
function createDefaultChannels(): ChatChannel[] {
|
|
46
|
+
return [
|
|
47
|
+
new TelegramChannel({ enabled: false }),
|
|
48
|
+
new FeishuChannel({ enabled: false }),
|
|
49
|
+
new QqChannel({ enabled: false }),
|
|
50
|
+
];
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
/**
|
|
36
54
|
* Chat plugin 类实现。
|
|
37
55
|
*/
|
|
@@ -69,6 +87,11 @@ export class ChatPlugin extends BasePlugin {
|
|
|
69
87
|
*/
|
|
70
88
|
public readonly options: ChatPluginOptions;
|
|
71
89
|
|
|
90
|
+
/**
|
|
91
|
+
* 当前实例持有的 chat channels。
|
|
92
|
+
*/
|
|
93
|
+
public readonly channels: ChatChannel[];
|
|
94
|
+
|
|
72
95
|
/**
|
|
73
96
|
* 当前 plugin 的 system 文本构建器。
|
|
74
97
|
*/
|
|
@@ -81,6 +104,16 @@ export class ChatPlugin extends BasePlugin {
|
|
|
81
104
|
*/
|
|
82
105
|
readonly actions: PluginActions;
|
|
83
106
|
|
|
107
|
+
/**
|
|
108
|
+
* 当前 plugin 的 hook 定义表。
|
|
109
|
+
*/
|
|
110
|
+
readonly hooks: PluginHooks;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* 当前 plugin 的 resolve 定义表。
|
|
114
|
+
*/
|
|
115
|
+
readonly resolves: PluginResolves;
|
|
116
|
+
|
|
84
117
|
/**
|
|
85
118
|
* 启动当前实例的 queue worker。
|
|
86
119
|
*/
|
|
@@ -109,9 +142,17 @@ export class ChatPlugin extends BasePlugin {
|
|
|
109
142
|
constructor(options?: ChatPluginOptions) {
|
|
110
143
|
super();
|
|
111
144
|
this.options = options || {};
|
|
112
|
-
this.
|
|
113
|
-
|
|
114
|
-
|
|
145
|
+
this.channels = Array.isArray(this.options.channels)
|
|
146
|
+
? [...this.options.channels]
|
|
147
|
+
: createDefaultChannels();
|
|
148
|
+
this.actions = {
|
|
149
|
+
...createChatPluginActions({
|
|
150
|
+
channelState: this.channelState,
|
|
151
|
+
}),
|
|
152
|
+
...createChatAuthorizationActions(),
|
|
153
|
+
};
|
|
154
|
+
this.hooks = createChatAuthorizationHooks();
|
|
155
|
+
this.resolves = createChatAuthorizationResolves();
|
|
115
156
|
this.lifecycle = {
|
|
116
157
|
start: async (context) => {
|
|
117
158
|
this.startQueueWorker(context);
|
|
@@ -130,18 +171,15 @@ export class ChatPlugin extends BasePlugin {
|
|
|
130
171
|
getQueueWorkerConfig(
|
|
131
172
|
context: AgentContext,
|
|
132
173
|
): Partial<ChatQueueWorkerConfig> | undefined {
|
|
133
|
-
|
|
174
|
+
void context;
|
|
175
|
+
return this.options.queue;
|
|
134
176
|
}
|
|
135
177
|
|
|
136
178
|
/**
|
|
137
179
|
* 判断指定渠道是否启用。
|
|
138
180
|
*/
|
|
139
181
|
isChannelEnabled(context: AgentContext, channel: ChatChannelName): boolean {
|
|
140
|
-
|
|
141
|
-
if (explicit) {
|
|
142
|
-
return explicit.enabled !== false;
|
|
143
|
-
}
|
|
144
|
-
return context.config.plugins?.chat?.channels?.[channel]?.enabled === true;
|
|
182
|
+
return this.getChannel(channel)?.isEnabled(context) === true;
|
|
145
183
|
}
|
|
146
184
|
|
|
147
185
|
/**
|
|
@@ -151,13 +189,40 @@ export class ChatPlugin extends BasePlugin {
|
|
|
151
189
|
context: AgentContext,
|
|
152
190
|
channel: ChatChannelName,
|
|
153
191
|
): string {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
192
|
+
return String(this.getChannel(channel)?.getChannelAccountId(context) || "").trim();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* 更新当前实例的渠道运行态配置。
|
|
197
|
+
*
|
|
198
|
+
* 关键点(中文)
|
|
199
|
+
* - chat.open/close/configure 只修改当前 plugin 实例,不写 downcity.json。
|
|
200
|
+
* - 当前运行态只允许更新 `enabled` 与 `channelAccountId`,密钥仍来自 constructor 或账号池。
|
|
201
|
+
*/
|
|
202
|
+
applyChannelRuntimePatch(params: {
|
|
203
|
+
/**
|
|
204
|
+
* 目标渠道。
|
|
205
|
+
*/
|
|
206
|
+
channel: ChatChannelName;
|
|
207
|
+
/**
|
|
208
|
+
* 是否启用该渠道。
|
|
209
|
+
*/
|
|
210
|
+
enabled?: boolean;
|
|
211
|
+
/**
|
|
212
|
+
* 绑定的账号池记录 ID;传入 null 表示清空绑定。
|
|
213
|
+
*/
|
|
214
|
+
channelAccountId?: string | null;
|
|
215
|
+
}): void {
|
|
216
|
+
const channel = this.getChannel(params.channel);
|
|
217
|
+
if (!channel) {
|
|
218
|
+
throw new Error(`Chat channel is not registered: ${params.channel}`);
|
|
219
|
+
}
|
|
220
|
+
channel.applyRuntimePatch({
|
|
221
|
+
...(typeof params.enabled === "boolean" ? { enabled: params.enabled } : {}),
|
|
222
|
+
...(Object.prototype.hasOwnProperty.call(params, "channelAccountId")
|
|
223
|
+
? { channelAccountId: params.channelAccountId ?? null }
|
|
224
|
+
: {}),
|
|
225
|
+
});
|
|
161
226
|
}
|
|
162
227
|
|
|
163
228
|
/**
|
|
@@ -166,73 +231,11 @@ export class ChatPlugin extends BasePlugin {
|
|
|
166
231
|
resolveChannelAccount(
|
|
167
232
|
context: AgentContext,
|
|
168
233
|
channel: ChatChannelName,
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
if (explicit) return explicit;
|
|
172
|
-
const channelAccountId = this.getChannelAccountId(context, channel);
|
|
173
|
-
if (!channelAccountId) return null;
|
|
174
|
-
return getStoredChannelAccountSync(channelAccountId);
|
|
234
|
+
) {
|
|
235
|
+
return this.getChannel(channel)?.getAccount(context) || null;
|
|
175
236
|
}
|
|
176
237
|
|
|
177
|
-
private
|
|
178
|
-
channel
|
|
179
|
-
): ChatPluginTelegramOptions | ChatPluginFeishuOptions | ChatPluginQqOptions | undefined {
|
|
180
|
-
if (channel === "telegram") return this.options.telegram;
|
|
181
|
-
if (channel === "feishu") return this.options.feishu;
|
|
182
|
-
return this.options.qq;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
private buildExplicitChannelAccount(
|
|
186
|
-
channel: ChatChannelName,
|
|
187
|
-
): StoredChannelAccount | null {
|
|
188
|
-
const now = new Date().toISOString();
|
|
189
|
-
|
|
190
|
-
if (channel === "telegram") {
|
|
191
|
-
const config = this.options.telegram;
|
|
192
|
-
const botToken = String(config?.botToken || "").trim();
|
|
193
|
-
if (!botToken) return null;
|
|
194
|
-
return {
|
|
195
|
-
id: String(config?.channelAccountId || `chat-sdk-${channel}`).trim(),
|
|
196
|
-
channel,
|
|
197
|
-
name: String(config?.name || "telegram").trim() || "telegram",
|
|
198
|
-
botToken,
|
|
199
|
-
createdAt: now,
|
|
200
|
-
updatedAt: now,
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
if (channel === "feishu") {
|
|
205
|
-
const config = this.options.feishu;
|
|
206
|
-
const appId = String(config?.appId || "").trim();
|
|
207
|
-
const appSecret = String(config?.appSecret || "").trim();
|
|
208
|
-
if (!appId || !appSecret) return null;
|
|
209
|
-
return {
|
|
210
|
-
id: String(config?.channelAccountId || `chat-sdk-${channel}`).trim(),
|
|
211
|
-
channel,
|
|
212
|
-
name: String(config?.name || "feishu").trim() || "feishu",
|
|
213
|
-
appId,
|
|
214
|
-
appSecret,
|
|
215
|
-
...(String(config?.domain || "").trim()
|
|
216
|
-
? { domain: String(config?.domain || "").trim() }
|
|
217
|
-
: {}),
|
|
218
|
-
createdAt: now,
|
|
219
|
-
updatedAt: now,
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const config = this.options.qq;
|
|
224
|
-
const appId = String(config?.appId || "").trim();
|
|
225
|
-
const appSecret = String(config?.appSecret || "").trim();
|
|
226
|
-
if (!appId || !appSecret) return null;
|
|
227
|
-
return {
|
|
228
|
-
id: String(config?.channelAccountId || `chat-sdk-${channel}`).trim(),
|
|
229
|
-
channel,
|
|
230
|
-
name: String(config?.name || "qq").trim() || "qq",
|
|
231
|
-
appId,
|
|
232
|
-
appSecret,
|
|
233
|
-
...(config?.sandbox === true ? { sandbox: true } : {}),
|
|
234
|
-
createdAt: now,
|
|
235
|
-
updatedAt: now,
|
|
236
|
-
};
|
|
238
|
+
private getChannel(channel: ChatChannelName): ChatChannel | null {
|
|
239
|
+
return this.channels.find((item) => item.name === channel) || null;
|
|
237
240
|
}
|
|
238
241
|
}
|
package/src/chat/Index.ts
CHANGED
|
@@ -2,7 +2,24 @@
|
|
|
2
2
|
* Chat Plugin 导出入口。
|
|
3
3
|
*
|
|
4
4
|
* 关键点(中文)
|
|
5
|
-
* - Index
|
|
5
|
+
* - Index 只负责导出类实现与 channel SDK 对象。
|
|
6
6
|
* - 真正的类实现位于 `ChatPlugin.ts`。
|
|
7
7
|
*/
|
|
8
8
|
export { ChatPlugin } from "./ChatPlugin.js";
|
|
9
|
+
export {
|
|
10
|
+
FeishuChannel,
|
|
11
|
+
QqChannel,
|
|
12
|
+
TelegramChannel,
|
|
13
|
+
} from "./channels/RuntimeChannel.js";
|
|
14
|
+
export type {
|
|
15
|
+
BaseChatChannelOptions,
|
|
16
|
+
ChatChannelEnv,
|
|
17
|
+
FeishuChannelOptions,
|
|
18
|
+
QqChannelOptions,
|
|
19
|
+
TelegramChannelOptions,
|
|
20
|
+
} from "./channels/RuntimeChannel.js";
|
|
21
|
+
export type {
|
|
22
|
+
ChatChannel,
|
|
23
|
+
ChatChannelRuntimePatch,
|
|
24
|
+
ChatPluginOptions,
|
|
25
|
+
} from "./types/ChatPluginOptions.js";
|
|
@@ -27,7 +27,7 @@ export abstract class ChatChannelConfiguration {
|
|
|
27
27
|
abstract describe(): ChatChannelConfigurationDescriptor;
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* 返回可通过 `chat.configure`
|
|
30
|
+
* 返回可通过 `chat.configure` 更新的运行态字段定义。
|
|
31
31
|
*/
|
|
32
32
|
getWritableShipFields(): ChatChannelConfigurationField[] {
|
|
33
33
|
return this.describe().fields.ship.filter((field) => field.writable);
|
|
@@ -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
|
+
}
|