chatccc 0.2.47 → 0.2.48

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.
@@ -1,148 +1,153 @@
1
- /**
2
- * sim-platform.ts — SimulatedPlatform: 零飞书依赖的本地模拟实现
3
- *
4
- * 所有飞书 API 调用都由本地 SimStore 替代:
5
- * - 消息通过 SimStore 写入内存 + JSONL + 事件推送
6
- * - 群聊/账户信息由 SimStore 统一管理
7
- * - createGroupChat 生成 "sim_<uuid>" 格式的 chat_id
8
- *
9
- * 纯函数(extractSessionInfo / formatDelayNotice / reportPermissionResults)
10
- * 直接从 feishu-api.ts re-export,不重新实现。
11
- */
12
-
13
- import { join } from "node:path";
14
-
15
- import {
16
- extractSessionInfo as realExtractSessionInfo,
17
- extractSessionId as realExtractSessionId,
18
- formatDelayNotice as realFormatDelayNotice,
19
- reportPermissionResults as realReportPermissionResults,
20
- } from "./feishu-api.ts";
21
- import type { FeishuPlatform } from "./feishu-platform.ts";
22
- import { simStore } from "./sim-store.ts";
23
-
24
- // ---------------------------------------------------------------------------
25
- // 持久化路径
26
- // ---------------------------------------------------------------------------
27
-
28
- import { homedir } from "node:os";
29
- const SIM_DIR = join(homedir(), ".chatccc", "sim");
30
-
31
- // ---------------------------------------------------------------------------
32
- // 工具函数
33
- // ---------------------------------------------------------------------------
34
-
35
- function ts(): string {
36
- return new Date().toISOString().replace("T", " ").slice(0, 19);
37
- }
38
-
39
- // ---------------------------------------------------------------------------
40
- // SimulatedPlatform
41
- // ---------------------------------------------------------------------------
42
-
43
- export const SimulatedPlatform: FeishuPlatform = {
44
- // ---- 认证 ----
45
- async getTenantAccessToken() {
46
- return "sim_token";
47
- },
48
-
49
- // ---- 消息发送:委托给 simStore ----
50
- async sendTextReply(_token, chatId, text) {
51
- console.log(`[${ts()}] [SIM:SEND] text → ${chatId}: ${text.slice(0, 80)}`);
52
- simStore.sendReply(chatId, "text", text);
53
- return true;
54
- },
55
-
56
- async sendCardReply(_token, chatId, title, content, _template) {
57
- console.log(`[${ts()}] [SIM:SEND] card → ${chatId}: [${title}]`);
58
- const text = `**[${title}]**\n${content}`;
59
- simStore.sendReply(chatId, "card", text);
60
- return true;
61
- },
62
-
63
- async sendImageReply(_token, chatId, imagePath) {
64
- console.log(`[${ts()}] [SIM:SEND] image → ${chatId}: ${imagePath}`);
65
- simStore.sendReply(chatId, "image", imagePath);
66
- return true;
67
- },
68
-
69
- async sendFileReply(_token, chatId, filePath) {
70
- console.log(`[${ts()}] [SIM:SEND] file → ${chatId}: ${filePath}`);
71
- simStore.sendReply(chatId, "file", filePath);
72
- return true;
73
- },
74
-
75
- async sendRawCard(_token, chatId, cardJson) {
76
- console.log(`[${ts()}] [SIM:SEND] raw_card → ${chatId}: ${cardJson.slice(0, 80)}...`);
77
- simStore.sendReply(chatId, "raw_card", cardJson.slice(0, 500));
78
- return true;
79
- },
80
-
81
- // ---- 消息管理 ----
82
- async addReaction(_token, _messageId, _emojiType) {
83
- // 模拟模式不需要表情回应
84
- },
85
-
86
- async recallMessage(_token, _messageId) {
87
- return true;
88
- },
89
-
90
- async updateCardMessage(_token, _messageId, content) {
91
- // 模拟模式:记录卡片更新到控制台(无 chatId,不写入消息历史)
92
- console.log(`[${ts()}] [SIM:CARD] update: msgId=${_messageId} preview=${content.slice(0, 80)}`);
93
- return true;
94
- },
95
-
96
- // ---- 群聊管理 ----
97
- async createGroupChat(_token, name, userIds) {
98
- const chat = simStore.createGroupChat(name, userIds);
99
- console.log(`[${ts()}] [SIM:CHAT] created: ${chat.id} name="${name}" members=${userIds.length}`);
100
- return chat.id;
101
- },
102
-
103
- async updateChatInfo(_token, chatId, name, description) {
104
- simStore.updateChatInfo(chatId, name, description);
105
- console.log(`[${ts()}] [SIM:CHAT] updated: ${chatId} name="${name}"`);
106
- },
107
-
108
- async getChatInfo(_token, chatId) {
109
- const chat = simStore.getChat(chatId);
110
- if (!chat) throw new Error(`[99999] chat not found: ${chatId}`);
111
- return { name: chat.name, description: chat.description };
112
- },
113
-
114
- // ---- 头像 ----
115
- async setChatAvatar(_token, _chatId, _tool, _status) {
116
- // 模拟模式不需要头像
117
- },
118
-
119
- // ---- 图片下载 ----
120
- async getOrDownloadImage(_token, _messageId, fileKey) {
121
- return join(SIM_DIR, "images", fileKey);
122
- },
123
-
124
- // ---- 权限验证 ----
125
- async verifyAllPermissions(_token) {
126
- return [
127
- { scope: "im:chat", description: "模拟", ok: true, detail: "模拟模式跳过" },
128
- { scope: "im:message:send_as_bot", description: "模拟", ok: true, detail: "模拟模式跳过" },
129
- { scope: "im:message:reaction", description: "模拟", ok: true, detail: "模拟模式跳过" },
130
- { scope: "im:message", description: "模拟", ok: true, detail: "模拟模式跳过" },
131
- { scope: "cardkit:card", description: "模拟", ok: true, detail: "模拟模式跳过" },
132
- ];
133
- },
134
-
135
- // ---- 纯函数:直接从真实实现 re-export ----
136
- extractSessionInfo: realExtractSessionInfo,
137
- extractSessionId: realExtractSessionId,
138
- formatDelayNotice: realFormatDelayNotice,
139
- reportPermissionResults: realReportPermissionResults,
140
-
141
- // ---- 其他 ----
142
- async sendRestartCard(_token) {
143
- // 模拟模式不需要重启通知
144
- },
145
- };
146
-
147
- /** 模拟模式下的默认 chat_id(重新导出以保持向后兼容) */
1
+ /**
2
+ * sim-platform.ts — SimulatedPlatform: 零飞书依赖的本地模拟实现
3
+ *
4
+ * 所有飞书 API 调用都由本地 SimStore 替代:
5
+ * - 消息通过 SimStore 写入内存 + JSONL + 事件推送
6
+ * - 群聊/账户信息由 SimStore 统一管理
7
+ * - createGroupChat 生成 "sim_<uuid>" 格式的 chat_id
8
+ *
9
+ * 纯函数(extractSessionInfo / formatDelayNotice / reportPermissionResults)
10
+ * 直接从 feishu-api.ts re-export,不重新实现。
11
+ */
12
+
13
+ import { join } from "node:path";
14
+
15
+ import {
16
+ extractSessionInfo as realExtractSessionInfo,
17
+ extractSessionId as realExtractSessionId,
18
+ formatDelayNotice as realFormatDelayNotice,
19
+ reportPermissionResults as realReportPermissionResults,
20
+ } from "./feishu-api.ts";
21
+ import type { FeishuPlatform } from "./feishu-platform.ts";
22
+ import { simStore } from "./sim-store.ts";
23
+
24
+ // ---------------------------------------------------------------------------
25
+ // 持久化路径
26
+ // ---------------------------------------------------------------------------
27
+
28
+ import { homedir } from "node:os";
29
+ const SIM_DIR = join(homedir(), ".chatccc", "sim");
30
+
31
+ // ---------------------------------------------------------------------------
32
+ // 工具函数
33
+ // ---------------------------------------------------------------------------
34
+
35
+ function ts(): string {
36
+ return new Date().toISOString().replace("T", " ").slice(0, 19);
37
+ }
38
+
39
+ // ---------------------------------------------------------------------------
40
+ // SimulatedPlatform
41
+ // ---------------------------------------------------------------------------
42
+
43
+ export const SimulatedPlatform: FeishuPlatform = {
44
+ // ---- 认证 ----
45
+ async getTenantAccessToken() {
46
+ return "sim_token";
47
+ },
48
+
49
+ // ---- 消息发送:委托给 simStore ----
50
+ async sendTextReply(_token, chatId, text) {
51
+ console.log(`[${ts()}] [SIM:SEND] text → ${chatId}: ${text.slice(0, 80)}`);
52
+ simStore.sendReply(chatId, "text", text);
53
+ return true;
54
+ },
55
+
56
+ async sendCardReply(_token, chatId, title, content, _template) {
57
+ console.log(`[${ts()}] [SIM:SEND] card → ${chatId}: [${title}]`);
58
+ const text = `**[${title}]**\n${content}`;
59
+ simStore.sendReply(chatId, "card", text);
60
+ return true;
61
+ },
62
+
63
+ async sendImageReply(_token, chatId, imagePath) {
64
+ console.log(`[${ts()}] [SIM:SEND] image → ${chatId}: ${imagePath}`);
65
+ simStore.sendReply(chatId, "image", imagePath);
66
+ return true;
67
+ },
68
+
69
+ async sendFileReply(_token, chatId, filePath) {
70
+ console.log(`[${ts()}] [SIM:SEND] file → ${chatId}: ${filePath}`);
71
+ simStore.sendReply(chatId, "file", filePath);
72
+ return true;
73
+ },
74
+
75
+ async sendRawCard(_token, chatId, cardJson) {
76
+ console.log(`[${ts()}] [SIM:SEND] raw_card → ${chatId}: ${cardJson.slice(0, 80)}...`);
77
+ simStore.sendReply(chatId, "raw_card", cardJson.slice(0, 500));
78
+ return true;
79
+ },
80
+
81
+ // ---- 消息管理 ----
82
+ async addReaction(_token, _messageId, _emojiType) {
83
+ // 模拟模式不需要表情回应
84
+ },
85
+
86
+ async recallMessage(_token, _messageId) {
87
+ return true;
88
+ },
89
+
90
+ async updateCardMessage(_token, _messageId, content) {
91
+ // 模拟模式:记录卡片更新到控制台(无 chatId,不写入消息历史)
92
+ console.log(`[${ts()}] [SIM:CARD] update: msgId=${_messageId} preview=${content.slice(0, 80)}`);
93
+ return true;
94
+ },
95
+
96
+ // ---- 群聊管理 ----
97
+ async createGroupChat(_token, name, userIds) {
98
+ const chat = simStore.createGroupChat(name, userIds);
99
+ console.log(`[${ts()}] [SIM:CHAT] created: ${chat.id} name="${name}" members=${userIds.length}`);
100
+ return chat.id;
101
+ },
102
+
103
+ async updateChatInfo(_token, chatId, name, description) {
104
+ simStore.updateChatInfo(chatId, name, description);
105
+ console.log(`[${ts()}] [SIM:CHAT] updated: ${chatId} name="${name}"`);
106
+ },
107
+
108
+ async getChatInfo(_token, chatId) {
109
+ const chat = simStore.getChat(chatId);
110
+ if (!chat) throw new Error(`[99999] chat not found: ${chatId}`);
111
+ return { name: chat.name, description: chat.description };
112
+ },
113
+
114
+ async disbandChat(_token, chatId) {
115
+ simStore.disbandChat(chatId);
116
+ console.log(`[${ts()}] [SIM:CHAT] disbanded: ${chatId}`);
117
+ },
118
+
119
+ // ---- 头像 ----
120
+ async setChatAvatar(_token, _chatId, _tool, _status) {
121
+ // 模拟模式不需要头像
122
+ },
123
+
124
+ // ---- 图片下载 ----
125
+ async getOrDownloadImage(_token, _messageId, fileKey) {
126
+ return join(SIM_DIR, "images", fileKey);
127
+ },
128
+
129
+ // ---- 权限验证 ----
130
+ async verifyAllPermissions(_token) {
131
+ return [
132
+ { scope: "im:chat", description: "模拟", ok: true, detail: "模拟模式跳过" },
133
+ { scope: "im:message:send_as_bot", description: "模拟", ok: true, detail: "模拟模式跳过" },
134
+ { scope: "im:message:reaction", description: "模拟", ok: true, detail: "模拟模式跳过" },
135
+ { scope: "im:message", description: "模拟", ok: true, detail: "模拟模式跳过" },
136
+ { scope: "cardkit:card", description: "模拟", ok: true, detail: "模拟模式跳过" },
137
+ ];
138
+ },
139
+
140
+ // ---- 纯函数:直接从真实实现 re-export ----
141
+ extractSessionInfo: realExtractSessionInfo,
142
+ extractSessionId: realExtractSessionId,
143
+ formatDelayNotice: realFormatDelayNotice,
144
+ reportPermissionResults: realReportPermissionResults,
145
+
146
+ // ---- 其他 ----
147
+ async sendRestartCard(_token) {
148
+ // 模拟模式不需要重启通知
149
+ },
150
+ };
151
+
152
+ /** 模拟模式下的默认 chat_id(重新导出以保持向后兼容) */
148
153
  export { SIM_DEFAULT_CHAT_ID } from "./sim-store.ts";