botmux 1.2.0 → 1.2.2
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/adapters/cli/aiden.d.ts.map +1 -1
- package/dist/adapters/cli/aiden.js +0 -1
- package/dist/adapters/cli/aiden.js.map +1 -1
- package/dist/adapters/cli/claude-code.d.ts.map +1 -1
- package/dist/adapters/cli/claude-code.js +0 -1
- package/dist/adapters/cli/claude-code.js.map +1 -1
- package/dist/adapters/cli/coco.d.ts.map +1 -1
- package/dist/adapters/cli/coco.js +0 -1
- package/dist/adapters/cli/coco.js.map +1 -1
- package/dist/cli.js +0 -0
- package/dist/core/types.d.ts +2 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/worker-pool.d.ts.map +1 -1
- package/dist/core/worker-pool.js +3 -2
- package/dist/core/worker-pool.js.map +1 -1
- package/dist/daemon.js +1 -1
- package/dist/daemon.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +52 -46
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/card-handler.d.ts.map +1 -1
- package/dist/im/lark/card-handler.js +13 -2
- package/dist/im/lark/card-handler.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +14 -1
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/scheduler.d.ts +38 -0
- package/dist/scheduler.d.ts.map +1 -0
- package/dist/scheduler.js +221 -0
- package/dist/scheduler.js.map +1 -0
- package/dist/services/lark-client.d.ts +22 -0
- package/dist/services/lark-client.d.ts.map +1 -0
- package/dist/services/lark-client.js +238 -0
- package/dist/services/lark-client.js.map +1 -0
- package/dist/services/lark-ws.d.ts +5 -0
- package/dist/services/lark-ws.d.ts.map +1 -0
- package/dist/services/lark-ws.js +79 -0
- package/dist/services/lark-ws.js.map +1 -0
- package/dist/services/message-router.d.ts +8 -0
- package/dist/services/message-router.d.ts.map +1 -0
- package/dist/services/message-router.js +73 -0
- package/dist/services/message-router.js.map +1 -0
- package/dist/tools/close-session.d.ts +22 -0
- package/dist/tools/close-session.d.ts.map +1 -0
- package/dist/tools/close-session.js +38 -0
- package/dist/tools/close-session.js.map +1 -0
- package/dist/tools/create-session.d.ts +28 -0
- package/dist/tools/create-session.d.ts.map +1 -0
- package/dist/tools/create-session.js +40 -0
- package/dist/tools/create-session.js.map +1 -0
- package/dist/tools/wait-for-reply.d.ts +17 -0
- package/dist/tools/wait-for-reply.d.ts.map +1 -0
- package/dist/tools/wait-for-reply.js +65 -0
- package/dist/tools/wait-for-reply.js.map +1 -0
- package/dist/utils/card-builder.d.ts +16 -0
- package/dist/utils/card-builder.d.ts.map +1 -0
- package/dist/utils/card-builder.js +183 -0
- package/dist/utils/card-builder.js.map +1 -0
- package/dist/utils/message-parser.d.ts +45 -0
- package/dist/utils/message-parser.d.ts.map +1 -0
- package/dist/utils/message-parser.js +132 -0
- package/dist/utils/message-parser.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ScheduledTask } from './types.js';
|
|
2
|
+
export declare function setExecuteCallback(cb: (task: ScheduledTask) => Promise<void>): void;
|
|
3
|
+
interface ParseResult {
|
|
4
|
+
cron: string;
|
|
5
|
+
type: ScheduledTask['type'];
|
|
6
|
+
prompt: string;
|
|
7
|
+
name: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Parse natural language schedule expression into cron + prompt.
|
|
11
|
+
*
|
|
12
|
+
* Examples:
|
|
13
|
+
* "每日17:50给我帮我看看AI新闻" → { cron: "50 17 * * *", prompt: "帮我看看AI新闻" }
|
|
14
|
+
* "每天9:00 检查服务状态" → { cron: "0 9 * * *", prompt: "检查服务状态" }
|
|
15
|
+
* "每周一10:30 生成周报" → { cron: "30 10 * * 1", prompt: "生成周报" }
|
|
16
|
+
* "工作日每天9:00 检查邮件" → { cron: "0 9 * * 1-5", prompt: "检查邮件" }
|
|
17
|
+
* "每小时 检查服务" → { cron: "0 * * * *", prompt: "检查服务" }
|
|
18
|
+
* "每30分钟 ping" → { cron: "*\/30 * * * *", prompt: "ping" }
|
|
19
|
+
* "每月1号9:00 生成月报" → { cron: "0 9 1 * *", prompt: "生成月报" }
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseNaturalSchedule(input: string): ParseResult | null;
|
|
22
|
+
export declare function startScheduler(): void;
|
|
23
|
+
export declare function stopScheduler(): void;
|
|
24
|
+
export declare function addTask(params: {
|
|
25
|
+
name: string;
|
|
26
|
+
type: ScheduledTask['type'];
|
|
27
|
+
schedule: string;
|
|
28
|
+
prompt: string;
|
|
29
|
+
workingDir: string;
|
|
30
|
+
chatId: string;
|
|
31
|
+
}): ScheduledTask;
|
|
32
|
+
export declare function removeTask(id: string): boolean;
|
|
33
|
+
export declare function enableTask(id: string): boolean;
|
|
34
|
+
export declare function disableTask(id: string): boolean;
|
|
35
|
+
export declare function runTaskNow(id: string): boolean;
|
|
36
|
+
export declare function getNextRun(id: string): Date | null;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=scheduler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.d.ts","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAShD,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAEnF;AASD,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CA4GtE;AA0CD,wBAAgB,cAAc,IAAI,IAAI,CAQrC;AAED,wBAAgB,aAAa,IAAI,IAAI,CAKpC;AAED,wBAAgB,OAAO,CAAC,MAAM,EAAE;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB,GAAG,aAAa,CAIhB;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAG9C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAO9C;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAM/C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAa9C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGlD"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import { Cron } from 'croner';
|
|
2
|
+
import * as scheduleStore from './services/schedule-store.js';
|
|
3
|
+
import { logger } from './utils/logger.js';
|
|
4
|
+
// ─── Active cron instances ──────────────────────────────────────────────────
|
|
5
|
+
const cronJobs = new Map();
|
|
6
|
+
// Callback set by daemon to execute a scheduled task
|
|
7
|
+
let executeCallback = null;
|
|
8
|
+
export function setExecuteCallback(cb) {
|
|
9
|
+
executeCallback = cb;
|
|
10
|
+
}
|
|
11
|
+
// ─── Natural language → cron parser ─────────────────────────────────────────
|
|
12
|
+
const WEEKDAY_MAP = {
|
|
13
|
+
'一': 1, '二': 2, '三': 3, '四': 4, '五': 5, '六': 6, '日': 0, '天': 0,
|
|
14
|
+
'周一': 1, '周二': 2, '周三': 3, '周四': 4, '周五': 5, '周六': 6, '周日': 0,
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Parse natural language schedule expression into cron + prompt.
|
|
18
|
+
*
|
|
19
|
+
* Examples:
|
|
20
|
+
* "每日17:50给我帮我看看AI新闻" → { cron: "50 17 * * *", prompt: "帮我看看AI新闻" }
|
|
21
|
+
* "每天9:00 检查服务状态" → { cron: "0 9 * * *", prompt: "检查服务状态" }
|
|
22
|
+
* "每周一10:30 生成周报" → { cron: "30 10 * * 1", prompt: "生成周报" }
|
|
23
|
+
* "工作日每天9:00 检查邮件" → { cron: "0 9 * * 1-5", prompt: "检查邮件" }
|
|
24
|
+
* "每小时 检查服务" → { cron: "0 * * * *", prompt: "检查服务" }
|
|
25
|
+
* "每30分钟 ping" → { cron: "*\/30 * * * *", prompt: "ping" }
|
|
26
|
+
* "每月1号9:00 生成月报" → { cron: "0 9 1 * *", prompt: "生成月报" }
|
|
27
|
+
*/
|
|
28
|
+
export function parseNaturalSchedule(input) {
|
|
29
|
+
let rest = input.trim();
|
|
30
|
+
let cron = '';
|
|
31
|
+
let type = 'cron';
|
|
32
|
+
// Helper: parse time like "17:50", "17:50", "9点", "9点30", "17点30分"
|
|
33
|
+
function parseTime(s) {
|
|
34
|
+
// HH:MM or HH:MM
|
|
35
|
+
let tm = s.match(/^(\d{1,2})[:::](\d{2})\s*(.*)/s);
|
|
36
|
+
if (tm)
|
|
37
|
+
return { hour: parseInt(tm[1]), minute: parseInt(tm[2]), rest: tm[3] };
|
|
38
|
+
// X点Y分 or X点Y
|
|
39
|
+
tm = s.match(/^(\d{1,2})点(\d{1,2})分?\s*(.*)/s);
|
|
40
|
+
if (tm)
|
|
41
|
+
return { hour: parseInt(tm[1]), minute: parseInt(tm[2]), rest: tm[3] };
|
|
42
|
+
// X点 (whole hour)
|
|
43
|
+
tm = s.match(/^(\d{1,2})点\s*(.*)/s);
|
|
44
|
+
if (tm)
|
|
45
|
+
return { hour: parseInt(tm[1]), minute: 0, rest: tm[2] };
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
// Pattern: 工作日/每个工作日 HH:MM
|
|
49
|
+
let m = rest.match(/^(?:每个?工作日|工作日每[天日])\s*(.*)/);
|
|
50
|
+
if (m) {
|
|
51
|
+
const t = parseTime(m[1]);
|
|
52
|
+
if (t) {
|
|
53
|
+
cron = `${t.minute} ${t.hour} * * 1-5`;
|
|
54
|
+
rest = t.rest;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// Pattern: 每日/每天 HH:MM
|
|
58
|
+
if (!cron) {
|
|
59
|
+
m = rest.match(/^每[天日]\s*(.*)/);
|
|
60
|
+
if (m) {
|
|
61
|
+
const t = parseTime(m[1]);
|
|
62
|
+
if (t) {
|
|
63
|
+
cron = `${t.minute} ${t.hour} * * *`;
|
|
64
|
+
rest = t.rest;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// Pattern: 每周X HH:MM
|
|
69
|
+
if (!cron) {
|
|
70
|
+
m = rest.match(/^每周([一二三四五六日天])\s*(.*)/);
|
|
71
|
+
if (m) {
|
|
72
|
+
const day = WEEKDAY_MAP[m[1]] ?? 1;
|
|
73
|
+
const t = parseTime(m[2]);
|
|
74
|
+
if (t) {
|
|
75
|
+
cron = `${t.minute} ${t.hour} * * ${day}`;
|
|
76
|
+
rest = t.rest;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
// Pattern: 每月X号 HH:MM
|
|
81
|
+
if (!cron) {
|
|
82
|
+
m = rest.match(/^每月(\d{1,2})[号日]\s*(.*)/);
|
|
83
|
+
if (m) {
|
|
84
|
+
const dayOfMonth = parseInt(m[1]);
|
|
85
|
+
const t = parseTime(m[2]);
|
|
86
|
+
if (t) {
|
|
87
|
+
cron = `${t.minute} ${t.hour} ${dayOfMonth} * *`;
|
|
88
|
+
rest = t.rest;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Pattern: 每N小时
|
|
93
|
+
if (!cron) {
|
|
94
|
+
m = rest.match(/^每(\d+)小时\s*(.*)/);
|
|
95
|
+
if (m) {
|
|
96
|
+
const hours = parseInt(m[1]);
|
|
97
|
+
cron = hours === 1 ? '0 * * * *' : `0 */${hours} * * *`;
|
|
98
|
+
rest = m[2];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
// Pattern: 每小时
|
|
102
|
+
if (!cron) {
|
|
103
|
+
m = rest.match(/^每小时\s*(.*)/);
|
|
104
|
+
if (m) {
|
|
105
|
+
cron = '0 * * * *';
|
|
106
|
+
rest = m[1];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// Pattern: 每N分钟
|
|
110
|
+
if (!cron) {
|
|
111
|
+
m = rest.match(/^每(\d+)分钟\s*(.*)/);
|
|
112
|
+
if (m) {
|
|
113
|
+
cron = `*/${parseInt(m[1])} * * * *`;
|
|
114
|
+
rest = m[2];
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (!cron)
|
|
118
|
+
return null;
|
|
119
|
+
// Clean prompt: remove leading connectors like "给我" "帮我" etc.
|
|
120
|
+
let prompt = rest.replace(/^[给帮]我\s*/, '').trim();
|
|
121
|
+
// Remove surrounding quotes
|
|
122
|
+
prompt = prompt.replace(/^["'"「](.+?)["'"」]$/, '$1').trim();
|
|
123
|
+
if (!prompt)
|
|
124
|
+
return null;
|
|
125
|
+
// Auto-generate name from prompt (first 20 chars)
|
|
126
|
+
const name = prompt.length > 20 ? prompt.substring(0, 20) + '...' : prompt;
|
|
127
|
+
return { cron, type, prompt, name };
|
|
128
|
+
}
|
|
129
|
+
// ─── Cron management ────────────────────────────────────────────────────────
|
|
130
|
+
function scheduleCronJob(task) {
|
|
131
|
+
// Stop existing job if any
|
|
132
|
+
stopCronJob(task.id);
|
|
133
|
+
if (!task.enabled)
|
|
134
|
+
return;
|
|
135
|
+
try {
|
|
136
|
+
const job = new Cron(task.schedule, { timezone: 'Asia/Shanghai' }, async () => {
|
|
137
|
+
logger.info(`[scheduler] Task "${task.name}" (${task.id}) triggered`);
|
|
138
|
+
scheduleStore.updateTask(task.id, { lastRunAt: new Date().toISOString() });
|
|
139
|
+
if (executeCallback) {
|
|
140
|
+
try {
|
|
141
|
+
await executeCallback(task);
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
logger.error(`[scheduler] Failed to execute task "${task.name}": ${err.message}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
cronJobs.set(task.id, job);
|
|
149
|
+
const next = job.nextRun();
|
|
150
|
+
logger.info(`[scheduler] Scheduled "${task.name}" (${task.id}): ${task.schedule}, next run: ${next?.toLocaleString('zh-CN', { timeZone: 'Asia/Shanghai' }) ?? 'N/A'}`);
|
|
151
|
+
}
|
|
152
|
+
catch (err) {
|
|
153
|
+
logger.error(`[scheduler] Invalid cron expression for task "${task.name}": ${task.schedule} — ${err.message}`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function stopCronJob(taskId) {
|
|
157
|
+
const job = cronJobs.get(taskId);
|
|
158
|
+
if (job) {
|
|
159
|
+
job.stop();
|
|
160
|
+
cronJobs.delete(taskId);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
164
|
+
export function startScheduler() {
|
|
165
|
+
const tasks = scheduleStore.listTasks();
|
|
166
|
+
const enabled = tasks.filter(t => t.enabled);
|
|
167
|
+
logger.info(`[scheduler] Starting with ${enabled.length}/${tasks.length} enabled tasks`);
|
|
168
|
+
for (const task of enabled) {
|
|
169
|
+
scheduleCronJob(task);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
export function stopScheduler() {
|
|
173
|
+
for (const [id] of cronJobs) {
|
|
174
|
+
stopCronJob(id);
|
|
175
|
+
}
|
|
176
|
+
logger.info('[scheduler] All cron jobs stopped');
|
|
177
|
+
}
|
|
178
|
+
export function addTask(params) {
|
|
179
|
+
const task = scheduleStore.createTask(params);
|
|
180
|
+
scheduleCronJob(task);
|
|
181
|
+
return task;
|
|
182
|
+
}
|
|
183
|
+
export function removeTask(id) {
|
|
184
|
+
stopCronJob(id);
|
|
185
|
+
return scheduleStore.removeTask(id);
|
|
186
|
+
}
|
|
187
|
+
export function enableTask(id) {
|
|
188
|
+
const task = scheduleStore.getTask(id);
|
|
189
|
+
if (!task)
|
|
190
|
+
return false;
|
|
191
|
+
scheduleStore.updateTask(id, { enabled: true });
|
|
192
|
+
task.enabled = true;
|
|
193
|
+
scheduleCronJob(task);
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
export function disableTask(id) {
|
|
197
|
+
const task = scheduleStore.getTask(id);
|
|
198
|
+
if (!task)
|
|
199
|
+
return false;
|
|
200
|
+
scheduleStore.updateTask(id, { enabled: false });
|
|
201
|
+
stopCronJob(id);
|
|
202
|
+
return true;
|
|
203
|
+
}
|
|
204
|
+
export function runTaskNow(id) {
|
|
205
|
+
const task = scheduleStore.getTask(id);
|
|
206
|
+
if (!task)
|
|
207
|
+
return false;
|
|
208
|
+
logger.info(`[scheduler] Manual run of task "${task.name}" (${task.id})`);
|
|
209
|
+
scheduleStore.updateTask(id, { lastRunAt: new Date().toISOString() });
|
|
210
|
+
if (executeCallback) {
|
|
211
|
+
executeCallback(task).catch(err => {
|
|
212
|
+
logger.error(`[scheduler] Manual run failed for "${task.name}": ${err.message}`);
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
export function getNextRun(id) {
|
|
218
|
+
const job = cronJobs.get(id);
|
|
219
|
+
return job?.nextRun() ?? null;
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=scheduler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as Lark from '@larksuiteoapi/node-sdk';
|
|
2
|
+
export declare function getLarkClient(): Lark.Client;
|
|
3
|
+
export declare function sendMessage(chatId: string, content: string, msgType?: string): Promise<string>;
|
|
4
|
+
export declare function replyMessage(messageId: string, content: string, msgType?: string, replyInThread?: boolean): Promise<string>;
|
|
5
|
+
export declare function addReaction(messageId: string, emojiType: string): Promise<string>;
|
|
6
|
+
export declare function removeReaction(messageId: string, reactionId: string): Promise<void>;
|
|
7
|
+
export declare function sendUserMessage(openId: string, content: string, msgType?: string): Promise<string>;
|
|
8
|
+
export declare function getChatInfo(chatId: string): Promise<{
|
|
9
|
+
userCount: number;
|
|
10
|
+
}>;
|
|
11
|
+
export declare function updateMessage(messageId: string, cardJson: string): Promise<void>;
|
|
12
|
+
export declare function getMessageDetail(messageId: string): Promise<any>;
|
|
13
|
+
export declare function downloadMessageResource(messageId: string, fileKey: string, type: 'image' | 'file', savePath: string): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Resolve email prefixes (e.g. "shenhan.sh") to Lark open_ids via batch user lookup.
|
|
16
|
+
* Accepts mixed input: items starting with "ou_" are kept as-is; everything else
|
|
17
|
+
* is treated as an email prefix and looked up as `${prefix}@bytedance.com`.
|
|
18
|
+
* Returns an array of open_ids (unresolvable entries are dropped with a warning).
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveAllowedUsers(raw: string[]): Promise<string[]>;
|
|
21
|
+
export declare function listThreadMessages(chatId: string, rootMessageId: string, pageSize?: number): Promise<any[]>;
|
|
22
|
+
//# sourceMappingURL=lark-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lark-client.d.ts","sourceRoot":"","sources":["../../src/services/lark-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAQhD,wBAAgB,aAAa,IAAI,IAAI,CAAC,MAAM,CAQ3C;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB5G;AAED,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAe,EAAE,aAAa,GAAE,OAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBhJ;AAED,wBAAsB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYvF;AAED,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASzF;AAED,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBhH;AAED,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAUhF;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAStF;AAED,wBAAsB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAStE;AAED,wBAAsB,uBAAuB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2BzI;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAoC1E;AAED,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,QAAQ,GAAE,MAAW,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAuCrH"}
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
import * as Lark from '@larksuiteoapi/node-sdk';
|
|
2
|
+
import { writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { config } from '../config.js';
|
|
5
|
+
import { logger } from '../utils/logger.js';
|
|
6
|
+
let client;
|
|
7
|
+
export function getLarkClient() {
|
|
8
|
+
if (!client) {
|
|
9
|
+
client = new Lark.Client({
|
|
10
|
+
appId: config.lark.appId,
|
|
11
|
+
appSecret: config.lark.appSecret,
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return client;
|
|
15
|
+
}
|
|
16
|
+
export async function sendMessage(chatId, content, msgType = 'text') {
|
|
17
|
+
const c = getLarkClient();
|
|
18
|
+
const body = msgType === 'text' ? JSON.stringify({ text: content }) : content;
|
|
19
|
+
const res = await c.im.v1.message.create({
|
|
20
|
+
params: { receive_id_type: 'chat_id' },
|
|
21
|
+
data: {
|
|
22
|
+
receive_id: chatId,
|
|
23
|
+
msg_type: msgType,
|
|
24
|
+
content: body,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
if (res.code !== 0) {
|
|
28
|
+
throw new Error(`Failed to send message: ${res.msg} (code: ${res.code})`);
|
|
29
|
+
}
|
|
30
|
+
const messageId = res.data?.message_id;
|
|
31
|
+
if (!messageId)
|
|
32
|
+
throw new Error('No message_id in response');
|
|
33
|
+
logger.info(`Sent message ${messageId} to chat ${chatId}`);
|
|
34
|
+
return messageId;
|
|
35
|
+
}
|
|
36
|
+
export async function replyMessage(messageId, content, msgType = 'text', replyInThread = false) {
|
|
37
|
+
const c = getLarkClient();
|
|
38
|
+
const body = msgType === 'text' ? JSON.stringify({ text: content }) : content;
|
|
39
|
+
const res = await c.im.v1.message.reply({
|
|
40
|
+
path: { message_id: messageId },
|
|
41
|
+
data: {
|
|
42
|
+
msg_type: msgType,
|
|
43
|
+
content: body,
|
|
44
|
+
...(replyInThread ? { reply_in_thread: true } : {}),
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
if (res.code !== 0) {
|
|
48
|
+
throw new Error(`Failed to reply message: ${res.msg} (code: ${res.code})`);
|
|
49
|
+
}
|
|
50
|
+
const replyId = res.data?.message_id;
|
|
51
|
+
if (!replyId)
|
|
52
|
+
throw new Error('No message_id in reply response');
|
|
53
|
+
logger.info(`Replied ${replyId} to message ${messageId}${replyInThread ? ' (in thread)' : ''}`);
|
|
54
|
+
return replyId;
|
|
55
|
+
}
|
|
56
|
+
export async function addReaction(messageId, emojiType) {
|
|
57
|
+
const c = getLarkClient();
|
|
58
|
+
const res = await c.im.v1.messageReaction.create({
|
|
59
|
+
path: { message_id: messageId },
|
|
60
|
+
data: { reaction_type: { emoji_type: emojiType } },
|
|
61
|
+
});
|
|
62
|
+
if (res.code !== 0) {
|
|
63
|
+
throw new Error(`Failed to add reaction: ${res.msg} (code: ${res.code})`);
|
|
64
|
+
}
|
|
65
|
+
const reactionId = res.data?.reaction_id;
|
|
66
|
+
logger.info(`Added reaction ${emojiType} (${reactionId}) to message ${messageId}`);
|
|
67
|
+
return reactionId ?? '';
|
|
68
|
+
}
|
|
69
|
+
export async function removeReaction(messageId, reactionId) {
|
|
70
|
+
const c = getLarkClient();
|
|
71
|
+
const res = await c.im.v1.messageReaction.delete({
|
|
72
|
+
path: { message_id: messageId, reaction_id: reactionId },
|
|
73
|
+
});
|
|
74
|
+
if (res.code !== 0) {
|
|
75
|
+
throw new Error(`Failed to remove reaction: ${res.msg} (code: ${res.code})`);
|
|
76
|
+
}
|
|
77
|
+
logger.info(`Removed reaction ${reactionId} from message ${messageId}`);
|
|
78
|
+
}
|
|
79
|
+
export async function sendUserMessage(openId, content, msgType = 'text') {
|
|
80
|
+
const c = getLarkClient();
|
|
81
|
+
const body = msgType === 'text' ? JSON.stringify({ text: content }) : content;
|
|
82
|
+
const res = await c.im.v1.message.create({
|
|
83
|
+
params: { receive_id_type: 'open_id' },
|
|
84
|
+
data: {
|
|
85
|
+
receive_id: openId,
|
|
86
|
+
msg_type: msgType,
|
|
87
|
+
content: body,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
if (res.code !== 0) {
|
|
91
|
+
throw new Error(`Failed to send user message: ${res.msg} (code: ${res.code})`);
|
|
92
|
+
}
|
|
93
|
+
const messageId = res.data?.message_id;
|
|
94
|
+
if (!messageId)
|
|
95
|
+
throw new Error('No message_id in response');
|
|
96
|
+
logger.info(`Sent DM ${messageId} to user ${openId}`);
|
|
97
|
+
return messageId;
|
|
98
|
+
}
|
|
99
|
+
export async function getChatInfo(chatId) {
|
|
100
|
+
const c = getLarkClient();
|
|
101
|
+
const res = await c.im.v1.chat.get({
|
|
102
|
+
path: { chat_id: chatId },
|
|
103
|
+
});
|
|
104
|
+
if (res.code !== 0) {
|
|
105
|
+
throw new Error(`Failed to get chat info: ${res.msg} (code: ${res.code})`);
|
|
106
|
+
}
|
|
107
|
+
// user_count excludes bots, only real users
|
|
108
|
+
return { userCount: Number(res.data?.user_count ?? 0) };
|
|
109
|
+
}
|
|
110
|
+
export async function updateMessage(messageId, cardJson) {
|
|
111
|
+
const c = getLarkClient();
|
|
112
|
+
const res = await c.im.v1.message.patch({
|
|
113
|
+
path: { message_id: messageId },
|
|
114
|
+
data: { content: cardJson },
|
|
115
|
+
});
|
|
116
|
+
if (res.code !== 0) {
|
|
117
|
+
throw new Error(`Failed to update message: ${res.msg} (code: ${res.code})`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
export async function getMessageDetail(messageId) {
|
|
121
|
+
const c = getLarkClient();
|
|
122
|
+
const res = await c.im.v1.message.get({
|
|
123
|
+
path: { message_id: messageId },
|
|
124
|
+
});
|
|
125
|
+
if (res.code !== 0) {
|
|
126
|
+
throw new Error(`Failed to get message: ${res.msg} (code: ${res.code})`);
|
|
127
|
+
}
|
|
128
|
+
return res.data;
|
|
129
|
+
}
|
|
130
|
+
export async function downloadMessageResource(messageId, fileKey, type, savePath) {
|
|
131
|
+
const c = getLarkClient();
|
|
132
|
+
const dir = dirname(savePath);
|
|
133
|
+
if (!existsSync(dir)) {
|
|
134
|
+
mkdirSync(dir, { recursive: true });
|
|
135
|
+
}
|
|
136
|
+
const res = await c.im.v1.messageResource.get({
|
|
137
|
+
path: { message_id: messageId, file_key: fileKey },
|
|
138
|
+
params: { type },
|
|
139
|
+
});
|
|
140
|
+
if (res instanceof Buffer) {
|
|
141
|
+
writeFileSync(savePath, res);
|
|
142
|
+
}
|
|
143
|
+
else if (res && typeof res === 'object' && 'writeFile' in res) {
|
|
144
|
+
await res.writeFile(savePath);
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
// Response is likely a readable stream or buffer-like
|
|
148
|
+
const chunks = [];
|
|
149
|
+
for await (const chunk of res) {
|
|
150
|
+
chunks.push(Buffer.from(chunk));
|
|
151
|
+
}
|
|
152
|
+
writeFileSync(savePath, Buffer.concat(chunks));
|
|
153
|
+
}
|
|
154
|
+
logger.info(`Downloaded ${type} ${fileKey} → ${savePath}`);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Resolve email prefixes (e.g. "shenhan.sh") to Lark open_ids via batch user lookup.
|
|
158
|
+
* Accepts mixed input: items starting with "ou_" are kept as-is; everything else
|
|
159
|
+
* is treated as an email prefix and looked up as `${prefix}@bytedance.com`.
|
|
160
|
+
* Returns an array of open_ids (unresolvable entries are dropped with a warning).
|
|
161
|
+
*/
|
|
162
|
+
export async function resolveAllowedUsers(raw) {
|
|
163
|
+
const openIds = [];
|
|
164
|
+
const emailPrefixes = [];
|
|
165
|
+
for (const v of raw) {
|
|
166
|
+
if (v.startsWith('ou_')) {
|
|
167
|
+
openIds.push(v);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
emailPrefixes.push(v);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
if (emailPrefixes.length === 0)
|
|
174
|
+
return openIds;
|
|
175
|
+
const emails = emailPrefixes.map(p => p.includes('@') ? p : `${p}@bytedance.com`);
|
|
176
|
+
const c = getLarkClient();
|
|
177
|
+
try {
|
|
178
|
+
const res = await c.contact.v3.user.batchGetId({
|
|
179
|
+
params: { user_id_type: 'open_id' },
|
|
180
|
+
data: { emails, include_resigned: false },
|
|
181
|
+
});
|
|
182
|
+
if (res.code !== 0) {
|
|
183
|
+
logger.warn(`Failed to resolve emails to open_ids: ${res.msg} (code: ${res.code})`);
|
|
184
|
+
return openIds;
|
|
185
|
+
}
|
|
186
|
+
const userList = res.data?.user_list ?? [];
|
|
187
|
+
for (const item of userList) {
|
|
188
|
+
if (item.user_id) {
|
|
189
|
+
openIds.push(item.user_id);
|
|
190
|
+
logger.info(`Resolved ${item.email} → ${item.user_id}`);
|
|
191
|
+
}
|
|
192
|
+
else {
|
|
193
|
+
logger.warn(`Could not resolve email: ${item.email}`);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
catch (err) {
|
|
198
|
+
logger.warn(`resolveAllowedUsers failed: ${err.message}`);
|
|
199
|
+
}
|
|
200
|
+
return openIds;
|
|
201
|
+
}
|
|
202
|
+
export async function listThreadMessages(chatId, rootMessageId, pageSize = 50) {
|
|
203
|
+
const c = getLarkClient();
|
|
204
|
+
const allMessages = [];
|
|
205
|
+
let pageToken;
|
|
206
|
+
// Lark API only supports container_id_type="chat", so we list chat messages
|
|
207
|
+
// and filter by root_id to get thread messages
|
|
208
|
+
do {
|
|
209
|
+
const res = await c.im.v1.message.list({
|
|
210
|
+
params: {
|
|
211
|
+
container_id_type: 'chat',
|
|
212
|
+
container_id: chatId,
|
|
213
|
+
page_size: pageSize,
|
|
214
|
+
sort_type: 'ByCreateTimeDesc',
|
|
215
|
+
...(pageToken ? { page_token: pageToken } : {}),
|
|
216
|
+
},
|
|
217
|
+
});
|
|
218
|
+
if (res.code !== 0) {
|
|
219
|
+
throw new Error(`Failed to list messages: ${res.msg} (code: ${res.code})`);
|
|
220
|
+
}
|
|
221
|
+
if (res.data?.items) {
|
|
222
|
+
for (const item of res.data.items) {
|
|
223
|
+
// Include the root message itself and all its thread replies
|
|
224
|
+
if (item.message_id === rootMessageId || item.root_id === rootMessageId) {
|
|
225
|
+
allMessages.push(item);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
pageToken = res.data?.page_token;
|
|
230
|
+
// Stop early if we've collected enough or gone past the root message timestamp
|
|
231
|
+
if (allMessages.length >= pageSize)
|
|
232
|
+
break;
|
|
233
|
+
} while (pageToken);
|
|
234
|
+
// Sort by create_time ascending
|
|
235
|
+
allMessages.sort((a, b) => (a.create_time ?? '').localeCompare(b.create_time ?? ''));
|
|
236
|
+
return allMessages;
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=lark-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lark-client.js","sourceRoot":"","sources":["../../src/services/lark-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lark-ws.d.ts","sourceRoot":"","sources":["../../src/services/lark-ws.ts"],"names":[],"mappings":"AASA,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAE5C;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAiBpD;AAED,wBAAgB,KAAK,IAAI,IAAI,CAgD5B;AAED,wBAAgB,IAAI,IAAI,IAAI,CAI3B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as Lark from '@larksuiteoapi/node-sdk';
|
|
2
|
+
import { config } from '../config.js';
|
|
3
|
+
import { logger } from '../utils/logger.js';
|
|
4
|
+
import { parseEventMessage } from '../utils/message-parser.js';
|
|
5
|
+
import * as messageRouter from './message-router.js';
|
|
6
|
+
let wsClient = null;
|
|
7
|
+
let botOpenId = null;
|
|
8
|
+
export function getBotOpenId() {
|
|
9
|
+
return botOpenId;
|
|
10
|
+
}
|
|
11
|
+
export async function fetchBotOpenId() {
|
|
12
|
+
try {
|
|
13
|
+
const { getLarkClient } = await import('./lark-client.js');
|
|
14
|
+
const client = getLarkClient();
|
|
15
|
+
const res = await client.contact.v3.user.get({
|
|
16
|
+
params: { user_id_type: 'open_id' },
|
|
17
|
+
path: { user_id: 'me' },
|
|
18
|
+
});
|
|
19
|
+
if (res.code === 0 && res.data?.user?.open_id) {
|
|
20
|
+
botOpenId = res.data.user.open_id;
|
|
21
|
+
logger.info(`Bot open_id: ${botOpenId}`);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
logger.debug('Bot open_id not available (non-critical, using sender_type filter)');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (e) {
|
|
28
|
+
logger.debug(`Bot open_id fetch skipped (non-critical): ${e}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export function start() {
|
|
32
|
+
if (wsClient) {
|
|
33
|
+
logger.warn('WSClient already started');
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
const eventDispatcher = new Lark.EventDispatcher({}).register({
|
|
37
|
+
'im.message.receive_v1': async (data) => {
|
|
38
|
+
try {
|
|
39
|
+
logger.debug(`Raw event data keys: ${Object.keys(data).join(', ')}`);
|
|
40
|
+
const message = data.message;
|
|
41
|
+
const sender = data.sender; // sender is at data top-level, NOT inside message
|
|
42
|
+
if (!message) {
|
|
43
|
+
logger.warn('Received event without message');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Only process thread replies (messages with root_id)
|
|
47
|
+
const rootId = message.root_id;
|
|
48
|
+
if (!rootId) {
|
|
49
|
+
logger.debug('Ignoring non-thread message');
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
// Skip bot's own messages (sender is at data level)
|
|
53
|
+
if (sender?.sender_type === 'app') {
|
|
54
|
+
logger.debug('Ignoring bot message');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const { parsed } = parseEventMessage(data);
|
|
58
|
+
logger.info(`WS received message in thread ${rootId}: ${parsed.content.substring(0, 100)}`);
|
|
59
|
+
messageRouter.dispatch(rootId, parsed);
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
logger.error(`Error handling message event: ${err}`);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
wsClient = new Lark.WSClient({
|
|
67
|
+
appId: config.lark.appId,
|
|
68
|
+
appSecret: config.lark.appSecret,
|
|
69
|
+
loggerLevel: Lark.LoggerLevel.info,
|
|
70
|
+
});
|
|
71
|
+
wsClient.start({ eventDispatcher });
|
|
72
|
+
logger.info('WSClient started, listening for messages...');
|
|
73
|
+
}
|
|
74
|
+
export function stop() {
|
|
75
|
+
// WSClient doesn't expose a stop method directly, but we null it out
|
|
76
|
+
wsClient = null;
|
|
77
|
+
logger.info('WSClient stopped');
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=lark-ws.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lark-ws.js","sourceRoot":"","sources":["../../src/services/lark-ws.ts"],"names":[],"mappings":"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"}
|