opencode-chat-channel 1.1.0 → 1.2.1
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/README.md +40 -2
- package/dist/channels/feishu/index.d.ts.map +1 -1
- package/dist/index.d.ts +11 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +40 -18
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -47,7 +47,26 @@ Edit `~/.config/opencode/opencode.json` and add the plugin:
|
|
|
47
47
|
|
|
48
48
|
opencode will pull and install the package automatically on next startup.
|
|
49
49
|
|
|
50
|
-
#### Step 2:
|
|
50
|
+
#### Step 2: Select channels to enable
|
|
51
|
+
|
|
52
|
+
Add `CHAT_CHANNELS` to `~/.config/opencode/.env` to control which channels are active:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# ~/.config/opencode/.env
|
|
56
|
+
|
|
57
|
+
# Enable Feishu only (recommended to start)
|
|
58
|
+
CHAT_CHANNELS=feishu
|
|
59
|
+
|
|
60
|
+
# Enable multiple channels at once
|
|
61
|
+
# CHAT_CHANNELS=feishu,wecom
|
|
62
|
+
|
|
63
|
+
# Leave unset or empty = auto mode: any channel with valid credentials starts automatically
|
|
64
|
+
# CHAT_CHANNELS=
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Then configure credentials for each enabled channel (see sections below).
|
|
68
|
+
|
|
69
|
+
#### Step 3: Configure channel credentials
|
|
51
70
|
|
|
52
71
|
See the [Feishu Configuration](#feishu-configuration) section below.
|
|
53
72
|
|
|
@@ -205,7 +224,26 @@ opencode AI (Sisyphus)
|
|
|
205
224
|
|
|
206
225
|
下次启动 opencode 时会自动拉取并安装。
|
|
207
226
|
|
|
208
|
-
####
|
|
227
|
+
#### 第二步:选择要启用的渠道
|
|
228
|
+
|
|
229
|
+
在 `~/.config/opencode/.env` 中配置 `CHAT_CHANNELS`,指定要开启哪些渠道:
|
|
230
|
+
|
|
231
|
+
```bash
|
|
232
|
+
# ~/.config/opencode/.env
|
|
233
|
+
|
|
234
|
+
# 只开启飞书(初始推荐)
|
|
235
|
+
CHAT_CHANNELS=feishu
|
|
236
|
+
|
|
237
|
+
# 同时开启多个渠道
|
|
238
|
+
# CHAT_CHANNELS=feishu,wecom
|
|
239
|
+
|
|
240
|
+
# 留空或不配置 = 自动模式:凭证存在的渠道自动启用
|
|
241
|
+
# CHAT_CHANNELS=
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
然后配置对应渠道的凭证(见下方各渠道配置说明)。
|
|
245
|
+
|
|
246
|
+
#### 第三步:配置渠道凭证
|
|
209
247
|
|
|
210
248
|
参见下方各渠道的配置说明。
|
|
211
249
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/feishu/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAe,cAAc,EAAiC,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/channels/feishu/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,KAAK,EAAe,cAAc,EAAiC,MAAM,gBAAgB,CAAC;AA8JjG;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,cAuBlC,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* opencode-chat-channel — opencode 多渠道机器人插件
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 当前已实现:飞书(Feishu/Lark)
|
|
6
|
-
* 骨架已创建:企业微信(WeCom)
|
|
4
|
+
* 通过 .env 文件中的 CHAT_CHANNELS 配置项选择启用哪些渠道:
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
6
|
+
* CHAT_CHANNELS=feishu # 只启用飞书
|
|
7
|
+
* CHAT_CHANNELS=feishu,wecom # 同时启用飞书和企业微信
|
|
8
|
+
* CHAT_CHANNELS= # 留空:自动探测(凭证存在即启用)
|
|
9
|
+
* # 不配置此项:同留空,自动探测
|
|
11
10
|
*
|
|
12
|
-
*
|
|
11
|
+
* 其他配置项:
|
|
12
|
+
* OPENCODE_BASE_URL opencode API 地址(默认 http://localhost:4321)
|
|
13
|
+
*
|
|
14
|
+
* 各渠道的凭证配置详见 README。
|
|
13
15
|
*/
|
|
14
16
|
import type { Plugin } from "@opencode-ai/plugin";
|
|
15
17
|
export declare const ChatChannelPlugin: Plugin;
|
|
16
18
|
export default ChatChannelPlugin;
|
|
17
|
-
export type { ChatChannel, ChannelFactory, IncomingMessage, PluginClient } from "./types.js";
|
|
18
|
-
export {
|
|
19
|
+
export type { ChatChannel, ChannelFactory, ChannelName, IncomingMessage, PluginClient } from "./types.js";
|
|
20
|
+
export { extractResponseText, loadDotEnv } from "./session-manager.js";
|
|
19
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAgIlD,eAAO,MAAM,iBAAiB,EAAE,MAyF/B,CAAC;AAEF,eAAe,iBAAiB,CAAC;AAGjC,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1G,OAAO,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -149,16 +149,6 @@ class FeishuChannel {
|
|
|
149
149
|
});
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
|
-
async sendThinking(chatId) {
|
|
153
|
-
await this.larkClient.im.message.create({
|
|
154
|
-
params: { receive_id_type: "chat_id" },
|
|
155
|
-
data: {
|
|
156
|
-
receive_id: chatId,
|
|
157
|
-
content: JSON.stringify({ text: "⏳ 正在思考..." }),
|
|
158
|
-
msg_type: "text"
|
|
159
|
-
}
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
152
|
parseEvent(data) {
|
|
163
153
|
const { message, sender } = data ?? {};
|
|
164
154
|
if (!message || !sender)
|
|
@@ -261,11 +251,32 @@ var wecomChannelFactory = async (client) => {
|
|
|
261
251
|
};
|
|
262
252
|
|
|
263
253
|
// src/index.ts
|
|
264
|
-
var
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
254
|
+
var CHANNEL_REGISTRY = {
|
|
255
|
+
feishu: feishuChannelFactory,
|
|
256
|
+
wecom: wecomChannelFactory
|
|
257
|
+
};
|
|
258
|
+
function resolveEnabledChannels(client) {
|
|
259
|
+
const raw = process.env["CHAT_CHANNELS"]?.trim();
|
|
260
|
+
if (!raw)
|
|
261
|
+
return null;
|
|
262
|
+
const requested = raw.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
263
|
+
const known = Object.keys(CHANNEL_REGISTRY);
|
|
264
|
+
const enabled = [];
|
|
265
|
+
for (const name of requested) {
|
|
266
|
+
if (known.includes(name)) {
|
|
267
|
+
enabled.push(name);
|
|
268
|
+
} else {
|
|
269
|
+
client.app.log({
|
|
270
|
+
body: {
|
|
271
|
+
service: "chat-channel",
|
|
272
|
+
level: "warn",
|
|
273
|
+
message: `[config] 未知渠道名 "${name}",已忽略。可用渠道:${known.join(", ")}`
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return enabled;
|
|
279
|
+
}
|
|
269
280
|
function createMessageHandler(channel, sessionManager, client) {
|
|
270
281
|
return async (msg) => {
|
|
271
282
|
const { userId, replyTarget, text } = msg;
|
|
@@ -313,18 +324,30 @@ function createMessageHandler(channel, sessionManager, client) {
|
|
|
313
324
|
var ChatChannelPlugin = async ({ client }) => {
|
|
314
325
|
const configDir = join(process.env["HOME"] ?? `/Users/${process.env["USER"] ?? "unknown"}`, ".config", "opencode");
|
|
315
326
|
loadDotEnv(join(configDir, ".env"));
|
|
327
|
+
const enabledNames = resolveEnabledChannels(client);
|
|
328
|
+
const factories = enabledNames ? enabledNames.map((name) => [name, CHANNEL_REGISTRY[name]]) : Object.entries(CHANNEL_REGISTRY);
|
|
329
|
+
if (enabledNames) {
|
|
330
|
+
await client.app.log({
|
|
331
|
+
body: {
|
|
332
|
+
service: "chat-channel",
|
|
333
|
+
level: "info",
|
|
334
|
+
message: `[config] CHAT_CHANNELS="${process.env["CHAT_CHANNELS"]}",将启用: ${enabledNames.join(", ") || "(无)"}`
|
|
335
|
+
}
|
|
336
|
+
});
|
|
337
|
+
}
|
|
316
338
|
const channels = [];
|
|
317
|
-
for (const factory of
|
|
339
|
+
for (const [, factory] of factories) {
|
|
318
340
|
const channel = await factory(client);
|
|
319
341
|
if (channel)
|
|
320
342
|
channels.push(channel);
|
|
321
343
|
}
|
|
322
344
|
if (channels.length === 0) {
|
|
345
|
+
const hint = enabledNames ? `检查 CHAT_CHANNELS="${process.env["CHAT_CHANNELS"]}" 指定的渠道是否已配置凭证` : "请在 .env 中配置至少一个渠道的凭证,或设置 CHAT_CHANNELS=<渠道名> 明确指定";
|
|
323
346
|
await client.app.log({
|
|
324
347
|
body: {
|
|
325
348
|
service: "chat-channel",
|
|
326
349
|
level: "warn",
|
|
327
|
-
message:
|
|
350
|
+
message: `所有渠道均未就绪,插件空启动。${hint}`
|
|
328
351
|
}
|
|
329
352
|
});
|
|
330
353
|
return {};
|
|
@@ -364,6 +387,5 @@ export {
|
|
|
364
387
|
loadDotEnv,
|
|
365
388
|
extractResponseText,
|
|
366
389
|
src_default as default,
|
|
367
|
-
SessionManager,
|
|
368
390
|
ChatChannelPlugin
|
|
369
391
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -49,4 +49,9 @@ export interface ChatChannel {
|
|
|
49
49
|
* 若凭证未配置,应返回 null(插件将跳过该渠道并记录日志)。
|
|
50
50
|
*/
|
|
51
51
|
export type ChannelFactory = (client: PluginClient) => Promise<ChatChannel | null>;
|
|
52
|
+
/**
|
|
53
|
+
* 已注册的渠道名称。
|
|
54
|
+
* 新增渠道时在此处添加对应字面量,便于编译期检查。
|
|
55
|
+
*/
|
|
56
|
+
export type ChannelName = "feishu" | "wecom";
|
|
52
57
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAI3D,kBAAkB;AAClB,MAAM,WAAW,eAAe;IAC9B,oBAAoB;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAID;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,KAAK,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE;;;OAGG;IACH,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvD,kBAAkB;IAClB,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAID;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,MAAM,EAAE,YAAY,KACjB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAElD,8CAA8C;AAC9C,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAI3D,kBAAkB;AAClB,MAAM,WAAW,eAAe;IAC9B,oBAAoB;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAC;IACf,sCAAsC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAID;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,gCAAgC;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,KAAK,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEzE;;;OAGG;IACH,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEvD,kBAAkB;IAClB,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAID;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,CAC3B,MAAM,EAAE,YAAY,KACjB,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;AAIjC;;;GAGG;AACH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,OAAO,CAAC"}
|
package/package.json
CHANGED