opencode-channels 0.1.0

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.
Files changed (121) hide show
  1. package/README.md +187 -0
  2. package/bin/cli.js +24 -0
  3. package/bin/cli.ts +62 -0
  4. package/dist/bot/auto-binding.d.ts +6 -0
  5. package/dist/bot/auto-binding.d.ts.map +1 -0
  6. package/dist/bot/auto-binding.js +81 -0
  7. package/dist/bot/auto-binding.js.map +1 -0
  8. package/dist/bot/commands/agents.d.ts +9 -0
  9. package/dist/bot/commands/agents.d.ts.map +1 -0
  10. package/dist/bot/commands/agents.js +53 -0
  11. package/dist/bot/commands/agents.js.map +1 -0
  12. package/dist/bot/commands/base.d.ts +4 -0
  13. package/dist/bot/commands/base.d.ts.map +1 -0
  14. package/dist/bot/commands/base.js +241 -0
  15. package/dist/bot/commands/base.js.map +1 -0
  16. package/dist/bot/commands/dynamic.d.ts +8 -0
  17. package/dist/bot/commands/dynamic.d.ts.map +1 -0
  18. package/dist/bot/commands/dynamic.js +82 -0
  19. package/dist/bot/commands/dynamic.js.map +1 -0
  20. package/dist/bot/commands/index.d.ts +15 -0
  21. package/dist/bot/commands/index.d.ts.map +1 -0
  22. package/dist/bot/commands/index.js +25 -0
  23. package/dist/bot/commands/index.js.map +1 -0
  24. package/dist/bot/commands/models.d.ts +7 -0
  25. package/dist/bot/commands/models.d.ts.map +1 -0
  26. package/dist/bot/commands/models.js +60 -0
  27. package/dist/bot/commands/models.js.map +1 -0
  28. package/dist/bot/commands/sdk-commands.d.ts +5 -0
  29. package/dist/bot/commands/sdk-commands.d.ts.map +1 -0
  30. package/dist/bot/commands/sdk-commands.js +135 -0
  31. package/dist/bot/commands/sdk-commands.js.map +1 -0
  32. package/dist/bot/handlers/callback.d.ts +3 -0
  33. package/dist/bot/handlers/callback.d.ts.map +1 -0
  34. package/dist/bot/handlers/callback.js +52 -0
  35. package/dist/bot/handlers/callback.js.map +1 -0
  36. package/dist/bot/handlers/file.d.ts +3 -0
  37. package/dist/bot/handlers/file.d.ts.map +1 -0
  38. package/dist/bot/handlers/file.js +121 -0
  39. package/dist/bot/handlers/file.js.map +1 -0
  40. package/dist/bot/handlers/group.d.ts +3 -0
  41. package/dist/bot/handlers/group.d.ts.map +1 -0
  42. package/dist/bot/handlers/group.js +41 -0
  43. package/dist/bot/handlers/group.js.map +1 -0
  44. package/dist/bot/handlers/index.d.ts +4 -0
  45. package/dist/bot/handlers/index.d.ts.map +1 -0
  46. package/dist/bot/handlers/index.js +13 -0
  47. package/dist/bot/handlers/index.js.map +1 -0
  48. package/dist/bot/handlers/message.d.ts +15 -0
  49. package/dist/bot/handlers/message.d.ts.map +1 -0
  50. package/dist/bot/handlers/message.js +183 -0
  51. package/dist/bot/handlers/message.js.map +1 -0
  52. package/dist/bot/handlers/topic.d.ts +3 -0
  53. package/dist/bot/handlers/topic.d.ts.map +1 -0
  54. package/dist/bot/handlers/topic.js +43 -0
  55. package/dist/bot/handlers/topic.js.map +1 -0
  56. package/dist/bot/index.d.ts +5 -0
  57. package/dist/bot/index.d.ts.map +1 -0
  58. package/dist/bot/index.js +66 -0
  59. package/dist/bot/index.js.map +1 -0
  60. package/dist/cli/daemon.d.ts +6 -0
  61. package/dist/cli/daemon.d.ts.map +1 -0
  62. package/dist/cli/daemon.js +255 -0
  63. package/dist/cli/daemon.js.map +1 -0
  64. package/dist/cli/init.d.ts +19 -0
  65. package/dist/cli/init.d.ts.map +1 -0
  66. package/dist/cli/init.js +235 -0
  67. package/dist/cli/init.js.map +1 -0
  68. package/dist/cli/logs.d.ts +6 -0
  69. package/dist/cli/logs.d.ts.map +1 -0
  70. package/dist/cli/logs.js +42 -0
  71. package/dist/cli/logs.js.map +1 -0
  72. package/dist/cli/start.d.ts +4 -0
  73. package/dist/cli/start.d.ts.map +1 -0
  74. package/dist/cli/start.js +254 -0
  75. package/dist/cli/start.js.map +1 -0
  76. package/dist/plugin/index.d.ts +4 -0
  77. package/dist/plugin/index.d.ts.map +1 -0
  78. package/dist/plugin/index.js +73 -0
  79. package/dist/plugin/index.js.map +1 -0
  80. package/dist/server/api.d.ts +3 -0
  81. package/dist/server/api.d.ts.map +1 -0
  82. package/dist/server/api.js +30 -0
  83. package/dist/server/api.js.map +1 -0
  84. package/dist/server/events.d.ts +18 -0
  85. package/dist/server/events.d.ts.map +1 -0
  86. package/dist/server/events.js +131 -0
  87. package/dist/server/events.js.map +1 -0
  88. package/dist/server/filters.d.ts +19 -0
  89. package/dist/server/filters.d.ts.map +1 -0
  90. package/dist/server/filters.js +149 -0
  91. package/dist/server/filters.js.map +1 -0
  92. package/dist/server/index.d.ts +4 -0
  93. package/dist/server/index.d.ts.map +1 -0
  94. package/dist/server/index.js +10 -0
  95. package/dist/server/index.js.map +1 -0
  96. package/dist/server/sdk.d.ts +36 -0
  97. package/dist/server/sdk.d.ts.map +1 -0
  98. package/dist/server/sdk.js +485 -0
  99. package/dist/server/sdk.js.map +1 -0
  100. package/dist/shared/config.d.ts +34 -0
  101. package/dist/shared/config.d.ts.map +1 -0
  102. package/dist/shared/config.js +163 -0
  103. package/dist/shared/config.js.map +1 -0
  104. package/dist/shared/logger.d.ts +5 -0
  105. package/dist/shared/logger.d.ts.map +1 -0
  106. package/dist/shared/logger.js +114 -0
  107. package/dist/shared/logger.js.map +1 -0
  108. package/dist/shared/mapping.d.ts +90 -0
  109. package/dist/shared/mapping.d.ts.map +1 -0
  110. package/dist/shared/mapping.js +234 -0
  111. package/dist/shared/mapping.js.map +1 -0
  112. package/dist/shared/message-queue.d.ts +64 -0
  113. package/dist/shared/message-queue.d.ts.map +1 -0
  114. package/dist/shared/message-queue.js +138 -0
  115. package/dist/shared/message-queue.js.map +1 -0
  116. package/dist/shared/types.d.ts +284 -0
  117. package/dist/shared/types.d.ts.map +1 -0
  118. package/dist/shared/types.js +7 -0
  119. package/dist/shared/types.js.map +1 -0
  120. package/index.js +1 -0
  121. package/package.json +71 -0
