@nextclaw/channel-runtime 0.4.1 → 0.4.3

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/dist/index.d.ts CHANGED
@@ -97,26 +97,6 @@ declare class EmailChannel extends BaseChannel<Config["channels"]["email"]> {
97
97
  private fetchNewMessages;
98
98
  }
99
99
 
100
- declare class FeishuChannel extends BaseChannel<Config["channels"]["feishu"]> {
101
- name: string;
102
- private clients;
103
- private processedMessageIds;
104
- private processedSet;
105
- private readonly inboundMediaResolver;
106
- constructor(config: Config["channels"]["feishu"], bus: MessageBus);
107
- start(): Promise<void>;
108
- stop(): Promise<void>;
109
- send(msg: OutboundMessage): Promise<void>;
110
- private handleIncoming;
111
- private isDuplicate;
112
- private addReaction;
113
- private resolveOutboundAccount;
114
- private isAllowedByPolicy;
115
- private resolveMentionState;
116
- private convertResource;
117
- private buildInboundPayload;
118
- }
119
-
120
100
  declare class MochatChannel extends BaseChannel<Config["channels"]["mochat"]> {
121
101
  name: string;
122
102
  private socket;
@@ -310,11 +290,6 @@ declare const BUILTIN_CHANNEL_RUNTIMES: {
310
290
  readonly isEnabled: (config: Config) => boolean;
311
291
  readonly createChannel: (context: BuiltinChannelCreateContext) => DiscordChannel;
312
292
  };
313
- readonly feishu: {
314
- readonly id: "feishu";
315
- readonly isEnabled: (config: Config) => boolean;
316
- readonly createChannel: (context: BuiltinChannelCreateContext) => FeishuChannel;
317
- };
318
293
  readonly mochat: {
319
294
  readonly id: "mochat";
320
295
  readonly isEnabled: (config: Config) => boolean;
@@ -351,4 +326,4 @@ declare const BUILTIN_CHANNEL_PLUGIN_IDS: BuiltinChannelId[];
351
326
  declare function listBuiltinChannelRuntimes(): BuiltinChannelRuntime[];
352
327
  declare function resolveBuiltinChannelRuntime(channelId: string): BuiltinChannelRuntime;
353
328
 
354
- export { BUILTIN_CHANNEL_PLUGIN_IDS, type BuiltinChannelId, type BuiltinChannelRuntime, DingTalkChannel, DiscordChannel, EmailChannel, FeishuChannel, MochatChannel, QQChannel, SlackChannel, TelegramChannel, WeComChannel, WhatsAppChannel, listBuiltinChannelRuntimes, resolveBuiltinChannelRuntime };
329
+ export { BUILTIN_CHANNEL_PLUGIN_IDS, type BuiltinChannelId, type BuiltinChannelRuntime, DingTalkChannel, DiscordChannel, EmailChannel, MochatChannel, QQChannel, SlackChannel, TelegramChannel, WeComChannel, WhatsAppChannel, listBuiltinChannelRuntimes, resolveBuiltinChannelRuntime };
package/dist/index.js CHANGED
@@ -1264,469 +1264,11 @@ var EmailChannel = class extends BaseChannel {
1264
1264
  }
1265
1265
  };
1266
1266
 
1267
- // src/channels/feishu-message-support.ts
1268
- var TABLE_RE = /((?:^[ \t]*\|.+\|[ \t]*\n)(?:^[ \t]*\|[-:\s|]+\|[ \t]*\n)(?:^[ \t]*\|.+\|[ \t]*\n?)+)/gm;
1269
- function extractSenderInfo(sender) {
1270
- const senderIdObj = sender.sender_id ?? {};
1271
- const senderOpenId = senderIdObj.open_id || sender.open_id || "";
1272
- const senderUserId = senderIdObj.user_id || sender.user_id || "";
1273
- const senderUnionId = senderIdObj.union_id || sender.union_id || "";
1274
- return {
1275
- senderId: senderOpenId || senderUserId || senderUnionId || "",
1276
- senderType: sender.sender_type ?? sender.senderType,
1277
- senderOpenId: senderOpenId || void 0,
1278
- senderUserId: senderUserId || void 0,
1279
- senderUnionId: senderUnionId || void 0
1280
- };
1281
- }
1282
- function extractMessageInfo(message) {
1283
- const chatId = message.chat_id ?? "";
1284
- const chatType = message.chat_type ?? "";
1285
- return {
1286
- chatId,
1287
- chatType,
1288
- isGroup: chatType === "group",
1289
- msgType: message.msg_type ?? message.message_type ?? "",
1290
- messageId: message.message_id ?? "",
1291
- rawContent: typeof message.content === "string" ? message.content : ""
1292
- };
1293
- }
1294
- function extractMentions(root, message) {
1295
- if (Array.isArray(root.mentions)) {
1296
- return root.mentions;
1297
- }
1298
- if (Array.isArray(message.mentions)) {
1299
- return message.mentions;
1300
- }
1301
- return [];
1302
- }
1303
- function buildInboundMetadata(params) {
1304
- return {
1305
- account_id: params.accountId,
1306
- accountId: params.accountId,
1307
- message_id: params.messageInfo.messageId,
1308
- chat_id: params.messageInfo.chatId,
1309
- chat_type: params.messageInfo.chatType,
1310
- msg_type: params.messageInfo.msgType,
1311
- is_group: params.messageInfo.isGroup,
1312
- peer_kind: params.messageInfo.isGroup ? "group" : "direct",
1313
- peer_id: params.messageInfo.isGroup ? params.messageInfo.chatId : params.senderInfo.senderId,
1314
- sender_open_id: params.senderInfo.senderOpenId,
1315
- sender_user_id: params.senderInfo.senderUserId,
1316
- sender_union_id: params.senderInfo.senderUnionId,
1317
- was_mentioned: params.mentionState.wasMentioned,
1318
- require_mention: params.mentionState.requireMention
1319
- };
1320
- }
1321
- function inferFeishuResourceMimeType(resourceType) {
1322
- if (resourceType === "image" || resourceType === "sticker") {
1323
- return "image/*";
1324
- }
1325
- if (resourceType === "audio") {
1326
- return "audio/*";
1327
- }
1328
- return void 0;
1329
- }
1330
- function buildFeishuCardElements(content) {
1331
- const elements = [];
1332
- let lastEnd = 0;
1333
- for (const match of content.matchAll(TABLE_RE)) {
1334
- const start = match.index ?? 0;
1335
- const tableText = match[1] ?? "";
1336
- const before = content.slice(lastEnd, start).trim();
1337
- if (before) {
1338
- elements.push({ tag: "markdown", content: before });
1339
- }
1340
- elements.push(parseMarkdownTable(tableText) ?? { tag: "markdown", content: tableText });
1341
- lastEnd = start + tableText.length;
1342
- }
1343
- const remaining = content.slice(lastEnd).trim();
1344
- if (remaining) {
1345
- elements.push({ tag: "markdown", content: remaining });
1346
- }
1347
- if (!elements.length) {
1348
- elements.push({ tag: "markdown", content });
1349
- }
1350
- return elements;
1351
- }
1352
- function parseMarkdownTable(tableText) {
1353
- const lines = tableText.trim().split("\n").map((line) => line.trim()).filter(Boolean);
1354
- if (lines.length < 3) {
1355
- return null;
1356
- }
1357
- const split = (line) => line.replace(/^\|+|\|+$/g, "").split("|").map((item) => item.trim());
1358
- const headers = split(lines[0]);
1359
- const rows = lines.slice(2).map(split);
1360
- return {
1361
- tag: "table",
1362
- page_size: rows.length + 1,
1363
- columns: headers.map((header, index) => ({
1364
- tag: "column",
1365
- name: `c${index}`,
1366
- display_name: header,
1367
- width: "auto"
1368
- })),
1369
- rows: rows.map((row) => {
1370
- const values = {};
1371
- headers.forEach((_, index) => {
1372
- values[`c${index}`] = row[index] ?? "";
1373
- });
1374
- return values;
1375
- })
1376
- };
1377
- }
1378
-
1379
- // src/channels/feishu.ts
1380
- import {
1381
- buildFeishuConvertContext,
1382
- convertFeishuMessageContent,
1383
- getDefaultFeishuAccountId,
1384
- getEnabledFeishuAccounts,
1385
- LarkClient
1386
- } from "@nextclaw/feishu-core";
1387
-
1388
- // src/channels/feishu-inbound-media.ts
1389
- import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
1390
- import { join as join2 } from "path";
1391
- var DEFAULT_FEISHU_MEDIA_MAX_MB = 20;
1392
- function sanitizeAttachmentName2(value) {
1393
- return value.replace(/[^a-zA-Z0-9._-]+/g, "_").replace(/^_+|_+$/g, "") || "attachment";
1394
- }
1395
- function inferAttachmentExtension(resourceType, mimeType) {
1396
- const normalizedMime = mimeType?.toLowerCase();
1397
- if (normalizedMime === "image/jpeg") {
1398
- return ".jpg";
1399
- }
1400
- if (normalizedMime === "image/png") {
1401
- return ".png";
1402
- }
1403
- if (normalizedMime === "image/webp") {
1404
- return ".webp";
1405
- }
1406
- if (normalizedMime === "image/gif") {
1407
- return ".gif";
1408
- }
1409
- if (normalizedMime === "audio/ogg") {
1410
- return ".ogg";
1411
- }
1412
- if (normalizedMime === "audio/mpeg") {
1413
- return ".mp3";
1414
- }
1415
- if (normalizedMime === "application/pdf") {
1416
- return ".pdf";
1417
- }
1418
- if (resourceType === "image") {
1419
- return ".jpg";
1420
- }
1421
- if (resourceType === "audio") {
1422
- return ".ogg";
1423
- }
1424
- if (resourceType === "sticker") {
1425
- return ".webp";
1426
- }
1427
- return ".bin";
1428
- }
1429
- function buildAttachmentFileName(params) {
1430
- const extension = inferAttachmentExtension(params.resource.type, params.mimeType);
1431
- const resourceId = sanitizeAttachmentName2(params.resource.fileKey).slice(0, 64);
1432
- const messageId = sanitizeAttachmentName2(params.messageId).slice(0, 48);
1433
- const preferredName = params.resource.fileName?.trim() ? sanitizeAttachmentName2(params.resource.fileName.trim()) : `${params.resource.type}${extension}`;
1434
- const baseName = preferredName.includes(".") ? preferredName : `${preferredName}${extension}`;
1435
- return `feishu_${messageId}_${resourceId}_${baseName}`;
1436
- }
1437
- function resolveMessageResourceType(resourceType) {
1438
- return resourceType === "image" ? "image" : "file";
1439
- }
1440
- var FeishuInboundMediaResolver = class {
1441
- maxBytes;
1442
- constructor(maxMb) {
1443
- this.maxBytes = Math.max(1, maxMb ?? DEFAULT_FEISHU_MEDIA_MAX_MB) * 1024 * 1024;
1444
- }
1445
- async resolve(params) {
1446
- const { client, messageId, resource } = params;
1447
- const mimeType = inferFeishuResourceMimeType(resource.type);
1448
- const baseAttachment = {
1449
- id: resource.fileKey,
1450
- name: resource.fileName,
1451
- source: "feishu",
1452
- status: "remote-only",
1453
- mimeType
1454
- };
1455
- if (!messageId?.trim()) {
1456
- return {
1457
- ...baseAttachment,
1458
- errorCode: "invalid_payload"
1459
- };
1460
- }
1461
- try {
1462
- const downloaded = await client.downloadMessageResource({
1463
- messageId,
1464
- fileKey: resource.fileKey,
1465
- type: resolveMessageResourceType(resource.type)
1466
- });
1467
- if (downloaded.buffer.length > this.maxBytes) {
1468
- return {
1469
- ...baseAttachment,
1470
- size: downloaded.buffer.length,
1471
- errorCode: "too_large"
1472
- };
1473
- }
1474
- const mediaDir = join2(getDataPath(), "media");
1475
- mkdirSync2(mediaDir, { recursive: true });
1476
- const fileName = buildAttachmentFileName({ messageId, resource, mimeType });
1477
- const filePath = join2(mediaDir, fileName);
1478
- writeFileSync2(filePath, downloaded.buffer);
1479
- return {
1480
- ...baseAttachment,
1481
- name: fileName,
1482
- path: filePath,
1483
- size: downloaded.buffer.length,
1484
- status: "ready"
1485
- };
1486
- } catch {
1487
- return {
1488
- ...baseAttachment,
1489
- errorCode: "download_failed"
1490
- };
1491
- }
1492
- }
1493
- };
1494
-
1495
- // src/channels/feishu.ts
1496
- function isRecord(value) {
1497
- return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1498
- }
1499
- var FeishuChannel = class extends BaseChannel {
1500
- name = "feishu";
1501
- clients = /* @__PURE__ */ new Map();
1502
- processedMessageIds = [];
1503
- processedSet = /* @__PURE__ */ new Set();
1504
- inboundMediaResolver;
1505
- constructor(config, bus) {
1506
- super(config, bus);
1507
- this.inboundMediaResolver = new FeishuInboundMediaResolver(this.config.mediaMaxMb);
1508
- }
1509
- async start() {
1510
- const accounts = getEnabledFeishuAccounts(this.config);
1511
- if (accounts.length === 0) {
1512
- throw new Error("Feishu appId/appSecret not configured");
1513
- }
1514
- this.running = true;
1515
- for (const account of accounts) {
1516
- const client = LarkClient.fromAccount(account);
1517
- const activeAccount = {
1518
- accountId: account.accountId,
1519
- client
1520
- };
1521
- const probe = await client.probe();
1522
- if (probe.ok) {
1523
- activeAccount.botOpenId = probe.botOpenId;
1524
- activeAccount.botName = probe.botName;
1525
- }
1526
- client.startWebsocket(async (data) => {
1527
- await this.handleIncoming(account.accountId, data);
1528
- });
1529
- this.clients.set(account.accountId, activeAccount);
1530
- }
1531
- }
1532
- async stop() {
1533
- this.running = false;
1534
- for (const account of this.clients.values()) {
1535
- account.client.closeWebsocket();
1536
- }
1537
- this.clients.clear();
1538
- }
1539
- async send(msg) {
1540
- const account = this.resolveOutboundAccount(msg.metadata);
1541
- if (!account) {
1542
- return;
1543
- }
1544
- const receiveIdType = msg.chatId.startsWith("oc_") ? "chat_id" : "open_id";
1545
- const elements = buildFeishuCardElements(msg.content ?? "");
1546
- const card = {
1547
- config: { wide_screen_mode: true },
1548
- elements
1549
- };
1550
- const content = JSON.stringify(card);
1551
- await account.client.sendInteractiveCard({
1552
- receiveId: msg.chatId,
1553
- receiveIdType,
1554
- content
1555
- });
1556
- }
1557
- async handleIncoming(accountId, data) {
1558
- const account = this.clients.get(accountId);
1559
- if (!account) {
1560
- return;
1561
- }
1562
- const root = isRecord(data.event) ? data.event : data;
1563
- const message = root.message ?? data.message ?? {};
1564
- const sender = root.sender ?? message.sender ?? data.sender ?? {};
1565
- const senderInfo = extractSenderInfo(sender);
1566
- if (senderInfo.senderType === "bot") {
1567
- return;
1568
- }
1569
- const messageInfo = extractMessageInfo(message);
1570
- if (!senderInfo.senderId || !messageInfo.chatId) {
1571
- return;
1572
- }
1573
- if (!this.isAllowedByPolicy({ senderId: senderInfo.senderId, chatId: messageInfo.chatId, isGroup: messageInfo.isGroup })) {
1574
- return;
1575
- }
1576
- if (messageInfo.messageId && this.isDuplicate(`${accountId}:${messageInfo.messageId}`)) {
1577
- return;
1578
- }
1579
- if (messageInfo.messageId) {
1580
- await this.addReaction(account, messageInfo.messageId, "THUMBSUP");
1581
- }
1582
- const mentions = extractMentions(root, message);
1583
- const mentionState = this.resolveMentionState({
1584
- account,
1585
- mentions,
1586
- chatId: messageInfo.chatId,
1587
- isGroup: messageInfo.isGroup,
1588
- rawContent: messageInfo.rawContent
1589
- });
1590
- if (mentionState.requireMention && !mentionState.wasMentioned) {
1591
- return;
1592
- }
1593
- const payload = await this.buildInboundPayload(account, messageInfo, mentions);
1594
- if (!payload) {
1595
- return;
1596
- }
1597
- await this.handleMessage({
1598
- senderId: senderInfo.senderId,
1599
- // Always route by Feishu chat_id so DM/group sessions are stable.
1600
- chatId: messageInfo.chatId,
1601
- content: payload.content,
1602
- attachments: payload.attachments,
1603
- metadata: buildInboundMetadata({
1604
- accountId,
1605
- messageInfo,
1606
- senderInfo,
1607
- mentionState
1608
- })
1609
- });
1610
- }
1611
- isDuplicate(messageId) {
1612
- if (this.processedSet.has(messageId)) {
1613
- return true;
1614
- }
1615
- this.processedSet.add(messageId);
1616
- this.processedMessageIds.push(messageId);
1617
- if (this.processedMessageIds.length > 1e3) {
1618
- const removed = this.processedMessageIds.splice(0, 500);
1619
- for (const id of removed) {
1620
- this.processedSet.delete(id);
1621
- }
1622
- }
1623
- return false;
1624
- }
1625
- async addReaction(account, messageId, emojiType) {
1626
- try {
1627
- await account.client.addReaction(messageId, emojiType);
1628
- } catch {
1629
- }
1630
- }
1631
- resolveOutboundAccount(metadata) {
1632
- const accountId = typeof metadata?.accountId === "string" ? metadata.accountId : typeof metadata?.account_id === "string" ? metadata.account_id : getDefaultFeishuAccountId(this.config);
1633
- return this.clients.get(accountId) ?? this.clients.get(getDefaultFeishuAccountId(this.config)) ?? null;
1634
- }
1635
- isAllowedByPolicy(params) {
1636
- if (!params.isGroup) {
1637
- if (this.config.dmPolicy === "disabled") {
1638
- return false;
1639
- }
1640
- if (this.config.dmPolicy === "allowlist" || this.config.dmPolicy === "pairing") {
1641
- return this.isAllowed(params.senderId);
1642
- }
1643
- const allowFrom = this.config.allowFrom ?? [];
1644
- return allowFrom.length === 0 || allowFrom.includes("*") || this.isAllowed(params.senderId);
1645
- }
1646
- if (this.config.groupPolicy === "disabled") {
1647
- return false;
1648
- }
1649
- if (this.config.groupPolicy === "allowlist") {
1650
- const allowFrom = this.config.groupAllowFrom ?? [];
1651
- return allowFrom.includes("*") || allowFrom.includes(params.chatId);
1652
- }
1653
- return true;
1654
- }
1655
- resolveMentionState(params) {
1656
- if (!params.isGroup) {
1657
- return { wasMentioned: false, requireMention: false };
1658
- }
1659
- const groupRule = this.config.groups?.[params.chatId] ?? this.config.groups?.["*"];
1660
- const requireMention = groupRule?.requireMention ?? this.config.requireMention ?? false;
1661
- if (!requireMention) {
1662
- return { wasMentioned: false, requireMention: false };
1663
- }
1664
- const patterns = [...this.config.mentionPatterns ?? [], ...groupRule?.mentionPatterns ?? []].map((pattern) => pattern.trim()).filter(Boolean);
1665
- const rawText = params.rawContent.toLowerCase();
1666
- const mentionedByPattern = patterns.some((pattern) => {
1667
- try {
1668
- return new RegExp(pattern, "i").test(rawText);
1669
- } catch {
1670
- return rawText.includes(pattern.toLowerCase());
1671
- }
1672
- });
1673
- const mentionedByIds = params.mentions.some((entry) => {
1674
- if (!entry || typeof entry !== "object") {
1675
- return false;
1676
- }
1677
- const mention = entry;
1678
- const openId = (typeof mention.open_id === "string" ? mention.open_id : "") || (mention.id && typeof mention.id === "object" && "open_id" in mention.id ? mention.id.open_id ?? "" : typeof mention.id === "string" ? mention.id : "");
1679
- const name = typeof mention.name === "string" ? mention.name : "";
1680
- return openId === params.account.botOpenId || (params.account.botName ? name === params.account.botName : false);
1681
- });
1682
- return {
1683
- wasMentioned: mentionedByPattern || mentionedByIds,
1684
- requireMention
1685
- };
1686
- }
1687
- async convertResource(params) {
1688
- return this.inboundMediaResolver.resolve({
1689
- client: params.account.client,
1690
- messageId: params.messageId,
1691
- resource: params.resource
1692
- });
1693
- }
1694
- async buildInboundPayload(account, messageInfo, mentions) {
1695
- const converted = convertFeishuMessageContent(
1696
- messageInfo.rawContent,
1697
- messageInfo.msgType,
1698
- buildFeishuConvertContext({
1699
- mentions,
1700
- stripBotMentions: true,
1701
- botOpenId: account.botOpenId,
1702
- botName: account.botName
1703
- })
1704
- );
1705
- const content = converted.content.trim() || `[${messageInfo.msgType || "message"}]`;
1706
- const attachments = await Promise.all(
1707
- converted.resources.map(
1708
- (resource) => this.convertResource({
1709
- account,
1710
- messageId: messageInfo.messageId,
1711
- resource
1712
- })
1713
- )
1714
- );
1715
- if (!content && attachments.length === 0) {
1716
- return null;
1717
- }
1718
- return {
1719
- content,
1720
- attachments
1721
- };
1722
- }
1723
- };
1724
-
1725
1267
  // src/channels/mochat.ts
1726
1268
  import { io } from "socket.io-client";
1727
1269
  import { fetch as fetch3 } from "undici";
1728
- import { join as join3 } from "path";
1729
- import { mkdirSync as mkdirSync3, existsSync, readFileSync, writeFileSync as writeFileSync3 } from "fs";
1270
+ import { join as join2 } from "path";
1271
+ import { mkdirSync as mkdirSync2, existsSync, readFileSync, writeFileSync as writeFileSync2 } from "fs";
1730
1272
  var MAX_SEEN_MESSAGE_IDS = 2e3;
1731
1273
  var CURSOR_SAVE_DEBOUNCE_MS = 500;
1732
1274
  var AsyncLock = class {
@@ -1745,8 +1287,8 @@ var MochatChannel = class extends BaseChannel {
1745
1287
  socket = null;
1746
1288
  wsConnected = false;
1747
1289
  wsReady = false;
1748
- stateDir = join3(getDataPath(), "mochat");
1749
- cursorPath = join3(this.stateDir, "session_cursors.json");
1290
+ stateDir = join2(getDataPath(), "mochat");
1291
+ cursorPath = join2(this.stateDir, "session_cursors.json");
1750
1292
  sessionCursor = {};
1751
1293
  cursorSaveTimer = null;
1752
1294
  sessionSet = /* @__PURE__ */ new Set();
@@ -1772,7 +1314,7 @@ var MochatChannel = class extends BaseChannel {
1772
1314
  if (!this.config.clawToken) {
1773
1315
  throw new Error("Mochat clawToken not configured");
1774
1316
  }
1775
- mkdirSync3(this.stateDir, { recursive: true });
1317
+ mkdirSync2(this.stateDir, { recursive: true });
1776
1318
  await this.loadSessionCursors();
1777
1319
  this.seedTargetsFromConfig();
1778
1320
  await this.refreshTargets(false);
@@ -2455,13 +1997,13 @@ var MochatChannel = class extends BaseChannel {
2455
1997
  }
2456
1998
  async saveSessionCursors() {
2457
1999
  try {
2458
- mkdirSync3(this.stateDir, { recursive: true });
2000
+ mkdirSync2(this.stateDir, { recursive: true });
2459
2001
  const payload = {
2460
2002
  schemaVersion: 1,
2461
2003
  updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2462
2004
  cursors: this.sessionCursor
2463
2005
  };
2464
- writeFileSync3(this.cursorPath, JSON.stringify(payload, null, 2) + "\n");
2006
+ writeFileSync2(this.cursorPath, JSON.stringify(payload, null, 2) + "\n");
2465
2007
  } catch {
2466
2008
  return;
2467
2009
  }
@@ -3254,8 +2796,8 @@ var GroqTranscriptionProvider = class {
3254
2796
  };
3255
2797
 
3256
2798
  // src/channels/telegram.ts
3257
- import { join as join4 } from "path";
3258
- import { mkdirSync as mkdirSync4 } from "fs";
2799
+ import { join as join3 } from "path";
2800
+ import { mkdirSync as mkdirSync3 } from "fs";
3259
2801
  import {
3260
2802
  isAssistantStreamResetControlMessage,
3261
2803
  isTypingStopControlMessage as isTypingStopControlMessage2,
@@ -3678,8 +3220,8 @@ Just send me a text message to chat!`;
3678
3220
  }
3679
3221
  const { fileId, mediaType, mimeType } = resolveMedia(message);
3680
3222
  if (fileId && mediaType) {
3681
- const mediaDir = join4(getDataPath(), "media");
3682
- mkdirSync4(mediaDir, { recursive: true });
3223
+ const mediaDir = join3(getDataPath(), "media");
3224
+ mkdirSync3(mediaDir, { recursive: true });
3683
3225
  const extension = getExtension(mediaType, mimeType);
3684
3226
  const downloaded = await this.bot.downloadFile(fileId, mediaDir);
3685
3227
  const finalPath = extension && !downloaded.endsWith(extension) ? `${downloaded}${extension}` : downloaded;
@@ -4387,11 +3929,6 @@ var BUILTIN_CHANNEL_RUNTIMES = {
4387
3929
  isEnabled: (config) => config.channels.discord.enabled,
4388
3930
  createChannel: (context) => new DiscordChannel(context.config.channels.discord, context.bus, context.sessionManager, context.config)
4389
3931
  },
4390
- feishu: {
4391
- id: "feishu",
4392
- isEnabled: (config) => config.channels.feishu.enabled,
4393
- createChannel: (context) => new FeishuChannel(context.config.channels.feishu, context.bus)
4394
- },
4395
3932
  mochat: {
4396
3933
  id: "mochat",
4397
3934
  isEnabled: (config) => config.channels.mochat.enabled,
@@ -4441,7 +3978,6 @@ export {
4441
3978
  DingTalkChannel,
4442
3979
  DiscordChannel,
4443
3980
  EmailChannel,
4444
- FeishuChannel,
4445
3981
  MochatChannel,
4446
3982
  QQChannel,
4447
3983
  SlackChannel,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/channel-runtime",
3
- "version": "0.4.1",
3
+ "version": "0.4.3",
4
4
  "private": false,
5
5
  "description": "Runtime implementations for NextClaw builtin channel plugins.",
6
6
  "type": "module",
@@ -28,8 +28,7 @@
28
28
  "undici": "^6.21.0",
29
29
  "ws": "^8.18.0",
30
30
  "socket.io-msgpack-parser": "^3.0.2",
31
- "@nextclaw/core": "0.11.1",
32
- "@nextclaw/feishu-core": "0.2.0"
31
+ "@nextclaw/core": "0.11.2"
33
32
  },
34
33
  "devDependencies": {
35
34
  "@types/mailparser": "^3.4.6",