@@ -0,0 +1,163 @@
1
+ /**
2
+ * OpenCode Channels 配置管理
3
+ *
4
+ * 负责配置文件的读取、保存和验证
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import * as os from 'os';
9
+ /**
10
+ * 配置文件路径
11
+ */
12
+ const CONFIG_DIR = path.join(os.homedir(), '.config', 'opencode');
13
+ const CONFIG_FILE = path.join(CONFIG_DIR, 'channels.json');
14
+ /**
15
+ * 确保配置目录存在
16
+ */
17
+ export function ensureConfigDir() {
18
+ try {
19
+ if (!fs.existsSync(CONFIG_DIR)) {
20
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
21
+ }
22
+ }
23
+ catch (error) {
24
+ throw new Error(`无法创建配置目录 ${CONFIG_DIR}: ${error instanceof Error ? error.message : String(error)}`);
25
+ }
26
+ }
27
+ /**
28
+ * 获取默认配置
29
+ */
30
+ export function getDefaultConfig() {
31
+ return {
32
+ workspace: path.join(os.homedir(), '.workspace'),
33
+ server: {
34
+ port: 3737,
35
+ host: 'localhost',
36
+ },
37
+ channels: {
38
+ telegram: {
39
+ enabled: true,
40
+ token: '',
41
+ },
42
+ },
43
+ notifications: {
44
+ onPermission: true,
45
+ onComplete: true,
46
+ onError: true,
47
+ onIdle: false,
48
+ },
49
+ };
50
+ }
51
+ /**
52
+ * 验证配置对象
53
+ * @param config 待验证的配置对象
54
+ * @returns 是否有效
55
+ * @throws 如果配置无效,抛出详细错误
56
+ */
57
+ export function validateConfig(config) {
58
+ if (!config || typeof config !== 'object') {
59
+ throw new Error('配置必须是一个对象');
60
+ }
61
+ const cfg = config;
62
+ // 验证 workspace
63
+ if (typeof cfg.workspace !== 'string') {
64
+ throw new Error('配置字段 workspace 必须是字符串');
65
+ }
66
+ // 验证 server
67
+ if (!cfg.server || typeof cfg.server !== 'object') {
68
+ throw new Error('配置字段 server 必须是对象');
69
+ }
70
+ const server = cfg.server;
71
+ if (typeof server.port !== 'number') {
72
+ throw new Error('配置字段 server.port 必须是数字');
73
+ }
74
+ if (typeof server.host !== 'string') {
75
+ throw new Error('配置字段 server.host 必须是字符串');
76
+ }
77
+ // 验证 channels
78
+ if (!cfg.channels || typeof cfg.channels !== 'object') {
79
+ throw new Error('配置字段 channels 必须是对象');
80
+ }
81
+ const channels = cfg.channels;
82
+ if (!channels.telegram || typeof channels.telegram !== 'object') {
83
+ throw new Error('配置字段 channels.telegram 必须是对象');
84
+ }
85
+ const telegram = channels.telegram;
86
+ if (typeof telegram.enabled !== 'boolean') {
87
+ throw new Error('配置字段 channels.telegram.enabled 必须是布尔值');
88
+ }
89
+ if (typeof telegram.token !== 'string') {
90
+ throw new Error('配置字段 channels.telegram.token 必须是字符串');
91
+ }
92
+ // 验证 notifications
93
+ if (!cfg.notifications || typeof cfg.notifications !== 'object') {
94
+ throw new Error('配置字段 notifications 必须是对象');
95
+ }
96
+ const notifications = cfg.notifications;
97
+ if (typeof notifications.onPermission !== 'boolean') {
98
+ throw new Error('配置字段 notifications.onPermission 必须是布尔值');
99
+ }
100
+ if (typeof notifications.onComplete !== 'boolean') {
101
+ throw new Error('配置字段 notifications.onComplete 必须是布尔值');
102
+ }
103
+ if (typeof notifications.onError !== 'boolean') {
104
+ throw new Error('配置字段 notifications.onError 必须是布尔值');
105
+ }
106
+ if (typeof notifications.onIdle !== 'boolean') {
107
+ throw new Error('配置字段 notifications.onIdle 必须是布尔值');
108
+ }
109
+ return true;
110
+ }
111
+ /**
112
+ * 加载配置文件
113
+ * @returns 配置对象,如果文件不存在返回 null
114
+ * @throws 如果文件格式错误或验证失败
115
+ */
116
+ export function loadConfig() {
117
+ try {
118
+ if (!fs.existsSync(CONFIG_FILE)) {
119
+ return null;
120
+ }
121
+ const content = fs.readFileSync(CONFIG_FILE, 'utf-8');
122
+ let config;
123
+ try {
124
+ config = JSON.parse(content);
125
+ }
126
+ catch (error) {
127
+ throw new Error(`配置文件 JSON 格式错误: ${error instanceof Error ? error.message : String(error)}`);
128
+ }
129
+ // 验证配置
130
+ validateConfig(config);
131
+ return config;
132
+ }
133
+ catch (error) {
134
+ if (error instanceof Error && error.message.includes('配置')) {
135
+ throw error;
136
+ }
137
+ throw new Error(`读取配置文件失败: ${error instanceof Error ? error.message : String(error)}`);
138
+ }
139
+ }
140
+ /**
141
+ * 保存配置文件
142
+ * @param config 配置对象
143
+ * @throws 如果保存失败
144
+ */
145
+ export function saveConfig(config) {
146
+ try {
147
+ // 验证配置
148
+ validateConfig(config);
149
+ // 确保配置目录存在
150
+ ensureConfigDir();
151
+ // 序列化配置
152
+ const content = JSON.stringify(config, null, 2);
153
+ // 写入文件
154
+ fs.writeFileSync(CONFIG_FILE, content, { encoding: 'utf-8', mode: 0o600 });
155
+ }
156
+ catch (error) {
157
+ if (error instanceof Error && error.message.includes('配置')) {
158
+ throw error;
159
+ }
160
+ throw new Error(`保存配置文件失败: ${error instanceof Error ? error.message : String(error)}`);
161
+ }
162
+ }
163
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/shared/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function setupLogger(): void;
2
+ export declare function getLogFilePath(): string;
3
+ export declare function readLogs(lines?: number): string[];
4
+ export declare function clearLogs(): void;
5
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":"AAiFA,wBAAgB,WAAW,IAAI,IAAI,CAkClC;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,QAAQ,CAAC,KAAK,GAAE,MAAY,GAAG,MAAM,EAAE,CAStD;AAED,wBAAgB,SAAS,IAAI,IAAI,CAIhC"}
@@ -0,0 +1,114 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import * as os from 'os';
4
+ function getLogDir() {
5
+ const platform = os.platform();
6
+ if (platform === 'win32') {
7
+ const appData = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
8
+ return path.join(appData, 'opencode', 'logs');
9
+ }
10
+ else {
11
+ return path.join(os.homedir(), '.config', 'opencode', 'logs');
12
+ }
13
+ }
14
+ const LOG_DIR = getLogDir();
15
+ const LOG_FILE = path.join(LOG_DIR, 'opencode-channels.log');
16
+ const MAX_LOG_SIZE = 10 * 1024 * 1024;
17
+ let logStream = null;
18
+ let originalLog;
19
+ let originalError;
20
+ let originalWarn;
21
+ function ensureLogDir() {
22
+ if (!fs.existsSync(LOG_DIR)) {
23
+ fs.mkdirSync(LOG_DIR, { recursive: true, mode: 0o755 });
24
+ }
25
+ }
26
+ function rotateLogIfNeeded() {
27
+ if (!fs.existsSync(LOG_FILE)) {
28
+ return;
29
+ }
30
+ const stats = fs.statSync(LOG_FILE);
31
+ if (stats.size > MAX_LOG_SIZE) {
32
+ const backupFile = path.join(LOG_DIR, `opencode-channels.log.${Date.now()}`);
33
+ fs.renameSync(LOG_FILE, backupFile);
34
+ const logFiles = fs.readdirSync(LOG_DIR)
35
+ .filter(f => f.startsWith('opencode-channels.log.'))
36
+ .sort()
37
+ .reverse();
38
+ if (logFiles.length > 5) {
39
+ logFiles.slice(5).forEach(f => {
40
+ fs.unlinkSync(path.join(LOG_DIR, f));
41
+ });
42
+ }
43
+ }
44
+ }
45
+ function formatTimestamp() {
46
+ const now = new Date();
47
+ return now.toISOString().replace('T', ' ').substring(0, 19);
48
+ }
49
+ function writeToLog(level, ...args) {
50
+ if (!logStream)
51
+ return;
52
+ const timestamp = formatTimestamp();
53
+ const message = args.map(arg => {
54
+ if (typeof arg === 'object') {
55
+ try {
56
+ return JSON.stringify(arg);
57
+ }
58
+ catch {
59
+ return String(arg);
60
+ }
61
+ }
62
+ return String(arg);
63
+ }).join(' ');
64
+ logStream.write(`[${timestamp}] [${level}] ${message}\n`);
65
+ if (process.env.NODE_ENV === 'test') {
66
+ logStream.end();
67
+ logStream = fs.createWriteStream(LOG_FILE, { flags: 'a' });
68
+ }
69
+ }
70
+ export function setupLogger() {
71
+ if (logStream) {
72
+ return;
73
+ }
74
+ ensureLogDir();
75
+ rotateLogIfNeeded();
76
+ logStream = fs.createWriteStream(LOG_FILE, { flags: 'a' });
77
+ originalLog = console.log;
78
+ originalError = console.error;
79
+ originalWarn = console.warn;
80
+ console.log = (...args) => {
81
+ writeToLog('INFO', ...args);
82
+ originalLog(...args);
83
+ };
84
+ console.error = (...args) => {
85
+ writeToLog('ERROR', ...args);
86
+ originalError(...args);
87
+ };
88
+ console.warn = (...args) => {
89
+ writeToLog('WARN', ...args);
90
+ originalWarn(...args);
91
+ };
92
+ process.on('exit', () => {
93
+ if (logStream) {
94
+ logStream.end();
95
+ }
96
+ });
97
+ }
98
+ export function getLogFilePath() {
99
+ return LOG_FILE;
100
+ }
101
+ export function readLogs(lines = 100) {
102
+ if (!fs.existsSync(LOG_FILE)) {
103
+ return [];
104
+ }
105
+ const content = fs.readFileSync(LOG_FILE, 'utf-8');
106
+ const allLines = content.split('\n').filter(line => line.trim() !== '');
107
+ return allLines.slice(-lines);
108
+ }
109
+ export function clearLogs() {
110
+ if (fs.existsSync(LOG_FILE)) {
111
+ fs.unlinkSync(LOG_FILE);
112
+ }
113
+ }
114
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/shared/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,90 @@
1
+ /**
2
+ * 映射管理模块
3
+ *
4
+ * 负责管理 Telegram 群组到项目的映射,以及 Telegram 主题到 OpenCode 会话的映射。
5
+ * 使用 JSON 文件存储映射数据,提供同步 API 进行增删改查操作。
6
+ */
7
+ import type { MappingData, GroupMapping, TopicMapping, GroupSettings, PendingRetry } from './types.js';
8
+ /**
9
+ * 从文件加载映射数据
10
+ *
11
+ * @returns 映射数据对象
12
+ * @throws 如果文件格式错误
13
+ */
14
+ export declare function loadMappings(): MappingData;
15
+ /**
16
+ * 保存映射数据到文件
17
+ *
18
+ * @param data - 映射数据对象
19
+ */
20
+ export declare function saveMappings(data: MappingData): void;
21
+ /**
22
+ * 添加或更新群组映射
23
+ *
24
+ * @param chatId - Telegram 群组 ID
25
+ * @param projectPath - 项目路径
26
+ * @returns 添加/更新的映射对象
27
+ */
28
+ export declare function addGroupMapping(chatId: number, projectPath: string): GroupMapping;
29
+ /**
30
+ * 添加或更新主题映射
31
+ *
32
+ * @param chatId - Telegram 群组 ID
33
+ * @param topicId - Telegram 主题 ID
34
+ * @param sessionId - OpenCode 会话 ID
35
+ * @returns 添加/更新的映射对象
36
+ */
37
+ export declare function addTopicMapping(chatId: number, topicId: number, sessionId: string): TopicMapping;
38
+ /**
39
+ * 根据 chatId 查询项目路径
40
+ *
41
+ * @param chatId - Telegram 群组 ID
42
+ * @returns 项目路径,如果未找到则返回 null
43
+ */
44
+ export declare function getProjectByChat(chatId: number): string | null;
45
+ /**
46
+ * 根据 chatId 和 topicId 查询会话 ID
47
+ *
48
+ * @param chatId - Telegram 群组 ID
49
+ * @param topicId - Telegram 主题 ID
50
+ * @returns 会话 ID,如果未找到则返回 null
51
+ */
52
+ export declare function getSessionByTopic(chatId: number, topicId: number): string | null;
53
+ /**
54
+ * 获取所有映射数据
55
+ *
56
+ * @returns 完整的映射数据对象
57
+ */
58
+ export declare function getAllMappings(): MappingData;
59
+ /**
60
+ * 获取群组设置
61
+ *
62
+ * @param chatId - Telegram 群组 ID
63
+ * @returns 群组设置,如果未找到则返回 null
64
+ */
65
+ export declare function getGroupSettings(chatId: number): GroupSettings | null;
66
+ /**
67
+ * 更新群组设置
68
+ *
69
+ * @param chatId - Telegram 群组 ID
70
+ * @param settings - 群组设置
71
+ * @returns 是否更新成功
72
+ */
73
+ export declare function setGroupSettings(chatId: number, settings: GroupSettings): boolean;
74
+ export declare const updateGroupSettings: typeof setGroupSettings;
75
+ /**
76
+ * 设置待重试消息
77
+ */
78
+ export declare function setPendingRetry(chatId: number, topicId: number, sessionId: string, message: string, projectPath?: string, agent?: string, model?: string): void;
79
+ /**
80
+ * 获取待重试消息
81
+ */
82
+ export declare function getPendingRetry(chatId: number, topicId: number): PendingRetry | null;
83
+ /**
84
+ * 清除待重试消息
85
+ */
86
+ export declare function clearPendingRetry(chatId: number, topicId: number): void;
87
+ export declare function setStatusMessageId(chatId: number, topicId: number, messageId: number): void;
88
+ export declare function getStatusMessageId(chatId: number, topicId: number): number | null;
89
+ export declare function clearStatusMessageId(chatId: number, topicId: number): void;
90
+ //# sourceMappingURL=mapping.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../src/shared/mapping.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAavG;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,WAAW,CA0B1C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAepD;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,YAAY,CA0BjF;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,YAAY,CAyBhG;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAI9D;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMhF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAIrE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAkBjF;AAED,eAAO,MAAM,mBAAmB,yBAAmB,CAAC;AAEpD;;GAEG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,WAAW,CAAC,EAAE,MAAM,EACpB,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM,GACb,IAAI,CAUN;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI,CAEpF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAEvE;AAID,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAE3F;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEjF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAE1E"}
@@ -0,0 +1,234 @@
1
+ /**
2
+ * 映射管理模块
3
+ *
4
+ * 负责管理 Telegram 群组到项目的映射,以及 Telegram 主题到 OpenCode 会话的映射。
5
+ * 使用 JSON 文件存储映射数据,提供同步 API 进行增删改查操作。
6
+ */
7
+ import * as fs from 'node:fs';
8
+ import * as path from 'node:path';
9
+ import * as os from 'node:os';
10
+ /**
11
+ * 映射文件路径
12
+ */
13
+ const MAPPING_FILE_PATH = path.join(os.homedir(), '.config', 'opencode', 'mappings.json');
14
+ const pendingRetry = new Map();
15
+ function retryKey(chatId, topicId) {
16
+ return `${chatId}:${topicId}`;
17
+ }
18
+ /**
19
+ * 从文件加载映射数据
20
+ *
21
+ * @returns 映射数据对象
22
+ * @throws 如果文件格式错误
23
+ */
24
+ export function loadMappings() {
25
+ try {
26
+ // 如果文件不存在,返回空映射数据
27
+ if (!fs.existsSync(MAPPING_FILE_PATH)) {
28
+ return { groups: [], topics: [] };
29
+ }
30
+ // 读取并解析 JSON 文件
31
+ const content = fs.readFileSync(MAPPING_FILE_PATH, 'utf-8');
32
+ const data = JSON.parse(content);
33
+ // 验证数据格式
34
+ if (!data.groups || !Array.isArray(data.groups)) {
35
+ throw new Error('Invalid mapping data: groups must be an array');
36
+ }
37
+ if (!data.topics || !Array.isArray(data.topics)) {
38
+ throw new Error('Invalid mapping data: topics must be an array');
39
+ }
40
+ return data;
41
+ }
42
+ catch (error) {
43
+ if (error instanceof SyntaxError) {
44
+ throw new Error(`Failed to parse mapping file: ${error.message}`);
45
+ }
46
+ throw error;
47
+ }
48
+ }
49
+ /**
50
+ * 保存映射数据到文件
51
+ *
52
+ * @param data - 映射数据对象
53
+ */
54
+ export function saveMappings(data) {
55
+ // 确保配置目录存在
56
+ const configDir = path.dirname(MAPPING_FILE_PATH);
57
+ if (!fs.existsSync(configDir)) {
58
+ fs.mkdirSync(configDir, { recursive: true });
59
+ }
60
+ // 序列化为 JSON(格式化,缩进 2 空格)
61
+ const content = JSON.stringify(data, null, 2);
62
+ // 写入文件
63
+ fs.writeFileSync(MAPPING_FILE_PATH, content, 'utf-8');
64
+ // 设置文件权限为 600(仅所有者可读写)
65
+ fs.chmodSync(MAPPING_FILE_PATH, 0o600);
66
+ }
67
+ /**
68
+ * 添加或更新群组映射
69
+ *
70
+ * @param chatId - Telegram 群组 ID
71
+ * @param projectPath - 项目路径
72
+ * @returns 添加/更新的映射对象
73
+ */
74
+ export function addGroupMapping(chatId, projectPath) {
75
+ const mappings = loadMappings();
76
+ // 查找是否已存在该 chatId 的映射
77
+ const existingIndex = mappings.groups.findIndex(g => g.chatId === chatId);
78
+ if (existingIndex !== -1) {
79
+ // 更新现有映射
80
+ const existing = mappings.groups[existingIndex];
81
+ mappings.groups[existingIndex] = {
82
+ ...existing,
83
+ projectPath,
84
+ };
85
+ saveMappings(mappings);
86
+ return mappings.groups[existingIndex];
87
+ }
88
+ else {
89
+ // 添加新映射
90
+ const newMapping = {
91
+ chatId,
92
+ projectPath,
93
+ createdAt: new Date().toISOString(),
94
+ };
95
+ mappings.groups.push(newMapping);
96
+ saveMappings(mappings);
97
+ return newMapping;
98
+ }
99
+ }
100
+ /**
101
+ * 添加或更新主题映射
102
+ *
103
+ * @param chatId - Telegram 群组 ID
104
+ * @param topicId - Telegram 主题 ID
105
+ * @param sessionId - OpenCode 会话 ID
106
+ * @returns 添加/更新的映射对象
107
+ */
108
+ export function addTopicMapping(chatId, topicId, sessionId) {
109
+ const mappings = loadMappings();
110
+ // 查找是否已存在该 chatId+topicId 的映射
111
+ const existingIndex = mappings.topics.findIndex(t => t.chatId === chatId && t.topicId === topicId);
112
+ if (existingIndex !== -1) {
113
+ // 更新现有映射
114
+ mappings.topics[existingIndex].sessionId = sessionId;
115
+ saveMappings(mappings);
116
+ return mappings.topics[existingIndex];
117
+ }
118
+ else {
119
+ // 添加新映射
120
+ const newMapping = {
121
+ chatId,
122
+ topicId,
123
+ sessionId,
124
+ createdAt: new Date().toISOString(),
125
+ };
126
+ mappings.topics.push(newMapping);
127
+ saveMappings(mappings);
128
+ return newMapping;
129
+ }
130
+ }
131
+ /**
132
+ * 根据 chatId 查询项目路径
133
+ *
134
+ * @param chatId - Telegram 群组 ID
135
+ * @returns 项目路径,如果未找到则返回 null
136
+ */
137
+ export function getProjectByChat(chatId) {
138
+ const mappings = loadMappings();
139
+ const groupMapping = mappings.groups.find(g => g.chatId === chatId);
140
+ return groupMapping ? groupMapping.projectPath : null;
141
+ }
142
+ /**
143
+ * 根据 chatId 和 topicId 查询会话 ID
144
+ *
145
+ * @param chatId - Telegram 群组 ID
146
+ * @param topicId - Telegram 主题 ID
147
+ * @returns 会话 ID,如果未找到则返回 null
148
+ */
149
+ export function getSessionByTopic(chatId, topicId) {
150
+ const mappings = loadMappings();
151
+ const topicMapping = mappings.topics.find(t => t.chatId === chatId && t.topicId === topicId);
152
+ return topicMapping ? topicMapping.sessionId : null;
153
+ }
154
+ /**
155
+ * 获取所有映射数据
156
+ *
157
+ * @returns 完整的映射数据对象
158
+ */
159
+ export function getAllMappings() {
160
+ return loadMappings();
161
+ }
162
+ /**
163
+ * 获取群组设置
164
+ *
165
+ * @param chatId - Telegram 群组 ID
166
+ * @returns 群组设置,如果未找到则返回 null
167
+ */
168
+ export function getGroupSettings(chatId) {
169
+ const mappings = loadMappings();
170
+ const groupMapping = mappings.groups.find(g => g.chatId === chatId);
171
+ return groupMapping?.settings ?? null;
172
+ }
173
+ /**
174
+ * 更新群组设置
175
+ *
176
+ * @param chatId - Telegram 群组 ID
177
+ * @param settings - 群组设置
178
+ * @returns 是否更新成功
179
+ */
180
+ export function setGroupSettings(chatId, settings) {
181
+ const mappings = loadMappings();
182
+ const existingIndex = mappings.groups.findIndex(g => g.chatId === chatId);
183
+ if (existingIndex === -1) {
184
+ return false;
185
+ }
186
+ const existing = mappings.groups[existingIndex];
187
+ mappings.groups[existingIndex] = {
188
+ ...existing,
189
+ settings: {
190
+ ...existing.settings,
191
+ ...settings,
192
+ },
193
+ };
194
+ saveMappings(mappings);
195
+ return true;
196
+ }
197
+ export const updateGroupSettings = setGroupSettings;
198
+ /**
199
+ * 设置待重试消息
200
+ */
201
+ export function setPendingRetry(chatId, topicId, sessionId, message, projectPath, agent, model) {
202
+ pendingRetry.set(retryKey(chatId, topicId), {
203
+ chatId,
204
+ topicId,
205
+ sessionId,
206
+ message,
207
+ projectPath,
208
+ agent,
209
+ model,
210
+ });
211
+ }
212
+ /**
213
+ * 获取待重试消息
214
+ */
215
+ export function getPendingRetry(chatId, topicId) {
216
+ return pendingRetry.get(retryKey(chatId, topicId)) ?? null;
217
+ }
218
+ /**
219
+ * 清除待重试消息
220
+ */
221
+ export function clearPendingRetry(chatId, topicId) {
222
+ pendingRetry.delete(retryKey(chatId, topicId));
223
+ }
224
+ const statusMessages = new Map();
225
+ export function setStatusMessageId(chatId, topicId, messageId) {
226
+ statusMessages.set(`${chatId}:${topicId}`, messageId);
227
+ }
228
+ export function getStatusMessageId(chatId, topicId) {
229
+ return statusMessages.get(`${chatId}:${topicId}`) ?? null;
230
+ }
231
+ export function clearStatusMessageId(chatId, topicId) {
232
+ statusMessages.delete(`${chatId}:${topicId}`);
233
+ }
234
+ //# sourceMappingURL=mapping.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapping.js","sourceRoot":"","sources":["../../src/shared/mapping.ts"],"names":[],"mappings":"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"}